aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-07-31 05:23:06 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-07-31 15:18:10 -0400
commit5cdaed1e878d723d56d04ae0be1738124acf9f46 (patch)
treee198fa62f954cf565dec6ee2fa63d0c742521c2e /net
parentcb236d2d713cff83d024a82b836757d9e2b50715 (diff)
mac80211: ignore HT primary channel while connected
While we're connected, the AP shouldn't change the primary channel in the HT information. We checked this, and dropped the connection if it did change it. Unfortunately, this is causing problems on some APs, e.g. on the Netgear WRT610NL: the beacons seem to always contain a bad channel and if we made a connection using a probe response (correct data) we drop the connection immediately and can basically not connect properly at all. Work around this by ignoring the HT primary channel information in beacons if we're already connected. Also print out more verbose messages in the other situations to help diagnose similar bugs quicker in the future. Cc: stable@vger.kernel.org [3.10] Acked-by: Andy Isaacson <adi@hexapodia.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/mlme.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e5c3cf405060..077a95360830 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -211,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
211 struct ieee80211_channel *channel, 211 struct ieee80211_channel *channel,
212 const struct ieee80211_ht_operation *ht_oper, 212 const struct ieee80211_ht_operation *ht_oper,
213 const struct ieee80211_vht_operation *vht_oper, 213 const struct ieee80211_vht_operation *vht_oper,
214 struct cfg80211_chan_def *chandef, bool verbose) 214 struct cfg80211_chan_def *chandef, bool tracking)
215{ 215{
216 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
216 struct cfg80211_chan_def vht_chandef; 217 struct cfg80211_chan_def vht_chandef;
217 u32 ht_cfreq, ret; 218 u32 ht_cfreq, ret;
218 219
@@ -231,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
231 ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, 232 ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
232 channel->band); 233 channel->band);
233 /* check that channel matches the right operating channel */ 234 /* check that channel matches the right operating channel */
234 if (channel->center_freq != ht_cfreq) { 235 if (!tracking && channel->center_freq != ht_cfreq) {
235 /* 236 /*
236 * It's possible that some APs are confused here; 237 * It's possible that some APs are confused here;
237 * Netgear WNDR3700 sometimes reports 4 higher than 238 * Netgear WNDR3700 sometimes reports 4 higher than
@@ -239,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
239 * since we look at probe response/beacon data here 240 * since we look at probe response/beacon data here
240 * it should be OK. 241 * it should be OK.
241 */ 242 */
242 if (verbose) 243 sdata_info(sdata,
243 sdata_info(sdata, 244 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
244 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", 245 channel->center_freq, ht_cfreq,
245 channel->center_freq, ht_cfreq, 246 ht_oper->primary_chan, channel->band);
246 ht_oper->primary_chan, channel->band);
247 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; 247 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
248 goto out; 248 goto out;
249 } 249 }
@@ -297,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
297 channel->band); 297 channel->band);
298 break; 298 break;
299 default: 299 default:
300 if (verbose) 300 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
301 sdata_info(sdata, 301 sdata_info(sdata,
302 "AP VHT operation IE has invalid channel width (%d), disable VHT\n", 302 "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
303 vht_oper->chan_width); 303 vht_oper->chan_width);
@@ -306,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
306 } 306 }
307 307
308 if (!cfg80211_chandef_valid(&vht_chandef)) { 308 if (!cfg80211_chandef_valid(&vht_chandef)) {
309 if (verbose) 309 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
310 sdata_info(sdata, 310 sdata_info(sdata,
311 "AP VHT information is invalid, disable VHT\n"); 311 "AP VHT information is invalid, disable VHT\n");
312 ret = IEEE80211_STA_DISABLE_VHT; 312 ret = IEEE80211_STA_DISABLE_VHT;
@@ -319,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
319 } 319 }
320 320
321 if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { 321 if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
322 if (verbose) 322 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
323 sdata_info(sdata, 323 sdata_info(sdata,
324 "AP VHT information doesn't match HT, disable VHT\n"); 324 "AP VHT information doesn't match HT, disable VHT\n");
325 ret = IEEE80211_STA_DISABLE_VHT; 325 ret = IEEE80211_STA_DISABLE_VHT;
@@ -346,7 +346,7 @@ out:
346 ret |= chandef_downgrade(chandef); 346 ret |= chandef_downgrade(chandef);
347 } 347 }
348 348
349 if (chandef->width != vht_chandef.width && verbose) 349 if (chandef->width != vht_chandef.width && !tracking)
350 sdata_info(sdata, 350 sdata_info(sdata,
351 "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); 351 "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
352 352
@@ -386,7 +386,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
386 386
387 /* calculate new channel (type) based on HT/VHT operation IEs */ 387 /* calculate new channel (type) based on HT/VHT operation IEs */
388 flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, 388 flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
389 vht_oper, &chandef, false); 389 vht_oper, &chandef, true);
390 390
391 /* 391 /*
392 * Downgrade the new channel if we associated with restricted 392 * Downgrade the new channel if we associated with restricted
@@ -3838,7 +3838,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3838 ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, 3838 ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
3839 cbss->channel, 3839 cbss->channel,
3840 ht_oper, vht_oper, 3840 ht_oper, vht_oper,
3841 &chandef, true); 3841 &chandef, false);
3842 3842
3843 sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), 3843 sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
3844 local->rx_chains); 3844 local->rx_chains);