CHROMIUM: iwl7000: improve the flow when a NIC is disconnected When the NIC is disconnected, we just can't do anything besides seeking for help from the bus driver. Dumping the device's memory is not necessary and just bloats the logs with unusable data. Moreover, asking mac80211 to restart the hardware is also useless. Bypass all this. Also, use the STATUS_TRANS_DEAD status bit instead of a bool inside the transport layer. The advantage of this is that now, the transport and the op_mode can know what is the situation and bypass the useless recovery steps mentioned above. BUG=b:35648315 TEST=None Change-Id: I484d2888307426a24178da78700f84f2e9b68018 Signed-off-by: Matt Chen <matt.chen@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> iwl7000-tree: a13b860009cd751e9fb989494712287fb2197b11 Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Reviewed-on: https://chromium-review.googlesource.com/1025750 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: Kirtika Ruchandani <kirtika@chromium.org> Reviewed-by: Kirtika Ruchandani <kirtika@chromium.org>
diff --git a/drivers/net/wireless/iwl7000/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwl7000/iwlwifi/mvm/ops.c index 82ec37f..b250ccf 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwl7000/iwlwifi/mvm/ops.c
@@ -1393,7 +1393,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); schedule_work(&reprobe->work); } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR && - mvm->hw_registered) { + mvm->hw_registered && + !test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { /* don't let the transport/FW power down */ iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); @@ -1408,7 +1409,8 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - iwl_mvm_dump_nic_error_log(mvm); + if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) + iwl_mvm_dump_nic_error_log(mvm); iwl_mvm_nic_restart(mvm, true); }
diff --git a/drivers/net/wireless/iwl7000/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwl7000/iwlwifi/pcie/internal.h index efb2b28..b6067ae 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwl7000/iwlwifi/pcie/internal.h
@@ -384,7 +384,6 @@ struct iwl_self_init_dram { * @fh_mask: current unmasked fh causes * @hw_mask: current unmasked hw causes * @in_rescan: true if we have triggered a device rescan - * @scheduled_for_removal: true if we have scheduled a device removal */ struct iwl_trans_pcie { struct iwl_rxq *rxq; @@ -467,7 +466,6 @@ struct iwl_trans_pcie { u32 hw_mask; cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES]; bool in_rescan; - bool scheduled_for_removal; }; static inline struct iwl_trans_pcie *
diff --git a/drivers/net/wireless/iwl7000/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwl7000/iwlwifi/pcie/trans.c index 388be41..34f8aaa 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwl7000/iwlwifi/pcie/trans.c
@@ -2057,7 +2057,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, if (iwlwifi_mod_params.remove_when_gone && cntrl == ~0U) { struct iwl_trans_pcie_removal *removal; - if (trans_pcie->scheduled_for_removal) + if (test_bit(STATUS_TRANS_DEAD, &trans->status)) goto err; IWL_ERR(trans, "Device gone - scheduling removal!\n"); @@ -2083,7 +2083,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, * we don't need to clear this flag, because * the trans will be freed and reallocated. */ - trans_pcie->scheduled_for_removal = true; + set_bit(STATUS_TRANS_DEAD, &trans->status); removal->pdev = to_pci_dev(trans->dev); INIT_WORK(&removal->work, iwl_trans_pcie_removal_wk); @@ -2294,6 +2294,10 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) unsigned long now = jiffies; u8 wr_ptr; + /* Make sure the NIC is still alive in the bus */ + if (test_bit(STATUS_TRANS_DEAD, &trans->status)) + return -ENODEV; + if (!test_bit(txq_idx, trans_pcie->queue_used)) return -EINVAL;
diff --git a/drivers/net/wireless/iwl7000/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwl7000/iwlwifi/pcie/tx.c index 7619a61..b009615 100644 --- a/drivers/net/wireless/iwl7000/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwl7000/iwlwifi/pcie/tx.c
@@ -1177,6 +1177,10 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans, lockdep_assert_held(&trans_pcie->reg_lock); + /* Make sure the NIC is still alive in the bus */ + if (test_bit(STATUS_TRANS_DEAD, &trans->status)) + return -ENODEV; + if (!(cmd->flags & CMD_SEND_IN_IDLE) && !trans_pcie->ref_cmd_in_flight) { trans_pcie->ref_cmd_in_flight = true; @@ -1939,6 +1943,10 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans, int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) { + /* Make sure the NIC is still alive in the bus */ + if (test_bit(STATUS_TRANS_DEAD, &trans->status)) + return -ENODEV; + if (!(cmd->flags & CMD_SEND_IN_RFKILL) && test_bit(STATUS_RFKILL_OPMODE, &trans->status)) { IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",