diff options
author | Arik Nemtsov <arik@wizery.com> | 2013-12-01 06:50:40 -0500 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2013-12-17 12:39:50 -0500 |
commit | 2a988e98085a76c1a238442e67e53874944cb353 (patch) | |
tree | 57d23374a6823e476d89ffd08535c91e69898f8c | |
parent | 8c678ed4665d9c6452279b770eb43feed32ca3e8 (diff) |
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>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/internal.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/rx.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 6 |
4 files changed, 20 insertions, 15 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c71519d54402..fa495bafa4e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -70,6 +70,7 @@ | |||
70 | #include "iwl-debug.h" | 70 | #include "iwl-debug.h" |
71 | #include "iwl-config.h" | 71 | #include "iwl-config.h" |
72 | #include "iwl-fw.h" | 72 | #include "iwl-fw.h" |
73 | #include "iwl-op-mode.h" | ||
73 | 74 | ||
74 | /** | 75 | /** |
75 | * DOC: Transport layer - what is it ? | 76 | * DOC: Transport layer - what is it ? |
@@ -805,6 +806,16 @@ iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags) | |||
805 | __release(nic_access); | 806 | __release(nic_access); |
806 | } | 807 | } |
807 | 808 | ||
809 | static inline void iwl_trans_fw_error(struct iwl_trans *trans) | ||
810 | { | ||
811 | if (WARN_ON_ONCE(!trans->op_mode)) | ||
812 | return; | ||
813 | |||
814 | /* prevent double restarts due to the same erroneous FW */ | ||
815 | if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status)) | ||
816 | iwl_op_mode_nic_error(trans->op_mode); | ||
817 | } | ||
818 | |||
808 | /***************************************************** | 819 | /***************************************************** |
809 | * driver (transport) register/unregister functions | 820 | * driver (transport) register/unregister functions |
810 | ******************************************************/ | 821 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index 8a2de33df48b..674c75b0d002 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -456,10 +456,4 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans) | |||
456 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | 456 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); |
457 | } | 457 | } |
458 | 458 | ||
459 | static inline void iwl_nic_error(struct iwl_trans *trans) | ||
460 | { | ||
461 | set_bit(STATUS_FW_ERROR, &trans->status); | ||
462 | iwl_op_mode_nic_error(trans->op_mode); | ||
463 | } | ||
464 | |||
465 | #endif /* __iwl_trans_int_pcie_h__ */ | 459 | #endif /* __iwl_trans_int_pcie_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index bbbb3ca400d7..7aeec5ccefa5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -797,14 +797,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans) | |||
797 | iwl_pcie_dump_csr(trans); | 797 | iwl_pcie_dump_csr(trans); |
798 | iwl_dump_fh(trans, NULL); | 798 | iwl_dump_fh(trans, NULL); |
799 | 799 | ||
800 | /* set the ERROR bit before we wake up the caller */ | ||
801 | set_bit(STATUS_FW_ERROR, &trans->status); | ||
802 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); | ||
803 | wake_up(&trans_pcie->wait_command_queue); | ||
804 | |||
805 | local_bh_disable(); | 800 | local_bh_disable(); |
806 | iwl_nic_error(trans); | 801 | /* The STATUS_FW_ERROR bit is set in this function. This must happen |
802 | * before we wake up the command caller, to ensure a proper cleanup. */ | ||
803 | iwl_trans_fw_error(trans); | ||
807 | local_bh_enable(); | 804 | local_bh_enable(); |
805 | |||
806 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); | ||
807 | wake_up(&trans_pcie->wait_command_queue); | ||
808 | } | 808 | } |
809 | 809 | ||
810 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | 810 | irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 5b63948220c9..8df24787c141 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
207 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | 207 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, |
208 | le32_to_cpu(txq->scratchbufs[i].scratch)); | 208 | le32_to_cpu(txq->scratchbufs[i].scratch)); |
209 | 209 | ||
210 | iwl_nic_error(trans); | 210 | iwl_trans_fw_error(trans); |
211 | } | 211 | } |
212 | 212 | ||
213 | /* | 213 | /* |
@@ -1021,7 +1021,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx) | |||
1021 | if (nfreed++ > 0) { | 1021 | if (nfreed++ > 0) { |
1022 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", | 1022 | IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", |
1023 | idx, q->write_ptr, q->read_ptr); | 1023 | idx, q->write_ptr, q->read_ptr); |
1024 | iwl_nic_error(trans); | 1024 | iwl_trans_fw_error(trans); |
1025 | } | 1025 | } |
1026 | } | 1026 | } |
1027 | 1027 | ||
@@ -1555,7 +1555,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, | |||
1555 | get_cmd_string(trans_pcie, cmd->id)); | 1555 | get_cmd_string(trans_pcie, cmd->id)); |
1556 | ret = -ETIMEDOUT; | 1556 | ret = -ETIMEDOUT; |
1557 | 1557 | ||
1558 | iwl_nic_error(trans); | 1558 | iwl_trans_fw_error(trans); |
1559 | 1559 | ||
1560 | goto cancel; | 1560 | goto cancel; |
1561 | } | 1561 | } |