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

Commit 23b40ede authored by Mordechay Goodstein's avatar Mordechay Goodstein Committed by Greg Kroah-Hartman
Browse files

iwlwifi: mvm: retry init flow if failed



commit 5283dd677e52af9db6fe6ad11b2f12220d519d0c upstream.

In some very rare cases the init flow may fail.  In many cases, this is
recoverable, so we can retry.  Implement a loop to retry two more times
after the first attempt failed.

This can happen in two different situations, namely during probe and
during mac80211 start.  For the first case, a simple loop is enough.
For the second case, we need to add a flag to prevent mac80211 from
trying to restart it as well, leaving full control with the driver.

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarMordechay Goodstein <mordechay.goodstein@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20211110150132.57514296ecab.I52a0411774b700bdc7dedb124d8b59bf99456eb2@changeid


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8d6e4b42
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -1276,6 +1276,9 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
	const struct iwl_op_mode_ops *ops = op->ops;
	struct dentry *dbgfs_dir = NULL;
	struct iwl_op_mode *op_mode = NULL;
	int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;

	for (retry = 0; retry <= max_retry; retry++) {

#ifdef CONFIG_IWLWIFI_DEBUGFS
		drv->dbgfs_op_mode = debugfs_create_dir(op->name,
@@ -1283,16 +1286,21 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
		dbgfs_dir = drv->dbgfs_op_mode;
#endif

	op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir);
		op_mode = ops->start(drv->trans, drv->trans->cfg,
				     &drv->fw, dbgfs_dir);

		if (op_mode)
			return op_mode;

		IWL_ERR(drv, "retry init count %d\n", retry);

#ifdef CONFIG_IWLWIFI_DEBUGFS
	if (!op_mode) {
		debugfs_remove_recursive(drv->dbgfs_op_mode);
		drv->dbgfs_op_mode = NULL;
	}
#endif
	}

	return op_mode;
	return NULL;
}

static void _iwl_op_mode_stop(struct iwl_drv *drv)
+3 −0
Original line number Diff line number Diff line
@@ -145,4 +145,7 @@ void iwl_drv_stop(struct iwl_drv *drv);
#define IWL_EXPORT_SYMBOL(sym)
#endif

/* max retry for init flow */
#define IWL_MAX_INIT_RETRY 2

#endif /* __iwl_drv_h__ */
+23 −1
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@
#include <net/ieee80211_radiotap.h>
#include <net/tcp.h>

#include "iwl-drv.h"
#include "iwl-op-mode.h"
#include "iwl-io.h"
#include "mvm.h"
@@ -1129,9 +1130,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	int ret;
	int retry, max_retry = 0;

	mutex_lock(&mvm->mutex);

	/* we are starting the mac not in error flow, and restart is enabled */
	if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) &&
	    iwlwifi_mod_params.fw_restart) {
		max_retry = IWL_MAX_INIT_RETRY;
		/*
		 * This will prevent mac80211 recovery flows to trigger during
		 * init failures
		 */
		set_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
	}

	for (retry = 0; retry <= max_retry; retry++) {
		ret = __iwl_mvm_mac_start(mvm);
		if (!ret)
			break;

		IWL_ERR(mvm, "mac start retry %d\n", retry);
	}
	clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status);

	mutex_unlock(&mvm->mutex);

	return ret;
+3 −0
Original line number Diff line number Diff line
@@ -1167,6 +1167,8 @@ struct iwl_mvm {
 * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running
 * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
 * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
 * @IWL_MVM_STATUS_STARTING: starting mac,
 *	used to disable restart flow while in STARTING state
 */
enum iwl_mvm_status {
	IWL_MVM_STATUS_HW_RFKILL,
@@ -1177,6 +1179,7 @@ enum iwl_mvm_status {
	IWL_MVM_STATUS_ROC_AUX_RUNNING,
	IWL_MVM_STATUS_FIRMWARE_RUNNING,
	IWL_MVM_STATUS_NEED_FLUSH_P2P,
	IWL_MVM_STATUS_STARTING,
};

/* Keep track of completed init configuration */
+3 −0
Original line number Diff line number Diff line
@@ -1288,6 +1288,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
	 */
	if (!mvm->fw_restart && fw_error) {
		iwl_fw_error_collect(&mvm->fwrt);
	} else if (test_bit(IWL_MVM_STATUS_STARTING,
			    &mvm->status)) {
		IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n");
	} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
		struct iwl_mvm_reprobe *reprobe;