~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/net/wireless/rtlwifi/rc.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 *
 
3
 * Copyright(c) 2009-2010  Realtek Corporation.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify it
 
6
 * under the terms of version 2 of the GNU General Public License as
 
7
 * published by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
12
 * more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along with
 
15
 * this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 
17
 *
 
18
 * The full GNU General Public License is included in this distribution in the
 
19
 * file called LICENSE.
 
20
 *
 
21
 * Contact Information:
 
22
 * wlanfae <wlanfae@realtek.com>
 
23
 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
 
24
 * Hsinchu 300, Taiwan.
 
25
 *
 
26
 * Larry Finger <Larry.Finger@lwfinger.net>
 
27
 *
 
28
 *****************************************************************************/
 
29
 
 
30
#include "wifi.h"
 
31
#include "base.h"
 
32
#include "rc.h"
 
33
 
 
34
/*
 
35
 *Finds the highest rate index we can use
 
36
 *if skb is special data like DHCP/EAPOL, we set should
 
37
 *it to lowest rate CCK_1M, otherwise we set rate to
 
38
 *CCK11M or OFDM_54M based on wireless mode.
 
39
 */
 
40
static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv,
 
41
                                  struct ieee80211_sta *sta,
 
42
                                  struct sk_buff *skb, bool not_data)
 
43
{
 
44
        struct rtl_mac *rtlmac = rtl_mac(rtlpriv);
 
45
        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 
46
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 
47
        struct rtl_sta_info *sta_entry = NULL;
 
48
        u8 wireless_mode = 0;
 
49
 
 
50
        /*
 
51
         *this rate is no use for true rate, firmware
 
52
         *will control rate at all it just used for
 
53
         *1.show in iwconfig in B/G mode
 
54
         *2.in rtl_get_tcb_desc when we check rate is
 
55
         *      1M we will not use FW rate but user rate.
 
56
         */
 
57
        if (rtlmac->opmode == NL80211_IFTYPE_AP ||
 
58
                rtlmac->opmode == NL80211_IFTYPE_ADHOC) {
 
59
                if (sta) {
 
60
                        sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 
61
                        wireless_mode = sta_entry->wireless_mode;
 
62
                } else {
 
63
                        return 0;
 
64
                }
 
65
        } else {
 
66
                wireless_mode = rtlmac->mode;
 
67
        }
 
68
 
 
69
        if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true) ||
 
70
                        not_data) {
 
71
                return 0;
 
72
        } else {
 
73
                if (rtlhal->current_bandtype == BAND_ON_2_4G) {
 
74
                        if (wireless_mode == WIRELESS_MODE_B) {
 
75
                                return B_MODE_MAX_RIX;
 
76
                        } else if (wireless_mode == WIRELESS_MODE_G) {
 
77
                                return G_MODE_MAX_RIX;
 
78
                        } else {
 
79
                                if (get_rf_type(rtlphy) != RF_2T2R)
 
80
                                        return N_MODE_MCS7_RIX;
 
81
                                else
 
82
                                        return N_MODE_MCS15_RIX;
 
83
                        }
 
84
                } else {
 
85
                        if (wireless_mode == WIRELESS_MODE_A) {
 
86
                                return A_MODE_MAX_RIX;
 
87
                        } else {
 
88
                                if (get_rf_type(rtlphy) != RF_2T2R)
 
89
                                        return N_MODE_MCS7_RIX;
 
90
                                else
 
91
                                        return N_MODE_MCS15_RIX;
 
92
                        }
 
93
                }
 
94
        }
 
95
}
 
96
 
 
97
static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv,
 
98
                                    struct ieee80211_sta *sta,
 
99
                                    struct ieee80211_tx_rate *rate,
 
100
                                    struct ieee80211_tx_rate_control *txrc,
 
101
                                    u8 tries, char rix, int rtsctsenable,
 
102
                                    bool not_data)
 
103
{
 
104
        struct rtl_mac *mac = rtl_mac(rtlpriv);
 
105
        u8 sgi_20 = 0, sgi_40 = 0;
 
106
 
 
107
        if (sta) {
 
108
                sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20;
 
109
                sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
 
110
        }
 
111
        rate->count = tries;
 
112
        rate->idx = rix >= 0x00 ? rix : 0x00;
 
113
 
 
114
        if (!not_data) {
 
115
                if (txrc->short_preamble)
 
116
                        rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
 
117
                if (mac->opmode == NL80211_IFTYPE_AP ||
 
118
                        mac->opmode == NL80211_IFTYPE_ADHOC) {
 
119
                        if (sta && (sta->ht_cap.cap &
 
120
                            IEEE80211_HT_CAP_SUP_WIDTH_20_40))
 
121
                                rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
 
122
                } else {
 
123
                        if (mac->bw_40)
 
124
                                rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
 
125
                }
 
126
                if (sgi_20 || sgi_40)
 
127
                        rate->flags |= IEEE80211_TX_RC_SHORT_GI;
 
128
                if (sta && sta->ht_cap.ht_supported)
 
129
                        rate->flags |= IEEE80211_TX_RC_MCS;
 
130
        }
 
131
}
 
132
 
 
133
static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta,
 
134
                         void *priv_sta, struct ieee80211_tx_rate_control *txrc)
 
135
{
 
136
        struct rtl_priv *rtlpriv = ppriv;
 
137
        struct sk_buff *skb = txrc->skb;
 
138
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 
139
        struct ieee80211_tx_rate *rates = tx_info->control.rates;
 
140
        __le16 fc = rtl_get_fc(skb);
 
141
        u8 try_per_rate, i, rix;
 
142
        bool not_data = !ieee80211_is_data(fc);
 
143
 
 
144
        if (rate_control_send_low(sta, priv_sta, txrc))
 
145
                return;
 
146
 
 
147
        rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data);
 
148
        try_per_rate = 1;
 
149
        _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc,
 
150
                                try_per_rate, rix, 1, not_data);
 
151
 
 
152
        if (!not_data) {
 
153
                for (i = 1; i < 4; i++)
 
154
                        _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i],
 
155
                                                txrc, i, (rix - i), 1,
 
156
                                                not_data);
 
157
        }
 
158
}
 
159
 
 
160
static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv,
 
161
                struct rtl_sta_info *sta_entry, u16 tid)
 
162
{
 
163
        struct rtl_mac *mac = rtl_mac(rtlpriv);
 
164
 
 
165
        if (mac->act_scanning)
 
166
                return false;
 
167
 
 
168
        if (mac->opmode == NL80211_IFTYPE_STATION &&
 
169
                mac->cnt_after_linked < 3)
 
170
                return false;
 
171
 
 
172
        if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP)
 
173
                return true;
 
174
 
 
175
        return false;
 
176
}
 
177
 
 
178
/*mac80211 Rate Control callbacks*/
 
179
static void rtl_tx_status(void *ppriv,
 
180
                          struct ieee80211_supported_band *sband,
 
181
                          struct ieee80211_sta *sta, void *priv_sta,
 
182
                          struct sk_buff *skb)
 
183
{
 
184
        struct rtl_priv *rtlpriv = ppriv;
 
185
        struct rtl_mac *mac = rtl_mac(rtlpriv);
 
186
        struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
 
187
        __le16 fc = rtl_get_fc(skb);
 
188
        struct rtl_sta_info *sta_entry;
 
189
 
 
190
        if (!priv_sta || !ieee80211_is_data(fc))
 
191
                return;
 
192
 
 
193
        if (rtl_is_special_data(mac->hw, skb, true))
 
194
                return;
 
195
 
 
196
        if (is_multicast_ether_addr(ieee80211_get_DA(hdr))
 
197
            || is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
 
198
                return;
 
199
 
 
200
        if (sta) {
 
201
                /* Check if aggregation has to be enabled for this tid */
 
202
                sta_entry = (struct rtl_sta_info *) sta->drv_priv;
 
203
                if ((sta->ht_cap.ht_supported) &&
 
204
                                !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
 
205
                        if (ieee80211_is_data_qos(fc)) {
 
206
                                u8 tid = rtl_get_tid(skb);
 
207
                                if (_rtl_tx_aggr_check(rtlpriv, sta_entry,
 
208
                                    tid)) {
 
209
                                        sta_entry->tids[tid].agg.agg_state =
 
210
                                                         RTL_AGG_PROGRESS;
 
211
                                        ieee80211_start_tx_ba_session(sta,
 
212
                                                                 tid, 5000);
 
213
                                }
 
214
                        }
 
215
                }
 
216
        }
 
217
}
 
218
 
 
219
static void rtl_rate_init(void *ppriv,
 
220
                          struct ieee80211_supported_band *sband,
 
221
                          struct ieee80211_sta *sta, void *priv_sta)
 
222
{
 
223
}
 
224
 
 
225
static void rtl_rate_update(void *ppriv,
 
226
                            struct ieee80211_supported_band *sband,
 
227
                            struct ieee80211_sta *sta, void *priv_sta,
 
228
                            u32 changed,
 
229
                            enum nl80211_channel_type oper_chan_type)
 
230
{
 
231
}
 
232
 
 
233
static void *rtl_rate_alloc(struct ieee80211_hw *hw,
 
234
                struct dentry *debugfsdir)
 
235
{
 
236
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
237
        return rtlpriv;
 
238
}
 
239
 
 
240
static void rtl_rate_free(void *rtlpriv)
 
241
{
 
242
        return;
 
243
}
 
244
 
 
245
static void *rtl_rate_alloc_sta(void *ppriv,
 
246
                                struct ieee80211_sta *sta, gfp_t gfp)
 
247
{
 
248
        struct rtl_priv *rtlpriv = ppriv;
 
249
        struct rtl_rate_priv *rate_priv;
 
250
 
 
251
        rate_priv = kzalloc(sizeof(struct rtl_rate_priv), gfp);
 
252
        if (!rate_priv) {
 
253
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 
254
                         ("Unable to allocate private rc structure\n"));
 
255
                return NULL;
 
256
        }
 
257
 
 
258
        rtlpriv->rate_priv = rate_priv;
 
259
 
 
260
        return rate_priv;
 
261
}
 
262
 
 
263
static void rtl_rate_free_sta(void *rtlpriv,
 
264
                              struct ieee80211_sta *sta, void *priv_sta)
 
265
{
 
266
        struct rtl_rate_priv *rate_priv = priv_sta;
 
267
        kfree(rate_priv);
 
268
}
 
269
 
 
270
static struct rate_control_ops rtl_rate_ops = {
 
271
        .module = NULL,
 
272
        .name = "rtl_rc",
 
273
        .alloc = rtl_rate_alloc,
 
274
        .free = rtl_rate_free,
 
275
        .alloc_sta = rtl_rate_alloc_sta,
 
276
        .free_sta = rtl_rate_free_sta,
 
277
        .rate_init = rtl_rate_init,
 
278
        .rate_update = rtl_rate_update,
 
279
        .tx_status = rtl_tx_status,
 
280
        .get_rate = rtl_get_rate,
 
281
};
 
282
 
 
283
int rtl_rate_control_register(void)
 
284
{
 
285
        return ieee80211_rate_control_register(&rtl_rate_ops);
 
286
}
 
287
 
 
288
void rtl_rate_control_unregister(void)
 
289
{
 
290
        ieee80211_rate_control_unregister(&rtl_rate_ops);
 
291
}