forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/dhd_rtt.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Broadcom Dongle Host Driver (DHD), RTT
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5
+ *
6
+ * Copyright (C) 1999-2017, Broadcom Corporation
7
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,12 +18,15 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
2425 *
25
- * $Id: dhd_rtt.c 674349 2017-10-19 07:59:24Z $
26
+ *
27
+ * <<Broadcom-WL-IPTag/Open:>>
28
+ *
29
+ * $Id$
2630 */
2731 #include <typedefs.h>
2832 #include <osl.h>
....@@ -38,13 +42,24 @@
3842 #include <linux/sort.h>
3943 #include <dngl_stats.h>
4044 #include <wlioctl.h>
45
+#include <bcmwifi_rspec.h>
4146
42
-#include <proto/bcmevent.h>
47
+#include <bcmevent.h>
4348 #include <dhd.h>
49
+#include <dhd_linux.h>
4450 #include <dhd_rtt.h>
4551 #include <dhd_dbg.h>
46
-#define GET_RTTSTATE(dhd) ((rtt_status_info_t *)dhd->rtt_state)
52
+#include <dhd_bus.h>
53
+#include <wldev_common.h>
54
+#ifdef WL_CFG80211
55
+#include <wl_cfg80211.h>
56
+#endif /* WL_CFG80211 */
57
+#ifdef WL_NAN
58
+#include <wl_cfgnan.h>
59
+#endif /* WL_NAN */
60
+
4761 static DEFINE_SPINLOCK(noti_list_lock);
62
+#ifndef NULL_CHECK
4863 #define NULL_CHECK(p, s, err) \
4964 do { \
5065 if (!(p)) { \
....@@ -53,11 +68,15 @@
5368 return err; \
5469 } \
5570 } while (0)
71
+#endif // endif
5672
57
-#define RTT_IS_ENABLED(rtt_status) (rtt_status->status == RTT_ENABLED)
58
-#define RTT_IS_STOPPED(rtt_status) (rtt_status->status == RTT_STOPPED)
5973 #define TIMESPEC_TO_US(ts) (((uint64)(ts).tv_sec * USEC_PER_SEC) + \
6074 (ts).tv_nsec / NSEC_PER_USEC)
75
+
76
+#undef DHD_RTT_MEM
77
+#undef DHD_RTT_ERR
78
+#define DHD_RTT_MEM DHD_LOG_MEM
79
+#define DHD_RTT_ERR DHD_ERROR
6180
6281 #define FTM_IOC_BUFSZ 2048 /* ioc buffsize for our module (> BCM_XTLV_HDR_SIZE) */
6382 #define FTM_AVAIL_MAX_SLOTS 32
....@@ -66,9 +85,11 @@
6685 #define FTM_DEFAULT_SESSION 1
6786 #define FTM_BURST_TIMEOUT_UNIT 250 /* 250 ns */
6887 #define FTM_INVALID -1
69
-#define FTM_DEFAULT_CNT_20M 12
70
-#define FTM_DEFAULT_CNT_40M 10
71
-#define FTM_DEFAULT_CNT_80M 5
88
+#define FTM_DEFAULT_CNT_20M 24u
89
+#define FTM_DEFAULT_CNT_40M 16u
90
+#define FTM_DEFAULT_CNT_80M 11u
91
+/* To handle congestion env, set max dur/timeout */
92
+#define FTM_MAX_BURST_DUR_TMO_MS 128u
7293
7394 /* convenience macros */
7495 #define FTM_TU2MICRO(_tu) ((uint64)(_tu) << 10)
....@@ -84,6 +105,14 @@
84105
85106 /* broadcom specific set to have more accurate data */
86107 #define ENABLE_VHT_ACK
108
+#define CH_MIN_5G_CHANNEL 34
109
+
110
+/* CUR ETH became obsolete with this major version onwards */
111
+#define RTT_IOV_CUR_ETH_OBSOLETE 12
112
+
113
+/* PROXD TIMEOUT */
114
+#define DHD_RTT_TIMER_INTERVAL_MS 5000u
115
+#define DHD_NAN_RTT_TIMER_INTERVAL_MS 10000u
87116
88117 struct rtt_noti_callback {
89118 struct list_head list;
....@@ -91,30 +120,10 @@
91120 dhd_rtt_compl_noti_fn noti_fn;
92121 };
93122
94
-typedef struct rtt_status_info {
95
- dhd_pub_t *dhd;
96
- int8 status; /* current status for the current entry */
97
- int8 txchain; /* current device tx chain */
98
- int8 mpc; /* indicate we change mpc mode */
99
- int8 cur_idx; /* current entry to do RTT */
100
- bool all_cancel; /* cancel all request once we got the cancel requet */
101
- struct capability {
102
- int32 proto :8;
103
- int32 feature :8;
104
- int32 preamble :8;
105
- int32 bw :8;
106
- } rtt_capa; /* rtt capability */
107
- struct mutex rtt_mutex;
108
- rtt_config_params_t rtt_config;
109
- struct work_struct work;
110
- struct list_head noti_fn_list;
111
- struct list_head rtt_results_cache; /* store results for RTT */
112
-} rtt_status_info_t;
113
-
114123 /* bitmask indicating which command groups; */
115124 typedef enum {
116125 FTM_SUBCMD_FLAG_METHOD = 0x01, /* FTM method command */
117
- FTM_SUBCMD_FLAG_SESSION = 0x02, /* FTM session command */
126
+ FTM_SUBCMD_FLAG_SESSION = 0x02, /* FTM session command */
118127 FTM_SUBCMD_FLAG_ALL = FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION
119128 } ftm_subcmd_flag_t;
120129
....@@ -125,7 +134,6 @@
125134 FTM_CONFIG_CAT_AVAIL = 3, /* 'config avail' */
126135 } ftm_config_category_t;
127136
128
-
129137 typedef struct ftm_subcmd_info {
130138 int16 version; /* FTM version (optional) */
131139 char *name; /* cmd-name string as cmdline input */
....@@ -134,9 +142,8 @@
134142 ftm_subcmd_flag_t cmdflag; /* CMD flag (optional) */
135143 } ftm_subcmd_info_t;
136144
137
-
138145 typedef struct ftm_config_options_info {
139
- uint32 flags; /* wl_proxd_flags_t/wl_proxd_session_flags_t */
146
+ uint32 flags; /* wl_proxd_flags_t/wl_proxd_session_flags_t */
140147 bool enable;
141148 } ftm_config_options_info_t;
142149
....@@ -149,157 +156,118 @@
149156 uint32 data32;
150157 uint16 data16;
151158 uint8 data8;
159
+ uint32 event_mask;
152160 };
153161 } ftm_config_param_info_t;
154162
155163 /*
156164 * definition for id-string mapping.
157
-* This is used to map an id (can be cmd-id, tlv-id, ....) to a text-string
158
-* for debug-display or cmd-log-display
165
+* This is used to map an id (can be cmd-id, tlv-id, ....) to a text-string
166
+* for debug-display or cmd-log-display
159167 */
160168 typedef struct ftm_strmap_entry {
161169 int32 id;
162170 char *text;
163171 } ftm_strmap_entry_t;
164172
165
-
166173 typedef struct ftm_status_map_host_entry {
167174 wl_proxd_status_t proxd_status;
168175 rtt_reason_t rtt_reason;
169176 } ftm_status_map_host_entry_t;
170177
178
+static uint16
179
+rtt_result_ver(uint16 tlvid, const uint8 *p_data);
180
+
171181 static int
172
-dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 tlvid, uint16 len);
182
+dhd_rtt_convert_results_to_host_v1(rtt_result_t *rtt_result, const uint8 *p_data,
183
+ uint16 tlvid, uint16 len);
184
+
185
+static int
186
+dhd_rtt_convert_results_to_host_v2(rtt_result_t *rtt_result, const uint8 *p_data,
187
+ uint16 tlvid, uint16 len);
173188
174189 static wifi_rate_t
175190 dhd_rtt_convert_rate_to_host(uint32 ratespec);
176191
192
+#if defined(WL_CFG80211) && defined(RTT_DEBUG)
193
+const char *
194
+ftm_cmdid_to_str(uint16 cmdid);
195
+#endif /* WL_CFG80211 && RTT_DEBUG */
196
+
197
+#ifdef WL_CFG80211
177198 static int
178199 dhd_rtt_start(dhd_pub_t *dhd);
200
+static int dhd_rtt_create_failure_result(rtt_status_info_t *rtt_status,
201
+ struct ether_addr *addr);
202
+static void dhd_rtt_handle_rtt_session_end(dhd_pub_t *dhd);
203
+static void dhd_rtt_timeout_work(struct work_struct *work);
204
+#endif /* WL_CFG80211 */
179205 static const int burst_duration_idx[] = {0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 0, 0};
180206
181207 /* ftm status mapping to host status */
182208 static const ftm_status_map_host_entry_t ftm_status_map_info[] = {
183
- {WL_PROXD_E_INCOMPLETE, RTT_REASON_FAILURE},
184
- {WL_PROXD_E_OVERRIDDEN, RTT_REASON_FAILURE},
185
- {WL_PROXD_E_ASAP_FAILED, RTT_REASON_FAILURE},
186
- {WL_PROXD_E_NOTSTARTED, RTT_REASON_FAIL_NOT_SCHEDULED_YET},
187
- {WL_PROXD_E_INVALIDAVB, RTT_REASON_FAIL_INVALID_TS},
188
- {WL_PROXD_E_INCAPABLE, RTT_REASON_FAIL_NO_CAPABILITY},
189
- {WL_PROXD_E_MISMATCH, RTT_REASON_FAILURE},
190
- {WL_PROXD_E_DUP_SESSION, RTT_REASON_FAILURE},
191
- {WL_PROXD_E_REMOTE_FAIL, RTT_REASON_FAILURE},
192
- {WL_PROXD_E_REMOTE_INCAPABLE, RTT_REASON_FAILURE},
193
- {WL_PROXD_E_SCHED_FAIL, RTT_REASON_FAIL_SCHEDULE},
194
- {WL_PROXD_E_PROTO, RTT_REASON_FAIL_PROTOCOL},
195
- {WL_PROXD_E_EXPIRED, RTT_REASON_FAILURE},
196
- {WL_PROXD_E_TIMEOUT, RTT_REASON_FAIL_TM_TIMEOUT},
197
- {WL_PROXD_E_NOACK, RTT_REASON_FAIL_NO_RSP},
198
- {WL_PROXD_E_DEFERRED, RTT_REASON_FAILURE},
199
- {WL_PROXD_E_INVALID_SID, RTT_REASON_FAILURE},
200
- {WL_PROXD_E_REMOTE_CANCEL, RTT_REASON_FAILURE},
201
- {WL_PROXD_E_CANCELED, RTT_REASON_ABORTED},
202
- {WL_PROXD_E_INVALID_SESSION, RTT_REASON_FAILURE},
203
- {WL_PROXD_E_BAD_STATE, RTT_REASON_FAILURE},
204
- {WL_PROXD_E_ERROR, RTT_REASON_FAILURE},
205
- {WL_PROXD_E_OK, RTT_REASON_SUCCESS}
206
-};
207
-
208
-/* ftm tlv-id mapping */
209
-static const ftm_strmap_entry_t ftm_tlvid_loginfo[] = {
210
- /* { WL_PROXD_TLV_ID_xxx, "text for WL_PROXD_TLV_ID_xxx" }, */
211
- { WL_PROXD_TLV_ID_NONE, "none" },
212
- { WL_PROXD_TLV_ID_METHOD, "method" },
213
- { WL_PROXD_TLV_ID_FLAGS, "flags" },
214
- { WL_PROXD_TLV_ID_CHANSPEC, "chanspec" },
215
- { WL_PROXD_TLV_ID_TX_POWER, "tx power" },
216
- { WL_PROXD_TLV_ID_RATESPEC, "ratespec" },
217
- { WL_PROXD_TLV_ID_BURST_DURATION, "burst duration" },
218
- { WL_PROXD_TLV_ID_BURST_PERIOD, "burst period" },
219
- { WL_PROXD_TLV_ID_BURST_FTM_SEP, "burst ftm sep" },
220
- { WL_PROXD_TLV_ID_BURST_NUM_FTM, "burst num ftm" },
221
- { WL_PROXD_TLV_ID_NUM_BURST, "num burst" },
222
- { WL_PROXD_TLV_ID_FTM_RETRIES, "ftm retries" },
223
- { WL_PROXD_TLV_ID_BSS_INDEX, "BSS index" },
224
- { WL_PROXD_TLV_ID_BSSID, "bssid" },
225
- { WL_PROXD_TLV_ID_INIT_DELAY, "burst init delay" },
226
- { WL_PROXD_TLV_ID_BURST_TIMEOUT, "burst timeout" },
227
- { WL_PROXD_TLV_ID_EVENT_MASK, "event mask" },
228
- { WL_PROXD_TLV_ID_FLAGS_MASK, "flags mask" },
229
- { WL_PROXD_TLV_ID_PEER_MAC, "peer addr" },
230
- { WL_PROXD_TLV_ID_FTM_REQ, "ftm req" },
231
- { WL_PROXD_TLV_ID_LCI_REQ, "lci req" },
232
- { WL_PROXD_TLV_ID_LCI, "lci" },
233
- { WL_PROXD_TLV_ID_CIVIC_REQ, "civic req" },
234
- { WL_PROXD_TLV_ID_CIVIC, "civic" },
235
- { WL_PROXD_TLV_ID_AVAIL, "availability" },
236
- { WL_PROXD_TLV_ID_SESSION_FLAGS, "session flags" },
237
- { WL_PROXD_TLV_ID_SESSION_FLAGS_MASK, "session flags mask" },
238
- { WL_PROXD_TLV_ID_RX_MAX_BURST, "rx max bursts" },
239
- { WL_PROXD_TLV_ID_RANGING_INFO, "ranging info" },
240
- { WL_PROXD_TLV_ID_RANGING_FLAGS, "ranging flags" },
241
- { WL_PROXD_TLV_ID_RANGING_FLAGS_MASK, "ranging flags mask" },
242
- /* output - 512 + x */
243
- { WL_PROXD_TLV_ID_STATUS, "status" },
244
- { WL_PROXD_TLV_ID_COUNTERS, "counters" },
245
- { WL_PROXD_TLV_ID_INFO, "info" },
246
- { WL_PROXD_TLV_ID_RTT_RESULT, "rtt result" },
247
- { WL_PROXD_TLV_ID_AOA_RESULT, "aoa result" },
248
- { WL_PROXD_TLV_ID_SESSION_INFO, "session info" },
249
- { WL_PROXD_TLV_ID_SESSION_STATUS, "session status" },
250
- { WL_PROXD_TLV_ID_SESSION_ID_LIST, "session ids" },
251
- /* debug tlvs can be added starting 1024 */
252
- { WL_PROXD_TLV_ID_DEBUG_MASK, "debug mask" },
253
- { WL_PROXD_TLV_ID_COLLECT, "collect" },
254
- { WL_PROXD_TLV_ID_STRBUF, "result" }
209
+ {WL_PROXD_E_INCOMPLETE, RTT_STATUS_FAILURE},
210
+ {WL_PROXD_E_OVERRIDDEN, RTT_STATUS_FAILURE},
211
+ {WL_PROXD_E_ASAP_FAILED, RTT_STATUS_FAILURE},
212
+ {WL_PROXD_E_NOTSTARTED, RTT_STATUS_FAIL_NOT_SCHEDULED_YET},
213
+ {WL_PROXD_E_INVALIDMEAS, RTT_STATUS_FAIL_INVALID_TS},
214
+ {WL_PROXD_E_INCAPABLE, RTT_STATUS_FAIL_NO_CAPABILITY},
215
+ {WL_PROXD_E_MISMATCH, RTT_STATUS_FAILURE},
216
+ {WL_PROXD_E_DUP_SESSION, RTT_STATUS_FAILURE},
217
+ {WL_PROXD_E_REMOTE_FAIL, RTT_STATUS_FAILURE},
218
+ {WL_PROXD_E_REMOTE_INCAPABLE, RTT_STATUS_FAILURE},
219
+ {WL_PROXD_E_SCHED_FAIL, RTT_STATUS_FAIL_SCHEDULE},
220
+ {WL_PROXD_E_PROTO, RTT_STATUS_FAIL_PROTOCOL},
221
+ {WL_PROXD_E_EXPIRED, RTT_STATUS_FAILURE},
222
+ {WL_PROXD_E_TIMEOUT, RTT_STATUS_FAIL_TM_TIMEOUT},
223
+ {WL_PROXD_E_NOACK, RTT_STATUS_FAIL_NO_RSP},
224
+ {WL_PROXD_E_DEFERRED, RTT_STATUS_FAILURE},
225
+ {WL_PROXD_E_INVALID_SID, RTT_STATUS_FAILURE},
226
+ {WL_PROXD_E_REMOTE_CANCEL, RTT_STATUS_FAILURE},
227
+ {WL_PROXD_E_CANCELED, RTT_STATUS_ABORTED},
228
+ {WL_PROXD_E_INVALID_SESSION, RTT_STATUS_FAILURE},
229
+ {WL_PROXD_E_BAD_STATE, RTT_STATUS_FAILURE},
230
+ {WL_PROXD_E_ERROR, RTT_STATUS_FAILURE},
231
+ {WL_PROXD_E_OK, RTT_STATUS_SUCCESS}
255232 };
256233
257234 static const ftm_strmap_entry_t ftm_event_type_loginfo[] = {
258
- /* wl_proxd_event_type_t, text-string */
259
- { WL_PROXD_EVENT_NONE, "none" },
235
+ /* wl_proxd_event_type_t, text-string */
236
+ { WL_PROXD_EVENT_NONE, "none" },
260237 { WL_PROXD_EVENT_SESSION_CREATE, "session create" },
261238 { WL_PROXD_EVENT_SESSION_START, "session start" },
262
- { WL_PROXD_EVENT_FTM_REQ, "FTM req" },
239
+ { WL_PROXD_EVENT_FTM_REQ, "FTM req" },
263240 { WL_PROXD_EVENT_BURST_START, "burst start" },
264
- { WL_PROXD_EVENT_BURST_END, "burst end" },
241
+ { WL_PROXD_EVENT_BURST_END, "burst end" },
265242 { WL_PROXD_EVENT_SESSION_END, "session end" },
266243 { WL_PROXD_EVENT_SESSION_RESTART, "session restart" },
267244 { WL_PROXD_EVENT_BURST_RESCHED, "burst rescheduled" },
268245 { WL_PROXD_EVENT_SESSION_DESTROY, "session destroy" },
269
- { WL_PROXD_EVENT_RANGE_REQ, "range request" },
270
- { WL_PROXD_EVENT_FTM_FRAME, "FTM frame" },
271
- { WL_PROXD_EVENT_DELAY, "delay" },
246
+ { WL_PROXD_EVENT_RANGE_REQ, "range request" },
247
+ { WL_PROXD_EVENT_FTM_FRAME, "FTM frame" },
248
+ { WL_PROXD_EVENT_DELAY, "delay" },
272249 { WL_PROXD_EVENT_VS_INITIATOR_RPT, "initiator-report " }, /* rx initiator-rpt */
273
- { WL_PROXD_EVENT_RANGING, "ranging " },
250
+ { WL_PROXD_EVENT_RANGING, "ranging " },
251
+ { WL_PROXD_EVENT_COLLECT, "collect" },
252
+ { WL_PROXD_EVENT_MF_STATS, "mf_stats" },
274253 };
275254
276255 /*
277256 * session-state --> text string mapping
278257 */
279258 static const ftm_strmap_entry_t ftm_session_state_value_loginfo[] = {
280
- /* wl_proxd_session_state_t, text string */
281
- { WL_PROXD_SESSION_STATE_CREATED, "created" },
259
+ /* wl_proxd_session_state_t, text string */
260
+ { WL_PROXD_SESSION_STATE_CREATED, "created" },
282261 { WL_PROXD_SESSION_STATE_CONFIGURED, "configured" },
283
- { WL_PROXD_SESSION_STATE_STARTED, "started" },
284
- { WL_PROXD_SESSION_STATE_DELAY, "delay" },
285
- { WL_PROXD_SESSION_STATE_USER_WAIT, "user-wait" },
262
+ { WL_PROXD_SESSION_STATE_STARTED, "started" },
263
+ { WL_PROXD_SESSION_STATE_DELAY, "delay" },
264
+ { WL_PROXD_SESSION_STATE_USER_WAIT, "user-wait" },
286265 { WL_PROXD_SESSION_STATE_SCHED_WAIT, "sched-wait" },
287
- { WL_PROXD_SESSION_STATE_BURST, "burst" },
288
- { WL_PROXD_SESSION_STATE_STOPPING, "stopping" },
289
- { WL_PROXD_SESSION_STATE_ENDED, "ended" },
266
+ { WL_PROXD_SESSION_STATE_BURST, "burst" },
267
+ { WL_PROXD_SESSION_STATE_STOPPING, "stopping" },
268
+ { WL_PROXD_SESSION_STATE_ENDED, "ended" },
290269 { WL_PROXD_SESSION_STATE_DESTROYING, "destroying" },
291
- { WL_PROXD_SESSION_STATE_NONE, "none" }
292
-};
293
-
294
-/*
295
-* ranging-state --> text string mapping
296
-*/
297
-static const ftm_strmap_entry_t ftm_ranging_state_value_loginfo [] = {
298
- /* wl_proxd_ranging_state_t, text string */
299
- { WL_PROXD_RANGING_STATE_NONE, "none" },
300
- { WL_PROXD_RANGING_STATE_NOTSTARTED, "nonstarted" },
301
- { WL_PROXD_RANGING_STATE_INPROGRESS, "inprogress" },
302
- { WL_PROXD_RANGING_STATE_DONE, "done" },
270
+ { WL_PROXD_SESSION_STATE_NONE, "none" }
303271 };
304272
305273 /*
....@@ -310,61 +278,39 @@
310278 { WL_PROXD_E_OVERRIDDEN, "overridden" },
311279 { WL_PROXD_E_ASAP_FAILED, "ASAP failed" },
312280 { WL_PROXD_E_NOTSTARTED, "not started" },
313
- { WL_PROXD_E_INVALIDAVB, "invalid AVB" },
314
- { WL_PROXD_E_INCAPABLE, "incapable" },
315
- { WL_PROXD_E_MISMATCH, "mismatch"},
281
+ { WL_PROXD_E_INVALIDMEAS, "invalid measurement" },
282
+ { WL_PROXD_E_INCAPABLE, "incapable" },
283
+ { WL_PROXD_E_MISMATCH, "mismatch"},
316284 { WL_PROXD_E_DUP_SESSION, "dup session" },
317285 { WL_PROXD_E_REMOTE_FAIL, "remote fail" },
318
- { WL_PROXD_E_REMOTE_INCAPABLE, "remote incapable" },
286
+ { WL_PROXD_E_REMOTE_INCAPABLE, "remote incapable" },
319287 { WL_PROXD_E_SCHED_FAIL, "sched failure" },
320288 { WL_PROXD_E_PROTO, "protocol error" },
321289 { WL_PROXD_E_EXPIRED, "expired" },
322290 { WL_PROXD_E_TIMEOUT, "timeout" },
323291 { WL_PROXD_E_NOACK, "no ack" },
324
- { WL_PROXD_E_DEFERRED, "deferred" },
292
+ { WL_PROXD_E_DEFERRED, "deferred" },
325293 { WL_PROXD_E_INVALID_SID, "invalid session id" },
326294 { WL_PROXD_E_REMOTE_CANCEL, "remote cancel" },
327
- { WL_PROXD_E_CANCELED, "canceled" },
328
- { WL_PROXD_E_INVALID_SESSION, "invalid session" },
329
- { WL_PROXD_E_BAD_STATE, "bad state" },
295
+ { WL_PROXD_E_CANCELED, "canceled" },
296
+ { WL_PROXD_E_INVALID_SESSION, "invalid session" },
297
+ { WL_PROXD_E_BAD_STATE, "bad state" },
330298 { WL_PROXD_E_ERROR, "error" },
331
- { WL_PROXD_E_OK, "OK" }
299
+ { WL_PROXD_E_OK, "OK" }
332300 };
333301
334302 /*
335303 * time interval unit --> text string mapping
336304 */
337305 static const ftm_strmap_entry_t ftm_tmu_value_loginfo[] = {
338
- /* wl_proxd_tmu_t, text-string */
339
- { WL_PROXD_TMU_TU, "TU" },
340
- { WL_PROXD_TMU_SEC, "sec" },
306
+ /* wl_proxd_tmu_t, text-string */
307
+ { WL_PROXD_TMU_TU, "TU" },
308
+ { WL_PROXD_TMU_SEC, "sec" },
341309 { WL_PROXD_TMU_MILLI_SEC, "ms" },
342310 { WL_PROXD_TMU_MICRO_SEC, "us" },
343311 { WL_PROXD_TMU_NANO_SEC, "ns" },
344312 { WL_PROXD_TMU_PICO_SEC, "ps" }
345313 };
346
-
347
-#define RSPEC_BW(rspec) ((rspec) & WL_RSPEC_BW_MASK)
348
-#define RSPEC_IS20MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_20MHZ)
349
-#define RSPEC_IS40MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_40MHZ)
350
-#define RSPEC_IS80MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_80MHZ)
351
-#define RSPEC_IS160MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_160MHZ)
352
-
353
-#define IS_MCS(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) != WL_RSPEC_ENCODE_RATE)
354
-#define IS_STBC(rspec) (((((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HT) || \
355
- (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_VHT)) && \
356
- (((rspec) & WL_RSPEC_STBC) == WL_RSPEC_STBC))
357
-#define RSPEC_ISSGI(rspec) (((rspec) & WL_RSPEC_SGI) != 0)
358
-#define RSPEC_ISLDPC(rspec) (((rspec) & WL_RSPEC_LDPC) != 0)
359
-#define RSPEC_ISSTBC(rspec) (((rspec) & WL_RSPEC_STBC) != 0)
360
-#define RSPEC_ISTXBF(rspec) (((rspec) & WL_RSPEC_TXBF) != 0)
361
-#define RSPEC_ISVHT(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_VHT)
362
-#define RSPEC_ISHT(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HT)
363
-#define RSPEC_ISLEGACY(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_RATE)
364
-#define RSPEC2RATE(rspec) (RSPEC_ISLEGACY(rspec) ? \
365
- ((rspec) & RSPEC_RATE_MASK) : rate_rspec2rate(rspec))
366
-/* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */
367
-#define RSPEC2KBPS(rspec) rate_rspec2rate(rspec)
368314
369315 struct ieee_80211_mcs_rate_info {
370316 uint8 constellation_bits;
....@@ -449,10 +395,10 @@
449395 } /* wlc_rate_mcs2rate */
450396
451397 /** take a well formed ratespec_t arg and return phy rate in [Kbps] units */
452
-int
398
+static uint32
453399 rate_rspec2rate(uint32 rspec)
454400 {
455
- int rate = -1;
401
+ int rate = 0;
456402
457403 if (RSPEC_ISLEGACY(rspec)) {
458404 rate = 500 * (rspec & WL_RSPEC_RATE_MASK);
....@@ -469,16 +415,17 @@
469415 } else if (RSPEC_ISVHT(rspec)) {
470416 uint mcs = (rspec & WL_RSPEC_VHT_MCS_MASK);
471417 uint nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
472
-
473
- ASSERT(mcs <= 9);
474
- ASSERT(nss <= 8);
418
+ if (mcs > 9 || nss > 8) {
419
+ DHD_RTT(("%s: Invalid mcs %d or nss %d\n", __FUNCTION__, mcs, nss));
420
+ goto exit;
421
+ }
475422
476423 rate = rate_mcs2rate(mcs, nss, RSPEC_BW(rspec), RSPEC_ISSGI(rspec));
477424 } else {
478
- ASSERT(0);
425
+ DHD_RTT(("%s: wrong rspec:%d\n", __FUNCTION__, rspec));
479426 }
480
-
481
- return (rate == 0) ? -1 : rate;
427
+exit:
428
+ return rate;
482429 }
483430
484431 char resp_buf[WLC_IOCTL_SMLEN];
....@@ -536,7 +483,7 @@
536483 }
537484 p_entry++; /* next entry */
538485 }
539
- return RTT_REASON_FAILURE; /* not found */
486
+ return RTT_STATUS_FAILURE; /* not found */
540487 }
541488 /*
542489 * lookup 'id' (as a key) from a table
....@@ -578,9 +525,7 @@
578525 return "invalid";
579526 }
580527
581
-
582
-#ifdef RTT_DEBUG
583
-
528
+#if defined(WL_CFG80211) && defined(RTT_DEBUG)
584529 /* define entry, e.g. { WL_PROXD_CMD_xxx, "WL_PROXD_CMD_xxx" } */
585530 #define DEF_STRMAP_ENTRY(id) { (id), #id }
586531
....@@ -613,13 +558,12 @@
613558 /*
614559 * map a ftm cmd-id to a text-string for display
615560 */
616
-static const char *
561
+const char *
617562 ftm_cmdid_to_str(uint16 cmdid)
618563 {
619564 return ftm_map_id_to_str((int32) cmdid, &ftm_cmdid_map[0], ARRAYSIZE(ftm_cmdid_map));
620565 }
621
-#endif /* RTT_DEBUG */
622
-
566
+#endif /* WL_CFG80211 && RTT_DEBUG */
623567
624568 /*
625569 * convert BCME_xxx error codes into related error strings
....@@ -674,7 +618,7 @@
674618 ARRAYSIZE(ftm_session_state_value_loginfo));
675619 }
676620
677
-
621
+#ifdef WL_CFG80211
678622 /*
679623 * send 'proxd' iovar for all ftm get-related commands
680624 */
....@@ -690,7 +634,7 @@
690634 status = dhd_getiovar(dhd, 0, "proxd", (char *)p_proxd_iov,
691635 proxd_iovsize, (char **)&p_iovresp, WLC_IOCTL_SMLEN);
692636 if (status != BCME_OK) {
693
- DHD_ERROR(("%s: failed to send getbuf proxd iovar (CMD ID : %d), status=%d\n",
637
+ DHD_RTT_ERR(("%s: failed to send getbuf proxd iovar (CMD ID : %d), status=%d\n",
694638 __FUNCTION__, p_subcmd_info->cmdid, status));
695639 return status;
696640 }
....@@ -702,7 +646,7 @@
702646
703647 tlvs_len = ltoh16(p_iovresp->len) - WL_PROXD_IOV_HDR_SIZE;
704648 if (tlvs_len < 0) {
705
- DHD_ERROR(("%s: alert, p_iovresp->len(%d) should not be smaller than %d\n",
649
+ DHD_RTT_ERR(("%s: alert, p_iovresp->len(%d) should not be smaller than %d\n",
706650 __FUNCTION__, ltoh16(p_iovresp->len), (int) WL_PROXD_IOV_HDR_SIZE));
707651 tlvs_len = 0;
708652 }
....@@ -716,13 +660,12 @@
716660 return status;
717661 }
718662
719
-
720663 static wl_proxd_iov_t *
721664 rtt_alloc_getset_buf(wl_proxd_method_t method, wl_proxd_session_id_t session_id,
722665 wl_proxd_cmd_t cmdid, uint16 tlvs_bufsize, uint16 *p_out_bufsize)
723666 {
724667 uint16 proxd_iovsize;
725
- uint16 kflags;
668
+ uint32 kflags;
726669 wl_proxd_tlv_t *p_tlv;
727670 wl_proxd_iov_t *p_proxd_iov = (wl_proxd_iov_t *) NULL;
728671
....@@ -733,7 +676,7 @@
733676
734677 p_proxd_iov = kzalloc(proxd_iovsize, kflags);
735678 if (p_proxd_iov == NULL) {
736
- DHD_ERROR(("error: failed to allocate %d bytes of memory\n", proxd_iovsize));
679
+ DHD_RTT_ERR(("error: failed to allocate %d bytes of memory\n", proxd_iovsize));
737680 return NULL;
738681 }
739682
....@@ -754,7 +697,6 @@
754697 return p_proxd_iov;
755698 }
756699
757
-
758700 static int
759701 dhd_rtt_common_get_handler(dhd_pub_t *dhd, ftm_subcmd_info_t *p_subcmd_info,
760702 wl_proxd_method_t method,
....@@ -767,7 +709,7 @@
767709 DHD_RTT(("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n",
768710 __FUNCTION__, method, session_id, p_subcmd_info->cmdid,
769711 ftm_cmdid_to_str(p_subcmd_info->cmdid)));
770
-#endif
712
+#endif // endif
771713 /* alloc mem for ioctl headr + reserved 0 bufsize for tlvs (initialize to zero) */
772714 p_proxd_iov = rtt_alloc_getset_buf(method, session_id, p_subcmd_info->cmdid,
773715 0, &proxd_iovsize);
....@@ -809,10 +751,11 @@
809751 int ret;
810752
811753 #ifdef RTT_DEBUG
812
- DHD_ERROR(("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n",
754
+ DHD_RTT(("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n",
813755 __FUNCTION__, method, session_id, p_subcmd_info->cmdid,
814756 ftm_cmdid_to_str(p_subcmd_info->cmdid)));
815
-#endif
757
+#endif // endif
758
+
816759 /* allocate and initialize a temp buffer for 'set proxd' iovar */
817760 proxd_iovsize = 0;
818761 p_proxd_iov = rtt_alloc_getset_buf(method, session_id, p_subcmd_info->cmdid,
....@@ -824,38 +767,269 @@
824767 ret = dhd_iovar(dhd, 0, "proxd", (char *)p_proxd_iov, proxd_iovsize, NULL, 0, TRUE);
825768 #ifdef RTT_DEBUG
826769 if (ret != BCME_OK) {
827
- DHD_ERROR(("error: Proxd IOVAR failed, status=%d\n", ret));
770
+ DHD_RTT(("error: IOVAR failed, status=%d\n", ret));
828771 }
829
-#endif
772
+#endif // endif
830773 /* clean up */
831774 kfree(p_proxd_iov);
775
+
776
+ return ret;
777
+}
778
+#endif /* WL_CFG80211 */
779
+
780
+/* gets the length and returns the version
781
+ * of the wl_proxd_collect_event_t version
782
+ */
783
+static uint
784
+rtt_collect_data_event_ver(uint16 len)
785
+{
786
+ if (len > sizeof(wl_proxd_collect_event_data_v3_t)) {
787
+ return WL_PROXD_COLLECT_EVENT_DATA_VERSION_MAX;
788
+ } else if (len == sizeof(wl_proxd_collect_event_data_v3_t)) {
789
+ return WL_PROXD_COLLECT_EVENT_DATA_VERSION_3;
790
+ } else if (len == sizeof(wl_proxd_collect_event_data_v2_t)) {
791
+ return WL_PROXD_COLLECT_EVENT_DATA_VERSION_2;
792
+ } else {
793
+ return WL_PROXD_COLLECT_EVENT_DATA_VERSION_1;
794
+ }
795
+}
796
+
797
+static void
798
+rtt_collect_event_data_display(uint8 ver, void *ctx, const uint8 *p_data, uint16 len)
799
+{
800
+ int i;
801
+ wl_proxd_collect_event_data_v1_t *p_collect_data_v1 = NULL;
802
+ wl_proxd_collect_event_data_v2_t *p_collect_data_v2 = NULL;
803
+ wl_proxd_collect_event_data_v3_t *p_collect_data_v3 = NULL;
804
+
805
+ if (!ctx || !p_data) {
806
+ return;
807
+ }
808
+
809
+ switch (ver) {
810
+ case WL_PROXD_COLLECT_EVENT_DATA_VERSION_1:
811
+ DHD_RTT(("\tVERSION_1\n"));
812
+ memcpy(ctx, p_data, sizeof(wl_proxd_collect_event_data_v1_t));
813
+ p_collect_data_v1 = (wl_proxd_collect_event_data_v1_t *)ctx;
814
+ DHD_RTT(("\tH_RX\n"));
815
+ for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
816
+ p_collect_data_v1->H_RX[i] = ltoh32_ua(&p_collect_data_v1->H_RX[i]);
817
+ DHD_RTT(("\t%u\n", p_collect_data_v1->H_RX[i]));
818
+ }
819
+ DHD_RTT(("\n"));
820
+ DHD_RTT(("\tH_LB\n"));
821
+ for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
822
+ p_collect_data_v1->H_LB[i] = ltoh32_ua(&p_collect_data_v1->H_LB[i]);
823
+ DHD_RTT(("\t%u\n", p_collect_data_v1->H_LB[i]));
824
+ }
825
+ DHD_RTT(("\n"));
826
+ DHD_RTT(("\tri_rr\n"));
827
+ for (i = 0; i < FTM_TPK_RI_RR_LEN; i++) {
828
+ DHD_RTT(("\t%u\n", p_collect_data_v1->ri_rr[i]));
829
+ }
830
+ p_collect_data_v1->phy_err_mask = ltoh32_ua(&p_collect_data_v1->phy_err_mask);
831
+ DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v1->phy_err_mask));
832
+ break;
833
+ case WL_PROXD_COLLECT_EVENT_DATA_VERSION_2:
834
+ memcpy(ctx, p_data, sizeof(wl_proxd_collect_event_data_v2_t));
835
+ p_collect_data_v2 = (wl_proxd_collect_event_data_v2_t *)ctx;
836
+ DHD_RTT(("\tH_RX\n"));
837
+ for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
838
+ p_collect_data_v2->H_RX[i] = ltoh32_ua(&p_collect_data_v2->H_RX[i]);
839
+ DHD_RTT(("\t%u\n", p_collect_data_v2->H_RX[i]));
840
+ }
841
+ DHD_RTT(("\n"));
842
+ DHD_RTT(("\tH_LB\n"));
843
+ for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
844
+ p_collect_data_v2->H_LB[i] = ltoh32_ua(&p_collect_data_v2->H_LB[i]);
845
+ DHD_RTT(("\t%u\n", p_collect_data_v2->H_LB[i]));
846
+ }
847
+ DHD_RTT(("\n"));
848
+ DHD_RTT(("\tri_rr\n"));
849
+ for (i = 0; i < FTM_TPK_RI_RR_LEN_SECURE_2_0; i++) {
850
+ DHD_RTT(("\t%u\n", p_collect_data_v2->ri_rr[i]));
851
+ }
852
+ p_collect_data_v2->phy_err_mask = ltoh32_ua(&p_collect_data_v2->phy_err_mask);
853
+ DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v2->phy_err_mask));
854
+ break;
855
+ case WL_PROXD_COLLECT_EVENT_DATA_VERSION_3:
856
+ memcpy(ctx, p_data, sizeof(wl_proxd_collect_event_data_v3_t));
857
+ p_collect_data_v3 = (wl_proxd_collect_event_data_v3_t *)ctx;
858
+ switch (p_collect_data_v3->version) {
859
+ case WL_PROXD_COLLECT_EVENT_DATA_VERSION_3:
860
+ if (p_collect_data_v3->length !=
861
+ (len - OFFSETOF(wl_proxd_collect_event_data_v3_t, H_LB))) {
862
+ DHD_RTT(("\tversion/length mismatch\n"));
863
+ break;
864
+ }
865
+ DHD_RTT(("\tH_RX\n"));
866
+ for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
867
+ p_collect_data_v3->H_RX[i] =
868
+ ltoh32_ua(&p_collect_data_v3->H_RX[i]);
869
+ DHD_RTT(("\t%u\n", p_collect_data_v3->H_RX[i]));
870
+ }
871
+ DHD_RTT(("\n"));
872
+ DHD_RTT(("\tH_LB\n"));
873
+ for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) {
874
+ p_collect_data_v3->H_LB[i] =
875
+ ltoh32_ua(&p_collect_data_v3->H_LB[i]);
876
+ DHD_RTT(("\t%u\n", p_collect_data_v3->H_LB[i]));
877
+ }
878
+ DHD_RTT(("\n"));
879
+ DHD_RTT(("\tri_rr\n"));
880
+ for (i = 0; i < FTM_TPK_RI_RR_LEN_SECURE_2_0; i++) {
881
+ DHD_RTT(("\t%u\n", p_collect_data_v3->ri_rr[i]));
882
+ }
883
+ p_collect_data_v3->phy_err_mask =
884
+ ltoh32_ua(&p_collect_data_v3->phy_err_mask);
885
+ DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v3->phy_err_mask));
886
+ break;
887
+ /* future case */
888
+ }
889
+ break;
890
+ }
891
+}
892
+
893
+static uint16
894
+rtt_result_ver(uint16 tlvid, const uint8 *p_data)
895
+{
896
+ uint16 ret = BCME_OK;
897
+ const wl_proxd_rtt_result_v2_t *r_v2 = NULL;
898
+
899
+ switch (tlvid) {
900
+ case WL_PROXD_TLV_ID_RTT_RESULT:
901
+ BCM_REFERENCE(p_data);
902
+ ret = WL_PROXD_RTT_RESULT_VERSION_1;
903
+ break;
904
+ case WL_PROXD_TLV_ID_RTT_RESULT_V2:
905
+ if (p_data) {
906
+ r_v2 = (const wl_proxd_rtt_result_v2_t *)p_data;
907
+ if (r_v2->version == WL_PROXD_RTT_RESULT_VERSION_2) {
908
+ ret = WL_PROXD_RTT_RESULT_VERSION_2;
909
+ }
910
+ }
911
+ break;
912
+ default:
913
+ DHD_RTT_ERR(("%s: > Unsupported TLV ID %d\n",
914
+ __FUNCTION__, tlvid));
915
+ break;
916
+ }
832917 return ret;
833918 }
834919
920
+/* pretty hex print a contiguous buffer */
921
+static void
922
+rtt_prhex(const char *msg, const uint8 *buf, uint nbytes)
923
+{
924
+ char line[128], *p;
925
+ int len = sizeof(line);
926
+ int nchar;
927
+ uint i;
928
+
929
+ if (msg && (msg[0] != '\0'))
930
+ DHD_RTT(("%s:\n", msg));
931
+
932
+ p = line;
933
+ for (i = 0; i < nbytes; i++) {
934
+ if (i % 16 == 0) {
935
+ nchar = snprintf(p, len, " %04d: ", i); /* line prefix */
936
+ p += nchar;
937
+ len -= nchar;
938
+ }
939
+ if (len > 0) {
940
+ nchar = snprintf(p, len, "%02x ", buf[i]);
941
+ p += nchar;
942
+ len -= nchar;
943
+ }
944
+
945
+ if (i % 16 == 15) {
946
+ DHD_RTT(("%s\n", line)); /* flush line */
947
+ p = line;
948
+ len = sizeof(line);
949
+ }
950
+ }
951
+
952
+ /* flush last partial line */
953
+ if (p != line)
954
+ DHD_RTT(("%s\n", line));
955
+}
956
+
835957 static int
836
-rtt_unpack_xtlv_cbfn(void *ctx, uint8 *p_data, uint16 tlvid, uint16 len)
958
+rtt_unpack_xtlv_cbfn(void *ctx, const uint8 *p_data, uint16 tlvid, uint16 len)
837959 {
838960 int ret = BCME_OK;
839
- wl_proxd_ftm_session_status_t *p_data_info;
961
+ int i;
962
+ wl_proxd_ftm_session_status_t *p_data_info = NULL;
963
+ uint32 chan_data_entry = 0;
964
+ uint16 expected_rtt_result_ver = 0;
965
+
966
+ BCM_REFERENCE(p_data_info);
967
+
840968 switch (tlvid) {
841969 case WL_PROXD_TLV_ID_RTT_RESULT:
842
- ret = dhd_rtt_convert_results_to_host((rtt_report_t *)ctx,
843
- p_data, tlvid, len);
970
+ case WL_PROXD_TLV_ID_RTT_RESULT_V2:
971
+ DHD_RTT(("WL_PROXD_TLV_ID_RTT_RESULT\n"));
972
+ expected_rtt_result_ver = rtt_result_ver(tlvid, p_data);
973
+ switch (expected_rtt_result_ver) {
974
+ case WL_PROXD_RTT_RESULT_VERSION_1:
975
+ ret = dhd_rtt_convert_results_to_host_v1((rtt_result_t *)ctx,
976
+ p_data, tlvid, len);
977
+ break;
978
+ case WL_PROXD_RTT_RESULT_VERSION_2:
979
+ ret = dhd_rtt_convert_results_to_host_v2((rtt_result_t *)ctx,
980
+ p_data, tlvid, len);
981
+ break;
982
+ default:
983
+ DHD_RTT_ERR((" > Unsupported RTT_RESULT version\n"));
984
+ ret = BCME_UNSUPPORTED;
985
+ break;
986
+ }
844987 break;
845988 case WL_PROXD_TLV_ID_SESSION_STATUS:
989
+ DHD_RTT(("WL_PROXD_TLV_ID_SESSION_STATUS\n"));
846990 memcpy(ctx, p_data, sizeof(wl_proxd_ftm_session_status_t));
847991 p_data_info = (wl_proxd_ftm_session_status_t *)ctx;
992
+ p_data_info->sid = ltoh16_ua(&p_data_info->sid);
848993 p_data_info->state = ltoh16_ua(&p_data_info->state);
849994 p_data_info->status = ltoh32_ua(&p_data_info->status);
995
+ p_data_info->burst_num = ltoh16_ua(&p_data_info->burst_num);
996
+ DHD_RTT(("\tsid=%u, state=%d, status=%d, burst_num=%u\n",
997
+ p_data_info->sid, p_data_info->state,
998
+ p_data_info->status, p_data_info->burst_num));
999
+
1000
+ break;
1001
+ case WL_PROXD_TLV_ID_COLLECT_DATA:
1002
+ DHD_RTT(("WL_PROXD_TLV_ID_COLLECT_DATA\n"));
1003
+ rtt_collect_event_data_display(
1004
+ rtt_collect_data_event_ver(len),
1005
+ ctx, p_data, len);
1006
+ break;
1007
+ case WL_PROXD_TLV_ID_COLLECT_CHAN_DATA:
1008
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
1009
+ DHD_RTT(("WL_PROXD_TLV_ID_COLLECT_CHAN_DATA\n"));
1010
+ DHD_RTT(("\tchan est %u\n", (uint32) (len / sizeof(uint32))));
1011
+ for (i = 0; i < (len/sizeof(chan_data_entry)); i++) {
1012
+ uint32 *p = (uint32*)p_data;
1013
+ chan_data_entry = ltoh32_ua(p + i);
1014
+ DHD_RTT(("\t%u\n", chan_data_entry));
1015
+ }
1016
+ GCC_DIAGNOSTIC_POP();
1017
+ break;
1018
+ case WL_PROXD_TLV_ID_MF_STATS_DATA:
1019
+ DHD_RTT(("WL_PROXD_TLV_ID_MF_STATS_DATA\n"));
1020
+ DHD_RTT(("\tmf stats len=%u\n", len));
1021
+ rtt_prhex("", p_data, len);
8501022 break;
8511023 default:
852
- DHD_ERROR(("> Unsupported TLV ID %d\n", tlvid));
1024
+ DHD_RTT_ERR(("> Unsupported TLV ID %d\n", tlvid));
8531025 ret = BCME_ERROR;
8541026 break;
8551027 }
8561028
8571029 return ret;
8581030 }
1031
+
1032
+#ifdef WL_CFG80211
8591033 static int
8601034 rtt_handle_config_options(wl_proxd_session_id_t session_id, wl_proxd_tlv_t **p_tlv,
8611035 uint16 *p_buf_space_left, ftm_config_options_info_t *ftm_configs, int ftm_cfg_cnt)
....@@ -885,9 +1059,9 @@
8851059 flags_mask = htol32(flags_mask);
8861060 /* setup flags_mask TLV */
8871061 ret = bcm_pack_xtlv_entry((uint8 **)p_tlv, p_buf_space_left,
888
- type, sizeof(uint32), &flags_mask, BCM_XTLV_OPTION_ALIGN32);
1062
+ type, sizeof(uint32), (uint8 *)&flags_mask, BCM_XTLV_OPTION_ALIGN32);
8891063 if (ret != BCME_OK) {
890
- DHD_ERROR(("%s : bcm_pack_xltv_entry() for mask flags failed, status=%d\n",
1064
+ DHD_RTT_ERR(("%s : bcm_pack_xltv_entry() for mask flags failed, status=%d\n",
8911065 __FUNCTION__, ret));
8921066 goto exit;
8931067 }
....@@ -896,12 +1070,12 @@
8961070 WL_PROXD_TLV_ID_FLAGS : WL_PROXD_TLV_ID_SESSION_FLAGS;
8971071 /* setup flags TLV */
8981072 ret = bcm_pack_xtlv_entry((uint8 **)p_tlv, p_buf_space_left,
899
- type, sizeof(uint32), &flags, BCM_XTLV_OPTION_ALIGN32);
1073
+ type, sizeof(uint32), (uint8 *)&flags, BCM_XTLV_OPTION_ALIGN32);
9001074 if (ret != BCME_OK) {
901
-//#ifdef RTT_DEBUG
1075
+#ifdef RTT_DEBUG
9021076 DHD_RTT(("%s: bcm_pack_xltv_entry() for flags failed, status=%d\n",
9031077 __FUNCTION__, ret));
904
-//#endif
1078
+#endif // endif
9051079 }
9061080 exit:
9071081 return ret;
....@@ -947,6 +1121,7 @@
9471121 break;
9481122 case WL_PROXD_TLV_ID_BSSID: /* mac address */
9491123 case WL_PROXD_TLV_ID_PEER_MAC:
1124
+ case WL_PROXD_TLV_ID_CUR_ETHER_ADDR:
9501125 p_src_data = &p_config_param_info->mac_addr;
9511126 src_data_size = sizeof(struct ether_addr);
9521127 break;
....@@ -963,36 +1138,22 @@
9631138 break;
9641139 }
9651140 if (ret != BCME_OK) {
966
- DHD_ERROR(("%s bad TLV ID : %d\n",
1141
+ DHD_RTT_ERR(("%s bad TLV ID : %d\n",
9671142 __FUNCTION__, p_config_param_info->tlvid));
9681143 break;
9691144 }
9701145
9711146 ret = bcm_pack_xtlv_entry((uint8 **) p_tlv, p_buf_space_left,
972
- p_config_param_info->tlvid, src_data_size, p_src_data,
1147
+ p_config_param_info->tlvid, src_data_size, (uint8 *)p_src_data,
9731148 BCM_XTLV_OPTION_ALIGN32);
9741149 if (ret != BCME_OK) {
975
- DHD_ERROR(("%s: bcm_pack_xltv_entry() failed,"
1150
+ DHD_RTT_ERR(("%s: bcm_pack_xltv_entry() failed,"
9761151 " status=%d\n", __FUNCTION__, ret));
9771152 break;
9781153 }
9791154
9801155 }
9811156 }
982
- return ret;
983
-}
984
-
985
-static int
986
-dhd_rtt_get_version(dhd_pub_t *dhd, int *out_version)
987
-{
988
- int ret;
989
- ftm_subcmd_info_t subcmd_info;
990
- subcmd_info.name = "ver";
991
- subcmd_info.cmdid = WL_PROXD_CMD_GET_VERSION;
992
- subcmd_info.handler = NULL;
993
- ret = dhd_rtt_common_get_handler(dhd, &subcmd_info,
994
- WL_PROXD_METHOD_FTM, WL_PROXD_SESSION_ID_GLOBAL);
995
- *out_version = (ret == BCME_OK) ? subcmd_info.version : 0;
9961157 return ret;
9971158 }
9981159
....@@ -1028,6 +1189,119 @@
10281189 return dhd_rtt_common_set_handler(dhd, &subcmd_info,
10291190 WL_PROXD_METHOD_FTM, session_id);
10301191 }
1192
+#ifdef WL_NAN
1193
+int
1194
+dhd_rtt_delete_nan_session(dhd_pub_t *dhd)
1195
+{
1196
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
1197
+ struct wireless_dev *wdev = ndev_to_wdev(dev);
1198
+ struct wiphy *wiphy = wdev->wiphy;
1199
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1200
+ wl_cfgnan_terminate_directed_rtt_sessions(dev, cfg);
1201
+ return BCME_OK;
1202
+}
1203
+#endif /* WL_NAN */
1204
+/* API to find out if the given Peer Mac from FTM events
1205
+* is nan-peer. Based on this we will handle the SESSION_END
1206
+* event. For nan-peer FTM_SESSION_END event is ignored and handled in
1207
+* nan-ranging-cancel or nan-ranging-end event.
1208
+*/
1209
+static bool
1210
+dhd_rtt_is_nan_peer(dhd_pub_t *dhd, struct ether_addr *peer_mac)
1211
+{
1212
+#ifdef WL_NAN
1213
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
1214
+ struct wireless_dev *wdev = ndev_to_wdev(dev);
1215
+ struct wiphy *wiphy = wdev->wiphy;
1216
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1217
+ nan_ranging_inst_t *ranging_inst = NULL;
1218
+ bool ret = FALSE;
1219
+
1220
+ if (cfg->nan_enable == FALSE || ETHER_ISNULLADDR(peer_mac)) {
1221
+ goto exit;
1222
+ }
1223
+
1224
+ ranging_inst = wl_cfgnan_check_for_ranging(cfg, peer_mac);
1225
+ if (ranging_inst) {
1226
+ DHD_RTT((" RTT peer is of type NAN\n"));
1227
+ ret = TRUE;
1228
+ goto exit;
1229
+ }
1230
+exit:
1231
+ return ret;
1232
+#else
1233
+ return FALSE;
1234
+#endif /* WL_NAN */
1235
+}
1236
+
1237
+#ifdef WL_NAN
1238
+static int
1239
+dhd_rtt_nan_start_session(dhd_pub_t *dhd, rtt_target_info_t *rtt_target)
1240
+{
1241
+ s32 err = BCME_OK;
1242
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
1243
+ struct wireless_dev *wdev = ndev_to_wdev(dev);
1244
+ struct wiphy *wiphy = wdev->wiphy;
1245
+ struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1246
+ wl_nan_ev_rng_rpt_ind_t range_res;
1247
+ nan_ranging_inst_t *ranging_inst = NULL;
1248
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1249
+
1250
+ NAN_MUTEX_LOCK();
1251
+
1252
+ bzero(&range_res, sizeof(range_res));
1253
+
1254
+ if (!rtt_status) {
1255
+ err = BCME_NOTENABLED;
1256
+ goto done;
1257
+ }
1258
+
1259
+ if (!cfg->nan_enable) { /* If nan is not enabled report error */
1260
+ err = BCME_NOTENABLED;
1261
+ goto done;
1262
+ }
1263
+
1264
+ /* check if new ranging session allowed */
1265
+ if (!wl_cfgnan_ranging_allowed(cfg)) {
1266
+ /* responder should be in progress because initiator requests are
1267
+ * queued in DHD. Since initiator has more proef cancel responder
1268
+ * sessions
1269
+ */
1270
+ wl_cfgnan_cancel_rng_responders(dev, cfg);
1271
+ }
1272
+
1273
+ ranging_inst = wl_cfgnan_get_ranging_inst(cfg,
1274
+ &rtt_target->addr, NAN_RANGING_ROLE_INITIATOR);
1275
+ if (!ranging_inst) {
1276
+ err = BCME_NORESOURCE;
1277
+ goto done;
1278
+ }
1279
+
1280
+ DHD_RTT(("Trigger nan based range request\n"));
1281
+ err = wl_cfgnan_trigger_ranging(bcmcfg_to_prmry_ndev(cfg),
1282
+ cfg, ranging_inst, NULL, NAN_RANGE_REQ_CMD, TRUE);
1283
+ if (unlikely(err)) {
1284
+ goto done;
1285
+ }
1286
+ ranging_inst->range_type = RTT_TYPE_NAN_DIRECTED;
1287
+ ranging_inst->range_role = NAN_RANGING_ROLE_INITIATOR;
1288
+ /* schedule proxd timeout */
1289
+ schedule_delayed_work(&rtt_status->proxd_timeout,
1290
+ msecs_to_jiffies(DHD_NAN_RTT_TIMER_INTERVAL_MS));
1291
+done:
1292
+ if (err) { /* notify failure RTT event to host */
1293
+ DHD_RTT_ERR(("Failed to issue Nan Ranging Request err %d\n", err));
1294
+ dhd_rtt_handle_nan_rtt_session_end(dhd, &rtt_target->addr);
1295
+ /* try to reset geofence */
1296
+ if (ranging_inst) {
1297
+ wl_cfgnan_reset_geofence_ranging(cfg, ranging_inst,
1298
+ RTT_SCHED_DIR_TRIGGER_FAIL);
1299
+ }
1300
+ }
1301
+ NAN_MUTEX_UNLOCK();
1302
+ return err;
1303
+}
1304
+#endif /* WL_NAN */
10311305
10321306 static int
10331307 dhd_rtt_ftm_config(dhd_pub_t *dhd, wl_proxd_session_id_t session_id,
....@@ -1042,6 +1316,7 @@
10421316 uint16 buf_space_left;
10431317 uint16 all_tlvsize;
10441318 int ret = BCME_OK;
1319
+
10451320 subcmd_info.name = "config";
10461321 subcmd_info.cmdid = WL_PROXD_CMD_CONFIG;
10471322
....@@ -1049,7 +1324,7 @@
10491324 FTM_IOC_BUFSZ, &proxd_iovsize);
10501325
10511326 if (p_proxd_iov == NULL) {
1052
- DHD_ERROR(("%s : failed to allocate the iovar (size :%d)\n",
1327
+ DHD_RTT_ERR(("%s : failed to allocate the iovar (size :%d)\n",
10531328 __FUNCTION__, FTM_IOC_BUFSZ));
10541329 return BCME_NOMEM;
10551330 }
....@@ -1072,13 +1347,29 @@
10721347 ret = dhd_iovar(dhd, 0, "proxd", (char *)p_proxd_iov,
10731348 all_tlvsize + WL_PROXD_IOV_HDR_SIZE, NULL, 0, TRUE);
10741349 if (ret != BCME_OK) {
1075
- DHD_ERROR(("%s : failed to set config \n", __FUNCTION__));
1350
+ DHD_RTT_ERR(("%s : failed to set config\n", __FUNCTION__));
10761351 }
10771352 }
10781353 /* clean up */
10791354 kfree(p_proxd_iov);
10801355 return ret;
10811356 }
1357
+
1358
+static int
1359
+dhd_rtt_get_version(dhd_pub_t *dhd, int *out_version)
1360
+{
1361
+ int ret;
1362
+ ftm_subcmd_info_t subcmd_info;
1363
+ subcmd_info.name = "ver";
1364
+ subcmd_info.cmdid = WL_PROXD_CMD_GET_VERSION;
1365
+ subcmd_info.handler = NULL;
1366
+ ret = dhd_rtt_common_get_handler(dhd, &subcmd_info,
1367
+ WL_PROXD_METHOD_FTM, WL_PROXD_SESSION_ID_GLOBAL);
1368
+ *out_version = (ret == BCME_OK) ? subcmd_info.version : 0;
1369
+ return ret;
1370
+}
1371
+#endif /* WL_CFG80211 */
1372
+
10821373 chanspec_t
10831374 dhd_rtt_convert_to_chspec(wifi_channel_info_t channel)
10841375 {
....@@ -1108,7 +1399,7 @@
11081399 chanspec = wf_chspec_80(center_chan, primary_chan);
11091400 break;
11101401 default:
1111
- DHD_ERROR(("doesn't support this bandwith : %d", channel.width));
1402
+ DHD_RTT_ERR(("doesn't support this bandwith : %d", channel.width));
11121403 bw = -1;
11131404 break;
11141405 }
....@@ -1129,27 +1420,50 @@
11291420 {
11301421 int err = BCME_OK;
11311422 int idx;
1132
- rtt_status_info_t *rtt_status;
1133
- NULL_CHECK(params, "params is NULL", err);
1423
+ rtt_status_info_t *rtt_status = NULL;
1424
+ struct net_device *dev = NULL;
11341425
1426
+ NULL_CHECK(params, "params is NULL", err);
11351427 NULL_CHECK(dhd, "dhd is NULL", err);
1428
+
1429
+ dev = dhd_linux_get_primary_netdev(dhd);
11361430 rtt_status = GET_RTTSTATE(dhd);
11371431 NULL_CHECK(rtt_status, "rtt_status is NULL", err);
1432
+ NULL_CHECK(dev, "dev is NULL", err);
1433
+
11381434 if (!HAS_11MC_CAP(rtt_status->rtt_capa.proto)) {
1139
- DHD_ERROR(("doesn't support RTT \n"));
1140
- return BCME_ERROR;
1435
+ DHD_RTT_ERR(("doesn't support RTT \n"));
1436
+ err = BCME_ERROR;
1437
+ goto exit;
11411438 }
1142
- if (rtt_status->status != RTT_STOPPED) {
1143
- DHD_ERROR(("rtt is already started\n"));
1144
- return BCME_BUSY;
1145
- }
1439
+
11461440 DHD_RTT(("%s enter\n", __FUNCTION__));
11471441
1442
+ if (params->rtt_target_cnt > 0) {
1443
+#ifdef WL_NAN
1444
+ /* cancel ongoing geofence RTT if there */
1445
+ if ((err = wl_cfgnan_suspend_geofence_rng_session(dev,
1446
+ NULL, RTT_GEO_SUSPN_HOST_DIR_RTT_TRIG, 0)) != BCME_OK) {
1447
+ goto exit;
1448
+ }
1449
+#endif /* WL_NAN */
1450
+ } else {
1451
+ err = BCME_BADARG;
1452
+ goto exit;
1453
+ }
1454
+
1455
+ mutex_lock(&rtt_status->rtt_mutex);
1456
+ if (rtt_status->status != RTT_STOPPED) {
1457
+ DHD_RTT_ERR(("rtt is already started\n"));
1458
+ err = BCME_BUSY;
1459
+ goto exit;
1460
+ }
11481461 memset(rtt_status->rtt_config.target_info, 0, TARGET_INFO_SIZE(RTT_MAX_TARGET_CNT));
11491462 rtt_status->rtt_config.rtt_target_cnt = params->rtt_target_cnt;
11501463 memcpy(rtt_status->rtt_config.target_info,
11511464 params->target_info, TARGET_INFO_SIZE(params->rtt_target_cnt));
11521465 rtt_status->status = RTT_STARTED;
1466
+ DHD_RTT_MEM(("dhd_rtt_set_cfg: RTT Started, target_cnt = %d\n", params->rtt_target_cnt));
11531467 /* start to measure RTT from first device */
11541468 /* find next target to trigger RTT */
11551469 for (idx = rtt_status->cur_idx; idx < rtt_status->rtt_config.rtt_target_cnt; idx++) {
....@@ -1164,15 +1478,511 @@
11641478 }
11651479 if (idx < rtt_status->rtt_config.rtt_target_cnt) {
11661480 DHD_RTT(("rtt_status->cur_idx : %d\n", rtt_status->cur_idx));
1481
+ rtt_status->rtt_sched_reason = RTT_SCHED_HOST_TRIGGER;
11671482 schedule_work(&rtt_status->work);
11681483 }
1484
+exit:
1485
+ mutex_unlock(&rtt_status->rtt_mutex);
11691486 return err;
1487
+}
1488
+
1489
+#define GEOFENCE_RTT_LOCK(rtt_status) mutex_lock(&(rtt_status)->geofence_mutex)
1490
+#define GEOFENCE_RTT_UNLOCK(rtt_status) mutex_unlock(&(rtt_status)->geofence_mutex)
1491
+
1492
+#ifdef WL_NAN
1493
+/* sets geofence role concurrency state TRUE/FALSE */
1494
+void
1495
+dhd_rtt_set_role_concurrency_state(dhd_pub_t *dhd, bool state)
1496
+{
1497
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1498
+ if (!rtt_status) {
1499
+ return;
1500
+ }
1501
+ GEOFENCE_RTT_LOCK(rtt_status);
1502
+ rtt_status->geofence_cfg.role_concurr_state = state;
1503
+ GEOFENCE_RTT_UNLOCK(rtt_status);
1504
+}
1505
+
1506
+/* returns TRUE if geofence role concurrency constraint exists */
1507
+bool
1508
+dhd_rtt_get_role_concurrency_state(dhd_pub_t *dhd)
1509
+{
1510
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1511
+ if (!rtt_status) {
1512
+ return FALSE;
1513
+ }
1514
+ return rtt_status->geofence_cfg.role_concurr_state;
1515
+}
1516
+
1517
+int8
1518
+dhd_rtt_get_geofence_target_cnt(dhd_pub_t *dhd)
1519
+{
1520
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1521
+ if (!rtt_status) {
1522
+ return 0;
1523
+ }
1524
+ return rtt_status->geofence_cfg.geofence_target_cnt;
1525
+}
1526
+
1527
+/* sets geofence rtt state TRUE/FALSE */
1528
+void
1529
+dhd_rtt_set_geofence_rtt_state(dhd_pub_t *dhd, bool state)
1530
+{
1531
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1532
+ if (!rtt_status) {
1533
+ return;
1534
+ }
1535
+ GEOFENCE_RTT_LOCK(rtt_status);
1536
+ rtt_status->geofence_cfg.rtt_in_progress = state;
1537
+ GEOFENCE_RTT_UNLOCK(rtt_status);
1538
+}
1539
+
1540
+/* returns TRUE if geofence rtt is in progress */
1541
+bool
1542
+dhd_rtt_get_geofence_rtt_state(dhd_pub_t *dhd)
1543
+{
1544
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1545
+
1546
+ if (!rtt_status) {
1547
+ return FALSE;
1548
+ }
1549
+
1550
+ return rtt_status->geofence_cfg.rtt_in_progress;
1551
+}
1552
+
1553
+/* returns geofence RTT target list Head */
1554
+rtt_geofence_target_info_t*
1555
+dhd_rtt_get_geofence_target_head(dhd_pub_t *dhd)
1556
+{
1557
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1558
+ rtt_geofence_target_info_t* head = NULL;
1559
+
1560
+ if (!rtt_status) {
1561
+ return NULL;
1562
+ }
1563
+
1564
+ if (rtt_status->geofence_cfg.geofence_target_cnt) {
1565
+ head = &rtt_status->geofence_cfg.geofence_target_info[0];
1566
+ }
1567
+
1568
+ return head;
1569
+}
1570
+
1571
+int8
1572
+dhd_rtt_get_geofence_cur_target_idx(dhd_pub_t *dhd)
1573
+{
1574
+ int8 target_cnt = 0, cur_idx = DHD_RTT_INVALID_TARGET_INDEX;
1575
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1576
+
1577
+ if (!rtt_status) {
1578
+ goto exit;
1579
+ }
1580
+
1581
+ target_cnt = rtt_status->geofence_cfg.geofence_target_cnt;
1582
+ if (target_cnt == 0) {
1583
+ goto exit;
1584
+ }
1585
+
1586
+ cur_idx = rtt_status->geofence_cfg.cur_target_idx;
1587
+ ASSERT(cur_idx <= target_cnt);
1588
+
1589
+exit:
1590
+ return cur_idx;
1591
+}
1592
+
1593
+void
1594
+dhd_rtt_move_geofence_cur_target_idx_to_next(dhd_pub_t *dhd)
1595
+{
1596
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1597
+
1598
+ if (!rtt_status) {
1599
+ return;
1600
+ }
1601
+
1602
+ if (rtt_status->geofence_cfg.geofence_target_cnt == 0) {
1603
+ /* Invalidate current idx if no targets */
1604
+ rtt_status->geofence_cfg.cur_target_idx =
1605
+ DHD_RTT_INVALID_TARGET_INDEX;
1606
+ /* Cancel pending retry timer if any */
1607
+ if (delayed_work_pending(&rtt_status->rtt_retry_timer)) {
1608
+ cancel_delayed_work(&rtt_status->rtt_retry_timer);
1609
+ }
1610
+ return;
1611
+ }
1612
+ rtt_status->geofence_cfg.cur_target_idx++;
1613
+
1614
+ if (rtt_status->geofence_cfg.cur_target_idx >=
1615
+ rtt_status->geofence_cfg.geofence_target_cnt) {
1616
+ /* Reset once all targets done */
1617
+ rtt_status->geofence_cfg.cur_target_idx = 0;
1618
+ }
1619
+}
1620
+
1621
+/* returns geofence current RTT target */
1622
+rtt_geofence_target_info_t*
1623
+dhd_rtt_get_geofence_current_target(dhd_pub_t *dhd)
1624
+{
1625
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1626
+ rtt_geofence_target_info_t* cur_target = NULL;
1627
+ int cur_idx = 0;
1628
+
1629
+ if (!rtt_status) {
1630
+ return NULL;
1631
+ }
1632
+
1633
+ cur_idx = dhd_rtt_get_geofence_cur_target_idx(dhd);
1634
+ if (cur_idx >= 0) {
1635
+ cur_target = &rtt_status->geofence_cfg.geofence_target_info[cur_idx];
1636
+ }
1637
+
1638
+ return cur_target;
1639
+}
1640
+
1641
+/* returns geofence target from list for the peer */
1642
+rtt_geofence_target_info_t*
1643
+dhd_rtt_get_geofence_target(dhd_pub_t *dhd, struct ether_addr* peer_addr, int8 *index)
1644
+{
1645
+ int8 i;
1646
+ rtt_status_info_t *rtt_status;
1647
+ int target_cnt;
1648
+ rtt_geofence_target_info_t *geofence_target_info, *tgt = NULL;
1649
+
1650
+ rtt_status = GET_RTTSTATE(dhd);
1651
+
1652
+ if (!rtt_status) {
1653
+ return NULL;
1654
+ }
1655
+
1656
+ target_cnt = rtt_status->geofence_cfg.geofence_target_cnt;
1657
+ geofence_target_info = rtt_status->geofence_cfg.geofence_target_info;
1658
+
1659
+ /* Loop through to find target */
1660
+ for (i = 0; i < target_cnt; i++) {
1661
+ if (geofence_target_info[i].valid == FALSE) {
1662
+ break;
1663
+ }
1664
+ if (!memcmp(peer_addr, &geofence_target_info[i].peer_addr,
1665
+ ETHER_ADDR_LEN)) {
1666
+ *index = i;
1667
+ tgt = &geofence_target_info[i];
1668
+ }
1669
+ }
1670
+ if (!tgt) {
1671
+ DHD_RTT(("dhd_rtt_get_geofence_target: Target not found in list,"
1672
+ " MAC ADDR: "MACDBG" \n", MAC2STRDBG(peer_addr)));
1673
+ }
1674
+ return tgt;
1675
+}
1676
+
1677
+/* add geofence target to the target list */
1678
+int
1679
+dhd_rtt_add_geofence_target(dhd_pub_t *dhd, rtt_geofence_target_info_t *target)
1680
+{
1681
+ int err = BCME_OK;
1682
+ rtt_status_info_t *rtt_status;
1683
+ rtt_geofence_target_info_t *geofence_target_info;
1684
+ int8 geofence_target_cnt, index;
1685
+
1686
+ NULL_CHECK(dhd, "dhd is NULL", err);
1687
+ rtt_status = GET_RTTSTATE(dhd);
1688
+ NULL_CHECK(rtt_status, "rtt_status is NULL", err);
1689
+
1690
+ GEOFENCE_RTT_LOCK(rtt_status);
1691
+
1692
+ /* Get the geofence_target via peer addr, index param is dumm here */
1693
+ geofence_target_info = dhd_rtt_get_geofence_target(dhd, &target->peer_addr, &index);
1694
+ if (geofence_target_info) {
1695
+ DHD_RTT(("Duplicate geofencing RTT add request dropped\n"));
1696
+ err = BCME_OK;
1697
+ goto exit;
1698
+ }
1699
+
1700
+ geofence_target_cnt = rtt_status->geofence_cfg.geofence_target_cnt;
1701
+ if (geofence_target_cnt >= RTT_MAX_GEOFENCE_TARGET_CNT) {
1702
+ DHD_RTT(("Queue full, Geofencing RTT add request dropped\n"));
1703
+ err = BCME_NORESOURCE;
1704
+ goto exit;
1705
+ }
1706
+
1707
+ /* Add Geofence RTT request and increment target count */
1708
+ geofence_target_info = rtt_status->geofence_cfg.geofence_target_info;
1709
+ /* src and dest buffer len same, pointers of same DS statically allocated */
1710
+ (void)memcpy_s(&geofence_target_info[geofence_target_cnt],
1711
+ sizeof(geofence_target_info[geofence_target_cnt]), target,
1712
+ sizeof(*target));
1713
+ geofence_target_info[geofence_target_cnt].valid = TRUE;
1714
+ rtt_status->geofence_cfg.geofence_target_cnt++;
1715
+ if (rtt_status->geofence_cfg.geofence_target_cnt == 1) {
1716
+ /* Adding first target */
1717
+ rtt_status->geofence_cfg.cur_target_idx = 0;
1718
+ }
1719
+
1720
+exit:
1721
+ GEOFENCE_RTT_UNLOCK(rtt_status);
1722
+ return err;
1723
+}
1724
+
1725
+/* removes geofence target from the target list */
1726
+int
1727
+dhd_rtt_remove_geofence_target(dhd_pub_t *dhd, struct ether_addr *peer_addr)
1728
+{
1729
+ int err = BCME_OK;
1730
+ rtt_status_info_t *rtt_status;
1731
+ rtt_geofence_target_info_t *geofence_target_info;
1732
+ int8 geofence_target_cnt, j, index = 0;
1733
+
1734
+ NULL_CHECK(dhd, "dhd is NULL", err);
1735
+ rtt_status = GET_RTTSTATE(dhd);
1736
+ NULL_CHECK(rtt_status, "rtt_status is NULL", err);
1737
+
1738
+ GEOFENCE_RTT_LOCK(rtt_status);
1739
+
1740
+ geofence_target_cnt = dhd_rtt_get_geofence_target_cnt(dhd);
1741
+ if (geofence_target_cnt == 0) {
1742
+ DHD_RTT(("Queue Empty, Geofencing RTT remove request dropped\n"));
1743
+ ASSERT(0);
1744
+ goto exit;
1745
+ }
1746
+
1747
+ /* Get the geofence_target via peer addr */
1748
+ geofence_target_info = dhd_rtt_get_geofence_target(dhd, peer_addr, &index);
1749
+ if (geofence_target_info == NULL) {
1750
+ DHD_RTT(("Geofencing RTT target not found, remove request dropped\n"));
1751
+ err = BCME_NOTFOUND;
1752
+ goto exit;
1753
+ }
1754
+
1755
+ /* left shift all the valid entries, as we dont keep holes in list */
1756
+ for (j = index; (j+1) < geofence_target_cnt; j++) {
1757
+ if (geofence_target_info[j].valid == TRUE) {
1758
+ /*
1759
+ * src and dest buffer len same, pointers of same DS
1760
+ * statically allocated
1761
+ */
1762
+ (void)memcpy_s(&geofence_target_info[j], sizeof(geofence_target_info[j]),
1763
+ &geofence_target_info[j + 1],
1764
+ sizeof(geofence_target_info[j + 1]));
1765
+ } else {
1766
+ break;
1767
+ }
1768
+ }
1769
+ rtt_status->geofence_cfg.geofence_target_cnt--;
1770
+ if ((rtt_status->geofence_cfg.geofence_target_cnt == 0) ||
1771
+ (index == rtt_status->geofence_cfg.cur_target_idx)) {
1772
+ /* Move cur_idx to next target */
1773
+ dhd_rtt_move_geofence_cur_target_idx_to_next(dhd);
1774
+ } else if (index < rtt_status->geofence_cfg.cur_target_idx) {
1775
+ /* Decrement cur index if cur target position changed */
1776
+ rtt_status->geofence_cfg.cur_target_idx--;
1777
+ }
1778
+
1779
+exit:
1780
+ GEOFENCE_RTT_UNLOCK(rtt_status);
1781
+ return err;
1782
+}
1783
+
1784
+/* deletes/empty geofence target list */
1785
+int
1786
+dhd_rtt_delete_geofence_target_list(dhd_pub_t *dhd)
1787
+{
1788
+ rtt_status_info_t *rtt_status;
1789
+
1790
+ int err = BCME_OK;
1791
+
1792
+ NULL_CHECK(dhd, "dhd is NULL", err);
1793
+ rtt_status = GET_RTTSTATE(dhd);
1794
+ NULL_CHECK(rtt_status, "rtt_status is NULL", err);
1795
+ GEOFENCE_RTT_LOCK(rtt_status);
1796
+ memset_s(&rtt_status->geofence_cfg, sizeof(rtt_geofence_cfg_t),
1797
+ 0, sizeof(rtt_geofence_cfg_t));
1798
+ GEOFENCE_RTT_UNLOCK(rtt_status);
1799
+ return err;
1800
+}
1801
+
1802
+int
1803
+dhd_rtt_sched_geofencing_target(dhd_pub_t *dhd)
1804
+{
1805
+ rtt_geofence_target_info_t *geofence_target_info;
1806
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
1807
+ int ret = BCME_OK;
1808
+ bool geofence_state;
1809
+ bool role_concurrency_state;
1810
+ u8 rtt_invalid_reason = RTT_STATE_VALID;
1811
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1812
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1813
+
1814
+ NAN_MUTEX_LOCK();
1815
+
1816
+ if ((cfg->nan_init_state == FALSE) ||
1817
+ (cfg->nan_enable == FALSE)) {
1818
+ ret = BCME_NOTENABLED;
1819
+ goto done;
1820
+ }
1821
+ geofence_state = dhd_rtt_get_geofence_rtt_state(dhd);
1822
+ role_concurrency_state = dhd_rtt_get_role_concurrency_state(dhd);
1823
+
1824
+ DHD_RTT_ERR(("dhd_rtt_sched_geofencing_target: sched_reason = %d\n",
1825
+ rtt_status->rtt_sched_reason));
1826
+
1827
+ if (geofence_state == TRUE || role_concurrency_state == TRUE) {
1828
+ ret = BCME_ERROR;
1829
+ DHD_RTT_ERR(("geofencing constraint , sched request dropped,"
1830
+ " geofence_state = %d, role_concurrency_state = %d\n",
1831
+ geofence_state, role_concurrency_state));
1832
+ goto done;
1833
+ }
1834
+
1835
+ /* Get current geofencing target */
1836
+ geofence_target_info = dhd_rtt_get_geofence_current_target(dhd);
1837
+
1838
+ /* call cfg API for trigerring geofencing RTT */
1839
+ if (geofence_target_info) {
1840
+ /* check for dp/others concurrency */
1841
+ rtt_invalid_reason = dhd_rtt_invalid_states(dev,
1842
+ &geofence_target_info->peer_addr);
1843
+ if (rtt_invalid_reason != RTT_STATE_VALID) {
1844
+ ret = BCME_BUSY;
1845
+ DHD_RTT_ERR(("DRV State is not valid for RTT, "
1846
+ "invalid_state = %d\n", rtt_invalid_reason));
1847
+ goto done;
1848
+ }
1849
+
1850
+ ret = wl_cfgnan_trigger_geofencing_ranging(dev,
1851
+ &geofence_target_info->peer_addr);
1852
+ if (ret == BCME_OK) {
1853
+ dhd_rtt_set_geofence_rtt_state(dhd, TRUE);
1854
+ }
1855
+ } else {
1856
+ DHD_RTT(("No RTT target to schedule\n"));
1857
+ ret = BCME_NOTFOUND;
1858
+ }
1859
+
1860
+done:
1861
+ NAN_MUTEX_UNLOCK();
1862
+ return ret;
1863
+}
1864
+#endif /* WL_NAN */
1865
+
1866
+#ifdef WL_CFG80211
1867
+#ifdef WL_NAN
1868
+static void
1869
+dhd_rtt_retry(dhd_pub_t *dhd)
1870
+{
1871
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
1872
+ struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1873
+ rtt_geofence_target_info_t *geofence_target = NULL;
1874
+ nan_ranging_inst_t *ranging_inst = NULL;
1875
+
1876
+ geofence_target = dhd_rtt_get_geofence_current_target(dhd);
1877
+ if (!geofence_target) {
1878
+ DHD_RTT(("dhd_rtt_retry: geofence target null\n"));
1879
+ goto exit;
1880
+ }
1881
+ ranging_inst = wl_cfgnan_get_ranging_inst(cfg,
1882
+ &geofence_target->peer_addr, NAN_RANGING_ROLE_INITIATOR);
1883
+ if (!ranging_inst) {
1884
+ DHD_RTT(("dhd_rtt_retry: ranging instance null\n"));
1885
+ goto exit;
1886
+ }
1887
+ wl_cfgnan_reset_geofence_ranging(cfg,
1888
+ ranging_inst, RTT_SCHED_RTT_RETRY_GEOFENCE);
1889
+
1890
+exit:
1891
+ return;
1892
+}
1893
+
1894
+static void
1895
+dhd_rtt_retry_work(struct work_struct *work)
1896
+{
1897
+ rtt_status_info_t *rtt_status = NULL;
1898
+ dhd_pub_t *dhd = NULL;
1899
+ struct net_device *dev = NULL;
1900
+ struct bcm_cfg80211 *cfg = NULL;
1901
+
1902
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1903
+#pragma GCC diagnostic push
1904
+#pragma GCC diagnostic ignored "-Wcast-qual"
1905
+#endif // endif
1906
+ rtt_status = container_of(work, rtt_status_info_t, proxd_timeout.work);
1907
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
1908
+#pragma GCC diagnostic pop
1909
+#endif // endif
1910
+
1911
+ dhd = rtt_status->dhd;
1912
+ if (dhd == NULL) {
1913
+ DHD_RTT_ERR(("%s : dhd is NULL\n", __FUNCTION__));
1914
+ goto exit;
1915
+ }
1916
+ dev = dhd_linux_get_primary_netdev(dhd);
1917
+ cfg = wl_get_cfg(dev);
1918
+
1919
+ NAN_MUTEX_LOCK();
1920
+ mutex_lock(&rtt_status->rtt_mutex);
1921
+ (void) dhd_rtt_retry(dhd);
1922
+ mutex_unlock(&rtt_status->rtt_mutex);
1923
+ NAN_MUTEX_UNLOCK();
1924
+
1925
+exit:
1926
+ return;
1927
+}
1928
+#endif /* WL_NAN */
1929
+
1930
+/*
1931
+ * Return zero (0)
1932
+ * for valid RTT state
1933
+ * means if RTT is applicable
1934
+ */
1935
+uint8
1936
+dhd_rtt_invalid_states(struct net_device *ndev, struct ether_addr *peer_addr)
1937
+{
1938
+ uint8 invalid_reason = RTT_STATE_VALID;
1939
+ struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
1940
+
1941
+ UNUSED_PARAMETER(cfg);
1942
+ UNUSED_PARAMETER(invalid_reason);
1943
+
1944
+ /* Make sure peer addr is not NULL in caller */
1945
+ ASSERT(peer_addr);
1946
+ /*
1947
+ * Keep adding prohibited drv states here
1948
+ * Only generic conditions which block
1949
+ * All RTTs like NDP connection
1950
+ */
1951
+
1952
+#ifdef WL_NAN
1953
+ if (wl_cfgnan_data_dp_exists_with_peer(cfg, peer_addr)) {
1954
+ invalid_reason = RTT_STATE_INV_REASON_NDP_EXIST;
1955
+ DHD_RTT(("NDP in progress/connected, RTT prohibited\n"));
1956
+ goto exit;
1957
+ }
1958
+#endif /* WL_NAN */
1959
+
1960
+ /* Remove below #defines once more exit calls come */
1961
+#ifdef WL_NAN
1962
+exit:
1963
+#endif /* WL_NAN */
1964
+ return invalid_reason;
1965
+}
1966
+#endif /* WL_CFG80211 */
1967
+
1968
+void
1969
+dhd_rtt_schedule_rtt_work_thread(dhd_pub_t *dhd, int sched_reason)
1970
+{
1971
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
1972
+ if (rtt_status == NULL) {
1973
+ ASSERT(0);
1974
+ } else {
1975
+ rtt_status->rtt_sched_reason = sched_reason;
1976
+ schedule_work(&rtt_status->work);
1977
+ }
1978
+ return;
11701979 }
11711980
11721981 int
11731982 dhd_rtt_stop(dhd_pub_t *dhd, struct ether_addr *mac_list, int mac_cnt)
11741983 {
11751984 int err = BCME_OK;
1985
+#ifdef WL_CFG80211
11761986 int i = 0, j = 0;
11771987 rtt_status_info_t *rtt_status;
11781988 rtt_results_header_t *entry, *next;
....@@ -1183,7 +1993,7 @@
11831993 rtt_status = GET_RTTSTATE(dhd);
11841994 NULL_CHECK(rtt_status, "rtt_status is NULL", err);
11851995 if (rtt_status->status == RTT_STOPPED) {
1186
- DHD_ERROR(("rtt is not started\n"));
1996
+ DHD_RTT_ERR(("rtt is not started\n"));
11871997 return BCME_OK;
11881998 }
11891999 DHD_RTT(("%s enter\n", __FUNCTION__));
....@@ -1203,6 +2013,7 @@
12032013 /* remove the rtt results in cache */
12042014 if (!list_empty(&rtt_status->rtt_results_cache)) {
12052015 /* Iterate rtt_results_header list */
2016
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
12062017 list_for_each_entry_safe(entry, next,
12072018 &rtt_status->rtt_results_cache, list) {
12082019 list_del(&entry->list);
....@@ -1214,12 +2025,14 @@
12142025 }
12152026 kfree(entry);
12162027 }
2028
+ GCC_DIAGNOSTIC_POP();
12172029 }
12182030 /* send the rtt complete event to wake up the user process */
2031
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
12192032 list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
2033
+ GCC_DIAGNOSTIC_POP();
12202034 iter->noti_fn(iter->ctx, &rtt_status->rtt_results_cache);
12212035 }
1222
-
12232036 /* reinitialize the HEAD */
12242037 INIT_LIST_HEAD(&rtt_status->rtt_results_cache);
12252038 /* clear information for rtt_config */
....@@ -1227,20 +2040,128 @@
12272040 memset(rtt_status->rtt_config.target_info, 0,
12282041 TARGET_INFO_SIZE(RTT_MAX_TARGET_CNT));
12292042 rtt_status->cur_idx = 0;
2043
+ /* Cancel pending proxd timeout work if any */
2044
+ if (delayed_work_pending(&rtt_status->proxd_timeout)) {
2045
+ cancel_delayed_work(&rtt_status->proxd_timeout);
2046
+ }
12302047 dhd_rtt_delete_session(dhd, FTM_DEFAULT_SESSION);
2048
+#ifdef WL_NAN
2049
+ dhd_rtt_delete_nan_session(dhd);
2050
+#endif /* WL_NAN */
12312051 dhd_rtt_ftm_enable(dhd, FALSE);
12322052 }
12332053 mutex_unlock(&rtt_status->rtt_mutex);
2054
+#endif /* WL_CFG80211 */
12342055 return err;
2056
+}
2057
+
2058
+#ifdef WL_CFG80211
2059
+static void
2060
+dhd_rtt_timeout(dhd_pub_t *dhd)
2061
+{
2062
+ rtt_status_info_t *rtt_status;
2063
+#ifndef DHD_DUMP_ON_RTT_TIMEOUT
2064
+ rtt_target_info_t *rtt_target = NULL;
2065
+ rtt_target_info_t *rtt_target_info = NULL;
2066
+#ifdef WL_NAN
2067
+ nan_ranging_inst_t *ranging_inst = NULL;
2068
+ int ret = BCME_OK;
2069
+ uint32 status;
2070
+ struct net_device *ndev = dhd_linux_get_primary_netdev(dhd);
2071
+ struct bcm_cfg80211 *cfg = wiphy_priv(ndev->ieee80211_ptr->wiphy);
2072
+#endif /* WL_NAN */
2073
+#endif /* !DHD_DUMP_ON_RTT_TIMEOUT */
2074
+
2075
+ rtt_status = GET_RTTSTATE(dhd);
2076
+ if (!rtt_status) {
2077
+ DHD_RTT_ERR(("Proxd timer expired but no RTT status\n"));
2078
+ goto exit;
2079
+ }
2080
+
2081
+ if (RTT_IS_STOPPED(rtt_status)) {
2082
+ DHD_RTT_ERR(("Proxd timer expired but no RTT Request\n"));
2083
+ goto exit;
2084
+ }
2085
+
2086
+#ifdef DHD_DUMP_ON_RTT_TIMEOUT
2087
+ /* Dump, and Panic depending on memdump.info */
2088
+ if (dhd_query_bus_erros(dhd)) {
2089
+ goto exit;
2090
+ }
2091
+#ifdef DHD_FW_COREDUMP
2092
+ if (dhd->memdump_enabled) {
2093
+ /* Behave based on user memdump info */
2094
+ dhd->memdump_type = DUMP_TYPE_PROXD_TIMEOUT;
2095
+ dhd_bus_mem_dump(dhd);
2096
+ }
2097
+#endif /* DHD_FW_COREDUMP */
2098
+#else /* DHD_DUMP_ON_RTT_TIMEOUT */
2099
+ /* Cancel RTT for target and proceed to next target */
2100
+ rtt_target_info = rtt_status->rtt_config.target_info;
2101
+ if ((!rtt_target_info) ||
2102
+ (rtt_status->cur_idx >= rtt_status->rtt_config.rtt_target_cnt)) {
2103
+ goto exit;
2104
+ }
2105
+ rtt_target = &rtt_target_info[rtt_status->cur_idx];
2106
+ WL_ERR(("Proxd timer expired for Target: "MACDBG" \n", MAC2STRDBG(&rtt_target->addr)));
2107
+#ifdef WL_NAN
2108
+ if (rtt_target->peer == RTT_PEER_NAN) {
2109
+ ranging_inst = wl_cfgnan_check_for_ranging(cfg, &rtt_target->addr);
2110
+ if (!ranging_inst) {
2111
+ goto exit;
2112
+ }
2113
+ ret = wl_cfgnan_cancel_ranging(ndev, cfg, ranging_inst->range_id,
2114
+ NAN_RNG_TERM_FLAG_IMMEDIATE, &status);
2115
+ if (unlikely(ret) || unlikely(status)) {
2116
+ WL_ERR(("%s:nan range cancel failed ret = %d status = %d\n",
2117
+ __FUNCTION__, ret, status));
2118
+ }
2119
+ } else
2120
+#endif /* WL_NAN */
2121
+ {
2122
+ /* For Legacy RTT */
2123
+ dhd_rtt_delete_session(dhd, FTM_DEFAULT_SESSION);
2124
+ }
2125
+ dhd_rtt_create_failure_result(rtt_status, &rtt_target->addr);
2126
+ dhd_rtt_handle_rtt_session_end(dhd);
2127
+#endif /* DHD_DUMP_ON_RTT_TIMEOUT */
2128
+exit:
2129
+ return;
2130
+}
2131
+
2132
+static void
2133
+dhd_rtt_timeout_work(struct work_struct *work)
2134
+{
2135
+ rtt_status_info_t *rtt_status = NULL;
2136
+ dhd_pub_t *dhd = NULL;
2137
+
2138
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2139
+#pragma GCC diagnostic push
2140
+#pragma GCC diagnostic ignored "-Wcast-qual"
2141
+#endif // endif
2142
+ rtt_status = container_of(work, rtt_status_info_t, proxd_timeout.work);
2143
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
2144
+#pragma GCC diagnostic pop
2145
+#endif // endif
2146
+
2147
+ dhd = rtt_status->dhd;
2148
+ if (dhd == NULL) {
2149
+ DHD_RTT_ERR(("%s : dhd is NULL\n", __FUNCTION__));
2150
+ return;
2151
+ }
2152
+ mutex_lock(&rtt_status->rtt_mutex);
2153
+ (void) dhd_rtt_timeout(dhd);
2154
+ mutex_unlock(&rtt_status->rtt_mutex);
12352155 }
12362156
12372157 static int
12382158 dhd_rtt_start(dhd_pub_t *dhd)
12392159 {
12402160 int err = BCME_OK;
2161
+ int err_at = 0;
12412162 char eabuf[ETHER_ADDR_STR_LEN];
12422163 char chanbuf[CHANSPEC_STR_LEN];
1243
- int mpc = 0;
2164
+ int pm = PM_OFF;
12442165 int ftm_cfg_cnt = 0;
12452166 int ftm_param_cnt = 0;
12462167 uint32 rspec = 0;
....@@ -1248,39 +2169,86 @@
12482169 ftm_config_param_info_t ftm_params[FTM_MAX_PARAMS];
12492170 rtt_target_info_t *rtt_target;
12502171 rtt_status_info_t *rtt_status;
2172
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
2173
+ u8 ioctl_buf[WLC_IOCTL_SMLEN];
2174
+ u8 rtt_invalid_reason = RTT_STATE_VALID;
2175
+ int rtt_sched_type = RTT_TYPE_INVALID;
2176
+
12512177 NULL_CHECK(dhd, "dhd is NULL", err);
12522178
12532179 rtt_status = GET_RTTSTATE(dhd);
12542180 NULL_CHECK(rtt_status, "rtt_status is NULL", err);
2181
+
2182
+ DHD_RTT(("Enter %s\n", __FUNCTION__));
2183
+
2184
+ if (RTT_IS_STOPPED(rtt_status)) {
2185
+ DHD_RTT(("No Directed RTT target to process, check for geofence\n"));
2186
+ goto geofence;
2187
+ }
2188
+
12552189 if (rtt_status->cur_idx >= rtt_status->rtt_config.rtt_target_cnt) {
12562190 err = BCME_RANGE;
1257
- DHD_ERROR(("%s : idx %d is out of range\n", __FUNCTION__, rtt_status->cur_idx));
1258
- goto exit;
1259
- }
1260
- if (RTT_IS_STOPPED(rtt_status)) {
1261
- DHD_ERROR(("RTT is stopped\n"));
1262
- goto exit;
1263
- }
1264
- /* turn off mpc in case of non-associted */
1265
- if (!dhd_is_associated(dhd, NULL, NULL)) {
1266
- err = dhd_iovar(dhd, 0, "mpc", (char *)&mpc, sizeof(mpc), NULL, 0, TRUE);
1267
- if (err) {
1268
- DHD_ERROR(("%s : failed to set mpc\n", __FUNCTION__));
1269
- goto exit;
2191
+ err_at = 1;
2192
+ DHD_RTT(("%s : idx %d is out of range\n", __FUNCTION__, rtt_status->cur_idx));
2193
+ if (rtt_status->flags == WL_PROXD_SESSION_FLAG_TARGET) {
2194
+ DHD_RTT_ERR(("STA is set as Target/Responder \n"));
2195
+ err = BCME_ERROR;
2196
+ err_at = 1;
12702197 }
1271
- rtt_status->mpc = 1; /* Either failure or complete, we need to enable mpc */
2198
+ goto exit;
2199
+ }
2200
+
2201
+ rtt_status->pm = PM_OFF;
2202
+ err = wldev_ioctl_get(dev, WLC_GET_PM, &rtt_status->pm, sizeof(rtt_status->pm));
2203
+ if (err) {
2204
+ DHD_RTT_ERR(("Failed to get the PM value\n"));
2205
+ } else {
2206
+ err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
2207
+ if (err) {
2208
+ DHD_RTT_ERR(("Failed to set the PM\n"));
2209
+ rtt_status->pm_restore = FALSE;
2210
+ } else {
2211
+ rtt_status->pm_restore = TRUE;
2212
+ }
12722213 }
12732214
12742215 mutex_lock(&rtt_status->rtt_mutex);
12752216 /* Get a target information */
12762217 rtt_target = &rtt_status->rtt_config.target_info[rtt_status->cur_idx];
12772218 mutex_unlock(&rtt_status->rtt_mutex);
1278
- DHD_ERROR(("%s enter\n", __FUNCTION__));
2219
+ DHD_RTT(("%s enter\n", __FUNCTION__));
2220
+
2221
+ if (ETHER_ISNULLADDR(rtt_target->addr.octet)) {
2222
+ err = BCME_BADADDR;
2223
+ err_at = 2;
2224
+ DHD_RTT(("RTT Target addr is NULL\n"));
2225
+ goto exit;
2226
+ }
2227
+
2228
+ /* check for dp/others concurrency */
2229
+ rtt_invalid_reason = dhd_rtt_invalid_states(dev, &rtt_target->addr);
2230
+ if (rtt_invalid_reason != RTT_STATE_VALID) {
2231
+ err = BCME_BUSY;
2232
+ err_at = 3;
2233
+ DHD_RTT(("DRV State is not valid for RTT\n"));
2234
+ goto exit;
2235
+ }
2236
+
2237
+#ifdef WL_NAN
2238
+ if (rtt_target->peer == RTT_PEER_NAN) {
2239
+ rtt_sched_type = RTT_TYPE_NAN_DIRECTED;
2240
+ rtt_status->status = RTT_ENABLED;
2241
+ /* Ignore return value..failure taken care inside the API */
2242
+ dhd_rtt_nan_start_session(dhd, rtt_target);
2243
+ goto exit;
2244
+ }
2245
+#endif /* WL_NAN */
12792246 if (!RTT_IS_ENABLED(rtt_status)) {
12802247 /* enable ftm */
12812248 err = dhd_rtt_ftm_enable(dhd, TRUE);
12822249 if (err) {
1283
- DHD_ERROR(("failed to enable FTM (%d)\n", err));
2250
+ DHD_RTT_ERR(("failed to enable FTM (%d)\n", err));
2251
+ err_at = 5;
12842252 goto exit;
12852253 }
12862254 }
....@@ -1288,7 +2256,8 @@
12882256 /* delete session of index default sesession */
12892257 err = dhd_rtt_delete_session(dhd, FTM_DEFAULT_SESSION);
12902258 if (err < 0 && err != BCME_NOTFOUND) {
1291
- DHD_ERROR(("failed to delete session of FTM (%d)\n", err));
2259
+ DHD_RTT_ERR(("failed to delete session of FTM (%d)\n", err));
2260
+ err_at = 6;
12922261 goto exit;
12932262 }
12942263 rtt_status->status = RTT_ENABLED;
....@@ -1300,45 +2269,72 @@
13002269 ftm_configs[ftm_cfg_cnt++].flags = WL_PROXD_SESSION_FLAG_INITIATOR;
13012270 dhd_rtt_ftm_config(dhd, FTM_DEFAULT_SESSION, FTM_CONFIG_CAT_OPTIONS,
13022271 ftm_configs, ftm_cfg_cnt);
2272
+
2273
+ memset(ioctl_buf, 0, WLC_IOCTL_SMLEN);
2274
+
2275
+ /* Rand Mac for newer version in place of cur_eth */
2276
+ if (dhd->wlc_ver_major < RTT_IOV_CUR_ETH_OBSOLETE) {
2277
+ err = wldev_iovar_getbuf(dev, "cur_etheraddr", NULL, 0,
2278
+ ioctl_buf, WLC_IOCTL_SMLEN, NULL);
2279
+ if (err) {
2280
+ DHD_RTT_ERR(("WLC_GET_CUR_ETHERADDR failed, error %d\n", err));
2281
+ err_at = 7;
2282
+ goto exit;
2283
+ }
2284
+ memcpy(rtt_target->local_addr.octet, ioctl_buf, ETHER_ADDR_LEN);
2285
+
2286
+ /* local mac address */
2287
+ if (!ETHER_ISNULLADDR(rtt_target->local_addr.octet)) {
2288
+ ftm_params[ftm_param_cnt].mac_addr = rtt_target->local_addr;
2289
+ ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_CUR_ETHER_ADDR;
2290
+ bcm_ether_ntoa(&rtt_target->local_addr, eabuf);
2291
+ DHD_RTT((">\t local %s\n", eabuf));
2292
+ }
2293
+ }
13032294 /* target's mac address */
13042295 if (!ETHER_ISNULLADDR(rtt_target->addr.octet)) {
13052296 ftm_params[ftm_param_cnt].mac_addr = rtt_target->addr;
13062297 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_PEER_MAC;
1307
- DHD_ERROR((">\t target %s\n", bcm_ether_ntoa(&rtt_target->addr, eabuf)));
2298
+ bcm_ether_ntoa(&rtt_target->addr, eabuf);
2299
+ DHD_RTT((">\t target %s\n", eabuf));
13082300 }
13092301 /* target's chanspec */
13102302 if (rtt_target->chanspec) {
13112303 ftm_params[ftm_param_cnt].chanspec = htol32((uint32)rtt_target->chanspec);
13122304 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_CHANSPEC;
1313
- DHD_ERROR((">\t chanspec : %s\n", wf_chspec_ntoa(rtt_target->chanspec, chanbuf)));
2305
+ wf_chspec_ntoa(rtt_target->chanspec, chanbuf);
2306
+ DHD_RTT((">\t chanspec : %s\n", chanbuf));
13142307 }
13152308 /* num-burst */
13162309 if (rtt_target->num_burst) {
13172310 ftm_params[ftm_param_cnt].data16 = htol16(rtt_target->num_burst);
13182311 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_NUM_BURST;
1319
- DHD_ERROR((">\t num of burst : %d\n", rtt_target->num_burst));
2312
+ DHD_RTT((">\t num of burst : %d\n", rtt_target->num_burst));
13202313 }
13212314 /* number of frame per burst */
1322
- if (rtt_target->num_frames_per_burst == 0) {
1323
- rtt_target->num_frames_per_burst =
1324
- CHSPEC_IS20(rtt_target->chanspec) ? FTM_DEFAULT_CNT_20M :
1325
- CHSPEC_IS40(rtt_target->chanspec) ? FTM_DEFAULT_CNT_40M :
1326
- FTM_DEFAULT_CNT_80M;
2315
+ rtt_target->num_frames_per_burst = FTM_DEFAULT_CNT_80M;
2316
+ if (CHSPEC_IS80(rtt_target->chanspec)) {
2317
+ rtt_target->num_frames_per_burst = FTM_DEFAULT_CNT_80M;
2318
+ } else if (CHSPEC_IS40(rtt_target->chanspec)) {
2319
+ rtt_target->num_frames_per_burst = FTM_DEFAULT_CNT_40M;
2320
+ } else if (CHSPEC_IS20(rtt_target->chanspec)) {
2321
+ rtt_target->num_frames_per_burst = FTM_DEFAULT_CNT_20M;
13272322 }
13282323 ftm_params[ftm_param_cnt].data16 = htol16(rtt_target->num_frames_per_burst);
13292324 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_BURST_NUM_FTM;
1330
- DHD_ERROR((">\t number of frame per burst : %d\n", rtt_target->num_frames_per_burst));
2325
+ DHD_RTT((">\t number of frame per burst : %d\n", rtt_target->num_frames_per_burst));
2326
+
13312327 /* FTM retry count */
13322328 if (rtt_target->num_retries_per_ftm) {
13332329 ftm_params[ftm_param_cnt].data8 = rtt_target->num_retries_per_ftm;
13342330 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_FTM_RETRIES;
1335
- DHD_ERROR((">\t retry count of FTM : %d\n", rtt_target->num_retries_per_ftm));
2331
+ DHD_RTT((">\t retry count of FTM : %d\n", rtt_target->num_retries_per_ftm));
13362332 }
13372333 /* FTM Request retry count */
13382334 if (rtt_target->num_retries_per_ftmr) {
13392335 ftm_params[ftm_param_cnt].data8 = rtt_target->num_retries_per_ftmr;
13402336 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_FTM_REQ_RETRIES;
1341
- DHD_ERROR((">\t retry count of FTM Req : %d\n", rtt_target->num_retries_per_ftm));
2337
+ DHD_RTT((">\t retry count of FTM Req : %d\n", rtt_target->num_retries_per_ftmr));
13422338 }
13432339 /* burst-period */
13442340 if (rtt_target->burst_period) {
....@@ -1346,86 +2342,140 @@
13462342 htol32(rtt_target->burst_period); /* ms */
13472343 ftm_params[ftm_param_cnt].data_intvl.tmu = WL_PROXD_TMU_MILLI_SEC;
13482344 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_BURST_PERIOD;
1349
- DHD_ERROR((">\t burst period : %d ms\n", rtt_target->burst_period));
2345
+ DHD_RTT((">\t burst period : %d ms\n", rtt_target->burst_period));
13502346 }
2347
+ /* Setting both duration and timeout to MAX duration
2348
+ * to handle the congestion environments.
2349
+ * Hence ignoring the user config.
2350
+ */
13512351 /* burst-duration */
2352
+ rtt_target->burst_duration = FTM_MAX_BURST_DUR_TMO_MS;
13522353 if (rtt_target->burst_duration) {
13532354 ftm_params[ftm_param_cnt].data_intvl.intvl =
1354
- htol32(rtt_target->burst_period); /* ms */
2355
+ htol32(rtt_target->burst_duration); /* ms */
13552356 ftm_params[ftm_param_cnt].data_intvl.tmu = WL_PROXD_TMU_MILLI_SEC;
13562357 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_BURST_DURATION;
1357
- DHD_ERROR((">\t burst duration : %d ms\n",
2358
+ DHD_RTT((">\t burst duration : %d ms\n",
13582359 rtt_target->burst_duration));
13592360 }
2361
+ /* burst-timeout */
2362
+ rtt_target->burst_timeout = FTM_MAX_BURST_DUR_TMO_MS;
2363
+ if (rtt_target->burst_timeout) {
2364
+ ftm_params[ftm_param_cnt].data_intvl.intvl =
2365
+ htol32(rtt_target->burst_timeout); /* ms */
2366
+ ftm_params[ftm_param_cnt].data_intvl.tmu = WL_PROXD_TMU_MILLI_SEC;
2367
+ ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_BURST_TIMEOUT;
2368
+ DHD_RTT((">\t burst timeout : %d ms\n",
2369
+ rtt_target->burst_timeout));
2370
+ }
2371
+ /* event_mask..applicable for only Legacy RTT.
2372
+ * For nan-rtt config happens from firmware
2373
+ */
2374
+ ftm_params[ftm_param_cnt].event_mask = ((1 << WL_PROXD_EVENT_BURST_END) |
2375
+ (1 << WL_PROXD_EVENT_SESSION_END));
2376
+ ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_EVENT_MASK;
2377
+
13602378 if (rtt_target->bw && rtt_target->preamble) {
13612379 bool use_default = FALSE;
13622380 int nss;
13632381 int mcs;
13642382 switch (rtt_target->preamble) {
1365
- case RTT_PREAMBLE_LEGACY:
1366
- rspec |= WL_RSPEC_ENCODE_RATE; /* 11abg */
1367
- rspec |= WL_RATE_6M;
1368
- break;
1369
- case RTT_PREAMBLE_HT:
1370
- rspec |= WL_RSPEC_ENCODE_HT; /* 11n HT */
1371
- mcs = 0; /* default MCS 0 */
1372
- rspec |= mcs;
1373
- break;
1374
- case RTT_PREAMBLE_VHT:
1375
- rspec |= WL_RSPEC_ENCODE_VHT; /* 11ac VHT */
1376
- mcs = 0; /* default MCS 0 */
1377
- nss = 1; /* default Nss = 1 */
1378
- rspec |= (nss << WL_RSPEC_VHT_NSS_SHIFT) | mcs;
1379
- break;
1380
- default:
1381
- DHD_ERROR(("doesn't support this preamble : %d\n", rtt_target->preamble));
1382
- use_default = TRUE;
1383
- break;
2383
+ case RTT_PREAMBLE_LEGACY:
2384
+ rspec |= WL_RSPEC_ENCODE_RATE; /* 11abg */
2385
+ rspec |= WL_RATE_6M;
2386
+ break;
2387
+ case RTT_PREAMBLE_HT:
2388
+ rspec |= WL_RSPEC_ENCODE_HT; /* 11n HT */
2389
+ mcs = 0; /* default MCS 0 */
2390
+ rspec |= mcs;
2391
+ break;
2392
+ case RTT_PREAMBLE_VHT:
2393
+ rspec |= WL_RSPEC_ENCODE_VHT; /* 11ac VHT */
2394
+ mcs = 0; /* default MCS 0 */
2395
+ nss = 1; /* default Nss = 1 */
2396
+ rspec |= (nss << WL_RSPEC_VHT_NSS_SHIFT) | mcs;
2397
+ break;
2398
+ default:
2399
+ DHD_RTT(("doesn't support this preamble : %d\n",
2400
+ rtt_target->preamble));
2401
+ use_default = TRUE;
2402
+ break;
13842403 }
13852404 switch (rtt_target->bw) {
1386
- case RTT_BW_20:
1387
- rspec |= WL_RSPEC_BW_20MHZ;
1388
- break;
1389
- case RTT_BW_40:
1390
- rspec |= WL_RSPEC_BW_40MHZ;
1391
- break;
1392
- case RTT_BW_80:
1393
- rspec |= WL_RSPEC_BW_80MHZ;
1394
- break;
1395
- default:
1396
- DHD_ERROR(("doesn't support this BW : %d\n", rtt_target->bw));
1397
- use_default = TRUE;
1398
- break;
2405
+ case RTT_BW_20:
2406
+ rspec |= WL_RSPEC_BW_20MHZ;
2407
+ break;
2408
+ case RTT_BW_40:
2409
+ rspec |= WL_RSPEC_BW_40MHZ;
2410
+ break;
2411
+ case RTT_BW_80:
2412
+ rspec |= WL_RSPEC_BW_80MHZ;
2413
+ break;
2414
+ default:
2415
+ DHD_RTT(("doesn't support this BW : %d\n", rtt_target->bw));
2416
+ use_default = TRUE;
2417
+ break;
13992418 }
14002419 if (!use_default) {
14012420 ftm_params[ftm_param_cnt].data32 = htol32(rspec);
14022421 ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_RATESPEC;
1403
- DHD_ERROR((">\t ratespec : %d\n", rspec));
2422
+ DHD_RTT((">\t ratespec : %d\n", rspec));
14042423 }
14052424
14062425 }
2426
+ dhd_set_rand_mac_oui(dhd);
14072427 dhd_rtt_ftm_config(dhd, FTM_DEFAULT_SESSION, FTM_CONFIG_CAT_GENERAL,
1408
- ftm_params, ftm_param_cnt);
2428
+ ftm_params, ftm_param_cnt);
14092429
2430
+ rtt_sched_type = RTT_TYPE_LEGACY;
14102431 err = dhd_rtt_start_session(dhd, FTM_DEFAULT_SESSION, TRUE);
14112432 if (err) {
1412
- DHD_ERROR(("failed to start session of FTM : error %d\n", err));
2433
+ DHD_RTT_ERR(("failed to start session of FTM : error %d\n", err));
2434
+ err_at = 8;
2435
+ } else {
2436
+ /* schedule proxd timeout */
2437
+ schedule_delayed_work(&rtt_status->proxd_timeout,
2438
+ msecs_to_jiffies(DHD_NAN_RTT_TIMER_INTERVAL_MS));
2439
+
14132440 }
2441
+
2442
+ goto exit;
2443
+geofence:
2444
+#ifdef WL_NAN
2445
+ /* sched geofencing rtt */
2446
+ rtt_sched_type = RTT_TYPE_NAN_GEOFENCE;
2447
+ if ((err = dhd_rtt_sched_geofencing_target(dhd)) != BCME_OK) {
2448
+ DHD_RTT_ERR(("geofencing sched failed, err = %d\n", err));
2449
+ err_at = 9;
2450
+ }
2451
+#endif /* WL_NAN */
2452
+
14142453 exit:
14152454 if (err) {
2455
+ /* RTT Failed */
2456
+ DHD_RTT_ERR(("dhd_rtt_start: Failed & RTT_STOPPED, err = %d,"
2457
+ " err_at = %d, rtt_sched_type = %d, rtt_invalid_reason = %d\n"
2458
+ " sched_reason = %d",
2459
+ err, err_at, rtt_sched_type, rtt_invalid_reason,
2460
+ rtt_status->rtt_sched_reason));
14162461 rtt_status->status = RTT_STOPPED;
14172462 /* disable FTM */
14182463 dhd_rtt_ftm_enable(dhd, FALSE);
1419
- if (rtt_status->mpc) {
1420
- /* enable mpc again in case of error */
1421
- mpc = 1;
1422
- rtt_status->mpc = 0;
1423
- err = dhd_iovar(dhd, 0, "mpc", (char *)&mpc, sizeof(mpc),
1424
- NULL, 0, TRUE);
2464
+ if (rtt_status->pm_restore) {
2465
+ pm = PM_FAST;
2466
+ DHD_RTT_ERR(("pm_restore =%d func =%s \n",
2467
+ rtt_status->pm_restore, __FUNCTION__));
2468
+ err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
2469
+ if (err) {
2470
+ DHD_RTT_ERR(("Failed to set PM \n"));
2471
+ } else {
2472
+ rtt_status->pm_restore = FALSE;
2473
+ }
14252474 }
14262475 }
14272476 return err;
14282477 }
2478
+#endif /* WL_CFG80211 */
14292479
14302480 int
14312481 dhd_rtt_register_noti_callback(dhd_pub_t *dhd, void *ctx, dhd_rtt_compl_noti_fn noti_fn)
....@@ -1439,7 +2489,9 @@
14392489 rtt_status = GET_RTTSTATE(dhd);
14402490 NULL_CHECK(rtt_status, "rtt_status is NULL", err);
14412491 spin_lock_bh(&noti_list_lock);
2492
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
14422493 list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
2494
+ GCC_DIAGNOSTIC_POP();
14432495 if (iter->noti_fn == noti_fn) {
14442496 goto exit;
14452497 }
....@@ -1468,13 +2520,16 @@
14682520 rtt_status = GET_RTTSTATE(dhd);
14692521 NULL_CHECK(rtt_status, "rtt_status is NULL", err);
14702522 spin_lock_bh(&noti_list_lock);
2523
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
14712524 list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
2525
+ GCC_DIAGNOSTIC_POP();
14722526 if (iter->noti_fn == noti_fn) {
14732527 cb = iter;
14742528 list_del(&cb->list);
14752529 break;
14762530 }
14772531 }
2532
+
14782533 spin_unlock_bh(&noti_list_lock);
14792534 if (cb) {
14802535 kfree(cb);
....@@ -1486,56 +2541,103 @@
14862541 dhd_rtt_convert_rate_to_host(uint32 rspec)
14872542 {
14882543 wifi_rate_t host_rate;
2544
+ uint32 bandwidth;
14892545 memset(&host_rate, 0, sizeof(wifi_rate_t));
1490
- if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_RATE) {
2546
+ if (RSPEC_ISLEGACY(rspec)) {
14912547 host_rate.preamble = 0;
1492
- } else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HT) {
2548
+ } else if (RSPEC_ISHT(rspec)) {
14932549 host_rate.preamble = 2;
14942550 host_rate.rateMcsIdx = rspec & WL_RSPEC_RATE_MASK;
1495
- } else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_VHT) {
2551
+ } else if (RSPEC_ISVHT(rspec)) {
14962552 host_rate.preamble = 3;
14972553 host_rate.rateMcsIdx = rspec & WL_RSPEC_VHT_MCS_MASK;
14982554 host_rate.nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
14992555 }
1500
- host_rate.bw = (rspec & WL_RSPEC_BW_MASK) - 1;
2556
+
2557
+ bandwidth = RSPEC_BW(rspec);
2558
+ switch (bandwidth) {
2559
+ case WL_RSPEC_BW_20MHZ:
2560
+ host_rate.bw = RTT_RATE_20M;
2561
+ break;
2562
+ case WL_RSPEC_BW_40MHZ:
2563
+ host_rate.bw = RTT_RATE_40M;
2564
+ break;
2565
+ case WL_RSPEC_BW_80MHZ:
2566
+ host_rate.bw = RTT_RATE_80M;
2567
+ break;
2568
+ case WL_RSPEC_BW_160MHZ:
2569
+ host_rate.bw = RTT_RATE_160M;
2570
+ break;
2571
+ default:
2572
+ host_rate.bw = RTT_RATE_20M;
2573
+ break;
2574
+ }
2575
+
15012576 host_rate.bitrate = rate_rspec2rate(rspec) / 100; /* 100kbps */
15022577 DHD_RTT(("bit rate : %d\n", host_rate.bitrate));
15032578 return host_rate;
15042579 }
15052580
1506
-
2581
+#define FTM_FRAME_TYPES {"SETUP", "TRIGGER", "TIMESTAMP"}
15072582 static int
1508
-dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 tlvid, uint16 len)
2583
+dhd_rtt_convert_results_to_host_v1(rtt_result_t *rtt_result, const uint8 *p_data,
2584
+ uint16 tlvid, uint16 len)
15092585 {
2586
+ int i;
15102587 int err = BCME_OK;
15112588 char eabuf[ETHER_ADDR_STR_LEN];
1512
- wl_proxd_rtt_result_t *p_data_info;
15132589 wl_proxd_result_flags_t flags;
15142590 wl_proxd_session_state_t session_state;
15152591 wl_proxd_status_t proxd_status;
15162592 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
15172593 struct timespec64 ts;
1518
-#else
2594
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
15192595 struct timespec ts;
1520
-#endif
2596
+#endif /* LINUX_VER >= 2.6.39 */
15212597 uint32 ratespec;
15222598 uint32 avg_dist;
1523
- wl_proxd_rtt_sample_t *p_sample;
2599
+ const wl_proxd_rtt_result_v1_t *p_data_info = NULL;
2600
+ const wl_proxd_rtt_sample_v1_t *p_sample_avg = NULL;
2601
+ const wl_proxd_rtt_sample_v1_t *p_sample = NULL;
15242602 wl_proxd_intvl_t rtt;
15252603 wl_proxd_intvl_t p_time;
2604
+ uint16 num_rtt = 0, snr = 0, bitflips = 0;
2605
+ wl_proxd_phy_error_t tof_phy_error = 0;
2606
+ wl_proxd_phy_error_t tof_phy_tgt_error = 0;
2607
+ wl_proxd_snr_t tof_target_snr = 0;
2608
+ wl_proxd_bitflips_t tof_target_bitflips = 0;
2609
+ int16 rssi = 0;
2610
+ int32 dist = 0;
2611
+ uint8 num_ftm = 0;
2612
+ char *ftm_frame_types[] = FTM_FRAME_TYPES;
2613
+ rtt_report_t *rtt_report = &(rtt_result->report);
2614
+
2615
+ BCM_REFERENCE(ftm_frame_types);
2616
+ BCM_REFERENCE(dist);
2617
+ BCM_REFERENCE(rssi);
2618
+ BCM_REFERENCE(tof_target_bitflips);
2619
+ BCM_REFERENCE(tof_target_snr);
2620
+ BCM_REFERENCE(tof_phy_tgt_error);
2621
+ BCM_REFERENCE(tof_phy_error);
2622
+ BCM_REFERENCE(bitflips);
2623
+ BCM_REFERENCE(snr);
2624
+ BCM_REFERENCE(session_state);
2625
+ BCM_REFERENCE(ftm_session_state_value_to_logstr);
15262626
15272627 NULL_CHECK(rtt_report, "rtt_report is NULL", err);
15282628 NULL_CHECK(p_data, "p_data is NULL", err);
15292629 DHD_RTT(("%s enter\n", __FUNCTION__));
1530
- p_data_info = (wl_proxd_rtt_result_t *) p_data;
2630
+ p_data_info = (const wl_proxd_rtt_result_v1_t *) p_data;
15312631 /* unpack and format 'flags' for display */
15322632 flags = ltoh16_ua(&p_data_info->flags);
15332633
15342634 /* session state and status */
15352635 session_state = ltoh16_ua(&p_data_info->state);
15362636 proxd_status = ltoh32_ua(&p_data_info->status);
2637
+ bcm_ether_ntoa((&(p_data_info->peer)), eabuf);
2638
+ ftm_status_value_to_logstr(proxd_status);
15372639 DHD_RTT((">\tTarget(%s) session state=%d(%s), status=%d(%s)\n",
1538
- bcm_ether_ntoa((&(p_data_info->peer)), eabuf),
2640
+ eabuf,
15392641 session_state,
15402642 ftm_session_state_value_to_logstr(session_state),
15412643 proxd_status,
....@@ -1558,13 +2660,14 @@
15582660 p_data_info->num_ftm)); /* in a session */
15592661 }
15602662 /* show 'avg_rtt' sample */
1561
- p_sample = &p_data_info->avg_rtt;
2663
+ p_sample_avg = &p_data_info->avg_rtt;
2664
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu));
15622665 DHD_RTT((">\tavg_rtt sample: rssi=%d rtt=%d%s std_deviation =%d.%d ratespec=0x%08x\n",
1563
- (int16) ltoh16_ua(&p_sample->rssi),
1564
- ltoh32_ua(&p_sample->rtt.intvl),
1565
- ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)),
2666
+ (int16) ltoh16_ua(&p_sample_avg->rssi),
2667
+ ltoh32_ua(&p_sample_avg->rtt.intvl),
2668
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu)),
15662669 ltoh16_ua(&p_data_info->sd_rtt)/10, ltoh16_ua(&p_data_info->sd_rtt)%10,
1567
- ltoh32_ua(&p_sample->ratespec)));
2670
+ ltoh32_ua(&p_sample_avg->ratespec)));
15682671
15692672 /* set peer address */
15702673 rtt_report->addr = p_data_info->peer;
....@@ -1578,8 +2681,10 @@
15782681 /* status */
15792682 rtt_report->status = ftm_get_statusmap_info(proxd_status,
15802683 &ftm_status_map_info[0], ARRAYSIZE(ftm_status_map_info));
2684
+
15812685 /* rssi (0.5db) */
1582
- rtt_report->rssi = (int16)ltoh16_ua(&p_data_info->avg_rtt.rssi) * 2;
2686
+ rtt_report->rssi = ABS((wl_proxd_rssi_t)ltoh16_ua(&p_data_info->avg_rtt.rssi)) * 2;
2687
+
15832688 /* rx rate */
15842689 ratespec = ltoh32_ua(&p_data_info->avg_rtt.ratespec);
15852690 rtt_report->rx_rate = dhd_rtt_convert_rate_to_host(ratespec);
....@@ -1592,26 +2697,24 @@
15922697 /* rtt_sd */
15932698 rtt.tmu = ltoh16_ua(&p_data_info->avg_rtt.rtt.tmu);
15942699 rtt.intvl = ltoh32_ua(&p_data_info->avg_rtt.rtt.intvl);
1595
- rtt_report->rtt = FTM_INTVL2NSEC(&rtt) * 10; /* nano -> 0.1 nano */
2700
+ rtt_report->rtt = (wifi_timespan)FTM_INTVL2NSEC(&rtt) * 1000; /* nano -> pico seconds */
15962701 rtt_report->rtt_sd = ltoh16_ua(&p_data_info->sd_rtt); /* nano -> 0.1 nano */
15972702 DHD_RTT(("rtt_report->rtt : %llu\n", rtt_report->rtt));
15982703 DHD_RTT(("rtt_report->rssi : %d (0.5db)\n", rtt_report->rssi));
15992704
16002705 /* average distance */
16012706 if (avg_dist != FTM_INVALID) {
1602
- rtt_report->distance = (avg_dist >> 8) * 100; /* meter -> cm */
1603
- rtt_report->distance += (avg_dist & 0xff) * 100 / 256;
2707
+ rtt_report->distance = (avg_dist >> 8) * 1000; /* meter -> mm */
2708
+ rtt_report->distance += (avg_dist & 0xff) * 1000 / 256;
16042709 } else {
16052710 rtt_report->distance = FTM_INVALID;
16062711 }
16072712 /* time stamp */
16082713 /* get the time elapsed from boot time */
1609
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
1610
- ktime_get_boottime_ts64(&ts);
1611
-#else
2714
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
16122715 get_monotonic_boottime(&ts);
1613
-#endif
16142716 rtt_report->ts = (uint64)TIMESPEC_TO_US(ts);
2717
+#endif /* LINUX_VER >= 2.6.39 */
16152718
16162719 if (proxd_status == WL_PROXD_E_REMOTE_FAIL) {
16172720 /* retry time after failure */
....@@ -1631,31 +2734,741 @@
16312734 ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_info->u.burst_duration.tmu))));
16322735 DHD_RTT(("rtt_report->burst_duration : %d\n", rtt_report->burst_duration));
16332736 }
2737
+
2738
+ /* display detail if available */
2739
+ num_rtt = ltoh16_ua(&p_data_info->num_rtt);
2740
+ if (num_rtt > 0) {
2741
+ DHD_RTT((">\tnum rtt: %d samples\n", num_rtt));
2742
+ p_sample = &p_data_info->rtt[0];
2743
+ for (i = 0; i < num_rtt; i++) {
2744
+ snr = 0;
2745
+ bitflips = 0;
2746
+ tof_phy_error = 0;
2747
+ tof_phy_tgt_error = 0;
2748
+ tof_target_snr = 0;
2749
+ tof_target_bitflips = 0;
2750
+ rssi = 0;
2751
+ dist = 0;
2752
+ num_ftm = p_data_info->num_ftm;
2753
+ /* FTM frames 1,4,7,11 have valid snr, rssi and bitflips */
2754
+ if ((i % num_ftm) == 1) {
2755
+ rssi = (wl_proxd_rssi_t) ltoh16_ua(&p_sample->rssi);
2756
+ snr = (wl_proxd_snr_t) ltoh16_ua(&p_sample->snr);
2757
+ bitflips = (wl_proxd_bitflips_t) ltoh16_ua(&p_sample->bitflips);
2758
+ tof_phy_error =
2759
+ (wl_proxd_phy_error_t)
2760
+ ltoh32_ua(&p_sample->tof_phy_error);
2761
+ tof_phy_tgt_error =
2762
+ (wl_proxd_phy_error_t)
2763
+ ltoh32_ua(&p_sample->tof_tgt_phy_error);
2764
+ tof_target_snr =
2765
+ (wl_proxd_snr_t)
2766
+ ltoh16_ua(&p_sample->tof_tgt_snr);
2767
+ tof_target_bitflips =
2768
+ (wl_proxd_bitflips_t)
2769
+ ltoh16_ua(&p_sample->tof_tgt_bitflips);
2770
+ dist = ltoh32_ua(&p_sample->distance);
2771
+ } else {
2772
+ rssi = -1;
2773
+ snr = 0;
2774
+ bitflips = 0;
2775
+ dist = 0;
2776
+ tof_target_bitflips = 0;
2777
+ tof_target_snr = 0;
2778
+ tof_phy_tgt_error = 0;
2779
+ }
2780
+ DHD_RTT((">\t sample[%d]: id=%d rssi=%d snr=0x%x bitflips=%d"
2781
+ " tof_phy_error %x tof_phy_tgt_error %x target_snr=0x%x"
2782
+ " target_bitflips=%d dist=%d rtt=%d%s status %s"
2783
+ " Type %s coreid=%d\n",
2784
+ i, p_sample->id, rssi, snr,
2785
+ bitflips, tof_phy_error, tof_phy_tgt_error,
2786
+ tof_target_snr,
2787
+ tof_target_bitflips, dist,
2788
+ ltoh32_ua(&p_sample->rtt.intvl),
2789
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)),
2790
+ ftm_status_value_to_logstr(ltoh32_ua(&p_sample->status)),
2791
+ ftm_frame_types[i % num_ftm], p_sample->coreid));
2792
+ p_sample++;
2793
+ }
2794
+ }
16342795 return err;
16352796 }
2797
+
2798
+static int
2799
+dhd_rtt_convert_results_to_host_v2(rtt_result_t *rtt_result, const uint8 *p_data,
2800
+ uint16 tlvid, uint16 len)
2801
+{
2802
+ int i;
2803
+ int err = BCME_OK;
2804
+ char eabuf[ETHER_ADDR_STR_LEN];
2805
+ wl_proxd_result_flags_t flags;
2806
+ wl_proxd_session_state_t session_state;
2807
+ wl_proxd_status_t proxd_status;
2808
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
2809
+ struct timespec64 ts;
2810
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2811
+ struct timespec ts;
2812
+#endif /* LINUX_VER >= 2.6.39 */
2813
+ uint32 ratespec;
2814
+ uint32 avg_dist;
2815
+ const wl_proxd_rtt_result_v2_t *p_data_info = NULL;
2816
+ const wl_proxd_rtt_sample_v2_t *p_sample_avg = NULL;
2817
+ const wl_proxd_rtt_sample_v2_t *p_sample = NULL;
2818
+ uint16 num_rtt = 0;
2819
+ wl_proxd_intvl_t rtt;
2820
+ wl_proxd_intvl_t p_time;
2821
+ uint16 snr = 0, bitflips = 0;
2822
+ wl_proxd_phy_error_t tof_phy_error = 0;
2823
+ wl_proxd_phy_error_t tof_phy_tgt_error = 0;
2824
+ wl_proxd_snr_t tof_target_snr = 0;
2825
+ wl_proxd_bitflips_t tof_target_bitflips = 0;
2826
+ int16 rssi = 0;
2827
+ int32 dist = 0;
2828
+ uint32 chanspec = 0;
2829
+ uint8 num_ftm = 0;
2830
+ char *ftm_frame_types[] = FTM_FRAME_TYPES;
2831
+ rtt_report_t *rtt_report = &(rtt_result->report);
2832
+
2833
+ BCM_REFERENCE(ftm_frame_types);
2834
+ BCM_REFERENCE(dist);
2835
+ BCM_REFERENCE(rssi);
2836
+ BCM_REFERENCE(tof_target_bitflips);
2837
+ BCM_REFERENCE(tof_target_snr);
2838
+ BCM_REFERENCE(tof_phy_tgt_error);
2839
+ BCM_REFERENCE(tof_phy_error);
2840
+ BCM_REFERENCE(bitflips);
2841
+ BCM_REFERENCE(snr);
2842
+ BCM_REFERENCE(chanspec);
2843
+ BCM_REFERENCE(session_state);
2844
+ BCM_REFERENCE(ftm_session_state_value_to_logstr);
2845
+
2846
+ NULL_CHECK(rtt_report, "rtt_report is NULL", err);
2847
+ NULL_CHECK(p_data, "p_data is NULL", err);
2848
+ DHD_RTT(("%s enter\n", __FUNCTION__));
2849
+ p_data_info = (const wl_proxd_rtt_result_v2_t *) p_data;
2850
+ /* unpack and format 'flags' for display */
2851
+ flags = ltoh16_ua(&p_data_info->flags);
2852
+ /* session state and status */
2853
+ session_state = ltoh16_ua(&p_data_info->state);
2854
+ proxd_status = ltoh32_ua(&p_data_info->status);
2855
+ bcm_ether_ntoa((&(p_data_info->peer)), eabuf);
2856
+
2857
+ if (proxd_status != BCME_OK) {
2858
+ DHD_RTT_ERR((">\tTarget(%s) session state=%d(%s), status=%d(%s) "
2859
+ "num_meas_ota %d num_valid_rtt %d result_flags %x\n",
2860
+ eabuf, session_state,
2861
+ ftm_session_state_value_to_logstr(session_state),
2862
+ proxd_status, ftm_status_value_to_logstr(proxd_status),
2863
+ p_data_info->num_meas, p_data_info->num_valid_rtt,
2864
+ p_data_info->flags));
2865
+ } else {
2866
+ DHD_RTT((">\tTarget(%s) session state=%d(%s), status=%d(%s)\n",
2867
+ eabuf, session_state,
2868
+ ftm_session_state_value_to_logstr(session_state),
2869
+ proxd_status, ftm_status_value_to_logstr(proxd_status)));
2870
+ }
2871
+ /* show avg_dist (1/256m units), burst_num */
2872
+ avg_dist = ltoh32_ua(&p_data_info->avg_dist);
2873
+ if (avg_dist == 0xffffffff) { /* report 'failure' case */
2874
+ DHD_RTT((">\tavg_dist=-1m, burst_num=%d, valid_measure_cnt=%d\n",
2875
+ ltoh16_ua(&p_data_info->burst_num),
2876
+ p_data_info->num_valid_rtt)); /* in a session */
2877
+ avg_dist = FTM_INVALID;
2878
+ } else {
2879
+ DHD_RTT((">\tavg_dist=%d.%04dm, burst_num=%d, valid_measure_cnt=%d num_ftm=%d "
2880
+ "num_meas_ota=%d, result_flags=%x\n", avg_dist >> 8, /* 1/256m units */
2881
+ ((avg_dist & 0xff) * 625) >> 4,
2882
+ ltoh16_ua(&p_data_info->burst_num),
2883
+ p_data_info->num_valid_rtt,
2884
+ p_data_info->num_ftm, p_data_info->num_meas,
2885
+ p_data_info->flags)); /* in a session */
2886
+ }
2887
+ rtt_result->rtt_detail.num_ota_meas = p_data_info->num_meas;
2888
+ rtt_result->rtt_detail.result_flags = p_data_info->flags;
2889
+ /* show 'avg_rtt' sample */
2890
+ /* in v2, avg_rtt is the first element of the variable rtt[] */
2891
+ p_sample_avg = &p_data_info->rtt[0];
2892
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu));
2893
+ DHD_RTT((">\tavg_rtt sample: rssi=%d rtt=%d%s std_deviation =%d.%d"
2894
+ "ratespec=0x%08x chanspec=0x%08x\n",
2895
+ (int16) ltoh16_ua(&p_sample_avg->rssi),
2896
+ ltoh32_ua(&p_sample_avg->rtt.intvl),
2897
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu)),
2898
+ ltoh16_ua(&p_data_info->sd_rtt)/10, ltoh16_ua(&p_data_info->sd_rtt)%10,
2899
+ ltoh32_ua(&p_sample_avg->ratespec),
2900
+ ltoh32_ua(&p_sample_avg->chanspec)));
2901
+
2902
+ /* set peer address */
2903
+ rtt_report->addr = p_data_info->peer;
2904
+
2905
+ /* burst num */
2906
+ rtt_report->burst_num = ltoh16_ua(&p_data_info->burst_num);
2907
+
2908
+ /* success num */
2909
+ rtt_report->success_num = p_data_info->num_valid_rtt;
2910
+
2911
+ /* num-ftm configured */
2912
+ rtt_report->ftm_num = p_data_info->num_ftm;
2913
+
2914
+ /* actual number of FTM supported by peer */
2915
+ rtt_report->num_per_burst_peer = p_data_info->num_ftm;
2916
+ rtt_report->negotiated_burst_num = p_data_info->num_ftm;
2917
+
2918
+ /* status */
2919
+ rtt_report->status = ftm_get_statusmap_info(proxd_status,
2920
+ &ftm_status_map_info[0], ARRAYSIZE(ftm_status_map_info));
2921
+
2922
+ /* Framework expects status as SUCCESS else all results will be
2923
+ * set to zero even if we have partial valid result.
2924
+ * So setting status as SUCCESS if we have a valid_rtt
2925
+ * On burst timeout we stop burst with "timeout" reason and
2926
+ * on msch end we set status as "cancel"
2927
+ */
2928
+ if ((proxd_status == WL_PROXD_E_TIMEOUT ||
2929
+ proxd_status == WL_PROXD_E_CANCELED) &&
2930
+ rtt_report->success_num) {
2931
+ rtt_report->status = RTT_STATUS_SUCCESS;
2932
+ }
2933
+
2934
+ /* rssi (0.5db) */
2935
+ rtt_report->rssi = ABS((wl_proxd_rssi_t)ltoh16_ua(&p_sample_avg->rssi)) * 2;
2936
+
2937
+ /* rx rate */
2938
+ ratespec = ltoh32_ua(&p_sample_avg->ratespec);
2939
+ rtt_report->rx_rate = dhd_rtt_convert_rate_to_host(ratespec);
2940
+
2941
+ /* tx rate */
2942
+ if (flags & WL_PROXD_RESULT_FLAG_VHTACK) {
2943
+ rtt_report->tx_rate = dhd_rtt_convert_rate_to_host(0x2010010);
2944
+ } else {
2945
+ rtt_report->tx_rate = dhd_rtt_convert_rate_to_host(0xc);
2946
+ }
2947
+
2948
+ /* rtt_sd */
2949
+ rtt.tmu = ltoh16_ua(&p_sample_avg->rtt.tmu);
2950
+ rtt.intvl = ltoh32_ua(&p_sample_avg->rtt.intvl);
2951
+ rtt_report->rtt = (wifi_timespan)FTM_INTVL2NSEC(&rtt) * 1000; /* nano -> pico seconds */
2952
+ rtt_report->rtt_sd = ltoh16_ua(&p_data_info->sd_rtt); /* nano -> 0.1 nano */
2953
+ DHD_RTT(("rtt_report->rtt : %llu\n", rtt_report->rtt));
2954
+ DHD_RTT(("rtt_report->rssi : %d (0.5db)\n", rtt_report->rssi));
2955
+
2956
+ /* average distance */
2957
+ if (avg_dist != FTM_INVALID) {
2958
+ rtt_report->distance = (avg_dist >> 8) * 1000; /* meter -> mm */
2959
+ rtt_report->distance += (avg_dist & 0xff) * 1000 / 256;
2960
+ /* rtt_sd is in 0.1 ns.
2961
+ * host needs distance_sd in milli mtrs
2962
+ * (0.1 * rtt_sd/2 * 10^-9) * C * 1000
2963
+ */
2964
+ rtt_report->distance_sd = rtt_report->rtt_sd * 15; /* mm */
2965
+ } else {
2966
+ rtt_report->distance = FTM_INVALID;
2967
+ }
2968
+ /* time stamp */
2969
+ /* get the time elapsed from boot time */
2970
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2971
+ get_monotonic_boottime(&ts);
2972
+ rtt_report->ts = (uint64)TIMESPEC_TO_US(ts);
2973
+#endif /* LINUX_VER >= 2.6.39 */
2974
+
2975
+ if (proxd_status == WL_PROXD_E_REMOTE_FAIL) {
2976
+ /* retry time after failure */
2977
+ p_time.intvl = ltoh32_ua(&p_data_info->u.retry_after.intvl);
2978
+ p_time.tmu = ltoh16_ua(&p_data_info->u.retry_after.tmu);
2979
+ rtt_report->retry_after_duration = FTM_INTVL2SEC(&p_time); /* s -> s */
2980
+ DHD_RTT((">\tretry_after: %d%s\n",
2981
+ ltoh32_ua(&p_data_info->u.retry_after.intvl),
2982
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_info->u.retry_after.tmu))));
2983
+ } else {
2984
+ /* burst duration */
2985
+ p_time.intvl = ltoh32_ua(&p_data_info->u.retry_after.intvl);
2986
+ p_time.tmu = ltoh16_ua(&p_data_info->u.retry_after.tmu);
2987
+ rtt_report->burst_duration = FTM_INTVL2MSEC(&p_time); /* s -> ms */
2988
+ DHD_RTT((">\tburst_duration: %d%s\n",
2989
+ ltoh32_ua(&p_data_info->u.burst_duration.intvl),
2990
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_info->u.burst_duration.tmu))));
2991
+ DHD_RTT(("rtt_report->burst_duration : %d\n", rtt_report->burst_duration));
2992
+ }
2993
+ /* display detail if available */
2994
+ num_rtt = ltoh16_ua(&p_data_info->num_rtt);
2995
+ if (num_rtt > 0) {
2996
+ DHD_RTT((">\tnum rtt: %d samples\n", num_rtt));
2997
+ p_sample = &p_data_info->rtt[1];
2998
+ for (i = 0; i < num_rtt; i++) {
2999
+ snr = 0;
3000
+ bitflips = 0;
3001
+ tof_phy_error = 0;
3002
+ tof_phy_tgt_error = 0;
3003
+ tof_target_snr = 0;
3004
+ tof_target_bitflips = 0;
3005
+ rssi = 0;
3006
+ dist = 0;
3007
+ num_ftm = p_data_info->num_ftm;
3008
+ /* FTM frames 1,4,7,11 have valid snr, rssi and bitflips */
3009
+ if ((i % num_ftm) == 1) {
3010
+ rssi = (wl_proxd_rssi_t) ltoh16_ua(&p_sample->rssi);
3011
+ snr = (wl_proxd_snr_t) ltoh16_ua(&p_sample->snr);
3012
+ bitflips = (wl_proxd_bitflips_t) ltoh16_ua(&p_sample->bitflips);
3013
+ tof_phy_error =
3014
+ (wl_proxd_phy_error_t)
3015
+ ltoh32_ua(&p_sample->tof_phy_error);
3016
+ tof_phy_tgt_error =
3017
+ (wl_proxd_phy_error_t)
3018
+ ltoh32_ua(&p_sample->tof_tgt_phy_error);
3019
+ tof_target_snr =
3020
+ (wl_proxd_snr_t)
3021
+ ltoh16_ua(&p_sample->tof_tgt_snr);
3022
+ tof_target_bitflips =
3023
+ (wl_proxd_bitflips_t)
3024
+ ltoh16_ua(&p_sample->tof_tgt_bitflips);
3025
+ dist = ltoh32_ua(&p_sample->distance);
3026
+ chanspec = ltoh32_ua(&p_sample->chanspec);
3027
+ } else {
3028
+ rssi = -1;
3029
+ snr = 0;
3030
+ bitflips = 0;
3031
+ dist = 0;
3032
+ tof_target_bitflips = 0;
3033
+ tof_target_snr = 0;
3034
+ tof_phy_tgt_error = 0;
3035
+ }
3036
+ DHD_RTT((">\t sample[%d]: id=%d rssi=%d snr=0x%x bitflips=%d"
3037
+ " tof_phy_error %x tof_phy_tgt_error %x target_snr=0x%x"
3038
+ " target_bitflips=%d dist=%d rtt=%d%s status %s Type %s"
3039
+ " coreid=%d chanspec=0x%08x\n",
3040
+ i, p_sample->id, rssi, snr,
3041
+ bitflips, tof_phy_error, tof_phy_tgt_error,
3042
+ tof_target_snr,
3043
+ tof_target_bitflips, dist,
3044
+ ltoh32_ua(&p_sample->rtt.intvl),
3045
+ ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)),
3046
+ ftm_status_value_to_logstr(ltoh32_ua(&p_sample->status)),
3047
+ ftm_frame_types[i % num_ftm], p_sample->coreid,
3048
+ chanspec));
3049
+ p_sample++;
3050
+ }
3051
+ }
3052
+ return err;
3053
+}
3054
+#ifdef WL_CFG80211
3055
+/* Common API for handling Session End.
3056
+* This API will flush out the results for a peer MAC.
3057
+*
3058
+* @For legacy FTM session, this API will be called
3059
+* when legacy FTM_SESSION_END event is received.
3060
+* @For legacy Nan-RTT , this API will be called when
3061
+* we are cancelling the nan-ranging session or on
3062
+* nan-ranging-end event.
3063
+*/
3064
+static void
3065
+dhd_rtt_handle_rtt_session_end(dhd_pub_t *dhd)
3066
+{
3067
+
3068
+ int idx;
3069
+ struct rtt_noti_callback *iter;
3070
+ rtt_results_header_t *entry, *next;
3071
+ rtt_result_t *next2;
3072
+ rtt_result_t *rtt_result;
3073
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
3074
+
3075
+ /* Cancel pending proxd timeout work if any */
3076
+ if (delayed_work_pending(&rtt_status->proxd_timeout)) {
3077
+ cancel_delayed_work(&rtt_status->proxd_timeout);
3078
+ }
3079
+
3080
+ /* find next target to trigger RTT */
3081
+ for (idx = (rtt_status->cur_idx + 1);
3082
+ idx < rtt_status->rtt_config.rtt_target_cnt; idx++) {
3083
+ /* skip the disabled device */
3084
+ if (rtt_status->rtt_config.target_info[idx].disable) {
3085
+ continue;
3086
+ } else {
3087
+ /* set the idx to cur_idx */
3088
+ rtt_status->cur_idx = idx;
3089
+ break;
3090
+ }
3091
+ }
3092
+ if (idx < rtt_status->rtt_config.rtt_target_cnt) {
3093
+ /* restart to measure RTT from next device */
3094
+ DHD_INFO(("restart to measure rtt\n"));
3095
+ schedule_work(&rtt_status->work);
3096
+ } else {
3097
+ DHD_RTT(("RTT_STOPPED\n"));
3098
+ rtt_status->status = RTT_STOPPED;
3099
+ /* notify the completed information to others */
3100
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
3101
+ list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
3102
+ iter->noti_fn(iter->ctx, &rtt_status->rtt_results_cache);
3103
+ }
3104
+ /* remove the rtt results in cache */
3105
+ if (!list_empty(&rtt_status->rtt_results_cache)) {
3106
+ /* Iterate rtt_results_header list */
3107
+ list_for_each_entry_safe(entry, next,
3108
+ &rtt_status->rtt_results_cache, list) {
3109
+ list_del(&entry->list);
3110
+ /* Iterate rtt_result list */
3111
+ list_for_each_entry_safe(rtt_result, next2,
3112
+ &entry->result_list, list) {
3113
+ list_del(&rtt_result->list);
3114
+ kfree(rtt_result);
3115
+ }
3116
+ kfree(entry);
3117
+ }
3118
+ }
3119
+ GCC_DIAGNOSTIC_POP();
3120
+ /* reinitialize the HEAD */
3121
+ INIT_LIST_HEAD(&rtt_status->rtt_results_cache);
3122
+ /* clear information for rtt_config */
3123
+ rtt_status->rtt_config.rtt_target_cnt = 0;
3124
+ memset_s(rtt_status->rtt_config.target_info, TARGET_INFO_SIZE(RTT_MAX_TARGET_CNT),
3125
+ 0, TARGET_INFO_SIZE(RTT_MAX_TARGET_CNT));
3126
+ rtt_status->cur_idx = 0;
3127
+ }
3128
+}
3129
+#endif /* WL_CFG80211 */
3130
+
3131
+#ifdef WL_CFG80211
3132
+static int
3133
+dhd_rtt_create_failure_result(rtt_status_info_t *rtt_status,
3134
+ struct ether_addr *addr)
3135
+{
3136
+ rtt_results_header_t *rtt_results_header = NULL;
3137
+ rtt_target_info_t *rtt_target_info;
3138
+ int ret = BCME_OK;
3139
+ rtt_result_t *rtt_result;
3140
+
3141
+ /* allocate new header for rtt_results */
3142
+ rtt_results_header = (rtt_results_header_t *)MALLOCZ(rtt_status->dhd->osh,
3143
+ sizeof(rtt_results_header_t));
3144
+ if (!rtt_results_header) {
3145
+ ret = -ENOMEM;
3146
+ goto exit;
3147
+ }
3148
+ rtt_target_info = &rtt_status->rtt_config.target_info[rtt_status->cur_idx];
3149
+ /* Initialize the head of list for rtt result */
3150
+ INIT_LIST_HEAD(&rtt_results_header->result_list);
3151
+ /* same src and dest len */
3152
+ (void)memcpy_s(&rtt_results_header->peer_mac,
3153
+ ETHER_ADDR_LEN, addr, ETHER_ADDR_LEN);
3154
+ list_add_tail(&rtt_results_header->list, &rtt_status->rtt_results_cache);
3155
+
3156
+ /* allocate rtt_results for new results */
3157
+ rtt_result = (rtt_result_t *)MALLOCZ(rtt_status->dhd->osh,
3158
+ sizeof(rtt_result_t));
3159
+ if (!rtt_result) {
3160
+ ret = -ENOMEM;
3161
+ kfree(rtt_results_header);
3162
+ goto exit;
3163
+ }
3164
+ /* fill out the results from the configuration param */
3165
+ rtt_result->report.ftm_num = rtt_target_info->num_frames_per_burst;
3166
+ rtt_result->report.type = RTT_TWO_WAY;
3167
+ DHD_RTT(("report->ftm_num : %d\n", rtt_result->report.ftm_num));
3168
+ rtt_result->report_len = RTT_REPORT_SIZE;
3169
+ rtt_result->report.status = RTT_STATUS_FAIL_NO_RSP;
3170
+ /* same src and dest len */
3171
+ (void)memcpy_s(&rtt_result->report.addr, ETHER_ADDR_LEN,
3172
+ &rtt_target_info->addr, ETHER_ADDR_LEN);
3173
+ rtt_result->report.distance = FTM_INVALID;
3174
+ list_add_tail(&rtt_result->list, &rtt_results_header->result_list);
3175
+ rtt_results_header->result_cnt++;
3176
+ rtt_results_header->result_tot_len += rtt_result->report_len;
3177
+exit:
3178
+ return ret;
3179
+}
3180
+
3181
+static bool
3182
+dhd_rtt_get_report_header(rtt_status_info_t *rtt_status,
3183
+ rtt_results_header_t **rtt_results_header, struct ether_addr *addr)
3184
+{
3185
+ rtt_results_header_t *entry;
3186
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
3187
+ /* find a rtt_report_header for this mac address */
3188
+ list_for_each_entry(entry, &rtt_status->rtt_results_cache, list) {
3189
+ GCC_DIAGNOSTIC_POP();
3190
+ if (!memcmp(&entry->peer_mac, addr, ETHER_ADDR_LEN)) {
3191
+ /* found a rtt_report_header for peer_mac in the list */
3192
+ if (rtt_results_header) {
3193
+ *rtt_results_header = entry;
3194
+ }
3195
+ return TRUE;
3196
+ }
3197
+ }
3198
+ return FALSE;
3199
+}
3200
+
3201
+int
3202
+dhd_rtt_handle_nan_rtt_session_end(dhd_pub_t *dhd, struct ether_addr *peer)
3203
+{
3204
+ bool is_new = TRUE;
3205
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
3206
+ mutex_lock(&rtt_status->rtt_mutex);
3207
+ is_new = !dhd_rtt_get_report_header(rtt_status, NULL, peer);
3208
+
3209
+ if (is_new) { /* no FTM result..create failure result */
3210
+ dhd_rtt_create_failure_result(rtt_status, peer);
3211
+ }
3212
+ dhd_rtt_handle_rtt_session_end(dhd);
3213
+ mutex_unlock(&rtt_status->rtt_mutex);
3214
+ return BCME_OK;
3215
+}
3216
+#endif /* WL_CFG80211 */
3217
+
3218
+static bool
3219
+dhd_rtt_is_valid_measurement(rtt_result_t *rtt_result)
3220
+{
3221
+ bool ret = FALSE;
3222
+
3223
+ if (rtt_result && (rtt_result->report.success_num != 0)) {
3224
+ ret = TRUE;
3225
+ }
3226
+ return ret;
3227
+}
3228
+
3229
+static int
3230
+dhd_rtt_parse_result_event(wl_proxd_event_t *proxd_ev_data,
3231
+ int tlvs_len, rtt_result_t *rtt_result)
3232
+{
3233
+ int ret = BCME_OK;
3234
+
3235
+ /* unpack TLVs and invokes the cbfn to print the event content TLVs */
3236
+ ret = bcm_unpack_xtlv_buf((void *) rtt_result,
3237
+ (uint8 *)&proxd_ev_data->tlvs[0], tlvs_len,
3238
+ BCM_XTLV_OPTION_ALIGN32, rtt_unpack_xtlv_cbfn);
3239
+ if (ret != BCME_OK) {
3240
+ DHD_RTT_ERR(("%s : Failed to unpack xtlv for an event\n",
3241
+ __FUNCTION__));
3242
+ goto exit;
3243
+ }
3244
+ /* fill out the results from the configuration param */
3245
+ rtt_result->report.type = RTT_TWO_WAY;
3246
+ DHD_RTT(("report->ftm_num : %d\n", rtt_result->report.ftm_num));
3247
+ rtt_result->report_len = RTT_REPORT_SIZE;
3248
+ rtt_result->detail_len = sizeof(rtt_result->rtt_detail);
3249
+
3250
+exit:
3251
+ return ret;
3252
+
3253
+}
3254
+
3255
+static int
3256
+dhd_rtt_handle_directed_rtt_burst_end(dhd_pub_t *dhd, struct ether_addr *peer_addr,
3257
+ wl_proxd_event_t *proxd_ev_data, int tlvs_len, rtt_result_t *rtt_result, bool is_nan)
3258
+{
3259
+ rtt_status_info_t *rtt_status;
3260
+ rtt_results_header_t *rtt_results_header = NULL;
3261
+ bool is_new = TRUE;
3262
+ int ret = BCME_OK;
3263
+ int err_at = 0;
3264
+
3265
+ rtt_status = GET_RTTSTATE(dhd);
3266
+ is_new = !dhd_rtt_get_report_header(rtt_status,
3267
+ &rtt_results_header, peer_addr);
3268
+
3269
+ if (tlvs_len > 0) {
3270
+ if (is_new) {
3271
+ /* allocate new header for rtt_results */
3272
+ rtt_results_header = (rtt_results_header_t *)MALLOCZ(rtt_status->dhd->osh,
3273
+ sizeof(rtt_results_header_t));
3274
+ if (!rtt_results_header) {
3275
+ ret = BCME_NORESOURCE;
3276
+ err_at = 1;
3277
+ goto exit;
3278
+ }
3279
+ /* Initialize the head of list for rtt result */
3280
+ INIT_LIST_HEAD(&rtt_results_header->result_list);
3281
+ /* same src and header len */
3282
+ (void)memcpy_s(&rtt_results_header->peer_mac, ETHER_ADDR_LEN,
3283
+ peer_addr, ETHER_ADDR_LEN);
3284
+ list_add_tail(&rtt_results_header->list, &rtt_status->rtt_results_cache);
3285
+ }
3286
+
3287
+ ret = dhd_rtt_parse_result_event(proxd_ev_data, tlvs_len, rtt_result);
3288
+ if ((ret == BCME_OK) && ((!is_nan) ||
3289
+ dhd_rtt_is_valid_measurement(rtt_result))) {
3290
+ /*
3291
+ * Add to list, if non-nan RTT (legacy) or
3292
+ * valid measurement in nan rtt case
3293
+ */
3294
+ list_add_tail(&rtt_result->list, &rtt_results_header->result_list);
3295
+ rtt_results_header->result_cnt++;
3296
+ rtt_results_header->result_tot_len += rtt_result->report_len +
3297
+ rtt_result->detail_len;
3298
+ } else {
3299
+ err_at = 2;
3300
+ if (ret == BCME_OK) {
3301
+ /* Case for nan rtt invalid measurement */
3302
+ ret = BCME_ERROR;
3303
+ err_at = 3;
3304
+ }
3305
+ goto exit;
3306
+ }
3307
+ } else {
3308
+ ret = BCME_ERROR;
3309
+ err_at = 4;
3310
+ goto exit;
3311
+ }
3312
+
3313
+exit:
3314
+ if (ret != BCME_OK) {
3315
+ DHD_RTT_ERR(("dhd_rtt_handle_directed_rtt_burst_end: failed, "
3316
+ " ret = %d, err_at = %d\n", ret, err_at));
3317
+ if (rtt_results_header) {
3318
+ list_del(&rtt_results_header->list);
3319
+ kfree(rtt_results_header);
3320
+ rtt_results_header = NULL;
3321
+ }
3322
+ }
3323
+ return ret;
3324
+}
3325
+
3326
+#ifdef WL_NAN
3327
+static void
3328
+dhd_rtt_nan_range_report(struct bcm_cfg80211 *cfg,
3329
+ rtt_result_t *rtt_result)
3330
+{
3331
+ wl_nan_ev_rng_rpt_ind_t range_res;
3332
+ nan_ranging_inst_t *rng_inst = NULL;
3333
+ dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
3334
+ rtt_status_info_t *rtt_status = GET_RTTSTATE(dhd);
3335
+
3336
+ UNUSED_PARAMETER(range_res);
3337
+
3338
+ if (!dhd_rtt_is_valid_measurement(rtt_result)) {
3339
+ /* Drop Invalid Measurements for NAN RTT report */
3340
+ DHD_RTT(("dhd_rtt_nan_range_report: Drop Invalid Measurements\n"));
3341
+ return;
3342
+ }
3343
+ bzero(&range_res, sizeof(range_res));
3344
+ range_res.indication = 0;
3345
+ range_res.dist_mm = rtt_result->report.distance;
3346
+ /* same src and header len, ignoring ret val here */
3347
+ (void)memcpy_s(&range_res.peer_m_addr, ETHER_ADDR_LEN,
3348
+ &rtt_result->report.addr, ETHER_ADDR_LEN);
3349
+ wl_cfgnan_process_range_report(cfg, &range_res);
3350
+ /*
3351
+ * suspend geofence ranging for this target
3352
+ * and move to next target
3353
+ * after valid measurement for the target
3354
+ */
3355
+ rng_inst = wl_cfgnan_check_for_ranging(cfg, &range_res.peer_m_addr);
3356
+ if (rng_inst) {
3357
+ wl_cfgnan_suspend_geofence_rng_session(bcmcfg_to_prmry_ndev(cfg),
3358
+ &rng_inst->peer_addr, RTT_GEO_SUSPN_RANGE_RES_REPORTED, 0);
3359
+ GEOFENCE_RTT_LOCK(rtt_status);
3360
+ dhd_rtt_move_geofence_cur_target_idx_to_next(dhd);
3361
+ GEOFENCE_RTT_UNLOCK(rtt_status);
3362
+ wl_cfgnan_reset_geofence_ranging(cfg,
3363
+ rng_inst, RTT_SCHED_RNG_RPT_GEOFENCE);
3364
+ }
3365
+}
3366
+
3367
+static int
3368
+dhd_rtt_handle_nan_burst_end(dhd_pub_t *dhd, struct ether_addr *peer_addr,
3369
+ wl_proxd_event_t *proxd_ev_data, int tlvs_len)
3370
+{
3371
+ struct net_device *ndev = NULL;
3372
+ struct bcm_cfg80211 *cfg = NULL;
3373
+ nan_ranging_inst_t *rng_inst = NULL;
3374
+ rtt_status_info_t *rtt_status = NULL;
3375
+ rtt_result_t *rtt_result = NULL;
3376
+ bool is_geofence = FALSE;
3377
+ int ret = BCME_OK;
3378
+
3379
+ ndev = dhd_linux_get_primary_netdev(dhd);
3380
+ cfg = wiphy_priv(ndev->ieee80211_ptr->wiphy);
3381
+
3382
+ rtt_status = GET_RTTSTATE(dhd);
3383
+ NULL_CHECK(rtt_status, "rtt_status is NULL", ret);
3384
+ NAN_MUTEX_LOCK();
3385
+ mutex_lock(&rtt_status->rtt_mutex);
3386
+
3387
+ if ((cfg->nan_enable == FALSE) ||
3388
+ ETHER_ISNULLADDR(peer_addr)) {
3389
+ DHD_RTT_ERR(("Received Burst End with NULL ether addr, "
3390
+ "or nan disable, nan_enable = %d\n", cfg->nan_enable));
3391
+ ret = BCME_UNSUPPORTED;
3392
+ goto exit;
3393
+ }
3394
+
3395
+ rng_inst = wl_cfgnan_check_for_ranging(cfg, peer_addr);
3396
+ if (rng_inst) {
3397
+ is_geofence = (rng_inst->range_type
3398
+ == RTT_TYPE_NAN_GEOFENCE);
3399
+ } else {
3400
+ DHD_RTT_ERR(("Received Burst End without Ranging Instance\n"));
3401
+ ret = BCME_ERROR;
3402
+ goto exit;
3403
+ }
3404
+
3405
+ /* allocate rtt_results for new results */
3406
+ rtt_result = (rtt_result_t *)MALLOCZ(dhd->osh, sizeof(rtt_result_t));
3407
+ if (!rtt_result) {
3408
+ ret = BCME_NORESOURCE;
3409
+ goto exit;
3410
+ }
3411
+
3412
+ if (is_geofence) {
3413
+ ret = dhd_rtt_parse_result_event(proxd_ev_data, tlvs_len, rtt_result);
3414
+ if (ret != BCME_OK) {
3415
+ DHD_RTT_ERR(("avilog: dhd_rtt_handle_nan_burst_end: "
3416
+ "dhd_rtt_parse_result_event failed\n"));
3417
+ goto exit;
3418
+ }
3419
+ } else {
3420
+ if (RTT_IS_STOPPED(rtt_status)) {
3421
+ /* Ignore the Proxd event */
3422
+ DHD_RTT((" event handler rtt is stopped \n"));
3423
+ if (rtt_status->flags == WL_PROXD_SESSION_FLAG_TARGET) {
3424
+ DHD_RTT(("Device is target/Responder. Recv the event. \n"));
3425
+ } else {
3426
+ ret = BCME_UNSUPPORTED;
3427
+ goto exit;
3428
+ }
3429
+ }
3430
+ ret = dhd_rtt_handle_directed_rtt_burst_end(dhd, peer_addr,
3431
+ proxd_ev_data, tlvs_len, rtt_result, TRUE);
3432
+ if (ret != BCME_OK) {
3433
+ goto exit;
3434
+ }
3435
+
3436
+ }
3437
+
3438
+exit:
3439
+ mutex_unlock(&rtt_status->rtt_mutex);
3440
+ if (ret == BCME_OK) {
3441
+ dhd_rtt_nan_range_report(cfg, rtt_result);
3442
+ }
3443
+ if (rtt_result &&
3444
+ ((ret != BCME_OK) || is_geofence)) {
3445
+ kfree(rtt_result);
3446
+ rtt_result = NULL;
3447
+ }
3448
+ NAN_MUTEX_UNLOCK();
3449
+ return ret;
3450
+}
3451
+#endif /* WL_NAN */
16363452
16373453 int
16383454 dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)
16393455 {
16403456 int ret = BCME_OK;
16413457 int tlvs_len;
1642
- int idx;
16433458 uint16 version;
16443459 wl_proxd_event_t *p_event;
16453460 wl_proxd_event_type_t event_type;
16463461 wl_proxd_ftm_session_status_t session_status;
16473462 const ftm_strmap_entry_t *p_loginfo;
3463
+ rtt_result_t *rtt_result;
3464
+#ifdef WL_CFG80211
16483465 rtt_status_info_t *rtt_status;
1649
- rtt_target_info_t *rtt_target_info;
1650
- struct rtt_noti_callback *iter;
1651
- rtt_results_header_t *entry, *next, *rtt_results_header = NULL;
1652
- rtt_result_t *rtt_result, *next2;
1653
- gfp_t kflags;
3466
+ rtt_results_header_t *rtt_results_header = NULL;
16543467 bool is_new = TRUE;
3468
+#endif /* WL_CFG80211 */
16553469
3470
+ DHD_RTT(("Enter %s \n", __FUNCTION__));
16563471 NULL_CHECK(dhd, "dhd is NULL", ret);
1657
- rtt_status = GET_RTTSTATE(dhd);
1658
- NULL_CHECK(rtt_status, "rtt_status is NULL", ret);
16593472
16603473 if (ntoh32_ua((void *)&event->datalen) < OFFSETOF(wl_proxd_event_t, tlvs)) {
16613474 DHD_RTT(("%s: wrong datalen:%d\n", __FUNCTION__,
....@@ -1664,46 +3477,37 @@
16643477 }
16653478 event_type = ntoh32_ua((void *)&event->event_type);
16663479 if (event_type != WLC_E_PROXD) {
1667
- DHD_ERROR((" failed event \n"));
3480
+ DHD_RTT_ERR((" failed event \n"));
16683481 return -EINVAL;
16693482 }
16703483
16713484 if (!event_data) {
1672
- DHD_ERROR(("%s: event_data:NULL\n", __FUNCTION__));
3485
+ DHD_RTT_ERR(("%s: event_data:NULL\n", __FUNCTION__));
16733486 return -EINVAL;
1674
- }
1675
-
1676
- if (RTT_IS_STOPPED(rtt_status)) {
1677
- /* Ignore the Proxd event */
1678
- return ret;
16793487 }
16803488 p_event = (wl_proxd_event_t *) event_data;
16813489 version = ltoh16(p_event->version);
16823490 if (version < WL_PROXD_API_VERSION) {
1683
- DHD_ERROR(("ignore non-ftm event version = 0x%0x < WL_PROXD_API_VERSION (0x%x)\n",
3491
+ DHD_RTT_ERR(("ignore non-ftm event version = 0x%0x < WL_PROXD_API_VERSION (0x%x)\n",
16843492 version, WL_PROXD_API_VERSION));
16853493 return ret;
16863494 }
1687
- if (!in_atomic()) {
1688
- mutex_lock(&rtt_status->rtt_mutex);
1689
- }
1690
- event_type = (wl_proxd_event_type_t) ltoh16(p_event->type);
16913495
1692
- kflags = in_softirq()? GFP_ATOMIC : GFP_KERNEL;
3496
+ event_type = (wl_proxd_event_type_t) ltoh16(p_event->type);
16933497
16943498 DHD_RTT(("event_type=0x%x, ntoh16()=0x%x, ltoh16()=0x%x\n",
16953499 p_event->type, ntoh16(p_event->type), ltoh16(p_event->type)));
16963500 p_loginfo = ftm_get_event_type_loginfo(event_type);
16973501 if (p_loginfo == NULL) {
1698
- DHD_ERROR(("receive an invalid FTM event %d\n", event_type));
3502
+ DHD_RTT_ERR(("receive an invalid FTM event %d\n", event_type));
16993503 ret = -EINVAL;
1700
- goto exit; /* ignore this event */
3504
+ return ret; /* ignore this event */
17013505 }
17023506 /* get TLVs len, skip over event header */
17033507 if (ltoh16(p_event->len) < OFFSETOF(wl_proxd_event_t, tlvs)) {
1704
- DHD_ERROR(("invalid FTM event length:%d\n", ltoh16(p_event->len)));
3508
+ DHD_RTT_ERR(("invalid FTM event length:%d\n", ltoh16(p_event->len)));
17053509 ret = -EINVAL;
1706
- goto exit;
3510
+ return ret;
17073511 }
17083512 tlvs_len = ltoh16(p_event->len) - OFFSETOF(wl_proxd_event_t, tlvs);
17093513 DHD_RTT(("receive '%s' event: version=0x%x len=%d method=%d sid=%d tlvs_len=%d\n",
....@@ -1713,17 +3517,38 @@
17133517 ltoh16(p_event->method),
17143518 ltoh16(p_event->sid),
17153519 tlvs_len));
1716
- rtt_target_info = &rtt_status->rtt_config.target_info[rtt_status->cur_idx];
1717
- /* find a rtt_report_header for this mac address */
1718
- list_for_each_entry(entry, &rtt_status->rtt_results_cache, list) {
1719
- if (!memcmp(&entry->peer_mac, &event->addr, ETHER_ADDR_LEN)) {
1720
- /* found a rtt_report_header for peer_mac in the list */
1721
- is_new = FALSE;
1722
- rtt_results_header = entry;
1723
- break;
1724
- }
3520
+#ifdef WL_CFG80211
3521
+#ifdef WL_NAN
3522
+ if ((event_type == WL_PROXD_EVENT_BURST_END) &&
3523
+ dhd_rtt_is_nan_peer(dhd, &event->addr)) {
3524
+ DHD_RTT(("WL_PROXD_EVENT_BURST_END for NAN RTT\n"));
3525
+ ret = dhd_rtt_handle_nan_burst_end(dhd, &event->addr, p_event, tlvs_len);
3526
+ return ret;
17253527 }
3528
+#endif /* WL_NAN */
17263529
3530
+ rtt_status = GET_RTTSTATE(dhd);
3531
+ NULL_CHECK(rtt_status, "rtt_status is NULL", ret);
3532
+ mutex_lock(&rtt_status->rtt_mutex);
3533
+
3534
+ if (RTT_IS_STOPPED(rtt_status)) {
3535
+ /* Ignore the Proxd event */
3536
+ DHD_RTT((" event handler rtt is stopped \n"));
3537
+ if (rtt_status->flags == WL_PROXD_SESSION_FLAG_TARGET) {
3538
+ DHD_RTT(("Device is target/Responder. Recv the event. \n"));
3539
+ } else {
3540
+ ret = BCME_NOTREADY;
3541
+ goto exit;
3542
+ }
3543
+ }
3544
+#endif /* WL_CFG80211 */
3545
+
3546
+#ifdef WL_CFG80211
3547
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
3548
+ is_new = !dhd_rtt_get_report_header(rtt_status,
3549
+ &rtt_results_header, &event->addr);
3550
+ GCC_DIAGNOSTIC_POP();
3551
+#endif /* WL_CFG80211 */
17273552 switch (event_type) {
17283553 case WL_PROXD_EVENT_SESSION_CREATE:
17293554 DHD_RTT(("WL_PROXD_EVENT_SESSION_CREATE\n"));
....@@ -1735,143 +3560,55 @@
17353560 DHD_RTT(("WL_PROXD_EVENT_BURST_START\n"));
17363561 break;
17373562 case WL_PROXD_EVENT_BURST_END:
1738
- DHD_RTT(("WL_PROXD_EVENT_BURST_END\n"));
1739
- if (is_new) {
1740
- /* allocate new header for rtt_results */
1741
- rtt_results_header = kzalloc(sizeof(rtt_results_header_t), kflags);
1742
- if (!rtt_results_header) {
1743
- ret = -ENOMEM;
1744
- goto exit;
1745
- }
1746
- /* Initialize the head of list for rtt result */
1747
- INIT_LIST_HEAD(&rtt_results_header->result_list);
1748
- rtt_results_header->peer_mac = event->addr;
1749
- list_add_tail(&rtt_results_header->list, &rtt_status->rtt_results_cache);
3563
+ DHD_RTT(("WL_PROXD_EVENT_BURST_END for Legacy RTT\n"));
3564
+ /* allocate rtt_results for new legacy rtt results */
3565
+ rtt_result = (rtt_result_t *)MALLOCZ(dhd->osh, sizeof(rtt_result_t));
3566
+ if (!rtt_result) {
3567
+ ret = -ENOMEM;
3568
+ goto exit;
17503569 }
1751
- if (tlvs_len > 0) {
1752
- /* allocate rtt_results for new results */
1753
- rtt_result = kzalloc(sizeof(rtt_result_t), kflags);
1754
- if (!rtt_result) {
1755
- ret = -ENOMEM;
1756
- goto exit;
1757
- }
1758
- /* unpack TLVs and invokes the cbfn to print the event content TLVs */
1759
- ret = bcm_unpack_xtlv_buf((void *) &(rtt_result->report),
1760
- (uint8 *)&p_event->tlvs[0], tlvs_len,
1761
- BCM_XTLV_OPTION_ALIGN32, rtt_unpack_xtlv_cbfn);
1762
- if (ret != BCME_OK) {
1763
- DHD_ERROR(("%s : Failed to unpack xtlv for an event\n",
1764
- __FUNCTION__));
1765
- goto exit;
1766
- }
1767
- /* fill out the results from the configuration param */
1768
- rtt_result->report.ftm_num = rtt_target_info->num_frames_per_burst;
1769
- rtt_result->report.type = RTT_TWO_WAY;
1770
- DHD_RTT(("report->ftm_num : %d\n", rtt_result->report.ftm_num));
1771
- rtt_result->report_len = RTT_REPORT_SIZE;
1772
-
1773
- list_add_tail(&rtt_result->list, &rtt_results_header->result_list);
1774
- rtt_results_header->result_cnt++;
1775
- rtt_results_header->result_tot_len += rtt_result->report_len;
3570
+ ret = dhd_rtt_handle_directed_rtt_burst_end(dhd, &event->addr,
3571
+ p_event, tlvs_len, rtt_result, FALSE);
3572
+ if (rtt_result && (ret != BCME_OK)) {
3573
+ kfree(rtt_result);
3574
+ rtt_result = NULL;
3575
+ goto exit;
17763576 }
17773577 break;
17783578 case WL_PROXD_EVENT_SESSION_END:
1779
- DHD_RTT(("WL_PROXD_EVENT_SESSION_END\n"));
3579
+ DHD_RTT(("WL_PROXD_EVENT_SESSION_END\n"));
3580
+ if (dhd_rtt_is_nan_peer(dhd, &event->addr)) {
3581
+ /*
3582
+ * Nothing to do for session end for nan peer
3583
+ * All taken care in burst end and nan rng rep
3584
+ */
3585
+ break;
3586
+ }
3587
+#ifdef WL_CFG80211
17803588 if (!RTT_IS_ENABLED(rtt_status)) {
17813589 DHD_RTT(("Ignore the session end evt\n"));
17823590 goto exit;
17833591 }
3592
+#endif /* WL_CFG80211 */
17843593 if (tlvs_len > 0) {
17853594 /* unpack TLVs and invokes the cbfn to print the event content TLVs */
17863595 ret = bcm_unpack_xtlv_buf((void *) &session_status,
17873596 (uint8 *)&p_event->tlvs[0], tlvs_len,
17883597 BCM_XTLV_OPTION_ALIGN32, rtt_unpack_xtlv_cbfn);
17893598 if (ret != BCME_OK) {
1790
- DHD_ERROR(("%s : Failed to unpack xtlv for an event\n",
3599
+ DHD_RTT_ERR(("%s : Failed to unpack xtlv for an event\n",
17913600 __FUNCTION__));
17923601 goto exit;
17933602 }
17943603 }
3604
+#ifdef WL_CFG80211
17953605 /* In case of no result for the peer device, make fake result for error case */
17963606 if (is_new) {
1797
- /* allocate new header for rtt_results */
1798
- rtt_results_header = kzalloc(sizeof(rtt_results_header_t), GFP_KERNEL);
1799
- if (!rtt_results_header) {
1800
- ret = -ENOMEM;
1801
- goto exit;
1802
- }
1803
- /* Initialize the head of list for rtt result */
1804
- INIT_LIST_HEAD(&rtt_results_header->result_list);
1805
- rtt_results_header->peer_mac = event->addr;
1806
- list_add_tail(&rtt_results_header->list, &rtt_status->rtt_results_cache);
1807
-
1808
- /* allocate rtt_results for new results */
1809
- rtt_result = kzalloc(sizeof(rtt_result_t), kflags);
1810
- if (!rtt_result) {
1811
- ret = -ENOMEM;
1812
- kfree(rtt_results_header);
1813
- goto exit;
1814
- }
1815
- /* fill out the results from the configuration param */
1816
- rtt_result->report.ftm_num = rtt_target_info->num_frames_per_burst;
1817
- rtt_result->report.type = RTT_TWO_WAY;
1818
- DHD_RTT(("report->ftm_num : %d\n", rtt_result->report.ftm_num));
1819
- rtt_result->report_len = RTT_REPORT_SIZE;
1820
- rtt_result->report.status = RTT_REASON_FAIL_NO_RSP;
1821
- rtt_result->report.addr = rtt_target_info->addr;
1822
- rtt_result->report.distance = FTM_INVALID;
1823
- list_add_tail(&rtt_result->list, &rtt_results_header->result_list);
1824
- rtt_results_header->result_cnt++;
1825
- rtt_results_header->result_tot_len += rtt_result->report_len;
3607
+ dhd_rtt_create_failure_result(rtt_status, &event->addr);
18263608 }
1827
- /* find next target to trigger RTT */
1828
- for (idx = (rtt_status->cur_idx + 1);
1829
- idx < rtt_status->rtt_config.rtt_target_cnt; idx++) {
1830
- /* skip the disabled device */
1831
- if (rtt_status->rtt_config.target_info[idx].disable) {
1832
- continue;
1833
- } else {
1834
- /* set the idx to cur_idx */
1835
- rtt_status->cur_idx = idx;
1836
- break;
1837
- }
1838
- }
1839
- if (idx < rtt_status->rtt_config.rtt_target_cnt) {
1840
- /* restart to measure RTT from next device */
1841
- schedule_work(&rtt_status->work);
1842
- } else {
1843
- DHD_RTT(("RTT_STOPPED\n"));
1844
- rtt_status->status = RTT_STOPPED;
1845
- /* to turn on mpc mode */
1846
- schedule_work(&rtt_status->work);
1847
- /* notify the completed information to others */
1848
- list_for_each_entry(iter, &rtt_status->noti_fn_list, list) {
1849
- iter->noti_fn(iter->ctx, &rtt_status->rtt_results_cache);
1850
- }
1851
- /* remove the rtt results in cache */
1852
- if (!list_empty(&rtt_status->rtt_results_cache)) {
1853
- /* Iterate rtt_results_header list */
1854
- list_for_each_entry_safe(entry, next,
1855
- &rtt_status->rtt_results_cache, list) {
1856
- list_del(&entry->list);
1857
- /* Iterate rtt_result list */
1858
- list_for_each_entry_safe(rtt_result, next2,
1859
- &entry->result_list, list) {
1860
- list_del(&rtt_result->list);
1861
- kfree(rtt_result);
1862
- }
1863
- kfree(entry);
1864
- }
1865
- }
1866
-
1867
- /* reinitialize the HEAD */
1868
- INIT_LIST_HEAD(&rtt_status->rtt_results_cache);
1869
- /* clear information for rtt_config */
1870
- rtt_status->rtt_config.rtt_target_cnt = 0;
1871
- memset(rtt_status->rtt_config.target_info, 0,
1872
- TARGET_INFO_SIZE(RTT_MAX_TARGET_CNT));
1873
- rtt_status->cur_idx = 0;
1874
- }
3609
+ DHD_RTT(("\n Not Nan peer..proceed to notify result and restart\n"));
3610
+ dhd_rtt_handle_rtt_session_end(dhd);
3611
+#endif /* WL_CFG80211 */
18753612 break;
18763613 case WL_PROXD_EVENT_SESSION_RESTART:
18773614 DHD_RTT(("WL_PROXD_EVENT_SESSION_RESTART\n"));
....@@ -1894,36 +3631,78 @@
18943631 case WL_PROXD_EVENT_RANGING:
18953632 DHD_RTT(("WL_PROXD_EVENT_RANGING\n"));
18963633 break;
3634
+ case WL_PROXD_EVENT_COLLECT:
3635
+ DHD_RTT(("WL_PROXD_EVENT_COLLECT\n"));
3636
+ if (tlvs_len > 0) {
3637
+ void *buffer = NULL;
3638
+ if (!(buffer = (void *)MALLOCZ(dhd->osh, tlvs_len))) {
3639
+ ret = -ENOMEM;
3640
+ goto exit;
3641
+ }
3642
+ /* unpack TLVs and invokes the cbfn to print the event content TLVs */
3643
+ ret = bcm_unpack_xtlv_buf(buffer,
3644
+ (uint8 *)&p_event->tlvs[0], tlvs_len,
3645
+ BCM_XTLV_OPTION_NONE, rtt_unpack_xtlv_cbfn);
3646
+ kfree(buffer);
3647
+ if (ret != BCME_OK) {
3648
+ DHD_RTT_ERR(("%s : Failed to unpack xtlv for event %d\n",
3649
+ __FUNCTION__, event_type));
3650
+ goto exit;
3651
+ }
3652
+ }
3653
+ break;
3654
+ case WL_PROXD_EVENT_MF_STATS:
3655
+ DHD_RTT(("WL_PROXD_EVENT_MF_STATS\n"));
3656
+ if (tlvs_len > 0) {
3657
+ void *buffer = NULL;
3658
+ if (!(buffer = (void *)MALLOCZ(dhd->osh, tlvs_len))) {
3659
+ ret = -ENOMEM;
3660
+ goto exit;
3661
+ }
3662
+ /* unpack TLVs and invokes the cbfn to print the event content TLVs */
3663
+ ret = bcm_unpack_xtlv_buf(buffer,
3664
+ (uint8 *)&p_event->tlvs[0], tlvs_len,
3665
+ BCM_XTLV_OPTION_NONE, rtt_unpack_xtlv_cbfn);
3666
+ kfree(buffer);
3667
+ if (ret != BCME_OK) {
3668
+ DHD_RTT_ERR(("%s : Failed to unpack xtlv for event %d\n",
3669
+ __FUNCTION__, event_type));
3670
+ goto exit;
3671
+ }
3672
+ }
3673
+ break;
18973674
18983675 default:
1899
- DHD_ERROR(("WLC_E_PROXD: not supported EVENT Type:%d\n", event_type));
3676
+ DHD_RTT_ERR(("WLC_E_PROXD: not supported EVENT Type:%d\n", event_type));
19003677 break;
19013678 }
19023679 exit:
1903
- if (!in_atomic()) {
1904
- mutex_unlock(&rtt_status->rtt_mutex);
1905
- }
3680
+#ifdef WL_CFG80211
3681
+ mutex_unlock(&rtt_status->rtt_mutex);
3682
+#endif /* WL_CFG80211 */
19063683
19073684 return ret;
19083685 }
19093686
3687
+#ifdef WL_CFG80211
19103688 static void
19113689 dhd_rtt_work(struct work_struct *work)
19123690 {
19133691 rtt_status_info_t *rtt_status;
19143692 dhd_pub_t *dhd;
3693
+
3694
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
19153695 rtt_status = container_of(work, rtt_status_info_t, work);
1916
- if (rtt_status == NULL) {
1917
- DHD_ERROR(("%s : rtt_status is NULL\n", __FUNCTION__));
1918
- return;
1919
- }
3696
+ GCC_DIAGNOSTIC_POP();
3697
+
19203698 dhd = rtt_status->dhd;
19213699 if (dhd == NULL) {
1922
- DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__));
3700
+ DHD_RTT_ERR(("%s : dhd is NULL\n", __FUNCTION__));
19233701 return;
19243702 }
19253703 (void) dhd_rtt_start(dhd);
19263704 }
3705
+#endif /* WL_CFG80211 */
19273706
19283707 int
19293708 dhd_rtt_capability(dhd_pub_t *dhd, rtt_capabilities_t *capa)
....@@ -1935,29 +3714,22 @@
19353714 NULL_CHECK(rtt_status, "rtt_status is NULL", err);
19363715 NULL_CHECK(capa, "capa is NULL", err);
19373716 bzero(capa, sizeof(rtt_capabilities_t));
1938
- switch (rtt_status->rtt_capa.proto) {
1939
- case RTT_CAP_ONE_WAY:
1940
- capa->rtt_one_sided_supported = 1;
1941
- break;
1942
- case RTT_CAP_FTM_WAY:
1943
- capa->rtt_ftm_supported = 1;
1944
- break;
1945
- }
19463717
1947
- switch (rtt_status->rtt_capa.feature) {
1948
- case RTT_FEATURE_LCI:
3718
+ /* set rtt capabilities */
3719
+ if (rtt_status->rtt_capa.proto & RTT_CAP_ONE_WAY)
3720
+ capa->rtt_one_sided_supported = 1;
3721
+ if (rtt_status->rtt_capa.proto & RTT_CAP_FTM_WAY)
3722
+ capa->rtt_ftm_supported = 1;
3723
+
3724
+ if (rtt_status->rtt_capa.feature & RTT_FEATURE_LCI)
19493725 capa->lci_support = 1;
1950
- break;
1951
- case RTT_FEATURE_LCR:
3726
+ if (rtt_status->rtt_capa.feature & RTT_FEATURE_LCR)
19523727 capa->lcr_support = 1;
1953
- break;
1954
- case RTT_FEATURE_PREAMBLE:
3728
+ if (rtt_status->rtt_capa.feature & RTT_FEATURE_PREAMBLE)
19553729 capa->preamble_support = 1;
1956
- break;
1957
- case RTT_FEATURE_BW:
3730
+ if (rtt_status->rtt_capa.feature & RTT_FEATURE_BW)
19583731 capa->bw_support = 1;
1959
- break;
1960
- }
3732
+
19613733 /* bit mask */
19623734 capa->preamble_support = rtt_status->rtt_capa.preamble;
19633735 capa->bw_support = rtt_status->rtt_capa.bw;
....@@ -1965,44 +3737,223 @@
19653737 return err;
19663738 }
19673739
3740
+#ifdef WL_CFG80211
3741
+int
3742
+dhd_rtt_avail_channel(dhd_pub_t *dhd, wifi_channel_info *channel_info)
3743
+{
3744
+ u32 chanspec = 0;
3745
+ int err = BCME_OK;
3746
+ chanspec_t c = 0;
3747
+ u32 channel;
3748
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
3749
+
3750
+ if ((err = wldev_iovar_getint(dev, "chanspec",
3751
+ (s32 *)&chanspec)) == BCME_OK) {
3752
+ c = (chanspec_t)dtoh32(chanspec);
3753
+ c = wl_chspec_driver_to_host(c);
3754
+ channel = wf_chspec_ctlchan(c);
3755
+ DHD_RTT((" control channel is %d \n", channel));
3756
+ if (CHSPEC_IS20(c)) {
3757
+ channel_info->width = WIFI_CHAN_WIDTH_20;
3758
+ DHD_RTT((" band is 20 \n"));
3759
+ } else if (CHSPEC_IS40(c)) {
3760
+ channel_info->width = WIFI_CHAN_WIDTH_40;
3761
+ DHD_RTT(("band is 40 \n"));
3762
+ } else {
3763
+ channel_info->width = WIFI_CHAN_WIDTH_80;
3764
+ DHD_RTT(("band is 80 \n"));
3765
+ }
3766
+ if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
3767
+ (channel <= CH_MAX_2G_CHANNEL)) {
3768
+ channel_info->center_freq =
3769
+ ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
3770
+ } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
3771
+ channel_info->center_freq =
3772
+ ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
3773
+ }
3774
+ if ((channel_info->width == WIFI_CHAN_WIDTH_80) ||
3775
+ (channel_info->width == WIFI_CHAN_WIDTH_40)) {
3776
+ channel = CHSPEC_CHANNEL(c);
3777
+ channel_info->center_freq0 =
3778
+ ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
3779
+ }
3780
+ } else {
3781
+ DHD_RTT_ERR(("Failed to get the chanspec \n"));
3782
+ }
3783
+ return err;
3784
+}
3785
+
3786
+int
3787
+dhd_rtt_enable_responder(dhd_pub_t *dhd, wifi_channel_info *channel_info)
3788
+{
3789
+ int err = BCME_OK;
3790
+ char chanbuf[CHANSPEC_STR_LEN];
3791
+ int pm = PM_OFF;
3792
+ int ftm_cfg_cnt = 0;
3793
+ chanspec_t chanspec;
3794
+ wifi_channel_info_t channel;
3795
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
3796
+ ftm_config_options_info_t ftm_configs[FTM_MAX_CONFIGS];
3797
+ ftm_config_param_info_t ftm_params[FTM_MAX_PARAMS];
3798
+ rtt_status_info_t *rtt_status;
3799
+
3800
+ memset(&channel, 0, sizeof(channel));
3801
+ BCM_REFERENCE(chanbuf);
3802
+ NULL_CHECK(dhd, "dhd is NULL", err);
3803
+ rtt_status = GET_RTTSTATE(dhd);
3804
+ NULL_CHECK(rtt_status, "rtt_status is NULL", err);
3805
+ if (RTT_IS_STOPPED(rtt_status)) {
3806
+ DHD_RTT(("STA responder/Target. \n"));
3807
+ }
3808
+ DHD_RTT(("Enter %s \n", __FUNCTION__));
3809
+ if (!dhd_is_associated(dhd, 0, NULL)) {
3810
+ if (channel_info) {
3811
+ channel.width = channel_info->width;
3812
+ channel.center_freq = channel_info->center_freq;
3813
+ channel.center_freq0 = channel_info->center_freq;
3814
+ }
3815
+ else {
3816
+ channel.width = WIFI_CHAN_WIDTH_80;
3817
+ channel.center_freq = DEFAULT_FTM_FREQ;
3818
+ channel.center_freq0 = DEFAULT_FTM_CNTR_FREQ0;
3819
+ }
3820
+ chanspec = dhd_rtt_convert_to_chspec(channel);
3821
+ DHD_RTT(("chanspec/channel set as %s for rtt.\n",
3822
+ wf_chspec_ntoa(chanspec, chanbuf)));
3823
+ err = wldev_iovar_setint(dev, "chanspec", chanspec);
3824
+ if (err) {
3825
+ DHD_RTT_ERR(("Failed to set the chanspec \n"));
3826
+ }
3827
+ }
3828
+ rtt_status->pm = PM_OFF;
3829
+ err = wldev_ioctl_get(dev, WLC_GET_PM, &rtt_status->pm, sizeof(rtt_status->pm));
3830
+ DHD_RTT(("Current PM value read %d\n", rtt_status->pm));
3831
+ if (err) {
3832
+ DHD_RTT_ERR(("Failed to get the PM value \n"));
3833
+ } else {
3834
+ err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
3835
+ if (err) {
3836
+ DHD_RTT_ERR(("Failed to set the PM \n"));
3837
+ rtt_status->pm_restore = FALSE;
3838
+ } else {
3839
+ rtt_status->pm_restore = TRUE;
3840
+ }
3841
+ }
3842
+ if (!RTT_IS_ENABLED(rtt_status)) {
3843
+ err = dhd_rtt_ftm_enable(dhd, TRUE);
3844
+ if (err) {
3845
+ DHD_RTT_ERR(("Failed to enable FTM (%d)\n", err));
3846
+ goto exit;
3847
+ }
3848
+ DHD_RTT(("FTM enabled \n"));
3849
+ }
3850
+ rtt_status->status = RTT_ENABLED;
3851
+ DHD_RTT(("Responder enabled \n"));
3852
+ memset(ftm_configs, 0, sizeof(ftm_configs));
3853
+ memset(ftm_params, 0, sizeof(ftm_params));
3854
+ ftm_configs[ftm_cfg_cnt].enable = TRUE;
3855
+ ftm_configs[ftm_cfg_cnt++].flags = WL_PROXD_SESSION_FLAG_TARGET;
3856
+ rtt_status->flags = WL_PROXD_SESSION_FLAG_TARGET;
3857
+ DHD_RTT(("Set the device as responder \n"));
3858
+ err = dhd_rtt_ftm_config(dhd, FTM_DEFAULT_SESSION, FTM_CONFIG_CAT_OPTIONS,
3859
+ ftm_configs, ftm_cfg_cnt);
3860
+exit:
3861
+ if (err) {
3862
+ rtt_status->status = RTT_STOPPED;
3863
+ DHD_RTT_ERR(("rtt is stopped %s \n", __FUNCTION__));
3864
+ dhd_rtt_ftm_enable(dhd, FALSE);
3865
+ DHD_RTT(("restoring the PM value \n"));
3866
+ if (rtt_status->pm_restore) {
3867
+ pm = PM_FAST;
3868
+ err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
3869
+ if (err) {
3870
+ DHD_RTT_ERR(("Failed to restore PM \n"));
3871
+ } else {
3872
+ rtt_status->pm_restore = FALSE;
3873
+ }
3874
+ }
3875
+ }
3876
+ return err;
3877
+}
3878
+
3879
+int
3880
+dhd_rtt_cancel_responder(dhd_pub_t *dhd)
3881
+{
3882
+ int err = BCME_OK;
3883
+ rtt_status_info_t *rtt_status;
3884
+ int pm = 0;
3885
+ struct net_device *dev = dhd_linux_get_primary_netdev(dhd);
3886
+
3887
+ NULL_CHECK(dhd, "dhd is NULL", err);
3888
+ rtt_status = GET_RTTSTATE(dhd);
3889
+ NULL_CHECK(rtt_status, "rtt_status is NULL", err);
3890
+ DHD_RTT(("Enter %s \n", __FUNCTION__));
3891
+ err = dhd_rtt_ftm_enable(dhd, FALSE);
3892
+ if (err) {
3893
+ DHD_RTT_ERR(("failed to disable FTM (%d)\n", err));
3894
+ }
3895
+ rtt_status->status = RTT_STOPPED;
3896
+ if (rtt_status->pm_restore) {
3897
+ pm = PM_FAST;
3898
+ DHD_RTT(("pm_restore =%d \n", rtt_status->pm_restore));
3899
+ err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
3900
+ if (err) {
3901
+ DHD_RTT_ERR(("Failed to restore PM \n"));
3902
+ } else {
3903
+ rtt_status->pm_restore = FALSE;
3904
+ }
3905
+ }
3906
+ return err;
3907
+}
3908
+#endif /* WL_CFG80211 */
3909
+
19683910 int
19693911 dhd_rtt_init(dhd_pub_t *dhd)
19703912 {
1971
- int err = BCME_OK, ret;
1972
- int32 up = 1;
3913
+ int err = BCME_OK;
3914
+#ifdef WL_CFG80211
3915
+ int ret;
3916
+ int32 drv_up = 1;
19733917 int32 version;
19743918 rtt_status_info_t *rtt_status;
3919
+ ftm_config_param_info_t ftm_params[FTM_MAX_PARAMS];
3920
+ int ftm_param_cnt = 0;
3921
+
19753922 NULL_CHECK(dhd, "dhd is NULL", err);
19763923 if (dhd->rtt_state) {
19773924 return err;
19783925 }
1979
- dhd->rtt_state = kzalloc(sizeof(rtt_status_info_t), GFP_KERNEL);
3926
+ dhd->rtt_state = (rtt_status_info_t *)MALLOCZ(dhd->osh,
3927
+ sizeof(rtt_status_info_t));
19803928 if (dhd->rtt_state == NULL) {
19813929 err = BCME_NOMEM;
1982
- DHD_ERROR(("%s : failed to create rtt_state\n", __FUNCTION__));
3930
+ DHD_RTT_ERR(("%s : failed to create rtt_state\n", __FUNCTION__));
19833931 return err;
19843932 }
19853933 bzero(dhd->rtt_state, sizeof(rtt_status_info_t));
19863934 rtt_status = GET_RTTSTATE(dhd);
19873935 rtt_status->rtt_config.target_info =
1988
- kzalloc(TARGET_INFO_SIZE(RTT_MAX_TARGET_CNT), GFP_KERNEL);
3936
+ (rtt_target_info_t *)MALLOCZ(dhd->osh,
3937
+ TARGET_INFO_SIZE(RTT_MAX_TARGET_CNT));
19893938 if (rtt_status->rtt_config.target_info == NULL) {
1990
- DHD_ERROR(("%s failed to allocate the target info for %d\n",
3939
+ DHD_RTT_ERR(("%s failed to allocate the target info for %d\n",
19913940 __FUNCTION__, RTT_MAX_TARGET_CNT));
19923941 err = BCME_NOMEM;
19933942 goto exit;
19943943 }
19953944 rtt_status->dhd = dhd;
19963945 /* need to do WLC_UP */
1997
- dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(int32), TRUE, 0);
3946
+ dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&drv_up, sizeof(int32), TRUE, 0);
19983947
19993948 ret = dhd_rtt_get_version(dhd, &version);
20003949 if (ret == BCME_OK && (version == WL_PROXD_API_VERSION)) {
2001
- DHD_ERROR(("%s : FTM is supported\n", __FUNCTION__));
3950
+ DHD_RTT_ERR(("%s : FTM is supported\n", __FUNCTION__));
20023951 /* rtt_status->rtt_capa.proto |= RTT_CAP_ONE_WAY; */
20033952 rtt_status->rtt_capa.proto |= RTT_CAP_FTM_WAY;
20043953
20053954 /* indicate to set tx rate */
3955
+ rtt_status->rtt_capa.feature |= RTT_FEATURE_LCI;
3956
+ rtt_status->rtt_capa.feature |= RTT_FEATURE_LCR;
20063957 rtt_status->rtt_capa.feature |= RTT_FEATURE_PREAMBLE;
20073958 rtt_status->rtt_capa.preamble |= RTT_PREAMBLE_VHT;
20083959 rtt_status->rtt_capa.preamble |= RTT_PREAMBLE_HT;
....@@ -2014,30 +3965,48 @@
20143965 rtt_status->rtt_capa.bw |= RTT_BW_80;
20153966 } else {
20163967 if ((ret != BCME_OK) || (version == 0)) {
2017
- DHD_ERROR(("%s : FTM is not supported\n", __FUNCTION__));
3968
+ DHD_RTT_ERR(("%s : FTM is not supported\n", __FUNCTION__));
20183969 } else {
2019
- DHD_ERROR(("%s : FTM version mismatch between HOST (%d) and FW (%d)\n",
3970
+ DHD_RTT_ERR(("%s : FTM version mismatch between HOST (%d) and FW (%d)\n",
20203971 __FUNCTION__, WL_PROXD_API_VERSION, version));
20213972 }
20223973 }
20233974 /* cancel all of RTT request once we got the cancel request */
20243975 rtt_status->all_cancel = TRUE;
20253976 mutex_init(&rtt_status->rtt_mutex);
3977
+ mutex_init(&rtt_status->geofence_mutex);
20263978 INIT_LIST_HEAD(&rtt_status->noti_fn_list);
20273979 INIT_LIST_HEAD(&rtt_status->rtt_results_cache);
20283980 INIT_WORK(&rtt_status->work, dhd_rtt_work);
3981
+ /* initialize proxd timer */
3982
+ INIT_DELAYED_WORK(&rtt_status->proxd_timeout, dhd_rtt_timeout_work);
3983
+#ifdef WL_NAN
3984
+ /* initialize proxd retry timer */
3985
+ INIT_DELAYED_WORK(&rtt_status->rtt_retry_timer, dhd_rtt_retry_work);
3986
+ /* initialize non zero params of geofenne cfg */
3987
+ rtt_status->geofence_cfg.cur_target_idx = DHD_RTT_INVALID_TARGET_INDEX;
3988
+#endif /* WL_NAN */
3989
+ /* Global proxd config */
3990
+ ftm_params[ftm_param_cnt].event_mask = ((1 << WL_PROXD_EVENT_BURST_END) |
3991
+ (1 << WL_PROXD_EVENT_SESSION_END));
3992
+ ftm_params[ftm_param_cnt++].tlvid = WL_PROXD_TLV_ID_EVENT_MASK;
3993
+ dhd_rtt_ftm_config(dhd, 0, FTM_CONFIG_CAT_GENERAL,
3994
+ ftm_params, ftm_param_cnt);
20293995 exit:
20303996 if (err < 0) {
20313997 kfree(rtt_status->rtt_config.target_info);
20323998 kfree(dhd->rtt_state);
20333999 }
4000
+#endif /* WL_CFG80211 */
20344001 return err;
4002
+
20354003 }
20364004
20374005 int
20384006 dhd_rtt_deinit(dhd_pub_t *dhd)
20394007 {
20404008 int err = BCME_OK;
4009
+#ifdef WL_CFG80211
20414010 rtt_status_info_t *rtt_status;
20424011 rtt_results_header_t *rtt_header, *next;
20434012 rtt_result_t *rtt_result, *next2;
....@@ -2046,7 +4015,9 @@
20464015 rtt_status = GET_RTTSTATE(dhd);
20474016 NULL_CHECK(rtt_status, "rtt_status is NULL", err);
20484017 rtt_status->status = RTT_STOPPED;
4018
+ DHD_RTT(("rtt is stopped %s \n", __FUNCTION__));
20494019 /* clear evt callback list */
4020
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
20504021 if (!list_empty(&rtt_status->noti_fn_list)) {
20514022 list_for_each_entry_safe(iter, iter2, &rtt_status->noti_fn_list, list) {
20524023 list_del(&iter->list);
....@@ -2065,8 +4036,11 @@
20654036 kfree(rtt_header);
20664037 }
20674038 }
4039
+ GCC_DIAGNOSTIC_POP();
4040
+
20684041 kfree(rtt_status->rtt_config.target_info);
20694042 kfree(dhd->rtt_state);
20704043 dhd->rtt_state = NULL;
4044
+#endif /* WL_CFG80211 */
20714045 return err;
20724046 }