iwl-trans: iwlwifi: move sync NMI logic to trans
The code is not directly related to PCIe transport, and it will help moving sync/async commands logic out of PCIe in the next patches. Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/iwlwifi.20210117130510.271f59887fd1.I8ff41236f4e11a25df83d76c982a2a30ba2b9903@changeid Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
25edc8f259
commit
3161a34d65
|
@ -445,3 +445,39 @@ int iwl_finish_nic_init(struct iwl_trans *trans,
|
||||||
return err < 0 ? err : 0;
|
return err < 0 ? err : 0;
|
||||||
}
|
}
|
||||||
IWL_EXPORT_SYMBOL(iwl_finish_nic_init);
|
IWL_EXPORT_SYMBOL(iwl_finish_nic_init);
|
||||||
|
|
||||||
|
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
|
||||||
|
u32 sw_err_bit)
|
||||||
|
{
|
||||||
|
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
|
||||||
|
bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
|
||||||
|
|
||||||
|
/* if the interrupts were already disabled, there is no point in
|
||||||
|
* calling iwl_disable_interrupts
|
||||||
|
*/
|
||||||
|
if (interrupts_enabled)
|
||||||
|
iwl_trans_interrupts(trans, false);
|
||||||
|
|
||||||
|
iwl_force_nmi(trans);
|
||||||
|
while (time_after(timeout, jiffies)) {
|
||||||
|
u32 inta_hw = iwl_read32(trans, inta_addr);
|
||||||
|
|
||||||
|
/* Error detected by uCode */
|
||||||
|
if (inta_hw & sw_err_bit) {
|
||||||
|
/* Clear causes register */
|
||||||
|
iwl_write32(trans, inta_addr, inta_hw & sw_err_bit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable interrupts only if there were already enabled before this
|
||||||
|
* function to avoid a case were the driver enable interrupts before
|
||||||
|
* proper configurations were made
|
||||||
|
*/
|
||||||
|
if (interrupts_enabled)
|
||||||
|
iwl_trans_interrupts(trans, true);
|
||||||
|
|
||||||
|
iwl_trans_fw_error(trans);
|
||||||
|
}
|
||||||
|
|
|
@ -514,6 +514,7 @@ struct iwl_trans_rxq_dma_data {
|
||||||
* of the trans debugfs
|
* of the trans debugfs
|
||||||
* @set_pnvm: set the pnvm data in the prph scratch buffer, inside the
|
* @set_pnvm: set the pnvm data in the prph scratch buffer, inside the
|
||||||
* context info.
|
* context info.
|
||||||
|
* @interrupts: disable/enable interrupts to transport
|
||||||
*/
|
*/
|
||||||
struct iwl_trans_ops {
|
struct iwl_trans_ops {
|
||||||
|
|
||||||
|
@ -587,6 +588,7 @@ struct iwl_trans_ops {
|
||||||
void (*debugfs_cleanup)(struct iwl_trans *trans);
|
void (*debugfs_cleanup)(struct iwl_trans *trans);
|
||||||
void (*sync_nmi)(struct iwl_trans *trans);
|
void (*sync_nmi)(struct iwl_trans *trans);
|
||||||
int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len);
|
int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len);
|
||||||
|
void (*interrupts)(struct iwl_trans *trans, bool enable);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1409,6 +1411,9 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||||
trans->ops->sync_nmi(trans);
|
trans->ops->sync_nmi(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr,
|
||||||
|
u32 sw_err_bit);
|
||||||
|
|
||||||
static inline int iwl_trans_set_pnvm(struct iwl_trans *trans,
|
static inline int iwl_trans_set_pnvm(struct iwl_trans *trans,
|
||||||
const void *data, u32 len)
|
const void *data, u32 len)
|
||||||
{
|
{
|
||||||
|
@ -1430,6 +1435,12 @@ static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans)
|
||||||
trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED;
|
trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void iwl_trans_interrupts(struct iwl_trans *trans, bool enable)
|
||||||
|
{
|
||||||
|
if (trans->ops->interrupts)
|
||||||
|
trans->ops->interrupts(trans, enable);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************
|
/*****************************************************
|
||||||
* transport helper functions
|
* transport helper functions
|
||||||
*****************************************************/
|
*****************************************************/
|
||||||
|
|
|
@ -760,7 +760,6 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
|
||||||
|
|
||||||
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
|
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
|
||||||
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
|
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
|
||||||
void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans);
|
|
||||||
|
|
||||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
|
void iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
|
||||||
|
|
|
@ -3284,6 +3284,30 @@ static struct iwl_trans_dump_data
|
||||||
return dump_data;
|
return dump_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iwl_trans_pci_interrupts(struct iwl_trans *trans, bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
iwl_enable_interrupts(trans);
|
||||||
|
else
|
||||||
|
iwl_disable_interrupts(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
||||||
|
{
|
||||||
|
u32 inta_addr, sw_err_bit;
|
||||||
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
|
|
||||||
|
if (trans_pcie->msix_enabled) {
|
||||||
|
inta_addr = CSR_MSIX_HW_INT_CAUSES_AD;
|
||||||
|
sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
|
||||||
|
} else {
|
||||||
|
inta_addr = CSR_INT;
|
||||||
|
sw_err_bit = CSR_INT_BIT_SW_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
iwl_trans_sync_nmi_with_addr(trans, inta_addr, sw_err_bit);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
|
static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
|
||||||
{
|
{
|
||||||
|
@ -3314,7 +3338,8 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
|
||||||
.dump_data = iwl_trans_pcie_dump_data, \
|
.dump_data = iwl_trans_pcie_dump_data, \
|
||||||
.d3_suspend = iwl_trans_pcie_d3_suspend, \
|
.d3_suspend = iwl_trans_pcie_d3_suspend, \
|
||||||
.d3_resume = iwl_trans_pcie_d3_resume, \
|
.d3_resume = iwl_trans_pcie_d3_resume, \
|
||||||
.sync_nmi = iwl_trans_pcie_sync_nmi
|
.interrupts = iwl_trans_pci_interrupts, \
|
||||||
|
.sync_nmi = iwl_trans_pcie_sync_nmi \
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
#define IWL_TRANS_PM_OPS \
|
#define IWL_TRANS_PM_OPS \
|
||||||
|
@ -3536,48 +3561,3 @@ out_free_trans:
|
||||||
iwl_trans_free(trans);
|
iwl_trans_free(trans);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
|
||||||
{
|
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
||||||
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
|
|
||||||
bool interrupts_enabled = test_bit(STATUS_INT_ENABLED, &trans->status);
|
|
||||||
u32 inta_addr, sw_err_bit;
|
|
||||||
|
|
||||||
if (trans_pcie->msix_enabled) {
|
|
||||||
inta_addr = CSR_MSIX_HW_INT_CAUSES_AD;
|
|
||||||
sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
|
|
||||||
} else {
|
|
||||||
inta_addr = CSR_INT;
|
|
||||||
sw_err_bit = CSR_INT_BIT_SW_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if the interrupts were already disabled, there is no point in
|
|
||||||
* calling iwl_disable_interrupts
|
|
||||||
*/
|
|
||||||
if (interrupts_enabled)
|
|
||||||
iwl_disable_interrupts(trans);
|
|
||||||
|
|
||||||
iwl_force_nmi(trans);
|
|
||||||
while (time_after(timeout, jiffies)) {
|
|
||||||
u32 inta_hw = iwl_read32(trans, inta_addr);
|
|
||||||
|
|
||||||
/* Error detected by uCode */
|
|
||||||
if (inta_hw & sw_err_bit) {
|
|
||||||
/* Clear causes register */
|
|
||||||
iwl_write32(trans, inta_addr, inta_hw & sw_err_bit);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mdelay(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* enable interrupts only if there were already enabled before this
|
|
||||||
* function to avoid a case were the driver enable interrupts before
|
|
||||||
* proper configurations were made
|
|
||||||
*/
|
|
||||||
if (interrupts_enabled)
|
|
||||||
iwl_enable_interrupts(trans);
|
|
||||||
|
|
||||||
iwl_trans_fw_error(trans);
|
|
||||||
}
|
|
||||||
|
|
|
@ -303,7 +303,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
|
||||||
cmd_str);
|
cmd_str);
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
|
||||||
iwl_trans_pcie_sync_nmi(trans);
|
iwl_trans_sync_nmi(trans);
|
||||||
goto cancel;
|
goto cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1320,7 +1320,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
|
||||||
iwl_get_cmd_string(trans, cmd->id));
|
iwl_get_cmd_string(trans, cmd->id));
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
|
||||||
iwl_trans_pcie_sync_nmi(trans);
|
iwl_trans_sync_nmi(trans);
|
||||||
goto cancel;
|
goto cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue