iwlwifi: improve the flow when a NIC is disconnected
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 1 May 2018 11:23:56 +0000 (14:23 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 31 Aug 2018 08:38:31 +0000 (11:38 +0300)
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.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index d275832dbb145e42277816d7c941dcee4d8cedf6..da1aafb7129869dc7831ee405823baee85ffe061 100644 (file)
@@ -1254,7 +1254,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);
 
@@ -1269,7 +1270,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);
 }
index 8fdef4a26db4c04ed0cf47124d077a3ae93d063e..1089e6b216aa94b9bf353521662465e13a437d40 100644 (file)
@@ -480,7 +480,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;
@@ -573,7 +572,6 @@ struct iwl_trans_pcie {
        cpumask_t affinity_mask[IWL_MAX_RX_HW_QUEUES];
        u16 tx_cmd_queue_size;
        bool in_rescan;
-       bool scheduled_for_removal;
 };
 
 static inline struct iwl_trans_pcie *
index cf7d1acc8e7a64ebdcdf7306f8dff5be37a2a39e..2a20999d4c15ff8498182133002594ba909c9805 100644 (file)
@@ -2013,7 +2013,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");
@@ -2039,7 +2039,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);
@@ -2267,8 +2267,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
        u8 wr_ptr;
 
        /* Make sure the NIC is still alive in the bus */
-       if (trans_pcie->scheduled_for_removal)
-               return -EIO;
+       if (test_bit(STATUS_TRANS_DEAD, &trans->status))
+               return -ENODEV;
 
        if (!test_bit(txq_idx, trans_pcie->queue_used))
                return -EINVAL;
index d5aba9ebd84aaf7d84face36ac69b2f7d26d785b..b89e976ecfcdccf397ee67d2e7d70b204ada80ca 100644 (file)
@@ -1189,8 +1189,8 @@ 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 (trans_pcie->scheduled_for_removal)
-               return -EIO;
+       if (test_bit(STATUS_TRANS_DEAD, &trans->status))
+               return -ENODEV;
 
        if (!(cmd->flags & CMD_SEND_IN_IDLE) &&
            !trans_pcie->ref_cmd_in_flight) {
@@ -1961,11 +1961,9 @@ cancel:
 
 int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
        /* Make sure the NIC is still alive in the bus */
-       if (trans_pcie->scheduled_for_removal)
-               return -EIO;
+       if (test_bit(STATUS_TRANS_DEAD, &trans->status))
+               return -ENODEV;
 
        if (!(cmd->flags & CMD_SEND_IN_RFKILL) &&
            test_bit(STATUS_RFKILL_OPMODE, &trans->status)) {