iwlwifi: pcie: move power gating workaround earlier in the flow
commit 0df36b90c47d93295b7e393da2d961b2f3b6cde4 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b3ead320dc
commit
f5d43e9ec1
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user