FAILED: patch "[PATCH] wifi: mac80211: use wiphy_hrtimer_work for csa.switch_work" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x fbc1cc6973099f45e4c30b86f12b4435c7cb7d24
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025110956-smile-parade-ac75@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From fbc1cc6973099f45e4c30b86f12b4435c7cb7d24 Mon Sep 17 00:00:00 2001
From: Benjamin Berg <[email protected]>
Date: Tue, 28 Oct 2025 12:58:40 +0200
Subject: [PATCH] wifi: mac80211: use wiphy_hrtimer_work for csa.switch_work
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.
net/mac80211/chan.c +1 -1
@@ -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 :
net/mac80211/ieee80211_i.h +2 -2
@@ -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;
net/mac80211/link.c +2 -2
@@ -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 ) {
net/mac80211/mlme.c +9 -9
@@ -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); }
Sasha Levin
maintainerPATCH 1/2 wifi: cfg80211: add an hrtimer based delayed work item
From: Benjamin Berg <[email protected]>
The normal timer mechanism assume that timeout further in the future need a lower accuracy. As an example, the granularity for a timer scheduled 4096 ms in the future on a 1000 Hz system is already 512 ms. This granularity is perfectly sufficient for e.g. timeouts, but there are other types of events that will happen at a future point in time and require a higher accuracy.
Add a new wiphy_hrtimer_work type that uses an hrtimer internally. The API is almost identical to the existing wiphy_delayed_work and it can be used as a drop-in replacement after minor adjustments. The work will be scheduled relative to the current time with a slack of 1 millisecond.
--- include/net/cfg80211.h | 78 ++++++++++++++++++++++++++++++++++++++++++ net/wireless/core.c | 56 ++++++++++++++++++++++++++++++ net/wireless/trace.h | 21 ++++++++++++ 3 files changed, 155 insertions(+)
include/net/cfg80211.h +78 -0
@@ -6105,6 +6105,11 @@ static inline void wiphy_delayed_work_init(struct wiphy_delayed_work *dwork,* after wiphy_lock() was called. Therefore, wiphy_cancel_work() can * use just cancel_work() instead of cancel_work_sync(), it requires * being in a section protected by wiphy_lock(). +* +* Note that these are scheduled with a timer where the accuracy +* becomes less the longer in the future the scheduled timer is. Use +* wiphy_hrtimer_work_queue() if the timer must be not be late by more +* than approximately 10 percent. */ void wiphy_delayed_work_queue(struct wiphy *wiphy, struct wiphy_delayed_work *dwork,
@@ -6176,6 +6181,79 @@ void wiphy_delayed_work_flush(struct wiphy *wiphy,bool wiphy_delayed_work_pending (struct wiphy *wiphy,struct wiphy_delayed_work *dwork); +struct wiphy_hrtimer_work { +struct wiphy_work work; +struct wiphy *wiphy; +struct hrtimer timer; +}; + +enum hrtimer_restart wiphy_hrtimer_work_timer (struct hrtimer *t); + +static inline void wiphy_hrtimer_work_init (struct wiphy_hrtimer_work *hrwork, +wiphy_work_func_t func) +{ +hrtimer_init (&hrwork->timer,CLOCK_BOOTTIME ,HRTIMER_MODE_REL ); + hrwork->timer.function = wiphy_hrtimer_work_timer; +wiphy_work_init (&hrwork->work, func); +} + +/** +* wiphy_hrtimer_work_queue - queue hrtimer work for the wiphy +* @wiphy: the wiphy to queue for +* @hrwork: the high resolution timer worker +* @delay: the delay given as a ktime_t +* +* Please refer to wiphy_delayed_work_queue(). The difference is that +* the hrtimer work uses a high resolution timer for scheduling. This +* may be needed if timeouts might be scheduled further in the future +* and the accuracy of the normal timer is not sufficient. +* +* Expect a delay of a few milliseconds as the timer is scheduled +* with some slack and some more time may pass between queueing the +* work and its start. +*/ +void wiphy_hrtimer_work_queue (struct wiphy *wiphy, +struct wiphy_hrtimer_work *hrwork, +ktime_t delay); + +/** +* wiphy_hrtimer_work_cancel - cancel previously queued hrtimer work +* @wiphy: the wiphy, for debug purposes +* @hrtimer: the hrtimer work to cancel +* +* Cancel the work *without* waiting for it, this assumes being +* called under the wiphy mutex acquired by wiphy_lock(). +*/ +void wiphy_hrtimer_work_cancel (struct wiphy *wiphy, +struct wiphy_hrtimer_work *hrtimer); + +/** +* wiphy_hrtimer_work_flush - flush previously queued hrtimer work +* @wiphy: the wiphy, for debug purposes +* @hrwork: the hrtimer work to flush +* +* Flush the work (i.e. run it if pending). This must be called +* under the wiphy mutex acquired by wiphy_lock(). +*/ +void wiphy_hrtimer_work_flush (struct wiphy *wiphy, +struct wiphy_hrtimer_work *hrwork); + +/** +* wiphy_hrtimer_work_pending - Find out whether a wiphy hrtimer +* work item is currently pending. +* +* @wiphy: the wiphy, for debug purposes +* @hrwork: the hrtimer work in question +* +* Return: true if timer is pending, false otherwise +* +* Please refer to the wiphy_delayed_work_pending() documentation as +* this is the equivalent function for hrtimer based delayed work +* items. +*/ +bool wiphy_hrtimer_work_pending (struct wiphy *wiphy, +struct wiphy_hrtimer_work *hrwork); +/** * enum ieee80211_ap_reg_power - regulatory power for an Access Point *
net/wireless/core.c +56 -0
62 lines not on this page · raw message
net/wireless/trace.h +21 -0
@@ -304,6 +304,27 @@ TRACE_EVENT(wiphy_delayed_work_queue, __entry->delay) ); +TRACE_EVENT (wiphy_hrtimer_work_queue, + TP_PROTO(struct wiphy *wiphy, struct wiphy_work *work, + ktime_t delay), +TP_ARGS (wiphy, work, delay), +TP_STRUCT__entry ( + WIPHY_ENTRY + __field(void *, instance) + __field(void *, func) +__field (ktime_t, delay) + ), +TP_fast_assign ( + WIPHY_ASSIGN; + __entry->instance = work; + __entry->func = work->func; + __entry->delay = delay; + ), +TP_printk (WIPHY_PR_FMT " instance=%p func=%pS delay=%llu" , +WIPHY_PR_ARG , __entry->instance, __entry->func, + __entry->delay) +); + TRACE_EVENT(wiphy_work_worker_start, TP_PROTO(struct wiphy *wiphy), TP_ARGS(wiphy),
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 2/2 wifi: mac80211: use wiphy_hrtimer_work for csa.switch_work
From: Benjamin Berg <[email protected]>
[ Upstream commit fbc1cc6973099f45e4c30b86f12b4435c7cb7d24 ]
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.
--- net/mac80211/chan.c | 2 +- net/mac80211/ieee80211_i.h | 4 ++-- net/mac80211/link.c | 4 ++-- net/mac80211/mlme.c | 18 +++++++++--------- 4 files changed, 14 insertions(+), 14 deletions(-)
net/mac80211/chan.c +1 -1
@@ -1246,7 +1246,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 :
net/mac80211/ieee80211_i.h +2 -2
@@ -979,10 +979,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;
net/mac80211/link.c +2 -2
@@ -469,10 +469,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 ()); }list_for_each_entry (sta, &local->sta_list, list) {
net/mac80211/mlme.c +9 -9
@@ -2224,7 +2224,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 ); }
@@ -2383,7 +2383,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);
@@ -2613,10 +2614,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 +ns_to_ktime (ieee80211_tu_to_usec (csa_time_tu) *NSEC_PER_USEC );if (ieee80211_vif_link_active (&sdata->vif, link->link_id) && local->ops->channel_switch) {
@@ -2631,7 +2631,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 ;
@@ -8136,7 +8136,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);
@@ -9266,7 +9266,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); }
Signature · 1 line
2.51.0