From: Felix Fietkau Date: Wed, 27 Aug 2025 13:24:29 +0000 (+0200) Subject: mac80211: extend connection monitoring for MLO X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6fbf6d0cfd080230ce4ca72605580b0c188db8a1;p=thirdparty%2Fopenwrt.git mac80211: extend connection monitoring for MLO Required for latest mt76 Signed-off-by: Felix Fietkau --- diff --git a/package/kernel/mac80211/patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch b/package/kernel/mac80211/patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch new file mode 100644 index 00000000000..1c3bb784dd8 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch @@ -0,0 +1,44 @@ +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 +@@ -1237,6 +1237,19 @@ struct ieee80211_sub_if_data *vif_to_sda + ((__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/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch b/package/kernel/mac80211/patches/subsys/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch new file mode 100644 index 00000000000..f0226fdff16 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch @@ -0,0 +1,85 @@ +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 +@@ -2439,6 +2439,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); + } +@@ -8389,16 +8404,32 @@ 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; ++ ++ guard(rcu)(); ++ ++ for_each_link_data_rcu(sdata, link) { ++ if (!(link->conf->csa_active && ++ !link->u.mgd.csa.waiting_bcn)) ++ return false; ++ } ++ ++ return true; ++} ++ + static void ieee80211_sta_bcn_mon_timer(struct timer_list *t) + { + struct ieee80211_sub_if_data *sdata = + timer_container_of(sdata, t, u.mgd.bcn_mon_timer); + +- if (WARN_ON(ieee80211_vif_is_mld(&sdata->vif))) +- return; +- +- if (sdata->vif.bss_conf.csa_active && +- !sdata->deflink.u.mgd.csa.waiting_bcn) ++ if (ieee80211_is_csa_in_progress(sdata)) + return; + + if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) diff --git a/package/kernel/mac80211/patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch b/package/kernel/mac80211/patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch new file mode 100644 index 00000000000..3da06793de7 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch @@ -0,0 +1,136 @@ +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 +@@ -4300,9 +4300,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 +@@ -4348,9 +4345,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; + +@@ -8440,36 +8434,70 @@ 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; ++ unsigned int link_id; ++ struct sta_info *sta; ++ ++ guard(rcu)(); ++ ++ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr); ++ if (!sta) ++ return 0; ++ ++ 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; ++ } ++ ++ return latest_timeout; ++} ++ + static void ieee80211_sta_conn_mon_timer(struct timer_list *t) + { + struct ieee80211_sub_if_data *sdata = + timer_container_of(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))) +- 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) ++ if (ieee80211_is_csa_in_progress(sdata)) + 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 ++ /* ++ * If latest 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) { ++ mod_timer(&ifmgd->conn_mon_timer, ++ round_jiffies_up(latest_timeout)); + return; + } + diff --git a/package/kernel/mac80211/patches/subsys/343-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch b/package/kernel/mac80211/patches/subsys/343-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch new file mode 100644 index 00000000000..457a8894f24 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/343-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 +@@ -1179,9 +1179,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; + diff --git a/package/kernel/mac80211/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch b/package/kernel/mac80211/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch index 33ca9fe3359..fe9db05cb1b 100644 --- a/package/kernel/mac80211/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch +++ b/package/kernel/mac80211/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch @@ -77,7 +77,7 @@ --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1975,6 +1975,12 @@ int ieee80211_mesh_finish_csa(struct iee +@@ -1988,6 +1988,12 @@ int ieee80211_mesh_finish_csa(struct iee u64 *changed); /* scan/BSS handling */ @@ -90,7 +90,7 @@ void ieee80211_scan_work(struct wiphy *wiphy, struct wiphy_work *work); int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, const u8 *ssid, u8 ssid_len, -@@ -2013,6 +2019,7 @@ void ieee80211_sched_scan_stopped_work(s +@@ -2026,6 +2032,7 @@ void ieee80211_sched_scan_stopped_work(s /* off-channel/mgmt-tx */ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); void ieee80211_offchannel_return(struct ieee80211_local *local); @@ -98,7 +98,7 @@ void ieee80211_roc_setup(struct ieee80211_local *local); void ieee80211_start_next_roc(struct ieee80211_local *local); void ieee80211_reconfig_roc(struct ieee80211_local *local); -@@ -2660,6 +2667,8 @@ bool ieee80211_chandef_s1g_oper(const st +@@ -2673,6 +2680,8 @@ bool ieee80211_chandef_s1g_oper(const st struct cfg80211_chan_def *chandef); void ieee80211_chandef_downgrade(struct cfg80211_chan_def *chandef, struct ieee80211_conn_settings *conn); @@ -107,7 +107,7 @@ static inline void ieee80211_chanreq_downgrade(struct ieee80211_chan_req *chanreq, struct ieee80211_conn_settings *conn) -@@ -2716,7 +2725,7 @@ void ieee80211_recalc_chanctx_min_def(st +@@ -2729,7 +2738,7 @@ void ieee80211_recalc_chanctx_min_def(st struct ieee80211_chanctx *ctx, struct ieee80211_link_data *rsvd_for, bool check_reserved); diff --git a/package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch b/package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch index bffb66dfe73..b34465f3afe 100644 --- a/package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch +++ b/package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch @@ -126,7 +126,7 @@ Signed-off-by: Felix Fietkau } --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -2776,6 +2776,11 @@ u8 *ieee80211_get_bssid(struct ieee80211 +@@ -2789,6 +2789,11 @@ u8 *ieee80211_get_bssid(struct ieee80211 extern const struct ethtool_ops ieee80211_ethtool_ops;