Skip to content

Commit 5283dd6

Browse files
gomordKalle Valo
authored andcommitted
iwlwifi: mvm: retry init flow if failed
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
1 parent 1b54403 commit 5283dd6

File tree

5 files changed

+47
-8
lines changed

5 files changed

+47
-8
lines changed

drivers/net/wireless/intel/iwlwifi/iwl-drv.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,23 +1313,31 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
13131313
const struct iwl_op_mode_ops *ops = op->ops;
13141314
struct dentry *dbgfs_dir = NULL;
13151315
struct iwl_op_mode *op_mode = NULL;
1316+
int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;
1317+
1318+
for (retry = 0; retry <= max_retry; retry++) {
13161319

13171320
#ifdef CONFIG_IWLWIFI_DEBUGFS
1318-
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
1319-
drv->dbgfs_drv);
1320-
dbgfs_dir = drv->dbgfs_op_mode;
1321+
drv->dbgfs_op_mode = debugfs_create_dir(op->name,
1322+
drv->dbgfs_drv);
1323+
dbgfs_dir = drv->dbgfs_op_mode;
13211324
#endif
13221325

1323-
op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir);
1326+
op_mode = ops->start(drv->trans, drv->trans->cfg,
1327+
&drv->fw, dbgfs_dir);
1328+
1329+
if (op_mode)
1330+
return op_mode;
1331+
1332+
IWL_ERR(drv, "retry init count %d\n", retry);
13241333

13251334
#ifdef CONFIG_IWLWIFI_DEBUGFS
1326-
if (!op_mode) {
13271335
debugfs_remove_recursive(drv->dbgfs_op_mode);
13281336
drv->dbgfs_op_mode = NULL;
1329-
}
13301337
#endif
1338+
}
13311339

1332-
return op_mode;
1340+
return NULL;
13331341
}
13341342

13351343
static void _iwl_op_mode_stop(struct iwl_drv *drv)

drivers/net/wireless/intel/iwlwifi/iwl-drv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,7 @@ void iwl_drv_stop(struct iwl_drv *drv);
8989
#define IWL_EXPORT_SYMBOL(sym)
9090
#endif
9191

92+
/* max retry for init flow */
93+
#define IWL_MAX_INIT_RETRY 2
94+
9295
#endif /* __iwl_drv_h__ */

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <net/ieee80211_radiotap.h>
1717
#include <net/tcp.h>
1818

19+
#include "iwl-drv.h"
1920
#include "iwl-op-mode.h"
2021
#include "iwl-io.h"
2122
#include "mvm.h"
@@ -1117,9 +1118,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
11171118
{
11181119
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
11191120
int ret;
1121+
int retry, max_retry = 0;
11201122

11211123
mutex_lock(&mvm->mutex);
1122-
ret = __iwl_mvm_mac_start(mvm);
1124+
1125+
/* we are starting the mac not in error flow, and restart is enabled */
1126+
if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) &&
1127+
iwlwifi_mod_params.fw_restart) {
1128+
max_retry = IWL_MAX_INIT_RETRY;
1129+
/*
1130+
* This will prevent mac80211 recovery flows to trigger during
1131+
* init failures
1132+
*/
1133+
set_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
1134+
}
1135+
1136+
for (retry = 0; retry <= max_retry; retry++) {
1137+
ret = __iwl_mvm_mac_start(mvm);
1138+
if (!ret)
1139+
break;
1140+
1141+
IWL_ERR(mvm, "mac start retry %d\n", retry);
1142+
}
1143+
clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
1144+
11231145
mutex_unlock(&mvm->mutex);
11241146

11251147
return ret;

drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,8 @@ struct iwl_mvm {
11231123
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
11241124
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
11251125
* @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it)
1126+
* @IWL_MVM_STATUS_STARTING: starting mac,
1127+
* used to disable restart flow while in STARTING state
11261128
*/
11271129
enum iwl_mvm_status {
11281130
IWL_MVM_STATUS_HW_RFKILL,
@@ -1134,6 +1136,7 @@ enum iwl_mvm_status {
11341136
IWL_MVM_STATUS_FIRMWARE_RUNNING,
11351137
IWL_MVM_STATUS_NEED_FLUSH_P2P,
11361138
IWL_MVM_STATUS_IN_D3,
1139+
IWL_MVM_STATUS_STARTING,
11371140
};
11381141

11391142
/* Keep track of completed init configuration */

drivers/net/wireless/intel/iwlwifi/mvm/ops.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
16001600
*/
16011601
if (!mvm->fw_restart && fw_error) {
16021602
iwl_fw_error_collect(&mvm->fwrt, false);
1603+
} else if (test_bit(IWL_MVM_STATUS_STARTING,
1604+
&mvm->status)) {
1605+
IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n");
16031606
} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
16041607
struct iwl_mvm_reprobe *reprobe;
16051608

0 commit comments

Comments
 (0)