diff options
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r-- | net/mac80211/agg-tx.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 76be61744198..5b7053c58732 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -286,25 +286,25 @@ static inline int ieee80211_ac_from_tid(int tid) | |||
286 | * a global "agg_queue_stop" refcount. | 286 | * a global "agg_queue_stop" refcount. |
287 | */ | 287 | */ |
288 | static void __acquires(agg_queue) | 288 | static void __acquires(agg_queue) |
289 | ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid) | 289 | ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) |
290 | { | 290 | { |
291 | int queue = ieee80211_ac_from_tid(tid); | 291 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; |
292 | 292 | ||
293 | if (atomic_inc_return(&local->agg_queue_stop[queue]) == 1) | 293 | if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) |
294 | ieee80211_stop_queue_by_reason( | 294 | ieee80211_stop_queue_by_reason( |
295 | &local->hw, queue, | 295 | &sdata->local->hw, queue, |
296 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | 296 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); |
297 | __acquire(agg_queue); | 297 | __acquire(agg_queue); |
298 | } | 298 | } |
299 | 299 | ||
300 | static void __releases(agg_queue) | 300 | static void __releases(agg_queue) |
301 | ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | 301 | ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) |
302 | { | 302 | { |
303 | int queue = ieee80211_ac_from_tid(tid); | 303 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; |
304 | 304 | ||
305 | if (atomic_dec_return(&local->agg_queue_stop[queue]) == 0) | 305 | if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) |
306 | ieee80211_wake_queue_by_reason( | 306 | ieee80211_wake_queue_by_reason( |
307 | &local->hw, queue, | 307 | &sdata->local->hw, queue, |
308 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | 308 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); |
309 | __release(agg_queue); | 309 | __release(agg_queue); |
310 | } | 310 | } |
@@ -314,13 +314,14 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | |||
314 | * requires a call to ieee80211_agg_splice_finish later | 314 | * requires a call to ieee80211_agg_splice_finish later |
315 | */ | 315 | */ |
316 | static void __acquires(agg_queue) | 316 | static void __acquires(agg_queue) |
317 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | 317 | ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata, |
318 | struct tid_ampdu_tx *tid_tx, u16 tid) | 318 | struct tid_ampdu_tx *tid_tx, u16 tid) |
319 | { | 319 | { |
320 | int queue = ieee80211_ac_from_tid(tid); | 320 | struct ieee80211_local *local = sdata->local; |
321 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
321 | unsigned long flags; | 322 | unsigned long flags; |
322 | 323 | ||
323 | ieee80211_stop_queue_agg(local, tid); | 324 | ieee80211_stop_queue_agg(sdata, tid); |
324 | 325 | ||
325 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | 326 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" |
326 | " from the pending queue\n", tid)) | 327 | " from the pending queue\n", tid)) |
@@ -336,9 +337,9 @@ ieee80211_agg_splice_packets(struct ieee80211_local *local, | |||
336 | } | 337 | } |
337 | 338 | ||
338 | static void __releases(agg_queue) | 339 | static void __releases(agg_queue) |
339 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | 340 | ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid) |
340 | { | 341 | { |
341 | ieee80211_wake_queue_agg(local, tid); | 342 | ieee80211_wake_queue_agg(sdata, tid); |
342 | } | 343 | } |
343 | 344 | ||
344 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 345 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
@@ -376,9 +377,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
376 | " tid %d\n", tid); | 377 | " tid %d\n", tid); |
377 | #endif | 378 | #endif |
378 | spin_lock_bh(&sta->lock); | 379 | spin_lock_bh(&sta->lock); |
379 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 380 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); |
380 | ieee80211_assign_tid_tx(sta, tid, NULL); | 381 | ieee80211_assign_tid_tx(sta, tid, NULL); |
381 | ieee80211_agg_splice_finish(local, tid); | 382 | ieee80211_agg_splice_finish(sdata, tid); |
382 | spin_unlock_bh(&sta->lock); | 383 | spin_unlock_bh(&sta->lock); |
383 | 384 | ||
384 | kfree_rcu(tid_tx, rcu_head); | 385 | kfree_rcu(tid_tx, rcu_head); |
@@ -417,6 +418,18 @@ static void sta_tx_agg_session_timer_expired(unsigned long data) | |||
417 | u8 *timer_to_id = ptid - *ptid; | 418 | u8 *timer_to_id = ptid - *ptid; |
418 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | 419 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, |
419 | timer_to_tid[0]); | 420 | timer_to_tid[0]); |
421 | struct tid_ampdu_tx *tid_tx; | ||
422 | unsigned long timeout; | ||
423 | |||
424 | tid_tx = rcu_dereference_protected_tid_tx(sta, *ptid); | ||
425 | if (!tid_tx) | ||
426 | return; | ||
427 | |||
428 | timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout); | ||
429 | if (time_is_after_jiffies(timeout)) { | ||
430 | mod_timer(&tid_tx->session_timer, timeout); | ||
431 | return; | ||
432 | } | ||
420 | 433 | ||
421 | #ifdef CONFIG_MAC80211_HT_DEBUG | 434 | #ifdef CONFIG_MAC80211_HT_DEBUG |
422 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); | 435 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); |
@@ -542,7 +555,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
542 | /* tx timer */ | 555 | /* tx timer */ |
543 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; | 556 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; |
544 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 557 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
545 | init_timer(&tid_tx->session_timer); | 558 | init_timer_deferrable(&tid_tx->session_timer); |
546 | 559 | ||
547 | /* assign a dialog token */ | 560 | /* assign a dialog token */ |
548 | sta->ampdu_mlme.dialog_token_allocator++; | 561 | sta->ampdu_mlme.dialog_token_allocator++; |
@@ -586,14 +599,14 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
586 | */ | 599 | */ |
587 | spin_lock_bh(&sta->lock); | 600 | spin_lock_bh(&sta->lock); |
588 | 601 | ||
589 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 602 | ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); |
590 | /* | 603 | /* |
591 | * Now mark as operational. This will be visible | 604 | * Now mark as operational. This will be visible |
592 | * in the TX path, and lets it go lock-free in | 605 | * in the TX path, and lets it go lock-free in |
593 | * the common case. | 606 | * the common case. |
594 | */ | 607 | */ |
595 | set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | 608 | set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
596 | ieee80211_agg_splice_finish(local, tid); | 609 | ieee80211_agg_splice_finish(sta->sdata, tid); |
597 | 610 | ||
598 | spin_unlock_bh(&sta->lock); | 611 | spin_unlock_bh(&sta->lock); |
599 | } | 612 | } |
@@ -778,12 +791,12 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
778 | * more. | 791 | * more. |
779 | */ | 792 | */ |
780 | 793 | ||
781 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 794 | ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); |
782 | 795 | ||
783 | /* future packets must not find the tid_tx struct any more */ | 796 | /* future packets must not find the tid_tx struct any more */ |
784 | ieee80211_assign_tid_tx(sta, tid, NULL); | 797 | ieee80211_assign_tid_tx(sta, tid, NULL); |
785 | 798 | ||
786 | ieee80211_agg_splice_finish(local, tid); | 799 | ieee80211_agg_splice_finish(sta->sdata, tid); |
787 | 800 | ||
788 | kfree_rcu(tid_tx, rcu_head); | 801 | kfree_rcu(tid_tx, rcu_head); |
789 | 802 | ||
@@ -884,9 +897,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
884 | 897 | ||
885 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 898 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
886 | 899 | ||
887 | if (tid_tx->timeout) | 900 | if (tid_tx->timeout) { |
888 | mod_timer(&tid_tx->session_timer, | 901 | mod_timer(&tid_tx->session_timer, |
889 | TU_TO_EXP_TIME(tid_tx->timeout)); | 902 | TU_TO_EXP_TIME(tid_tx->timeout)); |
903 | tid_tx->last_tx = jiffies; | ||
904 | } | ||
890 | 905 | ||
891 | } else { | 906 | } else { |
892 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, | 907 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, |