blob: 0a172685416e92e89913947a5c055c27ac331863 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**
23 * DOC: wlan_hdd_ext_scan.c
24 *
25 * WLAN Host Device Driver EXT SCAN feature implementation
26 *
27 */
28
29#ifdef FEATURE_WLAN_EXTSCAN
30
Jeff Johnson630f9e72016-07-25 12:00:12 -070031/* denote that this file does not allow legacy hddLog */
32#define HDD_DISALLOW_LEGACY_HDDLOG 1
33
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080034#include "wlan_hdd_ext_scan.h"
35#include "cds_utils.h"
36#include "cds_sched.h"
37
38/* amount of time to wait for a synchronous request/response operation */
39#define WLAN_WAIT_TIME_EXTSCAN 1000
40
41/**
42 * struct hdd_ext_scan_context - hdd ext scan context
43 * @request_id: userspace-assigned ID associated with the request
44 * @response_event: Ext scan wait event
45 * @response_status: Status returned by FW in response to a request
46 * @ignore_cached_results: Flag to ignore cached results or not
47 * @context_lock: Spinlock to serialize all context accesses
48 * @capability_response: Ext scan capability response data from target
Mukul Sharmafa937be2016-08-12 18:13:36 +053049 * @buckets_scanned: bitmask of buckets scanned in extscan cycle
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050 */
51struct hdd_ext_scan_context {
52 uint32_t request_id;
53 int response_status;
54 bool ignore_cached_results;
55 struct completion response_event;
56 spinlock_t context_lock;
57 struct ext_scan_capabilities_response capability_response;
Mukul Sharmafa937be2016-08-12 18:13:36 +053058 uint32_t buckets_scanned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080059};
60static struct hdd_ext_scan_context ext_scan_context;
61
62static const struct nla_policy wlan_hdd_extscan_config_policy
63[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] = {
64 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = {
65 .type = NLA_U32},
66 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = {
67 .type = NLA_U32},
68 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = {.type = NLA_U32},
69 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = {
70 .type = NLA_U32},
71 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = {.type = NLA_U8},
72 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = {.type = NLA_U8},
73
74 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = {.type = NLA_U8},
75 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = {.type = NLA_U8},
76 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = {.type = NLA_U32},
77 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] = {
78 .type = NLA_U8},
79 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] = {
80 .type = NLA_U32},
81 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] = {
82 .type = NLA_U32},
83 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] = {
84 .type = NLA_U32},
85 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT] = {
86 .type = NLA_U8},
87 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS] = {
88 .type = NLA_U8 },
89 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] = {
90 .type = NLA_U8},
91 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = {
92 .type = NLA_U8},
93
94 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = {
95 .type = NLA_U32},
96 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = {
97 .type = NLA_UNSPEC},
98 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = {
99 .type = NLA_S32},
100 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = {
101 .type = NLA_S32},
102 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = {
103 .type = NLA_U32},
104 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] = {
105 .type = NLA_U32},
106 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] = {
107 .type = NLA_U32},
108 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = {
109 .type = NLA_U32},
110 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = {
111 .type = NLA_U32},
112 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = {
113 .type = NLA_U32},
114 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
115 .type = NLA_U32 },
116 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
117 .type = NLA_BINARY,
118 .len = IEEE80211_MAX_SSID_LEN },
119 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD] = {
120 .type = NLA_S8 },
121 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
122 .type = NLA_U8 },
123 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
124 .type = NLA_U8 },
125 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = {
126 .type = NLA_BINARY,
127 .len = IEEE80211_MAX_SSID_LEN + 1 },
128 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = {
129 .type = NLA_U32 },
130 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID] = {
131 .type = NLA_U32 },
132 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND] = {
133 .type = NLA_U8 },
134 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = {
135 .type = NLA_S32 },
136 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = {
137 .type = NLA_S32 },
138 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = {
139 .type = NLA_U32 },
140};
141
142static const struct nla_policy
143wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
144 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
145 .type = NLA_U16},
146 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = {
147 .type = NLA_U16},
148};
149
150/**
151 * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
152 * @ctx: Pointer to hdd context
153 * @data: Pointer to ext scan capabilities response from fw
154 *
155 * Return: None
156 */
157static void
158wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx,
159 struct ext_scan_capabilities_response *data)
160{
161 struct hdd_ext_scan_context *context;
162 hdd_context_t *hdd_ctx = ctx;
163
164 ENTER();
165
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530166 if (wlan_hdd_validate_context(hdd_ctx))
167 return;
168 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700169 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 return;
171 }
172
173 context = &ext_scan_context;
174
175 spin_lock(&context->context_lock);
176 /* validate response received from target*/
177 if (context->request_id != data->requestId) {
178 spin_unlock(&context->context_lock);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700179 hdd_err("Target response id did not match: request_id %d response_id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 context->request_id, data->requestId);
181 return;
182 } else {
183 context->capability_response = *data;
184 complete(&context->response_event);
185 }
186
187 spin_unlock(&context->context_lock);
188
189 return;
190}
191
192/*
193 * define short names for the global vendor params
194 * used by hdd_extscan_nl_fill_bss()
195 */
196#define PARAM_TIME_STAMP \
197 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
198#define PARAM_SSID \
199 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID
200#define PARAM_BSSID \
201 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID
202#define PARAM_CHANNEL \
203 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL
204#define PARAM_RSSI \
205 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI
206#define PARAM_RTT \
207 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT
208#define PARAM_RTT_SD \
209 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD
210#define PARAM_BEACON_PERIOD \
211 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD
212#define PARAM_CAPABILITY \
213 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY
214#define PARAM_IE_LENGTH \
215 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
216#define PARAM_IE_DATA \
217 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA
218
219/** hdd_extscan_nl_fill_bss() - extscan nl fill bss
220 * @skb: socket buffer
221 * @ap: bss information
222 * @idx: nesting index
223 *
224 * Return: 0 on success; error number otherwise
225 */
226static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap,
227 int idx)
228{
229 struct nlattr *nla_ap;
230
231 nla_ap = nla_nest_start(skb, idx);
232 if (!nla_ap)
233 return -EINVAL;
234
235 if (nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) ||
236 nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) ||
237 nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid.bytes) ||
238 nla_put_u32(skb, PARAM_CHANNEL, ap->channel) ||
239 nla_put_s32(skb, PARAM_RSSI, ap->rssi) ||
240 nla_put_u32(skb, PARAM_RTT, ap->rtt) ||
241 nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) ||
242 nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) ||
243 nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) ||
244 nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700245 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246 return -EINVAL;
247 }
248
249 if (ap->ieLength)
250 if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700251 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 return -EINVAL;
253 }
254
255 nla_nest_end(skb, nla_ap);
256
257 return 0;
258}
259/*
260 * done with short names for the global vendor params
261 * used by hdd_extscan_nl_fill_bss()
262 */
263#undef PARAM_TIME_STAMP
264#undef PARAM_SSID
265#undef PARAM_BSSID
266#undef PARAM_CHANNEL
267#undef PARAM_RSSI
268#undef PARAM_RTT
269#undef PARAM_RTT_SD
270#undef PARAM_BEACON_PERIOD
271#undef PARAM_CAPABILITY
272#undef PARAM_IE_LENGTH
273#undef PARAM_IE_DATA
274
275/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results
276 * @ctx: hdd global context
277 * @data: cached results
278 *
279 * This function reads the cached results %data, populated the NL
280 * attributes and sends the NL event to the upper layer.
281 *
282 * Return: none
283 */
284static void
285wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
286 struct extscan_cached_scan_results *data)
287{
288 hdd_context_t *pHddCtx = ctx;
289 struct sk_buff *skb = NULL;
290 struct hdd_ext_scan_context *context;
291 struct extscan_cached_scan_result *result;
292 tSirWifiScanResult *ap;
293 uint32_t i, j, nl_buf_len;
294 bool ignore_cached_results = false;
295
296 ENTER();
297
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530298 if (wlan_hdd_validate_context(pHddCtx))
299 return;
300 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700301 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800302 return;
303 }
304
305 context = &ext_scan_context;
306 spin_lock(&context->context_lock);
307 ignore_cached_results = context->ignore_cached_results;
308 spin_unlock(&context->context_lock);
309
310 if (ignore_cached_results) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700311 hdd_err("Ignore the cached results received after timeout");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800312 return;
313 }
314
315#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN
316#define EXTSCAN_CACHED_NL_FIXED_TLV \
317 ((sizeof(data->request_id) + NLA_HDRLEN) + \
318 (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \
319 (sizeof(data->more_data) + NLA_HDRLEN))
320#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \
321 ((sizeof(result->scan_id) + NLA_HDRLEN) + \
322 (sizeof(result->flags) + NLA_HDRLEN) + \
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530323 (sizeof(result->num_results) + NLA_HDRLEN))+ \
324 (sizeof(result->buckets_scanned) + NLA_HDRLEN)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800325#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
326 ((sizeof(ap->ts) + NLA_HDRLEN) + \
327 (sizeof(ap->ssid) + NLA_HDRLEN) + \
328 (sizeof(ap->bssid) + NLA_HDRLEN) + \
329 (sizeof(ap->channel) + NLA_HDRLEN) + \
330 (sizeof(ap->rssi) + NLA_HDRLEN) + \
331 (sizeof(ap->rtt) + NLA_HDRLEN) + \
332 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
333 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
334 (sizeof(ap->capability) + NLA_HDRLEN) + \
335 (sizeof(ap->ieLength) + NLA_HDRLEN))
336#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
337 (ap->ieLength + NLA_HDRLEN)
338
339 nl_buf_len = NLMSG_HDRLEN;
340 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
341 if (data->num_scan_ids) {
342 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
343 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
344 result = &data->result[0];
345 for (i = 0; i < data->num_scan_ids; i++) {
346 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
347 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
348 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
349
350 ap = &result->ap[0];
351 for (j = 0; j < result->num_results; j++) {
352 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
353 nl_buf_len +=
354 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
355 if (ap->ieLength)
356 nl_buf_len +=
357 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
358 ap++;
359 }
360 result++;
361 }
362 }
363
Jeff Johnson630f9e72016-07-25 12:00:12 -0700364 hdd_notice("nl_buf_len = %u", nl_buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len);
366
367 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700368 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369 goto fail;
370 }
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530371 hdd_notice("Req Id %u Num_scan_ids %u More Data %u",
372 data->request_id, data->num_scan_ids, data->more_data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373
374 result = &data->result[0];
375 for (i = 0; i < data->num_scan_ids; i++) {
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530376 hdd_notice("[i=%d] scan_id %u flags %u num_results %u buckets scanned %u",
377 i, result->scan_id, result->flags, result->num_results,
378 result->buckets_scanned);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379
380 ap = &result->ap[0];
381 for (j = 0; j < result->num_results; j++) {
382 /*
383 * Firmware returns timestamp from ext scan start till
384 * BSSID was cached (in micro seconds). Add this with
385 * time gap between system boot up to ext scan start
386 * to derive the time since boot when the
387 * BSSID was cached.
388 */
389 ap->ts += pHddCtx->ext_scan_start_since_boot;
Jeff Johnson630f9e72016-07-25 12:00:12 -0700390 hdd_notice("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 "Ssid: %s "
392 "Bssid (" MAC_ADDRESS_STR ") "
393 "Channel %u "
394 "Rssi %d "
395 "RTT %u "
396 "RTT_SD %u "
397 "Beacon Period %u "
398 "Capability 0x%x "
399 "Ie length %d",
400 ap->ts,
401 ap->ssid,
402 MAC_ADDR_ARRAY(ap->bssid.bytes),
403 ap->channel,
404 ap->rssi,
405 ap->rtt,
406 ap->rtt_sd,
407 ap->beaconPeriod,
408 ap->capability,
409 ap->ieLength);
410 ap++;
411 }
412 result++;
413 }
414
415 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
416 data->request_id) ||
417 nla_put_u32(skb,
418 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
419 data->num_scan_ids) ||
420 nla_put_u8(skb,
421 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
422 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700423 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 goto fail;
425 }
426
427 if (data->num_scan_ids) {
428 struct nlattr *nla_results;
429 result = &data->result[0];
430
431 if (nla_put_u32(skb,
432 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
433 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700434 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435 goto fail;
436 }
437 nla_results = nla_nest_start(skb,
438 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
439 if (!nla_results)
440 goto fail;
441
442 for (i = 0; i < data->num_scan_ids; i++) {
443 struct nlattr *nla_result;
444 struct nlattr *nla_aps;
445
446 nla_result = nla_nest_start(skb, i);
447 if (!nla_result)
448 goto fail;
449
450 if (nla_put_u32(skb,
451 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
452 result->scan_id) ||
453 nla_put_u32(skb,
454 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
455 result->flags) ||
456 nla_put_u32(skb,
Mukul Sharmafa937be2016-08-12 18:13:36 +0530457 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530458 result->buckets_scanned) ||
Mukul Sharmafa937be2016-08-12 18:13:36 +0530459 nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
461 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700462 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800463 goto fail;
464 }
465
466 nla_aps = nla_nest_start(skb,
467 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
468 if (!nla_aps)
469 goto fail;
470
471 ap = &result->ap[0];
472 for (j = 0; j < result->num_results; j++) {
473 if (hdd_extscan_nl_fill_bss(skb, ap, j))
474 goto fail;
475
476 ap++;
477 }
478 nla_nest_end(skb, nla_aps);
479 nla_nest_end(skb, nla_result);
480 result++;
481 }
482 nla_nest_end(skb, nla_results);
483 }
484
485 cfg80211_vendor_cmd_reply(skb);
486
487 if (!data->more_data) {
488 spin_lock(&context->context_lock);
489 context->response_status = 0;
490 complete(&context->response_event);
491 spin_unlock(&context->context_lock);
492 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530493 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800494 return;
495
496fail:
497 if (skb)
498 kfree_skb(skb);
499
500 spin_lock(&context->context_lock);
501 context->response_status = -EINVAL;
502 spin_unlock(&context->context_lock);
503
504 return;
505}
506
507/**
508 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
509 * @ctx: Pointer to hdd context
510 * @pData: Pointer to ext scan result event
511 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800512 * This callback execute in atomic context and must not invoke any
513 * blocking calls.
514 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 * Return: none
516 */
517static void
518wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
519 struct extscan_hotlist_match *data)
520{
521 hdd_context_t *pHddCtx = ctx;
522 struct sk_buff *skb = NULL;
523 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800524 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525
526 ENTER();
527
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530528 if (wlan_hdd_validate_context(pHddCtx))
529 return;
530 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700531 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 return;
533 }
534
535 if (data->ap_found)
536 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
537 else
538 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
539
540 skb = cfg80211_vendor_event_alloc(
541 pHddCtx->wiphy,
542 NULL,
543 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800544 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545
546 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700547 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 return;
549 }
550 hdd_info("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
551 data->requestId, data->numOfAps, data->moreData,
552 data->ap_found);
553
554 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530555 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556
Jeff Johnson630f9e72016-07-25 12:00:12 -0700557 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 "Ssid: %s "
559 "Bssid (" MAC_ADDRESS_STR ") "
560 "Channel %u "
561 "Rssi %d "
562 "RTT %u "
563 "RTT_SD %u",
564 i,
565 data->ap[i].ts,
566 data->ap[i].ssid,
567 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
568 data->ap[i].channel,
569 data->ap[i].rssi,
570 data->ap[i].rtt, data->ap[i].rtt_sd);
571 }
572
573 if (nla_put_u32(skb,
574 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
575 data->requestId) ||
576 nla_put_u32(skb,
577 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
578 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700579 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 goto fail;
581 }
582
583 if (data->numOfAps) {
584 struct nlattr *aps;
585
586 aps = nla_nest_start(skb,
587 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
588 if (!aps)
589 goto fail;
590
591 for (i = 0; i < data->numOfAps; i++) {
592 struct nlattr *ap;
593
594 ap = nla_nest_start(skb, i);
595 if (!ap)
596 goto fail;
597
598 if (nla_put_u64(skb,
599 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
600 data->ap[i].ts) ||
601 nla_put(skb,
602 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
603 sizeof(data->ap[i].ssid),
604 data->ap[i].ssid) ||
605 nla_put(skb,
606 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
607 sizeof(data->ap[i].bssid),
608 data->ap[i].bssid.bytes) ||
609 nla_put_u32(skb,
610 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
611 data->ap[i].channel) ||
612 nla_put_s32(skb,
613 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
614 data->ap[i].rssi) ||
615 nla_put_u32(skb,
616 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
617 data->ap[i].rtt) ||
618 nla_put_u32(skb,
619 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
620 data->ap[i].rtt_sd))
621 goto fail;
622
623 nla_nest_end(skb, ap);
624 }
625 nla_nest_end(skb, aps);
626
627 if (nla_put_u8(skb,
628 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
629 data->moreData))
630 goto fail;
631 }
632
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800633 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530634 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 return;
636
637fail:
638 kfree_skb(skb);
639 return;
640}
641
642/**
643 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
644 * significant wifi change results indication
645 * @ctx: Pointer to hdd context
646 * @pData: Pointer to signif wifi change event
647 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800648 * This callback execute in atomic context and must not invoke any
649 * blocking calls.
650 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 * Return: none
652 */
653static void
654wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
655 void *ctx,
656 tpSirWifiSignificantChangeEvent pData)
657{
658 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
659 struct sk_buff *skb = NULL;
660 tSirWifiSignificantChange *ap_info;
661 int32_t *rssi;
662 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800663 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664
665 ENTER();
666
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530667 if (wlan_hdd_validate_context(pHddCtx))
668 return;
669 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700670 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671 return;
672 }
673
674 skb = cfg80211_vendor_event_alloc(
675 pHddCtx->wiphy,
676 NULL,
677 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
678 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800679 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680
681 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700682 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683 return;
684 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700685 hdd_notice("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 pData->requestId, pData->numResults, pData->moreData);
687
688 ap_info = &pData->ap[0];
689 for (i = 0; i < pData->numResults; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700690 hdd_notice("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 "Bssid (" MAC_ADDRESS_STR ") "
692 "Channel %u "
693 "numOfRssi %d",
694 i,
695 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
696 ap_info->channel, ap_info->numOfRssi);
697 rssi = &(ap_info)->rssi[0];
698 for (j = 0; j < ap_info->numOfRssi; j++)
Jeff Johnson630f9e72016-07-25 12:00:12 -0700699 hdd_notice("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700
701 ap_info += ap_info->numOfRssi * sizeof(*rssi);
702 }
703
704 if (nla_put_u32(skb,
705 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
706 pData->requestId) ||
707 nla_put_u32(skb,
708 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
709 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700710 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 goto fail;
712 }
713
714 if (pData->numResults) {
715 struct nlattr *aps;
716
717 aps = nla_nest_start(skb,
718 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
719 if (!aps)
720 goto fail;
721
722 ap_info = &pData->ap[0];
723 for (i = 0; i < pData->numResults; i++) {
724 struct nlattr *ap;
725
726 ap = nla_nest_start(skb, i);
727 if (!ap)
728 goto fail;
729
730 if (nla_put(skb,
731 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530732 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800733 nla_put_u32(skb,
734 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
735 ap_info->channel) ||
736 nla_put_u32(skb,
737 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
738 ap_info->numOfRssi) ||
739 nla_put(skb,
740 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
741 sizeof(s32) * ap_info->numOfRssi,
742 &(ap_info)->rssi[0]))
743 goto fail;
744
745 nla_nest_end(skb, ap);
746
747 ap_info += ap_info->numOfRssi * sizeof(*rssi);
748 }
749 nla_nest_end(skb, aps);
750
751 if (nla_put_u8(skb,
752 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
753 pData->moreData))
754 goto fail;
755 }
756
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800757 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758 return;
759
760fail:
761 kfree_skb(skb);
762 return;
763
764}
765
766/**
767 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
768 * @ctx: Pointer to hdd context
769 * @pData: Pointer to full scan result event
770 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800771 * This callback execute in atomic context and must not invoke any
772 * blocking calls.
773 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774 * Return: none
775 */
776static void
777wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
778 tpSirWifiFullScanResultEvent
779 pData)
780{
781 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
782 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 struct timespec ts;
Mukul Sharmafa937be2016-08-12 18:13:36 +0530784 struct hdd_ext_scan_context *context;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700785
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800786 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787
788 ENTER();
789
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530790 if (wlan_hdd_validate_context(pHddCtx))
791 return;
792 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700793 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 return;
795 }
796
797 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700798 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 return;
800 }
801 skb = cfg80211_vendor_event_alloc(
802 pHddCtx->wiphy,
803 NULL,
804 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
805 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800806 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807
808 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700809 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 return;
811 }
812
813 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 /* Android does not want the time stamp from the frame.
816 Instead it wants a monotonic increasing value since boot */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700817 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700819
Jeff Johnson630f9e72016-07-25 12:00:12 -0700820 hdd_notice("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821 pData->moreData);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700822 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 "Bssid (" MAC_ADDRESS_STR ") "
824 "Channel %u "
825 "Rssi %d "
826 "RTT %u "
827 "RTT_SD %u "
828 "Bcn Period %d "
829 "Capability 0x%X "
830 "IE Length %d",
831 pData->ap.ts,
832 pData->ap.ssid,
833 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
834 pData->ap.channel,
835 pData->ap.rssi,
836 pData->ap.rtt,
837 pData->ap.rtt_sd,
838 pData->ap.beaconPeriod,
839 pData->ap.capability, pData->ap.ieLength);
840
841 if (nla_put_u32(skb,
842 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
843 pData->requestId) ||
844 nla_put_u64(skb,
845 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
846 pData->ap.ts) ||
847 nla_put(skb,
848 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
849 sizeof(pData->ap.ssid),
850 pData->ap.ssid) ||
851 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
852 sizeof(pData->ap.bssid),
853 pData->ap.bssid.bytes) ||
854 nla_put_u32(skb,
855 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
856 pData->ap.channel) ||
857 nla_put_s32(skb,
858 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
859 pData->ap.rssi) ||
860 nla_put_u32(skb,
861 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
862 pData->ap.rtt) ||
863 nla_put_u32(skb,
864 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
865 pData->ap.rtt_sd) ||
866 nla_put_u16(skb,
867 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
868 pData->ap.beaconPeriod) ||
869 nla_put_u16(skb,
870 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
871 pData->ap.capability) ||
872 nla_put_u32(skb,
873 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
874 pData->ap.ieLength) ||
875 nla_put_u8(skb,
876 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
877 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700878 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 goto nla_put_failure;
880 }
881
882 if (pData->ap.ieLength) {
883 if (nla_put(skb,
884 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
885 pData->ap.ieLength, pData->ap.ieData))
886 goto nla_put_failure;
887 }
888
Mukul Sharmafa937be2016-08-12 18:13:36 +0530889 context = &ext_scan_context;
890 spin_lock(&context->context_lock);
891 if (nla_put_u32(skb,
892 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
893 context->buckets_scanned)) {
894 spin_unlock(&context->context_lock);
895 hdd_notice("Failed to include buckets_scanned");
896 goto nla_put_failure;
897 }
898 spin_unlock(&context->context_lock);
899
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800900 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530901 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 return;
903
904nla_put_failure:
905 kfree_skb(skb);
906 return;
907}
908
909/**
910 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
911 * @ctx: Pointer to hdd context
912 * @pData: Pointer to scan results available indication param
913 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800914 * This callback execute in atomic context and must not invoke any
915 * blocking calls.
916 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 * Return: none
918 */
919static void
920wlan_hdd_cfg80211_extscan_scan_res_available_event(
921 void *ctx,
922 tpSirExtScanResultsAvailableIndParams pData)
923{
924 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
925 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800926 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800927
928 ENTER();
929
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530930 if (wlan_hdd_validate_context(pHddCtx))
931 return;
932 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700933 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 return;
935 }
936
937 skb = cfg80211_vendor_event_alloc(
938 pHddCtx->wiphy,
939 NULL,
940 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
941 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800942 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943
944 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700945 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800946 return;
947 }
948
Jeff Johnson630f9e72016-07-25 12:00:12 -0700949 hdd_notice("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 pData->requestId, pData->numResultsAvailable);
951 if (nla_put_u32(skb,
952 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
953 pData->requestId) ||
954 nla_put_u32(skb,
955 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
956 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700957 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800958 goto nla_put_failure;
959 }
960
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800961 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530962 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 return;
964
965nla_put_failure:
966 kfree_skb(skb);
967 return;
968}
969
970/**
971 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
972 * @ctx: Pointer to hdd context
973 * @pData: Pointer to scan event indication param
974 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800975 * This callback execute in atomic context and must not invoke any
976 * blocking calls.
977 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 * Return: none
979 */
980static void
981wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
982 tpSirExtScanOnScanEventIndParams
983 pData)
984{
985 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
986 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800987 int flags = cds_get_gfp_flags();
Mukul Sharmafa937be2016-08-12 18:13:36 +0530988 struct hdd_ext_scan_context *context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989
990 ENTER();
991
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530992 if (wlan_hdd_validate_context(pHddCtx))
993 return;
994 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700995 hdd_err("pData is null");
Mukul Sharma45114d92016-08-12 19:34:14 +0530996 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997 return;
998 }
999
1000 skb = cfg80211_vendor_event_alloc(
1001 pHddCtx->wiphy,
1002 NULL,
1003 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1004 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001005 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006
1007 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001008 hdd_err("cfg80211_vendor_event_alloc failed");
Mukul Sharma45114d92016-08-12 19:34:14 +05301009 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010 return;
1011 }
Mukul Sharmafa937be2016-08-12 18:13:36 +05301012
1013 hdd_notice("Request Id %u Scan event type %u Scan event status %u buckets scanned %u",
1014 pData->requestId, pData->scanEventType, pData->status,
1015 pData->buckets_scanned);
1016
Mukul Sharmafa937be2016-08-12 18:13:36 +05301017 context = &ext_scan_context;
1018 spin_lock(&context->context_lock);
1019 if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT) {
1020 context->buckets_scanned = 0;
1021 pData->scanEventType = WIFI_EXTSCAN_RESULTS_AVAILABLE;
1022 spin_unlock(&context->context_lock);
1023 } else if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_STARTED_EVENT) {
1024 context->buckets_scanned = pData->buckets_scanned;
1025 /* No need to report to user space */
1026 spin_unlock(&context->context_lock);
Mukul Sharma45114d92016-08-12 19:34:14 +05301027 goto nla_put_failure;
Mukul Sharmafa937be2016-08-12 18:13:36 +05301028 } else {
1029 spin_unlock(&context->context_lock);
1030 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031
1032 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1033 pData->requestId) ||
1034 nla_put_u8(skb,
1035 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
Mukul Sharmafa937be2016-08-12 18:13:36 +05301036 pData->scanEventType)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001037 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 goto nla_put_failure;
1039 }
1040
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001041 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301042 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043 return;
1044
1045nla_put_failure:
1046 kfree_skb(skb);
Mukul Sharma45114d92016-08-12 19:34:14 +05301047 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048 return;
1049}
1050
1051/**
1052 * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found
1053 * @hddctx: HDD context
1054 * @data: matched network data
1055 *
1056 * This function reads the matched network data and fills NL vendor attributes
1057 * and send it to upper layer.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001058 * This callback execute in atomic context and must not invoke any
1059 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 *
1061 * Return: 0 on success, error number otherwise
1062 */
1063static void
1064wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
1065 struct pno_match_found *data)
1066{
1067 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
1068 struct sk_buff *skb = NULL;
1069 uint32_t len, i;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001070 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071
1072 ENTER();
1073
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301074 if (wlan_hdd_validate_context(pHddCtx))
1075 return;
1076 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001077 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 return;
1079 }
1080
1081 /*
1082 * If the number of match found APs including IE data exceeds NL 4K size
1083 * limitation, drop that beacon/probe rsp frame.
1084 */
1085 len = sizeof(*data) +
1086 (data->num_results + sizeof(tSirWifiScanResult));
1087 for (i = 0; i < data->num_results; i++)
1088 len += data->ap[i].ieLength;
1089
1090 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001091 hdd_err("Frame exceeded NL size limitation, drop it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092 return;
1093 }
1094
1095 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1096 NULL,
1097 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1098 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001099 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001100
1101 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001102 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 return;
1104 }
1105
Jeff Johnson630f9e72016-07-25 12:00:12 -07001106 hdd_notice("Req Id %u More Data %u num_results %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107 data->request_id, data->more_data, data->num_results);
1108 for (i = 0; i < data->num_results; i++) {
1109 data->ap[i].channel = cds_chan_to_freq(data->ap[i].channel);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001110 hdd_notice("AP Info: Timestamp %llu) Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 "Bssid (" MAC_ADDRESS_STR ") "
1112 "Channel %u "
1113 "Rssi %d "
1114 "RTT %u "
1115 "RTT_SD %u "
1116 "Bcn Period %d "
1117 "Capability 0x%X "
1118 "IE Length %d",
1119 data->ap[i].ts,
1120 data->ap[i].ssid,
1121 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
1122 data->ap[i].channel,
1123 data->ap[i].rssi,
1124 data->ap[i].rtt,
1125 data->ap[i].rtt_sd,
1126 data->ap[i].beaconPeriod,
1127 data->ap[i].capability,
1128 data->ap[i].ieLength);
1129 }
1130
1131 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1132 data->request_id) ||
1133 nla_put_u32(skb,
1134 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1135 data->num_results) ||
1136 nla_put_u8(skb,
1137 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1138 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001139 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 goto fail;
1141 }
1142
1143 if (data->num_results) {
1144 struct nlattr *nla_aps;
1145 nla_aps = nla_nest_start(skb,
1146 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1147 if (!nla_aps)
1148 goto fail;
1149
1150 for (i = 0; i < data->num_results; i++) {
1151 if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i))
1152 goto fail;
1153 }
1154 nla_nest_end(skb, nla_aps);
1155 }
1156
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001157 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158 return;
1159
1160fail:
1161 kfree_skb(skb);
1162 return;
1163}
1164
1165/**
1166 * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found
1167 * @hddctx: HDD context
1168 * @data: matched network data
1169 *
1170 * This function reads the match network %data and fill in the skb with
1171 * NL attributes and send up the NL event
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001172 * This callback execute in atomic context and must not invoke any
1173 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 *
1175 * Return: none
1176 */
1177static void
1178wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
1179 struct wifi_passpoint_match *data)
1180{
1181 hdd_context_t *pHddCtx = ctx;
1182 struct sk_buff *skb = NULL;
1183 uint32_t len, i, num_matches = 1, more_data = 0;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001184 struct nlattr *nla_aps, *nla_bss;
1185 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186
1187 ENTER();
1188
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301189 if (wlan_hdd_validate_context(pHddCtx))
1190 return;
1191 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001192 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001193 return;
1194 }
1195
1196 len = sizeof(*data) + data->ap.ieLength + data->anqp_len;
1197 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001198 hdd_err("Result exceeded NL size limitation, drop it");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 return;
1200 }
1201
1202 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1203 NULL,
1204 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1205 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001206 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207
1208 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001209 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210 return;
1211 }
1212
Jeff Johnson630f9e72016-07-25 12:00:12 -07001213 hdd_notice("Req Id %u Id %u ANQP length %u num_matches %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001214 data->request_id, data->id, data->anqp_len, num_matches);
1215 for (i = 0; i < num_matches; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001216 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 "Bssid (" MAC_ADDRESS_STR ") "
1218 "Channel %u "
1219 "Rssi %d "
1220 "RTT %u "
1221 "RTT_SD %u "
1222 "Bcn Period %d "
1223 "Capability 0x%X "
1224 "IE Length %d",
1225 data->ap.ts,
1226 data->ap.ssid,
1227 MAC_ADDR_ARRAY(data->ap.bssid.bytes),
1228 data->ap.channel,
1229 data->ap.rssi,
1230 data->ap.rtt,
1231 data->ap.rtt_sd,
1232 data->ap.beaconPeriod,
1233 data->ap.capability,
1234 data->ap.ieLength);
1235 }
1236
1237 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1238 data->request_id) ||
1239 nla_put_u32(skb,
1240 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES,
1241 num_matches) ||
1242 nla_put_u8(skb,
1243 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1244 more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001245 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 goto fail;
1247 }
1248
1249 nla_aps = nla_nest_start(skb,
1250 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST);
1251 if (!nla_aps)
1252 goto fail;
1253
1254 for (i = 0; i < num_matches; i++) {
1255 struct nlattr *nla_ap;
1256
1257 nla_ap = nla_nest_start(skb, i);
1258 if (!nla_ap)
1259 goto fail;
1260
1261 if (nla_put_u32(skb,
1262 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID,
1263 data->id) ||
1264 nla_put_u32(skb,
1265 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN,
1266 data->anqp_len)) {
1267 goto fail;
1268 }
1269
1270 if (data->anqp_len)
1271 if (nla_put(skb,
1272 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP,
1273 data->anqp_len, data->anqp))
1274 goto fail;
1275
1276 nla_bss = nla_nest_start(skb,
1277 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1278 if (!nla_bss)
1279 goto fail;
1280
1281 if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0))
1282 goto fail;
1283
1284 nla_nest_end(skb, nla_bss);
1285 nla_nest_end(skb, nla_ap);
1286 }
1287 nla_nest_end(skb, nla_aps);
1288
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001289 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001290 return;
1291
1292fail:
1293 kfree_skb(skb);
1294 return;
1295}
1296
1297/**
1298 * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() -
1299 * Handle an SSID hotlist match event
1300 * @ctx: HDD context registered with SME
1301 * @event: The SSID hotlist match event
1302 *
1303 * This function will take an SSID match event that was generated by
1304 * firmware and will convert it into a cfg80211 vendor event which is
1305 * sent to userspace.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001306 * This callback execute in atomic context and must not invoke any
1307 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308 *
1309 * Return: none
1310 */
1311static void
1312wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
1313 tpSirWifiScanResultEvent event)
1314{
1315 hdd_context_t *hdd_ctx = ctx;
1316 struct sk_buff *skb;
1317 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001318 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001319
1320 ENTER();
1321
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301322 if (wlan_hdd_validate_context(hdd_ctx))
1323 return;
1324 if (!event) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001325 hdd_err("event is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 return;
1327 }
1328
1329 if (event->ap_found) {
1330 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001331 hdd_notice("SSID hotlist found");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332 } else {
1333 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001334 hdd_notice("SSID hotlist lost");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001335 }
1336
1337 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1338 NULL,
1339 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001340 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341
1342 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001343 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344 return;
1345 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07001346 hdd_notice("Req Id %u, Num results %u, More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347 event->requestId, event->numOfAps, event->moreData);
1348
1349 for (i = 0; i < event->numOfAps; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001350 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351 "Ssid: %s "
1352 "Bssid (" MAC_ADDRESS_STR ") "
1353 "Channel %u "
1354 "Rssi %d "
1355 "RTT %u "
1356 "RTT_SD %u",
1357 i,
1358 event->ap[i].ts,
1359 event->ap[i].ssid,
1360 MAC_ADDR_ARRAY(event->ap[i].bssid.bytes),
1361 event->ap[i].channel,
1362 event->ap[i].rssi,
1363 event->ap[i].rtt,
1364 event->ap[i].rtt_sd);
1365 }
1366
1367 if (nla_put_u32(skb,
1368 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1369 event->requestId) ||
1370 nla_put_u32(skb,
1371 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1372 event->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001373 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 goto fail;
1375 }
1376
1377 if (event->numOfAps) {
1378 struct nlattr *aps;
1379 aps = nla_nest_start(skb,
1380 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1381 if (!aps) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001382 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 goto fail;
1384 }
1385
1386 for (i = 0; i < event->numOfAps; i++) {
1387 struct nlattr *ap;
1388
1389 ap = nla_nest_start(skb, i);
1390 if (!ap) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001391 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 goto fail;
1393 }
1394
1395 if (nla_put_u64(skb,
1396 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
1397 event->ap[i].ts) ||
1398 nla_put(skb,
1399 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
1400 sizeof(event->ap[i].ssid),
1401 event->ap[i].ssid) ||
1402 nla_put(skb,
1403 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
1404 sizeof(event->ap[i].bssid),
1405 event->ap[i].bssid.bytes) ||
1406 nla_put_u32(skb,
1407 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
1408 event->ap[i].channel) ||
1409 nla_put_s32(skb,
1410 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
1411 event->ap[i].rssi) ||
1412 nla_put_u32(skb,
1413 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
1414 event->ap[i].rtt) ||
1415 nla_put_u32(skb,
1416 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
1417 event->ap[i].rtt_sd)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001418 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001419 goto fail;
1420 }
1421 nla_nest_end(skb, ap);
1422 }
1423 nla_nest_end(skb, aps);
1424
1425 if (nla_put_u8(skb,
1426 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1427 event->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001428 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429 goto fail;
1430 }
1431 }
1432
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001433 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 return;
1435
1436fail:
1437 kfree_skb(skb);
1438 return;
1439}
1440
1441/**
1442 * wlan_hdd_cfg80211_extscan_generic_rsp() -
1443 * Handle a generic ExtScan Response message
1444 * @ctx: HDD context registered with SME
1445 * @response: The ExtScan response from firmware
1446 *
1447 * This function will handle a generic ExtScan response message from
1448 * firmware and will communicate the result to the userspace thread
1449 * that is waiting for the response.
1450 *
1451 * Return: none
1452 */
1453static void
1454wlan_hdd_cfg80211_extscan_generic_rsp
1455 (void *ctx,
1456 struct sir_extscan_generic_response *response)
1457{
1458 hdd_context_t *hdd_ctx = ctx;
1459 struct hdd_ext_scan_context *context;
1460
1461 ENTER();
1462
1463 if (wlan_hdd_validate_context(hdd_ctx) || !response) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001464 hdd_err("HDD context is not valid or response(%p) is null",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 response);
1466 return;
1467 }
1468
Jeff Johnson630f9e72016-07-25 12:00:12 -07001469 hdd_notice("request %u status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470 response->request_id, response->status);
1471
1472 context = &ext_scan_context;
1473 spin_lock(&context->context_lock);
1474 if (context->request_id == response->request_id) {
1475 context->response_status = response->status ? -EINVAL : 0;
1476 complete(&context->response_event);
1477 }
1478 spin_unlock(&context->context_lock);
1479
1480 return;
1481}
1482
1483/**
1484 * wlan_hdd_cfg80211_extscan_callback() - ext scan callback
1485 * @ctx: Pointer to hdd context
1486 * @evType: Event type
1487 * @pMag: Pointer to message
1488 *
1489 * Return: none
1490 */
1491void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType,
1492 void *pMsg)
1493{
1494 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1495
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301496 ENTER();
1497
1498 if (wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500
Jeff Johnson630f9e72016-07-25 12:00:12 -07001501 hdd_notice("Rcvd Event %d", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502
1503 switch (evType) {
1504 case eSIR_EXTSCAN_CACHED_RESULTS_RSP:
1505 /* There is no need to send this response to upper layer
1506 Just log the message */
Jeff Johnson630f9e72016-07-25 12:00:12 -07001507 hdd_notice("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 break;
1509
1510 case eSIR_EXTSCAN_GET_CAPABILITIES_IND:
1511 wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx,
1512 (struct ext_scan_capabilities_response *) pMsg);
1513 break;
1514
1515 case eSIR_EXTSCAN_HOTLIST_MATCH_IND:
1516 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
1517 break;
1518
1519 case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND:
1520 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx,
1521 (tpSirWifiSignificantChangeEvent) pMsg);
1522 break;
1523
1524 case eSIR_EXTSCAN_CACHED_RESULTS_IND:
1525 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
1526 break;
1527
1528 case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND:
1529 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx,
1530 (tpSirExtScanResultsAvailableIndParams) pMsg);
1531 break;
1532
1533 case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND:
1534 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx,
1535 (tpSirWifiFullScanResultEvent) pMsg);
1536 break;
1537
1538 case eSIR_EPNO_NETWORK_FOUND_IND:
1539 wlan_hdd_cfg80211_extscan_epno_match_found(ctx,
1540 (struct pno_match_found *)pMsg);
1541 break;
1542
1543 case eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND:
1544 wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx,
1545 (tpSirWifiScanResultEvent)pMsg);
1546 break;
1547
1548 case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND:
1549 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx,
1550 (tpSirExtScanOnScanEventIndParams) pMsg);
1551 break;
1552
1553 case eSIR_PASSPOINT_NETWORK_FOUND_IND:
1554 wlan_hdd_cfg80211_passpoint_match_found(ctx,
1555 (struct wifi_passpoint_match *) pMsg);
1556 break;
1557
1558 case eSIR_EXTSCAN_START_RSP:
1559 case eSIR_EXTSCAN_STOP_RSP:
1560 case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP:
1561 case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP:
1562 case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP:
1563 case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP:
1564 case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP:
1565 case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP:
1566 wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg);
1567 break;
1568
1569 default:
Jeff Johnson630f9e72016-07-25 12:00:12 -07001570 hdd_err("Unknown event type %u", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001571 break;
1572 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301573 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001574}
1575
1576/*
1577 * define short names for the global vendor params
1578 * used by wlan_hdd_send_ext_scan_capability()
1579 */
1580#define PARAM_REQUEST_ID \
1581 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1582#define PARAM_STATUS \
1583 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1584#define MAX_SCAN_CACHE_SIZE \
1585 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1586#define MAX_SCAN_BUCKETS \
1587 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1588#define MAX_AP_CACHE_PER_SCAN \
1589 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1590#define MAX_RSSI_SAMPLE_SIZE \
1591 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1592#define MAX_SCAN_RPT_THRHOLD \
1593 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1594#define MAX_HOTLIST_BSSIDS \
1595 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1596#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1597 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1598#define MAX_BSSID_HISTORY_ENTRIES \
1599 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1600#define MAX_HOTLIST_SSIDS \
1601 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1602#define MAX_NUM_EPNO_NETS \
1603 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1604#define MAX_NUM_EPNO_NETS_BY_SSID \
1605 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1606#define MAX_NUM_WHITELISTED_SSID \
1607 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
1608
1609/**
1610 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1611 * @hdd_ctx: Pointer to hdd context
1612 *
1613 * Return: 0 for success, non-zero for failure
1614 */
1615static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx)
1616{
1617 int ret;
1618 struct sk_buff *skb;
1619 struct ext_scan_capabilities_response *data;
1620 uint32_t nl_buf_len;
1621
1622 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301623 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001624 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625
1626 data = &(ext_scan_context.capability_response);
1627
1628 nl_buf_len = NLMSG_HDRLEN;
1629 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1630 (sizeof(data->status) + NLA_HDRLEN) +
1631 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1632 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1633 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1634 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1635 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1636 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1637 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1638 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1639 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1640 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1641 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
1642 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN);
1643
1644 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1645
1646 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001647 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 return -ENOMEM;
1649 }
1650
1651
Jeff Johnson630f9e72016-07-25 12:00:12 -07001652 hdd_notice("Req Id %u", data->requestId);
1653 hdd_notice("Status %u", data->status);
1654 hdd_notice("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001655 data->max_scan_cache_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001656 hdd_notice("Scan buckets %u", data->max_scan_buckets);
1657 hdd_notice("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 data->max_ap_cache_per_scan);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001659 hdd_notice("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001660 data->max_rssi_sample_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001661 hdd_notice("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 data->max_scan_reporting_threshold);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001663 hdd_notice("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 data->max_hotlist_bssids);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001665 hdd_notice("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 data->max_significant_wifi_change_aps);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001667 hdd_notice("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668 data->max_bssid_history_entries);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001669 hdd_notice("max_hotlist_ssids %u", data->max_hotlist_ssids);
1670 hdd_notice("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671 data->max_number_epno_networks);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001672 hdd_notice("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673 data->max_number_epno_networks_by_ssid);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001674 hdd_notice("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001675 data->max_number_of_white_listed_ssid);
1676
1677 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1678 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1679 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1680 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1681 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1682 data->max_ap_cache_per_scan) ||
1683 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1684 data->max_rssi_sample_size) ||
1685 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1686 data->max_scan_reporting_threshold) ||
1687 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1688 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1689 data->max_significant_wifi_change_aps) ||
1690 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1691 data->max_bssid_history_entries) ||
1692 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1693 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1694 data->max_number_epno_networks) ||
1695 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1696 data->max_number_epno_networks_by_ssid) ||
1697 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
1698 data->max_number_of_white_listed_ssid)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001699 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001700 goto nla_put_failure;
1701 }
1702
1703 cfg80211_vendor_cmd_reply(skb);
1704 return 0;
1705
1706nla_put_failure:
1707 kfree_skb(skb);
1708 return -EINVAL;
1709}
1710/*
1711 * done with short names for the global vendor params
1712 * used by wlan_hdd_send_ext_scan_capability()
1713 */
1714#undef PARAM_REQUEST_ID
1715#undef PARAM_STATUS
1716#undef MAX_SCAN_CACHE_SIZE
1717#undef MAX_SCAN_BUCKETS
1718#undef MAX_AP_CACHE_PER_SCAN
1719#undef MAX_RSSI_SAMPLE_SIZE
1720#undef MAX_SCAN_RPT_THRHOLD
1721#undef MAX_HOTLIST_BSSIDS
1722#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1723#undef MAX_BSSID_HISTORY_ENTRIES
1724#undef MAX_HOTLIST_SSIDS
1725#undef MAX_NUM_EPNO_NETS
1726#undef MAX_NUM_EPNO_NETS_BY_SSID
1727#undef MAX_NUM_WHITELISTED_SSID
1728
1729/**
1730 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1731 * @wiphy: Pointer to wireless phy
1732 * @wdev: Pointer to wireless device
1733 * @data: Pointer to data
1734 * @data_len: Data length
1735 *
1736 * Return: none
1737 */
1738static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1739 struct wireless_dev *wdev,
1740 const void *data, int data_len)
1741{
1742 int ret;
1743 unsigned long rc;
1744 struct hdd_ext_scan_context *context;
1745 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1746 struct net_device *dev = wdev->netdev;
1747 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1748 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1749 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1750 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301751 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752
Jeff Johnson1f61b612016-02-12 16:28:33 -08001753 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754
Anurag Chouhan6d760662016-02-20 16:05:43 +05301755 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756 hdd_err("Command not allowed in FTM mode");
1757 return -EPERM;
1758 }
1759
1760 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301761 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301764 if (!pHddCtx->config->extscan_enabled) {
1765 hdd_err("extscan not supported");
1766 return -ENOTSUPP;
1767 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001768 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1769 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001770 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771 return -EINVAL;
1772 }
1773
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301774 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001776 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777 return -ENOMEM;
1778 }
1779
1780 /* Parse and fetch request Id */
1781 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001782 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001783 goto fail;
1784 }
1785
1786 pReqMsg->requestId =
1787 nla_get_u32(tb
1788 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
1789 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001790 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001791 pReqMsg->requestId, pReqMsg->sessionId);
1792
1793 context = &ext_scan_context;
1794 spin_lock(&context->context_lock);
1795 context->request_id = pReqMsg->requestId;
1796 INIT_COMPLETION(context->response_event);
1797 spin_unlock(&context->context_lock);
1798
1799 status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301800 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001801 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001802 status);
1803 goto fail;
1804 }
1805
1806 rc = wait_for_completion_timeout(&context->response_event,
1807 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1808 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001809 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 return -ETIMEDOUT;
1811 }
1812
1813 ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
1814 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001815 hdd_err("Failed to send ext scan capability to user space");
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301816 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001817 return ret;
1818fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301819 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 return -EINVAL;
1821}
1822
1823/**
1824 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1825 * @wiphy: Pointer to wiphy
1826 * @wdev: Pointer to wdev
1827 * @data: Pointer to data
1828 * @data_len: Data length
1829 *
1830 * Return: 0 for success, non-zero for failure
1831 */
1832int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1833 struct wireless_dev *wdev,
1834 const void *data, int data_len)
1835{
1836 int ret = 0;
1837
1838 cds_ssr_protect(__func__);
1839 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1840 data_len);
1841 cds_ssr_unprotect(__func__);
1842
1843 return ret;
1844}
1845
1846/*
1847 * define short names for the global vendor params
1848 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1849 */
1850#define PARAM_MAX \
1851 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1852#define PARAM_REQUEST_ID \
1853 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1854#define PARAM_FLUSH \
1855 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1856/**
1857 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1858 * @wiphy: wiphy pointer
1859 * @wdev: pointer to struct wireless_dev
1860 * @data: pointer to incoming NL vendor data
1861 * @data_len: length of @data
1862 *
1863 * This function parses the incoming NL vendor command data attributes and
1864 * invokes the SME Api and blocks on a completion variable.
1865 * Each WMI event with cached scan results data chunk results in
1866 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1867 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1868 *
1869 * If timeout happens before receiving all of the data, this function sets
1870 * a context variable @ignore_cached_results to %true, all of the next data
1871 * chunks are checked against this variable and dropped.
1872 *
1873 * Return: 0 on success; error number otherwise.
1874 */
1875static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1876 struct wireless_dev
1877 *wdev, const void *data,
1878 int data_len)
1879{
1880 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1881 struct net_device *dev = wdev->netdev;
1882 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1883 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1884 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1885 1];
1886 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301887 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888 int retval = 0;
1889 unsigned long rc;
1890
Jeff Johnson1f61b612016-02-12 16:28:33 -08001891 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892
Anurag Chouhan6d760662016-02-20 16:05:43 +05301893 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 hdd_err("Command not allowed in FTM mode");
1895 return -EPERM;
1896 }
1897
1898 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301899 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301902 if (!pHddCtx->config->extscan_enabled) {
1903 hdd_err("extscan not supported");
1904 return -ENOTSUPP;
1905 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 if (nla_parse(tb, PARAM_MAX, data, data_len,
1907 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001908 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 return -EINVAL;
1910 }
1911
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301912 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001914 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001915 return -ENOMEM;
1916 }
1917
1918 /* Parse and fetch request Id */
1919 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001920 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 goto fail;
1922 }
1923
1924 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
1925 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001926 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 pReqMsg->requestId, pReqMsg->sessionId);
1928
1929 /* Parse and fetch flush parameter */
1930 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001931 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 goto fail;
1933 }
1934 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001935 hdd_notice("Flush %d", pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936
1937 context = &ext_scan_context;
1938 spin_lock(&context->context_lock);
1939 context->request_id = pReqMsg->requestId;
1940 context->ignore_cached_results = false;
1941 INIT_COMPLETION(context->response_event);
1942 spin_unlock(&context->context_lock);
1943
1944 status = sme_get_cached_results(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301945 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001946 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 goto fail;
1948 }
1949
1950 rc = wait_for_completion_timeout(&context->response_event,
1951 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1952 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001953 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 retval = -ETIMEDOUT;
1955 spin_lock(&context->context_lock);
1956 context->ignore_cached_results = true;
1957 spin_unlock(&context->context_lock);
1958 } else {
1959 spin_lock(&context->context_lock);
1960 retval = context->response_status;
1961 spin_unlock(&context->context_lock);
1962 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301963 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001964 return retval;
1965
1966fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301967 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return -EINVAL;
1969}
1970/*
1971 * done with short names for the global vendor params
1972 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1973 */
1974#undef PARAM_MAX
1975#undef PARAM_REQUEST_ID
1976#undef PARAM_FLUSH
1977
1978/**
1979 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1980 * @wiphy: wiphy pointer
1981 * @wdev: pointer to struct wireless_dev
1982 * @data: pointer to incoming NL vendor data
1983 * @data_len: length of @data
1984 *
1985 * This function parses the incoming NL vendor command data attributes and
1986 * invokes the SME Api and blocks on a completion variable.
1987 * Each WMI event with cached scan results data chunk results in
1988 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1989 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1990 *
1991 * If timeout happens before receiving all of the data, this function sets
1992 * a context variable @ignore_cached_results to %true, all of the next data
1993 * chunks are checked against this variable and dropped.
1994 *
1995 * Return: 0 on success; error number otherwise.
1996 */
1997int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1998 struct wireless_dev *wdev,
1999 const void *data, int data_len)
2000{
2001 int ret = 0;
2002
2003 cds_ssr_protect(__func__);
2004 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
2005 data_len);
2006 cds_ssr_unprotect(__func__);
2007
2008 return ret;
2009}
2010
2011/**
2012 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
2013 * @wiphy: Pointer to wireless phy
2014 * @wdev: Pointer to wireless device
2015 * @data: Pointer to data
2016 * @data_len: Data length
2017 *
2018 * Return: none
2019 */
2020static int
2021__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2022 struct wireless_dev
2023 *wdev, const void *data,
2024 int data_len)
2025{
2026 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
2027 struct net_device *dev = wdev->netdev;
2028 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2029 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2030 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2031 1];
2032 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2033 + 1];
2034 struct nlattr *apTh;
2035 struct hdd_ext_scan_context *context;
2036 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302037 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 uint8_t i;
2039 int rem, retval;
2040 unsigned long rc;
2041
Jeff Johnson1f61b612016-02-12 16:28:33 -08002042 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002043
Anurag Chouhan6d760662016-02-20 16:05:43 +05302044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 hdd_err("Command not allowed in FTM mode");
2046 return -EPERM;
2047 }
2048
2049 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302050 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002051 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302053 if (!pHddCtx->config->extscan_enabled) {
2054 hdd_err("extscan not supported");
2055 return -ENOTSUPP;
2056 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002057 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2058 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002059 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002060 return -EINVAL;
2061 }
2062
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302063 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002065 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002066 return -ENOMEM;
2067 }
2068
2069 /* Parse and fetch request Id */
2070 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002071 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 goto fail;
2073 }
2074
2075 pReqMsg->requestId =
2076 nla_get_u32(tb
2077 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002078 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002079
2080 /* Parse and fetch number of APs */
2081 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002082 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 goto fail;
2084 }
2085 pReqMsg->numAp =
2086 nla_get_u32(tb
2087 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
2088 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002089 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002090 pReqMsg->numAp, pReqMsg->sessionId);
2091
2092 /* Parse and fetch lost ap sample size */
2093 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002094 hdd_err("attr lost ap sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 goto fail;
2096 }
2097
2098 pReqMsg->lost_ap_sample_size = nla_get_u32(
2099 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002100 hdd_notice("Lost ap sample size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002101 pReqMsg->lost_ap_sample_size);
2102
2103 i = 0;
2104 nla_for_each_nested(apTh,
2105 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2106 rem) {
2107 if (nla_parse
2108 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2109 nla_data(apTh), nla_len(apTh),
2110 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002111 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002112 goto fail;
2113 }
2114
2115 /* Parse and fetch MAC address */
2116 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002117 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002118 goto fail;
2119 }
2120 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2121 tb2
2122 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302123 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002124 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002125 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2126
2127 /* Parse and fetch low RSSI */
2128 if (!tb2
2129 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002130 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002131 goto fail;
2132 }
2133 pReqMsg->ap[i].low =
2134 nla_get_s32(tb2
2135 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002136 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002137
2138 /* Parse and fetch high RSSI */
2139 if (!tb2
2140 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002141 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142 goto fail;
2143 }
2144 pReqMsg->ap[i].high =
2145 nla_get_s32(tb2
2146 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002147 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002148
2149 i++;
2150 }
2151
2152 context = &ext_scan_context;
2153 spin_lock(&context->context_lock);
2154 INIT_COMPLETION(context->response_event);
2155 context->request_id = request_id = pReqMsg->requestId;
2156 spin_unlock(&context->context_lock);
2157
2158 status = sme_set_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302159 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002160 hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002161 goto fail;
2162 }
2163
2164 /* request was sent -- wait for the response */
2165 rc = wait_for_completion_timeout
2166 (&context->response_event,
2167 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2168
2169 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002170 hdd_err("sme_set_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 retval = -ETIMEDOUT;
2172 } else {
2173 spin_lock(&context->context_lock);
2174 if (context->request_id == request_id)
2175 retval = context->response_status;
2176 else
2177 retval = -EINVAL;
2178 spin_unlock(&context->context_lock);
2179 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302180 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 return retval;
2182
2183fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302184 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 return -EINVAL;
2186}
2187
2188/**
2189 * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist
2190 * @wiphy: Pointer to wiphy
2191 * @wdev: Pointer to wdev
2192 * @data: Pointer to data
2193 * @data_len: Data length
2194 *
2195 * Return: 0 for success, non-zero for failure
2196 */
2197int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2198 struct wireless_dev *wdev,
2199 const void *data, int data_len)
2200{
2201 int ret = 0;
2202
2203 cds_ssr_protect(__func__);
2204 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
2205 data_len);
2206 cds_ssr_unprotect(__func__);
2207
2208 return ret;
2209}
2210
2211
2212/**
2213 * __wlan_hdd_cfg80211_extscan_set_significant_change () - set significant change
2214 * @wiphy: Pointer to wireless phy
2215 * @wdev: Pointer to wireless device
2216 * @data: Pointer to data
2217 * @data_len: Data length
2218 *
2219 * Return: none
2220 */
2221static int
2222__wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2223 struct wireless_dev
2224 *wdev, const void *data,
2225 int data_len)
2226{
2227 tpSirExtScanSetSigChangeReqParams pReqMsg = NULL;
2228 struct net_device *dev = wdev->netdev;
2229 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2230 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2231 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2232 1];
2233 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2234 + 1];
2235 struct nlattr *apTh;
2236 struct hdd_ext_scan_context *context;
2237 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302238 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002239 uint8_t i;
2240 int rem, retval;
2241 unsigned long rc;
2242
Jeff Johnson1f61b612016-02-12 16:28:33 -08002243 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002244
Anurag Chouhan6d760662016-02-20 16:05:43 +05302245 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002246 hdd_err("Command not allowed in FTM mode");
2247 return -EPERM;
2248 }
2249
2250 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302251 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002252 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002253
2254 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2255 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002256 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257 return -EINVAL;
2258 }
2259
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302260 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002261 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002262 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002263 return -ENOMEM;
2264 }
2265
2266 /* Parse and fetch request Id */
2267 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002268 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 goto fail;
2270 }
2271
2272 pReqMsg->requestId =
2273 nla_get_u32(tb
2274 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002275 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002276
2277 /* Parse and fetch RSSI sample size */
2278 if (!tb
2279 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002280 hdd_err("attr RSSI sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002281 goto fail;
2282 }
2283 pReqMsg->rssiSampleSize =
2284 nla_get_u32(tb
2285 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002286 hdd_notice("RSSI sample size %u", pReqMsg->rssiSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002287
2288 /* Parse and fetch lost AP sample size */
2289 if (!tb
2290 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002291 hdd_err("attr lost AP sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002292 goto fail;
2293 }
2294 pReqMsg->lostApSampleSize =
2295 nla_get_u32(tb
2296 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002297 hdd_notice("Lost AP sample size %u", pReqMsg->lostApSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002298
2299 /* Parse and fetch AP min breacing */
2300 if (!tb
2301 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002302 hdd_err("attr AP min breaching");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 goto fail;
2304 }
2305 pReqMsg->minBreaching =
2306 nla_get_u32(tb
2307 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002308 hdd_notice("AP min breaching %u", pReqMsg->minBreaching);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002309
2310 /* Parse and fetch number of APs */
2311 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002312 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313 goto fail;
2314 }
2315 pReqMsg->numAp =
2316 nla_get_u32(tb
2317 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
2318 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002319 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002320 pReqMsg->numAp, pReqMsg->sessionId);
2321
2322 i = 0;
2323 nla_for_each_nested(apTh,
2324 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2325 rem) {
2326 if (nla_parse
2327 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2328 nla_data(apTh), nla_len(apTh),
2329 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002330 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002331 goto fail;
2332 }
2333
2334 /* Parse and fetch MAC address */
2335 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002336 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 goto fail;
2338 }
2339 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2340 tb2
2341 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302342 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002343 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2345
2346 /* Parse and fetch low RSSI */
2347 if (!tb2
2348 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002349 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 goto fail;
2351 }
2352 pReqMsg->ap[i].low =
2353 nla_get_s32(tb2
2354 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002355 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356
2357 /* Parse and fetch high RSSI */
2358 if (!tb2
2359 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002360 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361 goto fail;
2362 }
2363 pReqMsg->ap[i].high =
2364 nla_get_s32(tb2
2365 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002366 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367
2368 i++;
2369 }
2370
2371 context = &ext_scan_context;
2372 spin_lock(&context->context_lock);
2373 INIT_COMPLETION(context->response_event);
2374 context->request_id = request_id = pReqMsg->requestId;
2375 spin_unlock(&context->context_lock);
2376
2377 status = sme_set_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302378 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002379 hdd_err("sme_set_significant_change failed(err=%d)", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302380 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 return -EINVAL;
2382 }
2383
2384 /* request was sent -- wait for the response */
2385 rc = wait_for_completion_timeout(&context->response_event,
2386 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2387
2388 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002389 hdd_err("sme_set_significant_change timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390 retval = -ETIMEDOUT;
2391 } else {
2392 spin_lock(&context->context_lock);
2393 if (context->request_id == request_id)
2394 retval = context->response_status;
2395 else
2396 retval = -EINVAL;
2397 spin_unlock(&context->context_lock);
2398 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302399 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 return retval;
2401
2402fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302403 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002404 return -EINVAL;
2405}
2406
2407/**
2408 * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
2409 * @wiphy: Pointer to wireless phy
2410 * @wdev: Pointer to wireless device
2411 * @data: Pointer to data
2412 * @data_len: Data length
2413 *
2414 * Return: 0 on success, negative errno on failure
2415 */
2416int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2417 struct wireless_dev *wdev,
2418 const void *data, int data_len)
2419{
2420 int ret = 0;
2421
2422 cds_ssr_protect(__func__);
2423 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev,
2424 data, data_len);
2425 cds_ssr_unprotect(__func__);
2426
2427 return ret;
2428}
2429
2430/**
2431 * hdd_remove_dsrc_channels () - remove dsrc chanels
2432 * @wiphy: Pointer to wireless phy
2433 * @chan_list: channel list
2434 * @num_channels: number of channels
2435 *
2436 * Return: none
2437 */
2438void hdd_remove_dsrc_channels(struct wiphy *wiphy, uint32_t *chan_list,
2439 uint8_t *num_channels)
2440{
2441 uint8_t num_chan_temp = 0;
2442 int i;
2443
2444 for (i = 0; i < *num_channels; i++) {
2445 if (!cds_is_dsrc_channel(chan_list[i])) {
2446 chan_list[num_chan_temp] = chan_list[i];
2447 num_chan_temp++;
2448 }
2449 }
2450
2451 *num_channels = num_chan_temp;
2452}
2453
2454/**
2455 * hdd_remove_indoor_channels () - remove indoor channels
2456 * @wiphy: Pointer to wireless phy
2457 * @chan_list: channel list
2458 * @num_channels: number of channels
2459 *
2460 * Return: none
2461 */
2462#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
2463void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2464 uint8_t *num_channels)
2465{
2466 uint8_t num_chan_temp = 0;
2467 int i, j, k;
2468
2469 for (i = 0; i < *num_channels; i++)
2470 for (j = 0; j < IEEE80211_NUM_BANDS; j++) {
2471 if (wiphy->bands[j] == NULL)
2472 continue;
2473 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
2474 if ((chan_list[i] ==
2475 wiphy->bands[j]->channels[k].center_freq)
2476 && (!(wiphy->bands[j]->channels[k].flags &
2477 IEEE80211_CHAN_INDOOR_ONLY))
2478 ) {
2479 chan_list[num_chan_temp] = chan_list[i];
2480 num_chan_temp++;
2481 }
2482 }
2483 }
2484
2485 *num_channels = num_chan_temp;
2486}
2487#else
2488void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2489 uint8_t *num_channels)
2490{
2491 *num_channels = 0;
2492}
2493#endif
2494
2495/**
2496 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
2497 * @wiphy: Pointer to wireless phy
2498 * @wdev: Pointer to wireless device
2499 * @data: Pointer to data
2500 * @data_len: Data length
2501 *
2502 * Return: none
2503 */
2504static int
2505__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2506 struct wireless_dev
2507 *wdev, const void *data,
2508 int data_len)
2509{
2510 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2511 struct net_device *dev = wdev->netdev;
2512 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2513 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2514 uint8_t num_channels = 0;
2515 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2516 1];
2517 uint32_t requestId, maxChannels;
2518 tWifiBand wifiBand;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302519 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 struct sk_buff *reply_skb;
2521 uint8_t i;
2522 int ret;
2523
Jeff Johnson1f61b612016-02-12 16:28:33 -08002524 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525
Anurag Chouhan6d760662016-02-20 16:05:43 +05302526 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 hdd_err("Command not allowed in FTM mode");
2528 return -EPERM;
2529 }
2530
2531 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302532 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302535 if (!pHddCtx->config->extscan_enabled) {
2536 hdd_err("extscan not supported");
2537 return -ENOTSUPP;
2538 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2540 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002541 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542 return -EINVAL;
2543 }
2544
2545 /* Parse and fetch request Id */
2546 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002547 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 return -EINVAL;
2549 }
2550 requestId =
2551 nla_get_u32(tb
2552 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002553 hdd_notice("Req Id %d", requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554
2555 /* Parse and fetch wifi band */
2556 if (!tb
2557 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002558 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 return -EINVAL;
2560 }
2561 wifiBand =
2562 nla_get_u32(tb
2563 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002564 hdd_notice("Wifi band %d", wifiBand);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565
2566 if (!tb
2567 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002568 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569 return -EINVAL;
2570 }
2571 maxChannels =
2572 nla_get_u32(tb
2573 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002574 hdd_notice("Max channels %d", maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 status = sme_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal),
2576 wifiBand, chan_list,
2577 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302578 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002579 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580 status);
2581 return -EINVAL;
2582 }
2583
Anurag Chouhan6d760662016-02-20 16:05:43 +05302584 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585
2586 hdd_remove_dsrc_channels(wiphy, chan_list, &num_channels);
2587
Krunal Sonibe766b02016-03-10 13:00:44 -08002588 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 !strncmp(hdd_get_fwpath(), "ap", 2))
2590 hdd_remove_indoor_channels(wiphy, chan_list, &num_channels);
2591
Jeff Johnson630f9e72016-07-25 12:00:12 -07002592 hdd_notice("Number of channels %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 for (i = 0; i < num_channels; i++)
Jeff Johnson630f9e72016-07-25 12:00:12 -07002594 hdd_notice("Channel: %u ", chan_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002595
2596 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2597 sizeof(u32) *
2598 num_channels +
2599 NLMSG_HDRLEN);
2600
2601 if (reply_skb) {
2602 if (nla_put_u32(reply_skb,
2603 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2604 num_channels) ||
2605 nla_put(reply_skb,
2606 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2607 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002608 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002609 kfree_skb(reply_skb);
2610 return -EINVAL;
2611 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302612 ret = cfg80211_vendor_cmd_reply(reply_skb);
2613 EXIT();
2614 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002615 }
2616
Jeff Johnson630f9e72016-07-25 12:00:12 -07002617 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618 return -EINVAL;
2619}
2620
2621/**
2622 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2623 * @wiphy: Pointer to wireless phy
2624 * @wdev: Pointer to wireless device
2625 * @data: Pointer to data
2626 * @data_len: Data length
2627 *
2628 * Return: 0 on success, negative errno on failure
2629 */
2630int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2631 struct wireless_dev *wdev,
2632 const void *data, int data_len)
2633{
2634 int ret = 0;
2635
2636 cds_ssr_protect(__func__);
2637 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2638 data_len);
2639 cds_ssr_unprotect(__func__);
2640
2641 return ret;
2642}
2643
2644/**
2645 * hdd_extscan_update_dwell_time_limits() - update dwell times
2646 * @req_msg: Pointer to request message
2647 * @bkt_idx: Index of current bucket being processed
2648 * @active_min: minimum active dwell time
2649 * @active_max: maximum active dwell time
2650 * @passive_min: minimum passive dwell time
2651 * @passive_max: maximum passive dwell time
2652 *
2653 * Return: none
2654 */
2655static void hdd_extscan_update_dwell_time_limits(
2656 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2657 uint32_t active_min, uint32_t active_max,
2658 uint32_t passive_min, uint32_t passive_max)
2659{
2660 /* update per-bucket dwell times */
2661 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2662 active_min) {
2663 req_msg->buckets[bkt_idx].min_dwell_time_active =
2664 active_min;
2665 }
2666 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2667 active_max) {
2668 req_msg->buckets[bkt_idx].max_dwell_time_active =
2669 active_max;
2670 }
2671 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2672 passive_min) {
2673 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2674 passive_min;
2675 }
2676 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2677 passive_max) {
2678 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2679 passive_max;
2680 }
2681 /* update dwell-time across all buckets */
2682 if (req_msg->min_dwell_time_active >
2683 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2684 req_msg->min_dwell_time_active =
2685 req_msg->buckets[bkt_idx].min_dwell_time_active;
2686 }
2687 if (req_msg->max_dwell_time_active <
2688 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2689 req_msg->max_dwell_time_active =
2690 req_msg->buckets[bkt_idx].max_dwell_time_active;
2691 }
2692 if (req_msg->min_dwell_time_passive >
2693 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2694 req_msg->min_dwell_time_passive =
2695 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2696 }
2697 if (req_msg->max_dwell_time_passive >
2698 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2699 req_msg->max_dwell_time_passive =
2700 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2701 }
2702}
2703
2704/**
2705 * hdd_extscan_channel_max_reached() - channel max reached
2706 * @req: extscan request structure
2707 * @total_channels: total number of channels
2708 *
2709 * Return: true if total channels reached max, false otherwise
2710 */
2711static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2712 uint8_t total_channels)
2713{
2714 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2715 hdd_warn(
2716 "max #of channels %d reached, take only first %d bucket(s)",
2717 total_channels, req->numBuckets);
2718 return true;
2719 }
2720 return false;
2721}
2722
2723/**
2724 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2725 * @hdd_ctx: HDD global context
2726 * @req_msg: Pointer to request structure
2727 * @tb: pointer to NL attributes
2728 *
2729 * Return: 0 on success; error number otherwise
2730 */
2731static int hdd_extscan_start_fill_bucket_channel_spec(
2732 hdd_context_t *hdd_ctx,
2733 tpSirWifiScanCmdReqParams req_msg,
2734 struct nlattr **tb)
2735{
2736 struct nlattr *bucket[
2737 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2738 struct nlattr *channel[
2739 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2740 struct nlattr *buckets;
2741 struct nlattr *channels;
2742 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302743 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002744 uint8_t bkt_index, j, num_channels, total_channels = 0;
2745 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2746
2747 uint32_t min_dwell_time_active_bucket =
2748 hdd_ctx->config->extscan_active_max_chn_time;
2749 uint32_t max_dwell_time_active_bucket =
2750 hdd_ctx->config->extscan_active_max_chn_time;
2751 uint32_t min_dwell_time_passive_bucket =
2752 hdd_ctx->config->extscan_passive_max_chn_time;
2753 uint32_t max_dwell_time_passive_bucket =
2754 hdd_ctx->config->extscan_passive_max_chn_time;
2755
2756 bkt_index = 0;
2757 req_msg->min_dwell_time_active =
2758 req_msg->max_dwell_time_active =
2759 hdd_ctx->config->extscan_active_max_chn_time;
2760
2761 req_msg->min_dwell_time_passive =
2762 req_msg->max_dwell_time_passive =
2763 hdd_ctx->config->extscan_passive_max_chn_time;
2764 req_msg->numBuckets = 0;
2765
2766 nla_for_each_nested(buckets,
2767 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
2768 if (nla_parse(bucket,
2769 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2770 nla_data(buckets), nla_len(buckets), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002771 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 return -EINVAL;
2773 }
2774
2775 /* Parse and fetch bucket spec */
2776 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002777 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002778 return -EINVAL;
2779 }
2780 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2781 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002782 hdd_notice("Bucket spec Index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783 req_msg->buckets[bkt_index].bucket);
2784
2785 /* Parse and fetch wifi band */
2786 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002787 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002788 return -EINVAL;
2789 }
2790 req_msg->buckets[bkt_index].band = nla_get_u8(
2791 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002792 hdd_notice("Wifi band %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 req_msg->buckets[bkt_index].band);
2794
2795 /* Parse and fetch period */
2796 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002797 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002798 return -EINVAL;
2799 }
2800 req_msg->buckets[bkt_index].period = nla_get_u32(
2801 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002802 hdd_notice("period %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002803 req_msg->buckets[bkt_index].period);
2804
2805 /* Parse and fetch report events */
2806 if (!bucket[
2807 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002808 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 return -EINVAL;
2810 }
2811 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2812 bucket[
2813 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002814 hdd_notice("report events %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002815 req_msg->buckets[bkt_index].reportEvents);
2816
2817 /* Parse and fetch max period */
2818 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002819 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 return -EINVAL;
2821 }
2822 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2823 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002824 hdd_notice("max period %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002825 req_msg->buckets[bkt_index].max_period);
2826
Mukul Sharmafa937be2016-08-12 18:13:36 +05302827 /* Parse and fetch base */
2828 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]) {
2829 hdd_err("attr base failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 return -EINVAL;
2831 }
2832 req_msg->buckets[bkt_index].exponent = nla_get_u32(
Mukul Sharmafa937be2016-08-12 18:13:36 +05302833 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]);
2834 hdd_notice("base %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835 req_msg->buckets[bkt_index].exponent);
2836
2837 /* Parse and fetch step count */
2838 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002839 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002840 return -EINVAL;
2841 }
2842 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2843 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002844 hdd_notice("Step count %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002845 req_msg->buckets[bkt_index].step_count);
2846
2847 /* start with known good values for bucket dwell times */
2848 req_msg->buckets[bkt_index].min_dwell_time_active =
2849 req_msg->buckets[bkt_index].max_dwell_time_active =
2850 hdd_ctx->config->extscan_active_max_chn_time;
2851
2852 req_msg->buckets[bkt_index].min_dwell_time_passive =
2853 req_msg->buckets[bkt_index].max_dwell_time_passive =
2854 hdd_ctx->config->extscan_passive_max_chn_time;
2855
2856 /* Framework shall pass the channel list if the input WiFi band
2857 * is WIFI_BAND_UNSPECIFIED.
2858 * If the input WiFi band is specified (any value other than
2859 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2860 */
2861 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2862 if (hdd_extscan_channel_max_reached(req_msg,
2863 total_channels))
2864 return 0;
2865
2866 num_channels = 0;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002867 hdd_notice("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002868 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2869 req_msg->buckets[bkt_index].band,
2870 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302871 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002872 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002873 status);
2874 return -EINVAL;
2875 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07002876 hdd_notice("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 num_channels);
2878
2879 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302880 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881 (WLAN_EXTSCAN_MAX_CHANNELS -
2882 total_channels));
2883 hdd_info("Adj Num channels/bucket: %d total_channels: %d",
2884 req_msg->buckets[bkt_index].numChannels,
2885 total_channels);
2886 total_channels +=
2887 req_msg->buckets[bkt_index].numChannels;
2888
2889 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2890 j++) {
2891 req_msg->buckets[bkt_index].channels[j].channel =
2892 chan_list[j];
2893 req_msg->buckets[bkt_index].channels[j].
2894 chnlClass = 0;
2895 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2896 cds_freq_to_chan(chan_list[j]))) {
2897 req_msg->buckets[bkt_index].channels[j].
2898 passive = 1;
2899 req_msg->buckets[bkt_index].channels[j].
2900 dwellTimeMs =
2901 hdd_ctx->config->
2902 extscan_passive_max_chn_time;
2903 /* reconfigure per-bucket dwell time */
2904 if (min_dwell_time_passive_bucket >
2905 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2906 min_dwell_time_passive_bucket =
2907 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2908 }
2909 if (max_dwell_time_passive_bucket <
2910 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2911 max_dwell_time_passive_bucket =
2912 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2913 }
2914
2915 } else {
2916 req_msg->buckets[bkt_index].channels[j].
2917 passive = 0;
2918 req_msg->buckets[bkt_index].channels[j].
2919 dwellTimeMs =
2920 hdd_ctx->config->extscan_active_max_chn_time;
2921 /* reconfigure per-bucket dwell times */
2922 if (min_dwell_time_active_bucket >
2923 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2924 min_dwell_time_active_bucket =
2925 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2926 }
2927 if (max_dwell_time_active_bucket <
2928 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2929 max_dwell_time_active_bucket =
2930 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2931 }
2932
2933 }
2934
Jeff Johnson630f9e72016-07-25 12:00:12 -07002935 hdd_notice("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 req_msg->buckets[bkt_index].channels[j].channel,
2937 req_msg->buckets[bkt_index].channels[j].passive,
2938 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2939 req_msg->buckets[bkt_index].channels[j].chnlClass);
2940 }
2941
2942 hdd_extscan_update_dwell_time_limits(
2943 req_msg, bkt_index,
2944 min_dwell_time_active_bucket,
2945 max_dwell_time_active_bucket,
2946 min_dwell_time_passive_bucket,
2947 max_dwell_time_passive_bucket);
2948
Jeff Johnson630f9e72016-07-25 12:00:12 -07002949 hdd_notice("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 bkt_index,
2951 req_msg->buckets[bkt_index].min_dwell_time_active,
2952 req_msg->buckets[bkt_index].max_dwell_time_active,
2953 req_msg->buckets[bkt_index].min_dwell_time_passive,
2954 req_msg->buckets[bkt_index].max_dwell_time_passive);
2955
2956 bkt_index++;
2957 req_msg->numBuckets++;
2958 continue;
2959 }
2960
2961 /* Parse and fetch number of channels */
2962 if (!bucket[
2963 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002964 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002965 return -EINVAL;
2966 }
2967 req_msg->buckets[bkt_index].numChannels =
2968 nla_get_u32(bucket[
2969 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
2970 hdd_info("before trimming: num channels %d",
2971 req_msg->buckets[bkt_index].numChannels);
2972
2973 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302974 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002975 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
2976 hdd_info("Num channels/bucket: %d total_channels: %d",
2977 req_msg->buckets[bkt_index].numChannels,
2978 total_channels);
2979 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
2980 return 0;
2981
2982 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002983 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 return -EINVAL;
2985 }
2986
2987 j = 0;
2988 nla_for_each_nested(channels,
2989 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07002990 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
2991 hdd_extscan_channel_max_reached(req_msg,
2992 total_channels))
2993 break;
2994
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 if (nla_parse(channel,
2996 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2997 nla_data(channels), nla_len(channels),
2998 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002999 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000 return -EINVAL;
3001 }
3002
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003003 /* Parse and fetch channel */
3004 if (!channel[
3005 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003006 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003007 return -EINVAL;
3008 }
3009 req_msg->buckets[bkt_index].channels[j].channel =
3010 nla_get_u32(channel[
3011 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003012 hdd_notice("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013 req_msg->buckets[bkt_index].channels[j].channel);
3014
3015 /* Parse and fetch dwell time */
3016 if (!channel[
3017 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003018 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003019 return -EINVAL;
3020 }
3021 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3022 nla_get_u32(channel[
3023 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
3024
3025 /* Override dwell time if required */
3026 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
3027 hdd_ctx->config->extscan_active_min_chn_time ||
3028 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
3029 hdd_ctx->config->extscan_active_max_chn_time) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003030 hdd_notice("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3032
3033 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3034 cds_freq_to_chan(
3035 req_msg->buckets[bkt_index].channels[j].channel))) {
3036 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3037 hdd_ctx->config->extscan_passive_max_chn_time;
3038 } else {
3039 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3040 hdd_ctx->config->extscan_active_max_chn_time;
3041 }
3042 }
3043
Jeff Johnson630f9e72016-07-25 12:00:12 -07003044 hdd_notice("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003045 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3046
3047 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3048 cds_freq_to_chan(
3049 req_msg->buckets[bkt_index].channels[j].channel))) {
3050 if (min_dwell_time_passive_bucket >
3051 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3052 min_dwell_time_passive_bucket =
3053 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3054 }
3055 if (max_dwell_time_passive_bucket <
3056 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3057 max_dwell_time_passive_bucket =
3058 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3059 }
3060 } else {
3061 if (min_dwell_time_active_bucket >
3062 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3063 min_dwell_time_active_bucket =
3064 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3065 }
3066 if (max_dwell_time_active_bucket <
3067 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3068 max_dwell_time_active_bucket =
3069 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3070 }
3071 }
3072
3073 /* Parse and fetch channel spec passive */
3074 if (!channel[
3075 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003076 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003077 return -EINVAL;
3078 }
3079 req_msg->buckets[bkt_index].channels[j].passive =
3080 nla_get_u8(channel[
3081 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003082 hdd_notice("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 req_msg->buckets[bkt_index].channels[j].passive);
3084 /* Override scan type if required */
3085 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3086 cds_freq_to_chan(
3087 req_msg->buckets[bkt_index].channels[j].channel))) {
3088 req_msg->buckets[bkt_index].channels[j].passive = true;
3089 } else {
3090 req_msg->buckets[bkt_index].channels[j].passive = false;
3091 }
3092 j++;
3093 total_channels++;
3094 }
3095
3096 hdd_extscan_update_dwell_time_limits(
3097 req_msg, bkt_index,
3098 min_dwell_time_active_bucket,
3099 max_dwell_time_active_bucket,
3100 min_dwell_time_passive_bucket,
3101 max_dwell_time_passive_bucket);
3102
Jeff Johnson630f9e72016-07-25 12:00:12 -07003103 hdd_notice("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 bkt_index,
3105 req_msg->buckets[bkt_index].min_dwell_time_active,
3106 req_msg->buckets[bkt_index].max_dwell_time_active,
3107 req_msg->buckets[bkt_index].min_dwell_time_passive,
3108 req_msg->buckets[bkt_index].max_dwell_time_passive);
3109
3110 bkt_index++;
3111 req_msg->numBuckets++;
3112 }
3113
Jeff Johnson630f9e72016-07-25 12:00:12 -07003114 hdd_notice("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003115 req_msg->min_dwell_time_active,
3116 req_msg->max_dwell_time_active,
3117 req_msg->min_dwell_time_passive,
3118 req_msg->max_dwell_time_passive);
3119
3120 return 0;
3121}
3122
3123/*
3124 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3125 * @config_flags - [input] configuration flags.
3126 *
3127 * This function maps user space received configuration flags to
3128 * driver representation.
3129 *
3130 * Return: configuration flags
3131 */
3132static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3133{
3134 uint32_t configuration_flags = 0;
3135
3136 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3137 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3138
3139 return configuration_flags;
3140}
3141
3142/*
3143 * define short names for the global vendor params
3144 * used by __wlan_hdd_cfg80211_extscan_start()
3145 */
3146#define PARAM_MAX \
3147 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3148#define PARAM_REQUEST_ID \
3149 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3150#define PARAM_BASE_PERIOD \
3151 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3152#define PARAM_MAX_AP_PER_SCAN \
3153 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3154#define PARAM_RPT_THRHLD_PERCENT \
3155 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3156#define PARAM_RPT_THRHLD_NUM_SCANS \
3157 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3158#define PARAM_NUM_BUCKETS \
3159 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3160#define PARAM_CONFIG_FLAGS \
3161 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3162
3163/**
3164 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3165 * @wiphy: Pointer to wireless phy
3166 * @wdev: Pointer to wireless device
3167 * @data: Pointer to data
3168 * @data_len: Length of @data
3169 *
3170 * Return: 0 on success; error number otherwise
3171 */
3172static int
3173__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3174 struct wireless_dev *wdev,
3175 const void *data,
3176 int data_len)
3177{
3178 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3179 struct net_device *dev = wdev->netdev;
3180 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3181 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3182 struct nlattr *tb[PARAM_MAX + 1];
3183 struct hdd_ext_scan_context *context;
3184 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303185 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 int retval;
3187 unsigned long rc;
3188
Jeff Johnson1f61b612016-02-12 16:28:33 -08003189 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190
Anurag Chouhan6d760662016-02-20 16:05:43 +05303191 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 hdd_err("Command not allowed in FTM mode");
3193 return -EPERM;
3194 }
3195
3196 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303197 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303200 if (!pHddCtx->config->extscan_enabled) {
3201 hdd_err("extscan not supported");
3202 return -ENOTSUPP;
3203 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204 if (nla_parse(tb, PARAM_MAX, data, data_len,
3205 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003206 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003207 return -EINVAL;
3208 }
3209
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303210 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003212 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213 return -ENOMEM;
3214 }
3215
3216 /* Parse and fetch request Id */
3217 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003218 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219 goto fail;
3220 }
3221
3222 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3223 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003224 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003225 pReqMsg->requestId,
3226 pReqMsg->sessionId);
3227
3228 /* Parse and fetch base period */
3229 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003230 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003231 goto fail;
3232 }
3233 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003234 hdd_notice("Base Period %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 pReqMsg->basePeriod);
3236
3237 /* Parse and fetch max AP per scan */
3238 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003239 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 goto fail;
3241 }
3242 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003243 hdd_notice("Max AP per Scan %d", pReqMsg->maxAPperScan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
3245 /* Parse and fetch report threshold percent */
3246 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003247 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 goto fail;
3249 }
3250 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003251 hdd_notice("Report Threshold percent %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 pReqMsg->report_threshold_percent);
3253
3254 /* Parse and fetch report threshold num scans */
3255 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003256 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003257 goto fail;
3258 }
3259 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003260 hdd_notice("Report Threshold num scans %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003261 pReqMsg->report_threshold_num_scans);
3262
3263 /* Parse and fetch number of buckets */
3264 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003265 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266 goto fail;
3267 }
3268 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3269 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3270 hdd_warn("Exceeded MAX number of buckets: %d",
3271 WLAN_EXTSCAN_MAX_BUCKETS);
3272 }
3273 hdd_info("Input: Number of Buckets %d", num_buckets);
3274
3275 /* This is optional attribute, if not present set it to 0 */
3276 if (!tb[PARAM_CONFIG_FLAGS])
3277 pReqMsg->configuration_flags = 0;
3278 else
3279 pReqMsg->configuration_flags =
3280 hdd_extscan_map_usr_drv_config_flags(
3281 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3282
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303283 pReqMsg->extscan_adaptive_dwell_mode =
3284 pHddCtx->config->extscan_adaptive_dwell_mode;
3285
Jeff Johnson630f9e72016-07-25 12:00:12 -07003286 hdd_notice("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 pReqMsg->configuration_flags);
3288
3289 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003290 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003291 goto fail;
3292 }
3293
3294 if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb))
3295 goto fail;
3296
3297 context = &ext_scan_context;
3298 spin_lock(&context->context_lock);
3299 INIT_COMPLETION(context->response_event);
3300 context->request_id = request_id = pReqMsg->requestId;
Mukul Sharmafa937be2016-08-12 18:13:36 +05303301 context->buckets_scanned = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003302 spin_unlock(&context->context_lock);
3303
3304 status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303305 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003306 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003307 goto fail;
3308 }
3309
Anurag Chouhan50220ce2016-02-18 20:11:33 +05303310 pHddCtx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Jeff Johnson630f9e72016-07-25 12:00:12 -07003311 hdd_notice("Timestamp since boot: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003312 pHddCtx->ext_scan_start_since_boot);
3313
3314 /* request was sent -- wait for the response */
3315 rc = wait_for_completion_timeout(&context->response_event,
3316 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3317
3318 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003319 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003320 retval = -ETIMEDOUT;
3321 } else {
3322 spin_lock(&context->context_lock);
3323 if (context->request_id == request_id)
3324 retval = context->response_status;
3325 else
3326 retval = -EINVAL;
3327 spin_unlock(&context->context_lock);
3328 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303329 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003330 return retval;
3331
3332fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303333 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003334 return -EINVAL;
3335}
3336/*
3337 * done with short names for the global vendor params
3338 * used by __wlan_hdd_cfg80211_extscan_start()
3339 */
3340#undef PARAM_MAX
3341#undef PARAM_REQUEST_ID
3342#undef PARAM_BASE_PERIOD
3343#undef PARAMS_MAX_AP_PER_SCAN
3344#undef PARAMS_RPT_THRHLD_PERCENT
3345#undef PARAMS_RPT_THRHLD_NUM_SCANS
3346#undef PARAMS_NUM_BUCKETS
3347#undef PARAM_CONFIG_FLAGS
3348
3349/**
3350 * wlan_hdd_cfg80211_extscan_start() - start extscan
3351 * @wiphy: Pointer to wireless phy.
3352 * @wdev: Pointer to wireless device.
3353 * @data: Pointer to input data.
3354 * @data_len: Length of @data.
3355 *
3356 * Return: 0 on success, negative errno on failure
3357 */
3358int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3359 struct wireless_dev *wdev,
3360 const void *data, int data_len)
3361{
3362 int ret = 0;
3363
3364 cds_ssr_protect(__func__);
3365 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3366 cds_ssr_unprotect(__func__);
3367
3368 return ret;
3369}
3370
3371
3372/*
3373 * define short names for the global vendor params
3374 * used by __wlan_hdd_cfg80211_extscan_stop()
3375 */
3376#define PARAM_MAX \
3377 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3378#define PARAM_REQUEST_ID \
3379 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3380
3381/**
3382 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3383 * @wiphy: Pointer to wireless phy
3384 * @wdev: Pointer to wireless device
3385 * @data: Pointer to data
3386 * @data_len: Data length
3387 *
3388 * Return: none
3389 */
3390static int
3391__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3392 struct wireless_dev *wdev,
3393 const void *data, int data_len)
3394{
3395 tpSirExtScanStopReqParams pReqMsg = NULL;
3396 struct net_device *dev = wdev->netdev;
3397 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3398 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3399 struct nlattr *tb[PARAM_MAX + 1];
3400 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303401 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 uint32_t request_id;
3403 int retval;
3404 unsigned long rc;
3405
Jeff Johnson1f61b612016-02-12 16:28:33 -08003406 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407
Anurag Chouhan6d760662016-02-20 16:05:43 +05303408 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003409 hdd_err("Command not allowed in FTM mode");
3410 return -EPERM;
3411 }
3412
3413 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303414 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003416
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303417 if (!pHddCtx->config->extscan_enabled) {
3418 hdd_err("extscan not supported");
3419 return -ENOTSUPP;
3420 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 if (nla_parse(tb, PARAM_MAX, data, data_len,
3422 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003423 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003424 return -EINVAL;
3425 }
3426
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303427 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003428 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003429 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 return -ENOMEM;
3431 }
3432
3433 /* Parse and fetch request Id */
3434 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003435 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003436 goto fail;
3437 }
3438
3439 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3440 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003441 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 pReqMsg->requestId, pReqMsg->sessionId);
3443
3444 context = &ext_scan_context;
3445 spin_lock(&context->context_lock);
3446 INIT_COMPLETION(context->response_event);
3447 context->request_id = request_id = pReqMsg->requestId;
3448 spin_unlock(&context->context_lock);
3449
3450 status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303451 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003452 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003453 goto fail;
3454 }
3455
3456 /* request was sent -- wait for the response */
3457 rc = wait_for_completion_timeout(&context->response_event,
3458 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3459
3460 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003461 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003462 retval = -ETIMEDOUT;
3463 } else {
3464 spin_lock(&context->context_lock);
3465 if (context->request_id == request_id)
3466 retval = context->response_status;
3467 else
3468 retval = -EINVAL;
3469 spin_unlock(&context->context_lock);
3470 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303471 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003472 return retval;
3473
3474fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303475 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 return -EINVAL;
3477}
3478/*
3479 * done with short names for the global vendor params
3480 * used by wlan_hdd_cfg80211_extscan_stop()
3481 */
3482#undef PARAM_MAX
3483#undef PARAM_REQUEST_ID
3484
3485
3486/**
3487 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3488 * @wiphy: Pointer to wireless phy.
3489 * @wdev: Pointer to wireless device.
3490 * @data: Pointer to input data.
3491 * @data_len: Length of @data.
3492 *
3493 * Return: 0 on success, negative errno on failure
3494 */
3495int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3496 struct wireless_dev *wdev,
3497 const void *data, int data_len)
3498{
3499 int ret = 0;
3500
3501 cds_ssr_protect(__func__);
3502 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3503 cds_ssr_unprotect(__func__);
3504
3505 return ret;
3506}
3507
3508
3509/**
3510 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3511 * @wiphy: Pointer to wireless phy
3512 * @wdev: Pointer to wireless device
3513 * @data: Pointer to data
3514 * @data_len: Data length
3515 *
3516 * Return: none
3517 */
3518static int
3519__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3520 struct wireless_dev
3521 *wdev, const void *data,
3522 int data_len)
3523{
3524 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3525 struct net_device *dev = wdev->netdev;
3526 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3527 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3528 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3529 1];
3530 struct hdd_ext_scan_context *context;
3531 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303532 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533 int retval;
3534 unsigned long rc;
3535
Jeff Johnson1f61b612016-02-12 16:28:33 -08003536 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537
Anurag Chouhan6d760662016-02-20 16:05:43 +05303538 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539 hdd_err("Command not allowed in FTM mode");
3540 return -EPERM;
3541 }
3542
3543 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303544 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303547 if (!pHddCtx->config->extscan_enabled) {
3548 hdd_err("extscan not supported");
3549 return -ENOTSUPP;
3550 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3552 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003553 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554 return -EINVAL;
3555 }
3556
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303557 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003559 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003560 return -ENOMEM;
3561 }
3562
3563 /* Parse and fetch request Id */
3564 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003565 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 goto fail;
3567 }
3568
3569 pReqMsg->requestId =
3570 nla_get_u32(tb
3571 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3572 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003573 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003574 pReqMsg->requestId, pReqMsg->sessionId);
3575
3576 context = &ext_scan_context;
3577 spin_lock(&context->context_lock);
3578 INIT_COMPLETION(context->response_event);
3579 context->request_id = request_id = pReqMsg->requestId;
3580 spin_unlock(&context->context_lock);
3581
3582 status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303583 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003584 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 goto fail;
3586 }
3587
3588 /* request was sent -- wait for the response */
3589 rc = wait_for_completion_timeout
3590 (&context->response_event,
3591 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3592 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003593 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594 retval = -ETIMEDOUT;
3595 } else {
3596 spin_lock(&context->context_lock);
3597 if (context->request_id == request_id)
3598 retval = context->response_status;
3599 else
3600 retval = -EINVAL;
3601 spin_unlock(&context->context_lock);
3602 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303603 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003604 return retval;
3605
3606fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303607 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608 return -EINVAL;
3609}
3610
3611/**
3612 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3613 * @wiphy: Pointer to wireless phy
3614 * @wdev: Pointer to wireless device
3615 * @data: Pointer to data
3616 * @data_len: Data length
3617 *
3618 * Return: 0 on success, negative errno on failure
3619 */
3620int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3621 struct wireless_dev *wdev,
3622 const void *data, int data_len)
3623{
3624 int ret = 0;
3625
3626 cds_ssr_protect(__func__);
3627 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3628 data, data_len);
3629 cds_ssr_unprotect(__func__);
3630
3631 return ret;
3632}
3633
3634/**
3635 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3636 * reset significant change
3637 * @wiphy: Pointer to wireless phy
3638 * @wdev: Pointer to wireless device
3639 * @data: Pointer to data
3640 * @data_len: Data length
3641 *
3642 * Return: none
3643 */
3644static int
3645__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3646 *wiphy,
3647 struct
3648 wireless_dev
3649 *wdev, const void *data,
3650 int data_len)
3651{
3652 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3653 struct net_device *dev = wdev->netdev;
3654 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3655 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3656 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3657 1];
3658 struct hdd_ext_scan_context *context;
3659 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303660 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661 int retval;
3662 unsigned long rc;
3663
Jeff Johnson1f61b612016-02-12 16:28:33 -08003664 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665
Anurag Chouhan6d760662016-02-20 16:05:43 +05303666 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003667 hdd_err("Command not allowed in FTM mode");
3668 return -EPERM;
3669 }
3670
3671 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303672 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303675 if (!pHddCtx->config->extscan_enabled) {
3676 hdd_err("extscan not supported");
3677 return -ENOTSUPP;
3678 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3680 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003681 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682 return -EINVAL;
3683 }
3684
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303685 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003687 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003688 return -ENOMEM;
3689 }
3690
3691 /* Parse and fetch request Id */
3692 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003693 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694 goto fail;
3695 }
3696
3697 pReqMsg->requestId =
3698 nla_get_u32(tb
3699 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3700 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003701 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 pReqMsg->requestId, pReqMsg->sessionId);
3703
3704 context = &ext_scan_context;
3705 spin_lock(&context->context_lock);
3706 INIT_COMPLETION(context->response_event);
3707 context->request_id = request_id = pReqMsg->requestId;
3708 spin_unlock(&context->context_lock);
3709
3710 status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303711 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003712 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303714 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 return -EINVAL;
3716 }
3717
3718 /* request was sent -- wait for the response */
3719 rc = wait_for_completion_timeout(&context->response_event,
3720 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3721
3722 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003723 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003724 retval = -ETIMEDOUT;
3725 } else {
3726 spin_lock(&context->context_lock);
3727 if (context->request_id == request_id)
3728 retval = context->response_status;
3729 else
3730 retval = -EINVAL;
3731 spin_unlock(&context->context_lock);
3732 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303733 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 return retval;
3735
3736fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303737 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003738 return -EINVAL;
3739}
3740
3741/**
3742 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3743 * change
3744 * @wiphy: Pointer to wireless phy
3745 * @wdev: Pointer to wireless device
3746 * @data: Pointer to data
3747 * @data_len: Data length
3748 *
3749 * Return: 0 on success, negative errno on failure
3750 */
3751int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3752 struct wireless_dev *wdev,
3753 const void *data, int data_len)
3754{
3755 int ret = 0;
3756
3757 cds_ssr_protect(__func__);
3758 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3759 data, data_len);
3760 cds_ssr_unprotect(__func__);
3761
3762 return ret;
3763}
3764
3765
3766/**
3767 * hdd_extscan_epno_fill_network_list() - epno fill network list
3768 * @hddctx: HDD context
3769 * @req_msg: request message
3770 * @tb: vendor attribute table
3771 *
3772 * This function reads the network block NL vendor attributes from %tb and
3773 * fill in the epno request message.
3774 *
3775 * Return: 0 on success, error number otherwise
3776 */
3777static int hdd_extscan_epno_fill_network_list(
3778 hdd_context_t *hddctx,
3779 struct wifi_epno_params *req_msg,
3780 struct nlattr **tb)
3781{
3782 struct nlattr *network[
3783 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3784 struct nlattr *networks;
3785 int rem1, ssid_len;
3786 uint8_t index, *ssid;
3787
3788 index = 0;
3789 nla_for_each_nested(networks,
3790 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3791 rem1) {
3792 if (nla_parse(network,
3793 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3794 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003795 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796 return -EINVAL;
3797 }
3798
3799 /* Parse and fetch ssid */
3800 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003801 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003802 return -EINVAL;
3803 }
3804 ssid_len = nla_len(
3805 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3806
3807 /* Decrement by 1, don't count null character */
3808 ssid_len--;
3809
3810 req_msg->networks[index].ssid.length = ssid_len;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003811 hdd_notice("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303813 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814 ssid, ssid_len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003815 hdd_notice("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 req_msg->networks[index].ssid.length,
3817 req_msg->networks[index].ssid.ssId);
3818
3819 /* Parse and fetch rssi threshold */
3820 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003821 hdd_err("attr rssi threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003822 return -EINVAL;
3823 }
3824 req_msg->networks[index].rssi_threshold = nla_get_s8(
3825 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003826 hdd_notice("rssi threshold %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827 req_msg->networks[index].rssi_threshold);
3828
3829 /* Parse and fetch epno flags */
3830 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003831 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003832 return -EINVAL;
3833 }
3834 req_msg->networks[index].flags = nla_get_u8(
3835 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003836 hdd_notice("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837
3838 /* Parse and fetch auth bit */
3839 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003840 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003841 return -EINVAL;
3842 }
3843 req_msg->networks[index].auth_bit_field = nla_get_u8(
3844 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003845 hdd_notice("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846 req_msg->networks[index].auth_bit_field);
3847
3848 index++;
3849 }
3850 return 0;
3851}
3852
3853/**
3854 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3855 * @wiphy: wiphy
3856 * @wdev: pointer to wireless dev
3857 * @data: data pointer
3858 * @data_len: data length
3859 *
3860 * This function reads the NL vendor attributes from %tb and
3861 * fill in the epno request message.
3862 *
3863 * Return: 0 on success, error number otherwise
3864 */
3865static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3866 struct wireless_dev *wdev,
3867 const void *data,
3868 int data_len)
3869{
3870 struct wifi_epno_params *req_msg = NULL;
3871 struct net_device *dev = wdev->netdev;
3872 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3873 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3874 struct nlattr *tb[
3875 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303876 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003877 uint32_t num_networks, len;
3878 int ret_val;
3879
Jeff Johnson1f61b612016-02-12 16:28:33 -08003880 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881
3882 ret_val = wlan_hdd_validate_context(hdd_ctx);
3883 if (ret_val)
3884 return ret_val;
3885
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303886 if (!hdd_ctx->config->extscan_enabled) {
3887 hdd_err("extscan not supported");
3888 return -ENOTSUPP;
3889 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303890 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003891 hdd_err("Command not allowed in FTM mode");
3892 return -EPERM;
3893 }
3894
3895 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3896 data, data_len,
3897 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003898 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003899 return -EINVAL;
3900 }
3901
3902 /* Parse and fetch number of networks */
3903 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003904 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 return -EINVAL;
3906 }
3907 num_networks = nla_get_u32(
3908 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003909 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003910
3911 len = sizeof(*req_msg) +
3912 (num_networks * sizeof(struct wifi_epno_network));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303913 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003914 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003915 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916 return -ENOMEM;
3917 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303918 qdf_mem_zero(req_msg, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003919 req_msg->num_networks = num_networks;
3920
3921 /* Parse and fetch request Id */
3922 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003923 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924 goto fail;
3925 }
3926 req_msg->request_id = nla_get_u32(
3927 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003928 hdd_notice("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929
3930 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003931 hdd_notice("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003932
3933 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
3934 goto fail;
3935
3936 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303937 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003938 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003939 goto fail;
3940 }
3941
3942 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303943 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944 return 0;
3945
3946fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303947 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003948 return -EINVAL;
3949}
3950
3951 /**
3952 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
3953 * @wiphy: wiphy
3954 * @wdev: pointer to wireless dev
3955 * @data: data pointer
3956 * @data_len: data length
3957 *
3958 * This function reads the NL vendor attributes from %tb and
3959 * fill in the epno request message.
3960 *
3961 * Return: 0 on success, error number otherwise
3962 */
3963int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3964 struct wireless_dev *wdev,
3965 const void *data,
3966 int data_len)
3967{
3968 int ret;
3969
3970 cds_ssr_protect(__func__);
3971 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
3972 data, data_len);
3973 cds_ssr_unprotect(__func__);
3974
3975 return ret;
3976}
3977
3978/**
3979 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
3980 * @hddctx: HDD context
3981 * @req_msg: request message
3982 * @tb: vendor attribute table
3983 *
3984 * This function reads the network block NL vendor attributes from %tb and
3985 * fill in the passpoint request message.
3986 *
3987 * Return: 0 on success, error number otherwise
3988 */
3989static int hdd_extscan_passpoint_fill_network_list(
3990 hdd_context_t *hddctx,
3991 struct wifi_passpoint_req *req_msg,
3992 struct nlattr **tb)
3993{
3994 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
3995 struct nlattr *networks;
3996 int rem1, len;
3997 uint8_t index;
3998
3999 index = 0;
4000 nla_for_each_nested(networks,
4001 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
4002 rem1) {
4003 if (nla_parse(network,
4004 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
4005 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004006 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004007 return -EINVAL;
4008 }
4009
4010 /* Parse and fetch identifier */
4011 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004012 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013 return -EINVAL;
4014 }
4015 req_msg->networks[index].id = nla_get_u32(
4016 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004017 hdd_notice("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004018
4019 /* Parse and fetch realm */
4020 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004021 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004022 return -EINVAL;
4023 }
4024 len = nla_len(
4025 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
4026 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004027 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028 return -EINVAL;
4029 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304030 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
4032 len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004033 hdd_notice("realm len %d", len);
4034 hdd_notice("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004035
4036 /* Parse and fetch roaming consortium ids */
4037 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004038 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039 return -EINVAL;
4040 }
4041 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
4042 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
4043 sizeof(req_msg->networks[0].roaming_consortium_ids));
Jeff Johnson630f9e72016-07-25 12:00:12 -07004044 hdd_notice("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045
4046 /* Parse and fetch plmn */
4047 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004048 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 return -EINVAL;
4050 }
4051 nla_memcpy(&req_msg->networks[index].plmn,
4052 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
4053 SIR_PASSPOINT_PLMN_LEN);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004054 hdd_notice("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 req_msg->networks[index].plmn[0],
4056 req_msg->networks[index].plmn[1],
4057 req_msg->networks[index].plmn[2]);
4058
4059 index++;
4060 }
4061 return 0;
4062}
4063
4064/**
4065 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4066 * @wiphy: wiphy
4067 * @wdev: pointer to wireless dev
4068 * @data: data pointer
4069 * @data_len: data length
4070 *
4071 * This function reads the NL vendor attributes from %tb and
4072 * fill in the passpoint request message.
4073 *
4074 * Return: 0 on success, error number otherwise
4075 */
4076static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4077 struct wireless_dev *wdev,
4078 const void *data,
4079 int data_len)
4080{
4081 struct wifi_passpoint_req *req_msg = NULL;
4082 struct net_device *dev = wdev->netdev;
4083 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4084 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4085 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304086 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004087 uint32_t num_networks = 0;
4088 int ret;
4089
Jeff Johnson1f61b612016-02-12 16:28:33 -08004090 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091
4092 ret = wlan_hdd_validate_context(hdd_ctx);
4093 if (ret)
4094 return ret;
4095
Anurag Chouhan6d760662016-02-20 16:05:43 +05304096 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004097 hdd_err("Command not allowed in FTM mode");
4098 return -EPERM;
4099 }
4100
4101 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4102 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004103 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 return -EINVAL;
4105 }
4106
4107 /* Parse and fetch number of networks */
4108 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004109 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004110 return -EINVAL;
4111 }
4112 num_networks = nla_get_u32(
4113 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004114 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304116 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004117 (num_networks * sizeof(req_msg->networks[0])));
4118 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004119 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120 return -ENOMEM;
4121 }
4122 req_msg->num_networks = num_networks;
4123
4124 /* Parse and fetch request Id */
4125 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004126 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127 goto fail;
4128 }
4129 req_msg->request_id = nla_get_u32(
4130 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4131
4132 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004133 hdd_notice("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004134 req_msg->session_id);
4135
4136 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4137 goto fail;
4138
4139 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304140 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004141 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 goto fail;
4143 }
4144
4145 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304146 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 return 0;
4148
4149fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304150 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151 return -EINVAL;
4152}
4153
4154/**
4155 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4156 * @wiphy: wiphy
4157 * @wdev: pointer to wireless dev
4158 * @data: data pointer
4159 * @data_len: data length
4160 *
4161 * This function reads the NL vendor attributes from %tb and
4162 * fill in the passpoint request message.
4163 *
4164 * Return: 0 on success, error number otherwise
4165 */
4166int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4167 struct wireless_dev *wdev,
4168 const void *data,
4169 int data_len)
4170{
4171 int ret;
4172
4173 cds_ssr_protect(__func__);
4174 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4175 data, data_len);
4176 cds_ssr_unprotect(__func__);
4177
4178 return ret;
4179}
4180
4181/**
4182 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4183 * @wiphy: wiphy
4184 * @wdev: pointer to wireless dev
4185 * @data: data pointer
4186 * @data_len: data length
4187 *
4188 * This function resets passpoint networks list
4189 *
4190 * Return: 0 on success, error number otherwise
4191 */
4192static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4193 struct wireless_dev *wdev,
4194 const void *data,
4195 int data_len)
4196{
4197 struct wifi_passpoint_req *req_msg = NULL;
4198 struct net_device *dev = wdev->netdev;
4199 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4200 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4201 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304202 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004203 int ret;
4204
Jeff Johnson1f61b612016-02-12 16:28:33 -08004205 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004206
4207 ret = wlan_hdd_validate_context(hdd_ctx);
4208 if (ret)
4209 return ret;
4210
Anurag Chouhan6d760662016-02-20 16:05:43 +05304211 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212 hdd_err("Command not allowed in FTM mode");
4213 return -EPERM;
4214 }
4215
4216 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4217 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004218 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219 return -EINVAL;
4220 }
4221
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304222 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004223 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004224 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004225 return -ENOMEM;
4226 }
4227
4228 /* Parse and fetch request Id */
4229 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004230 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004231 goto fail;
4232 }
4233 req_msg->request_id = nla_get_u32(
4234 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4235
4236 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004237 hdd_notice("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004238 req_msg->request_id, req_msg->session_id);
4239
4240 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304241 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004242 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004243 goto fail;
4244 }
4245
4246 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304247 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004248 return 0;
4249
4250fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304251 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252 return -EINVAL;
4253}
4254
4255/**
4256 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4257 * @wiphy: wiphy
4258 * @wdev: pointer to wireless dev
4259 * @data: data pointer
4260 * @data_len: data length
4261 *
4262 * This function resets passpoint networks list
4263 *
4264 * Return: 0 on success, error number otherwise
4265 */
4266int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4267 struct wireless_dev *wdev,
4268 const void *data,
4269 int data_len)
4270{
4271 int ret;
4272
4273 cds_ssr_protect(__func__);
4274 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4275 data, data_len);
4276 cds_ssr_unprotect(__func__);
4277
4278 return ret;
4279}
4280
4281/*
4282 * define short names for the global vendor params
4283 * used by __wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4284 */
4285#define PARAM_MAX \
4286 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4287#define PARAM_REQUEST_ID \
4288 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4289#define PARAMS_LOST_SSID_SAMPLE_SIZE \
4290 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE
4291#define PARAMS_NUM_SSID \
4292 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID
4293#define THRESHOLD_PARAM \
4294 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM
4295#define PARAM_SSID \
4296 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID
4297#define PARAM_BAND \
4298 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND
4299#define PARAM_RSSI_LOW \
4300 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW
4301#define PARAM_RSSI_HIGH \
4302 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH
4303
4304/**
4305 * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4306 * @wiphy: Pointer to wireless phy
4307 * @wdev: Pointer to wireless device
4308 * @data: Pointer to data
4309 * @data_len: Data length
4310 *
4311 * Return: 0 on success, negative errno on failure
4312 */
4313static int
4314__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4315 struct wireless_dev *wdev,
4316 const void *data,
4317 int data_len)
4318{
4319 struct sir_set_ssid_hotlist_request *request;
4320 struct net_device *dev = wdev->netdev;
4321 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4322 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4323 struct nlattr *tb[PARAM_MAX + 1];
4324 struct nlattr *tb2[PARAM_MAX + 1];
4325 struct nlattr *ssids;
4326 struct hdd_ext_scan_context *context;
4327 uint32_t request_id;
4328 char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1];
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304329 int ssid_len, i, rem, ssid_str_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304330 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331 int retval;
4332 unsigned long rc;
4333
Jeff Johnson1f61b612016-02-12 16:28:33 -08004334 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335
Anurag Chouhan6d760662016-02-20 16:05:43 +05304336 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004337 hdd_err("Command not allowed in FTM mode");
4338 return -EPERM;
4339 }
4340
4341 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304342 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004343 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304345 if (!hdd_ctx->config->extscan_enabled) {
4346 hdd_err("extscan not supported");
4347 return -ENOTSUPP;
4348 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349 if (nla_parse(tb, PARAM_MAX,
4350 data, data_len,
4351 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004352 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 return -EINVAL;
4354 }
4355
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304356 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004358 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 return -ENOMEM;
4360 }
4361
4362 /* Parse and fetch request Id */
4363 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004364 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 goto fail;
4366 }
4367
4368 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004369 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004370
4371 /* Parse and fetch lost SSID sample size */
4372 if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004373 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374 goto fail;
4375 }
4376 request->lost_ssid_sample_size =
4377 nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004378 hdd_notice("Lost SSID Sample Size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379 request->lost_ssid_sample_size);
4380
4381 /* Parse and fetch number of hotlist SSID */
4382 if (!tb[PARAMS_NUM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004383 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 goto fail;
4385 }
4386 request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004387 hdd_notice("Number of SSID %d", request->ssid_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388
4389 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004390 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391
4392 i = 0;
4393 nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) {
4394 if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004395 hdd_err("Too Many SSIDs, %d exceeds %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396 i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS);
4397 break;
4398 }
4399 if (nla_parse(tb2, PARAM_MAX,
4400 nla_data(ssids), nla_len(ssids),
4401 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004402 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403 goto fail;
4404 }
4405
4406 /* Parse and fetch SSID */
4407 if (!tb2[PARAM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004408 hdd_err("attr ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409 goto fail;
4410 }
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304411 ssid_str_len = nla_strlcpy(ssid_string,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004412 tb2[PARAM_SSID],
4413 sizeof(ssid_string));
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304414 if (ssid_str_len > SIR_MAC_MAX_SSID_LENGTH) {
4415 hdd_err("Invalid length exceeds max ssid length");
4416 goto fail;
4417 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07004418 hdd_notice("SSID %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 ssid_string);
4420 ssid_len = strlen(ssid_string);
4421 memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len);
4422 request->ssids[i].ssid.length = ssid_len;
4423
4424 /* Parse and fetch low RSSI */
4425 if (!tb2[PARAM_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004426 hdd_err("attr band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004427 goto fail;
4428 }
4429 request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004430 hdd_notice("band %d", request->ssids[i].band);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004431
4432 /* Parse and fetch low RSSI */
4433 if (!tb2[PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004434 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435 goto fail;
4436 }
4437 request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004438 hdd_notice("RSSI low %d", request->ssids[i].rssi_low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439
4440 /* Parse and fetch high RSSI */
4441 if (!tb2[PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004442 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443 goto fail;
4444 }
4445 request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004446 hdd_notice("RSSI high %d", request->ssids[i].rssi_high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 i++;
4448 }
4449
4450 context = &ext_scan_context;
4451 spin_lock(&context->context_lock);
4452 INIT_COMPLETION(context->response_event);
4453 context->request_id = request_id = request->request_id;
4454 spin_unlock(&context->context_lock);
4455
4456 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304457 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004458 hdd_err("sme_set_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459 goto fail;
4460 }
4461
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304462 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463
4464 /* request was sent -- wait for the response */
4465 rc = wait_for_completion_timeout(&context->response_event,
4466 msecs_to_jiffies
4467 (WLAN_WAIT_TIME_EXTSCAN));
4468 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004469 hdd_err("sme_set_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470 retval = -ETIMEDOUT;
4471 } else {
4472 spin_lock(&context->context_lock);
4473 if (context->request_id == request_id)
4474 retval = context->response_status;
4475 else
4476 retval = -EINVAL;
4477 spin_unlock(&context->context_lock);
4478 }
4479
4480 return retval;
4481
4482fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304483 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004484 return -EINVAL;
4485}
4486
4487/*
4488 * done with short names for the global vendor params
4489 * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4490 */
4491#undef PARAM_MAX
4492#undef PARAM_REQUEST_ID
4493#undef PARAMS_NUM_SSID
4494#undef THRESHOLD_PARAM
4495#undef PARAM_SSID
4496#undef PARAM_BAND
4497#undef PARAM_RSSI_LOW
4498#undef PARAM_RSSI_HIGH
4499
4500/**
4501 * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4502 * @wiphy: Pointer to wireless phy
4503 * @wdev: Pointer to wireless device
4504 * @data: Pointer to data
4505 * @data_len: Data length
4506 *
4507 * Return: 0 on success, negative errno on failure
4508 */
4509int
4510wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4511 struct wireless_dev *wdev,
4512 const void *data,
4513 int data_len)
4514{
4515 int ret;
4516
4517 cds_ssr_protect(__func__);
4518 ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data,
4519 data_len);
4520 cds_ssr_unprotect(__func__);
4521
4522 return ret;
4523}
4524
4525/*
4526 * define short names for the global vendor params
4527 * used by __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4528 */
4529#define PARAM_MAX \
4530 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4531#define PARAM_REQUEST_ID \
4532 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4533
4534/**
4535 * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4536 * @wiphy: Pointer to wireless phy
4537 * @wdev: Pointer to wireless device
4538 * @data: Pointer to data
4539 * @data_len: Data length
4540 *
4541 * Return: 0 on success, negative errno on failure
4542 */
4543static int
4544__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4545 struct wireless_dev *wdev,
4546 const void *data,
4547 int data_len)
4548{
4549 struct sir_set_ssid_hotlist_request *request;
4550 struct net_device *dev = wdev->netdev;
4551 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4552 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4553 struct nlattr *tb[PARAM_MAX + 1];
4554 struct hdd_ext_scan_context *context;
4555 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304556 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004557 int retval;
4558 unsigned long rc;
4559
Jeff Johnson1f61b612016-02-12 16:28:33 -08004560 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004561
Anurag Chouhan6d760662016-02-20 16:05:43 +05304562 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004563 hdd_err("Command not allowed in FTM mode");
4564 return -EPERM;
4565 }
4566
4567 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304568 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004569 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004570
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304571 if (!hdd_ctx->config->extscan_enabled) {
4572 hdd_err("extscan not supported");
4573 return -ENOTSUPP;
4574 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 if (nla_parse(tb, PARAM_MAX,
4576 data, data_len,
4577 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004578 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004579 return -EINVAL;
4580 }
4581
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304582 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004584 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 return -ENOMEM;
4586 }
4587
4588 /* Parse and fetch request Id */
4589 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004590 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004591 goto fail;
4592 }
4593
4594 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004595 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004596
4597 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004598 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599
4600 request->lost_ssid_sample_size = 0;
4601 request->ssid_count = 0;
4602
4603 context = &ext_scan_context;
4604 spin_lock(&context->context_lock);
4605 INIT_COMPLETION(context->response_event);
4606 context->request_id = request_id = request->request_id;
4607 spin_unlock(&context->context_lock);
4608
4609 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304610 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004611 hdd_err("sme_reset_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 goto fail;
4613 }
4614
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304615 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616
4617 /* request was sent -- wait for the response */
4618 rc = wait_for_completion_timeout(&context->response_event,
4619 msecs_to_jiffies
4620 (WLAN_WAIT_TIME_EXTSCAN));
4621 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004622 hdd_err("sme_reset_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004623 retval = -ETIMEDOUT;
4624 } else {
4625 spin_lock(&context->context_lock);
4626 if (context->request_id == request_id)
4627 retval = context->response_status;
4628 else
4629 retval = -EINVAL;
4630 spin_unlock(&context->context_lock);
4631 }
4632
4633 return retval;
4634
4635fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304636 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637 return -EINVAL;
4638}
4639
4640/*
4641 * done with short names for the global vendor params
4642 * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4643 */
4644#undef PARAM_MAX
4645#undef PARAM_REQUEST_ID
4646
4647/**
4648 * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4649 * @wiphy: Pointer to wireless phy
4650 * @wdev: Pointer to wireless device
4651 * @data: Pointer to data
4652 * @data_len: Data length
4653 *
4654 * Return: 0 on success, negative errno on failure
4655 */
4656int
4657wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4658 struct wireless_dev *wdev,
4659 const void *data,
4660 int data_len)
4661{
4662 int ret;
4663
4664 cds_ssr_protect(__func__);
4665 ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev,
4666 data, data_len);
4667 cds_ssr_unprotect(__func__);
4668
4669 return ret;
4670}
4671
4672/**
4673 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4674 * @hdd_ctx: Global HDD context
4675 *
4676 * Return: none
4677 */
4678#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4679static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4680{
4681 init_completion(&pHddCtx->ready_to_extwow);
4682}
4683#else
4684static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4685{
4686 return;
4687}
4688#endif
4689
4690/**
4691 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4692 * @hdd_ctx: Global HDD context
4693 *
4694 * Return: none
4695 */
4696void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx)
4697{
4698 wlan_hdd_init_completion_extwow(hdd_ctx);
4699 init_completion(&ext_scan_context.response_event);
4700 spin_lock_init(&ext_scan_context.context_lock);
4701}
4702
4703#endif /* FEATURE_WLAN_EXTSCAN */