blob: 9ce9a61a49904bdd6a2d69629e4ee840452b87e5 [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"
Amar Singhalea10a872016-08-23 15:31:45 -070035#include "wlan_hdd_regulatory.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include "cds_utils.h"
37#include "cds_sched.h"
38
39/* amount of time to wait for a synchronous request/response operation */
40#define WLAN_WAIT_TIME_EXTSCAN 1000
41
42/**
43 * struct hdd_ext_scan_context - hdd ext scan context
44 * @request_id: userspace-assigned ID associated with the request
45 * @response_event: Ext scan wait event
46 * @response_status: Status returned by FW in response to a request
47 * @ignore_cached_results: Flag to ignore cached results or not
48 * @context_lock: Spinlock to serialize all context accesses
49 * @capability_response: Ext scan capability response data from target
Mukul Sharmafa937be2016-08-12 18:13:36 +053050 * @buckets_scanned: bitmask of buckets scanned in extscan cycle
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051 */
52struct hdd_ext_scan_context {
53 uint32_t request_id;
54 int response_status;
55 bool ignore_cached_results;
56 struct completion response_event;
57 spinlock_t context_lock;
58 struct ext_scan_capabilities_response capability_response;
Mukul Sharmafa937be2016-08-12 18:13:36 +053059 uint32_t buckets_scanned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080060};
61static struct hdd_ext_scan_context ext_scan_context;
62
63static const struct nla_policy wlan_hdd_extscan_config_policy
64[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] = {
65 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = {
66 .type = NLA_U32},
67 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = {
68 .type = NLA_U32},
69 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = {.type = NLA_U32},
70 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = {
71 .type = NLA_U32},
72 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = {.type = NLA_U8},
73 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = {.type = NLA_U8},
74
75 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = {.type = NLA_U8},
76 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = {.type = NLA_U8},
77 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = {.type = NLA_U32},
78 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] = {
79 .type = NLA_U8},
80 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] = {
81 .type = NLA_U32},
82 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] = {
83 .type = NLA_U32},
84 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] = {
85 .type = NLA_U32},
86 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT] = {
87 .type = NLA_U8},
88 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS] = {
89 .type = NLA_U8 },
90 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] = {
91 .type = NLA_U8},
92 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = {
93 .type = NLA_U8},
94
95 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = {
96 .type = NLA_U32},
97 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = {
98 .type = NLA_UNSPEC},
99 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = {
100 .type = NLA_S32},
101 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = {
102 .type = NLA_S32},
103 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = {
104 .type = NLA_U32},
105 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] = {
106 .type = NLA_U32},
107 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] = {
108 .type = NLA_U32},
109 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = {
110 .type = NLA_U32},
111 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = {
112 .type = NLA_U32},
113 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = {
114 .type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800115 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = {
116 .type = NLA_BINARY,
117 .len = IEEE80211_MAX_SSID_LEN + 1 },
118 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = {
119 .type = NLA_U32 },
120 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID] = {
121 .type = NLA_U32 },
122 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND] = {
123 .type = NLA_U8 },
124 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = {
125 .type = NLA_S32 },
126 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = {
127 .type = NLA_S32 },
128 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = {
129 .type = NLA_U32 },
130};
131
132static const struct nla_policy
Jeff Johnsonfa484bb2016-11-09 09:01:10 -0800133wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = {
134 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
135 .type = NLA_U32
136 },
137 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
138 .type = NLA_BINARY,
139 .len = IEEE80211_MAX_SSID_LEN + 1
140 },
141 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
142 .type = NLA_U8
143 },
144 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
145 .type = NLA_U8
146 },
147};
148
149static const struct nla_policy
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
151 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
152 .type = NLA_U16},
153 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = {
154 .type = NLA_U16},
155};
156
157/**
158 * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
159 * @ctx: Pointer to hdd context
160 * @data: Pointer to ext scan capabilities response from fw
161 *
162 * Return: None
163 */
164static void
165wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx,
166 struct ext_scan_capabilities_response *data)
167{
168 struct hdd_ext_scan_context *context;
169 hdd_context_t *hdd_ctx = ctx;
170
171 ENTER();
172
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530173 if (wlan_hdd_validate_context(hdd_ctx))
174 return;
175 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700176 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177 return;
178 }
179
180 context = &ext_scan_context;
181
182 spin_lock(&context->context_lock);
183 /* validate response received from target*/
184 if (context->request_id != data->requestId) {
185 spin_unlock(&context->context_lock);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700186 hdd_err("Target response id did not match: request_id %d response_id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187 context->request_id, data->requestId);
188 return;
189 } else {
190 context->capability_response = *data;
191 complete(&context->response_event);
192 }
193
194 spin_unlock(&context->context_lock);
195
196 return;
197}
198
199/*
200 * define short names for the global vendor params
201 * used by hdd_extscan_nl_fill_bss()
202 */
203#define PARAM_TIME_STAMP \
204 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
205#define PARAM_SSID \
206 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID
207#define PARAM_BSSID \
208 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID
209#define PARAM_CHANNEL \
210 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL
211#define PARAM_RSSI \
212 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI
213#define PARAM_RTT \
214 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT
215#define PARAM_RTT_SD \
216 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD
217#define PARAM_BEACON_PERIOD \
218 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD
219#define PARAM_CAPABILITY \
220 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY
221#define PARAM_IE_LENGTH \
222 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
223#define PARAM_IE_DATA \
224 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA
225
226/** hdd_extscan_nl_fill_bss() - extscan nl fill bss
227 * @skb: socket buffer
228 * @ap: bss information
229 * @idx: nesting index
230 *
231 * Return: 0 on success; error number otherwise
232 */
233static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap,
234 int idx)
235{
236 struct nlattr *nla_ap;
237
238 nla_ap = nla_nest_start(skb, idx);
239 if (!nla_ap)
240 return -EINVAL;
241
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700242 if (hdd_wlan_nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800243 nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) ||
244 nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid.bytes) ||
245 nla_put_u32(skb, PARAM_CHANNEL, ap->channel) ||
246 nla_put_s32(skb, PARAM_RSSI, ap->rssi) ||
247 nla_put_u32(skb, PARAM_RTT, ap->rtt) ||
248 nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) ||
249 nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) ||
250 nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) ||
251 nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700252 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 return -EINVAL;
254 }
255
256 if (ap->ieLength)
257 if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700258 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800259 return -EINVAL;
260 }
261
262 nla_nest_end(skb, nla_ap);
263
264 return 0;
265}
266/*
267 * done with short names for the global vendor params
268 * used by hdd_extscan_nl_fill_bss()
269 */
270#undef PARAM_TIME_STAMP
271#undef PARAM_SSID
272#undef PARAM_BSSID
273#undef PARAM_CHANNEL
274#undef PARAM_RSSI
275#undef PARAM_RTT
276#undef PARAM_RTT_SD
277#undef PARAM_BEACON_PERIOD
278#undef PARAM_CAPABILITY
279#undef PARAM_IE_LENGTH
280#undef PARAM_IE_DATA
281
282/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results
283 * @ctx: hdd global context
284 * @data: cached results
285 *
286 * This function reads the cached results %data, populated the NL
287 * attributes and sends the NL event to the upper layer.
288 *
289 * Return: none
290 */
291static void
292wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
293 struct extscan_cached_scan_results *data)
294{
295 hdd_context_t *pHddCtx = ctx;
296 struct sk_buff *skb = NULL;
297 struct hdd_ext_scan_context *context;
298 struct extscan_cached_scan_result *result;
299 tSirWifiScanResult *ap;
300 uint32_t i, j, nl_buf_len;
301 bool ignore_cached_results = false;
302
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700303 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800304
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530305 if (wlan_hdd_validate_context(pHddCtx))
306 return;
307 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700308 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309 return;
310 }
311
312 context = &ext_scan_context;
313 spin_lock(&context->context_lock);
314 ignore_cached_results = context->ignore_cached_results;
315 spin_unlock(&context->context_lock);
316
317 if (ignore_cached_results) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700318 hdd_err("Ignore the cached results received after timeout");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319 return;
320 }
321
322#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN
323#define EXTSCAN_CACHED_NL_FIXED_TLV \
324 ((sizeof(data->request_id) + NLA_HDRLEN) + \
325 (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \
326 (sizeof(data->more_data) + NLA_HDRLEN))
327#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \
328 ((sizeof(result->scan_id) + NLA_HDRLEN) + \
329 (sizeof(result->flags) + NLA_HDRLEN) + \
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530330 (sizeof(result->num_results) + NLA_HDRLEN))+ \
331 (sizeof(result->buckets_scanned) + NLA_HDRLEN)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800332#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
333 ((sizeof(ap->ts) + NLA_HDRLEN) + \
334 (sizeof(ap->ssid) + NLA_HDRLEN) + \
335 (sizeof(ap->bssid) + NLA_HDRLEN) + \
336 (sizeof(ap->channel) + NLA_HDRLEN) + \
337 (sizeof(ap->rssi) + NLA_HDRLEN) + \
338 (sizeof(ap->rtt) + NLA_HDRLEN) + \
339 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
340 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
341 (sizeof(ap->capability) + NLA_HDRLEN) + \
342 (sizeof(ap->ieLength) + NLA_HDRLEN))
343#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
344 (ap->ieLength + NLA_HDRLEN)
345
346 nl_buf_len = NLMSG_HDRLEN;
347 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
348 if (data->num_scan_ids) {
349 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
350 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
351 result = &data->result[0];
352 for (i = 0; i < data->num_scan_ids; i++) {
353 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
354 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
355 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
356
357 ap = &result->ap[0];
358 for (j = 0; j < result->num_results; j++) {
359 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
360 nl_buf_len +=
361 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
362 if (ap->ieLength)
363 nl_buf_len +=
364 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
365 ap++;
366 }
367 result++;
368 }
369 }
370
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len);
372
373 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700374 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375 goto fail;
376 }
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530377 hdd_notice("Req Id %u Num_scan_ids %u More Data %u",
378 data->request_id, data->num_scan_ids, data->more_data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800379
380 result = &data->result[0];
381 for (i = 0; i < data->num_scan_ids; i++) {
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530382 hdd_notice("[i=%d] scan_id %u flags %u num_results %u buckets scanned %u",
383 i, result->scan_id, result->flags, result->num_results,
384 result->buckets_scanned);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385
386 ap = &result->ap[0];
387 for (j = 0; j < result->num_results; j++) {
388 /*
389 * Firmware returns timestamp from ext scan start till
390 * BSSID was cached (in micro seconds). Add this with
391 * time gap between system boot up to ext scan start
392 * to derive the time since boot when the
393 * BSSID was cached.
394 */
395 ap->ts += pHddCtx->ext_scan_start_since_boot;
Jeff Johnson630f9e72016-07-25 12:00:12 -0700396 hdd_notice("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800397 "Ssid: %s "
398 "Bssid (" MAC_ADDRESS_STR ") "
399 "Channel %u "
400 "Rssi %d "
401 "RTT %u "
402 "RTT_SD %u "
403 "Beacon Period %u "
404 "Capability 0x%x "
405 "Ie length %d",
406 ap->ts,
407 ap->ssid,
408 MAC_ADDR_ARRAY(ap->bssid.bytes),
409 ap->channel,
410 ap->rssi,
411 ap->rtt,
412 ap->rtt_sd,
413 ap->beaconPeriod,
414 ap->capability,
415 ap->ieLength);
416 ap++;
417 }
418 result++;
419 }
420
421 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
422 data->request_id) ||
423 nla_put_u32(skb,
424 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
425 data->num_scan_ids) ||
426 nla_put_u8(skb,
427 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
428 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700429 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430 goto fail;
431 }
432
433 if (data->num_scan_ids) {
434 struct nlattr *nla_results;
435 result = &data->result[0];
436
437 if (nla_put_u32(skb,
438 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
439 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700440 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 goto fail;
442 }
443 nla_results = nla_nest_start(skb,
444 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
445 if (!nla_results)
446 goto fail;
447
448 for (i = 0; i < data->num_scan_ids; i++) {
449 struct nlattr *nla_result;
450 struct nlattr *nla_aps;
451
452 nla_result = nla_nest_start(skb, i);
453 if (!nla_result)
454 goto fail;
455
456 if (nla_put_u32(skb,
457 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
458 result->scan_id) ||
459 nla_put_u32(skb,
460 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
461 result->flags) ||
462 nla_put_u32(skb,
Mukul Sharmafa937be2016-08-12 18:13:36 +0530463 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530464 result->buckets_scanned) ||
Mukul Sharmafa937be2016-08-12 18:13:36 +0530465 nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
467 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700468 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800469 goto fail;
470 }
471
472 nla_aps = nla_nest_start(skb,
473 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
474 if (!nla_aps)
475 goto fail;
476
477 ap = &result->ap[0];
478 for (j = 0; j < result->num_results; j++) {
479 if (hdd_extscan_nl_fill_bss(skb, ap, j))
480 goto fail;
481
482 ap++;
483 }
484 nla_nest_end(skb, nla_aps);
485 nla_nest_end(skb, nla_result);
486 result++;
487 }
488 nla_nest_end(skb, nla_results);
489 }
490
491 cfg80211_vendor_cmd_reply(skb);
492
493 if (!data->more_data) {
494 spin_lock(&context->context_lock);
495 context->response_status = 0;
496 complete(&context->response_event);
497 spin_unlock(&context->context_lock);
498 }
499 return;
500
501fail:
502 if (skb)
503 kfree_skb(skb);
504
505 spin_lock(&context->context_lock);
506 context->response_status = -EINVAL;
507 spin_unlock(&context->context_lock);
508
509 return;
510}
511
512/**
513 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
514 * @ctx: Pointer to hdd context
515 * @pData: Pointer to ext scan result event
516 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800517 * This callback execute in atomic context and must not invoke any
518 * blocking calls.
519 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 * Return: none
521 */
522static void
523wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
524 struct extscan_hotlist_match *data)
525{
526 hdd_context_t *pHddCtx = ctx;
527 struct sk_buff *skb = NULL;
528 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800529 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530
531 ENTER();
532
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530533 if (wlan_hdd_validate_context(pHddCtx))
534 return;
535 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700536 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537 return;
538 }
539
540 if (data->ap_found)
541 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
542 else
543 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
544
545 skb = cfg80211_vendor_event_alloc(
546 pHddCtx->wiphy,
547 NULL,
548 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800549 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550
551 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700552 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 return;
554 }
555 hdd_info("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
556 data->requestId, data->numOfAps, data->moreData,
557 data->ap_found);
558
559 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530560 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561
Jeff Johnson630f9e72016-07-25 12:00:12 -0700562 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 "Ssid: %s "
564 "Bssid (" MAC_ADDRESS_STR ") "
565 "Channel %u "
566 "Rssi %d "
567 "RTT %u "
568 "RTT_SD %u",
569 i,
570 data->ap[i].ts,
571 data->ap[i].ssid,
572 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
573 data->ap[i].channel,
574 data->ap[i].rssi,
575 data->ap[i].rtt, data->ap[i].rtt_sd);
576 }
577
578 if (nla_put_u32(skb,
579 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
580 data->requestId) ||
581 nla_put_u32(skb,
582 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
583 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700584 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585 goto fail;
586 }
587
588 if (data->numOfAps) {
589 struct nlattr *aps;
590
591 aps = nla_nest_start(skb,
592 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
593 if (!aps)
594 goto fail;
595
596 for (i = 0; i < data->numOfAps; i++) {
597 struct nlattr *ap;
598
599 ap = nla_nest_start(skb, i);
600 if (!ap)
601 goto fail;
602
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700603 if (hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
605 data->ap[i].ts) ||
606 nla_put(skb,
607 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
608 sizeof(data->ap[i].ssid),
609 data->ap[i].ssid) ||
610 nla_put(skb,
611 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
612 sizeof(data->ap[i].bssid),
613 data->ap[i].bssid.bytes) ||
614 nla_put_u32(skb,
615 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
616 data->ap[i].channel) ||
617 nla_put_s32(skb,
618 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
619 data->ap[i].rssi) ||
620 nla_put_u32(skb,
621 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
622 data->ap[i].rtt) ||
623 nla_put_u32(skb,
624 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
625 data->ap[i].rtt_sd))
626 goto fail;
627
628 nla_nest_end(skb, ap);
629 }
630 nla_nest_end(skb, aps);
631
632 if (nla_put_u8(skb,
633 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
634 data->moreData))
635 goto fail;
636 }
637
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800638 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530639 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640 return;
641
642fail:
643 kfree_skb(skb);
644 return;
645}
646
647/**
648 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
649 * significant wifi change results indication
650 * @ctx: Pointer to hdd context
651 * @pData: Pointer to signif wifi change event
652 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800653 * This callback execute in atomic context and must not invoke any
654 * blocking calls.
655 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800656 * Return: none
657 */
658static void
659wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
660 void *ctx,
661 tpSirWifiSignificantChangeEvent pData)
662{
663 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
664 struct sk_buff *skb = NULL;
665 tSirWifiSignificantChange *ap_info;
666 int32_t *rssi;
667 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800668 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669
670 ENTER();
671
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530672 if (wlan_hdd_validate_context(pHddCtx))
673 return;
674 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700675 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 return;
677 }
678
679 skb = cfg80211_vendor_event_alloc(
680 pHddCtx->wiphy,
681 NULL,
682 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
683 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800684 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685
686 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700687 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 return;
689 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700690 hdd_notice("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 pData->requestId, pData->numResults, pData->moreData);
692
693 ap_info = &pData->ap[0];
694 for (i = 0; i < pData->numResults; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700695 hdd_notice("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 "Bssid (" MAC_ADDRESS_STR ") "
697 "Channel %u "
698 "numOfRssi %d",
699 i,
700 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
701 ap_info->channel, ap_info->numOfRssi);
702 rssi = &(ap_info)->rssi[0];
703 for (j = 0; j < ap_info->numOfRssi; j++)
Jeff Johnson630f9e72016-07-25 12:00:12 -0700704 hdd_notice("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705
706 ap_info += ap_info->numOfRssi * sizeof(*rssi);
707 }
708
709 if (nla_put_u32(skb,
710 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
711 pData->requestId) ||
712 nla_put_u32(skb,
713 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
714 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700715 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 goto fail;
717 }
718
719 if (pData->numResults) {
720 struct nlattr *aps;
721
722 aps = nla_nest_start(skb,
723 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
724 if (!aps)
725 goto fail;
726
727 ap_info = &pData->ap[0];
728 for (i = 0; i < pData->numResults; i++) {
729 struct nlattr *ap;
730
731 ap = nla_nest_start(skb, i);
732 if (!ap)
733 goto fail;
734
735 if (nla_put(skb,
736 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530737 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800738 nla_put_u32(skb,
739 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
740 ap_info->channel) ||
741 nla_put_u32(skb,
742 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
743 ap_info->numOfRssi) ||
744 nla_put(skb,
745 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
746 sizeof(s32) * ap_info->numOfRssi,
747 &(ap_info)->rssi[0]))
748 goto fail;
749
750 nla_nest_end(skb, ap);
751
752 ap_info += ap_info->numOfRssi * sizeof(*rssi);
753 }
754 nla_nest_end(skb, aps);
755
756 if (nla_put_u8(skb,
757 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
758 pData->moreData))
759 goto fail;
760 }
761
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800762 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763 return;
764
765fail:
766 kfree_skb(skb);
767 return;
768
769}
770
771/**
772 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
773 * @ctx: Pointer to hdd context
774 * @pData: Pointer to full scan result event
775 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800776 * This callback execute in atomic context and must not invoke any
777 * blocking calls.
778 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 * Return: none
780 */
781static void
782wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
783 tpSirWifiFullScanResultEvent
784 pData)
785{
786 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
787 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788 struct timespec ts;
Mukul Sharmafa937be2016-08-12 18:13:36 +0530789 struct hdd_ext_scan_context *context;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700790
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800791 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700793 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530795 if (wlan_hdd_validate_context(pHddCtx))
796 return;
797 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700798 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 return;
800 }
801
802 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700803 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 return;
805 }
806 skb = cfg80211_vendor_event_alloc(
807 pHddCtx->wiphy,
808 NULL,
809 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
810 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800811 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812
813 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700814 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 return;
816 }
817
818 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700819
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800820 /* Android does not want the time stamp from the frame.
821 Instead it wants a monotonic increasing value since boot */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700822 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700824
Jeff Johnson630f9e72016-07-25 12:00:12 -0700825 hdd_notice("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826 pData->moreData);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700827 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828 "Bssid (" MAC_ADDRESS_STR ") "
829 "Channel %u "
830 "Rssi %d "
831 "RTT %u "
832 "RTT_SD %u "
833 "Bcn Period %d "
834 "Capability 0x%X "
835 "IE Length %d",
836 pData->ap.ts,
837 pData->ap.ssid,
838 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
839 pData->ap.channel,
840 pData->ap.rssi,
841 pData->ap.rtt,
842 pData->ap.rtt_sd,
843 pData->ap.beaconPeriod,
844 pData->ap.capability, pData->ap.ieLength);
845
846 if (nla_put_u32(skb,
847 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
848 pData->requestId) ||
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700849 hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800850 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
851 pData->ap.ts) ||
852 nla_put(skb,
853 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
854 sizeof(pData->ap.ssid),
855 pData->ap.ssid) ||
856 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
857 sizeof(pData->ap.bssid),
858 pData->ap.bssid.bytes) ||
859 nla_put_u32(skb,
860 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
861 pData->ap.channel) ||
862 nla_put_s32(skb,
863 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
864 pData->ap.rssi) ||
865 nla_put_u32(skb,
866 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
867 pData->ap.rtt) ||
868 nla_put_u32(skb,
869 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
870 pData->ap.rtt_sd) ||
871 nla_put_u16(skb,
872 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
873 pData->ap.beaconPeriod) ||
874 nla_put_u16(skb,
875 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
876 pData->ap.capability) ||
877 nla_put_u32(skb,
878 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
879 pData->ap.ieLength) ||
880 nla_put_u8(skb,
881 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
882 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700883 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 goto nla_put_failure;
885 }
886
887 if (pData->ap.ieLength) {
888 if (nla_put(skb,
889 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
890 pData->ap.ieLength, pData->ap.ieData))
891 goto nla_put_failure;
892 }
893
Mukul Sharmafa937be2016-08-12 18:13:36 +0530894 context = &ext_scan_context;
895 spin_lock(&context->context_lock);
896 if (nla_put_u32(skb,
897 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
898 context->buckets_scanned)) {
899 spin_unlock(&context->context_lock);
900 hdd_notice("Failed to include buckets_scanned");
901 goto nla_put_failure;
902 }
903 spin_unlock(&context->context_lock);
904
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800905 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 return;
907
908nla_put_failure:
909 kfree_skb(skb);
910 return;
911}
912
913/**
914 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
915 * @ctx: Pointer to hdd context
916 * @pData: Pointer to scan results available indication param
917 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800918 * This callback execute in atomic context and must not invoke any
919 * blocking calls.
920 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921 * Return: none
922 */
923static void
924wlan_hdd_cfg80211_extscan_scan_res_available_event(
925 void *ctx,
926 tpSirExtScanResultsAvailableIndParams pData)
927{
928 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
929 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800930 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931
932 ENTER();
933
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530934 if (wlan_hdd_validate_context(pHddCtx))
935 return;
936 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700937 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800938 return;
939 }
940
941 skb = cfg80211_vendor_event_alloc(
942 pHddCtx->wiphy,
943 NULL,
944 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
945 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800946 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947
948 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700949 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 return;
951 }
952
Jeff Johnson630f9e72016-07-25 12:00:12 -0700953 hdd_notice("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954 pData->requestId, pData->numResultsAvailable);
955 if (nla_put_u32(skb,
956 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
957 pData->requestId) ||
958 nla_put_u32(skb,
959 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
960 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700961 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800962 goto nla_put_failure;
963 }
964
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800965 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530966 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967 return;
968
969nla_put_failure:
970 kfree_skb(skb);
971 return;
972}
973
974/**
975 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
976 * @ctx: Pointer to hdd context
977 * @pData: Pointer to scan event indication param
978 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800979 * This callback execute in atomic context and must not invoke any
980 * blocking calls.
981 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982 * Return: none
983 */
984static void
985wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
986 tpSirExtScanOnScanEventIndParams
987 pData)
988{
989 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
990 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800991 int flags = cds_get_gfp_flags();
Mukul Sharmafa937be2016-08-12 18:13:36 +0530992 struct hdd_ext_scan_context *context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700994 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530996 if (wlan_hdd_validate_context(pHddCtx))
997 return;
998 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700999 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 return;
1001 }
1002
1003 skb = cfg80211_vendor_event_alloc(
1004 pHddCtx->wiphy,
1005 NULL,
1006 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1007 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001008 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001009
1010 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001011 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001012 return;
1013 }
Mukul Sharmafa937be2016-08-12 18:13:36 +05301014
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001015 hdd_notice("Request Id: %u Scan event type: %u Scan event status: %u buckets scanned: %u",
Mukul Sharmafa937be2016-08-12 18:13:36 +05301016 pData->requestId, pData->scanEventType, pData->status,
1017 pData->buckets_scanned);
1018
Mukul Sharmafa937be2016-08-12 18:13:36 +05301019 context = &ext_scan_context;
1020 spin_lock(&context->context_lock);
1021 if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT) {
1022 context->buckets_scanned = 0;
1023 pData->scanEventType = WIFI_EXTSCAN_RESULTS_AVAILABLE;
1024 spin_unlock(&context->context_lock);
1025 } else if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_STARTED_EVENT) {
1026 context->buckets_scanned = pData->buckets_scanned;
1027 /* No need to report to user space */
1028 spin_unlock(&context->context_lock);
Mukul Sharma45114d92016-08-12 19:34:14 +05301029 goto nla_put_failure;
Mukul Sharmafa937be2016-08-12 18:13:36 +05301030 } else {
1031 spin_unlock(&context->context_lock);
1032 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001033
1034 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1035 pData->requestId) ||
1036 nla_put_u8(skb,
1037 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
Mukul Sharmafa937be2016-08-12 18:13:36 +05301038 pData->scanEventType)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001039 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001040 goto nla_put_failure;
1041 }
1042
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001043 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001044 return;
1045
1046nla_put_failure:
1047 kfree_skb(skb);
1048 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
Dustin Brownbb7e2f52016-10-17 12:16:35 -07001395 if (hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001396 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
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001496 /* ENTER() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301497
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 }
1573}
1574
1575/*
1576 * define short names for the global vendor params
1577 * used by wlan_hdd_send_ext_scan_capability()
1578 */
1579#define PARAM_REQUEST_ID \
1580 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1581#define PARAM_STATUS \
1582 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1583#define MAX_SCAN_CACHE_SIZE \
1584 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1585#define MAX_SCAN_BUCKETS \
1586 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1587#define MAX_AP_CACHE_PER_SCAN \
1588 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1589#define MAX_RSSI_SAMPLE_SIZE \
1590 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1591#define MAX_SCAN_RPT_THRHOLD \
1592 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1593#define MAX_HOTLIST_BSSIDS \
1594 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1595#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1596 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1597#define MAX_BSSID_HISTORY_ENTRIES \
1598 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1599#define MAX_HOTLIST_SSIDS \
1600 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1601#define MAX_NUM_EPNO_NETS \
1602 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1603#define MAX_NUM_EPNO_NETS_BY_SSID \
1604 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1605#define MAX_NUM_WHITELISTED_SSID \
1606 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301607#define MAX_NUM_BLACKLISTED_BSSID \
1608 QCA_WLAN_VENDOR_ATTR_EXTSCAN_MAX_NUM_BLACKLISTED_BSSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609
1610/**
1611 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1612 * @hdd_ctx: Pointer to hdd context
1613 *
1614 * Return: 0 for success, non-zero for failure
1615 */
1616static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx)
1617{
1618 int ret;
1619 struct sk_buff *skb;
1620 struct ext_scan_capabilities_response *data;
1621 uint32_t nl_buf_len;
1622
1623 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301624 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001626
1627 data = &(ext_scan_context.capability_response);
1628
1629 nl_buf_len = NLMSG_HDRLEN;
1630 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1631 (sizeof(data->status) + NLA_HDRLEN) +
1632 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1633 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1634 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1635 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1636 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1637 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1638 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1639 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1640 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1641 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1642 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301643 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN) +
1644 (sizeof(data->max_number_of_black_listed_bssid) + NLA_HDRLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001645
1646 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1647
1648 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001649 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650 return -ENOMEM;
1651 }
1652
1653
Jeff Johnson630f9e72016-07-25 12:00:12 -07001654 hdd_notice("Req Id %u", data->requestId);
1655 hdd_notice("Status %u", data->status);
1656 hdd_notice("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001657 data->max_scan_cache_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001658 hdd_notice("Scan buckets %u", data->max_scan_buckets);
1659 hdd_notice("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001660 data->max_ap_cache_per_scan);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001661 hdd_notice("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 data->max_rssi_sample_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001663 hdd_notice("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 data->max_scan_reporting_threshold);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001665 hdd_notice("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 data->max_hotlist_bssids);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001667 hdd_notice("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668 data->max_significant_wifi_change_aps);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001669 hdd_notice("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001670 data->max_bssid_history_entries);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001671 hdd_notice("max_hotlist_ssids %u", data->max_hotlist_ssids);
1672 hdd_notice("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673 data->max_number_epno_networks);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001674 hdd_notice("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001675 data->max_number_epno_networks_by_ssid);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001676 hdd_notice("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677 data->max_number_of_white_listed_ssid);
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301678 hdd_notice("max_number_of_black_listed_bssid (%u)",
1679 data->max_number_of_black_listed_bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001680
1681 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1682 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1683 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1684 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1685 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1686 data->max_ap_cache_per_scan) ||
1687 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1688 data->max_rssi_sample_size) ||
1689 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1690 data->max_scan_reporting_threshold) ||
1691 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1692 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1693 data->max_significant_wifi_change_aps) ||
1694 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1695 data->max_bssid_history_entries) ||
1696 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1697 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1698 data->max_number_epno_networks) ||
1699 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1700 data->max_number_epno_networks_by_ssid) ||
1701 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301702 data->max_number_of_white_listed_ssid) ||
1703 nla_put_u32(skb, MAX_NUM_BLACKLISTED_BSSID,
1704 data->max_number_of_black_listed_bssid)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001705 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001706 goto nla_put_failure;
1707 }
1708
1709 cfg80211_vendor_cmd_reply(skb);
1710 return 0;
1711
1712nla_put_failure:
1713 kfree_skb(skb);
1714 return -EINVAL;
1715}
1716/*
1717 * done with short names for the global vendor params
1718 * used by wlan_hdd_send_ext_scan_capability()
1719 */
1720#undef PARAM_REQUEST_ID
1721#undef PARAM_STATUS
1722#undef MAX_SCAN_CACHE_SIZE
1723#undef MAX_SCAN_BUCKETS
1724#undef MAX_AP_CACHE_PER_SCAN
1725#undef MAX_RSSI_SAMPLE_SIZE
1726#undef MAX_SCAN_RPT_THRHOLD
1727#undef MAX_HOTLIST_BSSIDS
1728#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1729#undef MAX_BSSID_HISTORY_ENTRIES
1730#undef MAX_HOTLIST_SSIDS
1731#undef MAX_NUM_EPNO_NETS
1732#undef MAX_NUM_EPNO_NETS_BY_SSID
1733#undef MAX_NUM_WHITELISTED_SSID
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301734#undef MAX_NUM_BLACKLISTED_BSSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001735
1736/**
1737 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1738 * @wiphy: Pointer to wireless phy
1739 * @wdev: Pointer to wireless device
1740 * @data: Pointer to data
1741 * @data_len: Data length
1742 *
1743 * Return: none
1744 */
1745static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1746 struct wireless_dev *wdev,
1747 const void *data, int data_len)
1748{
1749 int ret;
1750 unsigned long rc;
1751 struct hdd_ext_scan_context *context;
1752 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1753 struct net_device *dev = wdev->netdev;
1754 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1755 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1756 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1757 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301758 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759
Jeff Johnson1f61b612016-02-12 16:28:33 -08001760 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001761
Anurag Chouhan6d760662016-02-20 16:05:43 +05301762 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763 hdd_err("Command not allowed in FTM mode");
1764 return -EPERM;
1765 }
1766
1767 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301768 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001769 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301771 if (!pHddCtx->config->extscan_enabled) {
1772 hdd_err("extscan not supported");
1773 return -ENOTSUPP;
1774 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1776 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001777 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 return -EINVAL;
1779 }
1780
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301781 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001783 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784 return -ENOMEM;
1785 }
1786
1787 /* Parse and fetch request Id */
1788 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001789 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001790 goto fail;
1791 }
1792
1793 pReqMsg->requestId =
1794 nla_get_u32(tb
1795 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
1796 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001797 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 pReqMsg->requestId, pReqMsg->sessionId);
1799
1800 context = &ext_scan_context;
1801 spin_lock(&context->context_lock);
1802 context->request_id = pReqMsg->requestId;
1803 INIT_COMPLETION(context->response_event);
1804 spin_unlock(&context->context_lock);
1805
1806 status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301807 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001808 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809 status);
1810 goto fail;
1811 }
1812
1813 rc = wait_for_completion_timeout(&context->response_event,
1814 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1815 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001816 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001817 return -ETIMEDOUT;
1818 }
1819
1820 ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
1821 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001822 hdd_err("Failed to send ext scan capability to user space");
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301823 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 return ret;
1825fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301826 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001827 return -EINVAL;
1828}
1829
1830/**
1831 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1832 * @wiphy: Pointer to wiphy
1833 * @wdev: Pointer to wdev
1834 * @data: Pointer to data
1835 * @data_len: Data length
1836 *
1837 * Return: 0 for success, non-zero for failure
1838 */
1839int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1840 struct wireless_dev *wdev,
1841 const void *data, int data_len)
1842{
1843 int ret = 0;
1844
1845 cds_ssr_protect(__func__);
1846 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1847 data_len);
1848 cds_ssr_unprotect(__func__);
1849
1850 return ret;
1851}
1852
1853/*
1854 * define short names for the global vendor params
1855 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1856 */
1857#define PARAM_MAX \
1858 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1859#define PARAM_REQUEST_ID \
1860 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1861#define PARAM_FLUSH \
1862 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1863/**
1864 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1865 * @wiphy: wiphy pointer
1866 * @wdev: pointer to struct wireless_dev
1867 * @data: pointer to incoming NL vendor data
1868 * @data_len: length of @data
1869 *
1870 * This function parses the incoming NL vendor command data attributes and
1871 * invokes the SME Api and blocks on a completion variable.
1872 * Each WMI event with cached scan results data chunk results in
1873 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1874 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1875 *
1876 * If timeout happens before receiving all of the data, this function sets
1877 * a context variable @ignore_cached_results to %true, all of the next data
1878 * chunks are checked against this variable and dropped.
1879 *
1880 * Return: 0 on success; error number otherwise.
1881 */
1882static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1883 struct wireless_dev
1884 *wdev, const void *data,
1885 int data_len)
1886{
1887 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1888 struct net_device *dev = wdev->netdev;
1889 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1890 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1891 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1892 1];
1893 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301894 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 int retval = 0;
1896 unsigned long rc;
1897
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001898 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899
Anurag Chouhan6d760662016-02-20 16:05:43 +05301900 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 hdd_err("Command not allowed in FTM mode");
1902 return -EPERM;
1903 }
1904
1905 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301906 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001908
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301909 if (!pHddCtx->config->extscan_enabled) {
1910 hdd_err("extscan not supported");
1911 return -ENOTSUPP;
1912 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 if (nla_parse(tb, PARAM_MAX, data, data_len,
1914 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001915 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916 return -EINVAL;
1917 }
1918
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301919 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001921 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 return -ENOMEM;
1923 }
1924
1925 /* Parse and fetch request Id */
1926 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001927 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928 goto fail;
1929 }
1930
1931 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
1932 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001933
1934 /* Parse and fetch flush parameter */
1935 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001936 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937 goto fail;
1938 }
1939 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001940 hdd_notice("Req Id: %u Session Id: %d Flush: %d",
1941 pReqMsg->requestId, pReqMsg->sessionId, pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001942
1943 context = &ext_scan_context;
1944 spin_lock(&context->context_lock);
1945 context->request_id = pReqMsg->requestId;
1946 context->ignore_cached_results = false;
1947 INIT_COMPLETION(context->response_event);
1948 spin_unlock(&context->context_lock);
1949
1950 status = sme_get_cached_results(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301951 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001952 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 goto fail;
1954 }
1955
1956 rc = wait_for_completion_timeout(&context->response_event,
1957 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1958 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001959 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 retval = -ETIMEDOUT;
1961 spin_lock(&context->context_lock);
1962 context->ignore_cached_results = true;
1963 spin_unlock(&context->context_lock);
1964 } else {
1965 spin_lock(&context->context_lock);
1966 retval = context->response_status;
1967 spin_unlock(&context->context_lock);
1968 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969 return retval;
1970
1971fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301972 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 return -EINVAL;
1974}
1975/*
1976 * done with short names for the global vendor params
1977 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1978 */
1979#undef PARAM_MAX
1980#undef PARAM_REQUEST_ID
1981#undef PARAM_FLUSH
1982
1983/**
1984 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1985 * @wiphy: wiphy pointer
1986 * @wdev: pointer to struct wireless_dev
1987 * @data: pointer to incoming NL vendor data
1988 * @data_len: length of @data
1989 *
1990 * This function parses the incoming NL vendor command data attributes and
1991 * invokes the SME Api and blocks on a completion variable.
1992 * Each WMI event with cached scan results data chunk results in
1993 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1994 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1995 *
1996 * If timeout happens before receiving all of the data, this function sets
1997 * a context variable @ignore_cached_results to %true, all of the next data
1998 * chunks are checked against this variable and dropped.
1999 *
2000 * Return: 0 on success; error number otherwise.
2001 */
2002int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
2003 struct wireless_dev *wdev,
2004 const void *data, int data_len)
2005{
2006 int ret = 0;
2007
2008 cds_ssr_protect(__func__);
2009 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
2010 data_len);
2011 cds_ssr_unprotect(__func__);
2012
2013 return ret;
2014}
2015
2016/**
2017 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
2018 * @wiphy: Pointer to wireless phy
2019 * @wdev: Pointer to wireless device
2020 * @data: Pointer to data
2021 * @data_len: Data length
2022 *
2023 * Return: none
2024 */
2025static int
2026__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2027 struct wireless_dev
2028 *wdev, const void *data,
2029 int data_len)
2030{
2031 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
2032 struct net_device *dev = wdev->netdev;
2033 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2034 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2035 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2036 1];
2037 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2038 + 1];
2039 struct nlattr *apTh;
2040 struct hdd_ext_scan_context *context;
2041 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302042 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002043 uint8_t i;
2044 int rem, retval;
2045 unsigned long rc;
2046
Jeff Johnson1f61b612016-02-12 16:28:33 -08002047 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048
Anurag Chouhan6d760662016-02-20 16:05:43 +05302049 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002050 hdd_err("Command not allowed in FTM mode");
2051 return -EPERM;
2052 }
2053
2054 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302055 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002056 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002057
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302058 if (!pHddCtx->config->extscan_enabled) {
2059 hdd_err("extscan not supported");
2060 return -ENOTSUPP;
2061 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2063 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002064 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002065 return -EINVAL;
2066 }
2067
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302068 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002069 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002070 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 return -ENOMEM;
2072 }
2073
2074 /* Parse and fetch request Id */
2075 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002076 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 goto fail;
2078 }
2079
2080 pReqMsg->requestId =
2081 nla_get_u32(tb
2082 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002083 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084
2085 /* Parse and fetch number of APs */
2086 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002087 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002088 goto fail;
2089 }
2090 pReqMsg->numAp =
2091 nla_get_u32(tb
2092 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002093 if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_HOTLIST_APS) {
2094 hdd_err("Number of AP: %u exceeds max: %u",
2095 pReqMsg->numAp, WLAN_EXTSCAN_MAX_HOTLIST_APS);
2096 goto fail;
2097 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002098 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002099 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100 pReqMsg->numAp, pReqMsg->sessionId);
2101
2102 /* Parse and fetch lost ap sample size */
2103 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002104 hdd_err("attr lost ap sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002105 goto fail;
2106 }
2107
2108 pReqMsg->lost_ap_sample_size = nla_get_u32(
2109 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002110 hdd_notice("Lost ap sample size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111 pReqMsg->lost_ap_sample_size);
2112
2113 i = 0;
2114 nla_for_each_nested(apTh,
2115 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2116 rem) {
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002117 if (i == pReqMsg->numAp) {
2118 hdd_warn("Ignoring excess AP");
2119 break;
2120 }
2121
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 if (nla_parse
2123 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2124 nla_data(apTh), nla_len(apTh),
2125 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002126 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 goto fail;
2128 }
2129
2130 /* Parse and fetch MAC address */
2131 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002132 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002133 goto fail;
2134 }
2135 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2136 tb2
2137 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302138 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002139 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002140 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2141
2142 /* Parse and fetch low RSSI */
2143 if (!tb2
2144 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002145 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002146 goto fail;
2147 }
2148 pReqMsg->ap[i].low =
2149 nla_get_s32(tb2
2150 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002151 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002152
2153 /* Parse and fetch high RSSI */
2154 if (!tb2
2155 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002156 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002157 goto fail;
2158 }
2159 pReqMsg->ap[i].high =
2160 nla_get_s32(tb2
2161 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002162 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002163
2164 i++;
2165 }
2166
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002167 if (i < pReqMsg->numAp) {
2168 hdd_warn("Number of AP %u less than expected %u",
2169 i, pReqMsg->numAp);
2170 pReqMsg->numAp = i;
2171 }
2172
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 context = &ext_scan_context;
2174 spin_lock(&context->context_lock);
2175 INIT_COMPLETION(context->response_event);
2176 context->request_id = request_id = pReqMsg->requestId;
2177 spin_unlock(&context->context_lock);
2178
2179 status = sme_set_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302180 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002181 hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002182 goto fail;
2183 }
2184
2185 /* request was sent -- wait for the response */
2186 rc = wait_for_completion_timeout
2187 (&context->response_event,
2188 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2189
2190 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002191 hdd_err("sme_set_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192 retval = -ETIMEDOUT;
2193 } else {
2194 spin_lock(&context->context_lock);
2195 if (context->request_id == request_id)
2196 retval = context->response_status;
2197 else
2198 retval = -EINVAL;
2199 spin_unlock(&context->context_lock);
2200 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302201 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002202 return retval;
2203
2204fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302205 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 return -EINVAL;
2207}
2208
2209/**
2210 * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist
2211 * @wiphy: Pointer to wiphy
2212 * @wdev: Pointer to wdev
2213 * @data: Pointer to data
2214 * @data_len: Data length
2215 *
2216 * Return: 0 for success, non-zero for failure
2217 */
2218int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2219 struct wireless_dev *wdev,
2220 const void *data, int data_len)
2221{
2222 int ret = 0;
2223
2224 cds_ssr_protect(__func__);
2225 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
2226 data_len);
2227 cds_ssr_unprotect(__func__);
2228
2229 return ret;
2230}
2231
2232
2233/**
2234 * __wlan_hdd_cfg80211_extscan_set_significant_change () - set significant change
2235 * @wiphy: Pointer to wireless phy
2236 * @wdev: Pointer to wireless device
2237 * @data: Pointer to data
2238 * @data_len: Data length
2239 *
2240 * Return: none
2241 */
2242static int
2243__wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2244 struct wireless_dev
2245 *wdev, const void *data,
2246 int data_len)
2247{
2248 tpSirExtScanSetSigChangeReqParams pReqMsg = NULL;
2249 struct net_device *dev = wdev->netdev;
2250 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2251 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2252 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2253 1];
2254 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2255 + 1];
2256 struct nlattr *apTh;
2257 struct hdd_ext_scan_context *context;
2258 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302259 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260 uint8_t i;
2261 int rem, retval;
2262 unsigned long rc;
2263
Jeff Johnson1f61b612016-02-12 16:28:33 -08002264 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002265
Anurag Chouhan6d760662016-02-20 16:05:43 +05302266 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002267 hdd_err("Command not allowed in FTM mode");
2268 return -EPERM;
2269 }
2270
2271 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302272 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002273 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002274
2275 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2276 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002277 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 return -EINVAL;
2279 }
2280
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302281 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002283 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284 return -ENOMEM;
2285 }
2286
2287 /* Parse and fetch request Id */
2288 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002289 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002290 goto fail;
2291 }
2292
2293 pReqMsg->requestId =
2294 nla_get_u32(tb
2295 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002296 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297
2298 /* Parse and fetch RSSI sample size */
2299 if (!tb
2300 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002301 hdd_err("attr RSSI sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002302 goto fail;
2303 }
2304 pReqMsg->rssiSampleSize =
2305 nla_get_u32(tb
2306 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002307 hdd_notice("RSSI sample size %u", pReqMsg->rssiSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308
2309 /* Parse and fetch lost AP sample size */
2310 if (!tb
2311 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002312 hdd_err("attr lost AP sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313 goto fail;
2314 }
2315 pReqMsg->lostApSampleSize =
2316 nla_get_u32(tb
2317 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002318 hdd_notice("Lost AP sample size %u", pReqMsg->lostApSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319
2320 /* Parse and fetch AP min breacing */
2321 if (!tb
2322 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002323 hdd_err("attr AP min breaching");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002324 goto fail;
2325 }
2326 pReqMsg->minBreaching =
2327 nla_get_u32(tb
2328 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002329 hdd_notice("AP min breaching %u", pReqMsg->minBreaching);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002330
2331 /* Parse and fetch number of APs */
2332 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002333 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002334 goto fail;
2335 }
2336 pReqMsg->numAp =
2337 nla_get_u32(tb
2338 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002339 if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS) {
2340 hdd_err("Number of AP %u exceeds max %u",
2341 pReqMsg->numAp,
2342 WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS);
2343 goto fail;
2344 }
2345
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002346 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002347 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348 pReqMsg->numAp, pReqMsg->sessionId);
2349
2350 i = 0;
2351 nla_for_each_nested(apTh,
2352 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2353 rem) {
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002354
2355 if (i == pReqMsg->numAp) {
2356 hdd_warn("Ignoring excess AP");
2357 break;
2358 }
2359
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002360 if (nla_parse
2361 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2362 nla_data(apTh), nla_len(apTh),
2363 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002364 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 goto fail;
2366 }
2367
2368 /* Parse and fetch MAC address */
2369 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002370 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002371 goto fail;
2372 }
2373 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2374 tb2
2375 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302376 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002377 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2379
2380 /* Parse and fetch low RSSI */
2381 if (!tb2
2382 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002383 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 goto fail;
2385 }
2386 pReqMsg->ap[i].low =
2387 nla_get_s32(tb2
2388 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002389 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390
2391 /* Parse and fetch high RSSI */
2392 if (!tb2
2393 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002394 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 goto fail;
2396 }
2397 pReqMsg->ap[i].high =
2398 nla_get_s32(tb2
2399 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002400 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401
2402 i++;
2403 }
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002404 if (i < pReqMsg->numAp) {
2405 hdd_warn("Number of AP %u less than expected %u",
2406 i, pReqMsg->numAp);
2407 pReqMsg->numAp = i;
2408 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409
2410 context = &ext_scan_context;
2411 spin_lock(&context->context_lock);
2412 INIT_COMPLETION(context->response_event);
2413 context->request_id = request_id = pReqMsg->requestId;
2414 spin_unlock(&context->context_lock);
2415
2416 status = sme_set_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302417 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002418 hdd_err("sme_set_significant_change failed(err=%d)", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302419 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002420 return -EINVAL;
2421 }
2422
2423 /* request was sent -- wait for the response */
2424 rc = wait_for_completion_timeout(&context->response_event,
2425 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2426
2427 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002428 hdd_err("sme_set_significant_change timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 retval = -ETIMEDOUT;
2430 } else {
2431 spin_lock(&context->context_lock);
2432 if (context->request_id == request_id)
2433 retval = context->response_status;
2434 else
2435 retval = -EINVAL;
2436 spin_unlock(&context->context_lock);
2437 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302438 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 return retval;
2440
2441fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302442 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 return -EINVAL;
2444}
2445
2446/**
2447 * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
2448 * @wiphy: Pointer to wireless phy
2449 * @wdev: Pointer to wireless device
2450 * @data: Pointer to data
2451 * @data_len: Data length
2452 *
2453 * Return: 0 on success, negative errno on failure
2454 */
2455int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2456 struct wireless_dev *wdev,
2457 const void *data, int data_len)
2458{
2459 int ret = 0;
2460
2461 cds_ssr_protect(__func__);
2462 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev,
2463 data, data_len);
2464 cds_ssr_unprotect(__func__);
2465
2466 return ret;
2467}
2468
2469/**
2470 * hdd_remove_dsrc_channels () - remove dsrc chanels
2471 * @wiphy: Pointer to wireless phy
2472 * @chan_list: channel list
2473 * @num_channels: number of channels
2474 *
2475 * Return: none
2476 */
Jeff Johnsoncd2a0792016-10-05 15:17:13 -07002477static void hdd_remove_dsrc_channels(struct wiphy *wiphy, uint32_t *chan_list,
2478 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479{
2480 uint8_t num_chan_temp = 0;
2481 int i;
2482
2483 for (i = 0; i < *num_channels; i++) {
2484 if (!cds_is_dsrc_channel(chan_list[i])) {
2485 chan_list[num_chan_temp] = chan_list[i];
2486 num_chan_temp++;
2487 }
2488 }
2489
2490 *num_channels = num_chan_temp;
2491}
2492
2493/**
Amar Singhalea10a872016-08-23 15:31:45 -07002494 * hdd_remove_passive_channels () - remove passive channels
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 * @wiphy: Pointer to wireless phy
2496 * @chan_list: channel list
2497 * @num_channels: number of channels
2498 *
2499 * Return: none
2500 */
Amar Singhal25b10f92016-11-14 16:53:25 -08002501static void hdd_remove_passive_channels(struct wiphy *wiphy,
2502 uint32_t *chan_list,
2503 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504{
2505 uint8_t num_chan_temp = 0;
2506 int i, j, k;
2507
2508 for (i = 0; i < *num_channels; i++)
Dustin Browna30892e2016-10-12 17:28:36 -07002509 for (j = 0; j < NUM_NL80211_BANDS; j++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510 if (wiphy->bands[j] == NULL)
2511 continue;
2512 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
2513 if ((chan_list[i] ==
2514 wiphy->bands[j]->channels[k].center_freq)
2515 && (!(wiphy->bands[j]->channels[k].flags &
Amar Singhalea10a872016-08-23 15:31:45 -07002516 IEEE80211_CHAN_PASSIVE_SCAN))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 ) {
2518 chan_list[num_chan_temp] = chan_list[i];
2519 num_chan_temp++;
2520 }
2521 }
2522 }
2523
2524 *num_channels = num_chan_temp;
2525}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526
2527/**
2528 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
2529 * @wiphy: Pointer to wireless phy
2530 * @wdev: Pointer to wireless device
2531 * @data: Pointer to data
2532 * @data_len: Data length
2533 *
2534 * Return: none
2535 */
2536static int
2537__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2538 struct wireless_dev
2539 *wdev, const void *data,
2540 int data_len)
2541{
2542 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2543 struct net_device *dev = wdev->netdev;
2544 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2545 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002546 uint8_t num_channels = 0, i, buf[256] = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2548 1];
2549 uint32_t requestId, maxChannels;
2550 tWifiBand wifiBand;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302551 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002552 struct sk_buff *reply_skb;
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002553 int ret, len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002555 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556
Anurag Chouhan6d760662016-02-20 16:05:43 +05302557 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002558 hdd_err("Command not allowed in FTM mode");
2559 return -EPERM;
2560 }
2561
2562 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302563 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302566 if (!pHddCtx->config->extscan_enabled) {
2567 hdd_err("extscan not supported");
2568 return -ENOTSUPP;
2569 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2571 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002572 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573 return -EINVAL;
2574 }
2575
2576 /* Parse and fetch request Id */
2577 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002578 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 return -EINVAL;
2580 }
2581 requestId =
2582 nla_get_u32(tb
2583 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584
2585 /* Parse and fetch wifi band */
2586 if (!tb
2587 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002588 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 return -EINVAL;
2590 }
2591 wifiBand =
2592 nla_get_u32(tb
2593 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594
2595 if (!tb
2596 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002597 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002598 return -EINVAL;
2599 }
2600 maxChannels =
2601 nla_get_u32(tb
2602 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Manjeet Singhdb485182016-11-09 19:11:01 +05302603
2604 if (maxChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) {
2605 hdd_err("Max channels %d exceeded Valid channel list len %d",
2606 maxChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2607 return -EINVAL;
2608 }
2609
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002610 hdd_notice("Req Id: %u Wifi band: %d Max channels: %d", requestId,
2611 wifiBand, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 status = sme_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal),
2613 wifiBand, chan_list,
2614 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302615 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002616 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617 status);
2618 return -EINVAL;
2619 }
2620
Anurag Chouhan6d760662016-02-20 16:05:43 +05302621 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002622
2623 hdd_remove_dsrc_channels(wiphy, chan_list, &num_channels);
2624
Krunal Sonibe766b02016-03-10 13:00:44 -08002625 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002626 !strncmp(hdd_get_fwpath(), "ap", 2))
Amar Singhalea10a872016-08-23 15:31:45 -07002627 hdd_remove_passive_channels(wiphy, chan_list,
2628 &num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002629
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002630 hdd_notice("Number of channels: %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002631 for (i = 0; i < num_channels; i++)
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002632 len += scnprintf(buf + len, sizeof(buf) - len,
2633 "%u ", chan_list[i]);
2634
2635 hdd_notice("Channels: %s", buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636
2637 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2638 sizeof(u32) *
2639 num_channels +
2640 NLMSG_HDRLEN);
2641
2642 if (reply_skb) {
2643 if (nla_put_u32(reply_skb,
2644 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2645 num_channels) ||
2646 nla_put(reply_skb,
2647 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2648 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002649 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002650 kfree_skb(reply_skb);
2651 return -EINVAL;
2652 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302653 ret = cfg80211_vendor_cmd_reply(reply_skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302654 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655 }
2656
Jeff Johnson630f9e72016-07-25 12:00:12 -07002657 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658 return -EINVAL;
2659}
2660
2661/**
2662 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2663 * @wiphy: Pointer to wireless phy
2664 * @wdev: Pointer to wireless device
2665 * @data: Pointer to data
2666 * @data_len: Data length
2667 *
2668 * Return: 0 on success, negative errno on failure
2669 */
2670int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2671 struct wireless_dev *wdev,
2672 const void *data, int data_len)
2673{
2674 int ret = 0;
2675
2676 cds_ssr_protect(__func__);
2677 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2678 data_len);
2679 cds_ssr_unprotect(__func__);
2680
2681 return ret;
2682}
2683
2684/**
2685 * hdd_extscan_update_dwell_time_limits() - update dwell times
2686 * @req_msg: Pointer to request message
2687 * @bkt_idx: Index of current bucket being processed
2688 * @active_min: minimum active dwell time
2689 * @active_max: maximum active dwell time
2690 * @passive_min: minimum passive dwell time
2691 * @passive_max: maximum passive dwell time
2692 *
2693 * Return: none
2694 */
2695static void hdd_extscan_update_dwell_time_limits(
2696 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2697 uint32_t active_min, uint32_t active_max,
2698 uint32_t passive_min, uint32_t passive_max)
2699{
2700 /* update per-bucket dwell times */
2701 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2702 active_min) {
2703 req_msg->buckets[bkt_idx].min_dwell_time_active =
2704 active_min;
2705 }
2706 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2707 active_max) {
2708 req_msg->buckets[bkt_idx].max_dwell_time_active =
2709 active_max;
2710 }
2711 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2712 passive_min) {
2713 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2714 passive_min;
2715 }
2716 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2717 passive_max) {
2718 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2719 passive_max;
2720 }
2721 /* update dwell-time across all buckets */
2722 if (req_msg->min_dwell_time_active >
2723 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2724 req_msg->min_dwell_time_active =
2725 req_msg->buckets[bkt_idx].min_dwell_time_active;
2726 }
2727 if (req_msg->max_dwell_time_active <
2728 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2729 req_msg->max_dwell_time_active =
2730 req_msg->buckets[bkt_idx].max_dwell_time_active;
2731 }
2732 if (req_msg->min_dwell_time_passive >
2733 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2734 req_msg->min_dwell_time_passive =
2735 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2736 }
2737 if (req_msg->max_dwell_time_passive >
2738 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2739 req_msg->max_dwell_time_passive =
2740 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2741 }
2742}
2743
2744/**
2745 * hdd_extscan_channel_max_reached() - channel max reached
2746 * @req: extscan request structure
2747 * @total_channels: total number of channels
2748 *
2749 * Return: true if total channels reached max, false otherwise
2750 */
2751static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2752 uint8_t total_channels)
2753{
2754 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2755 hdd_warn(
2756 "max #of channels %d reached, take only first %d bucket(s)",
2757 total_channels, req->numBuckets);
2758 return true;
2759 }
2760 return false;
2761}
2762
2763/**
2764 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2765 * @hdd_ctx: HDD global context
2766 * @req_msg: Pointer to request structure
2767 * @tb: pointer to NL attributes
2768 *
2769 * Return: 0 on success; error number otherwise
2770 */
2771static int hdd_extscan_start_fill_bucket_channel_spec(
2772 hdd_context_t *hdd_ctx,
2773 tpSirWifiScanCmdReqParams req_msg,
2774 struct nlattr **tb)
2775{
2776 struct nlattr *bucket[
2777 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2778 struct nlattr *channel[
2779 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2780 struct nlattr *buckets;
2781 struct nlattr *channels;
2782 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302783 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 uint8_t bkt_index, j, num_channels, total_channels = 0;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002785 uint32_t expected_buckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2787
2788 uint32_t min_dwell_time_active_bucket =
2789 hdd_ctx->config->extscan_active_max_chn_time;
2790 uint32_t max_dwell_time_active_bucket =
2791 hdd_ctx->config->extscan_active_max_chn_time;
2792 uint32_t min_dwell_time_passive_bucket =
2793 hdd_ctx->config->extscan_passive_max_chn_time;
2794 uint32_t max_dwell_time_passive_bucket =
2795 hdd_ctx->config->extscan_passive_max_chn_time;
2796
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002797 req_msg->min_dwell_time_active =
2798 req_msg->max_dwell_time_active =
2799 hdd_ctx->config->extscan_active_max_chn_time;
2800
2801 req_msg->min_dwell_time_passive =
2802 req_msg->max_dwell_time_passive =
2803 hdd_ctx->config->extscan_passive_max_chn_time;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002804
2805 expected_buckets = req_msg->numBuckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806 req_msg->numBuckets = 0;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002807 bkt_index = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808
2809 nla_for_each_nested(buckets,
2810 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002811
2812 if (bkt_index >= expected_buckets) {
2813 hdd_warn("ignoring excess buckets");
2814 break;
2815 }
2816
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 if (nla_parse(bucket,
2818 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2819 nla_data(buckets), nla_len(buckets), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002820 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 return -EINVAL;
2822 }
2823
2824 /* Parse and fetch bucket spec */
2825 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002826 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002827 return -EINVAL;
2828 }
2829 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2830 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002831
2832 /* Parse and fetch wifi band */
2833 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002834 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835 return -EINVAL;
2836 }
2837 req_msg->buckets[bkt_index].band = nla_get_u8(
2838 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839
2840 /* Parse and fetch period */
2841 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002842 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 return -EINVAL;
2844 }
2845 req_msg->buckets[bkt_index].period = nla_get_u32(
2846 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847
2848 /* Parse and fetch report events */
2849 if (!bucket[
2850 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002851 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 return -EINVAL;
2853 }
2854 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2855 bucket[
2856 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857
2858 /* Parse and fetch max period */
2859 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002860 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002861 return -EINVAL;
2862 }
2863 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2864 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865
Mukul Sharmafa937be2016-08-12 18:13:36 +05302866 /* Parse and fetch base */
2867 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]) {
2868 hdd_err("attr base failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002869 return -EINVAL;
2870 }
2871 req_msg->buckets[bkt_index].exponent = nla_get_u32(
Mukul Sharmafa937be2016-08-12 18:13:36 +05302872 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002873
2874 /* Parse and fetch step count */
2875 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002876 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 return -EINVAL;
2878 }
2879 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2880 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002881 hdd_notice("Bucket spec Index: %d Wifi band: %d period: %d report events: %d max period: %u base: %u Step count: %u",
2882 req_msg->buckets[bkt_index].bucket,
2883 req_msg->buckets[bkt_index].band,
2884 req_msg->buckets[bkt_index].period,
2885 req_msg->buckets[bkt_index].reportEvents,
2886 req_msg->buckets[bkt_index].max_period,
2887 req_msg->buckets[bkt_index].exponent,
2888 req_msg->buckets[bkt_index].step_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002889
2890 /* start with known good values for bucket dwell times */
2891 req_msg->buckets[bkt_index].min_dwell_time_active =
2892 req_msg->buckets[bkt_index].max_dwell_time_active =
2893 hdd_ctx->config->extscan_active_max_chn_time;
2894
2895 req_msg->buckets[bkt_index].min_dwell_time_passive =
2896 req_msg->buckets[bkt_index].max_dwell_time_passive =
2897 hdd_ctx->config->extscan_passive_max_chn_time;
2898
2899 /* Framework shall pass the channel list if the input WiFi band
2900 * is WIFI_BAND_UNSPECIFIED.
2901 * If the input WiFi band is specified (any value other than
2902 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2903 */
2904 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2905 if (hdd_extscan_channel_max_reached(req_msg,
2906 total_channels))
2907 return 0;
2908
2909 num_channels = 0;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002910 hdd_notice("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2912 req_msg->buckets[bkt_index].band,
2913 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302914 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002915 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 status);
2917 return -EINVAL;
2918 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07002919 hdd_notice("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 num_channels);
2921
2922 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302923 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002924 (WLAN_EXTSCAN_MAX_CHANNELS -
2925 total_channels));
2926 hdd_info("Adj Num channels/bucket: %d total_channels: %d",
2927 req_msg->buckets[bkt_index].numChannels,
2928 total_channels);
2929 total_channels +=
2930 req_msg->buckets[bkt_index].numChannels;
2931
2932 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2933 j++) {
2934 req_msg->buckets[bkt_index].channels[j].channel =
2935 chan_list[j];
2936 req_msg->buckets[bkt_index].channels[j].
2937 chnlClass = 0;
2938 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2939 cds_freq_to_chan(chan_list[j]))) {
2940 req_msg->buckets[bkt_index].channels[j].
2941 passive = 1;
2942 req_msg->buckets[bkt_index].channels[j].
2943 dwellTimeMs =
2944 hdd_ctx->config->
2945 extscan_passive_max_chn_time;
2946 /* reconfigure per-bucket dwell time */
2947 if (min_dwell_time_passive_bucket >
2948 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2949 min_dwell_time_passive_bucket =
2950 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2951 }
2952 if (max_dwell_time_passive_bucket <
2953 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2954 max_dwell_time_passive_bucket =
2955 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2956 }
2957
2958 } else {
2959 req_msg->buckets[bkt_index].channels[j].
2960 passive = 0;
2961 req_msg->buckets[bkt_index].channels[j].
2962 dwellTimeMs =
2963 hdd_ctx->config->extscan_active_max_chn_time;
2964 /* reconfigure per-bucket dwell times */
2965 if (min_dwell_time_active_bucket >
2966 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2967 min_dwell_time_active_bucket =
2968 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2969 }
2970 if (max_dwell_time_active_bucket <
2971 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2972 max_dwell_time_active_bucket =
2973 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2974 }
2975
2976 }
2977
Jeff Johnson630f9e72016-07-25 12:00:12 -07002978 hdd_notice("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979 req_msg->buckets[bkt_index].channels[j].channel,
2980 req_msg->buckets[bkt_index].channels[j].passive,
2981 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2982 req_msg->buckets[bkt_index].channels[j].chnlClass);
2983 }
2984
2985 hdd_extscan_update_dwell_time_limits(
2986 req_msg, bkt_index,
2987 min_dwell_time_active_bucket,
2988 max_dwell_time_active_bucket,
2989 min_dwell_time_passive_bucket,
2990 max_dwell_time_passive_bucket);
2991
Jeff Johnson630f9e72016-07-25 12:00:12 -07002992 hdd_notice("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002993 bkt_index,
2994 req_msg->buckets[bkt_index].min_dwell_time_active,
2995 req_msg->buckets[bkt_index].max_dwell_time_active,
2996 req_msg->buckets[bkt_index].min_dwell_time_passive,
2997 req_msg->buckets[bkt_index].max_dwell_time_passive);
2998
2999 bkt_index++;
3000 req_msg->numBuckets++;
3001 continue;
3002 }
3003
3004 /* Parse and fetch number of channels */
3005 if (!bucket[
3006 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003007 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 return -EINVAL;
3009 }
3010 req_msg->buckets[bkt_index].numChannels =
3011 nla_get_u32(bucket[
3012 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
3013 hdd_info("before trimming: num channels %d",
3014 req_msg->buckets[bkt_index].numChannels);
3015
3016 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05303017 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
3019 hdd_info("Num channels/bucket: %d total_channels: %d",
3020 req_msg->buckets[bkt_index].numChannels,
3021 total_channels);
3022 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
3023 return 0;
3024
3025 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003026 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 return -EINVAL;
3028 }
3029
3030 j = 0;
3031 nla_for_each_nested(channels,
3032 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07003033 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
3034 hdd_extscan_channel_max_reached(req_msg,
3035 total_channels))
3036 break;
3037
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 if (nla_parse(channel,
3039 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3040 nla_data(channels), nla_len(channels),
3041 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003042 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 return -EINVAL;
3044 }
3045
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046 /* Parse and fetch channel */
3047 if (!channel[
3048 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003049 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 return -EINVAL;
3051 }
3052 req_msg->buckets[bkt_index].channels[j].channel =
3053 nla_get_u32(channel[
3054 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003055 hdd_notice("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 req_msg->buckets[bkt_index].channels[j].channel);
3057
3058 /* Parse and fetch dwell time */
3059 if (!channel[
3060 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003061 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003062 return -EINVAL;
3063 }
3064 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3065 nla_get_u32(channel[
3066 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
3067
3068 /* Override dwell time if required */
3069 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
3070 hdd_ctx->config->extscan_active_min_chn_time ||
3071 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
3072 hdd_ctx->config->extscan_active_max_chn_time) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003073 hdd_notice("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3075
3076 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3077 cds_freq_to_chan(
3078 req_msg->buckets[bkt_index].channels[j].channel))) {
3079 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3080 hdd_ctx->config->extscan_passive_max_chn_time;
3081 } else {
3082 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3083 hdd_ctx->config->extscan_active_max_chn_time;
3084 }
3085 }
3086
Jeff Johnson630f9e72016-07-25 12:00:12 -07003087 hdd_notice("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003088 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3089
3090 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3091 cds_freq_to_chan(
3092 req_msg->buckets[bkt_index].channels[j].channel))) {
3093 if (min_dwell_time_passive_bucket >
3094 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3095 min_dwell_time_passive_bucket =
3096 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3097 }
3098 if (max_dwell_time_passive_bucket <
3099 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3100 max_dwell_time_passive_bucket =
3101 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3102 }
3103 } else {
3104 if (min_dwell_time_active_bucket >
3105 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3106 min_dwell_time_active_bucket =
3107 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3108 }
3109 if (max_dwell_time_active_bucket <
3110 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3111 max_dwell_time_active_bucket =
3112 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3113 }
3114 }
3115
3116 /* Parse and fetch channel spec passive */
3117 if (!channel[
3118 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003119 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003120 return -EINVAL;
3121 }
3122 req_msg->buckets[bkt_index].channels[j].passive =
3123 nla_get_u8(channel[
3124 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003125 hdd_notice("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003126 req_msg->buckets[bkt_index].channels[j].passive);
3127 /* Override scan type if required */
3128 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3129 cds_freq_to_chan(
3130 req_msg->buckets[bkt_index].channels[j].channel))) {
3131 req_msg->buckets[bkt_index].channels[j].passive = true;
3132 } else {
3133 req_msg->buckets[bkt_index].channels[j].passive = false;
3134 }
3135 j++;
3136 total_channels++;
3137 }
3138
3139 hdd_extscan_update_dwell_time_limits(
3140 req_msg, bkt_index,
3141 min_dwell_time_active_bucket,
3142 max_dwell_time_active_bucket,
3143 min_dwell_time_passive_bucket,
3144 max_dwell_time_passive_bucket);
3145
Jeff Johnson630f9e72016-07-25 12:00:12 -07003146 hdd_notice("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003147 bkt_index,
3148 req_msg->buckets[bkt_index].min_dwell_time_active,
3149 req_msg->buckets[bkt_index].max_dwell_time_active,
3150 req_msg->buckets[bkt_index].min_dwell_time_passive,
3151 req_msg->buckets[bkt_index].max_dwell_time_passive);
3152
3153 bkt_index++;
3154 req_msg->numBuckets++;
3155 }
3156
Jeff Johnson630f9e72016-07-25 12:00:12 -07003157 hdd_notice("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158 req_msg->min_dwell_time_active,
3159 req_msg->max_dwell_time_active,
3160 req_msg->min_dwell_time_passive,
3161 req_msg->max_dwell_time_passive);
3162
3163 return 0;
3164}
3165
3166/*
3167 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3168 * @config_flags - [input] configuration flags.
3169 *
3170 * This function maps user space received configuration flags to
3171 * driver representation.
3172 *
3173 * Return: configuration flags
3174 */
3175static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3176{
3177 uint32_t configuration_flags = 0;
3178
3179 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3180 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3181
3182 return configuration_flags;
3183}
3184
3185/*
3186 * define short names for the global vendor params
3187 * used by __wlan_hdd_cfg80211_extscan_start()
3188 */
3189#define PARAM_MAX \
3190 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3191#define PARAM_REQUEST_ID \
3192 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3193#define PARAM_BASE_PERIOD \
3194 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3195#define PARAM_MAX_AP_PER_SCAN \
3196 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3197#define PARAM_RPT_THRHLD_PERCENT \
3198 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3199#define PARAM_RPT_THRHLD_NUM_SCANS \
3200 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3201#define PARAM_NUM_BUCKETS \
3202 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3203#define PARAM_CONFIG_FLAGS \
3204 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3205
3206/**
3207 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3208 * @wiphy: Pointer to wireless phy
3209 * @wdev: Pointer to wireless device
3210 * @data: Pointer to data
3211 * @data_len: Length of @data
3212 *
3213 * Return: 0 on success; error number otherwise
3214 */
3215static int
3216__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3217 struct wireless_dev *wdev,
3218 const void *data,
3219 int data_len)
3220{
3221 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3222 struct net_device *dev = wdev->netdev;
3223 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3224 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3225 struct nlattr *tb[PARAM_MAX + 1];
3226 struct hdd_ext_scan_context *context;
3227 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303228 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003229 int retval;
3230 unsigned long rc;
3231
Jeff Johnson1f61b612016-02-12 16:28:33 -08003232 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003233
Anurag Chouhan6d760662016-02-20 16:05:43 +05303234 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235 hdd_err("Command not allowed in FTM mode");
3236 return -EPERM;
3237 }
3238
3239 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303240 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303243 if (!pHddCtx->config->extscan_enabled) {
3244 hdd_err("extscan not supported");
3245 return -ENOTSUPP;
3246 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 if (nla_parse(tb, PARAM_MAX, data, data_len,
3248 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003249 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250 return -EINVAL;
3251 }
3252
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303253 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003254 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003255 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256 return -ENOMEM;
3257 }
3258
3259 /* Parse and fetch request Id */
3260 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003261 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003262 goto fail;
3263 }
3264
3265 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3266 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267
3268 /* Parse and fetch base period */
3269 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003270 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271 goto fail;
3272 }
3273 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274
3275 /* Parse and fetch max AP per scan */
3276 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003277 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 goto fail;
3279 }
3280 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281
3282 /* Parse and fetch report threshold percent */
3283 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003284 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003285 goto fail;
3286 }
3287 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003288
3289 /* Parse and fetch report threshold num scans */
3290 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003291 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 goto fail;
3293 }
3294 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003295 hdd_notice("Req Id: %d Session Id: %d Base Period: %d Max AP per Scan: %d Report Threshold percent: %d Report Threshold num scans: %d",
3296 pReqMsg->requestId, pReqMsg->sessionId,
3297 pReqMsg->basePeriod, pReqMsg->maxAPperScan,
3298 pReqMsg->report_threshold_percent,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 pReqMsg->report_threshold_num_scans);
3300
3301 /* Parse and fetch number of buckets */
3302 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003303 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003304 goto fail;
3305 }
3306 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3307 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3308 hdd_warn("Exceeded MAX number of buckets: %d",
3309 WLAN_EXTSCAN_MAX_BUCKETS);
Jeff Johnsonfae3c522016-11-11 17:57:13 -08003310 num_buckets = WLAN_EXTSCAN_MAX_BUCKETS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311 }
3312 hdd_info("Input: Number of Buckets %d", num_buckets);
Jeff Johnsonfae3c522016-11-11 17:57:13 -08003313 pReqMsg->numBuckets = num_buckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314
3315 /* This is optional attribute, if not present set it to 0 */
3316 if (!tb[PARAM_CONFIG_FLAGS])
3317 pReqMsg->configuration_flags = 0;
3318 else
3319 pReqMsg->configuration_flags =
3320 hdd_extscan_map_usr_drv_config_flags(
3321 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3322
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303323 pReqMsg->extscan_adaptive_dwell_mode =
3324 pHddCtx->config->extscan_adaptive_dwell_mode;
3325
Jeff Johnson630f9e72016-07-25 12:00:12 -07003326 hdd_notice("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003327 pReqMsg->configuration_flags);
3328
3329 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003330 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003331 goto fail;
3332 }
3333
3334 if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb))
3335 goto fail;
3336
3337 context = &ext_scan_context;
3338 spin_lock(&context->context_lock);
3339 INIT_COMPLETION(context->response_event);
3340 context->request_id = request_id = pReqMsg->requestId;
Mukul Sharmafa937be2016-08-12 18:13:36 +05303341 context->buckets_scanned = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003342 spin_unlock(&context->context_lock);
3343
3344 status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303345 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003346 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 goto fail;
3348 }
3349
Anurag Chouhan50220ce2016-02-18 20:11:33 +05303350 pHddCtx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Jeff Johnson630f9e72016-07-25 12:00:12 -07003351 hdd_notice("Timestamp since boot: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 pHddCtx->ext_scan_start_since_boot);
3353
3354 /* request was sent -- wait for the response */
3355 rc = wait_for_completion_timeout(&context->response_event,
3356 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3357
3358 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003359 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360 retval = -ETIMEDOUT;
3361 } else {
3362 spin_lock(&context->context_lock);
3363 if (context->request_id == request_id)
3364 retval = context->response_status;
3365 else
3366 retval = -EINVAL;
3367 spin_unlock(&context->context_lock);
3368 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303369 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003370 return retval;
3371
3372fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303373 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374 return -EINVAL;
3375}
3376/*
3377 * done with short names for the global vendor params
3378 * used by __wlan_hdd_cfg80211_extscan_start()
3379 */
3380#undef PARAM_MAX
3381#undef PARAM_REQUEST_ID
3382#undef PARAM_BASE_PERIOD
3383#undef PARAMS_MAX_AP_PER_SCAN
3384#undef PARAMS_RPT_THRHLD_PERCENT
3385#undef PARAMS_RPT_THRHLD_NUM_SCANS
3386#undef PARAMS_NUM_BUCKETS
3387#undef PARAM_CONFIG_FLAGS
3388
3389/**
3390 * wlan_hdd_cfg80211_extscan_start() - start extscan
3391 * @wiphy: Pointer to wireless phy.
3392 * @wdev: Pointer to wireless device.
3393 * @data: Pointer to input data.
3394 * @data_len: Length of @data.
3395 *
3396 * Return: 0 on success, negative errno on failure
3397 */
3398int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3399 struct wireless_dev *wdev,
3400 const void *data, int data_len)
3401{
3402 int ret = 0;
3403
3404 cds_ssr_protect(__func__);
3405 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3406 cds_ssr_unprotect(__func__);
3407
3408 return ret;
3409}
3410
3411
3412/*
3413 * define short names for the global vendor params
3414 * used by __wlan_hdd_cfg80211_extscan_stop()
3415 */
3416#define PARAM_MAX \
3417 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3418#define PARAM_REQUEST_ID \
3419 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3420
3421/**
3422 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3423 * @wiphy: Pointer to wireless phy
3424 * @wdev: Pointer to wireless device
3425 * @data: Pointer to data
3426 * @data_len: Data length
3427 *
3428 * Return: none
3429 */
3430static int
3431__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3432 struct wireless_dev *wdev,
3433 const void *data, int data_len)
3434{
3435 tpSirExtScanStopReqParams pReqMsg = NULL;
3436 struct net_device *dev = wdev->netdev;
3437 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3438 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3439 struct nlattr *tb[PARAM_MAX + 1];
3440 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303441 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003442 uint32_t request_id;
3443 int retval;
3444 unsigned long rc;
3445
Jeff Johnson1f61b612016-02-12 16:28:33 -08003446 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447
Anurag Chouhan6d760662016-02-20 16:05:43 +05303448 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003449 hdd_err("Command not allowed in FTM mode");
3450 return -EPERM;
3451 }
3452
3453 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303454 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003455 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303457 if (!pHddCtx->config->extscan_enabled) {
3458 hdd_err("extscan not supported");
3459 return -ENOTSUPP;
3460 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003461 if (nla_parse(tb, PARAM_MAX, data, data_len,
3462 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003463 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003464 return -EINVAL;
3465 }
3466
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303467 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003469 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003470 return -ENOMEM;
3471 }
3472
3473 /* Parse and fetch request Id */
3474 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003475 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003476 goto fail;
3477 }
3478
3479 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3480 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003481 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482 pReqMsg->requestId, pReqMsg->sessionId);
3483
3484 context = &ext_scan_context;
3485 spin_lock(&context->context_lock);
3486 INIT_COMPLETION(context->response_event);
3487 context->request_id = request_id = pReqMsg->requestId;
3488 spin_unlock(&context->context_lock);
3489
3490 status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303491 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003492 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493 goto fail;
3494 }
3495
3496 /* request was sent -- wait for the response */
3497 rc = wait_for_completion_timeout(&context->response_event,
3498 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3499
3500 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003501 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003502 retval = -ETIMEDOUT;
3503 } else {
3504 spin_lock(&context->context_lock);
3505 if (context->request_id == request_id)
3506 retval = context->response_status;
3507 else
3508 retval = -EINVAL;
3509 spin_unlock(&context->context_lock);
3510 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303511 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 return retval;
3513
3514fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303515 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 return -EINVAL;
3517}
3518/*
3519 * done with short names for the global vendor params
3520 * used by wlan_hdd_cfg80211_extscan_stop()
3521 */
3522#undef PARAM_MAX
3523#undef PARAM_REQUEST_ID
3524
3525
3526/**
3527 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3528 * @wiphy: Pointer to wireless phy.
3529 * @wdev: Pointer to wireless device.
3530 * @data: Pointer to input data.
3531 * @data_len: Length of @data.
3532 *
3533 * Return: 0 on success, negative errno on failure
3534 */
3535int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3536 struct wireless_dev *wdev,
3537 const void *data, int data_len)
3538{
3539 int ret = 0;
3540
3541 cds_ssr_protect(__func__);
3542 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3543 cds_ssr_unprotect(__func__);
3544
3545 return ret;
3546}
3547
3548
3549/**
3550 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3551 * @wiphy: Pointer to wireless phy
3552 * @wdev: Pointer to wireless device
3553 * @data: Pointer to data
3554 * @data_len: Data length
3555 *
3556 * Return: none
3557 */
3558static int
3559__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3560 struct wireless_dev
3561 *wdev, const void *data,
3562 int data_len)
3563{
3564 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3565 struct net_device *dev = wdev->netdev;
3566 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3567 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3568 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3569 1];
3570 struct hdd_ext_scan_context *context;
3571 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303572 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003573 int retval;
3574 unsigned long rc;
3575
Jeff Johnson1f61b612016-02-12 16:28:33 -08003576 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003577
Anurag Chouhan6d760662016-02-20 16:05:43 +05303578 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003579 hdd_err("Command not allowed in FTM mode");
3580 return -EPERM;
3581 }
3582
3583 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303584 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003586
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303587 if (!pHddCtx->config->extscan_enabled) {
3588 hdd_err("extscan not supported");
3589 return -ENOTSUPP;
3590 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003591 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3592 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003593 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594 return -EINVAL;
3595 }
3596
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303597 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003599 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003600 return -ENOMEM;
3601 }
3602
3603 /* Parse and fetch request Id */
3604 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003605 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003606 goto fail;
3607 }
3608
3609 pReqMsg->requestId =
3610 nla_get_u32(tb
3611 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3612 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003613 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003614 pReqMsg->requestId, pReqMsg->sessionId);
3615
3616 context = &ext_scan_context;
3617 spin_lock(&context->context_lock);
3618 INIT_COMPLETION(context->response_event);
3619 context->request_id = request_id = pReqMsg->requestId;
3620 spin_unlock(&context->context_lock);
3621
3622 status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303623 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003624 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003625 goto fail;
3626 }
3627
3628 /* request was sent -- wait for the response */
3629 rc = wait_for_completion_timeout
3630 (&context->response_event,
3631 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3632 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003633 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634 retval = -ETIMEDOUT;
3635 } else {
3636 spin_lock(&context->context_lock);
3637 if (context->request_id == request_id)
3638 retval = context->response_status;
3639 else
3640 retval = -EINVAL;
3641 spin_unlock(&context->context_lock);
3642 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303643 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 return retval;
3645
3646fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303647 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003648 return -EINVAL;
3649}
3650
3651/**
3652 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3653 * @wiphy: Pointer to wireless phy
3654 * @wdev: Pointer to wireless device
3655 * @data: Pointer to data
3656 * @data_len: Data length
3657 *
3658 * Return: 0 on success, negative errno on failure
3659 */
3660int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3661 struct wireless_dev *wdev,
3662 const void *data, int data_len)
3663{
3664 int ret = 0;
3665
3666 cds_ssr_protect(__func__);
3667 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3668 data, data_len);
3669 cds_ssr_unprotect(__func__);
3670
3671 return ret;
3672}
3673
3674/**
3675 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3676 * reset significant change
3677 * @wiphy: Pointer to wireless phy
3678 * @wdev: Pointer to wireless device
3679 * @data: Pointer to data
3680 * @data_len: Data length
3681 *
3682 * Return: none
3683 */
3684static int
3685__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3686 *wiphy,
3687 struct
3688 wireless_dev
3689 *wdev, const void *data,
3690 int data_len)
3691{
3692 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3693 struct net_device *dev = wdev->netdev;
3694 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3695 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3696 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3697 1];
3698 struct hdd_ext_scan_context *context;
3699 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303700 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 int retval;
3702 unsigned long rc;
3703
Jeff Johnson1f61b612016-02-12 16:28:33 -08003704 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003705
Anurag Chouhan6d760662016-02-20 16:05:43 +05303706 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003707 hdd_err("Command not allowed in FTM mode");
3708 return -EPERM;
3709 }
3710
3711 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303712 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003714
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303715 if (!pHddCtx->config->extscan_enabled) {
3716 hdd_err("extscan not supported");
3717 return -ENOTSUPP;
3718 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003719 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3720 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003721 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003722 return -EINVAL;
3723 }
3724
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303725 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003727 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003728 return -ENOMEM;
3729 }
3730
3731 /* Parse and fetch request Id */
3732 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003733 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003734 goto fail;
3735 }
3736
3737 pReqMsg->requestId =
3738 nla_get_u32(tb
3739 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3740 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003741 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742 pReqMsg->requestId, pReqMsg->sessionId);
3743
3744 context = &ext_scan_context;
3745 spin_lock(&context->context_lock);
3746 INIT_COMPLETION(context->response_event);
3747 context->request_id = request_id = pReqMsg->requestId;
3748 spin_unlock(&context->context_lock);
3749
3750 status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303751 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003752 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003753 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303754 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003755 return -EINVAL;
3756 }
3757
3758 /* request was sent -- wait for the response */
3759 rc = wait_for_completion_timeout(&context->response_event,
3760 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3761
3762 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003763 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003764 retval = -ETIMEDOUT;
3765 } else {
3766 spin_lock(&context->context_lock);
3767 if (context->request_id == request_id)
3768 retval = context->response_status;
3769 else
3770 retval = -EINVAL;
3771 spin_unlock(&context->context_lock);
3772 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303773 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003774 return retval;
3775
3776fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303777 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 return -EINVAL;
3779}
3780
3781/**
3782 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3783 * change
3784 * @wiphy: Pointer to wireless phy
3785 * @wdev: Pointer to wireless device
3786 * @data: Pointer to data
3787 * @data_len: Data length
3788 *
3789 * Return: 0 on success, negative errno on failure
3790 */
3791int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3792 struct wireless_dev *wdev,
3793 const void *data, int data_len)
3794{
3795 int ret = 0;
3796
3797 cds_ssr_protect(__func__);
3798 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3799 data, data_len);
3800 cds_ssr_unprotect(__func__);
3801
3802 return ret;
3803}
3804
3805
3806/**
3807 * hdd_extscan_epno_fill_network_list() - epno fill network list
3808 * @hddctx: HDD context
3809 * @req_msg: request message
3810 * @tb: vendor attribute table
3811 *
3812 * This function reads the network block NL vendor attributes from %tb and
3813 * fill in the epno request message.
3814 *
3815 * Return: 0 on success, error number otherwise
3816 */
3817static int hdd_extscan_epno_fill_network_list(
3818 hdd_context_t *hddctx,
3819 struct wifi_epno_params *req_msg,
3820 struct nlattr **tb)
3821{
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003822 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003823 struct nlattr *networks;
3824 int rem1, ssid_len;
3825 uint8_t index, *ssid;
Jeff Johnson14305e62016-11-11 17:37:54 -08003826 uint32_t expected_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003827
Jeff Johnson14305e62016-11-11 17:37:54 -08003828 expected_networks = req_msg->num_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003829 index = 0;
3830 nla_for_each_nested(networks,
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003831 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3832 rem1) {
Jeff Johnson14305e62016-11-11 17:37:54 -08003833
3834 if (index == expected_networks) {
3835 hdd_warn("ignoring excess networks");
3836 break;
3837 }
3838
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003839 if (nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3840 nla_data(networks), nla_len(networks),
3841 wlan_hdd_pno_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003842 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003843 return -EINVAL;
3844 }
3845
3846 /* Parse and fetch ssid */
3847 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003848 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849 return -EINVAL;
3850 }
3851 ssid_len = nla_len(
3852 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3853
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003854 /* nla_parse will detect overflow but not underflow */
3855 if (0 == ssid_len) {
3856 hdd_err("zero ssid length");
3857 return -EINVAL;
3858 }
3859
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003860 /* Decrement by 1, don't count null character */
3861 ssid_len--;
3862
3863 req_msg->networks[index].ssid.length = ssid_len;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003864 hdd_notice("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303866 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003867 ssid, ssid_len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003868 hdd_notice("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869 req_msg->networks[index].ssid.length,
3870 req_msg->networks[index].ssid.ssId);
3871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 /* Parse and fetch epno flags */
3873 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003874 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003875 return -EINVAL;
3876 }
3877 req_msg->networks[index].flags = nla_get_u8(
3878 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003879 hdd_notice("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880
3881 /* Parse and fetch auth bit */
3882 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003883 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003884 return -EINVAL;
3885 }
3886 req_msg->networks[index].auth_bit_field = nla_get_u8(
3887 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003888 hdd_notice("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889 req_msg->networks[index].auth_bit_field);
3890
3891 index++;
3892 }
Jeff Johnson14305e62016-11-11 17:37:54 -08003893 req_msg->num_networks = index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894 return 0;
3895}
3896
3897/**
3898 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3899 * @wiphy: wiphy
3900 * @wdev: pointer to wireless dev
3901 * @data: data pointer
3902 * @data_len: data length
3903 *
3904 * This function reads the NL vendor attributes from %tb and
3905 * fill in the epno request message.
3906 *
3907 * Return: 0 on success, error number otherwise
3908 */
3909static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3910 struct wireless_dev *wdev,
3911 const void *data,
3912 int data_len)
3913{
3914 struct wifi_epno_params *req_msg = NULL;
3915 struct net_device *dev = wdev->netdev;
3916 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3917 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3918 struct nlattr *tb[
3919 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303920 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003921 uint32_t num_networks, len;
3922 int ret_val;
3923
Jeff Johnson1f61b612016-02-12 16:28:33 -08003924 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003925
3926 ret_val = wlan_hdd_validate_context(hdd_ctx);
3927 if (ret_val)
3928 return ret_val;
3929
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303930 if (!hdd_ctx->config->extscan_enabled) {
3931 hdd_err("extscan not supported");
3932 return -ENOTSUPP;
3933 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303934 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003935 hdd_err("Command not allowed in FTM mode");
3936 return -EPERM;
3937 }
3938
3939 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003940 data, data_len,
3941 wlan_hdd_pno_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003942 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003943 return -EINVAL;
3944 }
3945
3946 /* Parse and fetch number of networks */
3947 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003948 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949 return -EINVAL;
3950 }
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303951
3952 /*
3953 * num_networks is also used as EPNO SET/RESET request.
3954 * if num_networks is zero then it is treated as RESET.
3955 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003956 num_networks = nla_get_u32(
3957 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003958
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303959 if (num_networks > MAX_EPNO_NETWORKS) {
3960 hdd_notice("num of nw: %d exceeded max: %d, resetting to: %d",
3961 num_networks, MAX_EPNO_NETWORKS, MAX_EPNO_NETWORKS);
3962 num_networks = MAX_EPNO_NETWORKS;
3963 }
3964
3965 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966 len = sizeof(*req_msg) +
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303967 (num_networks * sizeof(struct wifi_epno_network));
3968
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303969 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003970 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003971 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003972 return -ENOMEM;
3973 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003974 req_msg->num_networks = num_networks;
3975
3976 /* Parse and fetch request Id */
3977 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003978 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 goto fail;
3980 }
3981 req_msg->request_id = nla_get_u32(
3982 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003983 hdd_notice("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003984
3985 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003986 hdd_notice("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003987
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303988 if (num_networks) {
3989
3990 /* Parse and fetch min_5ghz_rssi */
3991 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]) {
3992 hdd_err("min_5ghz_rssi id failed");
3993 goto fail;
3994 }
3995 req_msg->min_5ghz_rssi = nla_get_u32(
3996 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]);
3997
3998 /* Parse and fetch min_24ghz_rssi */
3999 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]) {
4000 hdd_err("min_24ghz_rssi id failed");
4001 goto fail;
4002 }
4003 req_msg->min_24ghz_rssi = nla_get_u32(
4004 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]);
4005
4006 /* Parse and fetch initial_score_max */
4007 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]) {
4008 hdd_err("initial_score_max id failed");
4009 goto fail;
4010 }
4011 req_msg->initial_score_max = nla_get_u32(
4012 tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]);
4013
4014 /* Parse and fetch current_connection_bonus */
4015 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]) {
4016 hdd_err("current_connection_bonus id failed");
4017 goto fail;
4018 }
4019 req_msg->current_connection_bonus = nla_get_u32(
4020 tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]
4021 );
4022
4023 /* Parse and fetch same_network_bonus */
4024 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]) {
4025 hdd_err("same_network_bonus id failed");
4026 goto fail;
4027 }
4028 req_msg->same_network_bonus = nla_get_u32(
4029 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]);
4030
4031 /* Parse and fetch secure_bonus */
4032 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]) {
4033 hdd_err("secure_bonus id failed");
4034 goto fail;
4035 }
4036 req_msg->secure_bonus = nla_get_u32(
4037 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]);
4038
4039 /* Parse and fetch band_5ghz_bonus */
4040 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]) {
4041 hdd_err("band_5ghz_bonus id failed");
4042 goto fail;
4043 }
4044 req_msg->band_5ghz_bonus = nla_get_u32(
4045 tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]);
4046
4047 hdd_notice("min_5ghz_rssi: %d min_24ghz_rssi: %d",
4048 req_msg->min_5ghz_rssi,
4049 req_msg->min_24ghz_rssi);
4050 hdd_notice("initial_score_max: %d current_connection_bonus:%d",
4051 req_msg->initial_score_max,
4052 req_msg->current_connection_bonus);
4053 hdd_notice("Bonuses same_network: %d secure: %d band_5ghz: %d",
4054 req_msg->same_network_bonus,
4055 req_msg->secure_bonus,
4056 req_msg->band_5ghz_bonus);
4057
4058 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
4059 goto fail;
4060
4061 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004062
4063 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304064 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004065 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 goto fail;
4067 }
4068
4069 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304070 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071 return 0;
4072
4073fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304074 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 return -EINVAL;
4076}
4077
4078 /**
4079 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
4080 * @wiphy: wiphy
4081 * @wdev: pointer to wireless dev
4082 * @data: data pointer
4083 * @data_len: data length
4084 *
4085 * This function reads the NL vendor attributes from %tb and
4086 * fill in the epno request message.
4087 *
4088 * Return: 0 on success, error number otherwise
4089 */
4090int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
4091 struct wireless_dev *wdev,
4092 const void *data,
4093 int data_len)
4094{
4095 int ret;
4096
4097 cds_ssr_protect(__func__);
4098 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
4099 data, data_len);
4100 cds_ssr_unprotect(__func__);
4101
4102 return ret;
4103}
4104
4105/**
4106 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
4107 * @hddctx: HDD context
4108 * @req_msg: request message
4109 * @tb: vendor attribute table
4110 *
4111 * This function reads the network block NL vendor attributes from %tb and
4112 * fill in the passpoint request message.
4113 *
4114 * Return: 0 on success, error number otherwise
4115 */
4116static int hdd_extscan_passpoint_fill_network_list(
4117 hdd_context_t *hddctx,
4118 struct wifi_passpoint_req *req_msg,
4119 struct nlattr **tb)
4120{
4121 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
4122 struct nlattr *networks;
4123 int rem1, len;
4124 uint8_t index;
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004125 uint32_t expected_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004126
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004127 expected_networks = req_msg->num_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128 index = 0;
4129 nla_for_each_nested(networks,
4130 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
4131 rem1) {
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004132
4133 if (index == expected_networks) {
4134 hdd_warn("ignoring excess networks");
4135 break;
4136 }
4137
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 if (nla_parse(network,
4139 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
4140 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004141 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142 return -EINVAL;
4143 }
4144
4145 /* Parse and fetch identifier */
4146 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004147 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004148 return -EINVAL;
4149 }
4150 req_msg->networks[index].id = nla_get_u32(
4151 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004152 hdd_notice("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153
4154 /* Parse and fetch realm */
4155 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004156 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 return -EINVAL;
4158 }
4159 len = nla_len(
4160 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
4161 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004162 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 return -EINVAL;
4164 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304165 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004166 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
4167 len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004168 hdd_notice("realm len %d", len);
4169 hdd_notice("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170
4171 /* Parse and fetch roaming consortium ids */
4172 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004173 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174 return -EINVAL;
4175 }
4176 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
4177 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
4178 sizeof(req_msg->networks[0].roaming_consortium_ids));
Jeff Johnson630f9e72016-07-25 12:00:12 -07004179 hdd_notice("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180
4181 /* Parse and fetch plmn */
4182 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004183 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004184 return -EINVAL;
4185 }
4186 nla_memcpy(&req_msg->networks[index].plmn,
4187 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
4188 SIR_PASSPOINT_PLMN_LEN);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004189 hdd_notice("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004190 req_msg->networks[index].plmn[0],
4191 req_msg->networks[index].plmn[1],
4192 req_msg->networks[index].plmn[2]);
4193
4194 index++;
4195 }
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004196 req_msg->num_networks = index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197 return 0;
4198}
4199
4200/**
4201 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4202 * @wiphy: wiphy
4203 * @wdev: pointer to wireless dev
4204 * @data: data pointer
4205 * @data_len: data length
4206 *
4207 * This function reads the NL vendor attributes from %tb and
4208 * fill in the passpoint request message.
4209 *
4210 * Return: 0 on success, error number otherwise
4211 */
4212static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4213 struct wireless_dev *wdev,
4214 const void *data,
4215 int data_len)
4216{
4217 struct wifi_passpoint_req *req_msg = NULL;
4218 struct net_device *dev = wdev->netdev;
4219 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4220 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4221 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304222 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004223 uint32_t num_networks = 0;
4224 int ret;
4225
Jeff Johnson1f61b612016-02-12 16:28:33 -08004226 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004227
4228 ret = wlan_hdd_validate_context(hdd_ctx);
4229 if (ret)
4230 return ret;
4231
Anurag Chouhan6d760662016-02-20 16:05:43 +05304232 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004233 hdd_err("Command not allowed in FTM mode");
4234 return -EPERM;
4235 }
4236
4237 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4238 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004239 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240 return -EINVAL;
4241 }
4242
4243 /* Parse and fetch number of networks */
4244 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004245 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004246 return -EINVAL;
4247 }
4248 num_networks = nla_get_u32(
4249 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson96f93a32016-11-18 11:02:24 -08004250 if (num_networks > SIR_PASSPOINT_LIST_MAX_NETWORKS) {
4251 hdd_err("num networks %u exceeds max %u",
4252 num_networks, SIR_PASSPOINT_LIST_MAX_NETWORKS);
4253 return -EINVAL;
4254 }
4255
Jeff Johnson630f9e72016-07-25 12:00:12 -07004256 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004257
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304258 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259 (num_networks * sizeof(req_msg->networks[0])));
4260 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004261 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262 return -ENOMEM;
4263 }
4264 req_msg->num_networks = num_networks;
4265
4266 /* Parse and fetch request Id */
4267 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004268 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 goto fail;
4270 }
4271 req_msg->request_id = nla_get_u32(
4272 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4273
4274 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004275 hdd_notice("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 req_msg->session_id);
4277
4278 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4279 goto fail;
4280
4281 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304282 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004283 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 goto fail;
4285 }
4286
4287 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304288 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289 return 0;
4290
4291fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304292 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004293 return -EINVAL;
4294}
4295
4296/**
4297 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4298 * @wiphy: wiphy
4299 * @wdev: pointer to wireless dev
4300 * @data: data pointer
4301 * @data_len: data length
4302 *
4303 * This function reads the NL vendor attributes from %tb and
4304 * fill in the passpoint request message.
4305 *
4306 * Return: 0 on success, error number otherwise
4307 */
4308int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4309 struct wireless_dev *wdev,
4310 const void *data,
4311 int data_len)
4312{
4313 int ret;
4314
4315 cds_ssr_protect(__func__);
4316 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4317 data, data_len);
4318 cds_ssr_unprotect(__func__);
4319
4320 return ret;
4321}
4322
4323/**
4324 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4325 * @wiphy: wiphy
4326 * @wdev: pointer to wireless dev
4327 * @data: data pointer
4328 * @data_len: data length
4329 *
4330 * This function resets passpoint networks list
4331 *
4332 * Return: 0 on success, error number otherwise
4333 */
4334static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4335 struct wireless_dev *wdev,
4336 const void *data,
4337 int data_len)
4338{
4339 struct wifi_passpoint_req *req_msg = NULL;
4340 struct net_device *dev = wdev->netdev;
4341 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4342 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4343 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304344 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 int ret;
4346
Jeff Johnson1f61b612016-02-12 16:28:33 -08004347 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348
4349 ret = wlan_hdd_validate_context(hdd_ctx);
4350 if (ret)
4351 return ret;
4352
Anurag Chouhan6d760662016-02-20 16:05:43 +05304353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 hdd_err("Command not allowed in FTM mode");
4355 return -EPERM;
4356 }
4357
4358 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4359 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004360 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 return -EINVAL;
4362 }
4363
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304364 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004366 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 return -ENOMEM;
4368 }
4369
4370 /* Parse and fetch request Id */
4371 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004372 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 goto fail;
4374 }
4375 req_msg->request_id = nla_get_u32(
4376 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4377
4378 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004379 hdd_notice("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004380 req_msg->request_id, req_msg->session_id);
4381
4382 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304383 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004384 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004385 goto fail;
4386 }
4387
4388 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304389 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390 return 0;
4391
4392fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304393 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 return -EINVAL;
4395}
4396
4397/**
4398 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4399 * @wiphy: wiphy
4400 * @wdev: pointer to wireless dev
4401 * @data: data pointer
4402 * @data_len: data length
4403 *
4404 * This function resets passpoint networks list
4405 *
4406 * Return: 0 on success, error number otherwise
4407 */
4408int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4409 struct wireless_dev *wdev,
4410 const void *data,
4411 int data_len)
4412{
4413 int ret;
4414
4415 cds_ssr_protect(__func__);
4416 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4417 data, data_len);
4418 cds_ssr_unprotect(__func__);
4419
4420 return ret;
4421}
4422
4423/*
4424 * define short names for the global vendor params
4425 * used by __wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4426 */
4427#define PARAM_MAX \
4428 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4429#define PARAM_REQUEST_ID \
4430 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4431#define PARAMS_LOST_SSID_SAMPLE_SIZE \
4432 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE
4433#define PARAMS_NUM_SSID \
4434 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID
4435#define THRESHOLD_PARAM \
4436 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM
4437#define PARAM_SSID \
4438 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID
4439#define PARAM_BAND \
4440 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND
4441#define PARAM_RSSI_LOW \
4442 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW
4443#define PARAM_RSSI_HIGH \
4444 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH
4445
4446/**
4447 * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4448 * @wiphy: Pointer to wireless phy
4449 * @wdev: Pointer to wireless device
4450 * @data: Pointer to data
4451 * @data_len: Data length
4452 *
4453 * Return: 0 on success, negative errno on failure
4454 */
4455static int
4456__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4457 struct wireless_dev *wdev,
4458 const void *data,
4459 int data_len)
4460{
4461 struct sir_set_ssid_hotlist_request *request;
4462 struct net_device *dev = wdev->netdev;
4463 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4464 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4465 struct nlattr *tb[PARAM_MAX + 1];
4466 struct nlattr *tb2[PARAM_MAX + 1];
4467 struct nlattr *ssids;
4468 struct hdd_ext_scan_context *context;
4469 uint32_t request_id;
4470 char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1];
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304471 int ssid_len, i, rem, ssid_str_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304472 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004473 int retval;
4474 unsigned long rc;
4475
Jeff Johnson1f61b612016-02-12 16:28:33 -08004476 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004477
Anurag Chouhan6d760662016-02-20 16:05:43 +05304478 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 hdd_err("Command not allowed in FTM mode");
4480 return -EPERM;
4481 }
4482
4483 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304484 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004486
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304487 if (!hdd_ctx->config->extscan_enabled) {
4488 hdd_err("extscan not supported");
4489 return -ENOTSUPP;
4490 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491 if (nla_parse(tb, PARAM_MAX,
4492 data, data_len,
4493 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004494 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495 return -EINVAL;
4496 }
4497
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304498 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004500 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004501 return -ENOMEM;
4502 }
4503
4504 /* Parse and fetch request Id */
4505 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004506 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 goto fail;
4508 }
4509
4510 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004511 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004512
4513 /* Parse and fetch lost SSID sample size */
4514 if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004515 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004516 goto fail;
4517 }
4518 request->lost_ssid_sample_size =
4519 nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004520 hdd_notice("Lost SSID Sample Size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 request->lost_ssid_sample_size);
4522
4523 /* Parse and fetch number of hotlist SSID */
4524 if (!tb[PARAMS_NUM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004525 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526 goto fail;
4527 }
4528 request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004529 hdd_notice("Number of SSID %d", request->ssid_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530
4531 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004532 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004533
4534 i = 0;
4535 nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) {
4536 if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004537 hdd_err("Too Many SSIDs, %d exceeds %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538 i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS);
4539 break;
4540 }
4541 if (nla_parse(tb2, PARAM_MAX,
4542 nla_data(ssids), nla_len(ssids),
4543 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004544 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004545 goto fail;
4546 }
4547
4548 /* Parse and fetch SSID */
4549 if (!tb2[PARAM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004550 hdd_err("attr ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 goto fail;
4552 }
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304553 ssid_str_len = nla_strlcpy(ssid_string,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 tb2[PARAM_SSID],
4555 sizeof(ssid_string));
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304556 if (ssid_str_len > SIR_MAC_MAX_SSID_LENGTH) {
4557 hdd_err("Invalid length exceeds max ssid length");
4558 goto fail;
4559 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07004560 hdd_notice("SSID %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004561 ssid_string);
4562 ssid_len = strlen(ssid_string);
4563 memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len);
4564 request->ssids[i].ssid.length = ssid_len;
4565
4566 /* Parse and fetch low RSSI */
4567 if (!tb2[PARAM_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004568 hdd_err("attr band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004569 goto fail;
4570 }
4571 request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004572 hdd_notice("band %d", request->ssids[i].band);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004573
4574 /* Parse and fetch low RSSI */
4575 if (!tb2[PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004576 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004577 goto fail;
4578 }
4579 request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004580 hdd_notice("RSSI low %d", request->ssids[i].rssi_low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004581
4582 /* Parse and fetch high RSSI */
4583 if (!tb2[PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004584 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004585 goto fail;
4586 }
4587 request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004588 hdd_notice("RSSI high %d", request->ssids[i].rssi_high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 i++;
4590 }
4591
4592 context = &ext_scan_context;
4593 spin_lock(&context->context_lock);
4594 INIT_COMPLETION(context->response_event);
4595 context->request_id = request_id = request->request_id;
4596 spin_unlock(&context->context_lock);
4597
4598 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304599 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004600 hdd_err("sme_set_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004601 goto fail;
4602 }
4603
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304604 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004605
4606 /* request was sent -- wait for the response */
4607 rc = wait_for_completion_timeout(&context->response_event,
4608 msecs_to_jiffies
4609 (WLAN_WAIT_TIME_EXTSCAN));
4610 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004611 hdd_err("sme_set_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 retval = -ETIMEDOUT;
4613 } else {
4614 spin_lock(&context->context_lock);
4615 if (context->request_id == request_id)
4616 retval = context->response_status;
4617 else
4618 retval = -EINVAL;
4619 spin_unlock(&context->context_lock);
4620 }
4621
4622 return retval;
4623
4624fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304625 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626 return -EINVAL;
4627}
4628
4629/*
4630 * done with short names for the global vendor params
4631 * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4632 */
4633#undef PARAM_MAX
4634#undef PARAM_REQUEST_ID
4635#undef PARAMS_NUM_SSID
4636#undef THRESHOLD_PARAM
4637#undef PARAM_SSID
4638#undef PARAM_BAND
4639#undef PARAM_RSSI_LOW
4640#undef PARAM_RSSI_HIGH
4641
4642/**
4643 * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4644 * @wiphy: Pointer to wireless phy
4645 * @wdev: Pointer to wireless device
4646 * @data: Pointer to data
4647 * @data_len: Data length
4648 *
4649 * Return: 0 on success, negative errno on failure
4650 */
4651int
4652wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4653 struct wireless_dev *wdev,
4654 const void *data,
4655 int data_len)
4656{
4657 int ret;
4658
4659 cds_ssr_protect(__func__);
4660 ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data,
4661 data_len);
4662 cds_ssr_unprotect(__func__);
4663
4664 return ret;
4665}
4666
4667/*
4668 * define short names for the global vendor params
4669 * used by __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4670 */
4671#define PARAM_MAX \
4672 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4673#define PARAM_REQUEST_ID \
4674 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4675
4676/**
4677 * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4678 * @wiphy: Pointer to wireless phy
4679 * @wdev: Pointer to wireless device
4680 * @data: Pointer to data
4681 * @data_len: Data length
4682 *
4683 * Return: 0 on success, negative errno on failure
4684 */
4685static int
4686__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4687 struct wireless_dev *wdev,
4688 const void *data,
4689 int data_len)
4690{
4691 struct sir_set_ssid_hotlist_request *request;
4692 struct net_device *dev = wdev->netdev;
4693 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4694 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4695 struct nlattr *tb[PARAM_MAX + 1];
4696 struct hdd_ext_scan_context *context;
4697 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304698 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 int retval;
4700 unsigned long rc;
4701
Jeff Johnson1f61b612016-02-12 16:28:33 -08004702 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703
Anurag Chouhan6d760662016-02-20 16:05:43 +05304704 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004705 hdd_err("Command not allowed in FTM mode");
4706 return -EPERM;
4707 }
4708
4709 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304710 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004712
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304713 if (!hdd_ctx->config->extscan_enabled) {
4714 hdd_err("extscan not supported");
4715 return -ENOTSUPP;
4716 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004717 if (nla_parse(tb, PARAM_MAX,
4718 data, data_len,
4719 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004720 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 return -EINVAL;
4722 }
4723
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304724 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004725 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004726 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 return -ENOMEM;
4728 }
4729
4730 /* Parse and fetch request Id */
4731 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004732 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004733 goto fail;
4734 }
4735
4736 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004737 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004738
4739 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004740 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004741
4742 request->lost_ssid_sample_size = 0;
4743 request->ssid_count = 0;
4744
4745 context = &ext_scan_context;
4746 spin_lock(&context->context_lock);
4747 INIT_COMPLETION(context->response_event);
4748 context->request_id = request_id = request->request_id;
4749 spin_unlock(&context->context_lock);
4750
4751 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304752 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004753 hdd_err("sme_reset_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004754 goto fail;
4755 }
4756
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304757 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004758
4759 /* request was sent -- wait for the response */
4760 rc = wait_for_completion_timeout(&context->response_event,
4761 msecs_to_jiffies
4762 (WLAN_WAIT_TIME_EXTSCAN));
4763 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004764 hdd_err("sme_reset_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004765 retval = -ETIMEDOUT;
4766 } else {
4767 spin_lock(&context->context_lock);
4768 if (context->request_id == request_id)
4769 retval = context->response_status;
4770 else
4771 retval = -EINVAL;
4772 spin_unlock(&context->context_lock);
4773 }
4774
4775 return retval;
4776
4777fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304778 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779 return -EINVAL;
4780}
4781
4782/*
4783 * done with short names for the global vendor params
4784 * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4785 */
4786#undef PARAM_MAX
4787#undef PARAM_REQUEST_ID
4788
4789/**
4790 * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4791 * @wiphy: Pointer to wireless phy
4792 * @wdev: Pointer to wireless device
4793 * @data: Pointer to data
4794 * @data_len: Data length
4795 *
4796 * Return: 0 on success, negative errno on failure
4797 */
4798int
4799wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4800 struct wireless_dev *wdev,
4801 const void *data,
4802 int data_len)
4803{
4804 int ret;
4805
4806 cds_ssr_protect(__func__);
4807 ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev,
4808 data, data_len);
4809 cds_ssr_unprotect(__func__);
4810
4811 return ret;
4812}
4813
4814/**
4815 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4816 * @hdd_ctx: Global HDD context
4817 *
4818 * Return: none
4819 */
4820#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4821static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4822{
4823 init_completion(&pHddCtx->ready_to_extwow);
4824}
4825#else
4826static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4827{
4828 return;
4829}
4830#endif
4831
4832/**
4833 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4834 * @hdd_ctx: Global HDD context
4835 *
4836 * Return: none
4837 */
4838void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx)
4839{
4840 wlan_hdd_init_completion_extwow(hdd_ctx);
4841 init_completion(&ext_scan_context.response_event);
4842 spin_lock_init(&ext_scan_context.context_lock);
4843}
4844
4845#endif /* FEATURE_WLAN_EXTSCAN */