diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 6 | ||||
-rw-r--r-- | net/mac80211/ht.c | 181 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 12 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 88 |
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 | ||
23 | void ieee80211_ht_cap_ie_to_sta_ht_cap(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_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 | |||
45 | void 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 | */ | ||
68 | u32 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 | */ | ||
92 | u32 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); | |||
955 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | 955 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); |
956 | 956 | ||
957 | /* HT */ | 957 | /* HT */ |
958 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_ht_cap *ht_cap_ie, | 958 | void 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); |
960 | void ieee80211_ht_info_ie_to_ht_bss_info( | 961 | u32 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); |
963 | u32 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); | ||
966 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); | 964 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); |
967 | 965 | ||
968 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | 966 | void 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 | ||
702 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | 702 | static 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 | ||
872 | static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) | 865 | static 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); |