]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mac80211: use wiphy_hrtimer_work for csa.switch_work
authorBenjamin Berg <benjamin.berg@intel.com>
Tue, 28 Oct 2025 10:58:40 +0000 (12:58 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 28 Oct 2025 13:56:42 +0000 (14:56 +0100)
The work item may be scheduled relatively far in the future. As the
event happens at a specific point in time, the normal timer accuracy is
not sufficient in that case.

Switch to use wiphy_hrtimer_work so that the accuracy is sufficient. To
make this work, use the same clock to store the timestamp.

CC: stable@vger.kernel.org
Fixes: ec3252bff7b6 ("wifi: mac80211: use wiphy work for channel switch")
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20251028125710.68258c7e4ac4.I4ff2b2cdffbbf858bf5f08baccc7a88c4f9efe6f@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/chan.c
net/mac80211/ieee80211_i.h
net/mac80211/link.c
net/mac80211/mlme.c

index 57065714cf8ceb5e612705ddc913b90c1f296e2a..7f8799fd673eb81bab0e680b1e6331aa3215ad17 100644 (file)
@@ -1290,7 +1290,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
                                 &link->csa.finalize_work);
                break;
        case NL80211_IFTYPE_STATION:
-               wiphy_delayed_work_queue(sdata->local->hw.wiphy,
+               wiphy_hrtimer_work_queue(sdata->local->hw.wiphy,
                                         &link->u.mgd.csa.switch_work, 0);
                break;
        case NL80211_IFTYPE_UNSPECIFIED:
index eb38049b2252de816ec37aeed3d44514f211c5d8..878c3b14aeb806f6d7088d97abcd4e49cbaabe6e 100644 (file)
@@ -1017,10 +1017,10 @@ struct ieee80211_link_data_managed {
        bool operating_11g_mode;
 
        struct {
-               struct wiphy_delayed_work switch_work;
+               struct wiphy_hrtimer_work switch_work;
                struct cfg80211_chan_def ap_chandef;
                struct ieee80211_parsed_tpe tpe;
-               unsigned long time;
+               ktime_t time;
                bool waiting_bcn;
                bool ignored_same_chan;
                bool blocked_tx;
index d71eabe5abf8d8c6a061de9cc564c1e4d760b52f..4a19b765ccb69fd250ed9911d0329070a38bd33c 100644 (file)
@@ -472,10 +472,10 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
                 * from there.
                 */
                if (link->conf->csa_active)
-                       wiphy_delayed_work_queue(local->hw.wiphy,
+                       wiphy_hrtimer_work_queue(local->hw.wiphy,
                                                 &link->u.mgd.csa.switch_work,
                                                 link->u.mgd.csa.time -
-                                                jiffies);
+                                                ktime_get_boottime());
        }
 
        for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
index f95bcf84ecc2b8146ad34aa013d6325df32866a8..f3138d158535332e059462df7f500a15bc8f62f7 100644 (file)
@@ -2594,7 +2594,7 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
                        return;
                }
 
-               wiphy_delayed_work_queue(sdata->local->hw.wiphy,
+               wiphy_hrtimer_work_queue(sdata->local->hw.wiphy,
                                         &link->u.mgd.csa.switch_work, 0);
        }
 
@@ -2753,7 +2753,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
                .timestamp = timestamp,
                .device_timestamp = device_timestamp,
        };
-       unsigned long now;
+       u32 csa_time_tu;
+       ktime_t now;
        int res;
 
        lockdep_assert_wiphy(local->hw.wiphy);
@@ -2983,10 +2984,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
                                          csa_ie.mode);
 
        /* we may have to handle timeout for deactivated link in software */
-       now = jiffies;
-       link->u.mgd.csa.time = now +
-                              TU_TO_JIFFIES((max_t(int, csa_ie.count, 1) - 1) *
-                                            link->conf->beacon_int);
+       now = ktime_get_boottime();
+       csa_time_tu = (max_t(int, csa_ie.count, 1) - 1) * link->conf->beacon_int;
+       link->u.mgd.csa.time = now + us_to_ktime(ieee80211_tu_to_usec(csa_time_tu));
 
        if (ieee80211_vif_link_active(&sdata->vif, link->link_id) &&
            local->ops->channel_switch) {
@@ -3001,7 +3001,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
        }
 
        /* channel switch handled in software */
-       wiphy_delayed_work_queue(local->hw.wiphy,
+       wiphy_hrtimer_work_queue(local->hw.wiphy,
                                 &link->u.mgd.csa.switch_work,
                                 link->u.mgd.csa.time - now);
        return;
@@ -8849,7 +8849,7 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
        else
                link->u.mgd.req_smps = IEEE80211_SMPS_OFF;
 
-       wiphy_delayed_work_init(&link->u.mgd.csa.switch_work,
+       wiphy_hrtimer_work_init(&link->u.mgd.csa.switch_work,
                                ieee80211_csa_switch_work);
 
        ieee80211_clear_tpe(&link->conf->tpe);
@@ -10064,7 +10064,7 @@ void ieee80211_mgd_stop_link(struct ieee80211_link_data *link)
                          &link->u.mgd.request_smps_work);
        wiphy_work_cancel(link->sdata->local->hw.wiphy,
                          &link->u.mgd.recalc_smps);
-       wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy,
+       wiphy_hrtimer_work_cancel(link->sdata->local->hw.wiphy,
                                  &link->u.mgd.csa.switch_work);
 }