aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c5
-rw-r--r--drivers/net/wireless/rtlwifi/rc.c3
-rw-r--r--include/net/mac80211.h5
-rw-r--r--net/mac80211/chan.c26
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/mlme.c51
-rw-r--r--net/mac80211/rate.h5
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c15
-rw-r--r--net/mac80211/rx.c7
-rw-r--r--net/mac80211/sta_info.h2
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
1437static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, 1437static 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,
225static void rtl_rate_update(void *ppriv, 225static 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 */
144enum 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);
1502enum nl80211_channel_type 1500enum nl80211_channel_type
1503ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); 1501ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper);
1504enum 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
64static inline void rate_control_rate_update(struct ieee80211_local *local, 64static 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
78static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, 77static 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
687static void 687static void
688minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, 688minstrel_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
788minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, 783minstrel_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
796static void 789static void
797minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, 790minstrel_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
804static void * 797static 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};