wifi: iwlwifi: mvm: init vif works only once
authorJohannes Berg <johannes.berg@intel.com>
Tue, 16 Apr 2024 10:54:05 +0000 (13:54 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 19 Apr 2024 08:16:33 +0000 (10:16 +0200)
It's dangerous to re-initialize works repeatedly, especially
delayed ones that have an associated timer, and even more so
if they're not necessarily canceled inbetween. This can be
the case for these workers here during FW restart scenarios,
so make sure to initialize it only once.

While at it, also ensure it is cancelled correctly.

Fixes: f67806140220 ("iwlwifi: mvm: disconnect in case of bad channel switch parameters")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240416134215.ddf8eece5eac.I4164f5c9c444b64a9abbaab14c23858713778e35@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

index a9bcf235cde9330c5fbe7c6ccfe7e0416fff73b2..efe9205a7cf2b18824f431da3a428bda57d53f87 100644 (file)
@@ -1612,6 +1612,17 @@ static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
                                        IWL_STA_MULTICAST);
 }
 
+void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
+{
+       lockdep_assert_held(&mvm->mutex);
+
+       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
+               return;
+
+       INIT_DELAYED_WORK(&mvmvif->csa_work,
+                         iwl_mvm_channel_switch_disconnect_wk);
+}
+
 static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
                                     struct ieee80211_vif *vif)
 {
@@ -1622,6 +1633,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 
        mutex_lock(&mvm->mutex);
 
+       iwl_mvm_mac_init_mvmvif(mvm, mvmvif);
+
        mvmvif->mvm = mvm;
 
        /* the first link always points to the default one */
@@ -1703,8 +1716,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
                mvm->p2p_device_vif = vif;
 
        iwl_mvm_tcm_add_vif(mvm, vif);
-       INIT_DELAYED_WORK(&mvmvif->csa_work,
-                         iwl_mvm_channel_switch_disconnect_wk);
 
        if (vif->type == NL80211_IFTYPE_MONITOR) {
                mvm->monitor_on = true;
@@ -1742,6 +1753,8 @@ out:
 void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
                                 struct ieee80211_vif *vif)
 {
+       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
        if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
                /*
                 * Flush the ROC worker which will flush the OFFCHANNEL queue.
@@ -1750,6 +1763,8 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
                 */
                flush_work(&mvm->roc_done_wk);
        }
+
+       cancel_delayed_work_sync(&mvmvif->csa_work);
 }
 
 /* This function is doing the common part of removing the interface for
index 2a7d7d4e06493624d0133324966913863d4805cd..61f4c5dc3ceccccd4294db6a42869c95c3859203 100644 (file)
@@ -14,6 +14,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
 
        mutex_lock(&mvm->mutex);
 
+       iwl_mvm_mac_init_mvmvif(mvm, mvmvif);
+
        mvmvif->mvm = mvm;
 
        /* Not much to do here. The stack will not allow interface
index 3b726c8b9261ecf50947c1270c520c5f5c619eec..edeea988e819026d88e3ab3a838a650dfce25095 100644 (file)
@@ -1805,6 +1805,8 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm);
 
 int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm);
 
+void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif);
+
 /*
  * FW notifications / CMD responses handlers
  * Convention: iwl_mvm_rx_<NAME OF THE CMD>