diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2010-05-01 12:18:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-05-07 14:55:47 -0400 |
commit | f3926b49b7122f66f8f2a1da4ae3275b112ab3e7 (patch) | |
tree | d4c595cc976d5b5e76077a67afc3e754f06c1c62 | |
parent | adfba3c7c026a6a5560d2a43fefc9b198cb74462 (diff) |
ar9170usb: remove deprecated aggregation code
This patch removes the incomplete AMPDU implementation in ar9170usb.
The code in question is:
* too big and complex (more than 550 SLOC.)
This is enough to qualify for a new separate code file!
* unbalanced quantity & quality
over-engineered areas like:
* xmit scheduling and queuing frames for multiple HT peers
* redundant frame sorting
are confronted by gaping holes:
* accurate transmission feedback
* firmware error-handling and device reset
* HT rate control algorithm
* error-prone
Since its inclusion, hardly anything was done to fix
any of the outlined flaws from the initial commit message.
=> This also indicates poor maintainability.
* relies heavily on several spinlocks.
As a result of this shortcomings, the code is slow and does not
even support the most basic 11n requirement: HT station mode.
Therefore, I request to purge my heap of **** from the kernel:
"ar9170: implement transmit aggregation".
The next item on the agenda is: (re-)start from scratch with
an adequate design to accommodate the special requirements
and features of the available frameworks and tools.
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ar9170/ar9170.h | 52 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ar9170/main.c | 558 |
2 files changed, 12 insertions, 598 deletions
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index dc662b76a1c8..4f845f80c098 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -109,41 +109,6 @@ struct ar9170_rxstream_mpdu_merge { | |||
109 | bool has_plcp; | 109 | bool has_plcp; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | #define AR9170_NUM_TID 16 | ||
113 | #define WME_BA_BMP_SIZE 64 | ||
114 | #define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) | ||
115 | |||
116 | #define WME_AC_BE 2 | ||
117 | #define WME_AC_BK 3 | ||
118 | #define WME_AC_VI 1 | ||
119 | #define WME_AC_VO 0 | ||
120 | |||
121 | #define TID_TO_WME_AC(_tid) \ | ||
122 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | ||
123 | (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ | ||
124 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | ||
125 | WME_AC_VO) | ||
126 | |||
127 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | ||
128 | ((((_seqno) - (_start)) & 0xfff) < (_bawsz)) | ||
129 | |||
130 | enum ar9170_tid_state { | ||
131 | AR9170_TID_STATE_INVALID, | ||
132 | AR9170_TID_STATE_SHUTDOWN, | ||
133 | AR9170_TID_STATE_PROGRESS, | ||
134 | AR9170_TID_STATE_COMPLETE, | ||
135 | }; | ||
136 | |||
137 | struct ar9170_sta_tid { | ||
138 | struct list_head list; | ||
139 | struct sk_buff_head queue; | ||
140 | u8 addr[ETH_ALEN]; | ||
141 | u16 ssn; | ||
142 | u16 tid; | ||
143 | enum ar9170_tid_state state; | ||
144 | bool active; | ||
145 | }; | ||
146 | |||
147 | struct ar9170_tx_queue_stats { | 112 | struct ar9170_tx_queue_stats { |
148 | unsigned int len; | 113 | unsigned int len; |
149 | unsigned int limit; | 114 | unsigned int limit; |
@@ -152,14 +117,11 @@ struct ar9170_tx_queue_stats { | |||
152 | 117 | ||
153 | #define AR9170_QUEUE_TIMEOUT 64 | 118 | #define AR9170_QUEUE_TIMEOUT 64 |
154 | #define AR9170_TX_TIMEOUT 8 | 119 | #define AR9170_TX_TIMEOUT 8 |
155 | #define AR9170_BA_TIMEOUT 4 | ||
156 | #define AR9170_JANITOR_DELAY 128 | 120 | #define AR9170_JANITOR_DELAY 128 |
157 | #define AR9170_TX_INVALID_RATE 0xffffffff | 121 | #define AR9170_TX_INVALID_RATE 0xffffffff |
158 | 122 | ||
159 | #define AR9170_NUM_TX_STATUS 128 | 123 | #define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH |
160 | #define AR9170_NUM_TX_AGG_MAX 30 | 124 | #define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) |
161 | #define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH | ||
162 | #define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) | ||
163 | 125 | ||
164 | struct ar9170 { | 126 | struct ar9170 { |
165 | struct ieee80211_hw *hw; | 127 | struct ieee80211_hw *hw; |
@@ -234,11 +196,6 @@ struct ar9170 { | |||
234 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; | 196 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; |
235 | struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; | 197 | struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; |
236 | struct delayed_work tx_janitor; | 198 | struct delayed_work tx_janitor; |
237 | /* tx ampdu */ | ||
238 | struct sk_buff_head tx_status_ampdu; | ||
239 | spinlock_t tx_ampdu_list_lock; | ||
240 | struct list_head tx_ampdu_list; | ||
241 | atomic_t tx_ampdu_pending; | ||
242 | 199 | ||
243 | /* rxstream mpdu merge */ | 200 | /* rxstream mpdu merge */ |
244 | struct ar9170_rxstream_mpdu_merge rx_mpdu; | 201 | struct ar9170_rxstream_mpdu_merge rx_mpdu; |
@@ -250,11 +207,6 @@ struct ar9170 { | |||
250 | u8 global_ampdu_factor; | 207 | u8 global_ampdu_factor; |
251 | }; | 208 | }; |
252 | 209 | ||
253 | struct ar9170_sta_info { | ||
254 | struct ar9170_sta_tid agg[AR9170_NUM_TID]; | ||
255 | unsigned int ampdu_max_len; | ||
256 | }; | ||
257 | |||
258 | struct ar9170_tx_info { | 210 | struct ar9170_tx_info { |
259 | unsigned long timeout; | 211 | unsigned long timeout; |
260 | }; | 212 | }; |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index dfcc055a827f..b0654c873300 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -49,10 +49,6 @@ 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 | |||
56 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ | 52 | #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ |
57 | .bitrate = (_bitrate), \ | 53 | .bitrate = (_bitrate), \ |
58 | .flags = (_flags), \ | 54 | .flags = (_flags), \ |
@@ -181,7 +177,6 @@ static struct ieee80211_supported_band ar9170_band_5GHz = { | |||
181 | }; | 177 | }; |
182 | 178 | ||
183 | static void ar9170_tx(struct ar9170 *ar); | 179 | static void ar9170_tx(struct ar9170 *ar); |
184 | static bool ar9170_tx_ampdu(struct ar9170 *ar); | ||
185 | 180 | ||
186 | static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) | 181 | static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) |
187 | { | 182 | { |
@@ -194,21 +189,7 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb) | |||
194 | return ar9170_get_seq_h((void *) txc->frame_data); | 189 | return ar9170_get_seq_h((void *) txc->frame_data); |
195 | } | 190 | } |
196 | 191 | ||
197 | static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr) | 192 | #ifdef AR9170_QUEUE_DEBUG |
198 | { | ||
199 | return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
200 | } | ||
201 | |||
202 | static inline u16 ar9170_get_tid(struct sk_buff *skb) | ||
203 | { | ||
204 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
205 | return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data); | ||
206 | } | ||
207 | |||
208 | #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) | ||
209 | #define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb))) | ||
210 | |||
211 | #if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG) | ||
212 | static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) | 193 | static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) |
213 | { | 194 | { |
214 | struct ar9170_tx_control *txc = (void *) skb->data; | 195 | struct ar9170_tx_control *txc = (void *) skb->data; |
@@ -243,7 +224,7 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, | |||
243 | "mismatch %d != %d\n", skb_queue_len(queue), i); | 224 | "mismatch %d != %d\n", skb_queue_len(queue), i); |
244 | printk(KERN_DEBUG "---[ end ]---\n"); | 225 | printk(KERN_DEBUG "---[ end ]---\n"); |
245 | } | 226 | } |
246 | #endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */ | 227 | #endif /* AR9170_QUEUE_DEBUG */ |
247 | 228 | ||
248 | #ifdef AR9170_QUEUE_DEBUG | 229 | #ifdef AR9170_QUEUE_DEBUG |
249 | static void ar9170_dump_txqueue(struct ar9170 *ar, | 230 | static void ar9170_dump_txqueue(struct ar9170 *ar, |
@@ -274,20 +255,6 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) | |||
274 | } | 255 | } |
275 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | 256 | #endif /* AR9170_QUEUE_STOP_DEBUG */ |
276 | 257 | ||
277 | #ifdef AR9170_TXAGG_DEBUG | ||
278 | static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) | ||
279 | { | ||
280 | unsigned long flags; | ||
281 | |||
282 | spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); | ||
283 | printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n", | ||
284 | wiphy_name(ar->hw->wiphy)); | ||
285 | __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); | ||
286 | spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); | ||
287 | } | ||
288 | |||
289 | #endif /* AR9170_TXAGG_DEBUG */ | ||
290 | |||
291 | /* caller must guarantee exclusive access for _bin_ queue. */ | 258 | /* caller must guarantee exclusive access for _bin_ queue. */ |
292 | static void ar9170_recycle_expired(struct ar9170 *ar, | 259 | static void ar9170_recycle_expired(struct ar9170 *ar, |
293 | struct sk_buff_head *queue, | 260 | struct sk_buff_head *queue, |
@@ -359,70 +326,6 @@ static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, | |||
359 | ieee80211_tx_status_irqsafe(ar->hw, skb); | 326 | ieee80211_tx_status_irqsafe(ar->hw, skb); |
360 | } | 327 | } |
361 | 328 | ||
362 | static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) | ||
363 | { | ||
364 | struct sk_buff_head success; | ||
365 | struct sk_buff *skb; | ||
366 | unsigned int i; | ||
367 | unsigned long queue_bitmap = 0; | ||
368 | |||
369 | skb_queue_head_init(&success); | ||
370 | |||
371 | while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS) | ||
372 | __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu)); | ||
373 | |||
374 | ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success); | ||
375 | |||
376 | #ifdef AR9170_TXAGG_DEBUG | ||
377 | printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n", | ||
378 | wiphy_name(ar->hw->wiphy), skb_queue_len(&success)); | ||
379 | __ar9170_dump_txqueue(ar, &success); | ||
380 | #endif /* AR9170_TXAGG_DEBUG */ | ||
381 | |||
382 | while ((skb = __skb_dequeue(&success))) { | ||
383 | struct ieee80211_tx_info *txinfo; | ||
384 | |||
385 | queue_bitmap |= BIT(skb_get_queue_mapping(skb)); | ||
386 | |||
387 | txinfo = IEEE80211_SKB_CB(skb); | ||
388 | ieee80211_tx_info_clear_status(txinfo); | ||
389 | |||
390 | txinfo->flags |= IEEE80211_TX_STAT_ACK; | ||
391 | txinfo->status.rates[0].count = 1; | ||
392 | |||
393 | skb_pull(skb, sizeof(struct ar9170_tx_control)); | ||
394 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
395 | } | ||
396 | |||
397 | for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { | ||
398 | #ifdef AR9170_QUEUE_STOP_DEBUG | ||
399 | printk(KERN_DEBUG "%s: wake queue %d\n", | ||
400 | wiphy_name(ar->hw->wiphy), i); | ||
401 | __ar9170_dump_txstats(ar); | ||
402 | #endif /* AR9170_QUEUE_STOP_DEBUG */ | ||
403 | ieee80211_wake_queue(ar->hw, i); | ||
404 | } | ||
405 | |||
406 | if (queue_bitmap) | ||
407 | ar9170_tx(ar); | ||
408 | } | ||
409 | |||
410 | static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) | ||
411 | { | ||
412 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
413 | struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; | ||
414 | |||
415 | arinfo->timeout = jiffies + | ||
416 | msecs_to_jiffies(AR9170_BA_TIMEOUT); | ||
417 | |||
418 | skb_queue_tail(&ar->tx_status_ampdu, skb); | ||
419 | ar9170_tx_fake_ampdu_status(ar); | ||
420 | |||
421 | if (atomic_dec_and_test(&ar->tx_ampdu_pending) && | ||
422 | !list_empty(&ar->tx_ampdu_list)) | ||
423 | ar9170_tx_ampdu(ar); | ||
424 | } | ||
425 | |||
426 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | 329 | void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) |
427 | { | 330 | { |
428 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 331 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -446,14 +349,10 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
446 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) { | 349 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) { |
447 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); | 350 | ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); |
448 | } else { | 351 | } else { |
449 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 352 | arinfo->timeout = jiffies + |
450 | ar9170_tx_ampdu_callback(ar, skb); | 353 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
451 | } else { | ||
452 | arinfo->timeout = jiffies + | ||
453 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | ||
454 | 354 | ||
455 | skb_queue_tail(&ar->tx_status[queue], skb); | 355 | skb_queue_tail(&ar->tx_status[queue], skb); |
456 | } | ||
457 | } | 356 | } |
458 | 357 | ||
459 | if (!ar->tx_stats[queue].len && | 358 | if (!ar->tx_stats[queue].len && |
@@ -523,38 +422,6 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, | |||
523 | return NULL; | 422 | return NULL; |
524 | } | 423 | } |
525 | 424 | ||
526 | static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r) | ||
527 | { | ||
528 | struct sk_buff *skb; | ||
529 | struct ieee80211_tx_info *txinfo; | ||
530 | |||
531 | while (count) { | ||
532 | skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r); | ||
533 | if (!skb) | ||
534 | break; | ||
535 | |||
536 | txinfo = IEEE80211_SKB_CB(skb); | ||
537 | ieee80211_tx_info_clear_status(txinfo); | ||
538 | |||
539 | /* FIXME: maybe more ? */ | ||
540 | txinfo->status.rates[0].count = 1; | ||
541 | |||
542 | skb_pull(skb, sizeof(struct ar9170_tx_control)); | ||
543 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
544 | count--; | ||
545 | } | ||
546 | |||
547 | #ifdef AR9170_TXAGG_DEBUG | ||
548 | if (count) { | ||
549 | printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more " | ||
550 | "suitable frames left in tx_status queue.\n", | ||
551 | wiphy_name(ar->hw->wiphy), count); | ||
552 | |||
553 | ar9170_dump_tx_status_ampdu(ar); | ||
554 | } | ||
555 | #endif /* AR9170_TXAGG_DEBUG */ | ||
556 | } | ||
557 | |||
558 | /* | 425 | /* |
559 | * This worker tries to keeps an maintain tx_status queues. | 426 | * This worker tries to keeps an maintain tx_status queues. |
560 | * So we can guarantee that incoming tx_status reports are | 427 | * So we can guarantee that incoming tx_status reports are |
@@ -591,8 +458,6 @@ static void ar9170_tx_janitor(struct work_struct *work) | |||
591 | resched = true; | 458 | resched = true; |
592 | } | 459 | } |
593 | 460 | ||
594 | ar9170_tx_fake_ampdu_status(ar); | ||
595 | |||
596 | if (!resched) | 461 | if (!resched) |
597 | return; | 462 | return; |
598 | 463 | ||
@@ -672,10 +537,6 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |||
672 | 537 | ||
673 | case 0xc5: | 538 | case 0xc5: |
674 | /* BlockACK events */ | 539 | /* 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); | ||
679 | break; | 540 | break; |
680 | 541 | ||
681 | case 0xc6: | 542 | case 0xc6: |
@@ -1246,7 +1107,6 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1246 | ar->global_ampdu_density = 6; | 1107 | ar->global_ampdu_density = 6; |
1247 | ar->global_ampdu_factor = 3; | 1108 | ar->global_ampdu_factor = 3; |
1248 | 1109 | ||
1249 | atomic_set(&ar->tx_ampdu_pending, 0); | ||
1250 | ar->bad_hw_nagger = jiffies; | 1110 | ar->bad_hw_nagger = jiffies; |
1251 | 1111 | ||
1252 | err = ar->open(ar); | 1112 | err = ar->open(ar); |
@@ -1309,40 +1169,10 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) | |||
1309 | skb_queue_purge(&ar->tx_pending[i]); | 1169 | skb_queue_purge(&ar->tx_pending[i]); |
1310 | skb_queue_purge(&ar->tx_status[i]); | 1170 | skb_queue_purge(&ar->tx_status[i]); |
1311 | } | 1171 | } |
1312 | skb_queue_purge(&ar->tx_status_ampdu); | ||
1313 | 1172 | ||
1314 | mutex_unlock(&ar->mutex); | 1173 | mutex_unlock(&ar->mutex); |
1315 | } | 1174 | } |
1316 | 1175 | ||
1317 | static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb) | ||
1318 | { | ||
1319 | struct ar9170_tx_control *txc = (void *) skb->data; | ||
1320 | |||
1321 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU); | ||
1322 | } | ||
1323 | |||
1324 | static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst, | ||
1325 | struct sk_buff *src) | ||
1326 | { | ||
1327 | struct ar9170_tx_control *dst_txc, *src_txc; | ||
1328 | struct ieee80211_tx_info *dst_info, *src_info; | ||
1329 | struct ar9170_tx_info *dst_arinfo, *src_arinfo; | ||
1330 | |||
1331 | src_txc = (void *) src->data; | ||
1332 | src_info = IEEE80211_SKB_CB(src); | ||
1333 | src_arinfo = (void *) src_info->rate_driver_data; | ||
1334 | |||
1335 | dst_txc = (void *) dst->data; | ||
1336 | dst_info = IEEE80211_SKB_CB(dst); | ||
1337 | dst_arinfo = (void *) dst_info->rate_driver_data; | ||
1338 | |||
1339 | dst_txc->phy_control = src_txc->phy_control; | ||
1340 | |||
1341 | /* same MCS for the whole aggregate */ | ||
1342 | memcpy(dst_info->driver_rates, src_info->driver_rates, | ||
1343 | sizeof(dst_info->driver_rates)); | ||
1344 | } | ||
1345 | |||
1346 | static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | 1176 | static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) |
1347 | { | 1177 | { |
1348 | struct ieee80211_hdr *hdr; | 1178 | struct ieee80211_hdr *hdr; |
@@ -1419,14 +1249,7 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1419 | txc->phy_control |= | 1249 | txc->phy_control |= |
1420 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); | 1250 | cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); |
1421 | 1251 | ||
1422 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1252 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); |
1423 | if (unlikely(!info->control.sta)) | ||
1424 | goto err_out; | ||
1425 | |||
1426 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); | ||
1427 | } else { | ||
1428 | txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); | ||
1429 | } | ||
1430 | } | 1253 | } |
1431 | 1254 | ||
1432 | return 0; | 1255 | return 0; |
@@ -1536,158 +1359,6 @@ static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) | |||
1536 | txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); | 1359 | txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); |
1537 | } | 1360 | } |
1538 | 1361 | ||
1539 | static bool ar9170_tx_ampdu(struct ar9170 *ar) | ||
1540 | { | ||
1541 | struct sk_buff_head agg; | ||
1542 | struct ar9170_sta_tid *tid_info = NULL, *tmp; | ||
1543 | struct sk_buff *skb, *first = NULL; | ||
1544 | unsigned long flags, f2; | ||
1545 | unsigned int i = 0; | ||
1546 | u16 seq, queue, tmpssn; | ||
1547 | bool run = false; | ||
1548 | |||
1549 | skb_queue_head_init(&agg); | ||
1550 | |||
1551 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1552 | if (list_empty(&ar->tx_ampdu_list)) { | ||
1553 | #ifdef AR9170_TXAGG_DEBUG | ||
1554 | printk(KERN_DEBUG "%s: aggregation list is empty.\n", | ||
1555 | wiphy_name(ar->hw->wiphy)); | ||
1556 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1557 | goto out_unlock; | ||
1558 | } | ||
1559 | |||
1560 | list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) { | ||
1561 | if (tid_info->state != AR9170_TID_STATE_COMPLETE) { | ||
1562 | #ifdef AR9170_TXAGG_DEBUG | ||
1563 | printk(KERN_DEBUG "%s: dangling aggregation entry!\n", | ||
1564 | wiphy_name(ar->hw->wiphy)); | ||
1565 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1566 | continue; | ||
1567 | } | ||
1568 | |||
1569 | if (++i > 64) { | ||
1570 | #ifdef AR9170_TXAGG_DEBUG | ||
1571 | printk(KERN_DEBUG "%s: enough frames aggregated.\n", | ||
1572 | wiphy_name(ar->hw->wiphy)); | ||
1573 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1574 | break; | ||
1575 | } | ||
1576 | |||
1577 | queue = TID_TO_WME_AC(tid_info->tid); | ||
1578 | |||
1579 | if (skb_queue_len(&ar->tx_pending[queue]) >= | ||
1580 | AR9170_NUM_TX_AGG_MAX) { | ||
1581 | #ifdef AR9170_TXAGG_DEBUG | ||
1582 | printk(KERN_DEBUG "%s: queue %d full.\n", | ||
1583 | wiphy_name(ar->hw->wiphy), queue); | ||
1584 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1585 | continue; | ||
1586 | } | ||
1587 | |||
1588 | list_del_init(&tid_info->list); | ||
1589 | |||
1590 | spin_lock_irqsave(&tid_info->queue.lock, f2); | ||
1591 | tmpssn = seq = tid_info->ssn; | ||
1592 | first = skb_peek(&tid_info->queue); | ||
1593 | |||
1594 | if (likely(first)) | ||
1595 | tmpssn = ar9170_get_seq(first); | ||
1596 | |||
1597 | if (unlikely(tmpssn != seq)) { | ||
1598 | #ifdef AR9170_TXAGG_DEBUG | ||
1599 | printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.", | ||
1600 | wiphy_name(ar->hw->wiphy), seq, tmpssn); | ||
1601 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1602 | tid_info->ssn = tmpssn; | ||
1603 | } | ||
1604 | |||
1605 | #ifdef AR9170_TXAGG_DEBUG | ||
1606 | printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with " | ||
1607 | "%d queued frames.\n", wiphy_name(ar->hw->wiphy), | ||
1608 | tid_info->tid, tid_info->ssn, | ||
1609 | skb_queue_len(&tid_info->queue)); | ||
1610 | __ar9170_dump_txqueue(ar, &tid_info->queue); | ||
1611 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1612 | |||
1613 | while ((skb = skb_peek(&tid_info->queue))) { | ||
1614 | if (unlikely(ar9170_get_seq(skb) != seq)) | ||
1615 | break; | ||
1616 | |||
1617 | __skb_unlink(skb, &tid_info->queue); | ||
1618 | tid_info->ssn = seq = GET_NEXT_SEQ(seq); | ||
1619 | |||
1620 | if (unlikely(skb_get_queue_mapping(skb) != queue)) { | ||
1621 | #ifdef AR9170_TXAGG_DEBUG | ||
1622 | printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d " | ||
1623 | "!match.\n", wiphy_name(ar->hw->wiphy), | ||
1624 | tid_info->tid, | ||
1625 | TID_TO_WME_AC(tid_info->tid), | ||
1626 | skb_get_queue_mapping(skb)); | ||
1627 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1628 | dev_kfree_skb_any(skb); | ||
1629 | continue; | ||
1630 | } | ||
1631 | |||
1632 | if (unlikely(first == skb)) { | ||
1633 | ar9170_tx_prepare_phy(ar, skb); | ||
1634 | __skb_queue_tail(&agg, skb); | ||
1635 | first = skb; | ||
1636 | } else { | ||
1637 | ar9170_tx_copy_phy(ar, skb, first); | ||
1638 | __skb_queue_tail(&agg, skb); | ||
1639 | } | ||
1640 | |||
1641 | if (unlikely(skb_queue_len(&agg) == | ||
1642 | AR9170_NUM_TX_AGG_MAX)) | ||
1643 | break; | ||
1644 | } | ||
1645 | |||
1646 | if (skb_queue_empty(&tid_info->queue)) | ||
1647 | tid_info->active = false; | ||
1648 | else | ||
1649 | list_add_tail(&tid_info->list, | ||
1650 | &ar->tx_ampdu_list); | ||
1651 | |||
1652 | spin_unlock_irqrestore(&tid_info->queue.lock, f2); | ||
1653 | |||
1654 | if (unlikely(skb_queue_empty(&agg))) { | ||
1655 | #ifdef AR9170_TXAGG_DEBUG | ||
1656 | printk(KERN_DEBUG "%s: queued empty list!\n", | ||
1657 | wiphy_name(ar->hw->wiphy)); | ||
1658 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1659 | continue; | ||
1660 | } | ||
1661 | |||
1662 | /* | ||
1663 | * tell the FW/HW that this is the last frame, | ||
1664 | * that way it will wait for the immediate block ack. | ||
1665 | */ | ||
1666 | ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); | ||
1667 | |||
1668 | #ifdef AR9170_TXAGG_DEBUG | ||
1669 | printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", | ||
1670 | wiphy_name(ar->hw->wiphy)); | ||
1671 | __ar9170_dump_txqueue(ar, &agg); | ||
1672 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1673 | |||
1674 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1675 | |||
1676 | spin_lock_irqsave(&ar->tx_pending[queue].lock, flags); | ||
1677 | skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); | ||
1678 | spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags); | ||
1679 | run = true; | ||
1680 | |||
1681 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1682 | } | ||
1683 | |||
1684 | out_unlock: | ||
1685 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1686 | __skb_queue_purge(&agg); | ||
1687 | |||
1688 | return run; | ||
1689 | } | ||
1690 | |||
1691 | static void ar9170_tx(struct ar9170 *ar) | 1362 | static void ar9170_tx(struct ar9170 *ar) |
1692 | { | 1363 | { |
1693 | struct sk_buff *skb; | 1364 | struct sk_buff *skb; |
@@ -1762,9 +1433,6 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1762 | arinfo->timeout = jiffies + | 1433 | arinfo->timeout = jiffies + |
1763 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1434 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1764 | 1435 | ||
1765 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1766 | atomic_inc(&ar->tx_ampdu_pending); | ||
1767 | |||
1768 | #ifdef AR9170_QUEUE_DEBUG | 1436 | #ifdef AR9170_QUEUE_DEBUG |
1769 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", | 1437 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", |
1770 | wiphy_name(ar->hw->wiphy), i); | 1438 | wiphy_name(ar->hw->wiphy), i); |
@@ -1773,9 +1441,6 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1773 | 1441 | ||
1774 | err = ar->tx(ar, skb); | 1442 | err = ar->tx(ar, skb); |
1775 | if (unlikely(err)) { | 1443 | if (unlikely(err)) { |
1776 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1777 | atomic_dec(&ar->tx_ampdu_pending); | ||
1778 | |||
1779 | frames_failed++; | 1444 | frames_failed++; |
1780 | dev_kfree_skb_any(skb); | 1445 | dev_kfree_skb_any(skb); |
1781 | } else { | 1446 | } else { |
@@ -1822,94 +1487,11 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1822 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | 1487 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); |
1823 | } | 1488 | } |
1824 | 1489 | ||
1825 | static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) | ||
1826 | { | ||
1827 | struct ieee80211_tx_info *txinfo; | ||
1828 | struct ar9170_sta_info *sta_info; | ||
1829 | struct ar9170_sta_tid *agg; | ||
1830 | struct sk_buff *iter; | ||
1831 | unsigned long flags, f2; | ||
1832 | unsigned int max; | ||
1833 | u16 tid, seq, qseq; | ||
1834 | bool run = false, queue = false; | ||
1835 | |||
1836 | tid = ar9170_get_tid(skb); | ||
1837 | seq = ar9170_get_seq(skb); | ||
1838 | txinfo = IEEE80211_SKB_CB(skb); | ||
1839 | sta_info = (void *) txinfo->control.sta->drv_priv; | ||
1840 | agg = &sta_info->agg[tid]; | ||
1841 | max = sta_info->ampdu_max_len; | ||
1842 | |||
1843 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
1844 | |||
1845 | if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) { | ||
1846 | #ifdef AR9170_TXAGG_DEBUG | ||
1847 | printk(KERN_DEBUG "%s: BlockACK session not fully initialized " | ||
1848 | "for ESS:%pM tid:%d state:%d.\n", | ||
1849 | wiphy_name(ar->hw->wiphy), agg->addr, agg->tid, | ||
1850 | agg->state); | ||
1851 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1852 | goto err_unlock; | ||
1853 | } | ||
1854 | |||
1855 | if (!agg->active) { | ||
1856 | agg->active = true; | ||
1857 | agg->ssn = seq; | ||
1858 | queue = true; | ||
1859 | } | ||
1860 | |||
1861 | /* check if seq is within the BA window */ | ||
1862 | if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) { | ||
1863 | #ifdef AR9170_TXAGG_DEBUG | ||
1864 | printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not " | ||
1865 | "fit into BA window (%d - %d)\n", | ||
1866 | wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn, | ||
1867 | (agg->ssn + max) & 0xfff); | ||
1868 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1869 | goto err_unlock; | ||
1870 | } | ||
1871 | |||
1872 | spin_lock_irqsave(&agg->queue.lock, f2); | ||
1873 | |||
1874 | skb_queue_reverse_walk(&agg->queue, iter) { | ||
1875 | qseq = ar9170_get_seq(iter); | ||
1876 | |||
1877 | if (GET_NEXT_SEQ(qseq) == seq) { | ||
1878 | __skb_queue_after(&agg->queue, iter, skb); | ||
1879 | goto queued; | ||
1880 | } | ||
1881 | } | ||
1882 | |||
1883 | __skb_queue_head(&agg->queue, skb); | ||
1884 | |||
1885 | queued: | ||
1886 | spin_unlock_irqrestore(&agg->queue.lock, f2); | ||
1887 | |||
1888 | #ifdef AR9170_TXAGG_DEBUG | ||
1889 | printk(KERN_DEBUG "%s: new aggregate %p queued.\n", | ||
1890 | wiphy_name(ar->hw->wiphy), skb); | ||
1891 | __ar9170_dump_txqueue(ar, &agg->queue); | ||
1892 | #endif /* AR9170_TXAGG_DEBUG */ | ||
1893 | |||
1894 | if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX) | ||
1895 | run = true; | ||
1896 | |||
1897 | if (queue) | ||
1898 | list_add_tail(&agg->list, &ar->tx_ampdu_list); | ||
1899 | |||
1900 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1901 | return run; | ||
1902 | |||
1903 | err_unlock: | ||
1904 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
1905 | dev_kfree_skb_irq(skb); | ||
1906 | return false; | ||
1907 | } | ||
1908 | |||
1909 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1490 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1910 | { | 1491 | { |
1911 | struct ar9170 *ar = hw->priv; | 1492 | struct ar9170 *ar = hw->priv; |
1912 | struct ieee80211_tx_info *info; | 1493 | struct ieee80211_tx_info *info; |
1494 | unsigned int queue; | ||
1913 | 1495 | ||
1914 | if (unlikely(!IS_STARTED(ar))) | 1496 | if (unlikely(!IS_STARTED(ar))) |
1915 | goto err_free; | 1497 | goto err_free; |
@@ -1917,18 +1499,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1917 | if (unlikely(ar9170_tx_prepare(ar, skb))) | 1499 | if (unlikely(ar9170_tx_prepare(ar, skb))) |
1918 | goto err_free; | 1500 | goto err_free; |
1919 | 1501 | ||
1502 | queue = skb_get_queue_mapping(skb); | ||
1920 | info = IEEE80211_SKB_CB(skb); | 1503 | info = IEEE80211_SKB_CB(skb); |
1921 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1504 | ar9170_tx_prepare_phy(ar, skb); |
1922 | bool run = ar9170_tx_ampdu_queue(ar, skb); | 1505 | skb_queue_tail(&ar->tx_pending[queue], skb); |
1923 | |||
1924 | if (run || !atomic_read(&ar->tx_ampdu_pending)) | ||
1925 | ar9170_tx_ampdu(ar); | ||
1926 | } else { | ||
1927 | unsigned int queue = skb_get_queue_mapping(skb); | ||
1928 | |||
1929 | ar9170_tx_prepare_phy(ar, skb); | ||
1930 | skb_queue_tail(&ar->tx_pending[queue], skb); | ||
1931 | } | ||
1932 | 1506 | ||
1933 | ar9170_tx(ar); | 1507 | ar9170_tx(ar); |
1934 | return NETDEV_TX_OK; | 1508 | return NETDEV_TX_OK; |
@@ -2329,57 +1903,6 @@ out: | |||
2329 | return err; | 1903 | return err; |
2330 | } | 1904 | } |
2331 | 1905 | ||
2332 | static int ar9170_sta_add(struct ieee80211_hw *hw, | ||
2333 | struct ieee80211_vif *vif, | ||
2334 | struct ieee80211_sta *sta) | ||
2335 | { | ||
2336 | struct ar9170 *ar = hw->priv; | ||
2337 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2338 | unsigned int i; | ||
2339 | |||
2340 | memset(sta_info, 0, sizeof(*sta_info)); | ||
2341 | |||
2342 | if (!sta->ht_cap.ht_supported) | ||
2343 | return 0; | ||
2344 | |||
2345 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) | ||
2346 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; | ||
2347 | |||
2348 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) | ||
2349 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; | ||
2350 | |||
2351 | for (i = 0; i < AR9170_NUM_TID; i++) { | ||
2352 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; | ||
2353 | sta_info->agg[i].active = false; | ||
2354 | sta_info->agg[i].ssn = 0; | ||
2355 | sta_info->agg[i].tid = i; | ||
2356 | INIT_LIST_HEAD(&sta_info->agg[i].list); | ||
2357 | skb_queue_head_init(&sta_info->agg[i].queue); | ||
2358 | } | ||
2359 | |||
2360 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | ||
2361 | |||
2362 | return 0; | ||
2363 | } | ||
2364 | |||
2365 | static int ar9170_sta_remove(struct ieee80211_hw *hw, | ||
2366 | struct ieee80211_vif *vif, | ||
2367 | struct ieee80211_sta *sta) | ||
2368 | { | ||
2369 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2370 | unsigned int i; | ||
2371 | |||
2372 | if (!sta->ht_cap.ht_supported) | ||
2373 | return 0; | ||
2374 | |||
2375 | for (i = 0; i < AR9170_NUM_TID; i++) { | ||
2376 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; | ||
2377 | skb_queue_purge(&sta_info->agg[i].queue); | ||
2378 | } | ||
2379 | |||
2380 | return 0; | ||
2381 | } | ||
2382 | |||
2383 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 1906 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
2384 | struct ieee80211_low_level_stats *stats) | 1907 | struct ieee80211_low_level_stats *stats) |
2385 | { | 1908 | { |
@@ -2422,55 +1945,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
2422 | enum ieee80211_ampdu_mlme_action action, | 1945 | enum ieee80211_ampdu_mlme_action action, |
2423 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 1946 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2424 | { | 1947 | { |
2425 | struct ar9170 *ar = hw->priv; | ||
2426 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2427 | struct ar9170_sta_tid *tid_info = &sta_info->agg[tid]; | ||
2428 | unsigned long flags; | ||
2429 | |||
2430 | if (!modparam_ht) | ||
2431 | return -EOPNOTSUPP; | ||
2432 | |||
2433 | switch (action) { | 1948 | switch (action) { |
2434 | case IEEE80211_AMPDU_TX_START: | ||
2435 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2436 | if (tid_info->state != AR9170_TID_STATE_SHUTDOWN || | ||
2437 | !list_empty(&tid_info->list)) { | ||
2438 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2439 | #ifdef AR9170_TXAGG_DEBUG | ||
2440 | printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] " | ||
2441 | "is in a very bad state!\n", | ||
2442 | wiphy_name(hw->wiphy), sta->addr, tid); | ||
2443 | #endif /* AR9170_TXAGG_DEBUG */ | ||
2444 | return -EBUSY; | ||
2445 | } | ||
2446 | |||
2447 | *ssn = tid_info->ssn; | ||
2448 | tid_info->state = AR9170_TID_STATE_PROGRESS; | ||
2449 | tid_info->active = false; | ||
2450 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2451 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
2452 | break; | ||
2453 | |||
2454 | case IEEE80211_AMPDU_TX_STOP: | ||
2455 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2456 | tid_info->state = AR9170_TID_STATE_SHUTDOWN; | ||
2457 | list_del_init(&tid_info->list); | ||
2458 | tid_info->active = false; | ||
2459 | skb_queue_purge(&tid_info->queue); | ||
2460 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2461 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
2462 | break; | ||
2463 | |||
2464 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2465 | #ifdef AR9170_TXAGG_DEBUG | ||
2466 | printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n", | ||
2467 | wiphy_name(hw->wiphy), sta->addr, tid); | ||
2468 | #endif /* AR9170_TXAGG_DEBUG */ | ||
2469 | spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); | ||
2470 | sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE; | ||
2471 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | ||
2472 | break; | ||
2473 | |||
2474 | case IEEE80211_AMPDU_RX_START: | 1949 | case IEEE80211_AMPDU_RX_START: |
2475 | case IEEE80211_AMPDU_RX_STOP: | 1950 | case IEEE80211_AMPDU_RX_STOP: |
2476 | /* Handled by firmware */ | 1951 | /* Handled by firmware */ |
@@ -2496,8 +1971,6 @@ static const struct ieee80211_ops ar9170_ops = { | |||
2496 | .bss_info_changed = ar9170_op_bss_info_changed, | 1971 | .bss_info_changed = ar9170_op_bss_info_changed, |
2497 | .get_tsf = ar9170_op_get_tsf, | 1972 | .get_tsf = ar9170_op_get_tsf, |
2498 | .set_key = ar9170_set_key, | 1973 | .set_key = ar9170_set_key, |
2499 | .sta_add = ar9170_sta_add, | ||
2500 | .sta_remove = ar9170_sta_remove, | ||
2501 | .get_stats = ar9170_get_stats, | 1974 | .get_stats = ar9170_get_stats, |
2502 | .ampdu_action = ar9170_ampdu_action, | 1975 | .ampdu_action = ar9170_ampdu_action, |
2503 | }; | 1976 | }; |
@@ -2530,8 +2003,6 @@ void *ar9170_alloc(size_t priv_size) | |||
2530 | mutex_init(&ar->mutex); | 2003 | mutex_init(&ar->mutex); |
2531 | spin_lock_init(&ar->cmdlock); | 2004 | spin_lock_init(&ar->cmdlock); |
2532 | spin_lock_init(&ar->tx_stats_lock); | 2005 | spin_lock_init(&ar->tx_stats_lock); |
2533 | spin_lock_init(&ar->tx_ampdu_list_lock); | ||
2534 | skb_queue_head_init(&ar->tx_status_ampdu); | ||
2535 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { | 2006 | for (i = 0; i < __AR9170_NUM_TXQ; i++) { |
2536 | skb_queue_head_init(&ar->tx_status[i]); | 2007 | skb_queue_head_init(&ar->tx_status[i]); |
2537 | skb_queue_head_init(&ar->tx_pending[i]); | 2008 | skb_queue_head_init(&ar->tx_pending[i]); |
@@ -2539,7 +2010,6 @@ void *ar9170_alloc(size_t priv_size) | |||
2539 | ar9170_rx_reset_rx_mpdu(ar); | 2010 | ar9170_rx_reset_rx_mpdu(ar); |
2540 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); | 2011 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); |
2541 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); | 2012 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); |
2542 | INIT_LIST_HEAD(&ar->tx_ampdu_list); | ||
2543 | 2013 | ||
2544 | /* all hw supports 2.4 GHz, so set channel to 1 by default */ | 2014 | /* all hw supports 2.4 GHz, so set channel to 1 by default */ |
2545 | ar->channel = &ar9170_2ghz_chantable[0]; | 2015 | ar->channel = &ar9170_2ghz_chantable[0]; |
@@ -2552,16 +2022,8 @@ void *ar9170_alloc(size_t priv_size) | |||
2552 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 2022 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
2553 | IEEE80211_HW_SIGNAL_DBM; | 2023 | IEEE80211_HW_SIGNAL_DBM; |
2554 | 2024 | ||
2555 | if (modparam_ht) { | ||
2556 | ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | ||
2557 | } else { | ||
2558 | ar9170_band_2GHz.ht_cap.ht_supported = false; | ||
2559 | ar9170_band_5GHz.ht_cap.ht_supported = false; | ||
2560 | } | ||
2561 | |||
2562 | ar->hw->queues = __AR9170_NUM_TXQ; | 2025 | ar->hw->queues = __AR9170_NUM_TXQ; |
2563 | ar->hw->extra_tx_headroom = 8; | 2026 | ar->hw->extra_tx_headroom = 8; |
2564 | ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); | ||
2565 | 2027 | ||
2566 | ar->hw->max_rates = 1; | 2028 | ar->hw->max_rates = 1; |
2567 | ar->hw->max_rate_tries = 3; | 2029 | ar->hw->max_rate_tries = 3; |