@@ -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);