Skip to content

Commit b68bd2e

Browse files
ilanpeer2lucacoelho
authored andcommitted
iwlwifi: mvm: Add FTM initiator RTT smoothing logic
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 <[email protected]> Signed-off-by: Luca Coelho <[email protected]> Link: https://lore.kernel.org/r/iwlwifi.20200930161256.48a9cec2081b.Iaec1e29f738232adfe9e2ea8e9eb9b6ff0323ae1@changeid Signed-off-by: Luca Coelho <[email protected]>
1 parent 3830a01 commit b68bd2e

File tree

5 files changed

+138
-0
lines changed

5 files changed

+138
-0
lines changed

drivers/net/wireless/intel/iwlwifi/mvm/constants.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,11 @@
159159
#define IWL_MVM_PHY_FILTER_CHAIN_B 0
160160
#define IWL_MVM_PHY_FILTER_CHAIN_C 0
161161
#define IWL_MVM_PHY_FILTER_CHAIN_D 0
162+
#define IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH false
163+
#define IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA 40
164+
/* 20016 pSec is 6 meter RTT, meaning 3 meter range */
165+
#define IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT 20016
166+
#define IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT 20016
167+
#define IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC 2
162168

163169
#endif /* __MVM_CONSTANTS_H */

drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ struct iwl_mvm_loc_entry {
7676
u8 buf[];
7777
};
7878

79+
struct iwl_mvm_smooth_entry {
80+
struct list_head list;
81+
u8 addr[ETH_ALEN];
82+
s64 rtt_avg;
83+
u64 host_time;
84+
};
85+
7986
static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm)
8087
{
8188
struct iwl_mvm_loc_entry *e, *t;
@@ -84,6 +91,7 @@ static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm)
8491
mvm->ftm_initiator.req_wdev = NULL;
8592
memset(mvm->ftm_initiator.responses, 0,
8693
sizeof(mvm->ftm_initiator.responses));
94+
8795
list_for_each_entry_safe(e, t, &mvm->ftm_initiator.loc_list, list) {
8896
list_del(&e->list);
8997
kfree(e);
@@ -120,6 +128,30 @@ void iwl_mvm_ftm_restart(struct iwl_mvm *mvm)
120128
iwl_mvm_ftm_reset(mvm);
121129
}
122130

131+
void iwl_mvm_ftm_initiator_smooth_config(struct iwl_mvm *mvm)
132+
{
133+
INIT_LIST_HEAD(&mvm->ftm_initiator.smooth.resp);
134+
135+
IWL_DEBUG_INFO(mvm,
136+
"enable=%u, alpha=%u, age_jiffies=%u, thresh=(%u:%u)\n",
137+
IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH,
138+
IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA,
139+
IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC * HZ,
140+
IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT,
141+
IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT);
142+
}
143+
144+
void iwl_mvm_ftm_initiator_smooth_stop(struct iwl_mvm *mvm)
145+
{
146+
struct iwl_mvm_smooth_entry *se, *st;
147+
148+
list_for_each_entry_safe(se, st, &mvm->ftm_initiator.smooth.resp,
149+
list) {
150+
list_del(&se->list);
151+
kfree(se);
152+
}
153+
}
154+
123155
static int
124156
iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s)
125157
{
@@ -728,6 +760,95 @@ static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id,
728760
return 0;
729761
}
730762

763+
static void iwl_mvm_ftm_rtt_smoothing(struct iwl_mvm *mvm,
764+
struct cfg80211_pmsr_result *res)
765+
{
766+
struct iwl_mvm_smooth_entry *resp;
767+
s64 rtt_avg, rtt = res->ftm.rtt_avg;
768+
u32 undershoot, overshoot;
769+
u8 alpha;
770+
bool found;
771+
772+
if (!IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH)
773+
return;
774+
775+
WARN_ON(rtt < 0);
776+
777+
if (res->status != NL80211_PMSR_STATUS_SUCCESS) {
778+
IWL_DEBUG_INFO(mvm,
779+
": %pM: ignore failed measurement. Status=%u\n",
780+
res->addr, res->status);
781+
return;
782+
}
783+
784+
found = false;
785+
list_for_each_entry(resp, &mvm->ftm_initiator.smooth.resp, list) {
786+
if (!memcmp(res->addr, resp->addr, ETH_ALEN)) {
787+
found = true;
788+
break;
789+
}
790+
}
791+
792+
if (!found) {
793+
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
794+
if (!resp)
795+
return;
796+
797+
memcpy(resp->addr, res->addr, ETH_ALEN);
798+
list_add_tail(&resp->list, &mvm->ftm_initiator.smooth.resp);
799+
800+
resp->rtt_avg = rtt;
801+
802+
IWL_DEBUG_INFO(mvm, "new: %pM: rtt_avg=%lld\n",
803+
resp->addr, resp->rtt_avg);
804+
goto update_time;
805+
}
806+
807+
if (res->host_time - resp->host_time >
808+
IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC * 1000000000) {
809+
resp->rtt_avg = rtt;
810+
811+
IWL_DEBUG_INFO(mvm, "expired: %pM: rtt_avg=%lld\n",
812+
resp->addr, resp->rtt_avg);
813+
goto update_time;
814+
}
815+
816+
/* Smooth the results based on the tracked RTT average */
817+
undershoot = IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT;
818+
overshoot = IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT;
819+
alpha = IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA;
820+
821+
rtt_avg = (alpha * rtt + (100 - alpha) * resp->rtt_avg) / 100;
822+
823+
IWL_DEBUG_INFO(mvm,
824+
"%pM: prev rtt_avg=%lld, new rtt_avg=%lld, rtt=%lld\n",
825+
resp->addr, resp->rtt_avg, rtt_avg, rtt);
826+
827+
/*
828+
* update the responder's average RTT results regardless of
829+
* the under/over shoot logic below
830+
*/
831+
resp->rtt_avg = rtt_avg;
832+
833+
/* smooth the results */
834+
if (rtt_avg > rtt && (rtt_avg - rtt) > undershoot) {
835+
res->ftm.rtt_avg = rtt_avg;
836+
837+
IWL_DEBUG_INFO(mvm,
838+
"undershoot: val=%lld\n",
839+
(rtt_avg - rtt));
840+
} else if (rtt_avg < rtt && (rtt - rtt_avg) >
841+
overshoot) {
842+
res->ftm.rtt_avg = rtt_avg;
843+
IWL_DEBUG_INFO(mvm,
844+
"overshoot: val=%lld\n",
845+
(rtt - rtt_avg));
846+
}
847+
848+
update_time:
849+
resp->host_time = res->host_time;
850+
}
851+
731852
static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index,
732853
struct cfg80211_pmsr_result *res)
733854
{
@@ -865,6 +986,8 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
865986

866987
iwl_mvm_ftm_get_lci_civic(mvm, &result);
867988

989+
iwl_mvm_ftm_rtt_smoothing(mvm, &result);
990+
868991
cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev,
869992
mvm->ftm_initiator.req,
870993
&result, GFP_KERNEL);

drivers/net/wireless/intel/iwlwifi/mvm/fw.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
15121512
iwl_mvm_tas_init(mvm);
15131513
iwl_mvm_leds_sync(mvm);
15141514

1515+
iwl_mvm_ftm_initiator_smooth_config(mvm);
1516+
15151517
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
15161518
return 0;
15171519
error:

drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,8 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
12111211
{
12121212
lockdep_assert_held(&mvm->mutex);
12131213

1214+
iwl_mvm_ftm_initiator_smooth_stop(mvm);
1215+
12141216
/* firmware counters are obviously reset now, but we shouldn't
12151217
* partially track so also clear the fw_reset_accu counters.
12161218
*/

drivers/net/wireless/intel/iwlwifi/mvm/mvm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,9 @@ struct iwl_mvm {
11071107
struct wireless_dev *req_wdev;
11081108
struct list_head loc_list;
11091109
int responses[IWL_MVM_TOF_MAX_APS];
1110+
struct {
1111+
struct list_head resp;
1112+
} smooth;
11101113
} ftm_initiator;
11111114

11121115
struct list_head resp_pasn_list;
@@ -2011,6 +2014,8 @@ void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm,
20112014
int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
20122015
struct cfg80211_pmsr_request *request);
20132016
void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req);
2017+
void iwl_mvm_ftm_initiator_smooth_config(struct iwl_mvm *mvm);
2018+
void iwl_mvm_ftm_initiator_smooth_stop(struct iwl_mvm *mvm);
20142019

20152020
/* TDLS */
20162021

0 commit comments

Comments
 (0)