mac80211: add offset_tsf driver op and use it for mesh

This allows the mesh sync (and debugfs) code to make incremental
TSF adjustments, avoiding any uncertainty introduced by delay in
programming absolute TSF.

Signed-off-by: Thomas Pedersen <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
This commit is contained in:
Pedersen, Thomas 2016-09-28 16:56:28 -07:00 • committed by Johannes Berg
commit 354d381baf
6 changed files with 68 additions and 6 deletions

View file

@ -556,9 +556,15 @@ static ssize_t ieee80211_if_parse_tsf(
ret = kstrtoull(buf, 10, &tsf);
if (ret < 0)
return ret;
if (tsf_is_delta)
tsf = drv_get_tsf(local, sdata) + tsf_is_delta * tsf;
if (local->ops->set_tsf) {
if (tsf_is_delta && local->ops->offset_tsf) {
drv_offset_tsf(local, sdata, tsf_is_delta * tsf);
wiphy_info(local->hw.wiphy,
"debugfs offset TSF by %018lld\n",
tsf_is_delta * tsf);
} else if (local->ops->set_tsf) {
if (tsf_is_delta)
tsf = drv_get_tsf(local, sdata) +
tsf_is_delta * tsf;
drv_set_tsf(local, sdata, tsf);
wiphy_info(local->hw.wiphy,
"debugfs set TSF to %#018llx\n", tsf);

View file

@ -215,6 +215,21 @@ void drv_set_tsf(struct ieee80211_local *local,
trace_drv_return_void(local);
}
void drv_offset_tsf(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
s64 offset)
{
might_sleep();
if (!check_sdata_in_driver(sdata))
return;
trace_drv_offset_tsf(local, sdata, offset);
if (local->ops->offset_tsf)
local->ops->offset_tsf(&local->hw, &sdata->vif, offset);
trace_drv_return_void(local);
}
void drv_reset_tsf(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{

View file

@ -569,6 +569,9 @@ u64 drv_get_tsf(struct ieee80211_local *local,
void drv_set_tsf(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
u64 tsf);
void drv_offset_tsf(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
s64 offset);
void drv_reset_tsf(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);

View file

@ -70,9 +70,13 @@ void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata)
}
spin_unlock_bh(&ifmsh->sync_offset_lock);
tsf = drv_get_tsf(local, sdata);
if (tsf != -1ULL)
drv_set_tsf(local, sdata, tsf + tsfdelta);
if (local->ops->offset_tsf) {
drv_offset_tsf(local, sdata, tsfdelta);
} else {
tsf = drv_get_tsf(local, sdata);
if (tsf != -1ULL)
drv_set_tsf(local, sdata, tsf + tsfdelta);
}
}
static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,

View file

@ -984,6 +984,32 @@ TRACE_EVENT(drv_set_tsf,
)
);
TRACE_EVENT(drv_offset_tsf,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
s64 offset),
TP_ARGS(local, sdata, offset),
TP_STRUCT__entry(
LOCAL_ENTRY
VIF_ENTRY
__field(s64, tsf_offset)
),
TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
__entry->tsf_offset = offset;
),
TP_printk(
LOCAL_PR_FMT VIF_PR_FMT " tsf offset:%lld",
LOCAL_PR_ARG, VIF_PR_ARG,
(unsigned long long)__entry->tsf_offset
)
);
DEFINE_EVENT(local_sdata_evt, drv_reset_tsf,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata),