]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mac80211: change disassoc sequence a bit
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 24 Dec 2024 17:27:30 +0000 (19:27 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 13 Jan 2025 12:53:04 +0000 (13:53 +0100)
Currently, the sequence goes like this (among others):
1. flush all stations (including the AP ones) -> this will tell the
   drivers to remove the stations
2. notify the driver the vif is not associated.

Which means that in between 1 and 2, the state is that the vif is
associated, but there is no AP station, which makes no sense, and may be
problematic for some drivers (for example iwlwifi)

Change the sequence to:
1. flush the TDLS stations
2. move the AP station to IEEE80211_STA_NONE
3. notify the driver about the vif being unassociated
4. flush the AP station

In order to not break other drivers, add a vif flag to indicate whether
the driver wants to new sequence or not. If the flag is not set, then
things will be done in the old sequence.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20241224192322.996ad1be6cb3.I7815d33415aa1d65c0120b54be7a15a45388f807@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/sta.c
include/net/mac80211.h
net/mac80211/mlme.c

index 07778d55878bce748ce76ca80e4c7ed3b0b0f5b7..54275374815ae1edb52b01f59a23bfcf436b3e40 100644 (file)
@@ -1802,6 +1802,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
        mvmvif->deflink.active = 0;
        mvmvif->link[0] = &mvmvif->deflink;
 
+       vif->driver_flags = IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC;
+
        ret = iwl_mvm_set_link_mapping(mvm, vif, &vif->bss_conf);
        if (ret)
                goto out;
@@ -2967,33 +2969,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                            &mvm->status),
                                  "Failed to update SF upon disassociation\n");
 
-                       /*
-                        * If we get an assert during the connection (after the
-                        * station has been added, but before the vif is set
-                        * to associated), mac80211 will re-add the station and
-                        * then configure the vif. Since the vif is not
-                        * associated, we would remove the station here and
-                        * this would fail the recovery.
-                        */
-                       if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
-                                     &mvm->status)) {
-                               /* first remove remaining keys */
-                               iwl_mvm_sec_key_remove_ap(mvm, vif,
-                                                         &mvmvif->deflink, 0);
-
-                               /*
-                                * Remove AP station now that
-                                * the MAC is unassoc
-                                */
-                               ret = iwl_mvm_rm_sta_id(mvm, vif,
-                                                       mvmvif->deflink.ap_sta_id);
-                               if (ret)
-                                       IWL_ERR(mvm,
-                                               "failed to remove AP station\n");
-
-                               mvmvif->deflink.ap_sta_id = IWL_INVALID_STA;
-                       }
-
                        /* remove quota for this interface */
                        ret = iwl_mvm_update_quotas(mvm, false, NULL);
                        if (ret)
index b807046144c040f61f49cc9d760357a8b7bee3c8..d02114b093b66490d2c66087995ecd32ec80b5a5 100644 (file)
@@ -18,6 +18,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
 
        mvmvif->mvm = mvm;
 
+       vif->driver_flags |= IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC;
+
        /* Not much to do here. The stack will not allow interface
         * types or combinations that we didn't advertise, so we
         * don't really have to check the types.
@@ -831,30 +833,6 @@ static bool iwl_mvm_mld_vif_have_valid_ap_sta(struct iwl_mvm_vif *mvmvif)
        return false;
 }
 
-static void iwl_mvm_mld_vif_delete_all_stas(struct iwl_mvm *mvm,
-                                           struct ieee80211_vif *vif)
-{
-       struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       int i, ret;
-
-       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
-               return;
-
-       for_each_mvm_vif_valid_link(mvmvif, i) {
-               struct iwl_mvm_vif_link_info *link = mvmvif->link[i];
-
-               if (!link)
-                       continue;
-
-               iwl_mvm_sec_key_remove_ap(mvm, vif, link, i);
-               ret = iwl_mvm_mld_rm_sta_id(mvm, link->ap_sta_id);
-               if (ret)
-                       IWL_ERR(mvm, "failed to remove AP station\n");
-
-               link->ap_sta_id = IWL_INVALID_STA;
-       }
-}
-
 static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
                                                struct ieee80211_vif *vif,
                                                u64 changes)
@@ -938,15 +916,6 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm,
                                  !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
                                            &mvm->status),
                                  "Failed to update SF upon disassociation\n");
-
-                       /* If we get an assert during the connection (after the
-                        * station has been added, but before the vif is set
-                        * to associated), mac80211 will re-add the station and
-                        * then configure the vif. Since the vif is not
-                        * associated, we would remove the station here and
-                        * this would fail the recovery.
-                        */
-                       iwl_mvm_mld_vif_delete_all_stas(mvm, vif);
                }
 
                iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes);
index d3fa2c4feb0f45a3313de4da8f08c5f7824c104b..35f4ca89920e0c7308db78b10a2c6d3e40aef002 100644 (file)
@@ -2065,15 +2065,10 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        if (vif->type == NL80211_IFTYPE_STATION &&
            mvm_link->ap_sta_id == sta_id) {
-               /* if associated - we can't remove the AP STA now */
-               if (vif->cfg.assoc)
-                       return true;
-
                /* first remove remaining keys */
                iwl_mvm_sec_key_remove_ap(mvm, vif, mvm_link,
                                          link_sta->link_id);
 
-               /* unassoc - go ahead - remove the AP STA now */
                mvm_link->ap_sta_id = IWL_INVALID_STA;
        }
 
index 9320d4bc22ee41b3a5bf33f3fa213da941676cc6..769c1fe30e342ecf6715f6a7e9baec55cade73e4 100644 (file)
@@ -1855,6 +1855,9 @@ struct ieee80211_channel_switch {
  *     operation on this interface and request a channel context without
  *     the AP definition. Use this e.g. because the device is able to
  *     handle OFDMA (downlink and trigger for uplink) on a per-AP basis.
+ * @IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC: indicates that the AP sta should
+ *     be removed only after setting the vif as unassociated, and not the
+ *     opposite. Only relevant for STA vifs.
  */
 enum ieee80211_vif_flags {
        IEEE80211_VIF_BEACON_FILTER             = BIT(0),
@@ -1863,6 +1866,7 @@ enum ieee80211_vif_flags {
        IEEE80211_VIF_GET_NOA_UPDATE            = BIT(3),
        IEEE80211_VIF_EML_ACTIVE                = BIT(4),
        IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW     = BIT(5),
+       IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC  = BIT(6),
 };
 
 
index 61c318f5239fa1774a662d94eeb0062c31b4434d..e502f6d57289c6d5a3bde77f1b786e1e04f81002 100644 (file)
@@ -3599,6 +3599,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_local *local = sdata->local;
+       struct sta_info *ap_sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
        unsigned int link_id;
        u64 changed = 0;
        struct ieee80211_prep_tx_info info = {
@@ -3609,6 +3610,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        lockdep_assert_wiphy(local->hw.wiphy);
 
+       if (WARN_ON(!ap_sta))
+               return;
+
        if (WARN_ON_ONCE(tx && !frame_buf))
                return;
 
@@ -3672,8 +3676,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        sdata->vif.cfg.ssid_len = 0;
 
-       /* remove AP and TDLS peers */
-       sta_info_flush(sdata, -1);
+       /* Remove TDLS peers */
+       __sta_info_flush(sdata, false, -1, ap_sta);
+
+       if (sdata->vif.driver_flags & IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC) {
+               /* Only move the AP state */
+               sta_info_move_state(ap_sta, IEEE80211_STA_NONE);
+       } else {
+               /* Remove AP peer */
+               sta_info_flush(sdata, -1);
+       }
 
        /* finally reset all BSS / config parameters */
        if (!ieee80211_vif_is_mld(&sdata->vif))
@@ -3724,6 +3736,14 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
                ieee80211_vif_cfg_change_notify(sdata, changed);
        }
 
+       if (sdata->vif.driver_flags & IEEE80211_VIF_REMOVE_AP_AFTER_DISASSOC) {
+               /*
+                * After notifying the driver about the disassoc,
+                * remove the ap sta.
+                */
+               sta_info_flush(sdata, -1);
+       }
+
        /* disassociated - set to defaults now */
        ieee80211_set_wmm_default(&sdata->deflink, false, false);