mirror of https://gitee.com/openkylin/linux.git
iwlwifi: trans: prevent reprobe on repeated FW errors before restart
In case a sync command timeouts or Tx is stuck while a FW error interrupt arrives, we might call iwl_op_mode_nic_error twice before a restart has been initiated. This will cause a reprobe. Unify calls to this function at the transport level and only call it on the first FW error in a given by checking the transport FW error flag. While at it, remove the privately defined iwl_nic_error from PCIE code and use the common callback instead. Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
parent
8c678ed466
commit
2a988e9808
|
@ -70,6 +70,7 @@
|
||||||
#include "iwl-debug.h"
|
#include "iwl-debug.h"
|
||||||
#include "iwl-config.h"
|
#include "iwl-config.h"
|
||||||
#include "iwl-fw.h"
|
#include "iwl-fw.h"
|
||||||
|
#include "iwl-op-mode.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DOC: Transport layer - what is it ?
|
* DOC: Transport layer - what is it ?
|
||||||
|
@ -805,6 +806,16 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)
|
||||||
__release(nic_access);
|
__release(nic_access);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void iwl_trans_fw_error(struct iwl_trans *trans)
|
||||||
|
{
|
||||||
|
if (WARN_ON_ONCE(!trans->op_mode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* prevent double restarts due to the same erroneous FW */
|
||||||
|
if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status))
|
||||||
|
iwl_op_mode_nic_error(trans->op_mode);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************
|
/*****************************************************
|
||||||
* driver (transport) register/unregister functions
|
* driver (transport) register/unregister functions
|
||||||
******************************************************/
|
******************************************************/
|
||||||
|
|
|
@ -456,10 +456,4 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
|
||||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void iwl_nic_error(struct iwl_trans *trans)
|
|
||||||
{
|
|
||||||
set_bit(STATUS_FW_ERROR, &trans->status);
|
|
||||||
iwl_op_mode_nic_error(trans->op_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __iwl_trans_int_pcie_h__ */
|
#endif /* __iwl_trans_int_pcie_h__ */
|
||||||
|
|
|
@ -797,14 +797,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
|
||||||
iwl_pcie_dump_csr(trans);
|
iwl_pcie_dump_csr(trans);
|
||||||
iwl_dump_fh(trans, NULL);
|
iwl_dump_fh(trans, NULL);
|
||||||
|
|
||||||
/* set the ERROR bit before we wake up the caller */
|
local_bh_disable();
|
||||||
set_bit(STATUS_FW_ERROR, &trans->status);
|
/* The STATUS_FW_ERROR bit is set in this function. This must happen
|
||||||
|
* before we wake up the command caller, to ensure a proper cleanup. */
|
||||||
|
iwl_trans_fw_error(trans);
|
||||||
|
local_bh_enable();
|
||||||
|
|
||||||
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
|
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
|
||||||
wake_up(&trans_pcie->wait_command_queue);
|
wake_up(&trans_pcie->wait_command_queue);
|
||||||
|
|
||||||
local_bh_disable();
|
|
||||||
iwl_nic_error(trans);
|
|
||||||
local_bh_enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
|
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
|
||||||
|
|
|
@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
|
||||||
IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
|
IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
|
||||||
le32_to_cpu(txq->scratchbufs[i].scratch));
|
le32_to_cpu(txq->scratchbufs[i].scratch));
|
||||||
|
|
||||||
iwl_nic_error(trans);
|
iwl_trans_fw_error(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1021,7 +1021,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
|
||||||
if (nfreed++ > 0) {
|
if (nfreed++ > 0) {
|
||||||
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
|
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
|
||||||
idx, q->write_ptr, q->read_ptr);
|
idx, q->write_ptr, q->read_ptr);
|
||||||
iwl_nic_error(trans);
|
iwl_trans_fw_error(trans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1555,7 +1555,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
|
||||||
get_cmd_string(trans_pcie, cmd->id));
|
get_cmd_string(trans_pcie, cmd->id));
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
|
||||||
iwl_nic_error(trans);
|
iwl_trans_fw_error(trans);
|
||||||
|
|
||||||
goto cancel;
|
goto cancel;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue