diff options
Diffstat (limited to 'net/mac80211/ht.c')
-rw-r--r-- | net/mac80211/ht.c | 265 |
1 files changed, 181 insertions, 84 deletions
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index dc7d9a3d70d5..5f510a13b9f0 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -20,50 +20,138 @@ | |||
20 | #include "sta_info.h" | 20 | #include "sta_info.h" |
21 | #include "wme.h" | 21 | #include "wme.h" |
22 | 22 | ||
23 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | 23 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, |
24 | struct ieee80211_ht_info *ht_info) | 24 | struct ieee80211_ht_cap *ht_cap_ie, |
25 | struct ieee80211_sta_ht_cap *ht_cap) | ||
25 | { | 26 | { |
27 | u8 ampdu_info, tx_mcs_set_cap; | ||
28 | int i, max_tx_streams; | ||
26 | 29 | ||
27 | if (ht_info == NULL) | 30 | BUG_ON(!ht_cap); |
28 | return -EINVAL; | 31 | |
32 | memset(ht_cap, 0, sizeof(*ht_cap)); | ||
33 | |||
34 | if (!ht_cap_ie) | ||
35 | return; | ||
36 | |||
37 | ht_cap->ht_supported = true; | ||
29 | 38 | ||
30 | memset(ht_info, 0, sizeof(*ht_info)); | 39 | ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) & sband->ht_cap.cap; |
40 | ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
41 | ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS; | ||
31 | 42 | ||
32 | if (ht_cap_ie) { | 43 | ampdu_info = ht_cap_ie->ampdu_params_info; |
33 | u8 ampdu_info = ht_cap_ie->ampdu_params_info; | 44 | ht_cap->ampdu_factor = |
45 | ampdu_info & IEEE80211_HT_AMPDU_PARM_FACTOR; | ||
46 | ht_cap->ampdu_density = | ||
47 | (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; | ||
34 | 48 | ||
35 | ht_info->ht_supported = 1; | 49 | /* own MCS TX capabilities */ |
36 | ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); | 50 | tx_mcs_set_cap = sband->ht_cap.mcs.tx_params; |
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; | ||
44 | 51 | ||
45 | return 0; | 52 | /* can we TX with MCS rates? */ |
53 | if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED)) | ||
54 | return; | ||
55 | |||
56 | /* Counting from 0, therefore +1 */ | ||
57 | if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF) | ||
58 | max_tx_streams = | ||
59 | ((tx_mcs_set_cap & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) | ||
60 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; | ||
61 | else | ||
62 | max_tx_streams = IEEE80211_HT_MCS_TX_MAX_STREAMS; | ||
63 | |||
64 | /* | ||
65 | * 802.11n D5.0 20.3.5 / 20.6 says: | ||
66 | * - indices 0 to 7 and 32 are single spatial stream | ||
67 | * - 8 to 31 are multiple spatial streams using equal modulation | ||
68 | * [8..15 for two streams, 16..23 for three and 24..31 for four] | ||
69 | * - remainder are multiple spatial streams using unequal modulation | ||
70 | */ | ||
71 | for (i = 0; i < max_tx_streams; i++) | ||
72 | ht_cap->mcs.rx_mask[i] = | ||
73 | sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i]; | ||
74 | |||
75 | if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) | ||
76 | for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; | ||
77 | i < IEEE80211_HT_MCS_MASK_LEN; i++) | ||
78 | ht_cap->mcs.rx_mask[i] = | ||
79 | sband->ht_cap.mcs.rx_mask[i] & | ||
80 | ht_cap_ie->mcs.rx_mask[i]; | ||
81 | |||
82 | /* handle MCS rate 32 too */ | ||
83 | if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) | ||
84 | ht_cap->mcs.rx_mask[32/8] |= 1; | ||
46 | } | 85 | } |
47 | 86 | ||
48 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | 87 | /* |
49 | struct ieee80211_ht_addt_info *ht_add_info_ie, | 88 | * ieee80211_enable_ht should be called only after the operating band |
50 | struct ieee80211_ht_bss_info *bss_info) | 89 | * has been determined as ht configuration depends on the hw's |
90 | * HT abilities for a specific band. | ||
91 | */ | ||
92 | u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | ||
93 | struct ieee80211_ht_info *hti, | ||
94 | u16 ap_ht_cap_flags) | ||
51 | { | 95 | { |
52 | if (bss_info == NULL) | 96 | struct ieee80211_local *local = sdata->local; |
53 | return -EINVAL; | 97 | struct ieee80211_supported_band *sband; |
98 | struct ieee80211_bss_ht_conf ht; | ||
99 | u32 changed = 0; | ||
100 | bool enable_ht = true, ht_changed; | ||
101 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
102 | |||
103 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
104 | |||
105 | memset(&ht, 0, sizeof(ht)); | ||
106 | |||
107 | /* HT is not supported */ | ||
108 | if (!sband->ht_cap.ht_supported) | ||
109 | enable_ht = false; | ||
110 | |||
111 | /* check that channel matches the right operating channel */ | ||
112 | if (local->hw.conf.channel->center_freq != | ||
113 | ieee80211_channel_to_frequency(hti->control_chan)) | ||
114 | enable_ht = false; | ||
115 | |||
116 | if (enable_ht) { | ||
117 | channel_type = NL80211_CHAN_HT20; | ||
118 | |||
119 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
120 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && | ||
121 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | ||
122 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
123 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
124 | channel_type = NL80211_CHAN_HT40PLUS; | ||
125 | break; | ||
126 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
127 | channel_type = NL80211_CHAN_HT40MINUS; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
133 | ht_changed = local->hw.conf.ht.enabled != enable_ht || | ||
134 | channel_type != local->hw.conf.ht.channel_type; | ||
135 | |||
136 | local->oper_channel_type = channel_type; | ||
137 | local->hw.conf.ht.enabled = enable_ht; | ||
54 | 138 | ||
55 | memset(bss_info, 0, sizeof(*bss_info)); | 139 | if (ht_changed) |
140 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | ||
56 | 141 | ||
57 | if (ht_add_info_ie) { | 142 | /* disable HT */ |
58 | u16 op_mode; | 143 | if (!enable_ht) |
59 | op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); | 144 | return 0; |
60 | 145 | ||
61 | bss_info->primary_channel = ht_add_info_ie->control_chan; | 146 | ht.operation_mode = le16_to_cpu(hti->operation_mode); |
62 | bss_info->bss_cap = ht_add_info_ie->ht_param; | 147 | |
63 | bss_info->bss_op_mode = (u8)(op_mode & 0xff); | 148 | /* if bss configuration changed store the new one */ |
149 | if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) { | ||
150 | changed |= BSS_CHANGED_HT; | ||
151 | sdata->vif.bss_conf.ht = ht; | ||
64 | } | 152 | } |
65 | 153 | ||
66 | return 0; | 154 | return changed; |
67 | } | 155 | } |
68 | 156 | ||
69 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | 157 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, |
@@ -241,7 +329,6 @@ void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *r | |||
241 | struct ieee80211_hw *hw = &local->hw; | 329 | struct ieee80211_hw *hw = &local->hw; |
242 | struct sta_info *sta; | 330 | struct sta_info *sta; |
243 | int ret, i; | 331 | int ret, i; |
244 | DECLARE_MAC_BUF(mac); | ||
245 | 332 | ||
246 | rcu_read_lock(); | 333 | rcu_read_lock(); |
247 | 334 | ||
@@ -269,8 +356,8 @@ void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *r | |||
269 | BUG_ON(!local->ops->ampdu_action); | 356 | BUG_ON(!local->ops->ampdu_action); |
270 | 357 | ||
271 | #ifdef CONFIG_MAC80211_HT_DEBUG | 358 | #ifdef CONFIG_MAC80211_HT_DEBUG |
272 | printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", | 359 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", |
273 | print_mac(mac, ra), tid); | 360 | ra, tid); |
274 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 361 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
275 | 362 | ||
276 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | 363 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, |
@@ -383,14 +470,13 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
383 | u16 start_seq_num; | 470 | u16 start_seq_num; |
384 | u8 *state; | 471 | u8 *state; |
385 | int ret; | 472 | int ret; |
386 | DECLARE_MAC_BUF(mac); | ||
387 | 473 | ||
388 | if (tid >= STA_TID_NUM) | 474 | if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) |
389 | return -EINVAL; | 475 | return -EINVAL; |
390 | 476 | ||
391 | #ifdef CONFIG_MAC80211_HT_DEBUG | 477 | #ifdef CONFIG_MAC80211_HT_DEBUG |
392 | printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", | 478 | printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", |
393 | print_mac(mac, ra), tid); | 479 | ra, tid); |
394 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 480 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
395 | 481 | ||
396 | rcu_read_lock(); | 482 | rcu_read_lock(); |
@@ -442,17 +528,19 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
442 | (unsigned long)&sta->timer_to_tid[tid]; | 528 | (unsigned long)&sta->timer_to_tid[tid]; |
443 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 529 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
444 | 530 | ||
445 | /* create a new queue for this aggregation */ | 531 | if (hw->ampdu_queues) { |
446 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | 532 | /* create a new queue for this aggregation */ |
533 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
447 | 534 | ||
448 | /* case no queue is available to aggregation | 535 | /* case no queue is available to aggregation |
449 | * don't switch to aggregation */ | 536 | * don't switch to aggregation */ |
450 | if (ret) { | 537 | if (ret) { |
451 | #ifdef CONFIG_MAC80211_HT_DEBUG | 538 | #ifdef CONFIG_MAC80211_HT_DEBUG |
452 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | 539 | printk(KERN_DEBUG "BA request denied - " |
453 | " tid %d\n", tid); | 540 | "queue unavailable for tid %d\n", tid); |
454 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 541 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
455 | goto err_unlock_queue; | 542 | goto err_unlock_queue; |
543 | } | ||
456 | } | 544 | } |
457 | sdata = sta->sdata; | 545 | sdata = sta->sdata; |
458 | 546 | ||
@@ -471,7 +559,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
471 | /* No need to requeue the packets in the agg queue, since we | 559 | /* 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 | 560 | * held the tx lock: no packet could be enqueued to the newly |
473 | * allocated queue */ | 561 | * allocated queue */ |
474 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | 562 | if (hw->ampdu_queues) |
563 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
475 | #ifdef CONFIG_MAC80211_HT_DEBUG | 564 | #ifdef CONFIG_MAC80211_HT_DEBUG |
476 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | 565 | printk(KERN_DEBUG "BA request denied - HW unavailable for" |
477 | " tid %d\n", tid); | 566 | " tid %d\n", tid); |
@@ -481,7 +570,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
481 | } | 570 | } |
482 | 571 | ||
483 | /* Will put all the packets in the new SW queue */ | 572 | /* Will put all the packets in the new SW queue */ |
484 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | 573 | if (hw->ampdu_queues) |
574 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
485 | spin_unlock_bh(&sta->lock); | 575 | spin_unlock_bh(&sta->lock); |
486 | 576 | ||
487 | /* send an addBA request */ | 577 | /* send an addBA request */ |
@@ -524,7 +614,6 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
524 | struct sta_info *sta; | 614 | struct sta_info *sta; |
525 | u8 *state; | 615 | u8 *state; |
526 | int ret = 0; | 616 | int ret = 0; |
527 | DECLARE_MAC_BUF(mac); | ||
528 | 617 | ||
529 | if (tid >= STA_TID_NUM) | 618 | if (tid >= STA_TID_NUM) |
530 | return -EINVAL; | 619 | return -EINVAL; |
@@ -546,11 +635,12 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
546 | } | 635 | } |
547 | 636 | ||
548 | #ifdef CONFIG_MAC80211_HT_DEBUG | 637 | #ifdef CONFIG_MAC80211_HT_DEBUG |
549 | printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", | 638 | printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n", |
550 | print_mac(mac, ra), tid); | 639 | ra, tid); |
551 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 640 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
552 | 641 | ||
553 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | 642 | if (hw->ampdu_queues) |
643 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | ||
554 | 644 | ||
555 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | 645 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | |
556 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 646 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
@@ -563,7 +653,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
563 | if (ret) { | 653 | if (ret) { |
564 | WARN_ON(ret != -EBUSY); | 654 | WARN_ON(ret != -EBUSY); |
565 | *state = HT_AGG_STATE_OPERATIONAL; | 655 | *state = HT_AGG_STATE_OPERATIONAL; |
566 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 656 | if (hw->ampdu_queues) |
657 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
567 | goto stop_BA_exit; | 658 | goto stop_BA_exit; |
568 | } | 659 | } |
569 | 660 | ||
@@ -579,7 +670,6 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
579 | struct ieee80211_local *local = hw_to_local(hw); | 670 | struct ieee80211_local *local = hw_to_local(hw); |
580 | struct sta_info *sta; | 671 | struct sta_info *sta; |
581 | u8 *state; | 672 | u8 *state; |
582 | DECLARE_MAC_BUF(mac); | ||
583 | 673 | ||
584 | if (tid >= STA_TID_NUM) { | 674 | if (tid >= STA_TID_NUM) { |
585 | #ifdef CONFIG_MAC80211_HT_DEBUG | 675 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -594,8 +684,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
594 | if (!sta) { | 684 | if (!sta) { |
595 | rcu_read_unlock(); | 685 | rcu_read_unlock(); |
596 | #ifdef CONFIG_MAC80211_HT_DEBUG | 686 | #ifdef CONFIG_MAC80211_HT_DEBUG |
597 | printk(KERN_DEBUG "Could not find station: %s\n", | 687 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); |
598 | print_mac(mac, ra)); | ||
599 | #endif | 688 | #endif |
600 | return; | 689 | return; |
601 | } | 690 | } |
@@ -621,7 +710,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
621 | #ifdef CONFIG_MAC80211_HT_DEBUG | 710 | #ifdef CONFIG_MAC80211_HT_DEBUG |
622 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | 711 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); |
623 | #endif | 712 | #endif |
624 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 713 | if (hw->ampdu_queues) |
714 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
625 | } | 715 | } |
626 | spin_unlock_bh(&sta->lock); | 716 | spin_unlock_bh(&sta->lock); |
627 | rcu_read_unlock(); | 717 | rcu_read_unlock(); |
@@ -634,7 +724,6 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
634 | struct sta_info *sta; | 724 | struct sta_info *sta; |
635 | u8 *state; | 725 | u8 *state; |
636 | int agg_queue; | 726 | int agg_queue; |
637 | DECLARE_MAC_BUF(mac); | ||
638 | 727 | ||
639 | if (tid >= STA_TID_NUM) { | 728 | if (tid >= STA_TID_NUM) { |
640 | #ifdef CONFIG_MAC80211_HT_DEBUG | 729 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -645,16 +734,15 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
645 | } | 734 | } |
646 | 735 | ||
647 | #ifdef CONFIG_MAC80211_HT_DEBUG | 736 | #ifdef CONFIG_MAC80211_HT_DEBUG |
648 | printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", | 737 | printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n", |
649 | print_mac(mac, ra), tid); | 738 | ra, tid); |
650 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 739 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
651 | 740 | ||
652 | rcu_read_lock(); | 741 | rcu_read_lock(); |
653 | sta = sta_info_get(local, ra); | 742 | sta = sta_info_get(local, ra); |
654 | if (!sta) { | 743 | if (!sta) { |
655 | #ifdef CONFIG_MAC80211_HT_DEBUG | 744 | #ifdef CONFIG_MAC80211_HT_DEBUG |
656 | printk(KERN_DEBUG "Could not find station: %s\n", | 745 | printk(KERN_DEBUG "Could not find station: %pM\n", ra); |
657 | print_mac(mac, ra)); | ||
658 | #endif | 746 | #endif |
659 | rcu_read_unlock(); | 747 | rcu_read_unlock(); |
660 | return; | 748 | return; |
@@ -677,16 +765,18 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
677 | ieee80211_send_delba(sta->sdata, ra, tid, | 765 | ieee80211_send_delba(sta->sdata, ra, tid, |
678 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | 766 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); |
679 | 767 | ||
680 | agg_queue = sta->tid_to_tx_q[tid]; | 768 | if (hw->ampdu_queues) { |
681 | 769 | agg_queue = sta->tid_to_tx_q[tid]; | |
682 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | 770 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); |
683 | 771 | ||
684 | /* We just requeued the all the frames that were in the | 772 | /* We just requeued the all the frames that were in the |
685 | * removed queue, and since we might miss a softirq we do | 773 | * removed queue, and since we might miss a softirq we do |
686 | * netif_schedule_queue. ieee80211_wake_queue is not used | 774 | * netif_schedule_queue. ieee80211_wake_queue is not used |
687 | * here as this queue is not necessarily stopped | 775 | * here as this queue is not necessarily stopped |
688 | */ | 776 | */ |
689 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); | 777 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, |
778 | agg_queue)); | ||
779 | } | ||
690 | spin_lock_bh(&sta->lock); | 780 | spin_lock_bh(&sta->lock); |
691 | *state = HT_AGG_STATE_IDLE; | 781 | *state = HT_AGG_STATE_IDLE; |
692 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 782 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
@@ -783,7 +873,6 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
783 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | 873 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; |
784 | u8 dialog_token; | 874 | u8 dialog_token; |
785 | int ret = -EOPNOTSUPP; | 875 | int ret = -EOPNOTSUPP; |
786 | DECLARE_MAC_BUF(mac); | ||
787 | 876 | ||
788 | /* extract session parameters from addba request frame */ | 877 | /* extract session parameters from addba request frame */ |
789 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | 878 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; |
@@ -801,15 +890,16 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
801 | /* sanity check for incoming parameters: | 890 | /* sanity check for incoming parameters: |
802 | * check if configuration can support the BA policy | 891 | * check if configuration can support the BA policy |
803 | * and if buffer size does not exceeds max value */ | 892 | * and if buffer size does not exceeds max value */ |
893 | /* XXX: check own ht delayed BA capability?? */ | ||
804 | if (((ba_policy != 1) | 894 | if (((ba_policy != 1) |
805 | && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) | 895 | && (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) |
806 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | 896 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { |
807 | status = WLAN_STATUS_INVALID_QOS_PARAM; | 897 | status = WLAN_STATUS_INVALID_QOS_PARAM; |
808 | #ifdef CONFIG_MAC80211_HT_DEBUG | 898 | #ifdef CONFIG_MAC80211_HT_DEBUG |
809 | if (net_ratelimit()) | 899 | if (net_ratelimit()) |
810 | printk(KERN_DEBUG "AddBA Req with bad params from " | 900 | printk(KERN_DEBUG "AddBA Req with bad params from " |
811 | "%s on tid %u. policy %d, buffer size %d\n", | 901 | "%pM on tid %u. policy %d, buffer size %d\n", |
812 | print_mac(mac, mgmt->sa), tid, ba_policy, | 902 | mgmt->sa, tid, ba_policy, |
813 | buf_size); | 903 | buf_size); |
814 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 904 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
815 | goto end_no_lock; | 905 | goto end_no_lock; |
@@ -820,7 +910,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
820 | 910 | ||
821 | sband = local->hw.wiphy->bands[conf->channel->band]; | 911 | sband = local->hw.wiphy->bands[conf->channel->band]; |
822 | buf_size = IEEE80211_MIN_AMPDU_BUF; | 912 | buf_size = IEEE80211_MIN_AMPDU_BUF; |
823 | buf_size = buf_size << sband->ht_info.ampdu_factor; | 913 | buf_size = buf_size << sband->ht_cap.ampdu_factor; |
824 | } | 914 | } |
825 | 915 | ||
826 | 916 | ||
@@ -831,8 +921,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
831 | #ifdef CONFIG_MAC80211_HT_DEBUG | 921 | #ifdef CONFIG_MAC80211_HT_DEBUG |
832 | if (net_ratelimit()) | 922 | if (net_ratelimit()) |
833 | printk(KERN_DEBUG "unexpected AddBA Req from " | 923 | printk(KERN_DEBUG "unexpected AddBA Req from " |
834 | "%s on tid %u\n", | 924 | "%pM on tid %u\n", |
835 | print_mac(mac, mgmt->sa), tid); | 925 | mgmt->sa, tid); |
836 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 926 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
837 | goto end; | 927 | goto end; |
838 | } | 928 | } |
@@ -910,7 +1000,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
910 | { | 1000 | { |
911 | struct ieee80211_hw *hw = &local->hw; | 1001 | struct ieee80211_hw *hw = &local->hw; |
912 | u16 capab; | 1002 | u16 capab; |
913 | u16 tid; | 1003 | u16 tid, start_seq_num; |
914 | u8 *state; | 1004 | u8 *state; |
915 | 1005 | ||
916 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 1006 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
@@ -943,9 +1033,18 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
943 | *state |= HT_ADDBA_RECEIVED_MSK; | 1033 | *state |= HT_ADDBA_RECEIVED_MSK; |
944 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 1034 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
945 | 1035 | ||
946 | if (*state == HT_AGG_STATE_OPERATIONAL) | 1036 | if (*state == HT_AGG_STATE_OPERATIONAL && |
1037 | local->hw.ampdu_queues) | ||
947 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 1038 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); |
948 | 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 */ | ||
949 | spin_unlock_bh(&sta->lock); | 1048 | spin_unlock_bh(&sta->lock); |
950 | } else { | 1049 | } else { |
951 | sta->ampdu_mlme.addba_req_num[tid]++; | 1050 | sta->ampdu_mlme.addba_req_num[tid]++; |
@@ -964,7 +1063,6 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
964 | struct ieee80211_local *local = sdata->local; | 1063 | struct ieee80211_local *local = sdata->local; |
965 | u16 tid, params; | 1064 | u16 tid, params; |
966 | u16 initiator; | 1065 | u16 initiator; |
967 | DECLARE_MAC_BUF(mac); | ||
968 | 1066 | ||
969 | params = le16_to_cpu(mgmt->u.action.u.delba.params); | 1067 | params = le16_to_cpu(mgmt->u.action.u.delba.params); |
970 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; | 1068 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; |
@@ -972,9 +1070,8 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
972 | 1070 | ||
973 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1071 | #ifdef CONFIG_MAC80211_HT_DEBUG |
974 | if (net_ratelimit()) | 1072 | if (net_ratelimit()) |
975 | printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", | 1073 | printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n", |
976 | print_mac(mac, mgmt->sa), | 1074 | mgmt->sa, initiator ? "initiator" : "recipient", tid, |
977 | initiator ? "initiator" : "recipient", tid, | ||
978 | mgmt->u.action.u.delba.reason_code); | 1075 | mgmt->u.action.u.delba.reason_code); |
979 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1076 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
980 | 1077 | ||