lkml.org 
[lkml]   [2021]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 059/207] iwlwifi: mvm: retry init flow if failed
    Date
    From: Mordechay Goodstein <mordechay.goodstein@intel.com>

    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>
    ---
    drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 22 +++++++++++++-------
    drivers/net/wireless/intel/iwlwifi/iwl-drv.h | 3 ++
    drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 24 +++++++++++++++++++++-
    drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 ++
    drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 ++
    5 files changed, 47 insertions(+), 8 deletions(-)

    --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
    +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
    @@ -1271,23 +1271,31 @@ _iwl_op_mode_start(struct iwl_drv *drv,
    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,
    - drv->dbgfs_drv);
    - dbgfs_dir = drv->dbgfs_op_mode;
    + drv->dbgfs_op_mode = debugfs_create_dir(op->name,
    + drv->dbgfs_drv);
    + 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)
    --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
    +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
    @@ -90,4 +90,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__ */
    --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
    +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
    @@ -16,6 +16,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"
    @@ -1116,9 +1117,30 @@ static int iwl_mvm_mac_start(struct ieee
    {
    struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
    int ret;
    + int retry, max_retry = 0;

    mutex_lock(&mvm->mutex);
    - ret = __iwl_mvm_mac_start(mvm);
    +
    + /* 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;
    --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
    +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
    @@ -1121,6 +1121,8 @@ struct iwl_mvm {
    * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
    * @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_STARTING: starting mac,
    + * used to disable restart flow while in STARTING state
    */
    enum iwl_mvm_status {
    IWL_MVM_STATUS_HW_RFKILL,
    @@ -1132,6 +1134,7 @@ enum iwl_mvm_status {
    IWL_MVM_STATUS_FIRMWARE_RUNNING,
    IWL_MVM_STATUS_NEED_FLUSH_P2P,
    IWL_MVM_STATUS_IN_D3,
    + IWL_MVM_STATUS_STARTING,
    };

    /* Keep track of completed init configuration */
    --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
    +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
    @@ -1424,6 +1424,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm
    */
    if (!mvm->fw_restart && fw_error) {
    iwl_fw_error_collect(&mvm->fwrt, false);
    + } 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;


    \
     
     \ /
      Last update: 2021-12-06 17:11    [W:2.135 / U:0.800 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site