aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r--net/mac80211/agg-tx.c57
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 */
288static void __acquires(agg_queue) 288static void __acquires(agg_queue)
289ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid) 289ieee80211_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
300static void __releases(agg_queue) 300static void __releases(agg_queue)
301ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) 301ieee80211_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 */
316static void __acquires(agg_queue) 316static void __acquires(agg_queue)
317ieee80211_agg_splice_packets(struct ieee80211_local *local, 317ieee80211_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
338static void __releases(agg_queue) 339static void __releases(agg_queue)
339ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) 340ieee80211_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
344void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) 345void 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,