diff options
author | John W. Linville <linville@tuxdriver.com> | 2011-12-14 14:35:41 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-12-14 14:35:41 -0500 |
commit | 5d22df200beccb1dea26fe4d8684ed93ae2f0aeb (patch) | |
tree | 05220b08a0c9d170ad88e3b9ed0390750d22d8ea /net/mac80211/agg-tx.c | |
parent | 8b1fdb53075bd794a209a611bc94aedaf7ecf9e2 (diff) | |
parent | 78feb35b8161acd95c33a703ed6ab6f554d29387 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts:
drivers/net/wireless/iwlwifi/iwl-agn.c
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r-- | net/mac80211/agg-tx.c | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5c7f0c3c74cb..88754c067f1e 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -309,6 +309,38 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | |||
309 | __release(agg_queue); | 309 | __release(agg_queue); |
310 | } | 310 | } |
311 | 311 | ||
312 | /* | ||
313 | * splice packets from the STA's pending to the local pending, | ||
314 | * requires a call to ieee80211_agg_splice_finish later | ||
315 | */ | ||
316 | static void __acquires(agg_queue) | ||
317 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | ||
318 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
319 | { | ||
320 | int queue = ieee80211_ac_from_tid(tid); | ||
321 | unsigned long flags; | ||
322 | |||
323 | ieee80211_stop_queue_agg(local, tid); | ||
324 | |||
325 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | ||
326 | " from the pending queue\n", tid)) | ||
327 | return; | ||
328 | |||
329 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
330 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
331 | /* copy over remaining packets */ | ||
332 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
333 | &local->pending[queue]); | ||
334 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | static void __releases(agg_queue) | ||
339 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | ||
340 | { | ||
341 | ieee80211_wake_queue_agg(local, tid); | ||
342 | } | ||
343 | |||
312 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 344 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
313 | { | 345 | { |
314 | struct tid_ampdu_tx *tid_tx; | 346 | struct tid_ampdu_tx *tid_tx; |
@@ -320,19 +352,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
320 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 352 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
321 | 353 | ||
322 | /* | 354 | /* |
323 | * While we're asking the driver about the aggregation, | 355 | * Start queuing up packets for this aggregation session. |
324 | * stop the AC queue so that we don't have to worry | 356 | * We're going to release them once the driver is OK with |
325 | * about frames that came in while we were doing that, | 357 | * that. |
326 | * which would require us to put them to the AC pending | ||
327 | * afterwards which just makes the code more complex. | ||
328 | */ | 358 | */ |
329 | ieee80211_stop_queue_agg(local, tid); | ||
330 | |||
331 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | 359 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
332 | 360 | ||
333 | /* | 361 | /* |
334 | * make sure no packets are being processed to get | 362 | * Make sure no packets are being processed. This ensures that |
335 | * valid starting sequence number | 363 | * we have a valid starting sequence number and that in-flight |
364 | * packets have been flushed out and no packets for this TID | ||
365 | * will go into the driver during the ampdu_action call. | ||
336 | */ | 366 | */ |
337 | synchronize_net(); | 367 | synchronize_net(); |
338 | 368 | ||
@@ -346,17 +376,15 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
346 | " tid %d\n", tid); | 376 | " tid %d\n", tid); |
347 | #endif | 377 | #endif |
348 | spin_lock_bh(&sta->lock); | 378 | spin_lock_bh(&sta->lock); |
379 | ieee80211_agg_splice_packets(local, tid_tx, tid); | ||
349 | ieee80211_assign_tid_tx(sta, tid, NULL); | 380 | ieee80211_assign_tid_tx(sta, tid, NULL); |
381 | ieee80211_agg_splice_finish(local, tid); | ||
350 | spin_unlock_bh(&sta->lock); | 382 | spin_unlock_bh(&sta->lock); |
351 | 383 | ||
352 | ieee80211_wake_queue_agg(local, tid); | ||
353 | kfree_rcu(tid_tx, rcu_head); | 384 | kfree_rcu(tid_tx, rcu_head); |
354 | return; | 385 | return; |
355 | } | 386 | } |
356 | 387 | ||
357 | /* we can take packets again now */ | ||
358 | ieee80211_wake_queue_agg(local, tid); | ||
359 | |||
360 | /* activate the timer for the recipient's addBA response */ | 388 | /* activate the timer for the recipient's addBA response */ |
361 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); | 389 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); |
362 | #ifdef CONFIG_MAC80211_HT_DEBUG | 390 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -516,38 +544,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
516 | } | 544 | } |
517 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | 545 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); |
518 | 546 | ||
519 | /* | ||
520 | * splice packets from the STA's pending to the local pending, | ||
521 | * requires a call to ieee80211_agg_splice_finish later | ||
522 | */ | ||
523 | static void __acquires(agg_queue) | ||
524 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | ||
525 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
526 | { | ||
527 | int queue = ieee80211_ac_from_tid(tid); | ||
528 | unsigned long flags; | ||
529 | |||
530 | ieee80211_stop_queue_agg(local, tid); | ||
531 | |||
532 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | ||
533 | " from the pending queue\n", tid)) | ||
534 | return; | ||
535 | |||
536 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
537 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
538 | /* copy over remaining packets */ | ||
539 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
540 | &local->pending[queue]); | ||
541 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | static void __releases(agg_queue) | ||
546 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | ||
547 | { | ||
548 | ieee80211_wake_queue_agg(local, tid); | ||
549 | } | ||
550 | |||
551 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | 547 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, |
552 | struct sta_info *sta, u16 tid) | 548 | struct sta_info *sta, u16 tid) |
553 | { | 549 | { |