From 5481645f3ccf95c1c6f22c844a541e7a970bfa7f Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 1 Aug 2013 08:49:55 -0400 Subject: [PATCH] Fix mac80211 connection issues (rhbz 981445) --- kernel.spec | 11 ++ ...ng-disabled-channels-while-connected.patch | 43 +++++++ ...loop-in-ieee80211_determine_chantype.patch | 32 +++++ ...e-HT-primary-channel-while-connected.patch | 121 ++++++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 mac80211-continue-using-disabled-channels-while-connected.patch create mode 100644 mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch create mode 100644 mac80211-ignore-HT-primary-channel-while-connected.patch diff --git a/kernel.spec b/kernel.spec index 2fdf118a3..51bb6e7d0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -757,6 +757,11 @@ Patch25072: HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue. #rhbz 977053 Patch25073: iwl4965-reset-firmware-after-rfkill-off.patch +#rhbz 981445 +Patch25074: mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch +Patch25075: mac80211-ignore-HT-primary-channel-while-connected.patch +Patch25076: mac80211-continue-using-disabled-channels-while-connected.patch + # END OF PATCH DEFINITIONS %endif @@ -1466,6 +1471,11 @@ ApplyPatch HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.p #rhbz 977053 ApplyPatch iwl4965-reset-firmware-after-rfkill-off.patch +#rhbz 981445 +ApplyPatch mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch +ApplyPatch mac80211-ignore-HT-primary-channel-while-connected.patch +ApplyPatch mac80211-continue-using-disabled-channels-while-connected.patch + # END OF PATCH APPLICATIONS %endif @@ -2263,6 +2273,7 @@ fi # || || %changelog * Thu Aug 01 2013 Josh Boyer +- Fix mac80211 connection issues (rhbz 981445) - Fix firmware issues with iwl4965 and rfkill (rhbz 977053) - Drop hid-logitech-dj patch that was breaking enumeration (rhbz 989138) diff --git a/mac80211-continue-using-disabled-channels-while-connected.patch b/mac80211-continue-using-disabled-channels-while-connected.patch new file mode 100644 index 000000000..91dd1d7db --- /dev/null +++ b/mac80211-continue-using-disabled-channels-while-connected.patch @@ -0,0 +1,43 @@ +From ddfe49b42d8ad4bfdf92d63d4a74f162660d878d Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 31 Jul 2013 18:52:03 +0000 +Subject: mac80211: continue using disabled channels while connected + +In case the AP has different regulatory information than we do, +it can happen that we connect to an AP based on e.g. the world +roaming regulatory data, and then update our database with the +AP's country information disables the channel the AP is using. +If this happens on an HT AP, the bandwidth tracking code will +hit the WARN_ON() and disconnect. Since that's not very useful, +ignore the channel-disable flag in bandwidth tracking. + +Cc: stable@vger.kernel.org +Reported-by: Chris Wright +Tested-by: Chris Wright +Signed-off-by: Johannes Berg +--- +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 077a953..cc9e02d 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -335,8 +335,17 @@ out: + if (ret & IEEE80211_STA_DISABLE_VHT) + vht_chandef = *chandef; + ++ /* ++ * Ignore the DISABLED flag when we're already connected and only ++ * tracking the APs beacon for bandwidth changes - otherwise we ++ * might get disconnected here if we connect to an AP, update our ++ * regulatory information based on the AP's country IE and the ++ * information we have is wrong/outdated and disables the channel ++ * that we're actually using for the connection to the AP. ++ */ + while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, +- IEEE80211_CHAN_DISABLED)) { ++ tracking ? 0 : ++ IEEE80211_CHAN_DISABLED)) { + if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { + ret = IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_VHT; +-- +cgit v0.9.2 diff --git a/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch b/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch new file mode 100644 index 000000000..49115f969 --- /dev/null +++ b/mac80211-fix-infinite-loop-in-ieee80211_determine_chantype.patch @@ -0,0 +1,32 @@ +From b56e4b857c5210e848bfb80e074e5756a36cd523 Mon Sep 17 00:00:00 2001 +From: Chris Wright +Date: Wed, 31 Jul 2013 19:12:24 +0000 +Subject: mac80211: fix infinite loop in ieee80211_determine_chantype + +Commit "3d9646d mac80211: fix channel selection bug" introduced a possible +infinite loop by moving the out target above the chandef_downgrade +while loop. When we downgrade to NL80211_CHAN_WIDTH_20_NOHT, we jump +back up to re-run the while loop...indefinitely. Replace goto with +break and carry on. This may not be sufficient to connect to the AP, +but will at least keep the cpu from livelocking. Thanks to Derek Atkins +as an extra pair of debugging eyes. + +Cc: stable@kernel.org +Signed-off-by: Chris Wright +Signed-off-by: Johannes Berg +--- +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index ae31968..e3e7d2b 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -338,7 +338,7 @@ out: + if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { + ret = IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_VHT; +- goto out; ++ break; + } + + ret |= chandef_downgrade(chandef); +-- +cgit v0.9.2 diff --git a/mac80211-ignore-HT-primary-channel-while-connected.patch b/mac80211-ignore-HT-primary-channel-while-connected.patch new file mode 100644 index 000000000..ba5d2a478 --- /dev/null +++ b/mac80211-ignore-HT-primary-channel-while-connected.patch @@ -0,0 +1,121 @@ +From 5cdaed1e878d723d56d04ae0be1738124acf9f46 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 31 Jul 2013 09:23:06 +0000 +Subject: 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 +Signed-off-by: Johannes Berg +--- +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index e5c3cf4..077a953 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -211,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *channel, + const struct ieee80211_ht_operation *ht_oper, + const struct ieee80211_vht_operation *vht_oper, +- struct cfg80211_chan_def *chandef, bool verbose) ++ struct cfg80211_chan_def *chandef, bool tracking) + { ++ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct cfg80211_chan_def vht_chandef; + u32 ht_cfreq, ret; + +@@ -231,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, + channel->band); + /* check that channel matches the right operating channel */ +- if (channel->center_freq != ht_cfreq) { ++ if (!tracking && channel->center_freq != ht_cfreq) { + /* + * It's possible that some APs are confused here; + * Netgear WNDR3700 sometimes reports 4 higher than +@@ -239,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + * since we look at probe response/beacon data here + * it should be OK. + */ +- if (verbose) +- sdata_info(sdata, +- "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", +- channel->center_freq, ht_cfreq, +- ht_oper->primary_chan, channel->band); ++ sdata_info(sdata, ++ "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", ++ channel->center_freq, ht_cfreq, ++ ht_oper->primary_chan, channel->band); + ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; + goto out; + } +@@ -297,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + channel->band); + break; + default: +- if (verbose) ++ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + sdata_info(sdata, + "AP VHT operation IE has invalid channel width (%d), disable VHT\n", + vht_oper->chan_width); +@@ -306,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + } + + if (!cfg80211_chandef_valid(&vht_chandef)) { +- if (verbose) ++ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + sdata_info(sdata, + "AP VHT information is invalid, disable VHT\n"); + ret = IEEE80211_STA_DISABLE_VHT; +@@ -319,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, + } + + if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { +- if (verbose) ++ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + sdata_info(sdata, + "AP VHT information doesn't match HT, disable VHT\n"); + ret = IEEE80211_STA_DISABLE_VHT; +@@ -346,7 +346,7 @@ out: + ret |= chandef_downgrade(chandef); + } + +- if (chandef->width != vht_chandef.width && verbose) ++ if (chandef->width != vht_chandef.width && !tracking) + sdata_info(sdata, + "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); + +@@ -386,7 +386,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, + + /* calculate new channel (type) based on HT/VHT operation IEs */ + flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, +- vht_oper, &chandef, false); ++ vht_oper, &chandef, true); + + /* + * Downgrade the new channel if we associated with restricted +@@ -3838,7 +3838,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, + ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, + cbss->channel, + ht_oper, vht_oper, +- &chandef, true); ++ &chandef, false); + + sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), + local->rx_chains); +-- +cgit v0.9.2