Commit 15bf5ac6 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho

iwlwifi: pcie: retake ownership after reset

In most cases, unless shutting down the NIC, we really need
to retake ownership after doing a software reset of the NIC.
Encode that into the API so we "automatically" do it, even
in case of workarounds, and don't keep forgetting it like a
few of the places we have did.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20211204174545.458f9d98ac21.I40b9a22df1ab8178cc838fc83d5190e689dfac6a@changeidSigned-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent b780c10f
...@@ -212,7 +212,9 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu ...@@ -212,7 +212,9 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
IWL_ERR(trans, "HW error, resetting before reading\n"); IWL_ERR(trans, "HW error, resetting before reading\n");
/* reset the device */ /* reset the device */
iwl_trans_sw_reset(trans); err = iwl_trans_sw_reset(trans, true);
if (err)
return;
err = iwl_finish_nic_init(trans); err = iwl_finish_nic_init(trans);
if (err) if (err)
......
...@@ -593,7 +593,7 @@ struct iwl_trans_ops { ...@@ -593,7 +593,7 @@ struct iwl_trans_ops {
void (*configure)(struct iwl_trans *trans, void (*configure)(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg); const struct iwl_trans_config *trans_cfg);
void (*set_pmi)(struct iwl_trans *trans, bool state); void (*set_pmi)(struct iwl_trans *trans, bool state);
void (*sw_reset)(struct iwl_trans *trans); int (*sw_reset)(struct iwl_trans *trans, bool retake_ownership);
bool (*grab_nic_access)(struct iwl_trans *trans); bool (*grab_nic_access)(struct iwl_trans *trans);
void (*release_nic_access)(struct iwl_trans *trans); void (*release_nic_access)(struct iwl_trans *trans);
void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask, void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask,
...@@ -1386,10 +1386,12 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) ...@@ -1386,10 +1386,12 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
trans->ops->set_pmi(trans, state); trans->ops->set_pmi(trans, state);
} }
static inline void iwl_trans_sw_reset(struct iwl_trans *trans) static inline int iwl_trans_sw_reset(struct iwl_trans *trans,
bool retake_ownership)
{ {
if (trans->ops->sw_reset) if (trans->ops->sw_reset)
trans->ops->sw_reset(trans); return trans->ops->sw_reset(trans, retake_ownership);
return 0;
} }
static inline void static inline void
......
...@@ -81,7 +81,7 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave) ...@@ -81,7 +81,7 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
/* Stop device's DMA activity */ /* Stop device's DMA activity */
iwl_pcie_apm_stop_master(trans); iwl_pcie_apm_stop_master(trans);
iwl_trans_sw_reset(trans); iwl_trans_sw_reset(trans, false);
/* /*
* Clear "initialization complete" bit to move adapter from * Clear "initialization complete" bit to move adapter from
...@@ -166,7 +166,8 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) ...@@ -166,7 +166,8 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_pcie_gen2_apm_stop(trans, false); iwl_pcie_gen2_apm_stop(trans, false);
iwl_trans_sw_reset(trans); /* re-take ownership to prevent other users from stealing the device */
iwl_trans_sw_reset(trans, true);
/* /*
* Upon stop, the IVAR table gets erased, so msi-x won't * Upon stop, the IVAR table gets erased, so msi-x won't
...@@ -196,9 +197,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) ...@@ -196,9 +197,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
* interrupt * interrupt
*/ */
iwl_enable_rfkill_int(trans); iwl_enable_rfkill_int(trans);
/* re-take ownership to prevent other users from stealing the device */
iwl_pcie_prepare_card_hw(trans);
} }
void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
......
...@@ -127,7 +127,8 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans) ...@@ -127,7 +127,8 @@ void iwl_trans_pcie_dump_regs(struct iwl_trans *trans)
kfree(buf); kfree(buf);
} }
static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans) static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans,
bool retake_ownership)
{ {
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */ /* Reset entire device - do controller reset (results in SHRD_HW_RST) */
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
...@@ -137,6 +138,11 @@ static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans) ...@@ -137,6 +138,11 @@ static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
iwl_set_bit(trans, CSR_RESET, iwl_set_bit(trans, CSR_RESET,
CSR_RESET_REG_FLAG_SW_RESET); CSR_RESET_REG_FLAG_SW_RESET);
usleep_range(5000, 6000); usleep_range(5000, 6000);
if (retake_ownership)
return iwl_pcie_prepare_card_hw(trans);
return 0;
} }
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans) static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
...@@ -382,9 +388,11 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) ...@@ -382,9 +388,11 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_XTAL_ON); CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
iwl_trans_pcie_sw_reset(trans); ret = iwl_trans_pcie_sw_reset(trans, true);
if (!ret)
ret = iwl_finish_nic_init(trans);
ret = iwl_finish_nic_init(trans);
if (WARN_ON(ret)) { if (WARN_ON(ret)) {
/* Release XTAL ON request */ /* Release XTAL ON request */
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL, __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
...@@ -409,7 +417,10 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans) ...@@ -409,7 +417,10 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
apmg_xtal_cfg_reg | apmg_xtal_cfg_reg |
SHR_APMG_XTAL_CFG_XTAL_ON_REQ); SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
iwl_trans_pcie_sw_reset(trans); ret = iwl_trans_pcie_sw_reset(trans, true);
if (ret)
IWL_ERR(trans,
"iwl_pcie_apm_lp_xtal_enable: failed to retake NIC ownership\n");
/* Enable LP XTAL by indirect access through CSR */ /* Enable LP XTAL by indirect access through CSR */
apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG); apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG);
...@@ -515,7 +526,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave) ...@@ -515,7 +526,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
return; return;
} }
iwl_trans_pcie_sw_reset(trans); iwl_trans_pcie_sw_reset(trans, false);
/* /*
* Clear "initialization complete" bit to move adapter from * Clear "initialization complete" bit to move adapter from
...@@ -1261,7 +1272,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans) ...@@ -1261,7 +1272,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
/* Stop the device, and put it in low power state */ /* Stop the device, and put it in low power state */
iwl_pcie_apm_stop(trans, false); iwl_pcie_apm_stop(trans, false);
iwl_trans_pcie_sw_reset(trans); /* re-take ownership to prevent other users from stealing the device */
iwl_trans_pcie_sw_reset(trans, true);
/* /*
* Upon stop, the IVAR table gets erased, so msi-x won't * Upon stop, the IVAR table gets erased, so msi-x won't
...@@ -1291,9 +1303,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans) ...@@ -1291,9 +1303,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
* interrupt * interrupt
*/ */
iwl_enable_rfkill_int(trans); iwl_enable_rfkill_int(trans);
/* re-take ownership to prevent other users from stealing the device */
iwl_pcie_prepare_card_hw(trans);
} }
void iwl_pcie_synchronize_irqs(struct iwl_trans *trans) void iwl_pcie_synchronize_irqs(struct iwl_trans *trans)
...@@ -1802,9 +1811,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans) ...@@ -1802,9 +1811,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG, iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE); HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
iwl_trans_pcie_sw_reset(trans); return iwl_trans_pcie_sw_reset(trans, true);
return 0;
} }
static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans) static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
...@@ -1824,7 +1831,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans) ...@@ -1824,7 +1831,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
if (err) if (err)
return err; return err;
iwl_trans_pcie_sw_reset(trans); err = iwl_trans_pcie_sw_reset(trans, true);
if (err)
return err;
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 && if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
trans->trans_cfg->integrated) { trans->trans_cfg->integrated) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment