aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r--net/mac80211/agg-tx.c582
1 files changed, 337 insertions, 245 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 5e3a7eccef5a..8f23401832b7 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
@@ -14,34 +14,46 @@
14 */ 14 */
15 15
16#include <linux/ieee80211.h> 16#include <linux/ieee80211.h>
17#include <linux/slab.h>
17#include <net/mac80211.h> 18#include <net/mac80211.h>
18#include "ieee80211_i.h" 19#include "ieee80211_i.h"
19#include "driver-ops.h" 20#include "driver-ops.h"
20#include "wme.h" 21#include "wme.h"
21 22
22/** 23/**
23 * DOC: TX aggregation 24 * DOC: TX A-MPDU aggregation
24 * 25 *
25 * Aggregation on the TX side requires setting the hardware flag 26 * Aggregation on the TX side requires setting the hardware flag
26 * %IEEE80211_HW_AMPDU_AGGREGATION as well as, if present, the @ampdu_queues 27 * %IEEE80211_HW_AMPDU_AGGREGATION. The driver will then be handed
27 * hardware parameter to the number of hardware AMPDU queues. If there are no 28 * packets with a flag indicating A-MPDU aggregation. The driver
28 * hardware queues then the driver will (currently) have to do all frame 29 * or device is responsible for actually aggregating the frames,
29 * buffering. 30 * as well as deciding how many and which to aggregate.
30 * 31 *
31 * When TX aggregation is started by some subsystem (usually the rate control 32 * When TX aggregation is started by some subsystem (usually the rate
32 * algorithm would be appropriate) by calling the 33 * control algorithm would be appropriate) by calling the
33 * ieee80211_start_tx_ba_session() function, the driver will be notified via 34 * ieee80211_start_tx_ba_session() function, the driver will be
34 * its @ampdu_action function, with the %IEEE80211_AMPDU_TX_START action. 35 * notified via its @ampdu_action function, with the
36 * %IEEE80211_AMPDU_TX_START action.
35 * 37 *
36 * In response to that, the driver is later required to call the 38 * In response to that, the driver is later required to call the
37 * ieee80211_start_tx_ba_cb() (or ieee80211_start_tx_ba_cb_irqsafe()) 39 * ieee80211_start_tx_ba_cb_irqsafe() function, which will really
38 * function, which will start the aggregation session. 40 * start the aggregation session after the peer has also responded.
41 * If the peer responds negatively, the session will be stopped
42 * again right away. Note that it is possible for the aggregation
43 * session to be stopped before the driver has indicated that it
44 * is done setting it up, in which case it must not indicate the
45 * setup completion.
39 * 46 *
40 * Similarly, when the aggregation session is stopped by 47 * Also note that, since we also need to wait for a response from
41 * ieee80211_stop_tx_ba_session(), the driver's @ampdu_action function will 48 * the peer, the driver is notified of the completion of the
42 * be called with the action %IEEE80211_AMPDU_TX_STOP. In this case, the 49 * handshake by the %IEEE80211_AMPDU_TX_OPERATIONAL action to the
43 * call must not fail, and the driver must later call ieee80211_stop_tx_ba_cb() 50 * @ampdu_action callback.
44 * (or ieee80211_stop_tx_ba_cb_irqsafe()). 51 *
52 * Similarly, when the aggregation session is stopped by the peer
53 * or something calling ieee80211_stop_tx_ba_session(), the driver's
54 * @ampdu_action function will be called with the action
55 * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail,
56 * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe().
45 */ 57 */
46 58
47static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, 59static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -58,17 +70,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
58 70
59 if (!skb) { 71 if (!skb) {
60 printk(KERN_ERR "%s: failed to allocate buffer " 72 printk(KERN_ERR "%s: failed to allocate buffer "
61 "for addba request frame\n", sdata->dev->name); 73 "for addba request frame\n", sdata->name);
62 return; 74 return;
63 } 75 }
64 skb_reserve(skb, local->hw.extra_tx_headroom); 76 skb_reserve(skb, local->hw.extra_tx_headroom);
65 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 77 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
66 memset(mgmt, 0, 24); 78 memset(mgmt, 0, 24);
67 memcpy(mgmt->da, da, ETH_ALEN); 79 memcpy(mgmt->da, da, ETH_ALEN);
68 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 80 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
69 if (sdata->vif.type == NL80211_IFTYPE_AP || 81 if (sdata->vif.type == NL80211_IFTYPE_AP ||
70 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 82 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
71 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); 83 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
72 else if (sdata->vif.type == NL80211_IFTYPE_STATION) 84 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
73 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); 85 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
74 86
@@ -104,7 +116,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
104 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); 116 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
105 if (!skb) { 117 if (!skb) {
106 printk(KERN_ERR "%s: failed to allocate buffer for " 118 printk(KERN_ERR "%s: failed to allocate buffer for "
107 "bar frame\n", sdata->dev->name); 119 "bar frame\n", sdata->name);
108 return; 120 return;
109 } 121 }
110 skb_reserve(skb, local->hw.extra_tx_headroom); 122 skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -113,7 +125,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
113 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | 125 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
114 IEEE80211_STYPE_BACK_REQ); 126 IEEE80211_STYPE_BACK_REQ);
115 memcpy(bar->ra, ra, ETH_ALEN); 127 memcpy(bar->ra, ra, ETH_ALEN);
116 memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); 128 memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);
117 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; 129 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
118 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; 130 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
119 bar_control |= (u16)(tid << 12); 131 bar_control |= (u16)(tid << 12);
@@ -124,27 +136,57 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
124 ieee80211_tx_skb(sdata, skb); 136 ieee80211_tx_skb(sdata, skb);
125} 137}
126 138
139static void kfree_tid_tx(struct rcu_head *rcu_head)
140{
141 struct tid_ampdu_tx *tid_tx =
142 container_of(rcu_head, struct tid_ampdu_tx, rcu_head);
143
144 kfree(tid_tx);
145}
146
127int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 147int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
128 enum ieee80211_back_parties initiator) 148 enum ieee80211_back_parties initiator)
129{ 149{
130 struct ieee80211_local *local = sta->local; 150 struct ieee80211_local *local = sta->local;
151 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid];
131 int ret; 152 int ret;
132 u8 *state; 153
154 lockdep_assert_held(&sta->ampdu_mlme.mtx);
155
156 if (!tid_tx)
157 return -ENOENT;
158
159 spin_lock_bh(&sta->lock);
160
161 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
162 /* not even started yet! */
163 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL);
164 spin_unlock_bh(&sta->lock);
165 call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
166 return 0;
167 }
168
169 spin_unlock_bh(&sta->lock);
133 170
134#ifdef CONFIG_MAC80211_HT_DEBUG 171#ifdef CONFIG_MAC80211_HT_DEBUG
135 printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", 172 printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
136 sta->sta.addr, tid); 173 sta->sta.addr, tid);
137#endif /* CONFIG_MAC80211_HT_DEBUG */ 174#endif /* CONFIG_MAC80211_HT_DEBUG */
138 175
139 state = &sta->ampdu_mlme.tid_state_tx[tid]; 176 set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
140 177
141 if (*state == HT_AGG_STATE_OPERATIONAL) 178 del_timer_sync(&tid_tx->addba_resp_timer);
142 sta->ampdu_mlme.addba_req_num[tid] = 0; 179
180 /*
181 * After this packets are no longer handed right through
182 * to the driver but are put onto tid_tx->pending instead,
183 * with locking to ensure proper access.
184 */
185 clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
143 186
144 *state = HT_AGG_STATE_REQ_STOP_BA_MSK | 187 tid_tx->stop_initiator = initiator;
145 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
146 188
147 ret = drv_ampdu_action(local, &sta->sdata->vif, 189 ret = drv_ampdu_action(local, sta->sdata,
148 IEEE80211_AMPDU_TX_STOP, 190 IEEE80211_AMPDU_TX_STOP,
149 &sta->sta, tid, NULL); 191 &sta->sta, tid, NULL);
150 192
@@ -173,19 +215,17 @@ static void sta_addba_resp_timer_expired(unsigned long data)
173 u16 tid = *(u8 *)data; 215 u16 tid = *(u8 *)data;
174 struct sta_info *sta = container_of((void *)data, 216 struct sta_info *sta = container_of((void *)data,
175 struct sta_info, timer_to_tid[tid]); 217 struct sta_info, timer_to_tid[tid]);
176 u8 *state; 218 struct tid_ampdu_tx *tid_tx;
177
178 state = &sta->ampdu_mlme.tid_state_tx[tid];
179 219
180 /* check if the TID waits for addBA response */ 220 /* check if the TID waits for addBA response */
181 spin_lock_bh(&sta->lock); 221 rcu_read_lock();
182 if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK)) != 222 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
183 HT_ADDBA_REQUESTED_MSK) { 223 if (!tid_tx ||
184 spin_unlock_bh(&sta->lock); 224 test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) {
185 *state = HT_AGG_STATE_IDLE; 225 rcu_read_unlock();
186#ifdef CONFIG_MAC80211_HT_DEBUG 226#ifdef CONFIG_MAC80211_HT_DEBUG
187 printk(KERN_DEBUG "timer expired on tid %d but we are not " 227 printk(KERN_DEBUG "timer expired on tid %d but we are not "
188 "(or no longer) expecting addBA response there", 228 "(or no longer) expecting addBA response there\n",
189 tid); 229 tid);
190#endif 230#endif
191 return; 231 return;
@@ -195,8 +235,8 @@ static void sta_addba_resp_timer_expired(unsigned long data)
195 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); 235 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
196#endif 236#endif
197 237
198 ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); 238 ieee80211_stop_tx_ba_session(&sta->sta, tid);
199 spin_unlock_bh(&sta->lock); 239 rcu_read_unlock();
200} 240}
201 241
202static inline int ieee80211_ac_from_tid(int tid) 242static inline int ieee80211_ac_from_tid(int tid)
@@ -204,14 +244,114 @@ static inline int ieee80211_ac_from_tid(int tid)
204 return ieee802_1d_to_ac[tid & 7]; 244 return ieee802_1d_to_ac[tid & 7];
205} 245}
206 246
247/*
248 * When multiple aggregation sessions on multiple stations
249 * are being created/destroyed simultaneously, we need to
250 * refcount the global queue stop caused by that in order
251 * to not get into a situation where one of the aggregation
252 * setup or teardown re-enables queues before the other is
253 * ready to handle that.
254 *
255 * These two functions take care of this issue by keeping
256 * a global "agg_queue_stop" refcount.
257 */
258static void __acquires(agg_queue)
259ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid)
260{
261 int queue = ieee80211_ac_from_tid(tid);
262
263 if (atomic_inc_return(&local->agg_queue_stop[queue]) == 1)
264 ieee80211_stop_queue_by_reason(
265 &local->hw, queue,
266 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
267 __acquire(agg_queue);
268}
269
270static void __releases(agg_queue)
271ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid)
272{
273 int queue = ieee80211_ac_from_tid(tid);
274
275 if (atomic_dec_return(&local->agg_queue_stop[queue]) == 0)
276 ieee80211_wake_queue_by_reason(
277 &local->hw, queue,
278 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
279 __release(agg_queue);
280}
281
282void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
283{
284 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid];
285 struct ieee80211_local *local = sta->local;
286 struct ieee80211_sub_if_data *sdata = sta->sdata;
287 u16 start_seq_num;
288 int ret;
289
290 lockdep_assert_held(&sta->ampdu_mlme.mtx);
291
292 /*
293 * While we're asking the driver about the aggregation,
294 * stop the AC queue so that we don't have to worry
295 * about frames that came in while we were doing that,
296 * which would require us to put them to the AC pending
297 * afterwards which just makes the code more complex.
298 */
299 ieee80211_stop_queue_agg(local, tid);
300
301 clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
302
303 /*
304 * make sure no packets are being processed to get
305 * valid starting sequence number
306 */
307 synchronize_net();
308
309 start_seq_num = sta->tid_seq[tid] >> 4;
310
311 ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
312 &sta->sta, tid, &start_seq_num);
313 if (ret) {
314#ifdef CONFIG_MAC80211_HT_DEBUG
315 printk(KERN_DEBUG "BA request denied - HW unavailable for"
316 " tid %d\n", tid);
317#endif
318 spin_lock_bh(&sta->lock);
319 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL);
320 spin_unlock_bh(&sta->lock);
321
322 ieee80211_wake_queue_agg(local, tid);
323 call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
324 return;
325 }
326
327 /* we can take packets again now */
328 ieee80211_wake_queue_agg(local, tid);
329
330 /* activate the timer for the recipient's addBA response */
331 mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
332#ifdef CONFIG_MAC80211_HT_DEBUG
333 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
334#endif
335
336 spin_lock_bh(&sta->lock);
337 sta->ampdu_mlme.addba_req_num[tid]++;
338 spin_unlock_bh(&sta->lock);
339
340 /* send AddBA request */
341 ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
342 tid_tx->dialog_token, start_seq_num,
343 0x40, 5000);
344}
345
207int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) 346int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
208{ 347{
209 struct sta_info *sta = container_of(pubsta, struct sta_info, sta); 348 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
210 struct ieee80211_sub_if_data *sdata = sta->sdata; 349 struct ieee80211_sub_if_data *sdata = sta->sdata;
211 struct ieee80211_local *local = sdata->local; 350 struct ieee80211_local *local = sdata->local;
212 u8 *state; 351 struct tid_ampdu_tx *tid_tx;
213 int ret = 0; 352 int ret = 0;
214 u16 start_seq_num; 353
354 trace_api_start_tx_ba_session(pubsta, tid);
215 355
216 if (WARN_ON(!local->ops->ampdu_action)) 356 if (WARN_ON(!local->ops->ampdu_action))
217 return -EINVAL; 357 return -EINVAL;
@@ -236,16 +376,15 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
236 sdata->vif.type != NL80211_IFTYPE_AP) 376 sdata->vif.type != NL80211_IFTYPE_AP)
237 return -EINVAL; 377 return -EINVAL;
238 378
239 if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { 379 if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
240#ifdef CONFIG_MAC80211_HT_DEBUG 380#ifdef CONFIG_MAC80211_HT_DEBUG
241 printk(KERN_DEBUG "Suspend in progress. " 381 printk(KERN_DEBUG "BA sessions blocked. "
242 "Denying BA session request\n"); 382 "Denying BA session request\n");
243#endif 383#endif
244 return -EINVAL; 384 return -EINVAL;
245 } 385 }
246 386
247 spin_lock_bh(&sta->lock); 387 spin_lock_bh(&sta->lock);
248 spin_lock(&local->ampdu_lock);
249 388
250 /* we have tried too many times, receiver does not want A-MPDU */ 389 /* we have tried too many times, receiver does not want A-MPDU */
251 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { 390 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
@@ -253,9 +392,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
253 goto err_unlock_sta; 392 goto err_unlock_sta;
254 } 393 }
255 394
256 state = &sta->ampdu_mlme.tid_state_tx[tid]; 395 tid_tx = sta->ampdu_mlme.tid_tx[tid];
257 /* check if the TID is not in aggregation flow already */ 396 /* check if the TID is not in aggregation flow already */
258 if (*state != HT_AGG_STATE_IDLE) { 397 if (tid_tx) {
259#ifdef CONFIG_MAC80211_HT_DEBUG 398#ifdef CONFIG_MAC80211_HT_DEBUG
260 printk(KERN_DEBUG "BA request denied - session is not " 399 printk(KERN_DEBUG "BA request denied - session is not "
261 "idle on tid %u\n", tid); 400 "idle on tid %u\n", tid);
@@ -264,95 +403,37 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
264 goto err_unlock_sta; 403 goto err_unlock_sta;
265 } 404 }
266 405
267 /*
268 * While we're asking the driver about the aggregation,
269 * stop the AC queue so that we don't have to worry
270 * about frames that came in while we were doing that,
271 * which would require us to put them to the AC pending
272 * afterwards which just makes the code more complex.
273 */
274 ieee80211_stop_queue_by_reason(
275 &local->hw, ieee80211_ac_from_tid(tid),
276 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
277
278 /* prepare A-MPDU MLME for Tx aggregation */ 406 /* prepare A-MPDU MLME for Tx aggregation */
279 sta->ampdu_mlme.tid_tx[tid] = 407 tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
280 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); 408 if (!tid_tx) {
281 if (!sta->ampdu_mlme.tid_tx[tid]) {
282#ifdef CONFIG_MAC80211_HT_DEBUG 409#ifdef CONFIG_MAC80211_HT_DEBUG
283 if (net_ratelimit()) 410 if (net_ratelimit())
284 printk(KERN_ERR "allocate tx mlme to tid %d failed\n", 411 printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
285 tid); 412 tid);
286#endif 413#endif
287 ret = -ENOMEM; 414 ret = -ENOMEM;
288 goto err_wake_queue; 415 goto err_unlock_sta;
289 } 416 }
290 417
291 skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending); 418 skb_queue_head_init(&tid_tx->pending);
419 __set_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
292 420
293 /* Tx timer */ 421 /* Tx timer */
294 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = 422 tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired;
295 sta_addba_resp_timer_expired; 423 tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid];
296 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = 424 init_timer(&tid_tx->addba_resp_timer);
297 (unsigned long)&sta->timer_to_tid[tid];
298 init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
299
300 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
301 * call back right away, it must see that the flow has begun */
302 *state |= HT_ADDBA_REQUESTED_MSK;
303
304 start_seq_num = sta->tid_seq[tid];
305 425
306 ret = drv_ampdu_action(local, &sdata->vif, 426 /* assign a dialog token */
307 IEEE80211_AMPDU_TX_START, 427 sta->ampdu_mlme.dialog_token_allocator++;
308 pubsta, tid, &start_seq_num); 428 tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator;
309
310 if (ret) {
311#ifdef CONFIG_MAC80211_HT_DEBUG
312 printk(KERN_DEBUG "BA request denied - HW unavailable for"
313 " tid %d\n", tid);
314#endif /* CONFIG_MAC80211_HT_DEBUG */
315 *state = HT_AGG_STATE_IDLE;
316 goto err_free;
317 }
318 429
319 /* Driver vetoed or OKed, but we can take packets again now */ 430 /* finally, assign it to the array */
320 ieee80211_wake_queue_by_reason( 431 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
321 &local->hw, ieee80211_ac_from_tid(tid),
322 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
323 432
324 spin_unlock(&local->ampdu_lock); 433 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
325 spin_unlock_bh(&sta->lock);
326 434
327 /* send an addBA request */ 435 /* this flow continues off the work */
328 sta->ampdu_mlme.dialog_token_allocator++;
329 sta->ampdu_mlme.tid_tx[tid]->dialog_token =
330 sta->ampdu_mlme.dialog_token_allocator;
331 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
332
333 ieee80211_send_addba_request(sdata, pubsta->addr, tid,
334 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
335 sta->ampdu_mlme.tid_tx[tid]->ssn,
336 0x40, 5000);
337 sta->ampdu_mlme.addba_req_num[tid]++;
338 /* activate the timer for the recipient's addBA response */
339 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
340 jiffies + ADDBA_RESP_INTERVAL;
341 add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
342#ifdef CONFIG_MAC80211_HT_DEBUG
343 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
344#endif
345 return 0;
346
347 err_free:
348 kfree(sta->ampdu_mlme.tid_tx[tid]);
349 sta->ampdu_mlme.tid_tx[tid] = NULL;
350 err_wake_queue:
351 ieee80211_wake_queue_by_reason(
352 &local->hw, ieee80211_ac_from_tid(tid),
353 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
354 err_unlock_sta: 436 err_unlock_sta:
355 spin_unlock(&local->ampdu_lock);
356 spin_unlock_bh(&sta->lock); 437 spin_unlock_bh(&sta->lock);
357 return ret; 438 return ret;
358} 439}
@@ -360,69 +441,65 @@ EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
360 441
361/* 442/*
362 * splice packets from the STA's pending to the local pending, 443 * splice packets from the STA's pending to the local pending,
363 * requires a call to ieee80211_agg_splice_finish and holding 444 * requires a call to ieee80211_agg_splice_finish later
364 * local->ampdu_lock across both calls.
365 */ 445 */
366static void ieee80211_agg_splice_packets(struct ieee80211_local *local, 446static void __acquires(agg_queue)
367 struct sta_info *sta, u16 tid) 447ieee80211_agg_splice_packets(struct ieee80211_local *local,
448 struct tid_ampdu_tx *tid_tx, u16 tid)
368{ 449{
450 int queue = ieee80211_ac_from_tid(tid);
369 unsigned long flags; 451 unsigned long flags;
370 u16 queue = ieee80211_ac_from_tid(tid);
371
372 ieee80211_stop_queue_by_reason(
373 &local->hw, queue,
374 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
375 452
376 if (!(sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK)) 453 ieee80211_stop_queue_agg(local, tid);
377 return;
378 454
379 if (WARN(!sta->ampdu_mlme.tid_tx[tid], 455 if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
380 "TID %d gone but expected when splicing aggregates from" 456 " from the pending queue\n", tid))
381 "the pending queue\n", tid))
382 return; 457 return;
383 458
384 if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { 459 if (!skb_queue_empty(&tid_tx->pending)) {
385 spin_lock_irqsave(&local->queue_stop_reason_lock, flags); 460 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
386 /* copy over remaining packets */ 461 /* copy over remaining packets */
387 skb_queue_splice_tail_init( 462 skb_queue_splice_tail_init(&tid_tx->pending,
388 &sta->ampdu_mlme.tid_tx[tid]->pending, 463 &local->pending[queue]);
389 &local->pending[queue]);
390 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 464 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
391 } 465 }
392} 466}
393 467
394static void ieee80211_agg_splice_finish(struct ieee80211_local *local, 468static void __releases(agg_queue)
395 struct sta_info *sta, u16 tid) 469ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
396{ 470{
397 u16 queue = ieee80211_ac_from_tid(tid); 471 ieee80211_wake_queue_agg(local, tid);
398
399 ieee80211_wake_queue_by_reason(
400 &local->hw, queue,
401 IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
402} 472}
403 473
404/* caller must hold sta->lock */
405static void ieee80211_agg_tx_operational(struct ieee80211_local *local, 474static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
406 struct sta_info *sta, u16 tid) 475 struct sta_info *sta, u16 tid)
407{ 476{
477 lockdep_assert_held(&sta->ampdu_mlme.mtx);
478
408#ifdef CONFIG_MAC80211_HT_DEBUG 479#ifdef CONFIG_MAC80211_HT_DEBUG
409 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); 480 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid);
410#endif 481#endif
411 482
412 spin_lock(&local->ampdu_lock); 483 drv_ampdu_action(local, sta->sdata,
413 ieee80211_agg_splice_packets(local, sta, tid); 484 IEEE80211_AMPDU_TX_OPERATIONAL,
485 &sta->sta, tid, NULL);
486
414 /* 487 /*
415 * NB: we rely on sta->lock being taken in the TX 488 * synchronize with TX path, while splicing the TX path
416 * processing here when adding to the pending queue, 489 * should block so it won't put more packets onto pending.
417 * otherwise we could only change the state of the
418 * session to OPERATIONAL _here_.
419 */ 490 */
420 ieee80211_agg_splice_finish(local, sta, tid); 491 spin_lock_bh(&sta->lock);
421 spin_unlock(&local->ampdu_lock);
422 492
423 drv_ampdu_action(local, &sta->sdata->vif, 493 ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid);
424 IEEE80211_AMPDU_TX_OPERATIONAL, 494 /*
425 &sta->sta, tid, NULL); 495 * Now mark as operational. This will be visible
496 * in the TX path, and lets it go lock-free in
497 * the common case.
498 */
499 set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state);
500 ieee80211_agg_splice_finish(local, tid);
501
502 spin_unlock_bh(&sta->lock);
426} 503}
427 504
428void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) 505void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
@@ -430,7 +507,9 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
430 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 507 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
431 struct ieee80211_local *local = sdata->local; 508 struct ieee80211_local *local = sdata->local;
432 struct sta_info *sta; 509 struct sta_info *sta;
433 u8 *state; 510 struct tid_ampdu_tx *tid_tx;
511
512 trace_api_start_tx_ba_cb(sdata, ra, tid);
434 513
435 if (tid >= STA_TID_NUM) { 514 if (tid >= STA_TID_NUM) {
436#ifdef CONFIG_MAC80211_HT_DEBUG 515#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -440,42 +519,36 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
440 return; 519 return;
441 } 520 }
442 521
443 rcu_read_lock(); 522 mutex_lock(&local->sta_mtx);
444 sta = sta_info_get(local, ra); 523 sta = sta_info_get(sdata, ra);
445 if (!sta) { 524 if (!sta) {
446 rcu_read_unlock(); 525 mutex_unlock(&local->sta_mtx);
447#ifdef CONFIG_MAC80211_HT_DEBUG 526#ifdef CONFIG_MAC80211_HT_DEBUG
448 printk(KERN_DEBUG "Could not find station: %pM\n", ra); 527 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
449#endif 528#endif
450 return; 529 return;
451 } 530 }
452 531
453 state = &sta->ampdu_mlme.tid_state_tx[tid]; 532 mutex_lock(&sta->ampdu_mlme.mtx);
454 spin_lock_bh(&sta->lock); 533 tid_tx = sta->ampdu_mlme.tid_tx[tid];
455 534
456 if (WARN_ON(!(*state & HT_ADDBA_REQUESTED_MSK))) { 535 if (WARN_ON(!tid_tx)) {
457#ifdef CONFIG_MAC80211_HT_DEBUG 536#ifdef CONFIG_MAC80211_HT_DEBUG
458 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", 537 printk(KERN_DEBUG "addBA was not requested!\n");
459 *state);
460#endif 538#endif
461 spin_unlock_bh(&sta->lock); 539 goto unlock;
462 rcu_read_unlock();
463 return;
464 } 540 }
465 541
466 if (WARN_ON(*state & HT_ADDBA_DRV_READY_MSK)) 542 if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
467 goto out; 543 goto unlock;
468
469 *state |= HT_ADDBA_DRV_READY_MSK;
470 544
471 if (*state == HT_AGG_STATE_OPERATIONAL) 545 if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
472 ieee80211_agg_tx_operational(local, sta, tid); 546 ieee80211_agg_tx_operational(local, sta, tid);
473 547
474 out: 548 unlock:
475 spin_unlock_bh(&sta->lock); 549 mutex_unlock(&sta->ampdu_mlme.mtx);
476 rcu_read_unlock(); 550 mutex_unlock(&local->sta_mtx);
477} 551}
478EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
479 552
480void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, 553void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
481 const u8 *ra, u16 tid) 554 const u8 *ra, u16 tid)
@@ -489,49 +562,43 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
489#ifdef CONFIG_MAC80211_HT_DEBUG 562#ifdef CONFIG_MAC80211_HT_DEBUG
490 if (net_ratelimit()) 563 if (net_ratelimit())
491 printk(KERN_WARNING "%s: Not enough memory, " 564 printk(KERN_WARNING "%s: Not enough memory, "
492 "dropping start BA session", skb->dev->name); 565 "dropping start BA session", sdata->name);
493#endif 566#endif
494 return; 567 return;
495 } 568 }
496 ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 569 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
497 memcpy(&ra_tid->ra, ra, ETH_ALEN); 570 memcpy(&ra_tid->ra, ra, ETH_ALEN);
498 ra_tid->tid = tid; 571 ra_tid->tid = tid;
499 ra_tid->vif = vif;
500 572
501 skb->pkt_type = IEEE80211_ADDBA_MSG; 573 skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_START;
502 skb_queue_tail(&local->skb_queue, skb); 574 skb_queue_tail(&sdata->skb_queue, skb);
503 tasklet_schedule(&local->tasklet); 575 ieee80211_queue_work(&local->hw, &sdata->work);
504} 576}
505EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); 577EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
506 578
507int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 579int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
508 enum ieee80211_back_parties initiator) 580 enum ieee80211_back_parties initiator)
509{ 581{
510 u8 *state;
511 int ret; 582 int ret;
512 583
513 /* check if the TID is in aggregation */ 584 mutex_lock(&sta->ampdu_mlme.mtx);
514 state = &sta->ampdu_mlme.tid_state_tx[tid];
515 spin_lock_bh(&sta->lock);
516
517 if (*state != HT_AGG_STATE_OPERATIONAL) {
518 ret = -ENOENT;
519 goto unlock;
520 }
521 585
522 ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); 586 ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator);
523 587
524 unlock: 588 mutex_unlock(&sta->ampdu_mlme.mtx);
525 spin_unlock_bh(&sta->lock); 589
526 return ret; 590 return ret;
527} 591}
528 592
529int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, 593int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
530 enum ieee80211_back_parties initiator)
531{ 594{
532 struct sta_info *sta = container_of(pubsta, struct sta_info, sta); 595 struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
533 struct ieee80211_sub_if_data *sdata = sta->sdata; 596 struct ieee80211_sub_if_data *sdata = sta->sdata;
534 struct ieee80211_local *local = sdata->local; 597 struct ieee80211_local *local = sdata->local;
598 struct tid_ampdu_tx *tid_tx;
599 int ret = 0;
600
601 trace_api_stop_tx_ba_session(pubsta, tid);
535 602
536 if (!local->ops->ampdu_action) 603 if (!local->ops->ampdu_action)
537 return -EINVAL; 604 return -EINVAL;
@@ -539,7 +606,26 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
539 if (tid >= STA_TID_NUM) 606 if (tid >= STA_TID_NUM)
540 return -EINVAL; 607 return -EINVAL;
541 608
542 return __ieee80211_stop_tx_ba_session(sta, tid, initiator); 609 spin_lock_bh(&sta->lock);
610 tid_tx = sta->ampdu_mlme.tid_tx[tid];
611
612 if (!tid_tx) {
613 ret = -ENOENT;
614 goto unlock;
615 }
616
617 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
618 /* already in progress stopping it */
619 ret = 0;
620 goto unlock;
621 }
622
623 set_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state);
624 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
625
626 unlock:
627 spin_unlock_bh(&sta->lock);
628 return ret;
543} 629}
544EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); 630EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
545 631
@@ -548,7 +634,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
548 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 634 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
549 struct ieee80211_local *local = sdata->local; 635 struct ieee80211_local *local = sdata->local;
550 struct sta_info *sta; 636 struct sta_info *sta;
551 u8 *state; 637 struct tid_ampdu_tx *tid_tx;
638
639 trace_api_stop_tx_ba_cb(sdata, ra, tid);
552 640
553 if (tid >= STA_TID_NUM) { 641 if (tid >= STA_TID_NUM) {
554#ifdef CONFIG_MAC80211_HT_DEBUG 642#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -563,51 +651,56 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
563 ra, tid); 651 ra, tid);
564#endif /* CONFIG_MAC80211_HT_DEBUG */ 652#endif /* CONFIG_MAC80211_HT_DEBUG */
565 653
566 rcu_read_lock(); 654 mutex_lock(&local->sta_mtx);
567 sta = sta_info_get(local, ra); 655
656 sta = sta_info_get(sdata, ra);
568 if (!sta) { 657 if (!sta) {
569#ifdef CONFIG_MAC80211_HT_DEBUG 658#ifdef CONFIG_MAC80211_HT_DEBUG
570 printk(KERN_DEBUG "Could not find station: %pM\n", ra); 659 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
571#endif 660#endif
572 rcu_read_unlock(); 661 goto unlock;
573 return;
574 } 662 }
575 state = &sta->ampdu_mlme.tid_state_tx[tid];
576 663
577 /* NOTE: no need to use sta->lock in this state check, as 664 mutex_lock(&sta->ampdu_mlme.mtx);
578 * ieee80211_stop_tx_ba_session will let only one stop call to 665 spin_lock_bh(&sta->lock);
579 * pass through per sta/tid 666 tid_tx = sta->ampdu_mlme.tid_tx[tid];
580 */ 667
581 if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { 668 if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
582#ifdef CONFIG_MAC80211_HT_DEBUG 669#ifdef CONFIG_MAC80211_HT_DEBUG
583 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); 670 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
584#endif 671#endif
585 rcu_read_unlock(); 672 goto unlock_sta;
586 return;
587 } 673 }
588 674
589 if (*state & HT_AGG_STATE_INITIATOR_MSK) 675 if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR)
590 ieee80211_send_delba(sta->sdata, ra, tid, 676 ieee80211_send_delba(sta->sdata, ra, tid,
591 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); 677 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
592 678
593 spin_lock_bh(&sta->lock); 679 /*
594 spin_lock(&local->ampdu_lock); 680 * When we get here, the TX path will not be lockless any more wrt.
681 * aggregation, since the OPERATIONAL bit has long been cleared.
682 * Thus it will block on getting the lock, if it occurs. So if we
683 * stop the queue now, we will not get any more packets, and any
684 * that might be being processed will wait for us here, thereby
685 * guaranteeing that no packets go to the tid_tx pending queue any
686 * more.
687 */
595 688
596 ieee80211_agg_splice_packets(local, sta, tid); 689 ieee80211_agg_splice_packets(local, tid_tx, tid);
597 690
598 *state = HT_AGG_STATE_IDLE; 691 /* future packets must not find the tid_tx struct any more */
599 /* from now on packets are no longer put onto sta->pending */ 692 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL);
600 kfree(sta->ampdu_mlme.tid_tx[tid]);
601 sta->ampdu_mlme.tid_tx[tid] = NULL;
602 693
603 ieee80211_agg_splice_finish(local, sta, tid); 694 ieee80211_agg_splice_finish(local, tid);
604 695
605 spin_unlock(&local->ampdu_lock); 696 call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
606 spin_unlock_bh(&sta->lock);
607 697
608 rcu_read_unlock(); 698 unlock_sta:
699 spin_unlock_bh(&sta->lock);
700 mutex_unlock(&sta->ampdu_mlme.mtx);
701 unlock:
702 mutex_unlock(&local->sta_mtx);
609} 703}
610EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
611 704
612void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, 705void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
613 const u8 *ra, u16 tid) 706 const u8 *ra, u16 tid)
@@ -621,18 +714,17 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
621#ifdef CONFIG_MAC80211_HT_DEBUG 714#ifdef CONFIG_MAC80211_HT_DEBUG
622 if (net_ratelimit()) 715 if (net_ratelimit())
623 printk(KERN_WARNING "%s: Not enough memory, " 716 printk(KERN_WARNING "%s: Not enough memory, "
624 "dropping stop BA session", skb->dev->name); 717 "dropping stop BA session", sdata->name);
625#endif 718#endif
626 return; 719 return;
627 } 720 }
628 ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 721 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
629 memcpy(&ra_tid->ra, ra, ETH_ALEN); 722 memcpy(&ra_tid->ra, ra, ETH_ALEN);
630 ra_tid->tid = tid; 723 ra_tid->tid = tid;
631 ra_tid->vif = vif;
632 724
633 skb->pkt_type = IEEE80211_DELBA_MSG; 725 skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_STOP;
634 skb_queue_tail(&local->skb_queue, skb); 726 skb_queue_tail(&sdata->skb_queue, skb);
635 tasklet_schedule(&local->tasklet); 727 ieee80211_queue_work(&local->hw, &sdata->work);
636} 728}
637EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); 729EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
638 730
@@ -642,40 +734,40 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
642 struct ieee80211_mgmt *mgmt, 734 struct ieee80211_mgmt *mgmt,
643 size_t len) 735 size_t len)
644{ 736{
737 struct tid_ampdu_tx *tid_tx;
645 u16 capab, tid; 738 u16 capab, tid;
646 u8 *state;
647 739
648 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); 740 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
649 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; 741 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
650 742
651 state = &sta->ampdu_mlme.tid_state_tx[tid]; 743 mutex_lock(&sta->ampdu_mlme.mtx);
652 744
653 spin_lock_bh(&sta->lock); 745 tid_tx = sta->ampdu_mlme.tid_tx[tid];
654 746 if (!tid_tx)
655 if (!(*state & HT_ADDBA_REQUESTED_MSK))
656 goto out; 747 goto out;
657 748
658 if (mgmt->u.action.u.addba_resp.dialog_token != 749 if (mgmt->u.action.u.addba_resp.dialog_token != tid_tx->dialog_token) {
659 sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
660#ifdef CONFIG_MAC80211_HT_DEBUG 750#ifdef CONFIG_MAC80211_HT_DEBUG
661 printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); 751 printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
662#endif /* CONFIG_MAC80211_HT_DEBUG */ 752#endif
663 goto out; 753 goto out;
664 } 754 }
665 755
666 del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); 756 del_timer(&tid_tx->addba_resp_timer);
667 757
668#ifdef CONFIG_MAC80211_HT_DEBUG 758#ifdef CONFIG_MAC80211_HT_DEBUG
669 printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); 759 printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid);
670#endif /* CONFIG_MAC80211_HT_DEBUG */ 760#endif
671 761
672 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) 762 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
673 == WLAN_STATUS_SUCCESS) { 763 == WLAN_STATUS_SUCCESS) {
674 u8 curstate = *state; 764 if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
765 &tid_tx->state)) {
766 /* ignore duplicate response */
767 goto out;
768 }
675 769
676 *state |= HT_ADDBA_RECEIVED_MSK; 770 if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))
677
678 if (*state != curstate && *state == HT_AGG_STATE_OPERATIONAL)
679 ieee80211_agg_tx_operational(local, sta, tid); 771 ieee80211_agg_tx_operational(local, sta, tid);
680 772
681 sta->ampdu_mlme.addba_req_num[tid] = 0; 773 sta->ampdu_mlme.addba_req_num[tid] = 0;
@@ -684,5 +776,5 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
684 } 776 }
685 777
686 out: 778 out:
687 spin_unlock_bh(&sta->lock); 779 mutex_unlock(&sta->ampdu_mlme.mtx);
688} 780}