From: Benjamin Berg 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 --- .../net/wireless/virtual/mac80211_hwsim_i.h | 1 - .../wireless/virtual/mac80211_hwsim_main.c | 37 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_i.h b/drivers/net/wireless/virtual/mac80211_hwsim_i.h index 5aae80cee8ec..87d5e7c2b643 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim_i.h +++ b/drivers/net/wireless/virtual/mac80211_hwsim_i.h @@ -102,7 +102,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; diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c index 118c4d92d94f..43b969592d44 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c @@ -1116,6 +1116,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) { @@ -1137,8 +1143,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; @@ -1147,13 +1151,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, @@ -2274,7 +2275,8 @@ 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; + u64 tsf_now; + u64 tbtt; if (!data->started) return HRTIMER_NORESTART; @@ -2283,13 +2285,18 @@ 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 */ + tbtt = tbtt - tbtt % link_data->beacon_int; + + hrtimer_set_expires(&link_data->beacon_timer, + mac80211_hwsim_tsf_to_boottime(data, tbtt)); + return HRTIMER_RESTART; } -- 2.51.1