diff options
-rw-r--r-- | net/mac80211/mlme.c | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 86b69bd94b4c..b4b7ea52c65e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -4367,9 +4367,6 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) 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 @@ -4415,9 +4412,6 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, lockdep_assert_wiphy(sdata->local->hw.wiphy); - if (WARN_ON_ONCE(ieee80211_vif_is_mld(&sdata->vif))) - return; - if (!ieee80211_sdata_running(sdata)) return; @@ -8524,36 +8518,70 @@ static void ieee80211_sta_bcn_mon_timer(struct timer_list *t) &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; } |