Skip to content

Commit

Permalink
iwlwifi: mvm: Add FTM initiator RTT smoothing logic
Browse files Browse the repository at this point in the history
The overcome instabilities in the RTT results add smoothing logic
to the reported results. In short, the smoothing logic tracks the
RTT average of each responder for a period of time, and in case
a new RTT results is found to be a spur, the tracked RTT average
is reported instead of the current RTT measurement.

Smooth logic debug configuration using iwl-dbg-cfg.ini:

- MVM_FTM_INITIATOR_ENABLE_SMOOTH: Set to 1 to enable smoothing logic
 (default=0).
- MVM_FTM_INITIATOR_SMOOTH_ALPHA: A value between 0 - 100, defining
  the weight of the current RTT results vs. the RTT average tracked
  based on the previous results. A value of 100 means use only the
  current RTT results.
- MVM_FTM_INITIATOR_SMOOTH_AGE_SEC: The maximal time in seconds in which
  the RTT average tracked based on previous results is considered valid.
- MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT: if the current RTT is positive
  and below the RTT average by at least this value, report the average
  RTT instead of the current one. In units of picoseconds.
- MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT: if the current RTT is positive
  and above the RTT average by at least this value, report the average
  RTT instead of the current one. In units of picoseconds.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20200930161256.48a9cec2081b.Iaec1e29f738232adfe9e2ea8e9eb9b6ff0323ae1@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
  • Loading branch information
Ilan Peer authored and Luca Coelho committed Oct 1, 2020
1 parent 3830a01 commit b68bd2e
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 0 deletions.
6 changes: 6 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,11 @@
#define IWL_MVM_PHY_FILTER_CHAIN_B 0
#define IWL_MVM_PHY_FILTER_CHAIN_C 0
#define IWL_MVM_PHY_FILTER_CHAIN_D 0
#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false
#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40
/* 20016 pSec is 6 meter RTT, meaning 3 meter range */
#define IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT 20016
#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016
#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2

#endif /* __MVM_CONSTANTS_H */
123 changes: 123 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ struct iwl_mvm_loc_entry {
u8 buf[];
};

struct iwl_mvm_smooth_entry {
struct list_head list;
u8 addr[ETH_ALEN];
s64 rtt_avg;
u64 host_time;
};

static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm)
{
struct iwl_mvm_loc_entry *e, *t;
Expand All @@ -84,6 +91,7 @@ static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm)
mvm->ftm_initiator.req_wdev = NULL;
memset(mvm->ftm_initiator.responses, 0,
sizeof(mvm->ftm_initiator.responses));

list_for_each_entry_safe(e, t, &mvm->ftm_initiator.loc_list, list) {
list_del(&e->list);
kfree(e);
Expand Down Expand Up @@ -120,6 +128,30 @@ void iwl_mvm_ftm_restart(struct iwl_mvm *mvm)
iwl_mvm_ftm_reset(mvm);
}

void iwl_mvm_ftm_initiator_smooth_config(struct iwl_mvm *mvm)
{
INIT_LIST_HEAD(&mvm->ftm_initiator.smooth.resp);

IWL_DEBUG_INFO(mvm,
"enable=%u, alpha=%u, age_jiffies=%u, thresh=(%u:%u)\n",
IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH,
IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA,
IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC * HZ,
IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT,
IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT);
}

void iwl_mvm_ftm_initiator_smooth_stop(struct iwl_mvm *mvm)
{
struct iwl_mvm_smooth_entry *se, *st;

list_for_each_entry_safe(se, st, &mvm->ftm_initiator.smooth.resp,
list) {
list_del(&se->list);
kfree(se);
}
}

static int
iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s)
{
Expand Down Expand Up @@ -728,6 +760,95 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id,
return 0;
}

static void iwl_mvm_ftm_rtt_smoothing(struct iwl_mvm *mvm,
struct cfg80211_pmsr_result *res)
{
struct iwl_mvm_smooth_entry *resp;
s64 rtt_avg, rtt = res->ftm.rtt_avg;
u32 undershoot, overshoot;
u8 alpha;
bool found;

if (!IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH)
return;

WARN_ON(rtt < 0);

if (res->status != NL80211_PMSR_STATUS_SUCCESS) {
IWL_DEBUG_INFO(mvm,
": %pM: ignore failed measurement. Status=%u\n",
res->addr, res->status);
return;
}

found = false;
list_for_each_entry(resp, &mvm->ftm_initiator.smooth.resp, list) {
if (!memcmp(res->addr, resp->addr, ETH_ALEN)) {
found = true;
break;
}
}

if (!found) {
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
if (!resp)
return;

memcpy(resp->addr, res->addr, ETH_ALEN);
list_add_tail(&resp->list, &mvm->ftm_initiator.smooth.resp);

resp->rtt_avg = rtt;

IWL_DEBUG_INFO(mvm, "new: %pM: rtt_avg=%lld\n",
resp->addr, resp->rtt_avg);
goto update_time;
}

if (res->host_time - resp->host_time >
IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC * 1000000000) {
resp->rtt_avg = rtt;

IWL_DEBUG_INFO(mvm, "expired: %pM: rtt_avg=%lld\n",
resp->addr, resp->rtt_avg);
goto update_time;
}

/* Smooth the results based on the tracked RTT average */
undershoot = IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT;
overshoot = IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT;
alpha = IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA;

rtt_avg = (alpha * rtt + (100 - alpha) * resp->rtt_avg) / 100;

IWL_DEBUG_INFO(mvm,
"%pM: prev rtt_avg=%lld, new rtt_avg=%lld, rtt=%lld\n",
resp->addr, resp->rtt_avg, rtt_avg, rtt);

/*
* update the responder's average RTT results regardless of
* the under/over shoot logic below
*/
resp->rtt_avg = rtt_avg;

/* smooth the results */
if (rtt_avg > rtt && (rtt_avg - rtt) > undershoot) {
res->ftm.rtt_avg = rtt_avg;

IWL_DEBUG_INFO(mvm,
"undershoot: val=%lld\n",
(rtt_avg - rtt));
} else if (rtt_avg < rtt && (rtt - rtt_avg) >
overshoot) {
res->ftm.rtt_avg = rtt_avg;
IWL_DEBUG_INFO(mvm,
"overshoot: val=%lld\n",
(rtt - rtt_avg));
}

update_time:
resp->host_time = res->host_time;
}

static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index,
struct cfg80211_pmsr_result *res)
{
Expand Down Expand Up @@ -865,6 +986,8 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)

iwl_mvm_ftm_get_lci_civic(mvm, &result);

iwl_mvm_ftm_rtt_smoothing(mvm, &result);

cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev,
mvm->ftm_initiator.req,
&result, GFP_KERNEL);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
iwl_mvm_tas_init(mvm);
iwl_mvm_leds_sync(mvm);

iwl_mvm_ftm_initiator_smooth_config(mvm);

IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
return 0;
error:
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,8 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
{
lockdep_assert_held(&mvm->mutex);

iwl_mvm_ftm_initiator_smooth_stop(mvm);

/* firmware counters are obviously reset now, but we shouldn't
* partially track so also clear the fw_reset_accu counters.
*/
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,9 @@ struct iwl_mvm {
struct wireless_dev *req_wdev;
struct list_head loc_list;
int responses[IWL_MVM_TOF_MAX_APS];
struct {
struct list_head resp;
} smooth;
} ftm_initiator;

struct list_head resp_pasn_list;
Expand Down Expand Up @@ -2011,6 +2014,8 @@ void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm,
int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_pmsr_request *request);
void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req);
void iwl_mvm_ftm_initiator_smooth_config(struct iwl_mvm *mvm);
void iwl_mvm_ftm_initiator_smooth_stop(struct iwl_mvm *mvm);

/* TDLS */

Expand Down

0 comments on commit b68bd2e

Please sign in to comment.