From: Felix Fietkau Date: Wed, 27 Aug 2025 13:24:29 +0000 (+0200) Subject: mac80211: extend connection monitoring for MLO X-Git-Tag: v24.10.3~59 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03fe5966997363a08d686bca219b647f58ef4fc3;p=thirdparty%2Fopenwrt.git mac80211: extend connection monitoring for MLO Required for latest mt76 Signed-off-by: Felix Fietkau (cherry picked from commit 6fbf6d0cfd080230ce4ca72605580b0c188db8a1) --- diff --git a/package/kernel/mac80211/patches/subsys/350-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch b/package/kernel/mac80211/patches/subsys/350-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch new file mode 100644 index 00000000000..d78a72d246f --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/350-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch @@ -0,0 +1,55 @@ +From: Maharaja Kennadyrajan +Date: Fri, 18 Jul 2025 11:38:35 +0530 +Subject: [PATCH] wifi: mac80211: Add link iteration macro for link data + with rcu_dereference + +Currently, the existing macro for_each_link_data() uses sdata_dereference() +which requires the wiphy lock. This lock cannot be used in atomic or RCU +read-side contexts, such as in the RX path. + +Introduce a new macro, for_each_link_data_rcu(), that iterates over link of +sdata using rcu_dereference(), making it safe to use in RCU contexts. This +allows callers to access link data without requiring the wiphy lock. + +The macro takes into account the vif.valid_links bitmap and ensures only +valid links are accessed safely. Callers are responsible for ensuring that +rcu_read_lock() is held when using this macro. + +Signed-off-by: Maharaja Kennadyrajan +Link: https://patch.msgid.link/20250718060837.59371-3-maharaja.kennadyrajan@oss.qualcomm.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1211,6 +1211,30 @@ struct ieee80211_sub_if_data *vif_to_sda + if ((_link = wiphy_dereference((local)->hw.wiphy, \ + ___sdata->link[___link_id]))) + ++#define for_each_link_data(sdata, __link) \ ++ /* outer loop just to define the variable ... */ \ ++ for (struct ieee80211_sub_if_data *__sdata = (sdata); __sdata; \ ++ __sdata = NULL /* always stop */) \ ++ for (int __link_id = 0; \ ++ __link_id < ARRAY_SIZE((__sdata)->link); __link_id++) \ ++ if ((!(__sdata)->vif.valid_links || \ ++ (__sdata)->vif.valid_links & BIT(__link_id)) && \ ++ ((__link) = sdata_dereference((__sdata)->link[__link_id], \ ++ (__sdata)))) ++ ++/* ++ * for_each_link_data_rcu should be used under RCU read lock. ++ */ ++#define for_each_link_data_rcu(sdata, __link) \ ++ /* outer loop just to define the variable ... */ \ ++ for (struct ieee80211_sub_if_data *__sdata = (sdata); __sdata; \ ++ __sdata = NULL /* always stop */) \ ++ for (int __link_id = 0; \ ++ __link_id < ARRAY_SIZE((__sdata)->link); __link_id++) \ ++ if ((!(__sdata)->vif.valid_links || \ ++ (__sdata)->vif.valid_links & BIT(__link_id)) && \ ++ ((__link) = rcu_dereference((__sdata)->link[__link_id]))) \ ++ + static inline int + ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems, + struct cfg80211_rnr_elems *rnr_elems, diff --git a/package/kernel/mac80211/patches/subsys/351-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch b/package/kernel/mac80211/patches/subsys/351-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch new file mode 100644 index 00000000000..b1986dc8aac --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/351-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch @@ -0,0 +1,77 @@ +From: Maharaja Kennadyrajan +Date: Fri, 18 Jul 2025 11:38:36 +0530 +Subject: [PATCH] wifi: mac80211: extend beacon monitoring for MLO + +Currently, reset beacon monitor (ieee80211_sta_reset_beacon_monitor()) +timer is handled only for non-AP non-MLD STA and do not support non-AP MLD +STA. When the beacon loss occurs in non-AP MLD STA with the current +implementation, it is treated as a single link and the timer will reset +based on the timeout of the deflink, without checking all the links. + +Check the CSA flags for all the links in the MLO and decide whether to +schedule the work queue for beacon loss. If any of the links has CSA +active, then beacon loss work is not scheduled. + +Also, call the functions ieee80211_sta_reset_beacon_monitor() and +ieee80211_sta_reset_conn_monitor() from ieee80211_csa_switch_work() only +when all the links are CSA active. + +Signed-off-by: Maharaja Kennadyrajan +Link: https://patch.msgid.link/20250718060837.59371-4-maharaja.kennadyrajan@oss.qualcomm.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2159,6 +2159,21 @@ static void ieee80211_csa_switch_work(st + } + } + ++ /* ++ * It is not necessary to reset these timers if any link does not ++ * have an active CSA and that link still receives the beacons ++ * when other links have active CSA. ++ */ ++ for_each_link_data(sdata, link) { ++ if (!link->conf->csa_active) ++ return; ++ } ++ ++ /* ++ * Reset the beacon monitor and connection monitor timers when CSA ++ * is active for all links in MLO when channel switch occurs in all ++ * the links. ++ */ + ieee80211_sta_reset_beacon_monitor(sdata); + ieee80211_sta_reset_conn_monitor(sdata); + } +@@ -7863,6 +7878,29 @@ void ieee80211_sta_work(struct ieee80211 + } + } + ++static bool ++ieee80211_is_csa_in_progress(struct ieee80211_sub_if_data *sdata) ++{ ++ /* ++ * In MLO, check the CSA flags 'active' and 'waiting_bcn' for all ++ * the links. ++ */ ++ struct ieee80211_link_data *link; ++ bool ret = true; ++ ++ rcu_read_lock(); ++ for_each_link_data_rcu(sdata, link) { ++ if (!(link->conf->csa_active && ++ !link->u.mgd.csa.waiting_bcn)) { ++ ret = false; ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ ++ return ret; ++} ++ + static void ieee80211_sta_bcn_mon_timer(struct timer_list *t) + { + struct ieee80211_sub_if_data *sdata = diff --git a/package/kernel/mac80211/patches/subsys/352-wifi-mac80211-extend-connection-monitoring-for-MLO.patch b/package/kernel/mac80211/patches/subsys/352-wifi-mac80211-extend-connection-monitoring-for-MLO.patch new file mode 100644 index 00000000000..e6227b97ea9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/352-wifi-mac80211-extend-connection-monitoring-for-MLO.patch @@ -0,0 +1,141 @@ +From: Maharaja Kennadyrajan +Date: Fri, 18 Jul 2025 11:38:37 +0530 +Subject: [PATCH] wifi: mac80211: extend connection monitoring for MLO + +Currently, reset connection monitor (ieee80211_sta_reset_conn_monitor()) +timer is handled only for non-AP non-MLD STA and do not support non-AP MLD +STA. The current implementation checks for the CSA active and update the +monitor timer with the timeout value of deflink and reset the timer based +on the deflink's timeout value else schedule the connection loss work when +the deflink is timed out and it won't work for the non-AP MLD STA. + +Handle the reset connection monitor timer for non-AP MLD STA by updating +the monitor timer with the timeout value which is determined based on the +link that will expire last among all the links in MLO. If at least one link +has not timed out, the timer is updated accordingly with the latest timeout +value else schedule the connection loss work when all links have timed out. + +Remove the MLO-related WARN_ON() checks in the beacon and connection +monitoring logic code paths as they support MLO now. + +Signed-off-by: Maharaja Kennadyrajan +Link: https://patch.msgid.link/20250718060837.59371-5-maharaja.kennadyrajan@oss.qualcomm.com +Signed-off-by: Johannes Berg +--- + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3831,9 +3831,6 @@ static void ieee80211_mgd_probe_ap_send( + + lockdep_assert_wiphy(sdata->local->hw.wiphy); + +- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif))) +- return; +- + /* + * Try sending broadcast probe requests for the last three + * probe requests after the first ones failed since some +@@ -3879,9 +3876,6 @@ static void ieee80211_mgd_probe_ap(struc + + lockdep_assert_wiphy(sdata->local->hw.wiphy); + +- if (WARN_ON_ONCE(ieee80211_vif_is_mld(&sdata->vif))) +- return; +- + if (!ieee80211_sdata_running(sdata)) + return; + +@@ -7921,36 +7915,73 @@ static void ieee80211_sta_bcn_mon_timer( + &sdata->u.mgd.beacon_connection_loss_work); + } + ++static unsigned long ++ieee80211_latest_active_link_conn_timeout(struct ieee80211_sub_if_data *sdata) ++{ ++ unsigned long latest_timeout = 0; ++ unsigned int link_id; ++ struct sta_info *sta; ++ ++ rcu_read_lock(); ++ ++ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr); ++ if (!sta) ++ goto out; ++ ++ for (link_id = 0; link_id < ARRAY_SIZE(sta->link); ++ link_id++) { ++ struct link_sta_info *link_sta; ++ unsigned long timeout; ++ ++ link_sta = rcu_dereference(sta->link[link_id]); ++ if (!link_sta) ++ continue; ++ ++ timeout = link_sta->status_stats.last_ack; ++ if (time_before(timeout, link_sta->rx_stats.last_rx)) ++ timeout = link_sta->rx_stats.last_rx; ++ ++ timeout += IEEE80211_CONNECTION_IDLE_TIME; ++ ++ /* ++ * latest_timeout holds the timeout of the link ++ * that will expire last among all links in an ++ * non-AP MLD STA. This ensures that the connection ++ * monitor timer is only reset if at least one link ++ * is still active, and it is scheduled to fire at ++ * the latest possible timeout. ++ */ ++ if (time_is_after_jiffies(timeout) && ++ time_after(timeout, latest_timeout)) ++ latest_timeout = timeout; ++ } ++ ++out: ++ rcu_read_unlock(); ++ ++ return latest_timeout; ++} ++ + static void ieee80211_sta_conn_mon_timer(struct timer_list *t) + { + struct ieee80211_sub_if_data *sdata = + from_timer(sdata, t, u.mgd.conn_mon_timer); + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; +- struct sta_info *sta; +- unsigned long timeout; ++ unsigned long latest_timeout; + +- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif))) ++ if (ieee80211_is_csa_in_progress(sdata)) + return; + +- if (sdata->vif.bss_conf.csa_active && +- !sdata->deflink.u.mgd.csa.waiting_bcn) +- return; +- +- sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr); +- if (!sta) +- return; +- +- timeout = sta->deflink.status_stats.last_ack; +- if (time_before(sta->deflink.status_stats.last_ack, sta->deflink.rx_stats.last_rx)) +- timeout = sta->deflink.rx_stats.last_rx; +- timeout += IEEE80211_CONNECTION_IDLE_TIME; ++ latest_timeout = ieee80211_latest_active_link_conn_timeout(sdata); + +- /* If timeout is after now, then update timer to fire at +- * the later date, but do not actually probe at this time. +- */ +- if (time_is_after_jiffies(timeout)) { +- mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout)); ++ /* ++ * If latest timeout is after now, then update timer to fire at ++ * the later date, but do not actually probe at this time. ++ */ ++ if (latest_timeout) { ++ mod_timer(&ifmgd->conn_mon_timer, ++ round_jiffies_up(latest_timeout)); + return; + } + diff --git a/package/kernel/mac80211/patches/subsys/353-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch b/package/kernel/mac80211/patches/subsys/353-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch new file mode 100644 index 00000000000..bbc02cc21d9 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/353-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch @@ -0,0 +1,25 @@ +From: Lorenzo Bianconi +Date: Tue, 26 Aug 2025 13:54:31 +0200 +Subject: [PATCH] wifi: mac80211: Make CONNECTION_MONITOR optional for MLO sta + +Since commit '1bc892d76a6f ("wifi: mac80211: extend connection +monitoring for MLO")' mac80211 supports connection monitor for MLO +client interfaces. Remove the CONNECTION_MONITOR requirement in +ieee80211_register_hw routine. + +Fixes: 1bc892d76a6f ("wifi: mac80211: extend connection monitoring for MLO") +Signed-off-by: Lorenzo Bianconi +--- + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -1174,9 +1174,6 @@ int ieee80211_register_hw(struct ieee802 + if (WARN_ON(!ieee80211_hw_check(hw, MFP_CAPABLE))) + return -EINVAL; + +- if (WARN_ON(!ieee80211_hw_check(hw, CONNECTION_MONITOR))) +- return -EINVAL; +- + if (WARN_ON(ieee80211_hw_check(hw, NEED_DTIM_BEFORE_ASSOC))) + return -EINVAL; +