Merge commit 'v2.6.28-rc9' into x86/apic
[linux-2.6/mini2440.git] / net / mac80211 / ht.c
blobdc7d9a3d70d5ccc450faa96a4728a3cee7500cd0
1 /*
2 * HT handling
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-2008, Intel Corporation
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.
16 #include <linux/ieee80211.h>
17 #include <net/wireless.h>
18 #include <net/mac80211.h>
19 #include "ieee80211_i.h"
20 #include "sta_info.h"
21 #include "wme.h"
23 int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
24 struct ieee80211_ht_info *ht_info)
27 if (ht_info == NULL)
28 return -EINVAL;
30 memset(ht_info, 0, sizeof(*ht_info));
32 if (ht_cap_ie) {
33 u8 ampdu_info = ht_cap_ie->ampdu_params_info;
35 ht_info->ht_supported = 1;
36 ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
37 ht_info->ampdu_factor =
38 ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
39 ht_info->ampdu_density =
40 (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
41 memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
42 } else
43 ht_info->ht_supported = 0;
45 return 0;
48 int ieee80211_ht_addt_info_ie_to_ht_bss_info(
49 struct ieee80211_ht_addt_info *ht_add_info_ie,
50 struct ieee80211_ht_bss_info *bss_info)
52 if (bss_info == NULL)
53 return -EINVAL;
55 memset(bss_info, 0, sizeof(*bss_info));
57 if (ht_add_info_ie) {
58 u16 op_mode;
59 op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
61 bss_info->primary_channel = ht_add_info_ie->control_chan;
62 bss_info->bss_cap = ht_add_info_ie->ht_param;
63 bss_info->bss_op_mode = (u8)(op_mode & 0xff);
66 return 0;
69 static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
70 const u8 *da, u16 tid,
71 u8 dialog_token, u16 start_seq_num,
72 u16 agg_size, u16 timeout)
74 struct ieee80211_local *local = sdata->local;
75 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
76 struct sk_buff *skb;
77 struct ieee80211_mgmt *mgmt;
78 u16 capab;
80 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
82 if (!skb) {
83 printk(KERN_ERR "%s: failed to allocate buffer "
84 "for addba request frame\n", sdata->dev->name);
85 return;
87 skb_reserve(skb, local->hw.extra_tx_headroom);
88 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
89 memset(mgmt, 0, 24);
90 memcpy(mgmt->da, da, ETH_ALEN);
91 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
92 if (sdata->vif.type == NL80211_IFTYPE_AP)
93 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
94 else
95 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
97 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
98 IEEE80211_STYPE_ACTION);
100 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
102 mgmt->u.action.category = WLAN_CATEGORY_BACK;
103 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
105 mgmt->u.action.u.addba_req.dialog_token = dialog_token;
106 capab = (u16)(1 << 1); /* bit 1 aggregation policy */
107 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
108 capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */
110 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
112 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
113 mgmt->u.action.u.addba_req.start_seq_num =
114 cpu_to_le16(start_seq_num << 4);
116 ieee80211_tx_skb(sdata, skb, 0);
119 static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
120 u8 dialog_token, u16 status, u16 policy,
121 u16 buf_size, u16 timeout)
123 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
124 struct ieee80211_local *local = sdata->local;
125 struct sk_buff *skb;
126 struct ieee80211_mgmt *mgmt;
127 u16 capab;
129 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
131 if (!skb) {
132 printk(KERN_DEBUG "%s: failed to allocate buffer "
133 "for addba resp frame\n", sdata->dev->name);
134 return;
137 skb_reserve(skb, local->hw.extra_tx_headroom);
138 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
139 memset(mgmt, 0, 24);
140 memcpy(mgmt->da, da, ETH_ALEN);
141 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
142 if (sdata->vif.type == NL80211_IFTYPE_AP)
143 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
144 else
145 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
146 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
147 IEEE80211_STYPE_ACTION);
149 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
150 mgmt->u.action.category = WLAN_CATEGORY_BACK;
151 mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
152 mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
154 capab = (u16)(policy << 1); /* bit 1 aggregation policy */
155 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
156 capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
158 mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
159 mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
160 mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
162 ieee80211_tx_skb(sdata, skb, 0);
165 static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
166 const u8 *da, u16 tid,
167 u16 initiator, u16 reason_code)
169 struct ieee80211_local *local = sdata->local;
170 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
171 struct sk_buff *skb;
172 struct ieee80211_mgmt *mgmt;
173 u16 params;
175 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
177 if (!skb) {
178 printk(KERN_ERR "%s: failed to allocate buffer "
179 "for delba frame\n", sdata->dev->name);
180 return;
183 skb_reserve(skb, local->hw.extra_tx_headroom);
184 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
185 memset(mgmt, 0, 24);
186 memcpy(mgmt->da, da, ETH_ALEN);
187 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
188 if (sdata->vif.type == NL80211_IFTYPE_AP)
189 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
190 else
191 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
192 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
193 IEEE80211_STYPE_ACTION);
195 skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
197 mgmt->u.action.category = WLAN_CATEGORY_BACK;
198 mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
199 params = (u16)(initiator << 11); /* bit 11 initiator */
200 params |= (u16)(tid << 12); /* bit 15:12 TID number */
202 mgmt->u.action.u.delba.params = cpu_to_le16(params);
203 mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
205 ieee80211_tx_skb(sdata, skb, 0);
208 void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
210 struct ieee80211_local *local = sdata->local;
211 struct sk_buff *skb;
212 struct ieee80211_bar *bar;
213 u16 bar_control = 0;
215 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
216 if (!skb) {
217 printk(KERN_ERR "%s: failed to allocate buffer for "
218 "bar frame\n", sdata->dev->name);
219 return;
221 skb_reserve(skb, local->hw.extra_tx_headroom);
222 bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
223 memset(bar, 0, sizeof(*bar));
224 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
225 IEEE80211_STYPE_BACK_REQ);
226 memcpy(bar->ra, ra, ETH_ALEN);
227 memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
228 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
229 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
230 bar_control |= (u16)(tid << 12);
231 bar->control = cpu_to_le16(bar_control);
232 bar->start_seq_num = cpu_to_le16(ssn);
234 ieee80211_tx_skb(sdata, skb, 0);
237 void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
238 u16 initiator, u16 reason)
240 struct ieee80211_local *local = sdata->local;
241 struct ieee80211_hw *hw = &local->hw;
242 struct sta_info *sta;
243 int ret, i;
244 DECLARE_MAC_BUF(mac);
246 rcu_read_lock();
248 sta = sta_info_get(local, ra);
249 if (!sta) {
250 rcu_read_unlock();
251 return;
254 /* check if TID is in operational state */
255 spin_lock_bh(&sta->lock);
256 if (sta->ampdu_mlme.tid_state_rx[tid]
257 != HT_AGG_STATE_OPERATIONAL) {
258 spin_unlock_bh(&sta->lock);
259 rcu_read_unlock();
260 return;
262 sta->ampdu_mlme.tid_state_rx[tid] =
263 HT_AGG_STATE_REQ_STOP_BA_MSK |
264 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
265 spin_unlock_bh(&sta->lock);
267 /* stop HW Rx aggregation. ampdu_action existence
268 * already verified in session init so we add the BUG_ON */
269 BUG_ON(!local->ops->ampdu_action);
271 #ifdef CONFIG_MAC80211_HT_DEBUG
272 printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
273 print_mac(mac, ra), tid);
274 #endif /* CONFIG_MAC80211_HT_DEBUG */
276 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
277 &sta->sta, tid, NULL);
278 if (ret)
279 printk(KERN_DEBUG "HW problem - can not stop rx "
280 "aggregation for tid %d\n", tid);
282 /* shutdown timer has not expired */
283 if (initiator != WLAN_BACK_TIMER)
284 del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
286 /* check if this is a self generated aggregation halt */
287 if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
288 ieee80211_send_delba(sdata, ra, tid, 0, reason);
290 /* free the reordering buffer */
291 for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
292 if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
293 /* release the reordered frames */
294 dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
295 sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
296 sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
299 /* free resources */
300 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
301 kfree(sta->ampdu_mlme.tid_rx[tid]);
302 sta->ampdu_mlme.tid_rx[tid] = NULL;
303 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
305 rcu_read_unlock();
310 * After sending add Block Ack request we activated a timer until
311 * add Block Ack response will arrive from the recipient.
312 * If this timer expires sta_addba_resp_timer_expired will be executed.
314 static void sta_addba_resp_timer_expired(unsigned long data)
316 /* not an elegant detour, but there is no choice as the timer passes
317 * only one argument, and both sta_info and TID are needed, so init
318 * flow in sta_info_create gives the TID as data, while the timer_to_id
319 * array gives the sta through container_of */
320 u16 tid = *(u8 *)data;
321 struct sta_info *temp_sta = container_of((void *)data,
322 struct sta_info, timer_to_tid[tid]);
324 struct ieee80211_local *local = temp_sta->local;
325 struct ieee80211_hw *hw = &local->hw;
326 struct sta_info *sta;
327 u8 *state;
329 rcu_read_lock();
331 sta = sta_info_get(local, temp_sta->sta.addr);
332 if (!sta) {
333 rcu_read_unlock();
334 return;
337 state = &sta->ampdu_mlme.tid_state_tx[tid];
338 /* check if the TID waits for addBA response */
339 spin_lock_bh(&sta->lock);
340 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
341 spin_unlock_bh(&sta->lock);
342 *state = HT_AGG_STATE_IDLE;
343 #ifdef CONFIG_MAC80211_HT_DEBUG
344 printk(KERN_DEBUG "timer expired on tid %d but we are not "
345 "expecting addBA response there", tid);
346 #endif
347 goto timer_expired_exit;
350 #ifdef CONFIG_MAC80211_HT_DEBUG
351 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
352 #endif
354 /* go through the state check in stop_BA_session */
355 *state = HT_AGG_STATE_OPERATIONAL;
356 spin_unlock_bh(&sta->lock);
357 ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid,
358 WLAN_BACK_INITIATOR);
360 timer_expired_exit:
361 rcu_read_unlock();
364 void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr)
366 struct ieee80211_local *local = sdata->local;
367 int i;
369 for (i = 0; i < STA_TID_NUM; i++) {
370 ieee80211_stop_tx_ba_session(&local->hw, addr, i,
371 WLAN_BACK_INITIATOR);
372 ieee80211_sta_stop_rx_ba_session(sdata, addr, i,
373 WLAN_BACK_RECIPIENT,
374 WLAN_REASON_QSTA_LEAVE_QBSS);
378 int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
380 struct ieee80211_local *local = hw_to_local(hw);
381 struct sta_info *sta;
382 struct ieee80211_sub_if_data *sdata;
383 u16 start_seq_num;
384 u8 *state;
385 int ret;
386 DECLARE_MAC_BUF(mac);
388 if (tid >= STA_TID_NUM)
389 return -EINVAL;
391 #ifdef CONFIG_MAC80211_HT_DEBUG
392 printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
393 print_mac(mac, ra), tid);
394 #endif /* CONFIG_MAC80211_HT_DEBUG */
396 rcu_read_lock();
398 sta = sta_info_get(local, ra);
399 if (!sta) {
400 #ifdef CONFIG_MAC80211_HT_DEBUG
401 printk(KERN_DEBUG "Could not find the station\n");
402 #endif
403 ret = -ENOENT;
404 goto exit;
407 spin_lock_bh(&sta->lock);
409 /* we have tried too many times, receiver does not want A-MPDU */
410 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
411 ret = -EBUSY;
412 goto err_unlock_sta;
415 state = &sta->ampdu_mlme.tid_state_tx[tid];
416 /* check if the TID is not in aggregation flow already */
417 if (*state != HT_AGG_STATE_IDLE) {
418 #ifdef CONFIG_MAC80211_HT_DEBUG
419 printk(KERN_DEBUG "BA request denied - session is not "
420 "idle on tid %u\n", tid);
421 #endif /* CONFIG_MAC80211_HT_DEBUG */
422 ret = -EAGAIN;
423 goto err_unlock_sta;
426 /* prepare A-MPDU MLME for Tx aggregation */
427 sta->ampdu_mlme.tid_tx[tid] =
428 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
429 if (!sta->ampdu_mlme.tid_tx[tid]) {
430 #ifdef CONFIG_MAC80211_HT_DEBUG
431 if (net_ratelimit())
432 printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
433 tid);
434 #endif
435 ret = -ENOMEM;
436 goto err_unlock_sta;
438 /* Tx timer */
439 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
440 sta_addba_resp_timer_expired;
441 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
442 (unsigned long)&sta->timer_to_tid[tid];
443 init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
445 /* create a new queue for this aggregation */
446 ret = ieee80211_ht_agg_queue_add(local, sta, tid);
448 /* case no queue is available to aggregation
449 * don't switch to aggregation */
450 if (ret) {
451 #ifdef CONFIG_MAC80211_HT_DEBUG
452 printk(KERN_DEBUG "BA request denied - queue unavailable for"
453 " tid %d\n", tid);
454 #endif /* CONFIG_MAC80211_HT_DEBUG */
455 goto err_unlock_queue;
457 sdata = sta->sdata;
459 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
460 * call back right away, it must see that the flow has begun */
461 *state |= HT_ADDBA_REQUESTED_MSK;
463 /* This is slightly racy because the queue isn't stopped */
464 start_seq_num = sta->tid_seq[tid];
466 if (local->ops->ampdu_action)
467 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
468 &sta->sta, tid, &start_seq_num);
470 if (ret) {
471 /* No need to requeue the packets in the agg queue, since we
472 * held the tx lock: no packet could be enqueued to the newly
473 * allocated queue */
474 ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
475 #ifdef CONFIG_MAC80211_HT_DEBUG
476 printk(KERN_DEBUG "BA request denied - HW unavailable for"
477 " tid %d\n", tid);
478 #endif /* CONFIG_MAC80211_HT_DEBUG */
479 *state = HT_AGG_STATE_IDLE;
480 goto err_unlock_queue;
483 /* Will put all the packets in the new SW queue */
484 ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
485 spin_unlock_bh(&sta->lock);
487 /* send an addBA request */
488 sta->ampdu_mlme.dialog_token_allocator++;
489 sta->ampdu_mlme.tid_tx[tid]->dialog_token =
490 sta->ampdu_mlme.dialog_token_allocator;
491 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
494 ieee80211_send_addba_request(sta->sdata, ra, tid,
495 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
496 sta->ampdu_mlme.tid_tx[tid]->ssn,
497 0x40, 5000);
498 /* activate the timer for the recipient's addBA response */
499 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
500 jiffies + ADDBA_RESP_INTERVAL;
501 add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
502 #ifdef CONFIG_MAC80211_HT_DEBUG
503 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
504 #endif
505 goto exit;
507 err_unlock_queue:
508 kfree(sta->ampdu_mlme.tid_tx[tid]);
509 sta->ampdu_mlme.tid_tx[tid] = NULL;
510 ret = -EBUSY;
511 err_unlock_sta:
512 spin_unlock_bh(&sta->lock);
513 exit:
514 rcu_read_unlock();
515 return ret;
517 EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
519 int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
520 u8 *ra, u16 tid,
521 enum ieee80211_back_parties initiator)
523 struct ieee80211_local *local = hw_to_local(hw);
524 struct sta_info *sta;
525 u8 *state;
526 int ret = 0;
527 DECLARE_MAC_BUF(mac);
529 if (tid >= STA_TID_NUM)
530 return -EINVAL;
532 rcu_read_lock();
533 sta = sta_info_get(local, ra);
534 if (!sta) {
535 rcu_read_unlock();
536 return -ENOENT;
539 /* check if the TID is in aggregation */
540 state = &sta->ampdu_mlme.tid_state_tx[tid];
541 spin_lock_bh(&sta->lock);
543 if (*state != HT_AGG_STATE_OPERATIONAL) {
544 ret = -ENOENT;
545 goto stop_BA_exit;
548 #ifdef CONFIG_MAC80211_HT_DEBUG
549 printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
550 print_mac(mac, ra), tid);
551 #endif /* CONFIG_MAC80211_HT_DEBUG */
553 ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
555 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
556 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
558 if (local->ops->ampdu_action)
559 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
560 &sta->sta, tid, NULL);
562 /* case HW denied going back to legacy */
563 if (ret) {
564 WARN_ON(ret != -EBUSY);
565 *state = HT_AGG_STATE_OPERATIONAL;
566 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
567 goto stop_BA_exit;
570 stop_BA_exit:
571 spin_unlock_bh(&sta->lock);
572 rcu_read_unlock();
573 return ret;
575 EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
577 void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
579 struct ieee80211_local *local = hw_to_local(hw);
580 struct sta_info *sta;
581 u8 *state;
582 DECLARE_MAC_BUF(mac);
584 if (tid >= STA_TID_NUM) {
585 #ifdef CONFIG_MAC80211_HT_DEBUG
586 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
587 tid, STA_TID_NUM);
588 #endif
589 return;
592 rcu_read_lock();
593 sta = sta_info_get(local, ra);
594 if (!sta) {
595 rcu_read_unlock();
596 #ifdef CONFIG_MAC80211_HT_DEBUG
597 printk(KERN_DEBUG "Could not find station: %s\n",
598 print_mac(mac, ra));
599 #endif
600 return;
603 state = &sta->ampdu_mlme.tid_state_tx[tid];
604 spin_lock_bh(&sta->lock);
606 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
607 #ifdef CONFIG_MAC80211_HT_DEBUG
608 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
609 *state);
610 #endif
611 spin_unlock_bh(&sta->lock);
612 rcu_read_unlock();
613 return;
616 WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
618 *state |= HT_ADDBA_DRV_READY_MSK;
620 if (*state == HT_AGG_STATE_OPERATIONAL) {
621 #ifdef CONFIG_MAC80211_HT_DEBUG
622 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
623 #endif
624 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
626 spin_unlock_bh(&sta->lock);
627 rcu_read_unlock();
629 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
631 void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
633 struct ieee80211_local *local = hw_to_local(hw);
634 struct sta_info *sta;
635 u8 *state;
636 int agg_queue;
637 DECLARE_MAC_BUF(mac);
639 if (tid >= STA_TID_NUM) {
640 #ifdef CONFIG_MAC80211_HT_DEBUG
641 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
642 tid, STA_TID_NUM);
643 #endif
644 return;
647 #ifdef CONFIG_MAC80211_HT_DEBUG
648 printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
649 print_mac(mac, ra), tid);
650 #endif /* CONFIG_MAC80211_HT_DEBUG */
652 rcu_read_lock();
653 sta = sta_info_get(local, ra);
654 if (!sta) {
655 #ifdef CONFIG_MAC80211_HT_DEBUG
656 printk(KERN_DEBUG "Could not find station: %s\n",
657 print_mac(mac, ra));
658 #endif
659 rcu_read_unlock();
660 return;
662 state = &sta->ampdu_mlme.tid_state_tx[tid];
664 /* NOTE: no need to use sta->lock in this state check, as
665 * ieee80211_stop_tx_ba_session will let only one stop call to
666 * pass through per sta/tid
668 if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
669 #ifdef CONFIG_MAC80211_HT_DEBUG
670 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
671 #endif
672 rcu_read_unlock();
673 return;
676 if (*state & HT_AGG_STATE_INITIATOR_MSK)
677 ieee80211_send_delba(sta->sdata, ra, tid,
678 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
680 agg_queue = sta->tid_to_tx_q[tid];
682 ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
684 /* We just requeued the all the frames that were in the
685 * removed queue, and since we might miss a softirq we do
686 * netif_schedule_queue. ieee80211_wake_queue is not used
687 * here as this queue is not necessarily stopped
689 netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
690 spin_lock_bh(&sta->lock);
691 *state = HT_AGG_STATE_IDLE;
692 sta->ampdu_mlme.addba_req_num[tid] = 0;
693 kfree(sta->ampdu_mlme.tid_tx[tid]);
694 sta->ampdu_mlme.tid_tx[tid] = NULL;
695 spin_unlock_bh(&sta->lock);
697 rcu_read_unlock();
699 EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
701 void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
702 const u8 *ra, u16 tid)
704 struct ieee80211_local *local = hw_to_local(hw);
705 struct ieee80211_ra_tid *ra_tid;
706 struct sk_buff *skb = dev_alloc_skb(0);
708 if (unlikely(!skb)) {
709 #ifdef CONFIG_MAC80211_HT_DEBUG
710 if (net_ratelimit())
711 printk(KERN_WARNING "%s: Not enough memory, "
712 "dropping start BA session", skb->dev->name);
713 #endif
714 return;
716 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
717 memcpy(&ra_tid->ra, ra, ETH_ALEN);
718 ra_tid->tid = tid;
720 skb->pkt_type = IEEE80211_ADDBA_MSG;
721 skb_queue_tail(&local->skb_queue, skb);
722 tasklet_schedule(&local->tasklet);
724 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
726 void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
727 const u8 *ra, u16 tid)
729 struct ieee80211_local *local = hw_to_local(hw);
730 struct ieee80211_ra_tid *ra_tid;
731 struct sk_buff *skb = dev_alloc_skb(0);
733 if (unlikely(!skb)) {
734 #ifdef CONFIG_MAC80211_HT_DEBUG
735 if (net_ratelimit())
736 printk(KERN_WARNING "%s: Not enough memory, "
737 "dropping stop BA session", skb->dev->name);
738 #endif
739 return;
741 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
742 memcpy(&ra_tid->ra, ra, ETH_ALEN);
743 ra_tid->tid = tid;
745 skb->pkt_type = IEEE80211_DELBA_MSG;
746 skb_queue_tail(&local->skb_queue, skb);
747 tasklet_schedule(&local->tasklet);
749 EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
752 * After accepting the AddBA Request we activated a timer,
753 * resetting it after each frame that arrives from the originator.
754 * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
756 static void sta_rx_agg_session_timer_expired(unsigned long data)
758 /* not an elegant detour, but there is no choice as the timer passes
759 * only one argument, and various sta_info are needed here, so init
760 * flow in sta_info_create gives the TID as data, while the timer_to_id
761 * array gives the sta through container_of */
762 u8 *ptid = (u8 *)data;
763 u8 *timer_to_id = ptid - *ptid;
764 struct sta_info *sta = container_of(timer_to_id, struct sta_info,
765 timer_to_tid[0]);
767 #ifdef CONFIG_MAC80211_HT_DEBUG
768 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
769 #endif
770 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
771 (u16)*ptid, WLAN_BACK_TIMER,
772 WLAN_REASON_QSTA_TIMEOUT);
775 void ieee80211_process_addba_request(struct ieee80211_local *local,
776 struct sta_info *sta,
777 struct ieee80211_mgmt *mgmt,
778 size_t len)
780 struct ieee80211_hw *hw = &local->hw;
781 struct ieee80211_conf *conf = &hw->conf;
782 struct tid_ampdu_rx *tid_agg_rx;
783 u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
784 u8 dialog_token;
785 int ret = -EOPNOTSUPP;
786 DECLARE_MAC_BUF(mac);
788 /* extract session parameters from addba request frame */
789 dialog_token = mgmt->u.action.u.addba_req.dialog_token;
790 timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
791 start_seq_num =
792 le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
794 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
795 ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
796 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
797 buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
799 status = WLAN_STATUS_REQUEST_DECLINED;
801 /* sanity check for incoming parameters:
802 * check if configuration can support the BA policy
803 * and if buffer size does not exceeds max value */
804 if (((ba_policy != 1)
805 && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
806 || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
807 status = WLAN_STATUS_INVALID_QOS_PARAM;
808 #ifdef CONFIG_MAC80211_HT_DEBUG
809 if (net_ratelimit())
810 printk(KERN_DEBUG "AddBA Req with bad params from "
811 "%s on tid %u. policy %d, buffer size %d\n",
812 print_mac(mac, mgmt->sa), tid, ba_policy,
813 buf_size);
814 #endif /* CONFIG_MAC80211_HT_DEBUG */
815 goto end_no_lock;
817 /* determine default buffer size */
818 if (buf_size == 0) {
819 struct ieee80211_supported_band *sband;
821 sband = local->hw.wiphy->bands[conf->channel->band];
822 buf_size = IEEE80211_MIN_AMPDU_BUF;
823 buf_size = buf_size << sband->ht_info.ampdu_factor;
827 /* examine state machine */
828 spin_lock_bh(&sta->lock);
830 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
831 #ifdef CONFIG_MAC80211_HT_DEBUG
832 if (net_ratelimit())
833 printk(KERN_DEBUG "unexpected AddBA Req from "
834 "%s on tid %u\n",
835 print_mac(mac, mgmt->sa), tid);
836 #endif /* CONFIG_MAC80211_HT_DEBUG */
837 goto end;
840 /* prepare A-MPDU MLME for Rx aggregation */
841 sta->ampdu_mlme.tid_rx[tid] =
842 kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
843 if (!sta->ampdu_mlme.tid_rx[tid]) {
844 #ifdef CONFIG_MAC80211_HT_DEBUG
845 if (net_ratelimit())
846 printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
847 tid);
848 #endif
849 goto end;
851 /* rx timer */
852 sta->ampdu_mlme.tid_rx[tid]->session_timer.function =
853 sta_rx_agg_session_timer_expired;
854 sta->ampdu_mlme.tid_rx[tid]->session_timer.data =
855 (unsigned long)&sta->timer_to_tid[tid];
856 init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
858 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
860 /* prepare reordering buffer */
861 tid_agg_rx->reorder_buf =
862 kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC);
863 if (!tid_agg_rx->reorder_buf) {
864 #ifdef CONFIG_MAC80211_HT_DEBUG
865 if (net_ratelimit())
866 printk(KERN_ERR "can not allocate reordering buffer "
867 "to tid %d\n", tid);
868 #endif
869 kfree(sta->ampdu_mlme.tid_rx[tid]);
870 goto end;
872 memset(tid_agg_rx->reorder_buf, 0,
873 buf_size * sizeof(struct sk_buff *));
875 if (local->ops->ampdu_action)
876 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
877 &sta->sta, tid, &start_seq_num);
878 #ifdef CONFIG_MAC80211_HT_DEBUG
879 printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
880 #endif /* CONFIG_MAC80211_HT_DEBUG */
882 if (ret) {
883 kfree(tid_agg_rx->reorder_buf);
884 kfree(tid_agg_rx);
885 sta->ampdu_mlme.tid_rx[tid] = NULL;
886 goto end;
889 /* change state and send addba resp */
890 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
891 tid_agg_rx->dialog_token = dialog_token;
892 tid_agg_rx->ssn = start_seq_num;
893 tid_agg_rx->head_seq_num = start_seq_num;
894 tid_agg_rx->buf_size = buf_size;
895 tid_agg_rx->timeout = timeout;
896 tid_agg_rx->stored_mpdu_num = 0;
897 status = WLAN_STATUS_SUCCESS;
898 end:
899 spin_unlock_bh(&sta->lock);
901 end_no_lock:
902 ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
903 dialog_token, status, 1, buf_size, timeout);
906 void ieee80211_process_addba_resp(struct ieee80211_local *local,
907 struct sta_info *sta,
908 struct ieee80211_mgmt *mgmt,
909 size_t len)
911 struct ieee80211_hw *hw = &local->hw;
912 u16 capab;
913 u16 tid;
914 u8 *state;
916 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
917 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
919 state = &sta->ampdu_mlme.tid_state_tx[tid];
921 spin_lock_bh(&sta->lock);
923 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
924 spin_unlock_bh(&sta->lock);
925 return;
928 if (mgmt->u.action.u.addba_resp.dialog_token !=
929 sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
930 spin_unlock_bh(&sta->lock);
931 #ifdef CONFIG_MAC80211_HT_DEBUG
932 printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
933 #endif /* CONFIG_MAC80211_HT_DEBUG */
934 return;
937 del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
938 #ifdef CONFIG_MAC80211_HT_DEBUG
939 printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
940 #endif /* CONFIG_MAC80211_HT_DEBUG */
941 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
942 == WLAN_STATUS_SUCCESS) {
943 *state |= HT_ADDBA_RECEIVED_MSK;
944 sta->ampdu_mlme.addba_req_num[tid] = 0;
946 if (*state == HT_AGG_STATE_OPERATIONAL)
947 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
949 spin_unlock_bh(&sta->lock);
950 } else {
951 sta->ampdu_mlme.addba_req_num[tid]++;
952 /* this will allow the state check in stop_BA_session */
953 *state = HT_AGG_STATE_OPERATIONAL;
954 spin_unlock_bh(&sta->lock);
955 ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid,
956 WLAN_BACK_INITIATOR);
960 void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
961 struct sta_info *sta,
962 struct ieee80211_mgmt *mgmt, size_t len)
964 struct ieee80211_local *local = sdata->local;
965 u16 tid, params;
966 u16 initiator;
967 DECLARE_MAC_BUF(mac);
969 params = le16_to_cpu(mgmt->u.action.u.delba.params);
970 tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
971 initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
973 #ifdef CONFIG_MAC80211_HT_DEBUG
974 if (net_ratelimit())
975 printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n",
976 print_mac(mac, mgmt->sa),
977 initiator ? "initiator" : "recipient", tid,
978 mgmt->u.action.u.delba.reason_code);
979 #endif /* CONFIG_MAC80211_HT_DEBUG */
981 if (initiator == WLAN_BACK_INITIATOR)
982 ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid,
983 WLAN_BACK_INITIATOR, 0);
984 else { /* WLAN_BACK_RECIPIENT */
985 spin_lock_bh(&sta->lock);
986 sta->ampdu_mlme.tid_state_tx[tid] =
987 HT_AGG_STATE_OPERATIONAL;
988 spin_unlock_bh(&sta->lock);
989 ieee80211_stop_tx_ba_session(&local->hw, sta->sta.addr, tid,
990 WLAN_BACK_RECIPIENT);