aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ht.c181
-rw-r--r--net/mac80211/ieee80211_i.h12
-rw-r--r--net/mac80211/mlme.c88
4 files changed, 134 insertions, 153 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 28382b5c7c25..55e3a26510ed 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -582,6 +582,8 @@ static void sta_apply_parameters(struct ieee80211_local *local,
582 struct ieee80211_supported_band *sband; 582 struct ieee80211_supported_band *sband;
583 struct ieee80211_sub_if_data *sdata = sta->sdata; 583 struct ieee80211_sub_if_data *sdata = sta->sdata;
584 584
585 sband = local->hw.wiphy->bands[local->oper_channel->band];
586
585 /* 587 /*
586 * FIXME: updating the flags is racy when this function is 588 * FIXME: updating the flags is racy when this function is
587 * called from ieee80211_change_station(), this will 589 * called from ieee80211_change_station(), this will
@@ -622,7 +624,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
622 624
623 if (params->supported_rates) { 625 if (params->supported_rates) {
624 rates = 0; 626 rates = 0;
625 sband = local->hw.wiphy->bands[local->oper_channel->band];
626 627
627 for (i = 0; i < params->supported_rates_len; i++) { 628 for (i = 0; i < params->supported_rates_len; i++) {
628 int rate = (params->supported_rates[i] & 0x7f) * 5; 629 int rate = (params->supported_rates[i] & 0x7f) * 5;
@@ -635,7 +636,8 @@ static void sta_apply_parameters(struct ieee80211_local *local,
635 } 636 }
636 637
637 if (params->ht_capa) 638 if (params->ht_capa)
638 ieee80211_ht_cap_ie_to_sta_ht_cap(params->ht_capa, 639 ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
640 params->ht_capa,
639 &sta->sta.ht_cap); 641 &sta->sta.ht_cap);
640 642
641 if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { 643 if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index e2d121bf2745..42c3e590df98 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -20,114 +20,38 @@
20#include "sta_info.h" 20#include "sta_info.h"
21#include "wme.h" 21#include "wme.h"
22 22
23void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_ht_cap *ht_cap_ie, 23void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
24 struct ieee80211_ht_cap *ht_cap_ie,
24 struct ieee80211_sta_ht_cap *ht_cap) 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 BUG_ON(!ht_cap); 30 BUG_ON(!ht_cap);
28 31
29 memset(ht_cap, 0, sizeof(*ht_cap)); 32 memset(ht_cap, 0, sizeof(*ht_cap));
30 33
31 if (ht_cap_ie) { 34 if (!ht_cap_ie)
32 u8 ampdu_info = ht_cap_ie->ampdu_params_info; 35 return;
33
34 ht_cap->ht_supported = true;
35 ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info);
36 ht_cap->ampdu_factor =
37 ampdu_info & IEEE80211_HT_AMPDU_PARM_FACTOR;
38 ht_cap->ampdu_density =
39 (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2;
40 memcpy(&ht_cap->mcs, &ht_cap_ie->mcs, sizeof(ht_cap->mcs));
41 } else
42 ht_cap->ht_supported = false;
43}
44
45void ieee80211_ht_info_ie_to_ht_bss_info(
46 struct ieee80211_ht_info *ht_add_info_ie,
47 struct ieee80211_ht_bss_info *bss_info)
48{
49 BUG_ON(!bss_info);
50
51 memset(bss_info, 0, sizeof(*bss_info));
52
53 if (ht_add_info_ie) {
54 u16 op_mode;
55 op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
56
57 bss_info->primary_channel = ht_add_info_ie->control_chan;
58 bss_info->bss_cap = ht_add_info_ie->ht_param;
59 bss_info->bss_op_mode = (u8)(op_mode & 0xff);
60 }
61}
62
63/*
64 * ieee80211_handle_ht should be called only after the operating band
65 * has been determined as ht configuration depends on the hw's
66 * HT abilities for a specific band.
67 */
68u32 ieee80211_handle_ht(struct ieee80211_local *local,
69 struct ieee80211_sta_ht_cap *req_ht_cap,
70 struct ieee80211_ht_bss_info *req_bss_cap)
71{
72 struct ieee80211_conf *conf = &local->hw.conf;
73 struct ieee80211_supported_band *sband;
74 struct ieee80211_sta_ht_cap ht_cap;
75 struct ieee80211_ht_bss_info ht_bss_conf;
76 u32 changed = 0;
77 int i;
78 u8 max_tx_streams;
79 u8 tx_mcs_set_cap;
80 bool enable_ht = true;
81
82 sband = local->hw.wiphy->bands[conf->channel->band];
83
84 memset(&ht_cap, 0, sizeof(ht_cap));
85 memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
86
87 /* HT is not supported */
88 if (!sband->ht_cap.ht_supported)
89 enable_ht = false;
90
91 /* disable HT */
92 if (!enable_ht) {
93 if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
94 changed |= BSS_CHANGED_HT;
95 conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
96 conf->ht_cap.ht_supported = false;
97 return changed;
98 }
99
100
101 if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
102 changed |= BSS_CHANGED_HT;
103
104 conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
105 ht_cap.ht_supported = true;
106 36
107 ht_cap.cap = req_ht_cap->cap & sband->ht_cap.cap; 37 ht_cap->ht_supported = true;
108 ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS;
109 ht_cap.cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS;
110 38
111 ht_bss_conf.primary_channel = req_bss_cap->primary_channel; 39 ht_cap->cap = ht_cap->cap & sband->ht_cap.cap;
112 ht_bss_conf.bss_cap = req_bss_cap->bss_cap; 40 ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS;
113 ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; 41 ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS;
114 42
115 ht_cap.ampdu_factor = req_ht_cap->ampdu_factor; 43 ampdu_info = ht_cap_ie->ampdu_params_info;
116 ht_cap.ampdu_density = req_ht_cap->ampdu_density; 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;
117 48
118 /* own MCS TX capabilities */ 49 /* own MCS TX capabilities */
119 tx_mcs_set_cap = sband->ht_cap.mcs.tx_params; 50 tx_mcs_set_cap = sband->ht_cap.mcs.tx_params;
120 51
121 /*
122 * configure supported Tx MCS according to requested MCS
123 * (based in most cases on Rx capabilities of peer) and self
124 * Tx MCS capabilities (as defined by low level driver HW
125 * Tx capabilities)
126 */
127
128 /* can we TX with MCS rates? */ 52 /* can we TX with MCS rates? */
129 if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED)) 53 if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED))
130 goto check_changed; 54 return;
131 55
132 /* Counting from 0, therefore +1 */ 56 /* Counting from 0, therefore +1 */
133 if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF) 57 if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF)
@@ -145,29 +69,73 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local,
145 * - remainder are multiple spatial streams using unequal modulation 69 * - remainder are multiple spatial streams using unequal modulation
146 */ 70 */
147 for (i = 0; i < max_tx_streams; i++) 71 for (i = 0; i < max_tx_streams; i++)
148 ht_cap.mcs.rx_mask[i] = 72 ht_cap->mcs.rx_mask[i] =
149 sband->ht_cap.mcs.rx_mask[i] & 73 sband->ht_cap.mcs.rx_mask[i] & ht_cap_ie->mcs.rx_mask[i];
150 req_ht_cap->mcs.rx_mask[i];
151 74
152 if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) 75 if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION)
153 for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; 76 for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE;
154 i < IEEE80211_HT_MCS_MASK_LEN; i++) 77 i < IEEE80211_HT_MCS_MASK_LEN; i++)
155 ht_cap.mcs.rx_mask[i] = 78 ht_cap->mcs.rx_mask[i] =
156 sband->ht_cap.mcs.rx_mask[i] & 79 sband->ht_cap.mcs.rx_mask[i] &
157 req_ht_cap->mcs.rx_mask[i]; 80 ht_cap_ie->mcs.rx_mask[i];
158 81
159 /* handle MCS rate 32 too */ 82 /* handle MCS rate 32 too */
160 if (sband->ht_cap.mcs.rx_mask[32/8] & 83 if (sband->ht_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
161 req_ht_cap->mcs.rx_mask[32/8] & 1) 84 ht_cap->mcs.rx_mask[32/8] |= 1;
162 ht_cap.mcs.rx_mask[32/8] |= 1; 85}
86
87/*
88 * ieee80211_enable_ht should be called only after the operating band
89 * has been determined as ht configuration depends on the hw's
90 * HT abilities for a specific band.
91 */
92u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
93 struct ieee80211_ht_info *hti,
94 u16 ap_ht_cap_flags)
95{
96 struct ieee80211_local *local = sdata->local;
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
102 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
103
104 memset(&ht, 0, sizeof(ht));
105
106 /* HT is not supported */
107 if (!sband->ht_cap.ht_supported)
108 enable_ht = false;
109
110 /* check that channel matches the right operating channel */
111 if (local->hw.conf.channel->center_freq !=
112 ieee80211_channel_to_frequency(hti->control_chan))
113 enable_ht = false;
114
115 /*
116 * XXX: This is totally incorrect when there are multiple virtual
117 * interfaces, needs to be fixed later.
118 */
119 ht_changed = local->hw.conf.ht.enabled != enable_ht;
120 local->hw.conf.ht.enabled = enable_ht;
121 if (ht_changed)
122 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
123
124 /* disable HT */
125 if (!enable_ht)
126 return 0;
127 ht.secondary_channel_offset =
128 hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
129 ht.width_40_ok =
130 !(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
131 (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
132 (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY);
133 ht.operation_mode = le16_to_cpu(hti->operation_mode);
163 134
164 check_changed:
165 /* if bss configuration changed store the new one */ 135 /* if bss configuration changed store the new one */
166 if (memcmp(&conf->ht_cap, &ht_cap, sizeof(ht_cap)) || 136 if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) {
167 memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
168 changed |= BSS_CHANGED_HT; 137 changed |= BSS_CHANGED_HT;
169 memcpy(&conf->ht_cap, &ht_cap, sizeof(ht_cap)); 138 sdata->vif.bss_conf.ht = ht;
170 memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
171 } 139 }
172 140
173 return changed; 141 return changed;
@@ -900,8 +868,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
900 /* sanity check for incoming parameters: 868 /* sanity check for incoming parameters:
901 * check if configuration can support the BA policy 869 * check if configuration can support the BA policy
902 * and if buffer size does not exceeds max value */ 870 * and if buffer size does not exceeds max value */
871 /* XXX: check own ht delayed BA capability?? */
903 if (((ba_policy != 1) 872 if (((ba_policy != 1)
904 && (!(conf->ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) 873 && (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA)))
905 || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { 874 || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
906 status = WLAN_STATUS_INVALID_QOS_PARAM; 875 status = WLAN_STATUS_INVALID_QOS_PARAM;
907#ifdef CONFIG_MAC80211_HT_DEBUG 876#ifdef CONFIG_MAC80211_HT_DEBUG
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 859b5b001f22..6f8756d26a93 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -955,14 +955,12 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
955int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); 955int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
956 956
957/* HT */ 957/* HT */
958void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_ht_cap *ht_cap_ie, 958void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
959 struct ieee80211_ht_cap *ht_cap_ie,
959 struct ieee80211_sta_ht_cap *ht_cap); 960 struct ieee80211_sta_ht_cap *ht_cap);
960void ieee80211_ht_info_ie_to_ht_bss_info( 961u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
961 struct ieee80211_ht_info *ht_add_info_ie, 962 struct ieee80211_ht_info *hti,
962 struct ieee80211_ht_bss_info *bss_info); 963 u16 ap_ht_cap_flags);
963u32 ieee80211_handle_ht(struct ieee80211_local *local,
964 struct ieee80211_sta_ht_cap *req_ht_cap,
965 struct ieee80211_ht_bss_info *req_bss_cap);
966void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); 964void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn);
967 965
968void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, 966void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9c5f5c37a49e..39bc9c69893b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -700,14 +700,15 @@ static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata,
700 700
701 701
702static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, 702static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
703 struct ieee80211_if_sta *ifsta) 703 struct ieee80211_if_sta *ifsta,
704 u32 bss_info_changed)
704{ 705{
705 struct ieee80211_local *local = sdata->local; 706 struct ieee80211_local *local = sdata->local;
706 struct ieee80211_conf *conf = &local_to_hw(local)->conf; 707 struct ieee80211_conf *conf = &local_to_hw(local)->conf;
707 u32 changed = BSS_CHANGED_ASSOC;
708 708
709 struct ieee80211_bss *bss; 709 struct ieee80211_bss *bss;
710 710
711 bss_info_changed |= BSS_CHANGED_ASSOC;
711 ifsta->flags |= IEEE80211_STA_ASSOCIATED; 712 ifsta->flags |= IEEE80211_STA_ASSOCIATED;
712 713
713 if (sdata->vif.type != NL80211_IFTYPE_STATION) 714 if (sdata->vif.type != NL80211_IFTYPE_STATION)
@@ -722,19 +723,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
722 sdata->vif.bss_conf.timestamp = bss->timestamp; 723 sdata->vif.bss_conf.timestamp = bss->timestamp;
723 sdata->vif.bss_conf.dtim_period = bss->dtim_period; 724 sdata->vif.bss_conf.dtim_period = bss->dtim_period;
724 725
725 changed |= ieee80211_handle_bss_capability(sdata, 726 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
726 bss->capability, bss->has_erp_value, bss->erp_value); 727 bss->capability, bss->has_erp_value, bss->erp_value);
727 728
728 ieee80211_rx_bss_put(local, bss); 729 ieee80211_rx_bss_put(local, bss);
729 } 730 }
730 731
731 if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
732 changed |= BSS_CHANGED_HT;
733 sdata->vif.bss_conf.assoc_ht = 1;
734 sdata->vif.bss_conf.ht_cap = &conf->ht_cap;
735 sdata->vif.bss_conf.ht_bss_conf = &conf->ht_bss_conf;
736 }
737
738 ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; 732 ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
739 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); 733 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
740 ieee80211_sta_send_associnfo(sdata, ifsta); 734 ieee80211_sta_send_associnfo(sdata, ifsta);
@@ -748,8 +742,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
748 * when we have associated, we aren't checking whether it actually 742 * when we have associated, we aren't checking whether it actually
749 * changed or not. 743 * changed or not.
750 */ 744 */
751 changed |= BSS_CHANGED_BASIC_RATES; 745 bss_info_changed |= BSS_CHANGED_BASIC_RATES;
752 ieee80211_bss_info_change_notify(sdata, changed); 746 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
753 747
754 netif_tx_start_all_queues(sdata->dev); 748 netif_tx_start_all_queues(sdata->dev);
755 netif_carrier_on(sdata->dev); 749 netif_carrier_on(sdata->dev);
@@ -813,7 +807,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
813{ 807{
814 struct ieee80211_local *local = sdata->local; 808 struct ieee80211_local *local = sdata->local;
815 struct sta_info *sta; 809 struct sta_info *sta;
816 u32 changed = BSS_CHANGED_ASSOC; 810 u32 changed = 0;
817 811
818 rcu_read_lock(); 812 rcu_read_lock();
819 813
@@ -847,15 +841,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
847 ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; 841 ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
848 changed |= ieee80211_reset_erp_info(sdata); 842 changed |= ieee80211_reset_erp_info(sdata);
849 843
850 if (sdata->vif.bss_conf.assoc_ht)
851 changed |= BSS_CHANGED_HT;
852
853 sdata->vif.bss_conf.assoc_ht = 0;
854 sdata->vif.bss_conf.ht_cap = NULL;
855 sdata->vif.bss_conf.ht_bss_conf = NULL;
856
857 ieee80211_led_assoc(local, 0); 844 ieee80211_led_assoc(local, 0);
858 sdata->vif.bss_conf.assoc = 0; 845 changed |= BSS_CHANGED_ASSOC;
846 sdata->vif.bss_conf.assoc = false;
859 847
860 ieee80211_sta_send_apinfo(sdata, ifsta); 848 ieee80211_sta_send_apinfo(sdata, ifsta);
861 849
@@ -867,6 +855,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
867 rcu_read_unlock(); 855 rcu_read_unlock();
868 856
869 sta_info_destroy(sta); 857 sta_info_destroy(sta);
858
859 local->hw.conf.ht.enabled = false;
860 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
861
862 ieee80211_bss_info_change_notify(sdata, changed);
870} 863}
871 864
872static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) 865static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
@@ -1184,8 +1177,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1184 struct ieee802_11_elems elems; 1177 struct ieee802_11_elems elems;
1185 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 1178 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1186 u8 *pos; 1179 u8 *pos;
1180 u32 changed = 0;
1187 int i, j; 1181 int i, j;
1188 bool have_higher_than_11mbit = false; 1182 bool have_higher_than_11mbit = false;
1183 u16 ap_ht_cap_flags;
1189 1184
1190 /* AssocResp and ReassocResp have identical structure, so process both 1185 /* AssocResp and ReassocResp have identical structure, so process both
1191 * of them in this function. */ 1186 * of them in this function. */
@@ -1333,15 +1328,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1333 else 1328 else
1334 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 1329 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
1335 1330
1336 if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && 1331 if (elems.ht_cap_elem)
1337 (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { 1332 ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
1338 struct ieee80211_ht_bss_info bss_info;
1339 ieee80211_ht_cap_ie_to_sta_ht_cap(
1340 elems.ht_cap_elem, &sta->sta.ht_cap); 1333 elems.ht_cap_elem, &sta->sta.ht_cap);
1341 ieee80211_ht_info_ie_to_ht_bss_info( 1334
1342 elems.ht_info_elem, &bss_info); 1335 ap_ht_cap_flags = sta->sta.ht_cap.cap;
1343 ieee80211_handle_ht(local, &sta->sta.ht_cap, &bss_info);
1344 }
1345 1336
1346 rate_control_rate_init(sta); 1337 rate_control_rate_init(sta);
1347 1338
@@ -1353,11 +1344,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1353 } else 1344 } else
1354 rcu_read_unlock(); 1345 rcu_read_unlock();
1355 1346
1347 if (elems.ht_info_elem && elems.wmm_param &&
1348 (ifsta->flags & IEEE80211_STA_WMM_ENABLED))
1349 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
1350 ap_ht_cap_flags);
1351
1356 /* set AID and assoc capability, 1352 /* set AID and assoc capability,
1357 * ieee80211_set_associated() will tell the driver */ 1353 * ieee80211_set_associated() will tell the driver */
1358 bss_conf->aid = aid; 1354 bss_conf->aid = aid;
1359 bss_conf->assoc_capability = capab_info; 1355 bss_conf->assoc_capability = capab_info;
1360 ieee80211_set_associated(sdata, ifsta); 1356 ieee80211_set_associated(sdata, ifsta, changed);
1361 1357
1362 ieee80211_associated(sdata, ifsta); 1358 ieee80211_associated(sdata, ifsta);
1363} 1359}
@@ -1657,7 +1653,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1657 size_t baselen; 1653 size_t baselen;
1658 struct ieee802_11_elems elems; 1654 struct ieee802_11_elems elems;
1659 struct ieee80211_local *local = sdata->local; 1655 struct ieee80211_local *local = sdata->local;
1660 struct ieee80211_conf *conf = &local->hw.conf;
1661 u32 changed = 0; 1656 u32 changed = 0;
1662 bool erp_valid; 1657 bool erp_valid;
1663 u8 erp_value = 0; 1658 u8 erp_value = 0;
@@ -1693,14 +1688,31 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1693 le16_to_cpu(mgmt->u.beacon.capab_info), 1688 le16_to_cpu(mgmt->u.beacon.capab_info),
1694 erp_valid, erp_value); 1689 erp_valid, erp_value);
1695 1690
1696 if (elems.ht_cap_elem && elems.ht_info_elem &&
1697 elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
1698 struct ieee80211_ht_bss_info bss_info;
1699 1691
1700 ieee80211_ht_info_ie_to_ht_bss_info( 1692 if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
1701 elems.ht_info_elem, &bss_info); 1693 struct sta_info *sta;
1702 changed |= ieee80211_handle_ht(local, &conf->ht_cap, 1694 struct ieee80211_supported_band *sband;
1703 &bss_info); 1695 u16 ap_ht_cap_flags;
1696
1697 rcu_read_lock();
1698
1699 sta = sta_info_get(local, ifsta->bssid);
1700 if (!sta) {
1701 rcu_read_unlock();
1702 return;
1703 }
1704
1705 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1706
1707 ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
1708 elems.ht_cap_elem, &sta->sta.ht_cap);
1709
1710 ap_ht_cap_flags = sta->sta.ht_cap.cap;
1711
1712 rcu_read_unlock();
1713
1714 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
1715 ap_ht_cap_flags);
1704 } 1716 }
1705 1717
1706 ieee80211_bss_info_change_notify(sdata, changed); 1718 ieee80211_bss_info_change_notify(sdata, changed);