summarylogtreecommitdiffstats
path: root/0011-iwlwifi-pcie-move-power-gating-workaround-earlier-in.patch
diff options
context:
space:
mode:
Diffstat (limited to '0011-iwlwifi-pcie-move-power-gating-workaround-earlier-in.patch')
-rw-r--r--0011-iwlwifi-pcie-move-power-gating-workaround-earlier-in.patch120
1 files changed, 120 insertions, 0 deletions
diff --git a/0011-iwlwifi-pcie-move-power-gating-workaround-earlier-in.patch b/0011-iwlwifi-pcie-move-power-gating-workaround-earlier-in.patch
new file mode 100644
index 000000000000..04a7ea6e2dd4
--- /dev/null
+++ b/0011-iwlwifi-pcie-move-power-gating-workaround-earlier-in.patch
@@ -0,0 +1,120 @@
+From 9894b27702c2e6090213f84db3e3d47f191253cd Mon Sep 17 00:00:00 2001
+From: Luca Coelho <luciano.coelho@intel.com>
+Date: Thu, 5 Dec 2019 09:03:54 +0200
+Subject: [PATCH 11/20] iwlwifi: pcie: move power gating workaround earlier in
+ the flow
+
+We need to reset the NIC after setting the bits to enable power
+gating and that cannot be done too late in the flow otherwise it
+cleans other registers and things that were already configured,
+causing initialization to fail.
+
+In order to fix this, move the function to the common code in trans.c
+so it can be called directly from there at an earlier point, just
+after the reset we already do during initialization.
+
+Fixes: 9a47cb988338 ("iwlwifi: pcie: add workaround for power gating in integrated 22000")
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=205719
+Cc: stable@ver.kernel.org # 5.4+
+Reported-by: Anders Kaseorg <andersk@mit.edu>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 25 ----------------
+ .../net/wireless/intel/iwlwifi/pcie/trans.c | 30 +++++++++++++++++++
+ 2 files changed, 30 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+index ca3bb4d65b00..df8455f14e4d 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+@@ -57,24 +57,6 @@
+ #include "internal.h"
+ #include "fw/dbg.h"
+
+-static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
+-{
+- iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+- HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+- udelay(20);
+- iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+- HPM_HIPM_GEN_CFG_CR_PG_EN |
+- HPM_HIPM_GEN_CFG_CR_SLP_EN);
+- udelay(20);
+- iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
+- HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+-
+- iwl_trans_sw_reset(trans);
+- iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+-
+- return 0;
+-}
+-
+ /*
+ * Start up NIC's basic functionality after it has been reset
+ * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
+@@ -110,13 +92,6 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
+
+ iwl_pcie_apm_config(trans);
+
+- if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+- trans->cfg->integrated) {
+- ret = iwl_pcie_gen2_force_power_gating(trans);
+- if (ret)
+- return ret;
+- }
+-
+ ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+ if (ret)
+ return ret;
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+index 6961f00ff812..d3db38c3095b 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+@@ -1783,6 +1783,29 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
+ return 0;
+ }
+
++static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
++{
++ int ret;
++
++ ret = iwl_finish_nic_init(trans, trans->trans_cfg);
++ if (ret < 0)
++ return ret;
++
++ iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
++ HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
++ udelay(20);
++ iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
++ HPM_HIPM_GEN_CFG_CR_PG_EN |
++ HPM_HIPM_GEN_CFG_CR_SLP_EN);
++ udelay(20);
++ iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
++ HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
++
++ iwl_trans_pcie_sw_reset(trans);
++
++ return 0;
++}
++
+ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
+ {
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+@@ -1802,6 +1825,13 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
+
+ iwl_trans_pcie_sw_reset(trans);
+
++ if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
++ trans->cfg->integrated) {
++ err = iwl_pcie_gen2_force_power_gating(trans);
++ if (err)
++ return err;
++ }
++
+ err = iwl_pcie_apm_init(trans);
+ if (err)
+ return err;
+--
+2.24.1
+