]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211_hwsim: register beacon timer by calculating TBTT
authorBenjamin Berg <benjamin.berg@intel.com>
Mon, 4 May 2026 07:20:53 +0000 (10:20 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 5 May 2026 10:10:16 +0000 (12:10 +0200)
It is easy to calculate the next target beacon transmission time (TBTT)
based on the current TSF and the beacon interval. Use this method to
calculate the time to the next beacon.

With this, the bcn_delta variable can be removed and drift over time due
to the timer firing late is fully avoided.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260504101829.cc6f099ae2ac.Iccf6164f3feeb5350fcfe0df666248c686b226ae@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/virtual/mac80211_hwsim_i.h
drivers/net/wireless/virtual/mac80211_hwsim_main.c

index b4d0a3869619e6c72604d4623847666858570eab..d345595ca58873bf2bb23b40249d871eea7d2f2f 100644 (file)
@@ -103,7 +103,6 @@ struct mac80211_hwsim_data {
 
        /* difference between this hw's clock and the real clock, in usecs */
        s64 tsf_offset;
-       s64 bcn_delta;
 
        /* Stats */
        u64 tx_pkts;
index 5bf6541498ec75161b28a73e8c1f377f95c99193..ba2aa09b37cba03ce3ca8c484022bada11338260 100644 (file)
@@ -1216,6 +1216,12 @@ static inline u64 mac80211_hwsim_get_sim_tsf(void)
        return ktime_to_us(ktime_get_boottime());
 }
 
+static ktime_t mac80211_hwsim_tsf_to_boottime(struct mac80211_hwsim_data *data,
+                                             u64 tsf)
+{
+       return us_to_ktime(tsf - data->tsf_offset);
+}
+
 u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw,
                           struct ieee80211_vif *vif)
 {
@@ -1237,8 +1243,6 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
 {
        struct mac80211_hwsim_data *data = hw->priv;
        u64 now = mac80211_hwsim_get_tsf(hw, vif);
-       /* MLD not supported here */
-       u32 bcn_int = data->link_data[0].beacon_int;
        u64 delta = abs(tsf - now);
        struct ieee80211_bss_conf *conf;
 
@@ -1247,13 +1251,10 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
                return;
 
        /* adjust after beaconing with new timestamp at old TBTT */
-       if (tsf > now) {
+       if (tsf > now)
                data->tsf_offset += delta;
-               data->bcn_delta = do_div(delta, bcn_int);
-       } else {
+       else
                data->tsf_offset -= delta;
-               data->bcn_delta = -(s64)do_div(delta, bcn_int);
-       }
 }
 
 static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
@@ -2410,7 +2411,9 @@ mac80211_hwsim_beacon(struct hrtimer *timer)
                container_of(link_data, struct mac80211_hwsim_data,
                             link_data[link_data->link_id]);
        struct ieee80211_hw *hw = data->hw;
-       u64 bcn_int = link_data->beacon_int;
+       u32 remainder;
+       u64 tsf_now;
+       u64 tbtt;
 
        if (!data->started)
                return HRTIMER_NORESTART;
@@ -2419,13 +2422,19 @@ mac80211_hwsim_beacon(struct hrtimer *timer)
                hw, IEEE80211_IFACE_ITER_NORMAL,
                mac80211_hwsim_beacon_tx, link_data);
 
-       /* beacon at new TBTT + beacon interval */
-       if (data->bcn_delta) {
-               bcn_int -= data->bcn_delta;
-               data->bcn_delta = 0;
-       }
-       hrtimer_forward_now(&link_data->beacon_timer,
-                           ns_to_ktime(bcn_int * NSEC_PER_USEC));
+       /* TSF is the same for all VIFs, parameter is unused */
+       tsf_now = mac80211_hwsim_get_tsf(hw, NULL);
+
+       /* Wrap value to be after the next TBTT */
+       tbtt = tsf_now + link_data->beacon_int;
+
+       /* Round TBTT down to the correct time */
+       div_u64_rem(tbtt, link_data->beacon_int, &remainder);
+       tbtt = tbtt - remainder;
+
+       hrtimer_set_expires(&link_data->beacon_timer,
+                           mac80211_hwsim_tsf_to_boottime(data, tbtt));
+
        return HRTIMER_RESTART;
 }