From: Greg Kroah-Hartman Date: Fri, 22 Sep 2017 16:22:19 +0000 (+0200) Subject: 4.13-stable patches X-Git-Tag: v3.18.72~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6892229fd81dbe1b5193969ff28645a921732d36;p=thirdparty%2Fkernel%2Fstable-queue.git 4.13-stable patches added patches: iwlwifi-add-workaround-to-disable-wide-channels-in-5ghz.patch --- diff --git a/queue-4.13/iwlwifi-add-workaround-to-disable-wide-channels-in-5ghz.patch b/queue-4.13/iwlwifi-add-workaround-to-disable-wide-channels-in-5ghz.patch new file mode 100644 index 00000000000..d3d0144676a --- /dev/null +++ b/queue-4.13/iwlwifi-add-workaround-to-disable-wide-channels-in-5ghz.patch @@ -0,0 +1,189 @@ +From 01a9c948a09348950515bf2abb6113ed83e696d8 Mon Sep 17 00:00:00 2001 +From: Luca Coelho +Date: Tue, 15 Aug 2017 20:48:41 +0300 +Subject: iwlwifi: add workaround to disable wide channels in 5GHz + +From: Luca Coelho + +commit 01a9c948a09348950515bf2abb6113ed83e696d8 upstream. + +The OTP in some SKUs have erroneously allowed 40MHz and 80MHz channels +in the 5.2GHz band. The firmware has been modified to not allow this +in those SKUs, so the driver needs to do the same otherwise the +firmware will assert when we try to use it. + +Signed-off-by: Luca Coelho +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 62 +++++++++++++++++---- + drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h | 3 - + drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 3 - + 3 files changed, 56 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +@@ -79,6 +79,7 @@ + /* NVM offsets (in words) definitions */ + enum wkp_nvm_offsets { + /* NVM HW-Section offset (in words) definitions */ ++ SUBSYSTEM_ID = 0x0A, + HW_ADDR = 0x15, + + /* NVM SW-Section offset (in words) definitions */ +@@ -254,13 +255,12 @@ static u32 iwl_get_channel_flags(u8 ch_n + static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, + struct iwl_nvm_data *data, + const __le16 * const nvm_ch_flags, +- bool lar_supported) ++ bool lar_supported, bool no_wide_in_5ghz) + { + int ch_idx; + int n_channels = 0; + struct ieee80211_channel *channel; + u16 ch_flags; +- bool is_5ghz; + int num_of_ch, num_2ghz_channels; + const u8 *nvm_chan; + +@@ -275,12 +275,20 @@ static int iwl_init_channel_map(struct d + } + + for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { ++ bool is_5ghz = (ch_idx >= num_2ghz_channels); ++ + ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); + +- if (ch_idx >= num_2ghz_channels && +- !data->sku_cap_band_52GHz_enable) ++ if (is_5ghz && !data->sku_cap_band_52GHz_enable) + continue; + ++ /* workaround to disable wide channels in 5GHz */ ++ if (no_wide_in_5ghz && is_5ghz) { ++ ch_flags &= ~(NVM_CHANNEL_40MHZ | ++ NVM_CHANNEL_80MHZ | ++ NVM_CHANNEL_160MHZ); ++ } ++ + if (ch_flags & NVM_CHANNEL_160MHZ) + data->vht160_supported = true; + +@@ -303,8 +311,8 @@ static int iwl_init_channel_map(struct d + n_channels++; + + channel->hw_value = nvm_chan[ch_idx]; +- channel->band = (ch_idx < num_2ghz_channels) ? +- NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; ++ channel->band = is_5ghz ? ++ NL80211_BAND_5GHZ : NL80211_BAND_2GHZ; + channel->center_freq = + ieee80211_channel_to_frequency( + channel->hw_value, channel->band); +@@ -316,7 +324,6 @@ static int iwl_init_channel_map(struct d + * is not used in mvm, and is used for backwards compatibility + */ + channel->max_power = IWL_DEFAULT_MAX_TX_POWER; +- is_5ghz = channel->band == NL80211_BAND_5GHZ; + + /* don't put limitations in case we're using LAR */ + if (!lar_supported) +@@ -432,14 +439,15 @@ static void iwl_init_vht_hw_capab(const + + void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, + struct iwl_nvm_data *data, const __le16 *nvm_ch_flags, +- u8 tx_chains, u8 rx_chains, bool lar_supported) ++ u8 tx_chains, u8 rx_chains, bool lar_supported, ++ bool no_wide_in_5ghz) + { + int n_channels; + int n_used = 0; + struct ieee80211_supported_band *sband; + + n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags, +- lar_supported); ++ lar_supported, no_wide_in_5ghz); + sband = &data->bands[NL80211_BAND_2GHZ]; + sband->band = NL80211_BAND_2GHZ; + sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; +@@ -645,6 +653,39 @@ static int iwl_set_hw_address(struct iwl + return 0; + } + ++static bool ++iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg, ++ const __le16 *nvm_hw) ++{ ++ /* ++ * Workaround a bug in Indonesia SKUs where the regulatory in ++ * some 7000-family OTPs erroneously allow wide channels in ++ * 5GHz. To check for Indonesia, we take the SKU value from ++ * bits 1-4 in the subsystem ID and check if it is either 5 or ++ * 9. In those cases, we need to force-disable wide channels ++ * in 5GHz otherwise the FW will throw a sysassert when we try ++ * to use them. ++ */ ++ if (cfg->device_family == IWL_DEVICE_FAMILY_7000) { ++ /* ++ * Unlike the other sections in the NVM, the hw ++ * section uses big-endian. ++ */ ++ u16 subsystem_id = be16_to_cpup((const __be16 *)nvm_hw ++ + SUBSYSTEM_ID); ++ u8 sku = (subsystem_id & 0x1e) >> 1; ++ ++ if (sku == 5 || sku == 9) { ++ IWL_DEBUG_EEPROM(dev, ++ "disabling wide channels in 5GHz (0x%0x %d)\n", ++ subsystem_id, sku); ++ return true; ++ } ++ } ++ ++ return false; ++} ++ + struct iwl_nvm_data * + iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, + const __le16 *nvm_hw, const __le16 *nvm_sw, +@@ -655,6 +696,7 @@ iwl_parse_nvm_data(struct iwl_trans *tra + struct device *dev = trans->dev; + struct iwl_nvm_data *data; + bool lar_enabled; ++ bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw); + u32 sku, radio_cfg; + u16 lar_config; + const __le16 *ch_section; +@@ -725,7 +767,7 @@ iwl_parse_nvm_data(struct iwl_trans *tra + } + + iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains, +- lar_fw_supported && lar_enabled); ++ lar_fw_supported && lar_enabled, no_wide_in_5ghz); + data->calib_version = 255; + + return data; +--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h ++++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h +@@ -93,7 +93,8 @@ void iwl_set_hw_address_from_csr(struct + */ + void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, + struct iwl_nvm_data *data, const __le16 *nvm_ch_flags, +- u8 tx_chains, u8 rx_chains, bool lar_supported); ++ u8 tx_chains, u8 rx_chains, bool lar_supported, ++ bool no_wide_in_5ghz); + + /** + * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW +--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +@@ -628,7 +628,8 @@ int iwl_mvm_nvm_get_from_fw(struct iwl_m + rsp->regulatory.channel_profile, + mvm->nvm_data->valid_tx_ant & mvm->fw->valid_tx_ant, + mvm->nvm_data->valid_rx_ant & mvm->fw->valid_rx_ant, +- rsp->regulatory.lar_enabled && lar_fw_supported); ++ rsp->regulatory.lar_enabled && lar_fw_supported, ++ false); + + iwl_free_resp(&hcmd); + return 0; diff --git a/queue-4.13/series b/queue-4.13/series index 5b37e561ce4..8bd06370011 100644 --- a/queue-4.13/series +++ b/queue-4.13/series @@ -99,3 +99,4 @@ bcache-fix-sequential-large-write-io-bypass.patch bcache-fix-for-gc-and-write-back-race.patch bcache-fix-bch_hprint-crash-and-improve-output.patch sched-cpuset-pm-fix-cpuset-vs.-suspend-resume-bugs.patch +iwlwifi-add-workaround-to-disable-wide-channels-in-5ghz.patch