xref: /openbmc/linux/net/mac80211/agg-tx.c (revision 8abd3f9b)
1 /*
2  * HT handling
3  *
4  * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
5  * Copyright 2002-2005, Instant802 Networks, Inc.
6  * Copyright 2005-2006, Devicescape Software, Inc.
7  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
8  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
9  * Copyright 2007-2009, Intel Corporation
10  *
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
13  * published by the Free Software Foundation.
14  */
15 
16 #include <linux/ieee80211.h>
17 #include <net/mac80211.h>
18 #include "ieee80211_i.h"
19 #include "wme.h"
20 
21 static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
22 					 const u8 *da, u16 tid,
23 					 u8 dialog_token, u16 start_seq_num,
24 					 u16 agg_size, u16 timeout)
25 {
26 	struct ieee80211_local *local = sdata->local;
27 	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
28 	struct sk_buff *skb;
29 	struct ieee80211_mgmt *mgmt;
30 	u16 capab;
31 
32 	skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
33 
34 	if (!skb) {
35 		printk(KERN_ERR "%s: failed to allocate buffer "
36 				"for addba request frame\n", sdata->dev->name);
37 		return;
38 	}
39 	skb_reserve(skb, local->hw.extra_tx_headroom);
40 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
41 	memset(mgmt, 0, 24);
42 	memcpy(mgmt->da, da, ETH_ALEN);
43 	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
44 	if (sdata->vif.type == NL80211_IFTYPE_AP ||
45 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
46 		memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
47 	else
48 		memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
49 
50 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
51 					  IEEE80211_STYPE_ACTION);
52 
53 	skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
54 
55 	mgmt->u.action.category = WLAN_CATEGORY_BACK;
56 	mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
57 
58 	mgmt->u.action.u.addba_req.dialog_token = dialog_token;
59 	capab = (u16)(1 << 1);		/* bit 1 aggregation policy */
60 	capab |= (u16)(tid << 2); 	/* bit 5:2 TID number */
61 	capab |= (u16)(agg_size << 6);	/* bit 15:6 max size of aggergation */
62 
63 	mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
64 
65 	mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
66 	mgmt->u.action.u.addba_req.start_seq_num =
67 					cpu_to_le16(start_seq_num << 4);
68 
69 	ieee80211_tx_skb(sdata, skb, 1);
70 }
71 
72 void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
73 {
74 	struct ieee80211_local *local = sdata->local;
75 	struct sk_buff *skb;
76 	struct ieee80211_bar *bar;
77 	u16 bar_control = 0;
78 
79 	skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
80 	if (!skb) {
81 		printk(KERN_ERR "%s: failed to allocate buffer for "
82 			"bar frame\n", sdata->dev->name);
83 		return;
84 	}
85 	skb_reserve(skb, local->hw.extra_tx_headroom);
86 	bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
87 	memset(bar, 0, sizeof(*bar));
88 	bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
89 					 IEEE80211_STYPE_BACK_REQ);
90 	memcpy(bar->ra, ra, ETH_ALEN);
91 	memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
92 	bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
93 	bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
94 	bar_control |= (u16)(tid << 12);
95 	bar->control = cpu_to_le16(bar_control);
96 	bar->start_seq_num = cpu_to_le16(ssn);
97 
98 	ieee80211_tx_skb(sdata, skb, 0);
99 }
100 
101 /*
102  * After sending add Block Ack request we activated a timer until
103  * add Block Ack response will arrive from the recipient.
104  * If this timer expires sta_addba_resp_timer_expired will be executed.
105  */
106 static void sta_addba_resp_timer_expired(unsigned long data)
107 {
108 	/* not an elegant detour, but there is no choice as the timer passes
109 	 * only one argument, and both sta_info and TID are needed, so init
110 	 * flow in sta_info_create gives the TID as data, while the timer_to_id
111 	 * array gives the sta through container_of */
112 	u16 tid = *(u8 *)data;
113 	struct sta_info *temp_sta = container_of((void *)data,
114 		struct sta_info, timer_to_tid[tid]);
115 
116 	struct ieee80211_local *local = temp_sta->local;
117 	struct ieee80211_hw *hw = &local->hw;
118 	struct sta_info *sta;
119 	u8 *state;
120 
121 	rcu_read_lock();
122 
123 	sta = sta_info_get(local, temp_sta->sta.addr);
124 	if (!sta) {
125 		rcu_read_unlock();
126 		return;
127 	}
128 
129 	state = &sta->ampdu_mlme.tid_state_tx[tid];
130 	/* check if the TID waits for addBA response */
131 	spin_lock_bh(&sta->lock);
132 	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
133 		spin_unlock_bh(&sta->lock);
134 		*state = HT_AGG_STATE_IDLE;
135 #ifdef CONFIG_MAC80211_HT_DEBUG
136 		printk(KERN_DEBUG "timer expired on tid %d but we are not "
137 				"expecting addBA response there", tid);
138 #endif
139 		goto timer_expired_exit;
140 	}
141 
142 #ifdef CONFIG_MAC80211_HT_DEBUG
143 	printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
144 #endif
145 
146 	/* go through the state check in stop_BA_session */
147 	*state = HT_AGG_STATE_OPERATIONAL;
148 	spin_unlock_bh(&sta->lock);
149 	ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid,
150 				     WLAN_BACK_INITIATOR);
151 
152 timer_expired_exit:
153 	rcu_read_unlock();
154 }
155 
156 int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
157 {
158 	struct ieee80211_local *local = hw_to_local(hw);
159 	struct sta_info *sta;
160 	struct ieee80211_sub_if_data *sdata;
161 	u16 start_seq_num;
162 	u8 *state;
163 	int ret = 0;
164 
165 	if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
166 		return -EINVAL;
167 
168 #ifdef CONFIG_MAC80211_HT_DEBUG
169 	printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n",
170 	       ra, tid);
171 #endif /* CONFIG_MAC80211_HT_DEBUG */
172 
173 	rcu_read_lock();
174 
175 	sta = sta_info_get(local, ra);
176 	if (!sta) {
177 #ifdef CONFIG_MAC80211_HT_DEBUG
178 		printk(KERN_DEBUG "Could not find the station\n");
179 #endif
180 		ret = -ENOENT;
181 		goto exit;
182 	}
183 
184 	/*
185 	 * The aggregation code is not prepared to handle
186 	 * anything but STA/AP due to the BSSID handling.
187 	 * IBSS could work in the code but isn't supported
188 	 * by drivers or the standard.
189 	 */
190 	if (sta->sdata->vif.type != NL80211_IFTYPE_STATION &&
191 	    sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
192 	    sta->sdata->vif.type != NL80211_IFTYPE_AP) {
193 		ret = -EINVAL;
194 		goto exit;
195 	}
196 
197 	spin_lock_bh(&sta->lock);
198 
199 	/* we have tried too many times, receiver does not want A-MPDU */
200 	if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
201 		ret = -EBUSY;
202 		goto err_unlock_sta;
203 	}
204 
205 	state = &sta->ampdu_mlme.tid_state_tx[tid];
206 	/* check if the TID is not in aggregation flow already */
207 	if (*state != HT_AGG_STATE_IDLE) {
208 #ifdef CONFIG_MAC80211_HT_DEBUG
209 		printk(KERN_DEBUG "BA request denied - session is not "
210 				 "idle on tid %u\n", tid);
211 #endif /* CONFIG_MAC80211_HT_DEBUG */
212 		ret = -EAGAIN;
213 		goto err_unlock_sta;
214 	}
215 
216 	/* prepare A-MPDU MLME for Tx aggregation */
217 	sta->ampdu_mlme.tid_tx[tid] =
218 			kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
219 	if (!sta->ampdu_mlme.tid_tx[tid]) {
220 #ifdef CONFIG_MAC80211_HT_DEBUG
221 		if (net_ratelimit())
222 			printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
223 					tid);
224 #endif
225 		ret = -ENOMEM;
226 		goto err_unlock_sta;
227 	}
228 	/* Tx timer */
229 	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
230 			sta_addba_resp_timer_expired;
231 	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
232 			(unsigned long)&sta->timer_to_tid[tid];
233 	init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
234 
235 	if (hw->ampdu_queues) {
236 		/* create a new queue for this aggregation */
237 		ret = ieee80211_ht_agg_queue_add(local, sta, tid);
238 
239 		/* case no queue is available to aggregation
240 		 * don't switch to aggregation */
241 		if (ret) {
242 #ifdef CONFIG_MAC80211_HT_DEBUG
243 			printk(KERN_DEBUG "BA request denied - "
244 			       "queue unavailable for tid %d\n", tid);
245 #endif /* CONFIG_MAC80211_HT_DEBUG */
246 			goto err_unlock_queue;
247 		}
248 	}
249 	sdata = sta->sdata;
250 
251 	/* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
252 	 * call back right away, it must see that the flow has begun */
253 	*state |= HT_ADDBA_REQUESTED_MSK;
254 
255 	/* This is slightly racy because the queue isn't stopped */
256 	start_seq_num = sta->tid_seq[tid];
257 
258 	if (local->ops->ampdu_action)
259 		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
260 					       &sta->sta, tid, &start_seq_num);
261 
262 	if (ret) {
263 		/* No need to requeue the packets in the agg queue, since we
264 		 * held the tx lock: no packet could be enqueued to the newly
265 		 * allocated queue */
266 		if (hw->ampdu_queues)
267 			ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
268 #ifdef CONFIG_MAC80211_HT_DEBUG
269 		printk(KERN_DEBUG "BA request denied - HW unavailable for"
270 					" tid %d\n", tid);
271 #endif /* CONFIG_MAC80211_HT_DEBUG */
272 		*state = HT_AGG_STATE_IDLE;
273 		goto err_unlock_queue;
274 	}
275 
276 	/* Will put all the packets in the new SW queue */
277 	if (hw->ampdu_queues)
278 		ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
279 	spin_unlock_bh(&sta->lock);
280 
281 	/* send an addBA request */
282 	sta->ampdu_mlme.dialog_token_allocator++;
283 	sta->ampdu_mlme.tid_tx[tid]->dialog_token =
284 			sta->ampdu_mlme.dialog_token_allocator;
285 	sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
286 
287 
288 	ieee80211_send_addba_request(sta->sdata, ra, tid,
289 			 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
290 			 sta->ampdu_mlme.tid_tx[tid]->ssn,
291 			 0x40, 5000);
292 	/* activate the timer for the recipient's addBA response */
293 	sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
294 				jiffies + ADDBA_RESP_INTERVAL;
295 	add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
296 #ifdef CONFIG_MAC80211_HT_DEBUG
297 	printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
298 #endif
299 	goto exit;
300 
301 err_unlock_queue:
302 	kfree(sta->ampdu_mlme.tid_tx[tid]);
303 	sta->ampdu_mlme.tid_tx[tid] = NULL;
304 	ret = -EBUSY;
305 err_unlock_sta:
306 	spin_unlock_bh(&sta->lock);
307 exit:
308 	rcu_read_unlock();
309 	return ret;
310 }
311 EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
312 
313 void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
314 {
315 	struct ieee80211_local *local = hw_to_local(hw);
316 	struct sta_info *sta;
317 	u8 *state;
318 
319 	if (tid >= STA_TID_NUM) {
320 #ifdef CONFIG_MAC80211_HT_DEBUG
321 		printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
322 				tid, STA_TID_NUM);
323 #endif
324 		return;
325 	}
326 
327 	rcu_read_lock();
328 	sta = sta_info_get(local, ra);
329 	if (!sta) {
330 		rcu_read_unlock();
331 #ifdef CONFIG_MAC80211_HT_DEBUG
332 		printk(KERN_DEBUG "Could not find station: %pM\n", ra);
333 #endif
334 		return;
335 	}
336 
337 	state = &sta->ampdu_mlme.tid_state_tx[tid];
338 	spin_lock_bh(&sta->lock);
339 
340 	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
341 #ifdef CONFIG_MAC80211_HT_DEBUG
342 		printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
343 				*state);
344 #endif
345 		spin_unlock_bh(&sta->lock);
346 		rcu_read_unlock();
347 		return;
348 	}
349 
350 	WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
351 
352 	*state |= HT_ADDBA_DRV_READY_MSK;
353 
354 	if (*state == HT_AGG_STATE_OPERATIONAL) {
355 #ifdef CONFIG_MAC80211_HT_DEBUG
356 		printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
357 #endif
358 		if (hw->ampdu_queues)
359 			ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
360 	}
361 	spin_unlock_bh(&sta->lock);
362 	rcu_read_unlock();
363 }
364 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
365 
366 
367 int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
368 				 u8 *ra, u16 tid,
369 				 enum ieee80211_back_parties initiator)
370 {
371 	struct ieee80211_local *local = hw_to_local(hw);
372 	struct sta_info *sta;
373 	u8 *state;
374 	int ret = 0;
375 
376 	if (tid >= STA_TID_NUM)
377 		return -EINVAL;
378 
379 	rcu_read_lock();
380 	sta = sta_info_get(local, ra);
381 	if (!sta) {
382 		rcu_read_unlock();
383 		return -ENOENT;
384 	}
385 
386 	/* check if the TID is in aggregation */
387 	state = &sta->ampdu_mlme.tid_state_tx[tid];
388 	spin_lock_bh(&sta->lock);
389 
390 	if (*state != HT_AGG_STATE_OPERATIONAL) {
391 		ret = -ENOENT;
392 		goto stop_BA_exit;
393 	}
394 
395 #ifdef CONFIG_MAC80211_HT_DEBUG
396 	printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
397 	       ra, tid);
398 #endif /* CONFIG_MAC80211_HT_DEBUG */
399 
400 	if (hw->ampdu_queues)
401 		ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
402 
403 	*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
404 		(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
405 
406 	if (local->ops->ampdu_action)
407 		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
408 					       &sta->sta, tid, NULL);
409 
410 	/* case HW denied going back to legacy */
411 	if (ret) {
412 		WARN_ON(ret != -EBUSY);
413 		*state = HT_AGG_STATE_OPERATIONAL;
414 		if (hw->ampdu_queues)
415 			ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
416 		goto stop_BA_exit;
417 	}
418 
419 stop_BA_exit:
420 	spin_unlock_bh(&sta->lock);
421 	rcu_read_unlock();
422 	return ret;
423 }
424 EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
425 
426 void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
427 {
428 	struct ieee80211_local *local = hw_to_local(hw);
429 	struct sta_info *sta;
430 	u8 *state;
431 	int agg_queue;
432 
433 	if (tid >= STA_TID_NUM) {
434 #ifdef CONFIG_MAC80211_HT_DEBUG
435 		printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
436 				tid, STA_TID_NUM);
437 #endif
438 		return;
439 	}
440 
441 #ifdef CONFIG_MAC80211_HT_DEBUG
442 	printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n",
443 	       ra, tid);
444 #endif /* CONFIG_MAC80211_HT_DEBUG */
445 
446 	rcu_read_lock();
447 	sta = sta_info_get(local, ra);
448 	if (!sta) {
449 #ifdef CONFIG_MAC80211_HT_DEBUG
450 		printk(KERN_DEBUG "Could not find station: %pM\n", ra);
451 #endif
452 		rcu_read_unlock();
453 		return;
454 	}
455 	state = &sta->ampdu_mlme.tid_state_tx[tid];
456 
457 	/* NOTE: no need to use sta->lock in this state check, as
458 	 * ieee80211_stop_tx_ba_session will let only one stop call to
459 	 * pass through per sta/tid
460 	 */
461 	if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
462 #ifdef CONFIG_MAC80211_HT_DEBUG
463 		printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
464 #endif
465 		rcu_read_unlock();
466 		return;
467 	}
468 
469 	if (*state & HT_AGG_STATE_INITIATOR_MSK)
470 		ieee80211_send_delba(sta->sdata, ra, tid,
471 			WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
472 
473 	if (hw->ampdu_queues) {
474 		agg_queue = sta->tid_to_tx_q[tid];
475 		ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
476 
477 		/* We just requeued the all the frames that were in the
478 		 * removed queue, and since we might miss a softirq we do
479 		 * netif_schedule_queue.  ieee80211_wake_queue is not used
480 		 * here as this queue is not necessarily stopped
481 		 */
482 		netif_schedule_queue(netdev_get_tx_queue(local->mdev,
483 							 agg_queue));
484 	}
485 	spin_lock_bh(&sta->lock);
486 	*state = HT_AGG_STATE_IDLE;
487 	sta->ampdu_mlme.addba_req_num[tid] = 0;
488 	kfree(sta->ampdu_mlme.tid_tx[tid]);
489 	sta->ampdu_mlme.tid_tx[tid] = NULL;
490 	spin_unlock_bh(&sta->lock);
491 
492 	rcu_read_unlock();
493 }
494 EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
495 
496 void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
497 				      const u8 *ra, u16 tid)
498 {
499 	struct ieee80211_local *local = hw_to_local(hw);
500 	struct ieee80211_ra_tid *ra_tid;
501 	struct sk_buff *skb = dev_alloc_skb(0);
502 
503 	if (unlikely(!skb)) {
504 #ifdef CONFIG_MAC80211_HT_DEBUG
505 		if (net_ratelimit())
506 			printk(KERN_WARNING "%s: Not enough memory, "
507 			       "dropping start BA session", skb->dev->name);
508 #endif
509 		return;
510 	}
511 	ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
512 	memcpy(&ra_tid->ra, ra, ETH_ALEN);
513 	ra_tid->tid = tid;
514 
515 	skb->pkt_type = IEEE80211_ADDBA_MSG;
516 	skb_queue_tail(&local->skb_queue, skb);
517 	tasklet_schedule(&local->tasklet);
518 }
519 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
520 
521 void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
522 				     const u8 *ra, u16 tid)
523 {
524 	struct ieee80211_local *local = hw_to_local(hw);
525 	struct ieee80211_ra_tid *ra_tid;
526 	struct sk_buff *skb = dev_alloc_skb(0);
527 
528 	if (unlikely(!skb)) {
529 #ifdef CONFIG_MAC80211_HT_DEBUG
530 		if (net_ratelimit())
531 			printk(KERN_WARNING "%s: Not enough memory, "
532 			       "dropping stop BA session", skb->dev->name);
533 #endif
534 		return;
535 	}
536 	ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
537 	memcpy(&ra_tid->ra, ra, ETH_ALEN);
538 	ra_tid->tid = tid;
539 
540 	skb->pkt_type = IEEE80211_DELBA_MSG;
541 	skb_queue_tail(&local->skb_queue, skb);
542 	tasklet_schedule(&local->tasklet);
543 }
544 EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
545 
546 void ieee80211_process_addba_resp(struct ieee80211_local *local,
547 				  struct sta_info *sta,
548 				  struct ieee80211_mgmt *mgmt,
549 				  size_t len)
550 {
551 	struct ieee80211_hw *hw = &local->hw;
552 	u16 capab;
553 	u16 tid, start_seq_num;
554 	u8 *state;
555 
556 	capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
557 	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
558 
559 	state = &sta->ampdu_mlme.tid_state_tx[tid];
560 
561 	spin_lock_bh(&sta->lock);
562 
563 	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
564 		spin_unlock_bh(&sta->lock);
565 		return;
566 	}
567 
568 	if (mgmt->u.action.u.addba_resp.dialog_token !=
569 		sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
570 		spin_unlock_bh(&sta->lock);
571 #ifdef CONFIG_MAC80211_HT_DEBUG
572 		printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
573 #endif /* CONFIG_MAC80211_HT_DEBUG */
574 		return;
575 	}
576 
577 	del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
578 #ifdef CONFIG_MAC80211_HT_DEBUG
579 	printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
580 #endif /* CONFIG_MAC80211_HT_DEBUG */
581 	if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
582 			== WLAN_STATUS_SUCCESS) {
583 		*state |= HT_ADDBA_RECEIVED_MSK;
584 		sta->ampdu_mlme.addba_req_num[tid] = 0;
585 
586 		if (*state == HT_AGG_STATE_OPERATIONAL &&
587 		    local->hw.ampdu_queues)
588 			ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
589 
590 		if (local->ops->ampdu_action) {
591 			(void)local->ops->ampdu_action(hw,
592 					       IEEE80211_AMPDU_TX_RESUME,
593 					       &sta->sta, tid, &start_seq_num);
594 		}
595 #ifdef CONFIG_MAC80211_HT_DEBUG
596 		printk(KERN_DEBUG "Resuming TX aggregation for tid %d\n", tid);
597 #endif /* CONFIG_MAC80211_HT_DEBUG */
598 		spin_unlock_bh(&sta->lock);
599 	} else {
600 		sta->ampdu_mlme.addba_req_num[tid]++;
601 		/* this will allow the state check in stop_BA_session */
602 		*state = HT_AGG_STATE_OPERATIONAL;
603 		spin_unlock_bh(&sta->lock);
604 		ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid,
605 					     WLAN_BACK_INITIATOR);
606 	}
607 }
608