Commit 01e59e46 authored by Thomas Pedersen's avatar Thomas Pedersen Committed by Johannes Berg

mac80211_hwsim: hrtimer beacon

For testing various timing-sensitive protocols (power
save, MBCA, etc.), a beacon accuracy of jiffies is not
sufficient. A tasklet_hrtimer is used for the beacon since
it runs the callback in soft-IRQ context with hrtimer
resolution.

Also handle BSS_CHANGED_BEACON_ENABLED for hwsim.
Signed-off-by: default avatarThomas Pedersen <thomas@cozybit.com>
[simplify timer container_of]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 45034bfb
...@@ -337,11 +337,11 @@ struct mac80211_hwsim_data { ...@@ -337,11 +337,11 @@ struct mac80211_hwsim_data {
int scan_chan_idx; int scan_chan_idx;
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
unsigned long beacon_int; /* in jiffies unit */ u64 beacon_int /* beacon interval in us */;
unsigned int rx_filter; unsigned int rx_filter;
bool started, idle, scanning; bool started, idle, scanning;
struct mutex mutex; struct mutex mutex;
struct timer_list beacon_timer; struct tasklet_hrtimer beacon_timer;
enum ps_mode { enum ps_mode {
PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
} ps; } ps;
...@@ -917,7 +917,7 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) ...@@ -917,7 +917,7 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
{ {
struct mac80211_hwsim_data *data = hw->priv; struct mac80211_hwsim_data *data = hw->priv;
data->started = false; data->started = false;
del_timer(&data->beacon_timer); tasklet_hrtimer_cancel(&data->beacon_timer);
wiphy_debug(hw->wiphy, "%s\n", __func__); wiphy_debug(hw->wiphy, "%s\n", __func__);
} }
...@@ -1001,21 +1001,28 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, ...@@ -1001,21 +1001,28 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
rcu_dereference(vif->chanctx_conf)->def.chan); rcu_dereference(vif->chanctx_conf)->def.chan);
} }
static enum hrtimer_restart
static void mac80211_hwsim_beacon(unsigned long arg) mac80211_hwsim_beacon(struct hrtimer *timer)
{ {
struct ieee80211_hw *hw = (struct ieee80211_hw *) arg; struct mac80211_hwsim_data *data =
struct mac80211_hwsim_data *data = hw->priv; container_of(timer, struct mac80211_hwsim_data,
beacon_timer.timer);
struct ieee80211_hw *hw = data->hw;
u64 bcn_int = data->beacon_int;
ktime_t next_bcn;
if (!data->started) if (!data->started)
return; goto out;
ieee80211_iterate_active_interfaces_atomic( ieee80211_iterate_active_interfaces_atomic(
hw, IEEE80211_IFACE_ITER_NORMAL, hw, IEEE80211_IFACE_ITER_NORMAL,
mac80211_hwsim_beacon_tx, hw); mac80211_hwsim_beacon_tx, hw);
data->beacon_timer.expires = jiffies + data->beacon_int; next_bcn = ktime_add(hrtimer_get_expires(timer),
add_timer(&data->beacon_timer); ns_to_ktime(bcn_int * 1000));
tasklet_hrtimer_start(&data->beacon_timer, next_bcn, HRTIMER_MODE_ABS);
out:
return HRTIMER_NORESTART;
} }
static const char *hwsim_chantypes[] = { static const char *hwsim_chantypes[] = {
...@@ -1053,9 +1060,12 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1053,9 +1060,12 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
data->power_level = conf->power_level; data->power_level = conf->power_level;
if (!data->started || !data->beacon_int) if (!data->started || !data->beacon_int)
del_timer(&data->beacon_timer); tasklet_hrtimer_cancel(&data->beacon_timer);
else else if (!hrtimer_is_queued(&data->beacon_timer.timer)) {
mod_timer(&data->beacon_timer, jiffies + data->beacon_int); tasklet_hrtimer_start(&data->beacon_timer,
ns_to_ktime(data->beacon_int * 1000),
HRTIMER_MODE_REL);
}
return 0; return 0;
} }
...@@ -1105,12 +1115,22 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1105,12 +1115,22 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON_INT) { if (changed & BSS_CHANGED_BEACON_INT) {
wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int); wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int);
data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; data->beacon_int = info->beacon_int * 1024;
if (WARN_ON(!data->beacon_int)) }
data->beacon_int = 1;
if (data->started) if (changed & BSS_CHANGED_BEACON_ENABLED) {
mod_timer(&data->beacon_timer, wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon);
jiffies + data->beacon_int); if (data->started &&
!hrtimer_is_queued(&data->beacon_timer.timer) &&
info->enable_beacon) {
if (WARN_ON(!data->beacon_int))
data->beacon_int = 1000 * 1024;
tasklet_hrtimer_start(&data->beacon_timer,
ns_to_ktime(data->beacon_int *
1000),
HRTIMER_MODE_REL);
} else if (!info->enable_beacon)
tasklet_hrtimer_cancel(&data->beacon_timer);
} }
if (changed & BSS_CHANGED_ERP_CTS_PROT) { if (changed & BSS_CHANGED_ERP_CTS_PROT) {
...@@ -2393,8 +2413,9 @@ static int __init init_mac80211_hwsim(void) ...@@ -2393,8 +2413,9 @@ static int __init init_mac80211_hwsim(void)
data->debugfs, data, data->debugfs, data,
&hwsim_fops_group); &hwsim_fops_group);
setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, tasklet_hrtimer_init(&data->beacon_timer,
(unsigned long) hw); mac80211_hwsim_beacon,
CLOCK_REALTIME, HRTIMER_MODE_ABS);
list_add_tail(&data->list, &hwsim_radios); list_add_tail(&data->list, &hwsim_radios);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment