aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/agg-rx.c12
-rw-r--r--net/mac80211/driver-ops.h2
-rw-r--r--net/mac80211/ht.c6
-rw-r--r--net/mac80211/iface.c8
-rw-r--r--net/mac80211/sta_info.c1
-rw-r--r--net/mac80211/sta_info.h3
6 files changed, 21 insertions, 11 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index aa858a03951c..a843df26f384 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.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
@@ -38,7 +38,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
38 struct ieee80211_local *local = sta->local; 38 struct ieee80211_local *local = sta->local;
39 struct tid_ampdu_rx *tid_rx; 39 struct tid_ampdu_rx *tid_rx;
40 40
41 lockdep_assert_held(&sta->lock); 41 lockdep_assert_held(&sta->ampdu_mlme.mtx);
42 42
43 tid_rx = sta->ampdu_mlme.tid_rx[tid]; 43 tid_rx = sta->ampdu_mlme.tid_rx[tid];
44 44
@@ -70,9 +70,9 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
70void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 70void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
71 u16 initiator, u16 reason) 71 u16 initiator, u16 reason)
72{ 72{
73 spin_lock_bh(&sta->lock); 73 mutex_lock(&sta->ampdu_mlme.mtx);
74 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); 74 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason);
75 spin_unlock_bh(&sta->lock); 75 mutex_unlock(&sta->ampdu_mlme.mtx);
76} 76}
77 77
78/* 78/*
@@ -205,7 +205,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
205 205
206 206
207 /* examine state machine */ 207 /* examine state machine */
208 spin_lock_bh(&sta->lock); 208 mutex_lock(&sta->ampdu_mlme.mtx);
209 209
210 if (sta->ampdu_mlme.tid_rx[tid]) { 210 if (sta->ampdu_mlme.tid_rx[tid]) {
211#ifdef CONFIG_MAC80211_HT_DEBUG 211#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -279,7 +279,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
279 mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); 279 mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
280 280
281end: 281end:
282 spin_unlock_bh(&sta->lock); 282 mutex_unlock(&sta->ampdu_mlme.mtx);
283 283
284end_no_lock: 284end_no_lock:
285 ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, 285 ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 7d18a3245e3d..e5e7ef175ca2 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -349,9 +349,11 @@ 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 local_bh_disable();
352 if (local->ops->ampdu_action) 353 if (local->ops->ampdu_action)
353 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, 354 ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
354 sta, tid, ssn); 355 sta, tid, ssn);
356 local_bh_enable();
355 trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret); 357 trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret);
356 return ret; 358 return ret;
357} 359}
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 730f8089678e..e29be64083c3 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -130,13 +130,17 @@ void ieee80211_ba_session_work(struct work_struct *work)
130 if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) 130 if (test_sta_flags(sta, WLAN_STA_BLOCK_BA))
131 return; 131 return;
132 132
133 spin_lock_bh(&sta->lock); 133 mutex_lock(&sta->ampdu_mlme.mtx);
134 for (tid = 0; tid < STA_TID_NUM; tid++) { 134 for (tid = 0; tid < STA_TID_NUM; tid++) {
135 if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) 135 if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
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);
139 141
142 spin_lock_bh(&sta->lock);
143 for (tid = 0; tid < STA_TID_NUM; tid++) {
140 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 144 tid_tx = sta->ampdu_mlme.tid_tx[tid];
141 if (!tid_tx) 145 if (!tid_tx)
142 continue; 146 continue;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 9f00d3f174e4..490be2f3af27 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -740,7 +740,7 @@ static void ieee80211_iface_work(struct work_struct *work)
740 mgmt->u.action.category == WLAN_CATEGORY_BACK) { 740 mgmt->u.action.category == WLAN_CATEGORY_BACK) {
741 int len = skb->len; 741 int len = skb->len;
742 742
743 rcu_read_lock(); 743 mutex_lock(&local->sta_mtx);
744 sta = sta_info_get(sdata, mgmt->sa); 744 sta = sta_info_get(sdata, mgmt->sa);
745 if (sta) { 745 if (sta) {
746 switch (mgmt->u.action.u.addba_req.action_code) { 746 switch (mgmt->u.action.u.addba_req.action_code) {
@@ -761,7 +761,7 @@ static void ieee80211_iface_work(struct work_struct *work)
761 break; 761 break;
762 } 762 }
763 } 763 }
764 rcu_read_unlock(); 764 mutex_unlock(&local->sta_mtx);
765 } else if (ieee80211_is_data_qos(mgmt->frame_control)) { 765 } else if (ieee80211_is_data_qos(mgmt->frame_control)) {
766 struct ieee80211_hdr *hdr = (void *)mgmt; 766 struct ieee80211_hdr *hdr = (void *)mgmt;
767 /* 767 /*
@@ -781,7 +781,7 @@ static void ieee80211_iface_work(struct work_struct *work)
781 * a block-ack session was active. That cannot be 781 * a block-ack session was active. That cannot be
782 * right, so terminate the session. 782 * right, so terminate the session.
783 */ 783 */
784 rcu_read_lock(); 784 mutex_lock(&local->sta_mtx);
785 sta = sta_info_get(sdata, mgmt->sa); 785 sta = sta_info_get(sdata, mgmt->sa);
786 if (sta) { 786 if (sta) {
787 u16 tid = *ieee80211_get_qos_ctl(hdr) & 787 u16 tid = *ieee80211_get_qos_ctl(hdr) &
@@ -791,7 +791,7 @@ static void ieee80211_iface_work(struct work_struct *work)
791 sta, tid, WLAN_BACK_RECIPIENT, 791 sta, tid, WLAN_BACK_RECIPIENT,
792 WLAN_REASON_QSTA_REQUIRE_SETUP); 792 WLAN_REASON_QSTA_REQUIRE_SETUP);
793 } 793 }
794 rcu_read_unlock(); 794 mutex_unlock(&local->sta_mtx);
795 } else switch (sdata->vif.type) { 795 } else switch (sdata->vif.type) {
796 case NL80211_IFTYPE_STATION: 796 case NL80211_IFTYPE_STATION:
797 ieee80211_sta_rx_queued_mgmt(sdata, skb); 797 ieee80211_sta_rx_queued_mgmt(sdata, skb);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index bd726c6204df..f54d8ba7d788 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -236,6 +236,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
236 spin_lock_init(&sta->flaglock); 236 spin_lock_init(&sta->flaglock);
237 INIT_WORK(&sta->drv_unblock_wk, sta_unblock); 237 INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
238 INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); 238 INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
239 mutex_init(&sta->ampdu_mlme.mtx);
239 240
240 memcpy(sta->sta.addr, addr, ETH_ALEN); 241 memcpy(sta->sta.addr, addr, ETH_ALEN);
241 sta->local = local; 242 sta->local = local;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 500bafe0a0bb..10d0fcb417ae 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -142,8 +142,11 @@ struct tid_ampdu_rx {
142 * @work: work struct for starting/stopping aggregation 142 * @work: work struct for starting/stopping aggregation
143 * @tid_rx_timer_expired: bitmap indicating on which TIDs the 143 * @tid_rx_timer_expired: bitmap indicating on which TIDs the
144 * RX timer expired until the work for it runs 144 * RX timer expired until the work for it runs
145 * @mtx: mutex to protect all TX data (except non-NULL assignments
146 * to tid_tx[idx], which are protected by the sta spinlock)
145 */ 147 */
146struct sta_ampdu_mlme { 148struct sta_ampdu_mlme {
149 struct mutex mtx;
147 /* rx */ 150 /* rx */
148 struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; 151 struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
149 unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; 152 unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];