diff options
author | Christian Lamparter <chunkeey@web.de> | 2009-07-11 11:24:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:12 -0400 |
commit | acbadf01ff6727a2c7dc6e12f70ce8d05a16dc06 (patch) | |
tree | ae91e58ac9b298a3e731596d4cb9689e3977f139 /drivers/net/wireless/ath/ar9170/main.c | |
parent | 1a9b6679adfb8ef1f1f3dbb7ebd2ee72e2ea4b56 (diff) |
ar9170: implement transmit aggregation
This patch roughly implements xmit aggregation for ar9170-like device.
Not all AP are compatible with the driver(and firmware) yet, so YMMV.
A more refined code will definitely need the final HT specification
to be available for the public, lots of firmware modification and
possibly a redesigned driver just for good measure.
Sadly, these conditions won't come true anytime soon...
Signed-off-by: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 608 |
1 files changed, 582 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 51753ed1b8b..cfe6fc78067 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -49,6 +49,10 @@ static int modparam_nohwcrypt; | |||
49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 49 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 50 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
51 | 51 | ||
52 | static int modparam_ht; | ||
53 | module_param_named(ht, modparam_ht, bool, S_IRUGO); | ||
54 | MODULE_PARM_DESC(ht, "enable MPDU aggregation."); | ||
55 | |||
52 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ | 56 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ |
53 | .bitrate = (_bitrate), \ | 57 | .bitrate = (_bitrate), \ |
54 | .flags = (_flags), \ | 58 | .flags = (_flags), \ |
@@ -148,12 +152,15 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = { | |||
148 | .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ | 152 | .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ |
149 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ | 153 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ |
150 | IEEE80211_HT_CAP_SGI_40 | \ | 154 | IEEE80211_HT_CAP_SGI_40 | \ |
155 | IEEE80211_HT_CAP_GRN_FLD | \ | ||
151 | IEEE80211_HT_CAP_DSSSCCK40 | \ | 156 | IEEE80211_HT_CAP_DSSSCCK40 | \ |
152 | IEEE80211_HT_CAP_SM_PS, \ | 157 | IEEE80211_HT_CAP_SM_PS, \ |
153 | .ampdu_factor = 3, \ | 158 | .ampdu_factor = 3, \ |
154 | .ampdu_density = 6, \ | 159 | .ampdu_density = 6, \ |
155 | .mcs = { \ | 160 | .mcs = { \ |
156 | .rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \ | 161 | .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ |
162 | .rx_highest = cpu_to_le16(300), \ | ||
163 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ | ||
157 | }, \ | 164 | }, \ |
158 | } | 165 | } |
159 | 166 | ||
@@ -174,8 +181,31 @@ static struct ieee80211_supported_band ar9170_band_5GHz = { | |||
174 | }; | 181 | }; |
175 | 182 | ||
176 | static void ar9170_tx(struct ar9170 *ar); | 183 | static void ar9170_tx(struct ar9170 *ar); |
184 | static bool ar9170_tx_ampdu(struct ar9170 *ar); | ||
177 | 185 | ||
178 | #ifdef AR9170_QUEUE_DEBUG | 186 | static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) |
187 | { | ||
188 | return le16_to_cpu(hdr->seq_ctrl) >> 4; | ||
189 | } | ||
190 | |||
191 | static inline u16 ar9170_get_seq(struct sk_buff *skb) | ||
192 | { | ||
193 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
194 | return ar9170_get_seq_h((void *) txc->frame_data); | ||
195 | } | ||
196 | |||
197 | static inline u16 ar9170_get_tid(struct sk_buff *skb) | ||
198 | { | ||
199 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
200 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | ||
201 | |||
202 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
203 | } | ||
204 | |||
205 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) | ||
206 | #define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb))) | ||
207 | |||
208 | #if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG) | ||
179 | static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | 209 | static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) |
180 | { | 210 | { |
181 | struct ar9170_tx_control *txc = (void *) skb->data; | 211 | struct ar9170_tx_control *txc = (void *) skb->data; |
@@ -183,10 +213,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | |||
183 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | 213 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; |
184 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; | 214 | struct ieee80211_hdr *hdr = (void *) txc->frame_data; |
185 | 215 | ||
186 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x " | 216 | printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " |
187 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", | 217 | "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", |
188 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), | 218 | wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), |
189 | ieee80211_get_DA(hdr), arinfo->flags, | 219 | ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), |
190 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), | 220 | le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), |
191 | jiffies_to_msecs(arinfo->timeout - jiffies)); | 221 | jiffies_to_msecs(arinfo->timeout - jiffies)); |
192 | } | 222 | } |
@@ -210,7 +240,9 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, | |||
210 | "mismatch %d != %d\n", skb_queue_len(queue), i); | 240 | "mismatch %d != %d\n", skb_queue_len(queue), i); |
211 | printk(KERN_DEBUG "---[ end ]---\n"); | 241 | printk(KERN_DEBUG "---[ end ]---\n"); |
212 | } | 242 | } |
243 | #endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */ | ||
213 | 244 | ||
245 | #ifdef AR9170_QUEUE_DEBUG | ||
214 | static void ar9170_dump_txqueue(struct ar9170 *ar, | 246 | static void ar9170_dump_txqueue(struct ar9170 *ar, |
215 | struct sk_buff_head *queue) | 247 | struct sk_buff_head *queue) |
216 | { | 248 | { |
@@ -220,7 +252,9 @@ static void ar9170_dump_txqueue(struct ar9170 *ar, | |||
220 | __ar9170_dump_txqueue(ar, queue); | 252 | __ar9170_dump_txqueue(ar, queue); |
221 | spin_unlock_irqrestore(&queue->lock, flags); | 253 | spin_unlock_irqrestore(&queue->lock, flags); |
222 | } | 254 | } |
255 | #endif /* AR9170_QUEUE_DEBUG */ | ||
223 | 256 | ||
257 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
224 | static void __ar9170_dump_txstats(struct ar9170 *ar) | 258 | static void __ar9170_dump_txstats(struct ar9170 *ar) |
225 | { | 259 | { |
226 | int i; | 260 | int i; |
@@ -229,20 +263,27 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) | |||
229 | wiphy_name(ar->hw->wiphy)); | 263 | wiphy_name(ar->hw->wiphy)); |
230 | 264 | ||
231 | for (i = 0; i < __AR9170_NUM_TXQ; i++) | 265 | for (i = 0; i < __AR9170_NUM_TXQ; i++) |
232 | printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d\n", | 266 | printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d " |
233 | wiphy_name(ar->hw->wiphy), i, ar->tx_stats[i].limit, | 267 | " stopped:%d\n", wiphy_name(ar->hw->wiphy), i, |
234 | ar->tx_stats[i].len, skb_queue_len(&ar->tx_status[i])); | 268 | ar->tx_stats[i].limit, ar->tx_stats[i].len, |
269 | skb_queue_len(&ar->tx_status[i]), | ||
270 | ieee80211_queue_stopped(ar->hw, i)); | ||
235 | } | 271 | } |
272 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
236 | 273 | ||
237 | static void ar9170_dump_txstats(struct ar9170 *ar) | 274 | #ifdef AR9170_TXAGG_DEBUG |
275 | static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) | ||
238 | { | 276 | { |
239 | unsigned long flags; | 277 | unsigned long flags; |
240 | 278 | ||
241 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 279 | spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); |
242 | __ar9170_dump_txstats(ar); | 280 | printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", |
243 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 281 | wiphy_name(ar->hw->wiphy)); |
282 | __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); | ||
283 | spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); | ||
244 | } | 284 | } |
245 | #endif /* AR9170_QUEUE_DEBUG */ | 285 | |
286 | #endif /* AR9170_TXAGG_DEBUG */ | ||
246 | 287 | ||
247 | /* caller must guarantee exclusive access for _bin_ queue. */ | 288 | /* caller must guarantee exclusive access for _bin_ queue. */ |
248 | static void ar9170_recycle_expired(struct ar9170 *ar, | 289 | static void ar9170_recycle_expired(struct ar9170 *ar, |
@@ -315,6 +356,70 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | |||
315 | ieee80211_tx_status_irqsafe(ar->hw, skb); | 356 | ieee80211_tx_status_irqsafe(ar->hw, skb); |
316 | } | 357 | } |
317 | 358 | ||
359 | static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) | ||
360 | { | ||
361 | struct sk_buff_head success; | ||
362 | struct sk_buff *skb; | ||
363 | unsigned int i; | ||
364 | unsigned long queue_bitmap = 0; | ||
365 | |||
366 | skb_queue_head_init(&success); | ||
367 | |||
368 | while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS) | ||
369 | __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu)); | ||
370 | |||
371 | ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success); | ||
372 | |||
373 | #ifdef AR9170_TXAGG_DEBUG | ||
374 | printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n", | ||
375 | wiphy_name(ar->hw->wiphy), skb_queue_len(&success)); | ||
376 | __ar9170_dump_txqueue(ar, &success); | ||
377 | #endif /* AR9170_TXAGG_DEBUG */ | ||
378 | |||
379 | while ((skb = __skb_dequeue(&success))) { | ||
380 | struct ieee80211_tx_info *txinfo; | ||
381 | |||
382 | queue_bitmap |= BIT(skb_get_queue_mapping(skb)); | ||
383 | |||
384 | txinfo = IEEE80211_SKB_CB(skb); | ||
385 | ieee80211_tx_info_clear_status(txinfo); | ||
386 | |||
387 | txinfo->flags |= IEEE80211_TX_STAT_ACK; | ||
388 | txinfo->status.rates[0].count = 1; | ||
389 | |||
390 | skb_pull(skb, sizeof(struct ar9170_tx_control)); | ||
391 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
392 | } | ||
393 | |||
394 | for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { | ||
395 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
396 | printk(KERN_DEBUG "%s: wake queue %d\n", | ||
397 | wiphy_name(ar->hw->wiphy), i); | ||
398 | __ar9170_dump_txstats(ar); | ||
399 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
400 | ieee80211_wake_queue(ar->hw, i); | ||
401 | } | ||
402 | |||
403 | if (queue_bitmap) | ||
404 | ar9170_tx(ar); | ||
405 | } | ||
406 | |||
407 | static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) | ||
408 | { | ||
409 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
410 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | ||
411 | |||
412 | arinfo->timeout = jiffies + | ||
413 | msecs_to_jiffies(AR9170_BA_TIMEOUT); | ||
414 | |||
415 | skb_queue_tail(&ar->tx_status_ampdu, skb); | ||
416 | ar9170_tx_fake_ampdu_status(ar); | ||
417 | ar->tx_ampdu_pending--; | ||
418 | |||
419 | if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) | ||
420 | ar9170_tx_ampdu(ar); | ||
421 | } | ||
422 | |||
318 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | 423 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) |
319 | { | 424 | { |
320 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 425 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -336,7 +441,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
336 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 441 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
337 | 442 | ||
338 | if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { | 443 | if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { |
339 | dev_kfree_skb_any(skb); | 444 | ar9170_tx_ampdu_callback(ar, skb); |
340 | } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { | 445 | } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { |
341 | arinfo->timeout = jiffies + | 446 | arinfo->timeout = jiffies + |
342 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 447 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
@@ -420,6 +525,38 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, | |||
420 | return NULL; | 525 | return NULL; |
421 | } | 526 | } |
422 | 527 | ||
528 | static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r) | ||
529 | { | ||
530 | struct sk_buff *skb; | ||
531 | struct ieee80211_tx_info *txinfo; | ||
532 | |||
533 | while (count) { | ||
534 | skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r); | ||
535 | if (!skb) | ||
536 | break; | ||
537 | |||
538 | txinfo = IEEE80211_SKB_CB(skb); | ||
539 | ieee80211_tx_info_clear_status(txinfo); | ||
540 | |||
541 | /* FIXME: maybe more ? */ | ||
542 | txinfo->status.rates[0].count = 1; | ||
543 | |||
544 | skb_pull(skb, sizeof(struct ar9170_tx_control)); | ||
545 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
546 | count--; | ||
547 | } | ||
548 | |||
549 | #ifdef AR9170_TXAGG_DEBUG | ||
550 | if (count) { | ||
551 | printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more " | ||
552 | "suitable frames left in tx_status queue.\n", | ||
553 | wiphy_name(ar->hw->wiphy), count); | ||
554 | |||
555 | ar9170_dump_tx_status_ampdu(ar); | ||
556 | } | ||
557 | #endif /* AR9170_TXAGG_DEBUG */ | ||
558 | } | ||
559 | |||
423 | /* | 560 | /* |
424 | * This worker tries to keeps an maintain tx_status queues. | 561 | * This worker tries to keeps an maintain tx_status queues. |
425 | * So we can guarantee that incoming tx_status reports are | 562 | * So we can guarantee that incoming tx_status reports are |
@@ -456,6 +593,8 @@ static void ar9170_tx_janitor(struct work_struct *work) | |||
456 | resched = true; | 593 | resched = true; |
457 | } | 594 | } |
458 | 595 | ||
596 | ar9170_tx_fake_ampdu_status(ar); | ||
597 | |||
459 | if (resched) | 598 | if (resched) |
460 | queue_delayed_work(ar->hw->workqueue, | 599 | queue_delayed_work(ar->hw->workqueue, |
461 | &ar->tx_janitor, | 600 | &ar->tx_janitor, |
@@ -528,8 +667,15 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |||
528 | break; | 667 | break; |
529 | 668 | ||
530 | case 0xc4: | 669 | case 0xc4: |
670 | /* BlockACK bitmap */ | ||
671 | break; | ||
672 | |||
531 | case 0xc5: | 673 | case 0xc5: |
532 | /* BlockACK events */ | 674 | /* BlockACK events */ |
675 | ar9170_handle_block_ack(ar, | ||
676 | le16_to_cpu(cmd->ba_fail_cnt.failed), | ||
677 | le16_to_cpu(cmd->ba_fail_cnt.rate)); | ||
678 | ar9170_tx_fake_ampdu_status(ar); | ||
533 | break; | 679 | break; |
534 | 680 | ||
535 | case 0xc6: | 681 | case 0xc6: |
@@ -1098,6 +1244,10 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1098 | AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ | 1244 | AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ |
1099 | AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ | 1245 | AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ |
1100 | 1246 | ||
1247 | /* set sane AMPDU defaults */ | ||
1248 | ar->global_ampdu_density = 6; | ||
1249 | ar->global_ampdu_factor = 3; | ||
1250 | |||
1101 | ar->bad_hw_nagger = jiffies; | 1251 | ar->bad_hw_nagger = jiffies; |
1102 | 1252 | ||
1103 | err = ar->open(ar); | 1253 | err = ar->open(ar); |
@@ -1143,6 +1293,7 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) | |||
1143 | flush_workqueue(ar->hw->workqueue); | 1293 | flush_workqueue(ar->hw->workqueue); |
1144 | 1294 | ||
1145 | cancel_delayed_work_sync(&ar->tx_janitor); | 1295 | cancel_delayed_work_sync(&ar->tx_janitor); |
1296 | cancel_delayed_work_sync(&ar->led_work); | ||
1146 | cancel_work_sync(&ar->filter_config_work); | 1297 | cancel_work_sync(&ar->filter_config_work); |
1147 | cancel_work_sync(&ar->beacon_work); | 1298 | cancel_work_sync(&ar->beacon_work); |
1148 | mutex_lock(&ar->mutex); | 1299 | mutex_lock(&ar->mutex); |
@@ -1159,9 +1310,40 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) | |||
1159 | skb_queue_purge(&ar->tx_pending[i]); | 1310 | skb_queue_purge(&ar->tx_pending[i]); |
1160 | skb_queue_purge(&ar->tx_status[i]); | 1311 | skb_queue_purge(&ar->tx_status[i]); |
1161 | } | 1312 | } |
1313 | skb_queue_purge(&ar->tx_status_ampdu); | ||
1314 | |||
1162 | mutex_unlock(&ar->mutex); | 1315 | mutex_unlock(&ar->mutex); |
1163 | } | 1316 | } |
1164 | 1317 | ||
1318 | static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb) | ||
1319 | { | ||
1320 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
1321 | |||
1322 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU); | ||
1323 | } | ||
1324 | |||
1325 | static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst, | ||
1326 | struct sk_buff *src) | ||
1327 | { | ||
1328 | struct ar9170_tx_control *dst_txc, *src_txc; | ||
1329 | struct ieee80211_tx_info *dst_info, *src_info; | ||
1330 | struct ar9170_tx_info *dst_arinfo, *src_arinfo; | ||
1331 | |||
1332 | src_txc = (void *) src->data; | ||
1333 | src_info = IEEE80211_SKB_CB(src); | ||
1334 | src_arinfo = (void *) src_info->rate_driver_data; | ||
1335 | |||
1336 | dst_txc = (void *) dst->data; | ||
1337 | dst_info = IEEE80211_SKB_CB(dst); | ||
1338 | dst_arinfo = (void *) dst_info->rate_driver_data; | ||
1339 | |||
1340 | dst_txc->phy_control = src_txc->phy_control; | ||
1341 | |||
1342 | /* same MCS for the whole aggregate */ | ||
1343 | memcpy(dst_info->driver_rates, src_info->driver_rates, | ||
1344 | sizeof(dst_info->driver_rates)); | ||
1345 | } | ||
1346 | |||
1165 | static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | 1347 | static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) |
1166 | { | 1348 | { |
1167 | struct ieee80211_hdr *hdr; | 1349 | struct ieee80211_hdr *hdr; |
@@ -1230,6 +1412,7 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1230 | 1412 | ||
1231 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | 1413 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); |
1232 | arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; | 1414 | arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; |
1415 | |||
1233 | goto out; | 1416 | goto out; |
1234 | } | 1417 | } |
1235 | 1418 | ||
@@ -1360,6 +1543,159 @@ static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) | |||
1360 | txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); | 1543 | txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); |
1361 | } | 1544 | } |
1362 | 1545 | ||
1546 | static bool ar9170_tx_ampdu(struct ar9170 *ar) | ||
1547 | { | ||
1548 | struct sk_buff_head agg; | ||
1549 | struct ar9170_sta_tid *tid_info = NULL, *tmp; | ||
1550 | struct sk_buff *skb, *first = NULL; | ||
1551 | unsigned long flags, f2; | ||
1552 | unsigned int i = 0; | ||
1553 | u16 seq, queue, tmpssn; | ||
1554 | bool run = false; | ||
1555 | |||
1556 | skb_queue_head_init(&agg); | ||
1557 | |||
1558 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1559 | if (list_empty(&ar->tx_ampdu_list)) { | ||
1560 | #ifdef AR9170_TXAGG_DEBUG | ||
1561 | printk(KERN_DEBUG "%s: aggregation list is empty.\n", | ||
1562 | wiphy_name(ar->hw->wiphy)); | ||
1563 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1564 | goto out_unlock; | ||
1565 | } | ||
1566 | |||
1567 | list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) { | ||
1568 | if (tid_info->state != AR9170_TID_STATE_COMPLETE) { | ||
1569 | #ifdef AR9170_TXAGG_DEBUG | ||
1570 | printk(KERN_DEBUG "%s: dangling aggregation entry!\n", | ||
1571 | wiphy_name(ar->hw->wiphy)); | ||
1572 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1573 | continue; | ||
1574 | } | ||
1575 | |||
1576 | if (++i > 64) { | ||
1577 | #ifdef AR9170_TXAGG_DEBUG | ||
1578 | printk(KERN_DEBUG "%s: enough frames aggregated.\n", | ||
1579 | wiphy_name(ar->hw->wiphy)); | ||
1580 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1581 | break; | ||
1582 | } | ||
1583 | |||
1584 | queue = TID_TO_WME_AC(tid_info->tid); | ||
1585 | |||
1586 | if (skb_queue_len(&ar->tx_pending[queue]) >= | ||
1587 | AR9170_NUM_TX_AGG_MAX) { | ||
1588 | #ifdef AR9170_TXAGG_DEBUG | ||
1589 | printk(KERN_DEBUG "%s: queue %d full.\n", | ||
1590 | wiphy_name(ar->hw->wiphy), queue); | ||
1591 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1592 | continue; | ||
1593 | } | ||
1594 | |||
1595 | list_del_init(&tid_info->list); | ||
1596 | |||
1597 | spin_lock_irqsave(&tid_info->queue.lock, f2); | ||
1598 | tmpssn = seq = tid_info->ssn; | ||
1599 | first = skb_peek(&tid_info->queue); | ||
1600 | |||
1601 | if (likely(first)) | ||
1602 | tmpssn = ar9170_get_seq(first); | ||
1603 | |||
1604 | if (unlikely(tmpssn != seq)) { | ||
1605 | #ifdef AR9170_TXAGG_DEBUG | ||
1606 | printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.", | ||
1607 | wiphy_name(ar->hw->wiphy), seq, tmpssn); | ||
1608 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1609 | tid_info->ssn = tmpssn; | ||
1610 | } | ||
1611 | |||
1612 | #ifdef AR9170_TXAGG_DEBUG | ||
1613 | printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with " | ||
1614 | "%d queued frames.\n", wiphy_name(ar->hw->wiphy), | ||
1615 | tid_info->tid, tid_info->ssn, | ||
1616 | skb_queue_len(&tid_info->queue)); | ||
1617 | __ar9170_dump_txqueue(ar, &tid_info->queue); | ||
1618 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1619 | |||
1620 | while ((skb = skb_peek(&tid_info->queue))) { | ||
1621 | if (unlikely(ar9170_get_seq(skb) != seq)) | ||
1622 | break; | ||
1623 | |||
1624 | __skb_unlink(skb, &tid_info->queue); | ||
1625 | tid_info->ssn = seq = GET_NEXT_SEQ(seq); | ||
1626 | |||
1627 | if (unlikely(skb_get_queue_mapping(skb) != queue)) { | ||
1628 | #ifdef AR9170_TXAGG_DEBUG | ||
1629 | printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d " | ||
1630 | "!match.\n", wiphy_name(ar->hw->wiphy), | ||
1631 | tid_info->tid, | ||
1632 | TID_TO_WME_AC(tid_info->tid), | ||
1633 | skb_get_queue_mapping(skb)); | ||
1634 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1635 | dev_kfree_skb_any(skb); | ||
1636 | continue; | ||
1637 | } | ||
1638 | |||
1639 | if (unlikely(first == skb)) { | ||
1640 | ar9170_tx_prepare_phy(ar, skb); | ||
1641 | __skb_queue_tail(&agg, skb); | ||
1642 | first = skb; | ||
1643 | } else { | ||
1644 | ar9170_tx_copy_phy(ar, skb, first); | ||
1645 | __skb_queue_tail(&agg, skb); | ||
1646 | } | ||
1647 | |||
1648 | if (unlikely(skb_queue_len(&agg) == | ||
1649 | AR9170_NUM_TX_AGG_MAX)) | ||
1650 | break; | ||
1651 | } | ||
1652 | |||
1653 | if (skb_queue_empty(&tid_info->queue)) | ||
1654 | tid_info->active = false; | ||
1655 | else | ||
1656 | list_add_tail(&tid_info->list, | ||
1657 | &ar->tx_ampdu_list); | ||
1658 | |||
1659 | spin_unlock_irqrestore(&tid_info->queue.lock, f2); | ||
1660 | |||
1661 | if (unlikely(skb_queue_empty(&agg))) { | ||
1662 | #ifdef AR9170_TXAGG_DEBUG | ||
1663 | printk(KERN_DEBUG "%s: queued empty list!\n", | ||
1664 | wiphy_name(ar->hw->wiphy)); | ||
1665 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1666 | continue; | ||
1667 | } | ||
1668 | |||
1669 | /* | ||
1670 | * tell the FW/HW that this is the last frame, | ||
1671 | * that way it will wait for the immediate block ack. | ||
1672 | */ | ||
1673 | if (likely(skb_peek_tail(&agg))) | ||
1674 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); | ||
1675 | |||
1676 | #ifdef AR9170_TXAGG_DEBUG | ||
1677 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", | ||
1678 | wiphy_name(ar->hw->wiphy)); | ||
1679 | __ar9170_dump_txqueue(ar, &agg); | ||
1680 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1681 | |||
1682 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1683 | |||
1684 | spin_lock_irqsave(&ar->tx_pending[queue].lock, flags); | ||
1685 | skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); | ||
1686 | spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags); | ||
1687 | run = true; | ||
1688 | |||
1689 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1690 | } | ||
1691 | |||
1692 | out_unlock: | ||
1693 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1694 | __skb_queue_purge(&agg); | ||
1695 | |||
1696 | return run; | ||
1697 | } | ||
1698 | |||
1363 | static void ar9170_tx(struct ar9170 *ar) | 1699 | static void ar9170_tx(struct ar9170 *ar) |
1364 | { | 1700 | { |
1365 | struct sk_buff *skb; | 1701 | struct sk_buff *skb; |
@@ -1384,11 +1720,17 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1384 | printk(KERN_DEBUG "%s: queue %d full\n", | 1720 | printk(KERN_DEBUG "%s: queue %d full\n", |
1385 | wiphy_name(ar->hw->wiphy), i); | 1721 | wiphy_name(ar->hw->wiphy), i); |
1386 | 1722 | ||
1387 | __ar9170_dump_txstats(ar); | 1723 | printk(KERN_DEBUG "%s: stuck frames: ===> \n", |
1388 | printk(KERN_DEBUG "stuck frames: ===> \n"); | 1724 | wiphy_name(ar->hw->wiphy)); |
1389 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); | 1725 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); |
1390 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); | 1726 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); |
1391 | #endif /* AR9170_QUEUE_DEBUG */ | 1727 | #endif /* AR9170_QUEUE_DEBUG */ |
1728 | |||
1729 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
1730 | printk(KERN_DEBUG "%s: stop queue %d\n", | ||
1731 | wiphy_name(ar->hw->wiphy), i); | ||
1732 | __ar9170_dump_txstats(ar); | ||
1733 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
1392 | ieee80211_stop_queue(ar->hw, i); | 1734 | ieee80211_stop_queue(ar->hw, i); |
1393 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 1735 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
1394 | continue; | 1736 | continue; |
@@ -1403,8 +1745,6 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1403 | "remaining slots:%d, needed:%d\n", | 1745 | "remaining slots:%d, needed:%d\n", |
1404 | wiphy_name(ar->hw->wiphy), i, remaining_space, | 1746 | wiphy_name(ar->hw->wiphy), i, remaining_space, |
1405 | frames); | 1747 | frames); |
1406 | |||
1407 | ar9170_dump_txstats(ar); | ||
1408 | #endif /* AR9170_QUEUE_DEBUG */ | 1748 | #endif /* AR9170_QUEUE_DEBUG */ |
1409 | frames = remaining_space; | 1749 | frames = remaining_space; |
1410 | } | 1750 | } |
@@ -1432,6 +1772,9 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1432 | arinfo->timeout = jiffies + | 1772 | arinfo->timeout = jiffies + |
1433 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1773 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1434 | 1774 | ||
1775 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | ||
1776 | ar->tx_ampdu_pending++; | ||
1777 | |||
1435 | #ifdef AR9170_QUEUE_DEBUG | 1778 | #ifdef AR9170_QUEUE_DEBUG |
1436 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", | 1779 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", |
1437 | wiphy_name(ar->hw->wiphy), i); | 1780 | wiphy_name(ar->hw->wiphy), i); |
@@ -1440,6 +1783,9 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1440 | 1783 | ||
1441 | err = ar->tx(ar, skb); | 1784 | err = ar->tx(ar, skb); |
1442 | if (unlikely(err)) { | 1785 | if (unlikely(err)) { |
1786 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | ||
1787 | ar->tx_ampdu_pending--; | ||
1788 | |||
1443 | frames_failed++; | 1789 | frames_failed++; |
1444 | dev_kfree_skb_any(skb); | 1790 | dev_kfree_skb_any(skb); |
1445 | } else { | 1791 | } else { |
@@ -1461,13 +1807,18 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1461 | 1807 | ||
1462 | if (unlikely(frames_failed)) { | 1808 | if (unlikely(frames_failed)) { |
1463 | #ifdef AR9170_QUEUE_DEBUG | 1809 | #ifdef AR9170_QUEUE_DEBUG |
1464 | printk(KERN_DEBUG "%s: frames failed =>\n", | 1810 | printk(KERN_DEBUG "%s: frames failed %d =>\n", |
1465 | wiphy_name(ar->hw->wiphy), frames_failed); | 1811 | wiphy_name(ar->hw->wiphy), frames_failed); |
1466 | #endif /* AR9170_QUEUE_DEBUG */ | 1812 | #endif /* AR9170_QUEUE_DEBUG */ |
1467 | 1813 | ||
1468 | spin_lock_irqsave(&ar->tx_stats_lock, flags); | 1814 | spin_lock_irqsave(&ar->tx_stats_lock, flags); |
1469 | ar->tx_stats[i].len -= frames_failed; | 1815 | ar->tx_stats[i].len -= frames_failed; |
1470 | ar->tx_stats[i].count -= frames_failed; | 1816 | ar->tx_stats[i].count -= frames_failed; |
1817 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
1818 | printk(KERN_DEBUG "%s: wake queue %d\n", | ||
1819 | wiphy_name(ar->hw->wiphy), i); | ||
1820 | __ar9170_dump_txstats(ar); | ||
1821 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
1471 | ieee80211_wake_queue(ar->hw, i); | 1822 | ieee80211_wake_queue(ar->hw, i); |
1472 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); | 1823 | spin_unlock_irqrestore(&ar->tx_stats_lock, flags); |
1473 | } | 1824 | } |
@@ -1479,6 +1830,90 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1479 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | 1830 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); |
1480 | } | 1831 | } |
1481 | 1832 | ||
1833 | static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) | ||
1834 | { | ||
1835 | struct ieee80211_tx_info *txinfo; | ||
1836 | struct ar9170_sta_info *sta_info; | ||
1837 | struct ar9170_sta_tid *agg; | ||
1838 | struct sk_buff *iter; | ||
1839 | unsigned long flags, f2; | ||
1840 | unsigned int max; | ||
1841 | u16 tid, seq, qseq; | ||
1842 | bool run = false, queue = false; | ||
1843 | |||
1844 | tid = ar9170_get_tid(skb); | ||
1845 | seq = ar9170_get_seq(skb); | ||
1846 | txinfo = IEEE80211_SKB_CB(skb); | ||
1847 | sta_info = (void *) txinfo->control.sta->drv_priv; | ||
1848 | agg = &sta_info->agg[tid]; | ||
1849 | max = sta_info->ampdu_max_len; | ||
1850 | |||
1851 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1852 | |||
1853 | if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) { | ||
1854 | #ifdef AR9170_TXAGG_DEBUG | ||
1855 | printk(KERN_DEBUG "%s: BlockACK session not fully initialized " | ||
1856 | "for ESS:%pM tid:%d state:%d.\n", | ||
1857 | wiphy_name(ar->hw->wiphy), agg->addr, agg->tid, | ||
1858 | agg->state); | ||
1859 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1860 | goto err_unlock; | ||
1861 | } | ||
1862 | |||
1863 | if (!agg->active) { | ||
1864 | agg->active = true; | ||
1865 | agg->ssn = seq; | ||
1866 | queue = true; | ||
1867 | } | ||
1868 | |||
1869 | /* check if seq is within the BA window */ | ||
1870 | if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) { | ||
1871 | #ifdef AR9170_TXAGG_DEBUG | ||
1872 | printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not " | ||
1873 | "fit into BA window (%d - %d)\n", | ||
1874 | wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn, | ||
1875 | (agg->ssn + max) & 0xfff); | ||
1876 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1877 | goto err_unlock; | ||
1878 | } | ||
1879 | |||
1880 | spin_lock_irqsave(&agg->queue.lock, f2); | ||
1881 | |||
1882 | skb_queue_reverse_walk(&agg->queue, iter) { | ||
1883 | qseq = ar9170_get_seq(iter); | ||
1884 | |||
1885 | if (GET_NEXT_SEQ(qseq) == seq) { | ||
1886 | __skb_queue_after(&agg->queue, iter, skb); | ||
1887 | goto queued; | ||
1888 | } | ||
1889 | } | ||
1890 | |||
1891 | __skb_queue_head(&agg->queue, skb); | ||
1892 | |||
1893 | queued: | ||
1894 | spin_unlock_irqrestore(&agg->queue.lock, f2); | ||
1895 | |||
1896 | #ifdef AR9170_TXAGG_DEBUG | ||
1897 | printk(KERN_DEBUG "%s: new aggregate %p queued.\n", | ||
1898 | wiphy_name(ar->hw->wiphy), skb); | ||
1899 | __ar9170_dump_txqueue(ar, &agg->queue); | ||
1900 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1901 | |||
1902 | if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX) | ||
1903 | run = true; | ||
1904 | |||
1905 | if (queue) | ||
1906 | list_add_tail(&agg->list, &ar->tx_ampdu_list); | ||
1907 | |||
1908 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1909 | return run; | ||
1910 | |||
1911 | err_unlock: | ||
1912 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1913 | dev_kfree_skb_irq(skb); | ||
1914 | return false; | ||
1915 | } | ||
1916 | |||
1482 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1917 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1483 | { | 1918 | { |
1484 | struct ar9170 *ar = hw->priv; | 1919 | struct ar9170 *ar = hw->priv; |
@@ -1492,8 +1927,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1492 | 1927 | ||
1493 | info = IEEE80211_SKB_CB(skb); | 1928 | info = IEEE80211_SKB_CB(skb); |
1494 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1929 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1495 | /* drop frame, we do not allow TX A-MPDU aggregation yet. */ | 1930 | bool run = ar9170_tx_ampdu_queue(ar, skb); |
1496 | goto err_free; | 1931 | |
1932 | if (run || !ar->tx_ampdu_pending) | ||
1933 | ar9170_tx_ampdu(ar); | ||
1497 | } else { | 1934 | } else { |
1498 | unsigned int queue = skb_get_queue_mapping(skb); | 1935 | unsigned int queue = skb_get_queue_mapping(skb); |
1499 | 1936 | ||
@@ -1931,6 +2368,53 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, | |||
1931 | enum sta_notify_cmd cmd, | 2368 | enum sta_notify_cmd cmd, |
1932 | struct ieee80211_sta *sta) | 2369 | struct ieee80211_sta *sta) |
1933 | { | 2370 | { |
2371 | struct ar9170 *ar = hw->priv; | ||
2372 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2373 | unsigned int i; | ||
2374 | |||
2375 | switch (cmd) { | ||
2376 | case STA_NOTIFY_ADD: | ||
2377 | memset(sta_info, 0, sizeof(*sta_info)); | ||
2378 | |||
2379 | if (!sta->ht_cap.ht_supported) | ||
2380 | break; | ||
2381 | |||
2382 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) | ||
2383 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; | ||
2384 | |||
2385 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) | ||
2386 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; | ||
2387 | |||
2388 | for (i = 0; i < AR9170_NUM_TID; i++) { | ||
2389 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; | ||
2390 | sta_info->agg[i].active = false; | ||
2391 | sta_info->agg[i].ssn = 0; | ||
2392 | sta_info->agg[i].retry = 0; | ||
2393 | sta_info->agg[i].tid = i; | ||
2394 | INIT_LIST_HEAD(&sta_info->agg[i].list); | ||
2395 | skb_queue_head_init(&sta_info->agg[i].queue); | ||
2396 | } | ||
2397 | |||
2398 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | ||
2399 | break; | ||
2400 | |||
2401 | case STA_NOTIFY_REMOVE: | ||
2402 | if (!sta->ht_cap.ht_supported) | ||
2403 | break; | ||
2404 | |||
2405 | for (i = 0; i < AR9170_NUM_TID; i++) { | ||
2406 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; | ||
2407 | skb_queue_purge(&sta_info->agg[i].queue); | ||
2408 | } | ||
2409 | |||
2410 | break; | ||
2411 | |||
2412 | default: | ||
2413 | break; | ||
2414 | } | ||
2415 | |||
2416 | if (IS_STARTED(ar) && ar->filter_changed) | ||
2417 | queue_work(ar->hw->workqueue, &ar->filter_config_work); | ||
1934 | } | 2418 | } |
1935 | 2419 | ||
1936 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 2420 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
@@ -1985,18 +2469,65 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
1985 | enum ieee80211_ampdu_mlme_action action, | 2469 | enum ieee80211_ampdu_mlme_action action, |
1986 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2470 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
1987 | { | 2471 | { |
2472 | struct ar9170 *ar = hw->priv; | ||
2473 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2474 | struct ar9170_sta_tid *tid_info = &sta_info->agg[tid]; | ||
2475 | unsigned long flags; | ||
2476 | |||
2477 | if (!modparam_ht) | ||
2478 | return -EOPNOTSUPP; | ||
2479 | |||
1988 | switch (action) { | 2480 | switch (action) { |
2481 | case IEEE80211_AMPDU_TX_START: | ||
2482 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2483 | if (tid_info->state != AR9170_TID_STATE_SHUTDOWN || | ||
2484 | !list_empty(&tid_info->list)) { | ||
2485 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2486 | #ifdef AR9170_TXAGG_DEBUG | ||
2487 | printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] " | ||
2488 | "is in a very bad state!\n", | ||
2489 | wiphy_name(hw->wiphy), sta->addr, tid); | ||
2490 | #endif /* AR9170_TXAGG_DEBUG */ | ||
2491 | return -EBUSY; | ||
2492 | } | ||
2493 | |||
2494 | *ssn = tid_info->ssn; | ||
2495 | tid_info->state = AR9170_TID_STATE_PROGRESS; | ||
2496 | tid_info->active = false; | ||
2497 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2498 | ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); | ||
2499 | break; | ||
2500 | |||
2501 | case IEEE80211_AMPDU_TX_STOP: | ||
2502 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2503 | tid_info->state = AR9170_TID_STATE_SHUTDOWN; | ||
2504 | list_del_init(&tid_info->list); | ||
2505 | tid_info->active = false; | ||
2506 | skb_queue_purge(&tid_info->queue); | ||
2507 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2508 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); | ||
2509 | break; | ||
2510 | |||
2511 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2512 | #ifdef AR9170_TXAGG_DEBUG | ||
2513 | printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n", | ||
2514 | wiphy_name(hw->wiphy), sta->addr, tid); | ||
2515 | #endif /* AR9170_TXAGG_DEBUG */ | ||
2516 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2517 | sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE; | ||
2518 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2519 | break; | ||
2520 | |||
1989 | case IEEE80211_AMPDU_RX_START: | 2521 | case IEEE80211_AMPDU_RX_START: |
1990 | case IEEE80211_AMPDU_RX_STOP: | 2522 | case IEEE80211_AMPDU_RX_STOP: |
1991 | /* | 2523 | /* Handled by firmware */ |
1992 | * Something goes wrong -- RX locks up | 2524 | break; |
1993 | * after a while of receiving aggregated | 2525 | |
1994 | * frames -- not enabling for now. | ||
1995 | */ | ||
1996 | return -EOPNOTSUPP; | ||
1997 | default: | 2526 | default: |
1998 | return -EOPNOTSUPP; | 2527 | return -EOPNOTSUPP; |
1999 | } | 2528 | } |
2529 | |||
2530 | return 0; | ||
2000 | } | 2531 | } |
2001 | 2532 | ||
2002 | static const struct ieee80211_ops ar9170_ops = { | 2533 | static const struct ieee80211_ops ar9170_ops = { |
@@ -2045,6 +2576,8 @@ void *ar9170_alloc(size_t priv_size) | |||
2045 | mutex_init(&ar->mutex); | 2576 | mutex_init(&ar->mutex); |
2046 | spin_lock_init(&ar->cmdlock); | 2577 | spin_lock_init(&ar->cmdlock); |
2047 | spin_lock_init(&ar->tx_stats_lock); | 2578 | spin_lock_init(&ar->tx_stats_lock); |
2579 | spin_lock_init(&ar->tx_ampdu_list_lock); | ||
2580 | skb_queue_head_init(&ar->tx_status_ampdu); | ||
2048 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | 2581 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { |
2049 | skb_queue_head_init(&ar->tx_status[i]); | 2582 | skb_queue_head_init(&ar->tx_status[i]); |
2050 | skb_queue_head_init(&ar->tx_pending[i]); | 2583 | skb_queue_head_init(&ar->tx_pending[i]); |
@@ -2053,6 +2586,7 @@ void *ar9170_alloc(size_t priv_size) | |||
2053 | INIT_WORK(&ar->filter_config_work, ar9170_set_filters); | 2586 | INIT_WORK(&ar->filter_config_work, ar9170_set_filters); |
2054 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); | 2587 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); |
2055 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); | 2588 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); |
2589 | INIT_LIST_HEAD(&ar->tx_ampdu_list); | ||
2056 | 2590 | ||
2057 | /* all hw supports 2.4 GHz, so set channel to 1 by default */ | 2591 | /* all hw supports 2.4 GHz, so set channel to 1 by default */ |
2058 | ar->channel = &ar9170_2ghz_chantable[0]; | 2592 | ar->channel = &ar9170_2ghz_chantable[0]; |
@@ -2066,6 +2600,13 @@ void *ar9170_alloc(size_t priv_size) | |||
2066 | IEEE80211_HW_SIGNAL_DBM | | 2600 | IEEE80211_HW_SIGNAL_DBM | |
2067 | IEEE80211_HW_NOISE_DBM; | 2601 | IEEE80211_HW_NOISE_DBM; |
2068 | 2602 | ||
2603 | if (modparam_ht) { | ||
2604 | ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
2605 | } else { | ||
2606 | ar9170_band_2GHz.ht_cap.ht_supported = false; | ||
2607 | ar9170_band_5GHz.ht_cap.ht_supported = false; | ||
2608 | } | ||
2609 | |||
2069 | ar->hw->queues = __AR9170_NUM_TXQ; | 2610 | ar->hw->queues = __AR9170_NUM_TXQ; |
2070 | ar->hw->extra_tx_headroom = 8; | 2611 | ar->hw->extra_tx_headroom = 8; |
2071 | ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); | 2612 | ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); |
@@ -2091,6 +2632,7 @@ static int ar9170_read_eeprom(struct ar9170 *ar) | |||
2091 | u8 *eeprom = (void *)&ar->eeprom; | 2632 | u8 *eeprom = (void *)&ar->eeprom; |
2092 | u8 *addr = ar->eeprom.mac_address; | 2633 | u8 *addr = ar->eeprom.mac_address; |
2093 | __le32 offsets[RW]; | 2634 | __le32 offsets[RW]; |
2635 | unsigned int rx_streams, tx_streams, tx_params = 0; | ||
2094 | int i, j, err, bands = 0; | 2636 | int i, j, err, bands = 0; |
2095 | 2637 | ||
2096 | BUILD_BUG_ON(sizeof(ar->eeprom) & 3); | 2638 | BUILD_BUG_ON(sizeof(ar->eeprom) & 3); |
@@ -2127,6 +2669,20 @@ static int ar9170_read_eeprom(struct ar9170 *ar) | |||
2127 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; | 2669 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; |
2128 | bands++; | 2670 | bands++; |
2129 | } | 2671 | } |
2672 | |||
2673 | rx_streams = hweight8(ar->eeprom.rx_mask); | ||
2674 | tx_streams = hweight8(ar->eeprom.tx_mask); | ||
2675 | |||
2676 | if (rx_streams != tx_streams) | ||
2677 | tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; | ||
2678 | |||
2679 | if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) | ||
2680 | tx_params = (tx_streams - 1) << | ||
2681 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
2682 | |||
2683 | ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; | ||
2684 | ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; | ||
2685 | |||
2130 | /* | 2686 | /* |
2131 | * I measured this, a bandswitch takes roughly | 2687 | * I measured this, a bandswitch takes roughly |
2132 | * 135 ms and a frequency switch about 80. | 2688 | * 135 ms and a frequency switch about 80. |