mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
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 <twp@qca.qualcomm.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
3ff23cd565
commit
354d381baf
@ -3169,6 +3169,12 @@ enum ieee80211_reconfig_type {
|
||||
* required function.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @offset_tsf: Offset the TSF timer by the specified value in the
|
||||
* firmware/hardware. Preferred to set_tsf as it avoids delay between
|
||||
* calling set_tsf() and hardware getting programmed, which will show up
|
||||
* as TSF delay. Is not a required function.
|
||||
* The callback can sleep.
|
||||
*
|
||||
* @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize
|
||||
* with other STAs in the IBSS. This is only used in IBSS mode. This
|
||||
* function is optional if the firmware/hardware takes full care of
|
||||
@ -3549,6 +3555,8 @@ struct ieee80211_ops {
|
||||
u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u64 tsf);
|
||||
void (*offset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
s64 offset);
|
||||
void (*reset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
int (*tx_last_beacon)(struct ieee80211_hw *hw);
|
||||
int (*ampdu_action)(struct ieee80211_hw *hw,
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user