]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 Sep 2017 16:22:19 +0000 (18:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 Sep 2017 16:22:19 +0000 (18:22 +0200)
added patches:
iwlwifi-add-workaround-to-disable-wide-channels-in-5ghz.patch

queue-4.13/iwlwifi-add-workaround-to-disable-wide-channels-in-5ghz.patch [new file with mode: 0644]
queue-4.13/series

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 (file)
index 0000000..d3d0144
--- /dev/null
@@ -0,0 +1,189 @@
+From 01a9c948a09348950515bf2abb6113ed83e696d8 Mon Sep 17 00:00:00 2001
+From: Luca Coelho <luciano.coelho@intel.com>
+Date: Tue, 15 Aug 2017 20:48:41 +0300
+Subject: iwlwifi: add workaround to disable wide channels in 5GHz
+
+From: Luca Coelho <luciano.coelho@intel.com>
+
+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 <luciano.coelho@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
index 5b37e561ce4d1a063be53cc77a12a717ed4fd904..8bd06370011450444c460b0413bf29dbc43e9e8f 100644 (file)
@@ -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