#include "iwl-debug.h"
 #include "iwl-config.h"
 #include "iwl-fw.h"
+#include "iwl-op-mode.h"
 
 /**
  * DOC: Transport layer - what is it ?
        __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
 ******************************************************/
 
                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__ */
 
        iwl_pcie_dump_csr(trans);
        iwl_dump_fh(trans, NULL);
 
-       /* set the ERROR bit before we wake up the caller */
-       set_bit(STATUS_FW_ERROR, &trans->status);
-       clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
-       wake_up(&trans_pcie->wait_command_queue);
-
        local_bh_disable();
-       iwl_nic_error(trans);
+       /* 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);
+       wake_up(&trans_pcie->wait_command_queue);
 }
 
 irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
                IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
                        le32_to_cpu(txq->scratchbufs[i].scratch));
 
-       iwl_nic_error(trans);
+       iwl_trans_fw_error(trans);
 }
 
 /*
                if (nfreed++ > 0) {
                        IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
                                idx, q->write_ptr, q->read_ptr);
-                       iwl_nic_error(trans);
+                       iwl_trans_fw_error(trans);
                }
        }
 
                               get_cmd_string(trans_pcie, cmd->id));
                ret = -ETIMEDOUT;
 
-               iwl_nic_error(trans);
+               iwl_trans_fw_error(trans);
 
                goto cancel;
        }