wifi: mac80211: HW restart for MLO
authorJohannes Berg <johannes.berg@intel.com>
Thu, 4 May 2023 13:45:05 +0000 (16:45 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 6 Jun 2023 12:12:38 +0000 (14:12 +0200)
Implement proper reconfiguration for interfaces that are
doing MLO, in order to be able to recover from HW restart
correctly.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230504134511.828474-6-gregory.greenman@intel.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/util.c

index 1527d6aafc143bb7309239594482551f91a73fab..75c517dc8beef7323c7204ec8e91bd634d2902ba 100644 (file)
@@ -2624,21 +2624,55 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
        /* Finally also reconfigure all the BSS information */
        list_for_each_entry(sdata, &local->interfaces, list) {
+               /* common change flags for all interface types - link only */
+               u32 changed = BSS_CHANGED_ERP_CTS_PROT |
+                             BSS_CHANGED_ERP_PREAMBLE |
+                             BSS_CHANGED_ERP_SLOT |
+                             BSS_CHANGED_HT |
+                             BSS_CHANGED_BASIC_RATES |
+                             BSS_CHANGED_BEACON_INT |
+                             BSS_CHANGED_BSSID |
+                             BSS_CHANGED_CQM |
+                             BSS_CHANGED_QOS |
+                             BSS_CHANGED_TXPOWER |
+                             BSS_CHANGED_MCAST_RATE;
+               struct ieee80211_link_data *link = NULL;
                unsigned int link_id;
-               u32 changed;
+               u32 active_links = 0;
 
                if (!ieee80211_sdata_running(sdata))
                        continue;
 
                sdata_lock(sdata);
+               if (sdata->vif.valid_links) {
+                       struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS] = {
+                               [0] = &sdata->vif.bss_conf,
+                       };
+
+                       if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+                               /* start with a single active link */
+                               active_links = sdata->vif.active_links;
+                               link_id = ffs(active_links) - 1;
+                               sdata->vif.active_links = BIT(link_id);
+                       }
+
+                       drv_change_vif_links(local, sdata, 0,
+                                            sdata->vif.active_links,
+                                            old);
+               }
+
                for (link_id = 0;
                     link_id < ARRAY_SIZE(sdata->vif.link_conf);
                     link_id++) {
-                       struct ieee80211_link_data *link;
+                       if (sdata->vif.valid_links &&
+                           !(sdata->vif.active_links & BIT(link_id)))
+                               continue;
 
                        link = sdata_dereference(sdata->link[link_id], sdata);
-                       if (link)
-                               ieee80211_assign_chanctx(local, sdata, link);
+                       if (!link)
+                               continue;
+
+                       ieee80211_assign_chanctx(local, sdata, link);
                }
 
                switch (sdata->vif.type) {
@@ -2658,42 +2692,42 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                                            &sdata->deflink.tx_conf[i]);
                        break;
                }
-               sdata_unlock(sdata);
-
-               /* common change flags for all interface types */
-               changed = BSS_CHANGED_ERP_CTS_PROT |
-                         BSS_CHANGED_ERP_PREAMBLE |
-                         BSS_CHANGED_ERP_SLOT |
-                         BSS_CHANGED_HT |
-                         BSS_CHANGED_BASIC_RATES |
-                         BSS_CHANGED_BEACON_INT |
-                         BSS_CHANGED_BSSID |
-                         BSS_CHANGED_CQM |
-                         BSS_CHANGED_QOS |
-                         BSS_CHANGED_IDLE |
-                         BSS_CHANGED_TXPOWER |
-                         BSS_CHANGED_MCAST_RATE;
 
                if (sdata->vif.bss_conf.mu_mimo_owner)
                        changed |= BSS_CHANGED_MU_GROUPS;
 
+               if (!sdata->vif.valid_links)
+                       changed |= BSS_CHANGED_IDLE;
+
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_STATION:
-                       changed |= BSS_CHANGED_ASSOC |
-                                  BSS_CHANGED_ARP_FILTER |
-                                  BSS_CHANGED_PS;
-
-                       /* Re-send beacon info report to the driver */
-                       if (sdata->deflink.u.mgd.have_beacon)
-                               changed |= BSS_CHANGED_BEACON_INFO;
-
-                       if (sdata->vif.bss_conf.max_idle_period ||
-                           sdata->vif.bss_conf.protected_keep_alive)
-                               changed |= BSS_CHANGED_KEEP_ALIVE;
-
-                       sdata_lock(sdata);
-                       ieee80211_bss_info_change_notify(sdata, changed);
-                       sdata_unlock(sdata);
+                       if (!sdata->vif.valid_links) {
+                               changed |= BSS_CHANGED_ASSOC |
+                                          BSS_CHANGED_ARP_FILTER |
+                                          BSS_CHANGED_PS;
+
+                               /* Re-send beacon info report to the driver */
+                               if (sdata->deflink.u.mgd.have_beacon)
+                                       changed |= BSS_CHANGED_BEACON_INFO;
+
+                               if (sdata->vif.bss_conf.max_idle_period ||
+                                   sdata->vif.bss_conf.protected_keep_alive)
+                                       changed |= BSS_CHANGED_KEEP_ALIVE;
+
+                               if (sdata->vif.bss_conf.eht_puncturing)
+                                       changed |= BSS_CHANGED_EHT_PUNCTURING;
+
+                               ieee80211_bss_info_change_notify(sdata,
+                                                                changed);
+                       } else if (!WARN_ON(!link)) {
+                               ieee80211_link_info_change_notify(sdata, link,
+                                                                 changed);
+                               changed = BSS_CHANGED_ASSOC |
+                                         BSS_CHANGED_IDLE |
+                                         BSS_CHANGED_PS |
+                                         BSS_CHANGED_ARP_FILTER;
+                               ieee80211_vif_cfg_change_notify(sdata, changed);
+                       }
                        break;
                case NL80211_IFTYPE_OCB:
                        changed |= BSS_CHANGED_OCB;
@@ -2728,6 +2762,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                case NL80211_IFTYPE_NAN:
                        res = ieee80211_reconfig_nan(sdata);
                        if (res < 0) {
+                               sdata_unlock(sdata);
                                ieee80211_handle_reconfig_failure(local);
                                return res;
                        }
@@ -2745,6 +2780,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                        WARN_ON(1);
                        break;
                }
+               sdata_unlock(sdata);
+
+               if (active_links)
+                       ieee80211_set_active_links(&sdata->vif, active_links);
        }
 
        ieee80211_recalc_ps(local);