aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ht.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-03-30 17:53:32 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-30 17:53:32 -0400
commit65fb0d23fcddd8697c871047b700c78817bdaa43 (patch)
tree119e6e5f276622c4c862f6c9b6d795264ba1603a /net/mac80211/ht.c
parent8c083f081d0014057901c68a0a3e0f8ca7ac8d23 (diff)
parentdfbbe89e197a77f2c8046a51c74e33e35f878080 (diff)
Merge branch 'linus' into cpumask-for-linus
Conflicts: arch/x86/kernel/cpu/common.c
Diffstat (limited to 'net/mac80211/ht.c')
-rw-r--r--net/mac80211/ht.c903
1 files changed, 34 insertions, 869 deletions
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index c5c0c5271096..4e3c72f20de7 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -17,8 +17,7 @@
17#include <net/wireless.h> 17#include <net/wireless.h>
18#include <net/mac80211.h> 18#include <net/mac80211.h>
19#include "ieee80211_i.h" 19#include "ieee80211_i.h"
20#include "sta_info.h" 20#include "rate.h"
21#include "wme.h"
22 21
23void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, 22void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
24 struct ieee80211_ht_cap *ht_cap_ie, 23 struct ieee80211_ht_cap *ht_cap_ie,
@@ -95,7 +94,9 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
95{ 94{
96 struct ieee80211_local *local = sdata->local; 95 struct ieee80211_local *local = sdata->local;
97 struct ieee80211_supported_band *sband; 96 struct ieee80211_supported_band *sband;
97 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
98 struct ieee80211_bss_ht_conf ht; 98 struct ieee80211_bss_ht_conf ht;
99 struct sta_info *sta;
99 u32 changed = 0; 100 u32 changed = 0;
100 bool enable_ht = true, ht_changed; 101 bool enable_ht = true, ht_changed;
101 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 102 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
@@ -130,14 +131,25 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
130 } 131 }
131 } 132 }
132 133
133 ht_changed = local->hw.conf.ht.enabled != enable_ht || 134 ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
134 channel_type != local->hw.conf.ht.channel_type; 135 channel_type != local->hw.conf.channel_type;
135 136
136 local->oper_channel_type = channel_type; 137 local->oper_channel_type = channel_type;
137 local->hw.conf.ht.enabled = enable_ht;
138 138
139 if (ht_changed) 139 if (ht_changed) {
140 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); 140 /* channel_type change automatically detected */
141 ieee80211_hw_config(local, 0);
142
143 rcu_read_lock();
144
145 sta = sta_info_get(local, ifmgd->bssid);
146 if (sta)
147 rate_control_rate_update(local, sband, sta,
148 IEEE80211_RC_HT_CHANGED);
149
150 rcu_read_unlock();
151
152 }
141 153
142 /* disable HT */ 154 /* disable HT */
143 if (!enable_ht) 155 if (!enable_ht)
@@ -154,108 +166,22 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
154 return changed; 166 return changed;
155} 167}
156 168
157static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, 169void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta)
158 const u8 *da, u16 tid,
159 u8 dialog_token, u16 start_seq_num,
160 u16 agg_size, u16 timeout)
161{ 170{
162 struct ieee80211_local *local = sdata->local; 171 int i;
163 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
164 struct sk_buff *skb;
165 struct ieee80211_mgmt *mgmt;
166 u16 capab;
167
168 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
169
170 if (!skb) {
171 printk(KERN_ERR "%s: failed to allocate buffer "
172 "for addba request frame\n", sdata->dev->name);
173 return;
174 }
175 skb_reserve(skb, local->hw.extra_tx_headroom);
176 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
177 memset(mgmt, 0, 24);
178 memcpy(mgmt->da, da, ETH_ALEN);
179 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
180 if (sdata->vif.type == NL80211_IFTYPE_AP)
181 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
182 else
183 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
184
185 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
186 IEEE80211_STYPE_ACTION);
187
188 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
189
190 mgmt->u.action.category = WLAN_CATEGORY_BACK;
191 mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
192
193 mgmt->u.action.u.addba_req.dialog_token = dialog_token;
194 capab = (u16)(1 << 1); /* bit 1 aggregation policy */
195 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
196 capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */
197
198 mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
199
200 mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
201 mgmt->u.action.u.addba_req.start_seq_num =
202 cpu_to_le16(start_seq_num << 4);
203
204 ieee80211_tx_skb(sdata, skb, 0);
205}
206
207static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
208 u8 dialog_token, u16 status, u16 policy,
209 u16 buf_size, u16 timeout)
210{
211 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
212 struct ieee80211_local *local = sdata->local;
213 struct sk_buff *skb;
214 struct ieee80211_mgmt *mgmt;
215 u16 capab;
216
217 skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
218 172
219 if (!skb) { 173 for (i = 0; i < STA_TID_NUM; i++) {
220 printk(KERN_DEBUG "%s: failed to allocate buffer " 174 __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR);
221 "for addba resp frame\n", sdata->dev->name); 175 __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
222 return; 176 WLAN_REASON_QSTA_LEAVE_QBSS);
223 } 177 }
224
225 skb_reserve(skb, local->hw.extra_tx_headroom);
226 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
227 memset(mgmt, 0, 24);
228 memcpy(mgmt->da, da, ETH_ALEN);
229 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
230 if (sdata->vif.type == NL80211_IFTYPE_AP)
231 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
232 else
233 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
234 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
235 IEEE80211_STYPE_ACTION);
236
237 skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
238 mgmt->u.action.category = WLAN_CATEGORY_BACK;
239 mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
240 mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
241
242 capab = (u16)(policy << 1); /* bit 1 aggregation policy */
243 capab |= (u16)(tid << 2); /* bit 5:2 TID number */
244 capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
245
246 mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
247 mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
248 mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
249
250 ieee80211_tx_skb(sdata, skb, 0);
251} 178}
252 179
253static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, 180void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
254 const u8 *da, u16 tid, 181 const u8 *da, u16 tid,
255 u16 initiator, u16 reason_code) 182 u16 initiator, u16 reason_code)
256{ 183{
257 struct ieee80211_local *local = sdata->local; 184 struct ieee80211_local *local = sdata->local;
258 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
259 struct sk_buff *skb; 185 struct sk_buff *skb;
260 struct ieee80211_mgmt *mgmt; 186 struct ieee80211_mgmt *mgmt;
261 u16 params; 187 u16 params;
@@ -273,10 +199,12 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
273 memset(mgmt, 0, 24); 199 memset(mgmt, 0, 24);
274 memcpy(mgmt->da, da, ETH_ALEN); 200 memcpy(mgmt->da, da, ETH_ALEN);
275 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 201 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
276 if (sdata->vif.type == NL80211_IFTYPE_AP) 202 if (sdata->vif.type == NL80211_IFTYPE_AP ||
203 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
277 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); 204 memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
278 else 205 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
279 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); 206 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
207
280 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 208 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
281 IEEE80211_STYPE_ACTION); 209 IEEE80211_STYPE_ACTION);
282 210
@@ -290,770 +218,7 @@ static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
290 mgmt->u.action.u.delba.params = cpu_to_le16(params); 218 mgmt->u.action.u.delba.params = cpu_to_le16(params);
291 mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); 219 mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
292 220
293 ieee80211_tx_skb(sdata, skb, 0); 221 ieee80211_tx_skb(sdata, skb, 1);
294}
295
296void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
297{
298 struct ieee80211_local *local = sdata->local;
299 struct sk_buff *skb;
300 struct ieee80211_bar *bar;
301 u16 bar_control = 0;
302
303 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
304 if (!skb) {
305 printk(KERN_ERR "%s: failed to allocate buffer for "
306 "bar frame\n", sdata->dev->name);
307 return;
308 }
309 skb_reserve(skb, local->hw.extra_tx_headroom);
310 bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
311 memset(bar, 0, sizeof(*bar));
312 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
313 IEEE80211_STYPE_BACK_REQ);
314 memcpy(bar->ra, ra, ETH_ALEN);
315 memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
316 bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
317 bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
318 bar_control |= (u16)(tid << 12);
319 bar->control = cpu_to_le16(bar_control);
320 bar->start_seq_num = cpu_to_le16(ssn);
321
322 ieee80211_tx_skb(sdata, skb, 0);
323}
324
325void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid,
326 u16 initiator, u16 reason)
327{
328 struct ieee80211_local *local = sdata->local;
329 struct ieee80211_hw *hw = &local->hw;
330 struct sta_info *sta;
331 int ret, i;
332
333 rcu_read_lock();
334
335 sta = sta_info_get(local, ra);
336 if (!sta) {
337 rcu_read_unlock();
338 return;
339 }
340
341 /* check if TID is in operational state */
342 spin_lock_bh(&sta->lock);
343 if (sta->ampdu_mlme.tid_state_rx[tid]
344 != HT_AGG_STATE_OPERATIONAL) {
345 spin_unlock_bh(&sta->lock);
346 rcu_read_unlock();
347 return;
348 }
349 sta->ampdu_mlme.tid_state_rx[tid] =
350 HT_AGG_STATE_REQ_STOP_BA_MSK |
351 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
352 spin_unlock_bh(&sta->lock);
353
354 /* stop HW Rx aggregation. ampdu_action existence
355 * already verified in session init so we add the BUG_ON */
356 BUG_ON(!local->ops->ampdu_action);
357
358#ifdef CONFIG_MAC80211_HT_DEBUG
359 printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n",
360 ra, tid);
361#endif /* CONFIG_MAC80211_HT_DEBUG */
362
363 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
364 &sta->sta, tid, NULL);
365 if (ret)
366 printk(KERN_DEBUG "HW problem - can not stop rx "
367 "aggregation for tid %d\n", tid);
368
369 /* shutdown timer has not expired */
370 if (initiator != WLAN_BACK_TIMER)
371 del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
372
373 /* check if this is a self generated aggregation halt */
374 if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
375 ieee80211_send_delba(sdata, ra, tid, 0, reason);
376
377 /* free the reordering buffer */
378 for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
379 if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
380 /* release the reordered frames */
381 dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
382 sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
383 sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
384 }
385 }
386 /* free resources */
387 kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
388 kfree(sta->ampdu_mlme.tid_rx[tid]);
389 sta->ampdu_mlme.tid_rx[tid] = NULL;
390 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
391
392 rcu_read_unlock();
393}
394
395
396/*
397 * After sending add Block Ack request we activated a timer until
398 * add Block Ack response will arrive from the recipient.
399 * If this timer expires sta_addba_resp_timer_expired will be executed.
400 */
401static void sta_addba_resp_timer_expired(unsigned long data)
402{
403 /* not an elegant detour, but there is no choice as the timer passes
404 * only one argument, and both sta_info and TID are needed, so init
405 * flow in sta_info_create gives the TID as data, while the timer_to_id
406 * array gives the sta through container_of */
407 u16 tid = *(u8 *)data;
408 struct sta_info *temp_sta = container_of((void *)data,
409 struct sta_info, timer_to_tid[tid]);
410
411 struct ieee80211_local *local = temp_sta->local;
412 struct ieee80211_hw *hw = &local->hw;
413 struct sta_info *sta;
414 u8 *state;
415
416 rcu_read_lock();
417
418 sta = sta_info_get(local, temp_sta->sta.addr);
419 if (!sta) {
420 rcu_read_unlock();
421 return;
422 }
423
424 state = &sta->ampdu_mlme.tid_state_tx[tid];
425 /* check if the TID waits for addBA response */
426 spin_lock_bh(&sta->lock);
427 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
428 spin_unlock_bh(&sta->lock);
429 *state = HT_AGG_STATE_IDLE;
430#ifdef CONFIG_MAC80211_HT_DEBUG
431 printk(KERN_DEBUG "timer expired on tid %d but we are not "
432 "expecting addBA response there", tid);
433#endif
434 goto timer_expired_exit;
435 }
436
437#ifdef CONFIG_MAC80211_HT_DEBUG
438 printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
439#endif
440
441 /* go through the state check in stop_BA_session */
442 *state = HT_AGG_STATE_OPERATIONAL;
443 spin_unlock_bh(&sta->lock);
444 ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid,
445 WLAN_BACK_INITIATOR);
446
447timer_expired_exit:
448 rcu_read_unlock();
449}
450
451void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr)
452{
453 struct ieee80211_local *local = sdata->local;
454 int i;
455
456 for (i = 0; i < STA_TID_NUM; i++) {
457 ieee80211_stop_tx_ba_session(&local->hw, addr, i,
458 WLAN_BACK_INITIATOR);
459 ieee80211_sta_stop_rx_ba_session(sdata, addr, i,
460 WLAN_BACK_RECIPIENT,
461 WLAN_REASON_QSTA_LEAVE_QBSS);
462 }
463}
464
465int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
466{
467 struct ieee80211_local *local = hw_to_local(hw);
468 struct sta_info *sta;
469 struct ieee80211_sub_if_data *sdata;
470 u16 start_seq_num;
471 u8 *state;
472 int ret = 0;
473
474 if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
475 return -EINVAL;
476
477#ifdef CONFIG_MAC80211_HT_DEBUG
478 printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n",
479 ra, tid);
480#endif /* CONFIG_MAC80211_HT_DEBUG */
481
482 rcu_read_lock();
483
484 sta = sta_info_get(local, ra);
485 if (!sta) {
486#ifdef CONFIG_MAC80211_HT_DEBUG
487 printk(KERN_DEBUG "Could not find the station\n");
488#endif
489 ret = -ENOENT;
490 goto exit;
491 }
492
493 spin_lock_bh(&sta->lock);
494
495 /* we have tried too many times, receiver does not want A-MPDU */
496 if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
497 ret = -EBUSY;
498 goto err_unlock_sta;
499 }
500
501 state = &sta->ampdu_mlme.tid_state_tx[tid];
502 /* check if the TID is not in aggregation flow already */
503 if (*state != HT_AGG_STATE_IDLE) {
504#ifdef CONFIG_MAC80211_HT_DEBUG
505 printk(KERN_DEBUG "BA request denied - session is not "
506 "idle on tid %u\n", tid);
507#endif /* CONFIG_MAC80211_HT_DEBUG */
508 ret = -EAGAIN;
509 goto err_unlock_sta;
510 }
511
512 /* prepare A-MPDU MLME for Tx aggregation */
513 sta->ampdu_mlme.tid_tx[tid] =
514 kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
515 if (!sta->ampdu_mlme.tid_tx[tid]) {
516#ifdef CONFIG_MAC80211_HT_DEBUG
517 if (net_ratelimit())
518 printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
519 tid);
520#endif
521 ret = -ENOMEM;
522 goto err_unlock_sta;
523 }
524 /* Tx timer */
525 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
526 sta_addba_resp_timer_expired;
527 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
528 (unsigned long)&sta->timer_to_tid[tid];
529 init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
530
531 if (hw->ampdu_queues) {
532 /* create a new queue for this aggregation */
533 ret = ieee80211_ht_agg_queue_add(local, sta, tid);
534
535 /* case no queue is available to aggregation
536 * don't switch to aggregation */
537 if (ret) {
538#ifdef CONFIG_MAC80211_HT_DEBUG
539 printk(KERN_DEBUG "BA request denied - "
540 "queue unavailable for tid %d\n", tid);
541#endif /* CONFIG_MAC80211_HT_DEBUG */
542 goto err_unlock_queue;
543 }
544 }
545 sdata = sta->sdata;
546
547 /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
548 * call back right away, it must see that the flow has begun */
549 *state |= HT_ADDBA_REQUESTED_MSK;
550
551 /* This is slightly racy because the queue isn't stopped */
552 start_seq_num = sta->tid_seq[tid];
553
554 if (local->ops->ampdu_action)
555 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
556 &sta->sta, tid, &start_seq_num);
557
558 if (ret) {
559 /* No need to requeue the packets in the agg queue, since we
560 * held the tx lock: no packet could be enqueued to the newly
561 * allocated queue */
562 if (hw->ampdu_queues)
563 ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
564#ifdef CONFIG_MAC80211_HT_DEBUG
565 printk(KERN_DEBUG "BA request denied - HW unavailable for"
566 " tid %d\n", tid);
567#endif /* CONFIG_MAC80211_HT_DEBUG */
568 *state = HT_AGG_STATE_IDLE;
569 goto err_unlock_queue;
570 }
571
572 /* Will put all the packets in the new SW queue */
573 if (hw->ampdu_queues)
574 ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
575 spin_unlock_bh(&sta->lock);
576
577 /* send an addBA request */
578 sta->ampdu_mlme.dialog_token_allocator++;
579 sta->ampdu_mlme.tid_tx[tid]->dialog_token =
580 sta->ampdu_mlme.dialog_token_allocator;
581 sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
582
583
584 ieee80211_send_addba_request(sta->sdata, ra, tid,
585 sta->ampdu_mlme.tid_tx[tid]->dialog_token,
586 sta->ampdu_mlme.tid_tx[tid]->ssn,
587 0x40, 5000);
588 /* activate the timer for the recipient's addBA response */
589 sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
590 jiffies + ADDBA_RESP_INTERVAL;
591 add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
592#ifdef CONFIG_MAC80211_HT_DEBUG
593 printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
594#endif
595 goto exit;
596
597err_unlock_queue:
598 kfree(sta->ampdu_mlme.tid_tx[tid]);
599 sta->ampdu_mlme.tid_tx[tid] = NULL;
600 ret = -EBUSY;
601err_unlock_sta:
602 spin_unlock_bh(&sta->lock);
603exit:
604 rcu_read_unlock();
605 return ret;
606}
607EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
608
609int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
610 u8 *ra, u16 tid,
611 enum ieee80211_back_parties initiator)
612{
613 struct ieee80211_local *local = hw_to_local(hw);
614 struct sta_info *sta;
615 u8 *state;
616 int ret = 0;
617
618 if (tid >= STA_TID_NUM)
619 return -EINVAL;
620
621 rcu_read_lock();
622 sta = sta_info_get(local, ra);
623 if (!sta) {
624 rcu_read_unlock();
625 return -ENOENT;
626 }
627
628 /* check if the TID is in aggregation */
629 state = &sta->ampdu_mlme.tid_state_tx[tid];
630 spin_lock_bh(&sta->lock);
631
632 if (*state != HT_AGG_STATE_OPERATIONAL) {
633 ret = -ENOENT;
634 goto stop_BA_exit;
635 }
636
637#ifdef CONFIG_MAC80211_HT_DEBUG
638 printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
639 ra, tid);
640#endif /* CONFIG_MAC80211_HT_DEBUG */
641
642 if (hw->ampdu_queues)
643 ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
644
645 *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
646 (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
647
648 if (local->ops->ampdu_action)
649 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
650 &sta->sta, tid, NULL);
651
652 /* case HW denied going back to legacy */
653 if (ret) {
654 WARN_ON(ret != -EBUSY);
655 *state = HT_AGG_STATE_OPERATIONAL;
656 if (hw->ampdu_queues)
657 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
658 goto stop_BA_exit;
659 }
660
661stop_BA_exit:
662 spin_unlock_bh(&sta->lock);
663 rcu_read_unlock();
664 return ret;
665}
666EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
667
668void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
669{
670 struct ieee80211_local *local = hw_to_local(hw);
671 struct sta_info *sta;
672 u8 *state;
673
674 if (tid >= STA_TID_NUM) {
675#ifdef CONFIG_MAC80211_HT_DEBUG
676 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
677 tid, STA_TID_NUM);
678#endif
679 return;
680 }
681
682 rcu_read_lock();
683 sta = sta_info_get(local, ra);
684 if (!sta) {
685 rcu_read_unlock();
686#ifdef CONFIG_MAC80211_HT_DEBUG
687 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
688#endif
689 return;
690 }
691
692 state = &sta->ampdu_mlme.tid_state_tx[tid];
693 spin_lock_bh(&sta->lock);
694
695 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
696#ifdef CONFIG_MAC80211_HT_DEBUG
697 printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
698 *state);
699#endif
700 spin_unlock_bh(&sta->lock);
701 rcu_read_unlock();
702 return;
703 }
704
705 WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
706
707 *state |= HT_ADDBA_DRV_READY_MSK;
708
709 if (*state == HT_AGG_STATE_OPERATIONAL) {
710#ifdef CONFIG_MAC80211_HT_DEBUG
711 printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
712#endif
713 if (hw->ampdu_queues)
714 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
715 }
716 spin_unlock_bh(&sta->lock);
717 rcu_read_unlock();
718}
719EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
720
721void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
722{
723 struct ieee80211_local *local = hw_to_local(hw);
724 struct sta_info *sta;
725 u8 *state;
726 int agg_queue;
727
728 if (tid >= STA_TID_NUM) {
729#ifdef CONFIG_MAC80211_HT_DEBUG
730 printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
731 tid, STA_TID_NUM);
732#endif
733 return;
734 }
735
736#ifdef CONFIG_MAC80211_HT_DEBUG
737 printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n",
738 ra, tid);
739#endif /* CONFIG_MAC80211_HT_DEBUG */
740
741 rcu_read_lock();
742 sta = sta_info_get(local, ra);
743 if (!sta) {
744#ifdef CONFIG_MAC80211_HT_DEBUG
745 printk(KERN_DEBUG "Could not find station: %pM\n", ra);
746#endif
747 rcu_read_unlock();
748 return;
749 }
750 state = &sta->ampdu_mlme.tid_state_tx[tid];
751
752 /* NOTE: no need to use sta->lock in this state check, as
753 * ieee80211_stop_tx_ba_session will let only one stop call to
754 * pass through per sta/tid
755 */
756 if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
757#ifdef CONFIG_MAC80211_HT_DEBUG
758 printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
759#endif
760 rcu_read_unlock();
761 return;
762 }
763
764 if (*state & HT_AGG_STATE_INITIATOR_MSK)
765 ieee80211_send_delba(sta->sdata, ra, tid,
766 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
767
768 if (hw->ampdu_queues) {
769 agg_queue = sta->tid_to_tx_q[tid];
770 ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
771
772 /* We just requeued the all the frames that were in the
773 * removed queue, and since we might miss a softirq we do
774 * netif_schedule_queue. ieee80211_wake_queue is not used
775 * here as this queue is not necessarily stopped
776 */
777 netif_schedule_queue(netdev_get_tx_queue(local->mdev,
778 agg_queue));
779 }
780 spin_lock_bh(&sta->lock);
781 *state = HT_AGG_STATE_IDLE;
782 sta->ampdu_mlme.addba_req_num[tid] = 0;
783 kfree(sta->ampdu_mlme.tid_tx[tid]);
784 sta->ampdu_mlme.tid_tx[tid] = NULL;
785 spin_unlock_bh(&sta->lock);
786
787 rcu_read_unlock();
788}
789EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
790
791void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
792 const u8 *ra, u16 tid)
793{
794 struct ieee80211_local *local = hw_to_local(hw);
795 struct ieee80211_ra_tid *ra_tid;
796 struct sk_buff *skb = dev_alloc_skb(0);
797
798 if (unlikely(!skb)) {
799#ifdef CONFIG_MAC80211_HT_DEBUG
800 if (net_ratelimit())
801 printk(KERN_WARNING "%s: Not enough memory, "
802 "dropping start BA session", skb->dev->name);
803#endif
804 return;
805 }
806 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
807 memcpy(&ra_tid->ra, ra, ETH_ALEN);
808 ra_tid->tid = tid;
809
810 skb->pkt_type = IEEE80211_ADDBA_MSG;
811 skb_queue_tail(&local->skb_queue, skb);
812 tasklet_schedule(&local->tasklet);
813}
814EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
815
816void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
817 const u8 *ra, u16 tid)
818{
819 struct ieee80211_local *local = hw_to_local(hw);
820 struct ieee80211_ra_tid *ra_tid;
821 struct sk_buff *skb = dev_alloc_skb(0);
822
823 if (unlikely(!skb)) {
824#ifdef CONFIG_MAC80211_HT_DEBUG
825 if (net_ratelimit())
826 printk(KERN_WARNING "%s: Not enough memory, "
827 "dropping stop BA session", skb->dev->name);
828#endif
829 return;
830 }
831 ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
832 memcpy(&ra_tid->ra, ra, ETH_ALEN);
833 ra_tid->tid = tid;
834
835 skb->pkt_type = IEEE80211_DELBA_MSG;
836 skb_queue_tail(&local->skb_queue, skb);
837 tasklet_schedule(&local->tasklet);
838}
839EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
840
841/*
842 * After accepting the AddBA Request we activated a timer,
843 * resetting it after each frame that arrives from the originator.
844 * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
845 */
846static void sta_rx_agg_session_timer_expired(unsigned long data)
847{
848 /* not an elegant detour, but there is no choice as the timer passes
849 * only one argument, and various sta_info are needed here, so init
850 * flow in sta_info_create gives the TID as data, while the timer_to_id
851 * array gives the sta through container_of */
852 u8 *ptid = (u8 *)data;
853 u8 *timer_to_id = ptid - *ptid;
854 struct sta_info *sta = container_of(timer_to_id, struct sta_info,
855 timer_to_tid[0]);
856
857#ifdef CONFIG_MAC80211_HT_DEBUG
858 printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
859#endif
860 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
861 (u16)*ptid, WLAN_BACK_TIMER,
862 WLAN_REASON_QSTA_TIMEOUT);
863}
864
865void ieee80211_process_addba_request(struct ieee80211_local *local,
866 struct sta_info *sta,
867 struct ieee80211_mgmt *mgmt,
868 size_t len)
869{
870 struct ieee80211_hw *hw = &local->hw;
871 struct ieee80211_conf *conf = &hw->conf;
872 struct tid_ampdu_rx *tid_agg_rx;
873 u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
874 u8 dialog_token;
875 int ret = -EOPNOTSUPP;
876
877 /* extract session parameters from addba request frame */
878 dialog_token = mgmt->u.action.u.addba_req.dialog_token;
879 timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
880 start_seq_num =
881 le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
882
883 capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
884 ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
885 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
886 buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
887
888 status = WLAN_STATUS_REQUEST_DECLINED;
889
890 /* sanity check for incoming parameters:
891 * check if configuration can support the BA policy
892 * and if buffer size does not exceeds max value */
893 /* XXX: check own ht delayed BA capability?? */
894 if (((ba_policy != 1)
895 && (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA)))
896 || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
897 status = WLAN_STATUS_INVALID_QOS_PARAM;
898#ifdef CONFIG_MAC80211_HT_DEBUG
899 if (net_ratelimit())
900 printk(KERN_DEBUG "AddBA Req with bad params from "
901 "%pM on tid %u. policy %d, buffer size %d\n",
902 mgmt->sa, tid, ba_policy,
903 buf_size);
904#endif /* CONFIG_MAC80211_HT_DEBUG */
905 goto end_no_lock;
906 }
907 /* determine default buffer size */
908 if (buf_size == 0) {
909 struct ieee80211_supported_band *sband;
910
911 sband = local->hw.wiphy->bands[conf->channel->band];
912 buf_size = IEEE80211_MIN_AMPDU_BUF;
913 buf_size = buf_size << sband->ht_cap.ampdu_factor;
914 }
915
916
917 /* examine state machine */
918 spin_lock_bh(&sta->lock);
919
920 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
921#ifdef CONFIG_MAC80211_HT_DEBUG
922 if (net_ratelimit())
923 printk(KERN_DEBUG "unexpected AddBA Req from "
924 "%pM on tid %u\n",
925 mgmt->sa, tid);
926#endif /* CONFIG_MAC80211_HT_DEBUG */
927 goto end;
928 }
929
930 /* prepare A-MPDU MLME for Rx aggregation */
931 sta->ampdu_mlme.tid_rx[tid] =
932 kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
933 if (!sta->ampdu_mlme.tid_rx[tid]) {
934#ifdef CONFIG_MAC80211_HT_DEBUG
935 if (net_ratelimit())
936 printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
937 tid);
938#endif
939 goto end;
940 }
941 /* rx timer */
942 sta->ampdu_mlme.tid_rx[tid]->session_timer.function =
943 sta_rx_agg_session_timer_expired;
944 sta->ampdu_mlme.tid_rx[tid]->session_timer.data =
945 (unsigned long)&sta->timer_to_tid[tid];
946 init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
947
948 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
949
950 /* prepare reordering buffer */
951 tid_agg_rx->reorder_buf =
952 kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC);
953 if (!tid_agg_rx->reorder_buf) {
954#ifdef CONFIG_MAC80211_HT_DEBUG
955 if (net_ratelimit())
956 printk(KERN_ERR "can not allocate reordering buffer "
957 "to tid %d\n", tid);
958#endif
959 kfree(sta->ampdu_mlme.tid_rx[tid]);
960 goto end;
961 }
962 memset(tid_agg_rx->reorder_buf, 0,
963 buf_size * sizeof(struct sk_buff *));
964
965 if (local->ops->ampdu_action)
966 ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
967 &sta->sta, tid, &start_seq_num);
968#ifdef CONFIG_MAC80211_HT_DEBUG
969 printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
970#endif /* CONFIG_MAC80211_HT_DEBUG */
971
972 if (ret) {
973 kfree(tid_agg_rx->reorder_buf);
974 kfree(tid_agg_rx);
975 sta->ampdu_mlme.tid_rx[tid] = NULL;
976 goto end;
977 }
978
979 /* change state and send addba resp */
980 sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
981 tid_agg_rx->dialog_token = dialog_token;
982 tid_agg_rx->ssn = start_seq_num;
983 tid_agg_rx->head_seq_num = start_seq_num;
984 tid_agg_rx->buf_size = buf_size;
985 tid_agg_rx->timeout = timeout;
986 tid_agg_rx->stored_mpdu_num = 0;
987 status = WLAN_STATUS_SUCCESS;
988end:
989 spin_unlock_bh(&sta->lock);
990
991end_no_lock:
992 ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
993 dialog_token, status, 1, buf_size, timeout);
994}
995
996void ieee80211_process_addba_resp(struct ieee80211_local *local,
997 struct sta_info *sta,
998 struct ieee80211_mgmt *mgmt,
999 size_t len)
1000{
1001 struct ieee80211_hw *hw = &local->hw;
1002 u16 capab;
1003 u16 tid, start_seq_num;
1004 u8 *state;
1005
1006 capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
1007 tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
1008
1009 state = &sta->ampdu_mlme.tid_state_tx[tid];
1010
1011 spin_lock_bh(&sta->lock);
1012
1013 if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
1014 spin_unlock_bh(&sta->lock);
1015 return;
1016 }
1017
1018 if (mgmt->u.action.u.addba_resp.dialog_token !=
1019 sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
1020 spin_unlock_bh(&sta->lock);
1021#ifdef CONFIG_MAC80211_HT_DEBUG
1022 printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
1023#endif /* CONFIG_MAC80211_HT_DEBUG */
1024 return;
1025 }
1026
1027 del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
1028#ifdef CONFIG_MAC80211_HT_DEBUG
1029 printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
1030#endif /* CONFIG_MAC80211_HT_DEBUG */
1031 if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
1032 == WLAN_STATUS_SUCCESS) {
1033 *state |= HT_ADDBA_RECEIVED_MSK;
1034 sta->ampdu_mlme.addba_req_num[tid] = 0;
1035
1036 if (*state == HT_AGG_STATE_OPERATIONAL &&
1037 local->hw.ampdu_queues)
1038 ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
1039
1040 if (local->ops->ampdu_action) {
1041 (void)local->ops->ampdu_action(hw,
1042 IEEE80211_AMPDU_TX_RESUME,
1043 &sta->sta, tid, &start_seq_num);
1044 }
1045#ifdef CONFIG_MAC80211_HT_DEBUG
1046 printk(KERN_DEBUG "Resuming TX aggregation for tid %d\n", tid);
1047#endif /* CONFIG_MAC80211_HT_DEBUG */
1048 spin_unlock_bh(&sta->lock);
1049 } else {
1050 sta->ampdu_mlme.addba_req_num[tid]++;
1051 /* this will allow the state check in stop_BA_session */
1052 *state = HT_AGG_STATE_OPERATIONAL;
1053 spin_unlock_bh(&sta->lock);
1054 ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid,
1055 WLAN_BACK_INITIATOR);
1056 }
1057} 222}
1058 223
1059void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, 224void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,