]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
mac80211: extend connection monitoring for MLO
authorFelix Fietkau <nbd@nbd.name>
Wed, 27 Aug 2025 13:24:29 +0000 (15:24 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 27 Aug 2025 13:24:30 +0000 (15:24 +0200)
Required for latest mt76

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/kernel/mac80211/patches/subsys/340-wifi-mac80211-Add-link-iteration-macro-for-link-data.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/341-wifi-mac80211-extend-beacon-monitoring-for-MLO.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/342-wifi-mac80211-extend-connection-monitoring-for-MLO.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/343-wifi-mac80211-Make-CONNECTION_MONITOR-optional-for-M.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch
package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch

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 (file)
index 0000000..1c3bb78
--- /dev/null
@@ -0,0 +1,44 @@
+From: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
+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 <maharaja.kennadyrajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250718060837.59371-3-maharaja.kennadyrajan@oss.qualcomm.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- 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 (file)
index 0000000..f0226fd
--- /dev/null
@@ -0,0 +1,85 @@
+From: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
+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 <maharaja.kennadyrajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250718060837.59371-4-maharaja.kennadyrajan@oss.qualcomm.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- 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 (file)
index 0000000..3da0679
--- /dev/null
@@ -0,0 +1,136 @@
+From: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
+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 <maharaja.kennadyrajan@oss.qualcomm.com>
+Link: https://patch.msgid.link/20250718060837.59371-5-maharaja.kennadyrajan@oss.qualcomm.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- 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 (file)
index 0000000..457a889
--- /dev/null
@@ -0,0 +1,25 @@
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+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 <lorenzo@kernel.org>
+---
+
+--- 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;
index 33ca9fe3359f5cc16fb06abe585f0e7d34c53466..fe9db05cb1bbc1a583ba6d37601a12fdb42d9330 100644 (file)
@@ -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);
  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);
index bffb66dfe73f9a62fe5b6bea2ef23e0e30eaf6dd..b34465f3afe670b372d8922ae499c1aaa868e470 100644 (file)
@@ -126,7 +126,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
        }
 --- 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;