Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a988e98 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Emmanuel Grumbach
Browse files

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: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 8c678ed4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@
#include "iwl-debug.h"
#include "iwl-config.h"
#include "iwl-fw.h"
#include "iwl-op-mode.h"

/**
 * 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);
}

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
******************************************************/
+0 −6
Original line number Diff line number Diff line
@@ -456,10 +456,4 @@ static inline bool iwl_is_rfkill_set(struct iwl_trans *trans)
		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__ */
+6 −6
Original line number Diff line number Diff line
@@ -797,14 +797,14 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
	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)
+3 −3
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
		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);
}

/*
@@ -1021,7 +1021,7 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
		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);
		}
	}

@@ -1555,7 +1555,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
			       get_cmd_string(trans_pcie, cmd->id));
		ret = -ETIMEDOUT;

		iwl_nic_error(trans);
		iwl_trans_fw_error(trans);

		goto cancel;
	}