aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/agg-tx.c94
-rw-r--r--net/mac80211/driver-ops.h3
-rw-r--r--net/mac80211/ht.c8
3 files changed, 58 insertions, 47 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}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index e5e7ef175ca2..7e86c6f89be9 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -349,6 +349,9 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
349 u16 *ssn) 349 u16 *ssn)
350{ 350{
351 int ret = -EOPNOTSUPP; 351 int ret = -EOPNOTSUPP;
352
353 might_sleep();
354
352 local_bh_disable(); 355 local_bh_disable();
353 if (local->ops->ampdu_action) 356 if (local->ops->ampdu_action)
354 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, 357 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index e29be64083c3..be928ef7ef51 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.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-2008, 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
@@ -136,11 +136,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
136 ___ieee80211_stop_rx_ba_session( 136 ___ieee80211_stop_rx_ba_session(
137 sta, tid, WLAN_BACK_RECIPIENT, 137 sta, tid, WLAN_BACK_RECIPIENT,
138 WLAN_REASON_QSTA_TIMEOUT); 138 WLAN_REASON_QSTA_TIMEOUT);
139 }
140 mutex_unlock(&sta->ampdu_mlme.mtx);
141 139
142 spin_lock_bh(&sta->lock);
143 for (tid = 0; tid < STA_TID_NUM; tid++) {
144 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 140 tid_tx = sta->ampdu_mlme.tid_tx[tid];
145 if (!tid_tx) 141 if (!tid_tx)
146 continue; 142 continue;
@@ -152,7 +148,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
152 ___ieee80211_stop_tx_ba_session(sta, tid, 148 ___ieee80211_stop_tx_ba_session(sta, tid,
153 WLAN_BACK_INITIATOR); 149 WLAN_BACK_INITIATOR);
154 } 150 }
155 spin_unlock_bh(&sta->lock); 151 mutex_unlock(&sta->ampdu_mlme.mtx);
156} 152}
157 153
158void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, 154void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,