diff options
author | David S. Miller <davem@davemloft.net> | 2011-05-05 17:09:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-05 17:09:28 -0400 |
commit | 90864fbc7639d7a2300c67a18c9fb9fbcf7d51d2 (patch) | |
tree | 6951c8d0e529dbfc7c4cec75d4cec63350e39b7c /drivers/net/wireless/rtlwifi/rc.c | |
parent | 228e548e602061b08ee8e8966f567c12aa079682 (diff) | |
parent | a70171dce9cd44cb06c7d299eba9fa87a8933045 (diff) |
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/rtlwifi/rc.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/rc.c | 212 |
1 files changed, 87 insertions, 125 deletions
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index 91634107434a..30da68a77786 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c | |||
@@ -38,17 +38,14 @@ | |||
38 | *CCK11M or OFDM_54M based on wireless mode. | 38 | *CCK11M or OFDM_54M based on wireless mode. |
39 | */ | 39 | */ |
40 | static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, | 40 | static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, |
41 | struct ieee80211_sta *sta, | ||
41 | struct sk_buff *skb, bool not_data) | 42 | struct sk_buff *skb, bool not_data) |
42 | { | 43 | { |
43 | struct rtl_mac *rtlmac = rtl_mac(rtlpriv); | 44 | struct rtl_mac *rtlmac = rtl_mac(rtlpriv); |
44 | 45 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | |
45 | /* | 46 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
46 | *mgt use 1M, although we have check it | 47 | struct rtl_sta_info *sta_entry = NULL; |
47 | *before this function use rate_control_send_low, | 48 | u8 wireless_mode = 0; |
48 | *we still check it here | ||
49 | */ | ||
50 | if (not_data) | ||
51 | return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; | ||
52 | 49 | ||
53 | /* | 50 | /* |
54 | *this rate is no use for true rate, firmware | 51 | *this rate is no use for true rate, firmware |
@@ -57,35 +54,78 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, | |||
57 | *2.in rtl_get_tcb_desc when we check rate is | 54 | *2.in rtl_get_tcb_desc when we check rate is |
58 | * 1M we will not use FW rate but user rate. | 55 | * 1M we will not use FW rate but user rate. |
59 | */ | 56 | */ |
60 | if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true)) { | 57 | if (rtlmac->opmode == NL80211_IFTYPE_AP || |
61 | return rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]; | 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; | ||
62 | } else { | 72 | } else { |
63 | if (rtlmac->mode == WIRELESS_MODE_B) | 73 | if (rtlhal->current_bandtype == BAND_ON_2_4G) { |
64 | return rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; | 74 | if (wireless_mode == WIRELESS_MODE_B) { |
65 | else | 75 | return B_MODE_MAX_RIX; |
66 | return rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; | 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 | } | ||
67 | } | 94 | } |
68 | } | 95 | } |
69 | 96 | ||
70 | static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, | 97 | static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, |
98 | struct ieee80211_sta *sta, | ||
71 | struct ieee80211_tx_rate *rate, | 99 | struct ieee80211_tx_rate *rate, |
72 | struct ieee80211_tx_rate_control *txrc, | 100 | struct ieee80211_tx_rate_control *txrc, |
73 | u8 tries, u8 rix, int rtsctsenable, | 101 | u8 tries, char rix, int rtsctsenable, |
74 | bool not_data) | 102 | bool not_data) |
75 | { | 103 | { |
76 | struct rtl_mac *mac = rtl_mac(rtlpriv); | 104 | struct rtl_mac *mac = rtl_mac(rtlpriv); |
105 | u8 sgi_20 = 0, sgi_40 = 0; | ||
77 | 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 | } | ||
78 | rate->count = tries; | 111 | rate->count = tries; |
79 | rate->idx = (rix > 0x2) ? rix : 0x2; | 112 | rate->idx = rix >= 0x00 ? rix : 0x00; |
80 | 113 | ||
81 | if (!not_data) { | 114 | if (!not_data) { |
82 | if (txrc->short_preamble) | 115 | if (txrc->short_preamble) |
83 | rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; | 116 | rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; |
84 | if (mac->bw_40) | 117 | if (mac->opmode == NL80211_IFTYPE_AP || |
85 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | 118 | mac->opmode == NL80211_IFTYPE_ADHOC) { |
86 | if (mac->sgi_20 || mac->sgi_40) | 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) | ||
87 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; | 127 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; |
88 | if (mac->ht_enable) | 128 | if (sta && sta->ht_cap.ht_supported) |
89 | rate->flags |= IEEE80211_TX_RC_MCS; | 129 | rate->flags |= IEEE80211_TX_RC_MCS; |
90 | } | 130 | } |
91 | } | 131 | } |
@@ -97,39 +137,39 @@ static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, | |||
97 | struct sk_buff *skb = txrc->skb; | 137 | struct sk_buff *skb = txrc->skb; |
98 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 138 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
99 | struct ieee80211_tx_rate *rates = tx_info->control.rates; | 139 | struct ieee80211_tx_rate *rates = tx_info->control.rates; |
100 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 140 | __le16 fc = rtl_get_fc(skb); |
101 | __le16 fc = hdr->frame_control; | ||
102 | u8 try_per_rate, i, rix; | 141 | u8 try_per_rate, i, rix; |
103 | bool not_data = !ieee80211_is_data(fc); | 142 | bool not_data = !ieee80211_is_data(fc); |
104 | 143 | ||
105 | if (rate_control_send_low(sta, priv_sta, txrc)) | 144 | if (rate_control_send_low(sta, priv_sta, txrc)) |
106 | return; | 145 | return; |
107 | 146 | ||
108 | rix = _rtl_rc_get_highest_rix(rtlpriv, skb, not_data); | 147 | rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); |
109 | |||
110 | try_per_rate = 1; | 148 | try_per_rate = 1; |
111 | _rtl_rc_rate_set_series(rtlpriv, &rates[0], txrc, | 149 | _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, |
112 | try_per_rate, rix, 1, not_data); | 150 | try_per_rate, rix, 1, not_data); |
113 | 151 | ||
114 | if (!not_data) { | 152 | if (!not_data) { |
115 | for (i = 1; i < 4; i++) | 153 | for (i = 1; i < 4; i++) |
116 | _rtl_rc_rate_set_series(rtlpriv, &rates[i], | 154 | _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], |
117 | txrc, i, (rix - i), 1, | 155 | txrc, i, (rix - i), 1, |
118 | not_data); | 156 | not_data); |
119 | } | 157 | } |
120 | } | 158 | } |
121 | 159 | ||
122 | static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, u16 tid) | 160 | static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, |
161 | struct rtl_sta_info *sta_entry, u16 tid) | ||
123 | { | 162 | { |
124 | struct rtl_mac *mac = rtl_mac(rtlpriv); | 163 | struct rtl_mac *mac = rtl_mac(rtlpriv); |
125 | 164 | ||
126 | if (mac->act_scanning) | 165 | if (mac->act_scanning) |
127 | return false; | 166 | return false; |
128 | 167 | ||
129 | if (mac->cnt_after_linked < 3) | 168 | if (mac->opmode == NL80211_IFTYPE_STATION && |
169 | mac->cnt_after_linked < 3) | ||
130 | return false; | 170 | return false; |
131 | 171 | ||
132 | if (mac->tids[tid].agg.agg_state == RTL_AGG_OFF) | 172 | if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) |
133 | return true; | 173 | return true; |
134 | 174 | ||
135 | return false; | 175 | return false; |
@@ -143,11 +183,9 @@ static void rtl_tx_status(void *ppriv, | |||
143 | { | 183 | { |
144 | struct rtl_priv *rtlpriv = ppriv; | 184 | struct rtl_priv *rtlpriv = ppriv; |
145 | struct rtl_mac *mac = rtl_mac(rtlpriv); | 185 | struct rtl_mac *mac = rtl_mac(rtlpriv); |
146 | struct ieee80211_hdr *hdr; | 186 | struct ieee80211_hdr *hdr = rtl_get_hdr(skb); |
147 | __le16 fc; | 187 | __le16 fc = rtl_get_fc(skb); |
148 | 188 | struct rtl_sta_info *sta_entry; | |
149 | hdr = (struct ieee80211_hdr *)skb->data; | ||
150 | fc = hdr->frame_control; | ||
151 | 189 | ||
152 | if (!priv_sta || !ieee80211_is_data(fc)) | 190 | if (!priv_sta || !ieee80211_is_data(fc)) |
153 | return; | 191 | return; |
@@ -159,17 +197,21 @@ static void rtl_tx_status(void *ppriv, | |||
159 | || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) | 197 | || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) |
160 | return; | 198 | return; |
161 | 199 | ||
162 | /* Check if aggregation has to be enabled for this tid */ | 200 | if (sta) { |
163 | if (conf_is_ht(&mac->hw->conf) && | 201 | /* Check if aggregation has to be enabled for this tid */ |
164 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 202 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
165 | if (ieee80211_is_data_qos(fc)) { | 203 | if ((sta->ht_cap.ht_supported == true) && |
166 | u8 *qc, tid; | 204 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
167 | 205 | if (ieee80211_is_data_qos(fc)) { | |
168 | qc = ieee80211_get_qos_ctl(hdr); | 206 | u8 tid = rtl_get_tid(skb); |
169 | tid = qc[0] & 0xf; | 207 | if (_rtl_tx_aggr_check(rtlpriv, sta_entry, |
170 | 208 | tid)) { | |
171 | if (_rtl_tx_aggr_check(rtlpriv, tid)) | 209 | sta_entry->tids[tid].agg.agg_state = |
172 | ieee80211_start_tx_ba_session(sta, tid, 5000); | 210 | RTL_AGG_PROGRESS; |
211 | ieee80211_start_tx_ba_session(sta, | ||
212 | tid, 5000); | ||
213 | } | ||
214 | } | ||
173 | } | 215 | } |
174 | } | 216 | } |
175 | } | 217 | } |
@@ -178,43 +220,6 @@ static void rtl_rate_init(void *ppriv, | |||
178 | struct ieee80211_supported_band *sband, | 220 | struct ieee80211_supported_band *sband, |
179 | struct ieee80211_sta *sta, void *priv_sta) | 221 | struct ieee80211_sta *sta, void *priv_sta) |
180 | { | 222 | { |
181 | struct rtl_priv *rtlpriv = ppriv; | ||
182 | struct rtl_mac *mac = rtl_mac(rtlpriv); | ||
183 | u8 is_ht = conf_is_ht(&mac->hw->conf); | ||
184 | |||
185 | if ((mac->opmode == NL80211_IFTYPE_STATION) || | ||
186 | (mac->opmode == NL80211_IFTYPE_MESH_POINT) || | ||
187 | (mac->opmode == NL80211_IFTYPE_ADHOC)) { | ||
188 | |||
189 | switch (sband->band) { | ||
190 | case IEEE80211_BAND_2GHZ: | ||
191 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
192 | RATR_INX_WIRELESS_G; | ||
193 | if (is_ht) | ||
194 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
195 | RATR_INX_WIRELESS_NGB; | ||
196 | break; | ||
197 | case IEEE80211_BAND_5GHZ: | ||
198 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
199 | RATR_INX_WIRELESS_A; | ||
200 | if (is_ht) | ||
201 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
202 | RATR_INX_WIRELESS_NGB; | ||
203 | break; | ||
204 | default: | ||
205 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
206 | ("Invalid band\n")); | ||
207 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
208 | RATR_INX_WIRELESS_NGB; | ||
209 | break; | ||
210 | } | ||
211 | |||
212 | RT_TRACE(rtlpriv, COMP_RATE, DBG_DMESG, | ||
213 | ("Choosing rate table index: %d\n", | ||
214 | rtlpriv->rate_priv->cur_ratetab_idx)); | ||
215 | |||
216 | } | ||
217 | |||
218 | } | 223 | } |
219 | 224 | ||
220 | static void rtl_rate_update(void *ppriv, | 225 | static void rtl_rate_update(void *ppriv, |
@@ -223,49 +228,6 @@ static void rtl_rate_update(void *ppriv, | |||
223 | u32 changed, | 228 | u32 changed, |
224 | enum nl80211_channel_type oper_chan_type) | 229 | enum nl80211_channel_type oper_chan_type) |
225 | { | 230 | { |
226 | struct rtl_priv *rtlpriv = ppriv; | ||
227 | struct rtl_mac *mac = rtl_mac(rtlpriv); | ||
228 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | ||
229 | bool oper_cw40 = false, oper_sgi40; | ||
230 | bool local_cw40 = mac->bw_40; | ||
231 | bool local_sgi40 = mac->sgi_40; | ||
232 | u8 is_ht = conf_is_ht(&mac->hw->conf); | ||
233 | |||
234 | if (changed & IEEE80211_RC_HT_CHANGED) { | ||
235 | if (mac->opmode != NL80211_IFTYPE_STATION) | ||
236 | return; | ||
237 | |||
238 | if (rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || | ||
239 | rtlhal->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) | ||
240 | oper_cw40 = true; | ||
241 | |||
242 | oper_sgi40 = mac->sgi_40; | ||
243 | |||
244 | if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { | ||
245 | switch (sband->band) { | ||
246 | case IEEE80211_BAND_2GHZ: | ||
247 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
248 | RATR_INX_WIRELESS_G; | ||
249 | if (is_ht) | ||
250 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
251 | RATR_INX_WIRELESS_NGB; | ||
252 | break; | ||
253 | case IEEE80211_BAND_5GHZ: | ||
254 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
255 | RATR_INX_WIRELESS_A; | ||
256 | if (is_ht) | ||
257 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
258 | RATR_INX_WIRELESS_NGB; | ||
259 | break; | ||
260 | default: | ||
261 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
262 | ("Invalid band\n")); | ||
263 | rtlpriv->rate_priv->cur_ratetab_idx = | ||
264 | RATR_INX_WIRELESS_NGB; | ||
265 | break; | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | } | 231 | } |
270 | 232 | ||
271 | static void *rtl_rate_alloc(struct ieee80211_hw *hw, | 233 | static void *rtl_rate_alloc(struct ieee80211_hw *hw, |