aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-06-10 04:21:46 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-14 15:39:28 -0400
commita93e364430de7f7a5f4eedd604ad1ab3d825dde5 (patch)
tree441f0f69dc5b08d79c5f5f4e7adae88ad18dbd86 /net/mac80211
parentf955ebb44798e0058c987a0817810d2542e87349 (diff)
mac80211: change RX aggregation locking
To prepare for allowing drivers to sleep in ampdu_action, change the locking in the RX aggregation code to use a mutex, so that it would already allow drivers to sleep. But explicitly disable BHs around the callback for now since the TX part cannot yet sleep, and drivers' locking might require it. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-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)];