aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-06-10 04:21:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-14 15:39:28 -0400
commit7c3b1dd8f483bf4bcb9776cd9cd3b37dd327d7ea (patch)
treeb5e42cc6f18b80c1036d0b9e5590d171fa84d074 /net
parent67c282c00c9c06733aae229662d209957f6d23a7 (diff)
mac80211: defer RX agg session teardown to work
Since we want the code to be able to sleep in the future, it must not be called from the timer directly. To prepare, move it out into the aggregation work. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/agg-rx.c24
-rw-r--r--net/mac80211/ht.c5
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/sta_info.h3
4 files changed, 20 insertions, 14 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index bbf36d980232..1c4320b01e3c 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -32,21 +32,18 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
32 kfree(tid_rx); 32 kfree(tid_rx);
33} 33}
34 34
35static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 35void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
36 u16 initiator, u16 reason, 36 u16 initiator, u16 reason)
37 bool from_timer)
38{ 37{
39 struct ieee80211_local *local = sta->local; 38 struct ieee80211_local *local = sta->local;
40 struct tid_ampdu_rx *tid_rx; 39 struct tid_ampdu_rx *tid_rx;
41 40
42 spin_lock_bh(&sta->lock); 41 lockdep_assert_held(&sta->lock);
43 42
44 tid_rx = sta->ampdu_mlme.tid_rx[tid]; 43 tid_rx = sta->ampdu_mlme.tid_rx[tid];
45 44
46 if (!tid_rx) { 45 if (!tid_rx)
47 spin_unlock_bh(&sta->lock);
48 return; 46 return;
49 }
50 47
51 rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL); 48 rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], NULL);
52 49
@@ -65,10 +62,7 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
65 ieee80211_send_delba(sta->sdata, sta->sta.addr, 62 ieee80211_send_delba(sta->sdata, sta->sta.addr,
66 tid, 0, reason); 63 tid, 0, reason);
67 64
68 spin_unlock_bh(&sta->lock); 65 del_timer_sync(&tid_rx->session_timer);
69
70 if (!from_timer)
71 del_timer_sync(&tid_rx->session_timer);
72 66
73 call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); 67 call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
74} 68}
@@ -76,7 +70,9 @@ static void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
76void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 70void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
77 u16 initiator, u16 reason) 71 u16 initiator, u16 reason)
78{ 72{
79 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, false); 73 spin_lock_bh(&sta->lock);
74 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason);
75 spin_unlock_bh(&sta->lock);
80} 76}
81 77
82/* 78/*
@@ -97,8 +93,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)
97#ifdef CONFIG_MAC80211_HT_DEBUG 93#ifdef CONFIG_MAC80211_HT_DEBUG
98 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); 94 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
99#endif 95#endif
100 ___ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, 96 set_bit(*ptid, sta->ampdu_mlme.tid_rx_timer_expired);
101 WLAN_REASON_QSTA_TIMEOUT, true); 97 ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
102} 98}
103 99
104static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, 100static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 531a19d358df..730f8089678e 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -132,6 +132,11 @@ void ieee80211_ba_session_work(struct work_struct *work)
132 132
133 spin_lock_bh(&sta->lock); 133 spin_lock_bh(&sta->lock);
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))
136 ___ieee80211_stop_rx_ba_session(
137 sta, tid, WLAN_BACK_RECIPIENT,
138 WLAN_REASON_QSTA_TIMEOUT);
139
135 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 140 tid_tx = sta->ampdu_mlme.tid_tx[tid];
136 if (!tid_tx) 141 if (!tid_tx)
137 continue; 142 continue;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 628a53db9f7e..9d753a02a2e4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1096,6 +1096,8 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
1096 enum ieee80211_smps_mode smps, const u8 *da, 1096 enum ieee80211_smps_mode smps, const u8 *da,
1097 const u8 *bssid); 1097 const u8 *bssid);
1098 1098
1099void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
1100 u16 initiator, u16 reason);
1099void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 1101void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
1100 u16 initiator, u16 reason); 1102 u16 initiator, u16 reason);
1101void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); 1103void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 040cbb0ac3af..500bafe0a0bb 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -140,10 +140,13 @@ struct tid_ampdu_rx {
140 * @addba_req_num: number of times addBA request has been sent. 140 * @addba_req_num: number of times addBA request has been sent.
141 * @dialog_token_allocator: dialog token enumerator for each new session; 141 * @dialog_token_allocator: dialog token enumerator for each new session;
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
144 * RX timer expired until the work for it runs
143 */ 145 */
144struct sta_ampdu_mlme { 146struct sta_ampdu_mlme {
145 /* rx */ 147 /* rx */
146 struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; 148 struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
149 unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)];
147 /* tx */ 150 /* tx */
148 struct work_struct work; 151 struct work_struct work;
149 struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; 152 struct tid_ampdu_tx *tid_tx[STA_TID_NUM];