aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-06-10 04:21:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-14 15:39:28 -0400
commitcfcdbde35e2b621cf56bedc38a3a81e8c28addb9 (patch)
treecd0664681dc4629f7ce9a3319868eebb005060ff /net/mac80211/agg-tx.c
parent83a5cbf73a13d0c8be019b22afec4407e4285aed (diff)
mac80211: change TX aggregation locking
To prepare for allowing drivers to sleep in ampdu_action, change the locking in the TX aggregation code to use the mutex the RX part already uses. The spinlock is still necessary around some code to avoid races with TX, but now we can also synchronize_net() to avoid getting an inconsistent sequence number. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r--net/mac80211/agg-tx.c94
1 files changed, 53 insertions, 41 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 0026604cfe30..5dff73eebefb 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -6,7 +6,7 @@
6 * Copyright 2005-2006, Devicescape Software, Inc. 6 * Copyright 2005-2006, Devicescape Software, Inc.
7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9 * Copyright 2007-2009, Intel Corporation 9 * Copyright 2007-2010, Intel Corporation
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
@@ -140,18 +140,23 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
140 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; 140 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid];
141 int ret; 141 int ret;
142 142
143 lockdep_assert_held(&sta->lock); 143 lockdep_assert_held(&sta->ampdu_mlme.mtx);
144 144
145 if (WARN_ON(!tid_tx)) 145 if (!tid_tx)
146 return -ENOENT; 146 return -ENOENT;
147 147
148 spin_lock_bh(&sta->lock);
149
148 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { 150 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
149 /* not even started yet! */ 151 /* not even started yet! */
150 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); 152 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL);
153 spin_unlock_bh(&sta->lock);
151 call_rcu(&tid_tx->rcu_head, kfree_tid_tx); 154 call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
152 return 0; 155 return 0;
153 } 156 }
154 157
158 spin_unlock_bh(&sta->lock);
159
155#ifdef CONFIG_MAC80211_HT_DEBUG 160#ifdef CONFIG_MAC80211_HT_DEBUG
156 printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", 161 printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
157 sta->sta.addr, tid); 162 sta->sta.addr, tid);
@@ -269,6 +274,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
269 u16 start_seq_num; 274 u16 start_seq_num;
270 int ret; 275 int ret;
271 276
277 lockdep_assert_held(&sta->ampdu_mlme.mtx);
278
272 /* 279 /*
273 * While we're asking the driver about the aggregation, 280 * While we're asking the driver about the aggregation,
274 * stop the AC queue so that we don't have to worry 281 * stop the AC queue so that we don't have to worry
@@ -281,10 +288,11 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
281 clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); 288 clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
282 289
283 /* 290 /*
284 * This might be off by one due to a race that we can't 291 * make sure no packets are being processed to get
285 * really prevent here without synchronize_net() which 292 * valid starting sequence number
286 * can't be called now.
287 */ 293 */
294 synchronize_net();
295
288 start_seq_num = sta->tid_seq[tid] >> 4; 296 start_seq_num = sta->tid_seq[tid] >> 4;
289 297
290 ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, 298 ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
@@ -294,7 +302,10 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
294 printk(KERN_DEBUG "BA request denied - HW unavailable for" 302 printk(KERN_DEBUG "BA request denied - HW unavailable for"
295 " tid %d\n", tid); 303 " tid %d\n", tid);
296#endif 304#endif
305 spin_lock_bh(&sta->lock);
297 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); 306 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL);
307 spin_unlock_bh(&sta->lock);
308
298 ieee80211_wake_queue_agg(local, tid); 309 ieee80211_wake_queue_agg(local, tid);
299 call_rcu(&tid_tx->rcu_head, kfree_tid_tx); 310 call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
300 return; 311 return;
@@ -309,7 +320,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
309 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); 320 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
310#endif 321#endif
311 322
323 spin_lock_bh(&sta->lock);
312 sta->ampdu_mlme.addba_req_num[tid]++; 324 sta->ampdu_mlme.addba_req_num[tid]++;
325 spin_unlock_bh(&sta->lock);
313 326
314 /* send AddBA request */ 327 /* send AddBA request */
315 ieee80211_send_addba_request(sdata, sta->sta.addr, tid, 328 ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
@@ -445,16 +458,25 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
445 ieee80211_wake_queue_agg(local, tid); 458 ieee80211_wake_queue_agg(local, tid);
446} 459}
447 460
448/* caller must hold sta->lock */
449static void ieee80211_agg_tx_operational(struct ieee80211_local *local, 461static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
450 struct sta_info *sta, u16 tid) 462 struct sta_info *sta, u16 tid)
451{ 463{
452 lockdep_assert_held(&sta->lock); 464 lockdep_assert_held(&sta->ampdu_mlme.mtx);
453 465
454#ifdef CONFIG_MAC80211_HT_DEBUG 466#ifdef CONFIG_MAC80211_HT_DEBUG
455 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); 467 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid);
456#endif 468#endif
457 469
470 drv_ampdu_action(local, sta->sdata,
471 IEEE80211_AMPDU_TX_OPERATIONAL,
472 &sta->sta, tid, NULL);
473
474 /*
475 * synchronize with TX path, while splicing the TX path
476 * should block so it won't put more packets onto pending.
477 */
478 spin_lock_bh(&sta->lock);
479
458 ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); 480 ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid);
459 /* 481 /*
460 * Now mark as operational. This will be visible 482 * Now mark as operational. This will be visible
@@ -464,9 +486,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
464 set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); 486 set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state);
465 ieee80211_agg_splice_finish(local, tid); 487 ieee80211_agg_splice_finish(local, tid);
466 488
467 drv_ampdu_action(local, sta->sdata, 489 spin_unlock_bh(&sta->lock);
468 IEEE80211_AMPDU_TX_OPERATIONAL,
469 &sta->sta, tid, NULL);
470} 490}
471 491
472void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) 492void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
@@ -486,37 +506,35 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
486 return; 506 return;
487 } 507 }
488 508
489 rcu_read_lock(); 509 mutex_lock(&local->sta_mtx);
490 sta = sta_info_get(sdata, ra); 510 sta = sta_info_get(sdata, ra);
491 if (!sta) { 511 if (!sta) {
492 rcu_read_unlock(); 512 mutex_unlock(&local->sta_mtx);
493#ifdef CONFIG_MAC80211_HT_DEBUG 513#ifdef CONFIG_MAC80211_HT_DEBUG
494 printk(KERN_DEBUG "Could not find station: %pM\n", ra); 514 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
495#endif 515#endif
496 return; 516 return;
497 } 517 }
498 518
499 spin_lock_bh(&sta->lock); 519 mutex_lock(&sta->ampdu_mlme.mtx);
500 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 520 tid_tx = sta->ampdu_mlme.tid_tx[tid];
501 521
502 if (WARN_ON(!tid_tx)) { 522 if (WARN_ON(!tid_tx)) {
503#ifdef CONFIG_MAC80211_HT_DEBUG 523#ifdef CONFIG_MAC80211_HT_DEBUG
504 printk(KERN_DEBUG "addBA was not requested!\n"); 524 printk(KERN_DEBUG "addBA was not requested!\n");
505#endif 525#endif
506 spin_unlock_bh(&sta->lock); 526 goto unlock;
507 rcu_read_unlock();
508 return;
509 } 527 }
510 528
511 if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))) 529 if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
512 goto out; 530 goto unlock;
513 531
514 if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) 532 if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
515 ieee80211_agg_tx_operational(local, sta, tid); 533 ieee80211_agg_tx_operational(local, sta, tid);
516 534
517 out: 535 unlock:
518 spin_unlock_bh(&sta->lock); 536 mutex_unlock(&sta->ampdu_mlme.mtx);
519 rcu_read_unlock(); 537 mutex_unlock(&local->sta_mtx);
520} 538}
521 539
522void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, 540void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
@@ -548,21 +566,14 @@ EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
548int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 566int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
549 enum ieee80211_back_parties initiator) 567 enum ieee80211_back_parties initiator)
550{ 568{
551 struct tid_ampdu_tx *tid_tx;
552 int ret; 569 int ret;
553 570
554 spin_lock_bh(&sta->lock); 571 mutex_lock(&sta->ampdu_mlme.mtx);
555 tid_tx = sta->ampdu_mlme.tid_tx[tid];
556
557 if (!tid_tx) {
558 ret = -ENOENT;
559 goto unlock;
560 }
561 572
562 ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); 573 ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator);
563 574
564 unlock: 575 mutex_unlock(&sta->ampdu_mlme.mtx);
565 spin_unlock_bh(&sta->lock); 576
566 return ret; 577 return ret;
567} 578}
568 579
@@ -627,16 +638,17 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
627 ra, tid); 638 ra, tid);
628#endif /* CONFIG_MAC80211_HT_DEBUG */ 639#endif /* CONFIG_MAC80211_HT_DEBUG */
629 640
630 rcu_read_lock(); 641 mutex_lock(&local->sta_mtx);
642
631 sta = sta_info_get(sdata, ra); 643 sta = sta_info_get(sdata, ra);
632 if (!sta) { 644 if (!sta) {
633#ifdef CONFIG_MAC80211_HT_DEBUG 645#ifdef CONFIG_MAC80211_HT_DEBUG
634 printk(KERN_DEBUG "Could not find station: %pM\n", ra); 646 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
635#endif 647#endif
636 rcu_read_unlock(); 648 goto unlock;
637 return;
638 } 649 }
639 650
651 mutex_lock(&sta->ampdu_mlme.mtx);
640 spin_lock_bh(&sta->lock); 652 spin_lock_bh(&sta->lock);
641 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 653 tid_tx = sta->ampdu_mlme.tid_tx[tid];
642 654
@@ -644,9 +656,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
644#ifdef CONFIG_MAC80211_HT_DEBUG 656#ifdef CONFIG_MAC80211_HT_DEBUG
645 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); 657 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
646#endif 658#endif
647 spin_unlock_bh(&sta->lock); 659 goto unlock_sta;
648 rcu_read_unlock();
649 return;
650 } 660 }
651 661
652 if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR) 662 if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR)
@@ -672,8 +682,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
672 682
673 call_rcu(&tid_tx->rcu_head, kfree_tid_tx); 683 call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
674 684
685 unlock_sta:
675 spin_unlock_bh(&sta->lock); 686 spin_unlock_bh(&sta->lock);
676 rcu_read_unlock(); 687 mutex_unlock(&sta->ampdu_mlme.mtx);
688 unlock:
689 mutex_unlock(&local->sta_mtx);
677} 690}
678 691
679void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, 692void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
@@ -714,10 +727,9 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
714 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); 727 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
715 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; 728 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
716 729
717 spin_lock_bh(&sta->lock); 730 mutex_lock(&sta->ampdu_mlme.mtx);
718 731
719 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 732 tid_tx = sta->ampdu_mlme.tid_tx[tid];
720
721 if (!tid_tx) 733 if (!tid_tx)
722 goto out; 734 goto out;
723 735
@@ -751,5 +763,5 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
751 } 763 }
752 764
753 out: 765 out:
754 spin_unlock_bh(&sta->lock); 766 mutex_unlock(&sta->ampdu_mlme.mtx);
755} 767}