]> git.hungrycats.org Git - linux/commitdiff
wifi: iwlwifi: mvm: remove stale STA link data during restart
authorBenjamin Berg <benjamin.berg@intel.com>
Mon, 13 May 2024 10:27:08 +0000 (13:27 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jul 2024 07:53:21 +0000 (09:53 +0200)
[ Upstream commit cc3ba78f202de9752aceb16342ab62bdfbffac7e ]

If pre-recovery mac80211 tried to disable a link but this disablement
failed, then there might be a mismatch between mac80211 assuming the
link has been disabled and the driver still having the data around.
During recover itself, that is not a problem, but should the link be
activated again at a later point, iwlwifi will refuse the activation as
it detects the inconsistent state.

Solve this corner-case by iterating the station in the restart cleanup
handler.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240513132416.d2fd60338055.I840d4fdce5fd49fe69896d928b071067e3730259@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h

index 5f6b16d3fc8a330416b565c5a97799455db69857..3b61fe8ca47fa6ba8070f3ccbc2a43108f5f41d2 100644 (file)
@@ -1115,6 +1115,39 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
        RCU_INIT_POINTER(mvmvif->deflink.probe_resp_data, NULL);
 }
 
+static void iwl_mvm_cleanup_sta_iterator(void *data, struct ieee80211_sta *sta)
+{
+       struct iwl_mvm *mvm = data;
+       struct iwl_mvm_sta *mvm_sta;
+       struct ieee80211_vif *vif;
+       int link_id;
+
+       mvm_sta = iwl_mvm_sta_from_mac80211(sta);
+       vif = mvm_sta->vif;
+
+       if (!sta->valid_links)
+               return;
+
+       for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) {
+               struct iwl_mvm_link_sta *mvm_link_sta;
+
+               mvm_link_sta =
+                       rcu_dereference_check(mvm_sta->link[link_id],
+                                             lockdep_is_held(&mvm->mutex));
+               if (mvm_link_sta && !(vif->active_links & BIT(link_id))) {
+                       /*
+                        * We have a link STA but the link is inactive in
+                        * mac80211. This will happen if we failed to
+                        * deactivate the link but mac80211 roll back the
+                        * deactivation of the link.
+                        * Delete the stale data to avoid issues later on.
+                        */
+                       iwl_mvm_mld_free_sta_link(mvm, mvm_sta, mvm_link_sta,
+                                                 link_id, false);
+               }
+       }
+}
+
 static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
 {
        iwl_mvm_stop_device(mvm);
@@ -1137,6 +1170,10 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
         */
        ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm);
 
+       /* cleanup stations as links may be gone after restart */
+       ieee80211_iterate_stations_atomic(mvm->hw,
+                                         iwl_mvm_cleanup_sta_iterator, mvm);
+
        mvm->p2p_device_vif = NULL;
 
        iwl_mvm_reset_phy_ctxts(mvm);
index 36dc291d98dd6813c2e80af768a53097f0d2ead6..a21e29947475fb5f9dd17c94b2c13d50ce9ab4eb 100644 (file)
@@ -515,11 +515,11 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        return iwl_mvm_mld_send_sta_cmd(mvm, &cmd);
 }
 
-static void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm,
-                                     struct iwl_mvm_sta *mvm_sta,
-                                     struct iwl_mvm_link_sta *mvm_sta_link,
-                                     unsigned int link_id,
-                                     bool is_in_fw)
+void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm,
+                              struct iwl_mvm_sta *mvm_sta,
+                              struct iwl_mvm_link_sta *mvm_sta_link,
+                              unsigned int link_id,
+                              bool is_in_fw)
 {
        RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta_link->sta_id],
                         is_in_fw ? ERR_PTR(-EINVAL) : NULL);
index b3450569864eb290638790f26bd3f8d2a4d7e1a4..7dd8f7f4b44923bcfe42ea49916f11b999f8f922 100644 (file)
@@ -638,6 +638,11 @@ int iwl_mvm_mld_update_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta);
 int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
                       struct ieee80211_sta *sta);
+void iwl_mvm_mld_free_sta_link(struct iwl_mvm *mvm,
+                              struct iwl_mvm_sta *mvm_sta,
+                              struct iwl_mvm_link_sta *mvm_sta_link,
+                              unsigned int link_id,
+                              bool is_in_fw);
 int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id);
 int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm,
                                 struct ieee80211_vif *vif,