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: Mordechay Goodstein <mordechay.goodstein@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/iwlwifi.20211110150132.57514296ecab.I52a0411774b700bdc7dedb124d8b59bf99456eb2@changeid Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
a5d0a72b80
commit
01300d2150
@@ -1303,6 +1303,9 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
|||||||
const struct iwl_op_mode_ops *ops = op->ops;
|
const struct iwl_op_mode_ops *ops = op->ops;
|
||||||
struct dentry *dbgfs_dir = NULL;
|
struct dentry *dbgfs_dir = NULL;
|
||||||
struct iwl_op_mode *op_mode = 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
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
|
||||||
@@ -1310,16 +1313,21 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
|
|||||||
dbgfs_dir = drv->dbgfs_op_mode;
|
dbgfs_dir = drv->dbgfs_op_mode;
|
||||||
#endif
|
#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
|
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||||
if (!op_mode) {
|
|
||||||
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
debugfs_remove_recursive(drv->dbgfs_op_mode);
|
||||||
drv->dbgfs_op_mode = NULL;
|
drv->dbgfs_op_mode = NULL;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return op_mode;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _iwl_op_mode_stop(struct iwl_drv *drv)
|
static void _iwl_op_mode_stop(struct iwl_drv *drv)
|
||||||
|
@@ -144,4 +144,7 @@ void iwl_drv_stop(struct iwl_drv *drv);
|
|||||||
#define IWL_EXPORT_SYMBOL(sym)
|
#define IWL_EXPORT_SYMBOL(sym)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* max retry for init flow */
|
||||||
|
#define IWL_MAX_INIT_RETRY 2
|
||||||
|
|
||||||
#endif /* __iwl_drv_h__ */
|
#endif /* __iwl_drv_h__ */
|
||||||
|
@@ -71,6 +71,7 @@
|
|||||||
#include <net/ieee80211_radiotap.h>
|
#include <net/ieee80211_radiotap.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
|
|
||||||
|
#include "iwl-drv.h"
|
||||||
#include "iwl-op-mode.h"
|
#include "iwl-op-mode.h"
|
||||||
#include "iwl-io.h"
|
#include "iwl-io.h"
|
||||||
#include "mvm.h"
|
#include "mvm.h"
|
||||||
@@ -1163,9 +1164,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
|
|||||||
{
|
{
|
||||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||||
int ret;
|
int ret;
|
||||||
|
int retry, max_retry = 0;
|
||||||
|
|
||||||
mutex_lock(&mvm->mutex);
|
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);
|
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);
|
mutex_unlock(&mvm->mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -1162,6 +1162,8 @@ struct iwl_mvm {
|
|||||||
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware 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_NEED_FLUSH_P2P: need to flush P2P bcast STA
|
||||||
* @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it)
|
* @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it)
|
||||||
|
* @IWL_MVM_STATUS_STARTING: starting mac,
|
||||||
|
* used to disable restart flow while in STARTING state
|
||||||
*/
|
*/
|
||||||
enum iwl_mvm_status {
|
enum iwl_mvm_status {
|
||||||
IWL_MVM_STATUS_HW_RFKILL,
|
IWL_MVM_STATUS_HW_RFKILL,
|
||||||
@@ -1173,6 +1175,7 @@ enum iwl_mvm_status {
|
|||||||
IWL_MVM_STATUS_FIRMWARE_RUNNING,
|
IWL_MVM_STATUS_FIRMWARE_RUNNING,
|
||||||
IWL_MVM_STATUS_NEED_FLUSH_P2P,
|
IWL_MVM_STATUS_NEED_FLUSH_P2P,
|
||||||
IWL_MVM_STATUS_IN_D3,
|
IWL_MVM_STATUS_IN_D3,
|
||||||
|
IWL_MVM_STATUS_STARTING,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Keep track of completed init configuration */
|
/* Keep track of completed init configuration */
|
||||||
|
@@ -1295,6 +1295,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
|
|||||||
*/
|
*/
|
||||||
if (!mvm->fw_restart && fw_error) {
|
if (!mvm->fw_restart && fw_error) {
|
||||||
iwl_fw_error_collect(&mvm->fwrt);
|
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)) {
|
} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||||
struct iwl_mvm_reprobe *reprobe;
|
struct iwl_mvm_reprobe *reprobe;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user