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.

CC: stable@vger.kernel.org
Fixes: ec3252bff7 ("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>
This commit is contained in:
Benjamin Berg
2025-10-28 12:58:40 +02:00
committed by Johannes Berg
parent 3f654d53df
commit fbc1cc6973
4 changed files with 14 additions and 14 deletions

View File

@@ -1290,7 +1290,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
&link->csa.finalize_work); &link->csa.finalize_work);
break; break;
case NL80211_IFTYPE_STATION: 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); &link->u.mgd.csa.switch_work, 0);
break; break;
case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_UNSPECIFIED:

View File

@@ -1017,10 +1017,10 @@ struct ieee80211_link_data_managed {
bool operating_11g_mode; bool operating_11g_mode;
struct { struct {
struct wiphy_delayed_work switch_work; struct wiphy_hrtimer_work switch_work;
struct cfg80211_chan_def ap_chandef; struct cfg80211_chan_def ap_chandef;
struct ieee80211_parsed_tpe tpe; struct ieee80211_parsed_tpe tpe;
unsigned long time; ktime_t time;
bool waiting_bcn; bool waiting_bcn;
bool ignored_same_chan; bool ignored_same_chan;
bool blocked_tx; bool blocked_tx;

View File

@@ -472,10 +472,10 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
* from there. * from there.
*/ */
if (link->conf->csa_active) 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.switch_work,
link->u.mgd.csa.time - link->u.mgd.csa.time -
jiffies); ktime_get_boottime());
} }
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {

View File

@@ -2594,7 +2594,7 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
return; return;
} }
wiphy_delayed_work_queue(sdata->local->hw.wiphy, wiphy_hrtimer_work_queue(sdata->local->hw.wiphy,
&link->u.mgd.csa.switch_work, 0); &link->u.mgd.csa.switch_work, 0);
} }
@@ -2753,7 +2753,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
.timestamp = timestamp, .timestamp = timestamp,
.device_timestamp = device_timestamp, .device_timestamp = device_timestamp,
}; };
unsigned long now; u32 csa_time_tu;
ktime_t now;
int res; int res;
lockdep_assert_wiphy(local->hw.wiphy); lockdep_assert_wiphy(local->hw.wiphy);
@@ -2983,10 +2984,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
csa_ie.mode); csa_ie.mode);
/* we may have to handle timeout for deactivated link in software */ /* we may have to handle timeout for deactivated link in software */
now = jiffies; now = ktime_get_boottime();
link->u.mgd.csa.time = now + csa_time_tu = (max_t(int, csa_ie.count, 1) - 1) * link->conf->beacon_int;
TU_TO_JIFFIES((max_t(int, csa_ie.count, 1) - 1) * link->u.mgd.csa.time = now + us_to_ktime(ieee80211_tu_to_usec(csa_time_tu));
link->conf->beacon_int);
if (ieee80211_vif_link_active(&sdata->vif, link->link_id) && if (ieee80211_vif_link_active(&sdata->vif, link->link_id) &&
local->ops->channel_switch) { local->ops->channel_switch) {
@@ -3001,7 +3001,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
} }
/* channel switch handled in software */ /* 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.switch_work,
link->u.mgd.csa.time - now); link->u.mgd.csa.time - now);
return; return;
@@ -8849,7 +8849,7 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
else else
link->u.mgd.req_smps = IEEE80211_SMPS_OFF; 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_csa_switch_work);
ieee80211_clear_tpe(&link->conf->tpe); 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); &link->u.mgd.request_smps_work);
wiphy_work_cancel(link->sdata->local->hw.wiphy, wiphy_work_cancel(link->sdata->local->hw.wiphy,
&link->u.mgd.recalc_smps); &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); &link->u.mgd.csa.switch_work);
} }