diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/rc.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/rc.c | 3 | ||||
-rw-r--r-- | include/net/mac80211.h | 5 | ||||
-rw-r--r-- | net/mac80211/chan.c | 26 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 5 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 51 | ||||
-rw-r--r-- | net/mac80211/rate.h | 5 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 15 | ||||
-rw-r--r-- | net/mac80211/rx.c | 7 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 |
10 files changed, 50 insertions, 74 deletions
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 4f848493fece..4e39f27af077 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1436,7 +1436,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1436 | 1436 | ||
1437 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | 1437 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, |
1438 | struct ieee80211_sta *sta, void *priv_sta, | 1438 | struct ieee80211_sta *sta, void *priv_sta, |
1439 | u32 changed, enum nl80211_channel_type oper_chan_type) | 1439 | u32 changed) |
1440 | { | 1440 | { |
1441 | struct ath_softc *sc = priv; | 1441 | struct ath_softc *sc = priv; |
1442 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1442 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
@@ -1451,8 +1451,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1451 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) | 1451 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) |
1452 | return; | 1452 | return; |
1453 | 1453 | ||
1454 | if (oper_chan_type == NL80211_CHAN_HT40MINUS || | 1454 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
1455 | oper_chan_type == NL80211_CHAN_HT40PLUS) | ||
1456 | oper_cw40 = true; | 1455 | oper_cw40 = true; |
1457 | 1456 | ||
1458 | if (oper_cw40) | 1457 | if (oper_cw40) |
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index c66f08a0524a..d5cbf01da8ac 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c | |||
@@ -225,8 +225,7 @@ static void rtl_rate_init(void *ppriv, | |||
225 | static void rtl_rate_update(void *ppriv, | 225 | static void rtl_rate_update(void *ppriv, |
226 | struct ieee80211_supported_band *sband, | 226 | struct ieee80211_supported_band *sband, |
227 | struct ieee80211_sta *sta, void *priv_sta, | 227 | struct ieee80211_sta *sta, void *priv_sta, |
228 | u32 changed, | 228 | u32 changed) |
229 | enum nl80211_channel_type oper_chan_type) | ||
230 | { | 229 | { |
231 | } | 230 | } |
232 | 231 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 81cb66c3989e..21c653415d84 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -3569,9 +3569,8 @@ struct rate_control_ops { | |||
3569 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, | 3569 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, |
3570 | struct ieee80211_sta *sta, void *priv_sta); | 3570 | struct ieee80211_sta *sta, void *priv_sta); |
3571 | void (*rate_update)(void *priv, struct ieee80211_supported_band *sband, | 3571 | void (*rate_update)(void *priv, struct ieee80211_supported_band *sband, |
3572 | struct ieee80211_sta *sta, | 3572 | struct ieee80211_sta *sta, void *priv_sta, |
3573 | void *priv_sta, u32 changed, | 3573 | u32 changed); |
3574 | enum nl80211_channel_type oper_chan_type); | ||
3575 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, | 3574 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, |
3576 | void *priv_sta); | 3575 | void *priv_sta); |
3577 | 3576 | ||
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index e00ce8c3e28e..c76cf7230c7d 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -135,29 +135,3 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
135 | 135 | ||
136 | return result; | 136 | return result; |
137 | } | 137 | } |
138 | |||
139 | /* | ||
140 | * ieee80211_get_tx_channel_type returns the channel type we should | ||
141 | * use for packet transmission, given the channel capability and | ||
142 | * whatever regulatory flags we have been given. | ||
143 | */ | ||
144 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
145 | struct ieee80211_local *local, | ||
146 | enum nl80211_channel_type channel_type) | ||
147 | { | ||
148 | switch (channel_type) { | ||
149 | case NL80211_CHAN_HT40PLUS: | ||
150 | if (local->hw.conf.channel->flags & | ||
151 | IEEE80211_CHAN_NO_HT40PLUS) | ||
152 | return NL80211_CHAN_HT20; | ||
153 | break; | ||
154 | case NL80211_CHAN_HT40MINUS: | ||
155 | if (local->hw.conf.channel->flags & | ||
156 | IEEE80211_CHAN_NO_HT40MINUS) | ||
157 | return NL80211_CHAN_HT20; | ||
158 | break; | ||
159 | default: | ||
160 | break; | ||
161 | } | ||
162 | return channel_type; | ||
163 | } | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a67ba7c85a1e..867b8eec1e9e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -512,8 +512,6 @@ struct ieee80211_if_managed { | |||
512 | int rssi_min_thold, rssi_max_thold; | 512 | int rssi_min_thold, rssi_max_thold; |
513 | int last_ave_beacon_signal; | 513 | int last_ave_beacon_signal; |
514 | 514 | ||
515 | enum nl80211_channel_type tx_chantype; | ||
516 | |||
517 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ | 515 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ |
518 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | 516 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ |
519 | }; | 517 | }; |
@@ -1501,9 +1499,6 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
1501 | enum nl80211_channel_type chantype); | 1499 | enum nl80211_channel_type chantype); |
1502 | enum nl80211_channel_type | 1500 | enum nl80211_channel_type |
1503 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); | 1501 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); |
1504 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
1505 | struct ieee80211_local *local, | ||
1506 | enum nl80211_channel_type channel_type); | ||
1507 | 1502 | ||
1508 | #ifdef CONFIG_MAC80211_NOINLINE | 1503 | #ifdef CONFIG_MAC80211_NOINLINE |
1509 | #define debug_noinline noinline | 1504 | #define debug_noinline noinline |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 30259a73195c..9cc5dda68219 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -180,21 +180,38 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
180 | struct sta_info *sta; | 180 | struct sta_info *sta; |
181 | u32 changed = 0; | 181 | u32 changed = 0; |
182 | u16 ht_opmode; | 182 | u16 ht_opmode; |
183 | enum nl80211_channel_type channel_type; | 183 | bool disable_40 = false; |
184 | 184 | ||
185 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 185 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
186 | channel_type = local->hw.conf.channel_type; | ||
187 | 186 | ||
188 | if (WARN_ON_ONCE(channel_type == NL80211_CHAN_NO_HT)) | 187 | switch (sdata->vif.bss_conf.channel_type) { |
189 | return 0; | 188 | case NL80211_CHAN_HT40PLUS: |
190 | 189 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40PLUS) | |
191 | channel_type = ieee80211_get_tx_channel_type(local, channel_type); | 190 | disable_40 = true; |
191 | break; | ||
192 | case NL80211_CHAN_HT40MINUS: | ||
193 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
194 | disable_40 = true; | ||
195 | break; | ||
196 | default: | ||
197 | break; | ||
198 | } | ||
192 | 199 | ||
193 | /* This can change during the lifetime of the BSS */ | 200 | /* This can change during the lifetime of the BSS */ |
194 | if (!(ht_oper->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | 201 | if (!(ht_oper->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) |
195 | channel_type = NL80211_CHAN_HT20; | 202 | disable_40 = true; |
196 | 203 | ||
197 | if (!reconfig || (sdata->u.mgd.tx_chantype != channel_type)) { | 204 | mutex_lock(&local->sta_mtx); |
205 | sta = sta_info_get(sdata, bssid); | ||
206 | |||
207 | WARN_ON_ONCE(!sta); | ||
208 | |||
209 | if (sta && !sta->supports_40mhz) | ||
210 | disable_40 = true; | ||
211 | |||
212 | if (sta && (!reconfig || | ||
213 | (disable_40 != !!(sta->sta.ht_cap.cap & | ||
214 | IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) { | ||
198 | if (reconfig) { | 215 | if (reconfig) { |
199 | /* | 216 | /* |
200 | * Whenever the AP announces the HT mode changed | 217 | * Whenever the AP announces the HT mode changed |
@@ -211,20 +228,19 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
211 | drv_flush(local, false); | 228 | drv_flush(local, false); |
212 | } | 229 | } |
213 | 230 | ||
214 | rcu_read_lock(); | 231 | if (disable_40) |
215 | sta = sta_info_get(sdata, bssid); | 232 | sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
216 | if (sta) | 233 | else |
217 | rate_control_rate_update(local, sband, sta, | 234 | sta->sta.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
218 | IEEE80211_RC_HT_CHANGED, | ||
219 | channel_type); | ||
220 | rcu_read_unlock(); | ||
221 | 235 | ||
222 | sdata->u.mgd.tx_chantype = channel_type; | 236 | rate_control_rate_update(local, sband, sta, |
237 | IEEE80211_RC_HT_CHANGED); | ||
223 | 238 | ||
224 | if (reconfig) | 239 | if (reconfig) |
225 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 240 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
226 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | 241 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); |
227 | } | 242 | } |
243 | mutex_unlock(&local->sta_mtx); | ||
228 | 244 | ||
229 | ht_opmode = le16_to_cpu(ht_oper->operation_mode); | 245 | ht_opmode = le16_to_cpu(ht_oper->operation_mode); |
230 | 246 | ||
@@ -2006,6 +2022,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2006 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2022 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
2007 | elems.ht_cap_elem, &sta->sta.ht_cap); | 2023 | elems.ht_cap_elem, &sta->sta.ht_cap); |
2008 | 2024 | ||
2025 | sta->supports_40mhz = | ||
2026 | sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
2027 | |||
2009 | rate_control_rate_init(sta); | 2028 | rate_control_rate_init(sta); |
2010 | 2029 | ||
2011 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) | 2030 | if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index fbb1efdc4d04..27b66be8ac8f 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -63,8 +63,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
63 | 63 | ||
64 | static inline void rate_control_rate_update(struct ieee80211_local *local, | 64 | static inline void rate_control_rate_update(struct ieee80211_local *local, |
65 | struct ieee80211_supported_band *sband, | 65 | struct ieee80211_supported_band *sband, |
66 | struct sta_info *sta, u32 changed, | 66 | struct sta_info *sta, u32 changed) |
67 | enum nl80211_channel_type oper_chan_type) | ||
68 | { | 67 | { |
69 | struct rate_control_ref *ref = local->rate_ctrl; | 68 | struct rate_control_ref *ref = local->rate_ctrl; |
70 | struct ieee80211_sta *ista = &sta->sta; | 69 | struct ieee80211_sta *ista = &sta->sta; |
@@ -72,7 +71,7 @@ static inline void rate_control_rate_update(struct ieee80211_local *local, | |||
72 | 71 | ||
73 | if (ref && ref->ops->rate_update) | 72 | if (ref && ref->ops->rate_update) |
74 | ref->ops->rate_update(ref->priv, sband, ista, | 73 | ref->ops->rate_update(ref->priv, sband, ista, |
75 | priv_sta, changed, oper_chan_type); | 74 | priv_sta, changed); |
76 | } | 75 | } |
77 | 76 | ||
78 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 77 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 16e0b277b9a8..3b3dcae13bbc 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -686,8 +686,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
686 | 686 | ||
687 | static void | 687 | static void |
688 | minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | 688 | minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, |
689 | struct ieee80211_sta *sta, void *priv_sta, | 689 | struct ieee80211_sta *sta, void *priv_sta) |
690 | enum nl80211_channel_type oper_chan_type) | ||
691 | { | 690 | { |
692 | struct minstrel_priv *mp = priv; | 691 | struct minstrel_priv *mp = priv; |
693 | struct minstrel_ht_sta_priv *msp = priv_sta; | 692 | struct minstrel_ht_sta_priv *msp = priv_sta; |
@@ -735,10 +734,6 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
735 | if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING) | 734 | if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING) |
736 | mi->tx_flags |= IEEE80211_TX_CTL_LDPC; | 735 | mi->tx_flags |= IEEE80211_TX_CTL_LDPC; |
737 | 736 | ||
738 | if (oper_chan_type != NL80211_CHAN_HT40MINUS && | ||
739 | oper_chan_type != NL80211_CHAN_HT40PLUS) | ||
740 | sta_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
741 | |||
742 | smps = (sta_cap & IEEE80211_HT_CAP_SM_PS) >> | 737 | smps = (sta_cap & IEEE80211_HT_CAP_SM_PS) >> |
743 | IEEE80211_HT_CAP_SM_PS_SHIFT; | 738 | IEEE80211_HT_CAP_SM_PS_SHIFT; |
744 | 739 | ||
@@ -788,17 +783,15 @@ static void | |||
788 | minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, | 783 | minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, |
789 | struct ieee80211_sta *sta, void *priv_sta) | 784 | struct ieee80211_sta *sta, void *priv_sta) |
790 | { | 785 | { |
791 | struct minstrel_priv *mp = priv; | 786 | minstrel_ht_update_caps(priv, sband, sta, priv_sta); |
792 | |||
793 | minstrel_ht_update_caps(priv, sband, sta, priv_sta, mp->hw->conf.channel_type); | ||
794 | } | 787 | } |
795 | 788 | ||
796 | static void | 789 | static void |
797 | minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, | 790 | minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, |
798 | struct ieee80211_sta *sta, void *priv_sta, | 791 | struct ieee80211_sta *sta, void *priv_sta, |
799 | u32 changed, enum nl80211_channel_type oper_chan_type) | 792 | u32 changed) |
800 | { | 793 | { |
801 | minstrel_ht_update_caps(priv, sband, sta, priv_sta, oper_chan_type); | 794 | minstrel_ht_update_caps(priv, sband, sta, priv_sta); |
802 | } | 795 | } |
803 | 796 | ||
804 | static void * | 797 | static void * |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8da3b36c287a..54a049123a60 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2268,11 +2268,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2268 | 2268 | ||
2269 | sband = rx->local->hw.wiphy->bands[status->band]; | 2269 | sband = rx->local->hw.wiphy->bands[status->band]; |
2270 | 2270 | ||
2271 | rate_control_rate_update( | 2271 | rate_control_rate_update(local, sband, rx->sta, |
2272 | local, sband, rx->sta, | 2272 | IEEE80211_RC_SMPS_CHANGED); |
2273 | IEEE80211_RC_SMPS_CHANGED, | ||
2274 | ieee80211_get_tx_channel_type( | ||
2275 | local, local->_oper_channel_type)); | ||
2276 | goto handled; | 2273 | goto handled; |
2277 | } | 2274 | } |
2278 | default: | 2275 | default: |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index e21652bccf7c..b1b4b1413c74 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -369,6 +369,8 @@ struct sta_info { | |||
369 | unsigned int lost_packets; | 369 | unsigned int lost_packets; |
370 | unsigned int beacon_loss_count; | 370 | unsigned int beacon_loss_count; |
371 | 371 | ||
372 | bool supports_40mhz; | ||
373 | |||
372 | /* keep last! */ | 374 | /* keep last! */ |
373 | struct ieee80211_sta sta; | 375 | struct ieee80211_sta sta; |
374 | }; | 376 | }; |