|
|
@@ -0,0 +1,141 @@
|
|
|
+From: Maharaja Kennadyrajan <[email protected]>
|
|
|
+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 <[email protected]>
|
|
|
+Link: https://patch.msgid.link/[email protected]
|
|
|
+Signed-off-by: Johannes Berg <[email protected]>
|
|
|
+---
|
|
|
+
|
|
|
+--- 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;
|
|
|
+ }
|
|
|
+
|