xref: /linux/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c (revision b1a6db1320e94bc8e924918fc236b5df97c1cca7)
1b73f9a4aSJohannes Berg /******************************************************************************
2b73f9a4aSJohannes Berg  *
3b73f9a4aSJohannes Berg  * This file is provided under a dual BSD/GPLv2 license.  When using or
4b73f9a4aSJohannes Berg  * redistributing this file, you may do so under either license.
5b73f9a4aSJohannes Berg  *
6b73f9a4aSJohannes Berg  * GPL LICENSE SUMMARY
7b73f9a4aSJohannes Berg  *
8b73f9a4aSJohannes Berg  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
9*b1a6db13SAvraham Stern  * Copyright (C) 2018 - 2019 Intel Corporation
10b73f9a4aSJohannes Berg  *
11b73f9a4aSJohannes Berg  * This program is free software; you can redistribute it and/or modify
12b73f9a4aSJohannes Berg  * it under the terms of version 2 of the GNU General Public License as
13b73f9a4aSJohannes Berg  * published by the Free Software Foundation.
14b73f9a4aSJohannes Berg  *
15b73f9a4aSJohannes Berg  * This program is distributed in the hope that it will be useful, but
16b73f9a4aSJohannes Berg  * WITHOUT ANY WARRANTY; without even the implied warranty of
17b73f9a4aSJohannes Berg  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18b73f9a4aSJohannes Berg  * General Public License for more details.
19b73f9a4aSJohannes Berg  *
20b73f9a4aSJohannes Berg  * The full GNU General Public License is included in this distribution
21b73f9a4aSJohannes Berg  * in the file called COPYING.
22b73f9a4aSJohannes Berg  *
23b73f9a4aSJohannes Berg  * Contact Information:
24b73f9a4aSJohannes Berg  * Intel Linux Wireless <linuxwifi@intel.com>
25b73f9a4aSJohannes Berg  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26b73f9a4aSJohannes Berg  *
27b73f9a4aSJohannes Berg  * BSD LICENSE
28b73f9a4aSJohannes Berg  *
29b73f9a4aSJohannes Berg  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
30*b1a6db13SAvraham Stern  * Copyright (C) 2018 - 2019 Intel Corporation
31b73f9a4aSJohannes Berg  * All rights reserved.
32b73f9a4aSJohannes Berg  *
33b73f9a4aSJohannes Berg  * Redistribution and use in source and binary forms, with or without
34b73f9a4aSJohannes Berg  * modification, are permitted provided that the following conditions
35b73f9a4aSJohannes Berg  * are met:
36b73f9a4aSJohannes Berg  *
37b73f9a4aSJohannes Berg  *  * Redistributions of source code must retain the above copyright
38b73f9a4aSJohannes Berg  *    notice, this list of conditions and the following disclaimer.
39b73f9a4aSJohannes Berg  *  * Redistributions in binary form must reproduce the above copyright
40b73f9a4aSJohannes Berg  *    notice, this list of conditions and the following disclaimer in
41b73f9a4aSJohannes Berg  *    the documentation and/or other materials provided with the
42b73f9a4aSJohannes Berg  *    distribution.
43b73f9a4aSJohannes Berg  *  * Neither the name Intel Corporation nor the names of its
44b73f9a4aSJohannes Berg  *    contributors may be used to endorse or promote products derived
45b73f9a4aSJohannes Berg  *    from this software without specific prior written permission.
46b73f9a4aSJohannes Berg  *
47b73f9a4aSJohannes Berg  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48b73f9a4aSJohannes Berg  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49b73f9a4aSJohannes Berg  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
50b73f9a4aSJohannes Berg  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
51b73f9a4aSJohannes Berg  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52b73f9a4aSJohannes Berg  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53b73f9a4aSJohannes Berg  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54b73f9a4aSJohannes Berg  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55b73f9a4aSJohannes Berg  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56b73f9a4aSJohannes Berg  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57b73f9a4aSJohannes Berg  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58b73f9a4aSJohannes Berg  *
59b73f9a4aSJohannes Berg  *****************************************************************************/
60b73f9a4aSJohannes Berg #include <net/cfg80211.h>
61b73f9a4aSJohannes Berg #include <linux/etherdevice.h>
62b73f9a4aSJohannes Berg #include "mvm.h"
63b73f9a4aSJohannes Berg #include "constants.h"
64b73f9a4aSJohannes Berg 
65*b1a6db13SAvraham Stern static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef,
66*b1a6db13SAvraham Stern 					   u8 *bw, u8 *ctrl_ch_position)
67*b1a6db13SAvraham Stern {
68*b1a6db13SAvraham Stern 	switch (chandef->width) {
69*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_20_NOHT:
70*b1a6db13SAvraham Stern 		*bw = IWL_TOF_BW_20_LEGACY;
71*b1a6db13SAvraham Stern 		break;
72*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_20:
73*b1a6db13SAvraham Stern 		*bw = IWL_TOF_BW_20_HT;
74*b1a6db13SAvraham Stern 		break;
75*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_40:
76*b1a6db13SAvraham Stern 		*bw = IWL_TOF_BW_40;
77*b1a6db13SAvraham Stern 		*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
78*b1a6db13SAvraham Stern 		break;
79*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_80:
80*b1a6db13SAvraham Stern 		*bw = IWL_TOF_BW_80;
81*b1a6db13SAvraham Stern 		*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
82*b1a6db13SAvraham Stern 		break;
83*b1a6db13SAvraham Stern 	default:
84*b1a6db13SAvraham Stern 		return -ENOTSUPP;
85*b1a6db13SAvraham Stern 	}
86*b1a6db13SAvraham Stern 
87*b1a6db13SAvraham Stern 	return 0;
88*b1a6db13SAvraham Stern }
89*b1a6db13SAvraham Stern 
90*b1a6db13SAvraham Stern static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
91*b1a6db13SAvraham Stern 					   u8 *format_bw,
92*b1a6db13SAvraham Stern 					   u8 *ctrl_ch_position)
93*b1a6db13SAvraham Stern {
94*b1a6db13SAvraham Stern 	switch (chandef->width) {
95*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_20_NOHT:
96*b1a6db13SAvraham Stern 		*format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY;
97*b1a6db13SAvraham Stern 		*format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
98*b1a6db13SAvraham Stern 		break;
99*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_20:
100*b1a6db13SAvraham Stern 		*format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
101*b1a6db13SAvraham Stern 		*format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS;
102*b1a6db13SAvraham Stern 		break;
103*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_40:
104*b1a6db13SAvraham Stern 		*format_bw = IWL_LOCATION_FRAME_FORMAT_HT;
105*b1a6db13SAvraham Stern 		*format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS;
106*b1a6db13SAvraham Stern 		*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
107*b1a6db13SAvraham Stern 		break;
108*b1a6db13SAvraham Stern 	case NL80211_CHAN_WIDTH_80:
109*b1a6db13SAvraham Stern 		*format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;
110*b1a6db13SAvraham Stern 		*format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
111*b1a6db13SAvraham Stern 		*ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
112*b1a6db13SAvraham Stern 		break;
113*b1a6db13SAvraham Stern 	default:
114*b1a6db13SAvraham Stern 		return -ENOTSUPP;
115*b1a6db13SAvraham Stern 	}
116*b1a6db13SAvraham Stern 
117*b1a6db13SAvraham Stern 	return 0;
118*b1a6db13SAvraham Stern }
119*b1a6db13SAvraham Stern 
120b73f9a4aSJohannes Berg static int
121b73f9a4aSJohannes Berg iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
122b73f9a4aSJohannes Berg 			  struct ieee80211_vif *vif,
123b73f9a4aSJohannes Berg 			  struct cfg80211_chan_def *chandef)
124b73f9a4aSJohannes Berg {
125b73f9a4aSJohannes Berg 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
126*b1a6db13SAvraham Stern 	/*
127*b1a6db13SAvraham Stern 	 * The command structure is the same for versions 6 and 7, (only the
128*b1a6db13SAvraham Stern 	 * field interpretation is different), so the same struct can be use
129*b1a6db13SAvraham Stern 	 * for all cases.
130*b1a6db13SAvraham Stern 	 */
131b73f9a4aSJohannes Berg 	struct iwl_tof_responder_config_cmd cmd = {
132b73f9a4aSJohannes Berg 		.channel_num = chandef->chan->hw_value,
133b73f9a4aSJohannes Berg 		.cmd_valid_fields =
134b73f9a4aSJohannes Berg 			cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
135b73f9a4aSJohannes Berg 				    IWL_TOF_RESPONDER_CMD_VALID_BSSID |
136b73f9a4aSJohannes Berg 				    IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
137b73f9a4aSJohannes Berg 		.sta_id = mvmvif->bcast_sta.sta_id,
138b73f9a4aSJohannes Berg 	};
139*b1a6db13SAvraham Stern 	u8 cmd_ver = iwl_mvm_lookup_cmd_ver(mvm->fw, LOCATION_GROUP,
140*b1a6db13SAvraham Stern 					    TOF_RESPONDER_CONFIG_CMD);
141*b1a6db13SAvraham Stern 	int err;
142b73f9a4aSJohannes Berg 
143b73f9a4aSJohannes Berg 	lockdep_assert_held(&mvm->mutex);
144b73f9a4aSJohannes Berg 
145*b1a6db13SAvraham Stern 	if (cmd_ver == 7)
146*b1a6db13SAvraham Stern 		err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw,
147*b1a6db13SAvraham Stern 						      &cmd.ctrl_ch_position);
148*b1a6db13SAvraham Stern 	else
149*b1a6db13SAvraham Stern 		err = iwl_mvm_ftm_responder_set_bw_v1(chandef, &cmd.format_bw,
150*b1a6db13SAvraham Stern 						      &cmd.ctrl_ch_position);
151*b1a6db13SAvraham Stern 
152*b1a6db13SAvraham Stern 	if (err) {
153*b1a6db13SAvraham Stern 		IWL_ERR(mvm, "Failed to set responder bandwidth\n");
154*b1a6db13SAvraham Stern 		return err;
155b73f9a4aSJohannes Berg 	}
156b73f9a4aSJohannes Berg 
157b73f9a4aSJohannes Berg 	memcpy(cmd.bssid, vif->addr, ETH_ALEN);
158b73f9a4aSJohannes Berg 
159b73f9a4aSJohannes Berg 	return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RESPONDER_CONFIG_CMD,
160b73f9a4aSJohannes Berg 						    LOCATION_GROUP, 0),
161b73f9a4aSJohannes Berg 				    0, sizeof(cmd), &cmd);
162b73f9a4aSJohannes Berg }
163b73f9a4aSJohannes Berg 
164b73f9a4aSJohannes Berg static int
165b73f9a4aSJohannes Berg iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
166b73f9a4aSJohannes Berg 				  struct ieee80211_vif *vif,
167b73f9a4aSJohannes Berg 				  struct ieee80211_ftm_responder_params *params)
168b73f9a4aSJohannes Berg {
169b73f9a4aSJohannes Berg 	struct iwl_tof_responder_dyn_config_cmd cmd = {
170b73f9a4aSJohannes Berg 		.lci_len = cpu_to_le32(params->lci_len + 2),
171b73f9a4aSJohannes Berg 		.civic_len = cpu_to_le32(params->civicloc_len + 2),
172b73f9a4aSJohannes Berg 	};
173b73f9a4aSJohannes Berg 	u8 data[IWL_LCI_CIVIC_IE_MAX_SIZE] = {0};
174b73f9a4aSJohannes Berg 	struct iwl_host_cmd hcmd = {
175b73f9a4aSJohannes Berg 		.id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD,
176b73f9a4aSJohannes Berg 				 LOCATION_GROUP, 0),
177b73f9a4aSJohannes Berg 		.data[0] = &cmd,
178b73f9a4aSJohannes Berg 		.len[0] = sizeof(cmd),
179b73f9a4aSJohannes Berg 		.data[1] = &data,
180b73f9a4aSJohannes Berg 		/* .len[1] set later */
181b73f9a4aSJohannes Berg 		/* may not be able to DMA from stack */
182b73f9a4aSJohannes Berg 		.dataflags[1] = IWL_HCMD_DFL_DUP,
183b73f9a4aSJohannes Berg 	};
184b73f9a4aSJohannes Berg 	u32 aligned_lci_len = ALIGN(params->lci_len + 2, 4);
185b73f9a4aSJohannes Berg 	u32 aligned_civicloc_len = ALIGN(params->civicloc_len + 2, 4);
186b73f9a4aSJohannes Berg 	u8 *pos = data;
187b73f9a4aSJohannes Berg 
188b73f9a4aSJohannes Berg 	lockdep_assert_held(&mvm->mutex);
189b73f9a4aSJohannes Berg 
190b73f9a4aSJohannes Berg 	if (aligned_lci_len + aligned_civicloc_len > sizeof(data)) {
191b73f9a4aSJohannes Berg 		IWL_ERR(mvm, "LCI/civicloc data too big (%zd + %zd)\n",
192b73f9a4aSJohannes Berg 			params->lci_len, params->civicloc_len);
193b73f9a4aSJohannes Berg 		return -ENOBUFS;
194b73f9a4aSJohannes Berg 	}
195b73f9a4aSJohannes Berg 
196b73f9a4aSJohannes Berg 	pos[0] = WLAN_EID_MEASURE_REPORT;
197b73f9a4aSJohannes Berg 	pos[1] = params->lci_len;
198b73f9a4aSJohannes Berg 	memcpy(pos + 2, params->lci, params->lci_len);
199b73f9a4aSJohannes Berg 
200b73f9a4aSJohannes Berg 	pos += aligned_lci_len;
201b73f9a4aSJohannes Berg 	pos[0] = WLAN_EID_MEASURE_REPORT;
202b73f9a4aSJohannes Berg 	pos[1] = params->civicloc_len;
203b73f9a4aSJohannes Berg 	memcpy(pos + 2, params->civicloc, params->civicloc_len);
204b73f9a4aSJohannes Berg 
205b73f9a4aSJohannes Berg 	hcmd.len[1] = aligned_lci_len + aligned_civicloc_len;
206b73f9a4aSJohannes Berg 
207b73f9a4aSJohannes Berg 	return iwl_mvm_send_cmd(mvm, &hcmd);
208b73f9a4aSJohannes Berg }
209b73f9a4aSJohannes Berg 
210b73f9a4aSJohannes Berg int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
211b73f9a4aSJohannes Berg {
212b73f9a4aSJohannes Berg 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
213b73f9a4aSJohannes Berg 	struct ieee80211_ftm_responder_params *params;
214b73f9a4aSJohannes Berg 	struct ieee80211_chanctx_conf ctx, *pctx;
215b73f9a4aSJohannes Berg 	u16 *phy_ctxt_id;
216b73f9a4aSJohannes Berg 	struct iwl_mvm_phy_ctxt *phy_ctxt;
217b73f9a4aSJohannes Berg 	int ret;
218b73f9a4aSJohannes Berg 
219b73f9a4aSJohannes Berg 	params = vif->bss_conf.ftmr_params;
220b73f9a4aSJohannes Berg 
221b73f9a4aSJohannes Berg 	lockdep_assert_held(&mvm->mutex);
222b73f9a4aSJohannes Berg 
223b73f9a4aSJohannes Berg 	if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder))
224b73f9a4aSJohannes Berg 		return -EINVAL;
225b73f9a4aSJohannes Berg 
226b73f9a4aSJohannes Berg 	if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
227b73f9a4aSJohannes Berg 	    !mvmvif->ap_ibss_active) {
228b73f9a4aSJohannes Berg 		IWL_ERR(mvm, "Cannot start responder, not in AP mode\n");
229b73f9a4aSJohannes Berg 		return -EIO;
230b73f9a4aSJohannes Berg 	}
231b73f9a4aSJohannes Berg 
232b73f9a4aSJohannes Berg 	rcu_read_lock();
233b73f9a4aSJohannes Berg 	pctx = rcu_dereference(vif->chanctx_conf);
234b73f9a4aSJohannes Berg 	/* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care
235b73f9a4aSJohannes Berg 	 * about changes in the ctx after releasing the lock because the driver
236b73f9a4aSJohannes Berg 	 * is still protected by the mutex. */
237b73f9a4aSJohannes Berg 	ctx = *pctx;
238b73f9a4aSJohannes Berg 	phy_ctxt_id  = (u16 *)pctx->drv_priv;
239b73f9a4aSJohannes Berg 	rcu_read_unlock();
240b73f9a4aSJohannes Berg 
241b73f9a4aSJohannes Berg 	phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
242b73f9a4aSJohannes Berg 	ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def,
243b73f9a4aSJohannes Berg 				       ctx.rx_chains_static,
244b73f9a4aSJohannes Berg 				       ctx.rx_chains_dynamic);
245b73f9a4aSJohannes Berg 	if (ret)
246b73f9a4aSJohannes Berg 		return ret;
247b73f9a4aSJohannes Berg 
248b73f9a4aSJohannes Berg 	ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def);
249b73f9a4aSJohannes Berg 	if (ret)
250b73f9a4aSJohannes Berg 		return ret;
251b73f9a4aSJohannes Berg 
252b73f9a4aSJohannes Berg 	if (params)
253b73f9a4aSJohannes Berg 		ret = iwl_mvm_ftm_responder_dyn_cfg_cmd(mvm, vif, params);
254b73f9a4aSJohannes Berg 
255b73f9a4aSJohannes Berg 	return ret;
256b73f9a4aSJohannes Berg }
257b73f9a4aSJohannes Berg 
258b73f9a4aSJohannes Berg void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
259b73f9a4aSJohannes Berg 				   struct ieee80211_vif *vif)
260b73f9a4aSJohannes Berg {
261b73f9a4aSJohannes Berg 	if (!vif->bss_conf.ftm_responder)
262b73f9a4aSJohannes Berg 		return;
263b73f9a4aSJohannes Berg 
264b73f9a4aSJohannes Berg 	iwl_mvm_ftm_start_responder(mvm, vif);
265b73f9a4aSJohannes Berg }
266b73f9a4aSJohannes Berg 
267b73f9a4aSJohannes Berg void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
268b73f9a4aSJohannes Berg 				 struct iwl_rx_cmd_buffer *rxb)
269b73f9a4aSJohannes Berg {
270b73f9a4aSJohannes Berg 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
271b73f9a4aSJohannes Berg 	struct iwl_ftm_responder_stats *resp = (void *)pkt->data;
272b73f9a4aSJohannes Berg 	struct cfg80211_ftm_responder_stats *stats = &mvm->ftm_resp_stats;
273b73f9a4aSJohannes Berg 	u32 flags = le32_to_cpu(resp->flags);
274b73f9a4aSJohannes Berg 
275b73f9a4aSJohannes Berg 	if (resp->success_ftm == resp->ftm_per_burst)
276b73f9a4aSJohannes Berg 		stats->success_num++;
277b73f9a4aSJohannes Berg 	else if (resp->success_ftm >= 2)
278b73f9a4aSJohannes Berg 		stats->partial_num++;
279b73f9a4aSJohannes Berg 	else
280b73f9a4aSJohannes Berg 		stats->failed_num++;
281b73f9a4aSJohannes Berg 
282b73f9a4aSJohannes Berg 	if ((flags & FTM_RESP_STAT_ASAP_REQ) &&
283b73f9a4aSJohannes Berg 	    (flags & FTM_RESP_STAT_ASAP_RESP))
284b73f9a4aSJohannes Berg 		stats->asap_num++;
285b73f9a4aSJohannes Berg 
286b73f9a4aSJohannes Berg 	if (flags & FTM_RESP_STAT_NON_ASAP_RESP)
287b73f9a4aSJohannes Berg 		stats->non_asap_num++;
288b73f9a4aSJohannes Berg 
289b73f9a4aSJohannes Berg 	stats->total_duration_ms += le32_to_cpu(resp->duration) / USEC_PER_MSEC;
290b73f9a4aSJohannes Berg 
291b73f9a4aSJohannes Berg 	if (flags & FTM_RESP_STAT_TRIGGER_UNKNOWN)
292b73f9a4aSJohannes Berg 		stats->unknown_triggers_num++;
293b73f9a4aSJohannes Berg 
294b73f9a4aSJohannes Berg 	if (flags & FTM_RESP_STAT_DUP)
295b73f9a4aSJohannes Berg 		stats->reschedule_requests_num++;
296b73f9a4aSJohannes Berg 
297b73f9a4aSJohannes Berg 	if (flags & FTM_RESP_STAT_NON_ASAP_OUT_WIN)
298b73f9a4aSJohannes Berg 		stats->out_of_window_triggers_num++;
299b73f9a4aSJohannes Berg }
300