blob: e68da6776bc45789345edf5844a914c7cf002424 [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},
115 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
116 .type = NLA_U32 },
117 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
118 .type = NLA_BINARY,
119 .len = IEEE80211_MAX_SSID_LEN },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
121 .type = NLA_U8 },
122 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
123 .type = NLA_U8 },
124 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = {
125 .type = NLA_BINARY,
126 .len = IEEE80211_MAX_SSID_LEN + 1 },
127 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = {
128 .type = NLA_U32 },
129 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID] = {
130 .type = NLA_U32 },
131 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND] = {
132 .type = NLA_U8 },
133 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = {
134 .type = NLA_S32 },
135 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = {
136 .type = NLA_S32 },
137 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = {
138 .type = NLA_U32 },
139};
140
141static const struct nla_policy
142wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
143 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
144 .type = NLA_U16},
145 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = {
146 .type = NLA_U16},
147};
148
149/**
150 * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
151 * @ctx: Pointer to hdd context
152 * @data: Pointer to ext scan capabilities response from fw
153 *
154 * Return: None
155 */
156static void
157wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx,
158 struct ext_scan_capabilities_response *data)
159{
160 struct hdd_ext_scan_context *context;
161 hdd_context_t *hdd_ctx = ctx;
162
163 ENTER();
164
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530165 if (wlan_hdd_validate_context(hdd_ctx))
166 return;
167 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700168 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800169 return;
170 }
171
172 context = &ext_scan_context;
173
174 spin_lock(&context->context_lock);
175 /* validate response received from target*/
176 if (context->request_id != data->requestId) {
177 spin_unlock(&context->context_lock);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700178 hdd_err("Target response id did not match: request_id %d response_id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800179 context->request_id, data->requestId);
180 return;
181 } else {
182 context->capability_response = *data;
183 complete(&context->response_event);
184 }
185
186 spin_unlock(&context->context_lock);
187
188 return;
189}
190
191/*
192 * define short names for the global vendor params
193 * used by hdd_extscan_nl_fill_bss()
194 */
195#define PARAM_TIME_STAMP \
196 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
197#define PARAM_SSID \
198 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID
199#define PARAM_BSSID \
200 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID
201#define PARAM_CHANNEL \
202 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL
203#define PARAM_RSSI \
204 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI
205#define PARAM_RTT \
206 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT
207#define PARAM_RTT_SD \
208 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD
209#define PARAM_BEACON_PERIOD \
210 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD
211#define PARAM_CAPABILITY \
212 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY
213#define PARAM_IE_LENGTH \
214 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
215#define PARAM_IE_DATA \
216 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA
217
218/** hdd_extscan_nl_fill_bss() - extscan nl fill bss
219 * @skb: socket buffer
220 * @ap: bss information
221 * @idx: nesting index
222 *
223 * Return: 0 on success; error number otherwise
224 */
225static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap,
226 int idx)
227{
228 struct nlattr *nla_ap;
229
230 nla_ap = nla_nest_start(skb, idx);
231 if (!nla_ap)
232 return -EINVAL;
233
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700234 if (hdd_wlan_nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235 nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) ||
236 nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid.bytes) ||
237 nla_put_u32(skb, PARAM_CHANNEL, ap->channel) ||
238 nla_put_s32(skb, PARAM_RSSI, ap->rssi) ||
239 nla_put_u32(skb, PARAM_RTT, ap->rtt) ||
240 nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) ||
241 nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) ||
242 nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) ||
243 nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700244 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800245 return -EINVAL;
246 }
247
248 if (ap->ieLength)
249 if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700250 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800251 return -EINVAL;
252 }
253
254 nla_nest_end(skb, nla_ap);
255
256 return 0;
257}
258/*
259 * done with short names for the global vendor params
260 * used by hdd_extscan_nl_fill_bss()
261 */
262#undef PARAM_TIME_STAMP
263#undef PARAM_SSID
264#undef PARAM_BSSID
265#undef PARAM_CHANNEL
266#undef PARAM_RSSI
267#undef PARAM_RTT
268#undef PARAM_RTT_SD
269#undef PARAM_BEACON_PERIOD
270#undef PARAM_CAPABILITY
271#undef PARAM_IE_LENGTH
272#undef PARAM_IE_DATA
273
274/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results
275 * @ctx: hdd global context
276 * @data: cached results
277 *
278 * This function reads the cached results %data, populated the NL
279 * attributes and sends the NL event to the upper layer.
280 *
281 * Return: none
282 */
283static void
284wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
285 struct extscan_cached_scan_results *data)
286{
287 hdd_context_t *pHddCtx = ctx;
288 struct sk_buff *skb = NULL;
289 struct hdd_ext_scan_context *context;
290 struct extscan_cached_scan_result *result;
291 tSirWifiScanResult *ap;
292 uint32_t i, j, nl_buf_len;
293 bool ignore_cached_results = false;
294
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700295 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530297 if (wlan_hdd_validate_context(pHddCtx))
298 return;
299 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700300 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800301 return;
302 }
303
304 context = &ext_scan_context;
305 spin_lock(&context->context_lock);
306 ignore_cached_results = context->ignore_cached_results;
307 spin_unlock(&context->context_lock);
308
309 if (ignore_cached_results) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700310 hdd_err("Ignore the cached results received after timeout");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800311 return;
312 }
313
314#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN
315#define EXTSCAN_CACHED_NL_FIXED_TLV \
316 ((sizeof(data->request_id) + NLA_HDRLEN) + \
317 (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \
318 (sizeof(data->more_data) + NLA_HDRLEN))
319#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \
320 ((sizeof(result->scan_id) + NLA_HDRLEN) + \
321 (sizeof(result->flags) + NLA_HDRLEN) + \
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530322 (sizeof(result->num_results) + NLA_HDRLEN))+ \
323 (sizeof(result->buckets_scanned) + NLA_HDRLEN)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
325 ((sizeof(ap->ts) + NLA_HDRLEN) + \
326 (sizeof(ap->ssid) + NLA_HDRLEN) + \
327 (sizeof(ap->bssid) + NLA_HDRLEN) + \
328 (sizeof(ap->channel) + NLA_HDRLEN) + \
329 (sizeof(ap->rssi) + NLA_HDRLEN) + \
330 (sizeof(ap->rtt) + NLA_HDRLEN) + \
331 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
332 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
333 (sizeof(ap->capability) + NLA_HDRLEN) + \
334 (sizeof(ap->ieLength) + NLA_HDRLEN))
335#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
336 (ap->ieLength + NLA_HDRLEN)
337
338 nl_buf_len = NLMSG_HDRLEN;
339 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
340 if (data->num_scan_ids) {
341 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
342 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
343 result = &data->result[0];
344 for (i = 0; i < data->num_scan_ids; i++) {
345 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
346 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
347 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
348
349 ap = &result->ap[0];
350 for (j = 0; j < result->num_results; j++) {
351 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
352 nl_buf_len +=
353 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
354 if (ap->ieLength)
355 nl_buf_len +=
356 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
357 ap++;
358 }
359 result++;
360 }
361 }
362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len);
364
365 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700366 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800367 goto fail;
368 }
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530369 hdd_notice("Req Id %u Num_scan_ids %u More Data %u",
370 data->request_id, data->num_scan_ids, data->more_data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371
372 result = &data->result[0];
373 for (i = 0; i < data->num_scan_ids; i++) {
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530374 hdd_notice("[i=%d] scan_id %u flags %u num_results %u buckets scanned %u",
375 i, result->scan_id, result->flags, result->num_results,
376 result->buckets_scanned);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377
378 ap = &result->ap[0];
379 for (j = 0; j < result->num_results; j++) {
380 /*
381 * Firmware returns timestamp from ext scan start till
382 * BSSID was cached (in micro seconds). Add this with
383 * time gap between system boot up to ext scan start
384 * to derive the time since boot when the
385 * BSSID was cached.
386 */
387 ap->ts += pHddCtx->ext_scan_start_since_boot;
Jeff Johnson630f9e72016-07-25 12:00:12 -0700388 hdd_notice("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800389 "Ssid: %s "
390 "Bssid (" MAC_ADDRESS_STR ") "
391 "Channel %u "
392 "Rssi %d "
393 "RTT %u "
394 "RTT_SD %u "
395 "Beacon Period %u "
396 "Capability 0x%x "
397 "Ie length %d",
398 ap->ts,
399 ap->ssid,
400 MAC_ADDR_ARRAY(ap->bssid.bytes),
401 ap->channel,
402 ap->rssi,
403 ap->rtt,
404 ap->rtt_sd,
405 ap->beaconPeriod,
406 ap->capability,
407 ap->ieLength);
408 ap++;
409 }
410 result++;
411 }
412
413 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
414 data->request_id) ||
415 nla_put_u32(skb,
416 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
417 data->num_scan_ids) ||
418 nla_put_u8(skb,
419 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
420 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700421 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422 goto fail;
423 }
424
425 if (data->num_scan_ids) {
426 struct nlattr *nla_results;
427 result = &data->result[0];
428
429 if (nla_put_u32(skb,
430 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
431 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700432 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 goto fail;
434 }
435 nla_results = nla_nest_start(skb,
436 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
437 if (!nla_results)
438 goto fail;
439
440 for (i = 0; i < data->num_scan_ids; i++) {
441 struct nlattr *nla_result;
442 struct nlattr *nla_aps;
443
444 nla_result = nla_nest_start(skb, i);
445 if (!nla_result)
446 goto fail;
447
448 if (nla_put_u32(skb,
449 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
450 result->scan_id) ||
451 nla_put_u32(skb,
452 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
453 result->flags) ||
454 nla_put_u32(skb,
Mukul Sharmafa937be2016-08-12 18:13:36 +0530455 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530456 result->buckets_scanned) ||
Mukul Sharmafa937be2016-08-12 18:13:36 +0530457 nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
459 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700460 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800461 goto fail;
462 }
463
464 nla_aps = nla_nest_start(skb,
465 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
466 if (!nla_aps)
467 goto fail;
468
469 ap = &result->ap[0];
470 for (j = 0; j < result->num_results; j++) {
471 if (hdd_extscan_nl_fill_bss(skb, ap, j))
472 goto fail;
473
474 ap++;
475 }
476 nla_nest_end(skb, nla_aps);
477 nla_nest_end(skb, nla_result);
478 result++;
479 }
480 nla_nest_end(skb, nla_results);
481 }
482
483 cfg80211_vendor_cmd_reply(skb);
484
485 if (!data->more_data) {
486 spin_lock(&context->context_lock);
487 context->response_status = 0;
488 complete(&context->response_event);
489 spin_unlock(&context->context_lock);
490 }
491 return;
492
493fail:
494 if (skb)
495 kfree_skb(skb);
496
497 spin_lock(&context->context_lock);
498 context->response_status = -EINVAL;
499 spin_unlock(&context->context_lock);
500
501 return;
502}
503
504/**
505 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
506 * @ctx: Pointer to hdd context
507 * @pData: Pointer to ext scan result event
508 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800509 * This callback execute in atomic context and must not invoke any
510 * blocking calls.
511 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512 * Return: none
513 */
514static void
515wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
516 struct extscan_hotlist_match *data)
517{
518 hdd_context_t *pHddCtx = ctx;
519 struct sk_buff *skb = NULL;
520 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800521 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800522
523 ENTER();
524
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530525 if (wlan_hdd_validate_context(pHddCtx))
526 return;
527 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700528 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 return;
530 }
531
532 if (data->ap_found)
533 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
534 else
535 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
536
537 skb = cfg80211_vendor_event_alloc(
538 pHddCtx->wiphy,
539 NULL,
540 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800541 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542
543 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700544 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545 return;
546 }
547 hdd_info("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
548 data->requestId, data->numOfAps, data->moreData,
549 data->ap_found);
550
551 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530552 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553
Jeff Johnson630f9e72016-07-25 12:00:12 -0700554 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800555 "Ssid: %s "
556 "Bssid (" MAC_ADDRESS_STR ") "
557 "Channel %u "
558 "Rssi %d "
559 "RTT %u "
560 "RTT_SD %u",
561 i,
562 data->ap[i].ts,
563 data->ap[i].ssid,
564 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
565 data->ap[i].channel,
566 data->ap[i].rssi,
567 data->ap[i].rtt, data->ap[i].rtt_sd);
568 }
569
570 if (nla_put_u32(skb,
571 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
572 data->requestId) ||
573 nla_put_u32(skb,
574 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
575 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700576 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577 goto fail;
578 }
579
580 if (data->numOfAps) {
581 struct nlattr *aps;
582
583 aps = nla_nest_start(skb,
584 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
585 if (!aps)
586 goto fail;
587
588 for (i = 0; i < data->numOfAps; i++) {
589 struct nlattr *ap;
590
591 ap = nla_nest_start(skb, i);
592 if (!ap)
593 goto fail;
594
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700595 if (hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
597 data->ap[i].ts) ||
598 nla_put(skb,
599 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
600 sizeof(data->ap[i].ssid),
601 data->ap[i].ssid) ||
602 nla_put(skb,
603 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
604 sizeof(data->ap[i].bssid),
605 data->ap[i].bssid.bytes) ||
606 nla_put_u32(skb,
607 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
608 data->ap[i].channel) ||
609 nla_put_s32(skb,
610 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
611 data->ap[i].rssi) ||
612 nla_put_u32(skb,
613 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
614 data->ap[i].rtt) ||
615 nla_put_u32(skb,
616 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
617 data->ap[i].rtt_sd))
618 goto fail;
619
620 nla_nest_end(skb, ap);
621 }
622 nla_nest_end(skb, aps);
623
624 if (nla_put_u8(skb,
625 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
626 data->moreData))
627 goto fail;
628 }
629
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800630 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530631 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632 return;
633
634fail:
635 kfree_skb(skb);
636 return;
637}
638
639/**
640 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
641 * significant wifi change results indication
642 * @ctx: Pointer to hdd context
643 * @pData: Pointer to signif wifi change event
644 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800645 * This callback execute in atomic context and must not invoke any
646 * blocking calls.
647 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 * Return: none
649 */
650static void
651wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
652 void *ctx,
653 tpSirWifiSignificantChangeEvent pData)
654{
655 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
656 struct sk_buff *skb = NULL;
657 tSirWifiSignificantChange *ap_info;
658 int32_t *rssi;
659 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800660 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661
662 ENTER();
663
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530664 if (wlan_hdd_validate_context(pHddCtx))
665 return;
666 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700667 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800668 return;
669 }
670
671 skb = cfg80211_vendor_event_alloc(
672 pHddCtx->wiphy,
673 NULL,
674 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
675 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800676 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800677
678 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700679 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 return;
681 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700682 hdd_notice("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683 pData->requestId, pData->numResults, pData->moreData);
684
685 ap_info = &pData->ap[0];
686 for (i = 0; i < pData->numResults; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700687 hdd_notice("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 "Bssid (" MAC_ADDRESS_STR ") "
689 "Channel %u "
690 "numOfRssi %d",
691 i,
692 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
693 ap_info->channel, ap_info->numOfRssi);
694 rssi = &(ap_info)->rssi[0];
695 for (j = 0; j < ap_info->numOfRssi; j++)
Jeff Johnson630f9e72016-07-25 12:00:12 -0700696 hdd_notice("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697
698 ap_info += ap_info->numOfRssi * sizeof(*rssi);
699 }
700
701 if (nla_put_u32(skb,
702 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
703 pData->requestId) ||
704 nla_put_u32(skb,
705 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
706 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700707 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 goto fail;
709 }
710
711 if (pData->numResults) {
712 struct nlattr *aps;
713
714 aps = nla_nest_start(skb,
715 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
716 if (!aps)
717 goto fail;
718
719 ap_info = &pData->ap[0];
720 for (i = 0; i < pData->numResults; i++) {
721 struct nlattr *ap;
722
723 ap = nla_nest_start(skb, i);
724 if (!ap)
725 goto fail;
726
727 if (nla_put(skb,
728 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530729 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730 nla_put_u32(skb,
731 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
732 ap_info->channel) ||
733 nla_put_u32(skb,
734 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
735 ap_info->numOfRssi) ||
736 nla_put(skb,
737 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
738 sizeof(s32) * ap_info->numOfRssi,
739 &(ap_info)->rssi[0]))
740 goto fail;
741
742 nla_nest_end(skb, ap);
743
744 ap_info += ap_info->numOfRssi * sizeof(*rssi);
745 }
746 nla_nest_end(skb, aps);
747
748 if (nla_put_u8(skb,
749 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
750 pData->moreData))
751 goto fail;
752 }
753
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800754 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 return;
756
757fail:
758 kfree_skb(skb);
759 return;
760
761}
762
763/**
764 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
765 * @ctx: Pointer to hdd context
766 * @pData: Pointer to full scan result event
767 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800768 * This callback execute in atomic context and must not invoke any
769 * blocking calls.
770 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800771 * Return: none
772 */
773static void
774wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
775 tpSirWifiFullScanResultEvent
776 pData)
777{
778 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
779 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800780 struct timespec ts;
Mukul Sharmafa937be2016-08-12 18:13:36 +0530781 struct hdd_ext_scan_context *context;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700782
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800783 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700785 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530787 if (wlan_hdd_validate_context(pHddCtx))
788 return;
789 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700790 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 return;
792 }
793
794 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700795 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796 return;
797 }
798 skb = cfg80211_vendor_event_alloc(
799 pHddCtx->wiphy,
800 NULL,
801 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
802 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800803 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804
805 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700806 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 return;
808 }
809
810 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812 /* Android does not want the time stamp from the frame.
813 Instead it wants a monotonic increasing value since boot */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700814 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700816
Jeff Johnson630f9e72016-07-25 12:00:12 -0700817 hdd_notice("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818 pData->moreData);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700819 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800820 "Bssid (" MAC_ADDRESS_STR ") "
821 "Channel %u "
822 "Rssi %d "
823 "RTT %u "
824 "RTT_SD %u "
825 "Bcn Period %d "
826 "Capability 0x%X "
827 "IE Length %d",
828 pData->ap.ts,
829 pData->ap.ssid,
830 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
831 pData->ap.channel,
832 pData->ap.rssi,
833 pData->ap.rtt,
834 pData->ap.rtt_sd,
835 pData->ap.beaconPeriod,
836 pData->ap.capability, pData->ap.ieLength);
837
838 if (nla_put_u32(skb,
839 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
840 pData->requestId) ||
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700841 hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
843 pData->ap.ts) ||
844 nla_put(skb,
845 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
846 sizeof(pData->ap.ssid),
847 pData->ap.ssid) ||
848 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
849 sizeof(pData->ap.bssid),
850 pData->ap.bssid.bytes) ||
851 nla_put_u32(skb,
852 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
853 pData->ap.channel) ||
854 nla_put_s32(skb,
855 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
856 pData->ap.rssi) ||
857 nla_put_u32(skb,
858 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
859 pData->ap.rtt) ||
860 nla_put_u32(skb,
861 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
862 pData->ap.rtt_sd) ||
863 nla_put_u16(skb,
864 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
865 pData->ap.beaconPeriod) ||
866 nla_put_u16(skb,
867 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
868 pData->ap.capability) ||
869 nla_put_u32(skb,
870 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
871 pData->ap.ieLength) ||
872 nla_put_u8(skb,
873 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
874 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700875 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800876 goto nla_put_failure;
877 }
878
879 if (pData->ap.ieLength) {
880 if (nla_put(skb,
881 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
882 pData->ap.ieLength, pData->ap.ieData))
883 goto nla_put_failure;
884 }
885
Mukul Sharmafa937be2016-08-12 18:13:36 +0530886 context = &ext_scan_context;
887 spin_lock(&context->context_lock);
888 if (nla_put_u32(skb,
889 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
890 context->buckets_scanned)) {
891 spin_unlock(&context->context_lock);
892 hdd_notice("Failed to include buckets_scanned");
893 goto nla_put_failure;
894 }
895 spin_unlock(&context->context_lock);
896
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800897 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898 return;
899
900nla_put_failure:
901 kfree_skb(skb);
902 return;
903}
904
905/**
906 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
907 * @ctx: Pointer to hdd context
908 * @pData: Pointer to scan results available indication param
909 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800910 * This callback execute in atomic context and must not invoke any
911 * blocking calls.
912 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800913 * Return: none
914 */
915static void
916wlan_hdd_cfg80211_extscan_scan_res_available_event(
917 void *ctx,
918 tpSirExtScanResultsAvailableIndParams pData)
919{
920 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
921 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800922 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923
924 ENTER();
925
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530926 if (wlan_hdd_validate_context(pHddCtx))
927 return;
928 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700929 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800930 return;
931 }
932
933 skb = cfg80211_vendor_event_alloc(
934 pHddCtx->wiphy,
935 NULL,
936 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
937 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800938 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939
940 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700941 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 return;
943 }
944
Jeff Johnson630f9e72016-07-25 12:00:12 -0700945 hdd_notice("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800946 pData->requestId, pData->numResultsAvailable);
947 if (nla_put_u32(skb,
948 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
949 pData->requestId) ||
950 nla_put_u32(skb,
951 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
952 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700953 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954 goto nla_put_failure;
955 }
956
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800957 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530958 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959 return;
960
961nla_put_failure:
962 kfree_skb(skb);
963 return;
964}
965
966/**
967 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
968 * @ctx: Pointer to hdd context
969 * @pData: Pointer to scan event indication param
970 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800971 * This callback execute in atomic context and must not invoke any
972 * blocking calls.
973 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974 * Return: none
975 */
976static void
977wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
978 tpSirExtScanOnScanEventIndParams
979 pData)
980{
981 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
982 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800983 int flags = cds_get_gfp_flags();
Mukul Sharmafa937be2016-08-12 18:13:36 +0530984 struct hdd_ext_scan_context *context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700986 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530988 if (wlan_hdd_validate_context(pHddCtx))
989 return;
990 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700991 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992 return;
993 }
994
995 skb = cfg80211_vendor_event_alloc(
996 pHddCtx->wiphy,
997 NULL,
998 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
999 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001000 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001
1002 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001003 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001004 return;
1005 }
Mukul Sharmafa937be2016-08-12 18:13:36 +05301006
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001007 hdd_notice("Request Id: %u Scan event type: %u Scan event status: %u buckets scanned: %u",
Mukul Sharmafa937be2016-08-12 18:13:36 +05301008 pData->requestId, pData->scanEventType, pData->status,
1009 pData->buckets_scanned);
1010
Mukul Sharmafa937be2016-08-12 18:13:36 +05301011 context = &ext_scan_context;
1012 spin_lock(&context->context_lock);
1013 if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT) {
1014 context->buckets_scanned = 0;
1015 pData->scanEventType = WIFI_EXTSCAN_RESULTS_AVAILABLE;
1016 spin_unlock(&context->context_lock);
1017 } else if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_STARTED_EVENT) {
1018 context->buckets_scanned = pData->buckets_scanned;
1019 /* No need to report to user space */
1020 spin_unlock(&context->context_lock);
Mukul Sharma45114d92016-08-12 19:34:14 +05301021 goto nla_put_failure;
Mukul Sharmafa937be2016-08-12 18:13:36 +05301022 } else {
1023 spin_unlock(&context->context_lock);
1024 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001025
1026 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1027 pData->requestId) ||
1028 nla_put_u8(skb,
1029 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
Mukul Sharmafa937be2016-08-12 18:13:36 +05301030 pData->scanEventType)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001031 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001032 goto nla_put_failure;
1033 }
1034
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001035 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001036 return;
1037
1038nla_put_failure:
1039 kfree_skb(skb);
1040 return;
1041}
1042
1043/**
1044 * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found
1045 * @hddctx: HDD context
1046 * @data: matched network data
1047 *
1048 * This function reads the matched network data and fills NL vendor attributes
1049 * and send it to upper layer.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001050 * This callback execute in atomic context and must not invoke any
1051 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001052 *
1053 * Return: 0 on success, error number otherwise
1054 */
1055static void
1056wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
1057 struct pno_match_found *data)
1058{
1059 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
1060 struct sk_buff *skb = NULL;
1061 uint32_t len, i;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001062 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063
1064 ENTER();
1065
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301066 if (wlan_hdd_validate_context(pHddCtx))
1067 return;
1068 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001069 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001070 return;
1071 }
1072
1073 /*
1074 * If the number of match found APs including IE data exceeds NL 4K size
1075 * limitation, drop that beacon/probe rsp frame.
1076 */
1077 len = sizeof(*data) +
1078 (data->num_results + sizeof(tSirWifiScanResult));
1079 for (i = 0; i < data->num_results; i++)
1080 len += data->ap[i].ieLength;
1081
1082 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001083 hdd_err("Frame exceeded NL size limitation, drop it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001084 return;
1085 }
1086
1087 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1088 NULL,
1089 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1090 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001091 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092
1093 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001094 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001095 return;
1096 }
1097
Jeff Johnson630f9e72016-07-25 12:00:12 -07001098 hdd_notice("Req Id %u More Data %u num_results %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001099 data->request_id, data->more_data, data->num_results);
1100 for (i = 0; i < data->num_results; i++) {
1101 data->ap[i].channel = cds_chan_to_freq(data->ap[i].channel);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001102 hdd_notice("AP Info: Timestamp %llu) Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 "Bssid (" MAC_ADDRESS_STR ") "
1104 "Channel %u "
1105 "Rssi %d "
1106 "RTT %u "
1107 "RTT_SD %u "
1108 "Bcn Period %d "
1109 "Capability 0x%X "
1110 "IE Length %d",
1111 data->ap[i].ts,
1112 data->ap[i].ssid,
1113 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
1114 data->ap[i].channel,
1115 data->ap[i].rssi,
1116 data->ap[i].rtt,
1117 data->ap[i].rtt_sd,
1118 data->ap[i].beaconPeriod,
1119 data->ap[i].capability,
1120 data->ap[i].ieLength);
1121 }
1122
1123 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1124 data->request_id) ||
1125 nla_put_u32(skb,
1126 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1127 data->num_results) ||
1128 nla_put_u8(skb,
1129 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1130 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001131 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 goto fail;
1133 }
1134
1135 if (data->num_results) {
1136 struct nlattr *nla_aps;
1137 nla_aps = nla_nest_start(skb,
1138 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1139 if (!nla_aps)
1140 goto fail;
1141
1142 for (i = 0; i < data->num_results; i++) {
1143 if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i))
1144 goto fail;
1145 }
1146 nla_nest_end(skb, nla_aps);
1147 }
1148
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001149 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001150 return;
1151
1152fail:
1153 kfree_skb(skb);
1154 return;
1155}
1156
1157/**
1158 * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found
1159 * @hddctx: HDD context
1160 * @data: matched network data
1161 *
1162 * This function reads the match network %data and fill in the skb with
1163 * NL attributes and send up the NL event
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001164 * This callback execute in atomic context and must not invoke any
1165 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166 *
1167 * Return: none
1168 */
1169static void
1170wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
1171 struct wifi_passpoint_match *data)
1172{
1173 hdd_context_t *pHddCtx = ctx;
1174 struct sk_buff *skb = NULL;
1175 uint32_t len, i, num_matches = 1, more_data = 0;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001176 struct nlattr *nla_aps, *nla_bss;
1177 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001178
1179 ENTER();
1180
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301181 if (wlan_hdd_validate_context(pHddCtx))
1182 return;
1183 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001184 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001185 return;
1186 }
1187
1188 len = sizeof(*data) + data->ap.ieLength + data->anqp_len;
1189 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001190 hdd_err("Result exceeded NL size limitation, drop it");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001191 return;
1192 }
1193
1194 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1195 NULL,
1196 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1197 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001198 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199
1200 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001201 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001202 return;
1203 }
1204
Jeff Johnson630f9e72016-07-25 12:00:12 -07001205 hdd_notice("Req Id %u Id %u ANQP length %u num_matches %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 data->request_id, data->id, data->anqp_len, num_matches);
1207 for (i = 0; i < num_matches; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001208 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209 "Bssid (" MAC_ADDRESS_STR ") "
1210 "Channel %u "
1211 "Rssi %d "
1212 "RTT %u "
1213 "RTT_SD %u "
1214 "Bcn Period %d "
1215 "Capability 0x%X "
1216 "IE Length %d",
1217 data->ap.ts,
1218 data->ap.ssid,
1219 MAC_ADDR_ARRAY(data->ap.bssid.bytes),
1220 data->ap.channel,
1221 data->ap.rssi,
1222 data->ap.rtt,
1223 data->ap.rtt_sd,
1224 data->ap.beaconPeriod,
1225 data->ap.capability,
1226 data->ap.ieLength);
1227 }
1228
1229 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1230 data->request_id) ||
1231 nla_put_u32(skb,
1232 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES,
1233 num_matches) ||
1234 nla_put_u8(skb,
1235 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1236 more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001237 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 goto fail;
1239 }
1240
1241 nla_aps = nla_nest_start(skb,
1242 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST);
1243 if (!nla_aps)
1244 goto fail;
1245
1246 for (i = 0; i < num_matches; i++) {
1247 struct nlattr *nla_ap;
1248
1249 nla_ap = nla_nest_start(skb, i);
1250 if (!nla_ap)
1251 goto fail;
1252
1253 if (nla_put_u32(skb,
1254 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID,
1255 data->id) ||
1256 nla_put_u32(skb,
1257 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN,
1258 data->anqp_len)) {
1259 goto fail;
1260 }
1261
1262 if (data->anqp_len)
1263 if (nla_put(skb,
1264 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP,
1265 data->anqp_len, data->anqp))
1266 goto fail;
1267
1268 nla_bss = nla_nest_start(skb,
1269 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1270 if (!nla_bss)
1271 goto fail;
1272
1273 if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0))
1274 goto fail;
1275
1276 nla_nest_end(skb, nla_bss);
1277 nla_nest_end(skb, nla_ap);
1278 }
1279 nla_nest_end(skb, nla_aps);
1280
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001281 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282 return;
1283
1284fail:
1285 kfree_skb(skb);
1286 return;
1287}
1288
1289/**
1290 * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() -
1291 * Handle an SSID hotlist match event
1292 * @ctx: HDD context registered with SME
1293 * @event: The SSID hotlist match event
1294 *
1295 * This function will take an SSID match event that was generated by
1296 * firmware and will convert it into a cfg80211 vendor event which is
1297 * sent to userspace.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001298 * This callback execute in atomic context and must not invoke any
1299 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001300 *
1301 * Return: none
1302 */
1303static void
1304wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
1305 tpSirWifiScanResultEvent event)
1306{
1307 hdd_context_t *hdd_ctx = ctx;
1308 struct sk_buff *skb;
1309 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001310 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001311
1312 ENTER();
1313
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301314 if (wlan_hdd_validate_context(hdd_ctx))
1315 return;
1316 if (!event) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001317 hdd_err("event is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001318 return;
1319 }
1320
1321 if (event->ap_found) {
1322 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001323 hdd_notice("SSID hotlist found");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324 } else {
1325 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001326 hdd_notice("SSID hotlist lost");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 }
1328
1329 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1330 NULL,
1331 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001332 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333
1334 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001335 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001336 return;
1337 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07001338 hdd_notice("Req Id %u, Num results %u, More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001339 event->requestId, event->numOfAps, event->moreData);
1340
1341 for (i = 0; i < event->numOfAps; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001342 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001343 "Ssid: %s "
1344 "Bssid (" MAC_ADDRESS_STR ") "
1345 "Channel %u "
1346 "Rssi %d "
1347 "RTT %u "
1348 "RTT_SD %u",
1349 i,
1350 event->ap[i].ts,
1351 event->ap[i].ssid,
1352 MAC_ADDR_ARRAY(event->ap[i].bssid.bytes),
1353 event->ap[i].channel,
1354 event->ap[i].rssi,
1355 event->ap[i].rtt,
1356 event->ap[i].rtt_sd);
1357 }
1358
1359 if (nla_put_u32(skb,
1360 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1361 event->requestId) ||
1362 nla_put_u32(skb,
1363 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1364 event->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001365 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001366 goto fail;
1367 }
1368
1369 if (event->numOfAps) {
1370 struct nlattr *aps;
1371 aps = nla_nest_start(skb,
1372 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1373 if (!aps) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001374 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001375 goto fail;
1376 }
1377
1378 for (i = 0; i < event->numOfAps; i++) {
1379 struct nlattr *ap;
1380
1381 ap = nla_nest_start(skb, i);
1382 if (!ap) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001383 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 goto fail;
1385 }
1386
Dustin Brownbb7e2f52016-10-17 12:16:35 -07001387 if (hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
1389 event->ap[i].ts) ||
1390 nla_put(skb,
1391 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
1392 sizeof(event->ap[i].ssid),
1393 event->ap[i].ssid) ||
1394 nla_put(skb,
1395 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
1396 sizeof(event->ap[i].bssid),
1397 event->ap[i].bssid.bytes) ||
1398 nla_put_u32(skb,
1399 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
1400 event->ap[i].channel) ||
1401 nla_put_s32(skb,
1402 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
1403 event->ap[i].rssi) ||
1404 nla_put_u32(skb,
1405 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
1406 event->ap[i].rtt) ||
1407 nla_put_u32(skb,
1408 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
1409 event->ap[i].rtt_sd)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001410 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001411 goto fail;
1412 }
1413 nla_nest_end(skb, ap);
1414 }
1415 nla_nest_end(skb, aps);
1416
1417 if (nla_put_u8(skb,
1418 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1419 event->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001420 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001421 goto fail;
1422 }
1423 }
1424
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001425 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001426 return;
1427
1428fail:
1429 kfree_skb(skb);
1430 return;
1431}
1432
1433/**
1434 * wlan_hdd_cfg80211_extscan_generic_rsp() -
1435 * Handle a generic ExtScan Response message
1436 * @ctx: HDD context registered with SME
1437 * @response: The ExtScan response from firmware
1438 *
1439 * This function will handle a generic ExtScan response message from
1440 * firmware and will communicate the result to the userspace thread
1441 * that is waiting for the response.
1442 *
1443 * Return: none
1444 */
1445static void
1446wlan_hdd_cfg80211_extscan_generic_rsp
1447 (void *ctx,
1448 struct sir_extscan_generic_response *response)
1449{
1450 hdd_context_t *hdd_ctx = ctx;
1451 struct hdd_ext_scan_context *context;
1452
1453 ENTER();
1454
1455 if (wlan_hdd_validate_context(hdd_ctx) || !response) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001456 hdd_err("HDD context is not valid or response(%p) is null",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457 response);
1458 return;
1459 }
1460
Jeff Johnson630f9e72016-07-25 12:00:12 -07001461 hdd_notice("request %u status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 response->request_id, response->status);
1463
1464 context = &ext_scan_context;
1465 spin_lock(&context->context_lock);
1466 if (context->request_id == response->request_id) {
1467 context->response_status = response->status ? -EINVAL : 0;
1468 complete(&context->response_event);
1469 }
1470 spin_unlock(&context->context_lock);
1471
1472 return;
1473}
1474
1475/**
1476 * wlan_hdd_cfg80211_extscan_callback() - ext scan callback
1477 * @ctx: Pointer to hdd context
1478 * @evType: Event type
1479 * @pMag: Pointer to message
1480 *
1481 * Return: none
1482 */
1483void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType,
1484 void *pMsg)
1485{
1486 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1487
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001488 /* ENTER() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301489
1490 if (wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001492
Jeff Johnson630f9e72016-07-25 12:00:12 -07001493 hdd_notice("Rcvd Event %d", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494
1495 switch (evType) {
1496 case eSIR_EXTSCAN_CACHED_RESULTS_RSP:
1497 /* There is no need to send this response to upper layer
1498 Just log the message */
Jeff Johnson630f9e72016-07-25 12:00:12 -07001499 hdd_notice("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500 break;
1501
1502 case eSIR_EXTSCAN_GET_CAPABILITIES_IND:
1503 wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx,
1504 (struct ext_scan_capabilities_response *) pMsg);
1505 break;
1506
1507 case eSIR_EXTSCAN_HOTLIST_MATCH_IND:
1508 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
1509 break;
1510
1511 case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND:
1512 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx,
1513 (tpSirWifiSignificantChangeEvent) pMsg);
1514 break;
1515
1516 case eSIR_EXTSCAN_CACHED_RESULTS_IND:
1517 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
1518 break;
1519
1520 case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND:
1521 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx,
1522 (tpSirExtScanResultsAvailableIndParams) pMsg);
1523 break;
1524
1525 case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND:
1526 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx,
1527 (tpSirWifiFullScanResultEvent) pMsg);
1528 break;
1529
1530 case eSIR_EPNO_NETWORK_FOUND_IND:
1531 wlan_hdd_cfg80211_extscan_epno_match_found(ctx,
1532 (struct pno_match_found *)pMsg);
1533 break;
1534
1535 case eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND:
1536 wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx,
1537 (tpSirWifiScanResultEvent)pMsg);
1538 break;
1539
1540 case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND:
1541 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx,
1542 (tpSirExtScanOnScanEventIndParams) pMsg);
1543 break;
1544
1545 case eSIR_PASSPOINT_NETWORK_FOUND_IND:
1546 wlan_hdd_cfg80211_passpoint_match_found(ctx,
1547 (struct wifi_passpoint_match *) pMsg);
1548 break;
1549
1550 case eSIR_EXTSCAN_START_RSP:
1551 case eSIR_EXTSCAN_STOP_RSP:
1552 case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP:
1553 case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP:
1554 case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP:
1555 case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP:
1556 case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP:
1557 case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP:
1558 wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg);
1559 break;
1560
1561 default:
Jeff Johnson630f9e72016-07-25 12:00:12 -07001562 hdd_err("Unknown event type %u", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 break;
1564 }
1565}
1566
1567/*
1568 * define short names for the global vendor params
1569 * used by wlan_hdd_send_ext_scan_capability()
1570 */
1571#define PARAM_REQUEST_ID \
1572 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1573#define PARAM_STATUS \
1574 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1575#define MAX_SCAN_CACHE_SIZE \
1576 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1577#define MAX_SCAN_BUCKETS \
1578 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1579#define MAX_AP_CACHE_PER_SCAN \
1580 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1581#define MAX_RSSI_SAMPLE_SIZE \
1582 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1583#define MAX_SCAN_RPT_THRHOLD \
1584 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1585#define MAX_HOTLIST_BSSIDS \
1586 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1587#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1588 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1589#define MAX_BSSID_HISTORY_ENTRIES \
1590 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1591#define MAX_HOTLIST_SSIDS \
1592 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1593#define MAX_NUM_EPNO_NETS \
1594 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1595#define MAX_NUM_EPNO_NETS_BY_SSID \
1596 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1597#define MAX_NUM_WHITELISTED_SSID \
1598 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
1599
1600/**
1601 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1602 * @hdd_ctx: Pointer to hdd context
1603 *
1604 * Return: 0 for success, non-zero for failure
1605 */
1606static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx)
1607{
1608 int ret;
1609 struct sk_buff *skb;
1610 struct ext_scan_capabilities_response *data;
1611 uint32_t nl_buf_len;
1612
1613 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301614 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001616
1617 data = &(ext_scan_context.capability_response);
1618
1619 nl_buf_len = NLMSG_HDRLEN;
1620 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1621 (sizeof(data->status) + NLA_HDRLEN) +
1622 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1623 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1624 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1625 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1626 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1627 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1628 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1629 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1630 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1631 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1632 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
1633 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN);
1634
1635 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1636
1637 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001638 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639 return -ENOMEM;
1640 }
1641
1642
Jeff Johnson630f9e72016-07-25 12:00:12 -07001643 hdd_notice("Req Id %u", data->requestId);
1644 hdd_notice("Status %u", data->status);
1645 hdd_notice("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001646 data->max_scan_cache_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001647 hdd_notice("Scan buckets %u", data->max_scan_buckets);
1648 hdd_notice("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001649 data->max_ap_cache_per_scan);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001650 hdd_notice("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001651 data->max_rssi_sample_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001652 hdd_notice("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001653 data->max_scan_reporting_threshold);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001654 hdd_notice("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001655 data->max_hotlist_bssids);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001656 hdd_notice("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001657 data->max_significant_wifi_change_aps);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001658 hdd_notice("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001659 data->max_bssid_history_entries);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001660 hdd_notice("max_hotlist_ssids %u", data->max_hotlist_ssids);
1661 hdd_notice("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 data->max_number_epno_networks);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001663 hdd_notice("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 data->max_number_epno_networks_by_ssid);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001665 hdd_notice("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 data->max_number_of_white_listed_ssid);
1667
1668 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1669 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1670 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1671 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1672 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1673 data->max_ap_cache_per_scan) ||
1674 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1675 data->max_rssi_sample_size) ||
1676 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1677 data->max_scan_reporting_threshold) ||
1678 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1679 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1680 data->max_significant_wifi_change_aps) ||
1681 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1682 data->max_bssid_history_entries) ||
1683 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1684 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1685 data->max_number_epno_networks) ||
1686 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1687 data->max_number_epno_networks_by_ssid) ||
1688 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
1689 data->max_number_of_white_listed_ssid)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001690 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001691 goto nla_put_failure;
1692 }
1693
1694 cfg80211_vendor_cmd_reply(skb);
1695 return 0;
1696
1697nla_put_failure:
1698 kfree_skb(skb);
1699 return -EINVAL;
1700}
1701/*
1702 * done with short names for the global vendor params
1703 * used by wlan_hdd_send_ext_scan_capability()
1704 */
1705#undef PARAM_REQUEST_ID
1706#undef PARAM_STATUS
1707#undef MAX_SCAN_CACHE_SIZE
1708#undef MAX_SCAN_BUCKETS
1709#undef MAX_AP_CACHE_PER_SCAN
1710#undef MAX_RSSI_SAMPLE_SIZE
1711#undef MAX_SCAN_RPT_THRHOLD
1712#undef MAX_HOTLIST_BSSIDS
1713#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1714#undef MAX_BSSID_HISTORY_ENTRIES
1715#undef MAX_HOTLIST_SSIDS
1716#undef MAX_NUM_EPNO_NETS
1717#undef MAX_NUM_EPNO_NETS_BY_SSID
1718#undef MAX_NUM_WHITELISTED_SSID
1719
1720/**
1721 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1722 * @wiphy: Pointer to wireless phy
1723 * @wdev: Pointer to wireless device
1724 * @data: Pointer to data
1725 * @data_len: Data length
1726 *
1727 * Return: none
1728 */
1729static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1730 struct wireless_dev *wdev,
1731 const void *data, int data_len)
1732{
1733 int ret;
1734 unsigned long rc;
1735 struct hdd_ext_scan_context *context;
1736 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1737 struct net_device *dev = wdev->netdev;
1738 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1739 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1740 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1741 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301742 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001743
Jeff Johnson1f61b612016-02-12 16:28:33 -08001744 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001745
Anurag Chouhan6d760662016-02-20 16:05:43 +05301746 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001747 hdd_err("Command not allowed in FTM mode");
1748 return -EPERM;
1749 }
1750
1751 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301752 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301755 if (!pHddCtx->config->extscan_enabled) {
1756 hdd_err("extscan not supported");
1757 return -ENOTSUPP;
1758 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1760 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001761 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 return -EINVAL;
1763 }
1764
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301765 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001766 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001767 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001768 return -ENOMEM;
1769 }
1770
1771 /* Parse and fetch request Id */
1772 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001773 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001774 goto fail;
1775 }
1776
1777 pReqMsg->requestId =
1778 nla_get_u32(tb
1779 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
1780 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001781 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 pReqMsg->requestId, pReqMsg->sessionId);
1783
1784 context = &ext_scan_context;
1785 spin_lock(&context->context_lock);
1786 context->request_id = pReqMsg->requestId;
1787 INIT_COMPLETION(context->response_event);
1788 spin_unlock(&context->context_lock);
1789
1790 status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301791 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001792 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001793 status);
1794 goto fail;
1795 }
1796
1797 rc = wait_for_completion_timeout(&context->response_event,
1798 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1799 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001800 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001801 return -ETIMEDOUT;
1802 }
1803
1804 ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
1805 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001806 hdd_err("Failed to send ext scan capability to user space");
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301807 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808 return ret;
1809fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301810 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001811 return -EINVAL;
1812}
1813
1814/**
1815 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1816 * @wiphy: Pointer to wiphy
1817 * @wdev: Pointer to wdev
1818 * @data: Pointer to data
1819 * @data_len: Data length
1820 *
1821 * Return: 0 for success, non-zero for failure
1822 */
1823int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1824 struct wireless_dev *wdev,
1825 const void *data, int data_len)
1826{
1827 int ret = 0;
1828
1829 cds_ssr_protect(__func__);
1830 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1831 data_len);
1832 cds_ssr_unprotect(__func__);
1833
1834 return ret;
1835}
1836
1837/*
1838 * define short names for the global vendor params
1839 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1840 */
1841#define PARAM_MAX \
1842 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1843#define PARAM_REQUEST_ID \
1844 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1845#define PARAM_FLUSH \
1846 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1847/**
1848 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1849 * @wiphy: wiphy pointer
1850 * @wdev: pointer to struct wireless_dev
1851 * @data: pointer to incoming NL vendor data
1852 * @data_len: length of @data
1853 *
1854 * This function parses the incoming NL vendor command data attributes and
1855 * invokes the SME Api and blocks on a completion variable.
1856 * Each WMI event with cached scan results data chunk results in
1857 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1858 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1859 *
1860 * If timeout happens before receiving all of the data, this function sets
1861 * a context variable @ignore_cached_results to %true, all of the next data
1862 * chunks are checked against this variable and dropped.
1863 *
1864 * Return: 0 on success; error number otherwise.
1865 */
1866static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1867 struct wireless_dev
1868 *wdev, const void *data,
1869 int data_len)
1870{
1871 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1872 struct net_device *dev = wdev->netdev;
1873 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1874 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1875 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1876 1];
1877 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301878 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 int retval = 0;
1880 unsigned long rc;
1881
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001882 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883
Anurag Chouhan6d760662016-02-20 16:05:43 +05301884 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 hdd_err("Command not allowed in FTM mode");
1886 return -EPERM;
1887 }
1888
1889 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301890 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301893 if (!pHddCtx->config->extscan_enabled) {
1894 hdd_err("extscan not supported");
1895 return -ENOTSUPP;
1896 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 if (nla_parse(tb, PARAM_MAX, data, data_len,
1898 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001899 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001900 return -EINVAL;
1901 }
1902
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301903 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001904 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001905 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 return -ENOMEM;
1907 }
1908
1909 /* Parse and fetch request Id */
1910 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001911 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001912 goto fail;
1913 }
1914
1915 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
1916 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001917
1918 /* Parse and fetch flush parameter */
1919 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001920 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001921 goto fail;
1922 }
1923 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001924 hdd_notice("Req Id: %u Session Id: %d Flush: %d",
1925 pReqMsg->requestId, pReqMsg->sessionId, pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001926
1927 context = &ext_scan_context;
1928 spin_lock(&context->context_lock);
1929 context->request_id = pReqMsg->requestId;
1930 context->ignore_cached_results = false;
1931 INIT_COMPLETION(context->response_event);
1932 spin_unlock(&context->context_lock);
1933
1934 status = sme_get_cached_results(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301935 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001936 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937 goto fail;
1938 }
1939
1940 rc = wait_for_completion_timeout(&context->response_event,
1941 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1942 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001943 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001944 retval = -ETIMEDOUT;
1945 spin_lock(&context->context_lock);
1946 context->ignore_cached_results = true;
1947 spin_unlock(&context->context_lock);
1948 } else {
1949 spin_lock(&context->context_lock);
1950 retval = context->response_status;
1951 spin_unlock(&context->context_lock);
1952 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 return retval;
1954
1955fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301956 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 return -EINVAL;
1958}
1959/*
1960 * done with short names for the global vendor params
1961 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1962 */
1963#undef PARAM_MAX
1964#undef PARAM_REQUEST_ID
1965#undef PARAM_FLUSH
1966
1967/**
1968 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1969 * @wiphy: wiphy pointer
1970 * @wdev: pointer to struct wireless_dev
1971 * @data: pointer to incoming NL vendor data
1972 * @data_len: length of @data
1973 *
1974 * This function parses the incoming NL vendor command data attributes and
1975 * invokes the SME Api and blocks on a completion variable.
1976 * Each WMI event with cached scan results data chunk results in
1977 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1978 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1979 *
1980 * If timeout happens before receiving all of the data, this function sets
1981 * a context variable @ignore_cached_results to %true, all of the next data
1982 * chunks are checked against this variable and dropped.
1983 *
1984 * Return: 0 on success; error number otherwise.
1985 */
1986int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1987 struct wireless_dev *wdev,
1988 const void *data, int data_len)
1989{
1990 int ret = 0;
1991
1992 cds_ssr_protect(__func__);
1993 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
1994 data_len);
1995 cds_ssr_unprotect(__func__);
1996
1997 return ret;
1998}
1999
2000/**
2001 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
2002 * @wiphy: Pointer to wireless phy
2003 * @wdev: Pointer to wireless device
2004 * @data: Pointer to data
2005 * @data_len: Data length
2006 *
2007 * Return: none
2008 */
2009static int
2010__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2011 struct wireless_dev
2012 *wdev, const void *data,
2013 int data_len)
2014{
2015 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
2016 struct net_device *dev = wdev->netdev;
2017 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2018 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2019 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2020 1];
2021 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2022 + 1];
2023 struct nlattr *apTh;
2024 struct hdd_ext_scan_context *context;
2025 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302026 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002027 uint8_t i;
2028 int rem, retval;
2029 unsigned long rc;
2030
Jeff Johnson1f61b612016-02-12 16:28:33 -08002031 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032
Anurag Chouhan6d760662016-02-20 16:05:43 +05302033 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 hdd_err("Command not allowed in FTM mode");
2035 return -EPERM;
2036 }
2037
2038 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302039 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302042 if (!pHddCtx->config->extscan_enabled) {
2043 hdd_err("extscan not supported");
2044 return -ENOTSUPP;
2045 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2047 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002048 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049 return -EINVAL;
2050 }
2051
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302052 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002054 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055 return -ENOMEM;
2056 }
2057
2058 /* Parse and fetch request Id */
2059 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002060 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002061 goto fail;
2062 }
2063
2064 pReqMsg->requestId =
2065 nla_get_u32(tb
2066 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002067 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002068
2069 /* Parse and fetch number of APs */
2070 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002071 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002072 goto fail;
2073 }
2074 pReqMsg->numAp =
2075 nla_get_u32(tb
2076 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002077 if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_HOTLIST_APS) {
2078 hdd_err("Number of AP: %u exceeds max: %u",
2079 pReqMsg->numAp, WLAN_EXTSCAN_MAX_HOTLIST_APS);
2080 goto fail;
2081 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002083 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 pReqMsg->numAp, pReqMsg->sessionId);
2085
2086 /* Parse and fetch lost ap sample size */
2087 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002088 hdd_err("attr lost ap sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002089 goto fail;
2090 }
2091
2092 pReqMsg->lost_ap_sample_size = nla_get_u32(
2093 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002094 hdd_notice("Lost ap sample size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 pReqMsg->lost_ap_sample_size);
2096
2097 i = 0;
2098 nla_for_each_nested(apTh,
2099 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2100 rem) {
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002101 if (i == pReqMsg->numAp) {
2102 hdd_warn("Ignoring excess AP");
2103 break;
2104 }
2105
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106 if (nla_parse
2107 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2108 nla_data(apTh), nla_len(apTh),
2109 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002110 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111 goto fail;
2112 }
2113
2114 /* Parse and fetch MAC address */
2115 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002116 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002117 goto fail;
2118 }
2119 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2120 tb2
2121 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302122 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002123 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002124 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2125
2126 /* Parse and fetch low RSSI */
2127 if (!tb2
2128 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002129 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 goto fail;
2131 }
2132 pReqMsg->ap[i].low =
2133 nla_get_s32(tb2
2134 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002135 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002136
2137 /* Parse and fetch high RSSI */
2138 if (!tb2
2139 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002140 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141 goto fail;
2142 }
2143 pReqMsg->ap[i].high =
2144 nla_get_s32(tb2
2145 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002146 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002147
2148 i++;
2149 }
2150
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002151 if (i < pReqMsg->numAp) {
2152 hdd_warn("Number of AP %u less than expected %u",
2153 i, pReqMsg->numAp);
2154 pReqMsg->numAp = i;
2155 }
2156
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002157 context = &ext_scan_context;
2158 spin_lock(&context->context_lock);
2159 INIT_COMPLETION(context->response_event);
2160 context->request_id = request_id = pReqMsg->requestId;
2161 spin_unlock(&context->context_lock);
2162
2163 status = sme_set_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302164 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002165 hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166 goto fail;
2167 }
2168
2169 /* request was sent -- wait for the response */
2170 rc = wait_for_completion_timeout
2171 (&context->response_event,
2172 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2173
2174 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002175 hdd_err("sme_set_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002176 retval = -ETIMEDOUT;
2177 } else {
2178 spin_lock(&context->context_lock);
2179 if (context->request_id == request_id)
2180 retval = context->response_status;
2181 else
2182 retval = -EINVAL;
2183 spin_unlock(&context->context_lock);
2184 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302185 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 return retval;
2187
2188fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302189 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190 return -EINVAL;
2191}
2192
2193/**
2194 * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist
2195 * @wiphy: Pointer to wiphy
2196 * @wdev: Pointer to wdev
2197 * @data: Pointer to data
2198 * @data_len: Data length
2199 *
2200 * Return: 0 for success, non-zero for failure
2201 */
2202int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2203 struct wireless_dev *wdev,
2204 const void *data, int data_len)
2205{
2206 int ret = 0;
2207
2208 cds_ssr_protect(__func__);
2209 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
2210 data_len);
2211 cds_ssr_unprotect(__func__);
2212
2213 return ret;
2214}
2215
2216
2217/**
2218 * __wlan_hdd_cfg80211_extscan_set_significant_change () - set significant change
2219 * @wiphy: Pointer to wireless phy
2220 * @wdev: Pointer to wireless device
2221 * @data: Pointer to data
2222 * @data_len: Data length
2223 *
2224 * Return: none
2225 */
2226static int
2227__wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2228 struct wireless_dev
2229 *wdev, const void *data,
2230 int data_len)
2231{
2232 tpSirExtScanSetSigChangeReqParams pReqMsg = NULL;
2233 struct net_device *dev = wdev->netdev;
2234 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2235 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2236 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2237 1];
2238 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2239 + 1];
2240 struct nlattr *apTh;
2241 struct hdd_ext_scan_context *context;
2242 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302243 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002244 uint8_t i;
2245 int rem, retval;
2246 unsigned long rc;
2247
Jeff Johnson1f61b612016-02-12 16:28:33 -08002248 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249
Anurag Chouhan6d760662016-02-20 16:05:43 +05302250 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251 hdd_err("Command not allowed in FTM mode");
2252 return -EPERM;
2253 }
2254
2255 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302256 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002258
2259 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2260 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002261 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 return -EINVAL;
2263 }
2264
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302265 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002266 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002267 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002268 return -ENOMEM;
2269 }
2270
2271 /* Parse and fetch request Id */
2272 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002273 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002274 goto fail;
2275 }
2276
2277 pReqMsg->requestId =
2278 nla_get_u32(tb
2279 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002280 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002281
2282 /* Parse and fetch RSSI sample size */
2283 if (!tb
2284 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002285 hdd_err("attr RSSI sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286 goto fail;
2287 }
2288 pReqMsg->rssiSampleSize =
2289 nla_get_u32(tb
2290 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002291 hdd_notice("RSSI sample size %u", pReqMsg->rssiSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002292
2293 /* Parse and fetch lost AP sample size */
2294 if (!tb
2295 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002296 hdd_err("attr lost AP sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297 goto fail;
2298 }
2299 pReqMsg->lostApSampleSize =
2300 nla_get_u32(tb
2301 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002302 hdd_notice("Lost AP sample size %u", pReqMsg->lostApSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303
2304 /* Parse and fetch AP min breacing */
2305 if (!tb
2306 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002307 hdd_err("attr AP min breaching");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 goto fail;
2309 }
2310 pReqMsg->minBreaching =
2311 nla_get_u32(tb
2312 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002313 hdd_notice("AP min breaching %u", pReqMsg->minBreaching);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314
2315 /* Parse and fetch number of APs */
2316 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002317 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318 goto fail;
2319 }
2320 pReqMsg->numAp =
2321 nla_get_u32(tb
2322 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
2323 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002324 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002325 pReqMsg->numAp, pReqMsg->sessionId);
2326
2327 i = 0;
2328 nla_for_each_nested(apTh,
2329 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2330 rem) {
2331 if (nla_parse
2332 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2333 nla_data(apTh), nla_len(apTh),
2334 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002335 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 goto fail;
2337 }
2338
2339 /* Parse and fetch MAC address */
2340 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002341 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002342 goto fail;
2343 }
2344 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2345 tb2
2346 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302347 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002348 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2350
2351 /* Parse and fetch low RSSI */
2352 if (!tb2
2353 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002354 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355 goto fail;
2356 }
2357 pReqMsg->ap[i].low =
2358 nla_get_s32(tb2
2359 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002360 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361
2362 /* Parse and fetch high RSSI */
2363 if (!tb2
2364 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002365 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366 goto fail;
2367 }
2368 pReqMsg->ap[i].high =
2369 nla_get_s32(tb2
2370 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002371 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372
2373 i++;
2374 }
2375
2376 context = &ext_scan_context;
2377 spin_lock(&context->context_lock);
2378 INIT_COMPLETION(context->response_event);
2379 context->request_id = request_id = pReqMsg->requestId;
2380 spin_unlock(&context->context_lock);
2381
2382 status = sme_set_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302383 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002384 hdd_err("sme_set_significant_change failed(err=%d)", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302385 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386 return -EINVAL;
2387 }
2388
2389 /* request was sent -- wait for the response */
2390 rc = wait_for_completion_timeout(&context->response_event,
2391 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2392
2393 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002394 hdd_err("sme_set_significant_change timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002395 retval = -ETIMEDOUT;
2396 } else {
2397 spin_lock(&context->context_lock);
2398 if (context->request_id == request_id)
2399 retval = context->response_status;
2400 else
2401 retval = -EINVAL;
2402 spin_unlock(&context->context_lock);
2403 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302404 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 return retval;
2406
2407fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302408 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409 return -EINVAL;
2410}
2411
2412/**
2413 * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
2414 * @wiphy: Pointer to wireless phy
2415 * @wdev: Pointer to wireless device
2416 * @data: Pointer to data
2417 * @data_len: Data length
2418 *
2419 * Return: 0 on success, negative errno on failure
2420 */
2421int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2422 struct wireless_dev *wdev,
2423 const void *data, int data_len)
2424{
2425 int ret = 0;
2426
2427 cds_ssr_protect(__func__);
2428 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev,
2429 data, data_len);
2430 cds_ssr_unprotect(__func__);
2431
2432 return ret;
2433}
2434
2435/**
2436 * hdd_remove_dsrc_channels () - remove dsrc chanels
2437 * @wiphy: Pointer to wireless phy
2438 * @chan_list: channel list
2439 * @num_channels: number of channels
2440 *
2441 * Return: none
2442 */
Jeff Johnsoncd2a0792016-10-05 15:17:13 -07002443static void hdd_remove_dsrc_channels(struct wiphy *wiphy, uint32_t *chan_list,
2444 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445{
2446 uint8_t num_chan_temp = 0;
2447 int i;
2448
2449 for (i = 0; i < *num_channels; i++) {
2450 if (!cds_is_dsrc_channel(chan_list[i])) {
2451 chan_list[num_chan_temp] = chan_list[i];
2452 num_chan_temp++;
2453 }
2454 }
2455
2456 *num_channels = num_chan_temp;
2457}
2458
2459/**
Amar Singhalea10a872016-08-23 15:31:45 -07002460 * hdd_remove_passive_channels () - remove passive channels
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 * @wiphy: Pointer to wireless phy
2462 * @chan_list: channel list
2463 * @num_channels: number of channels
2464 *
2465 * Return: none
2466 */
Amar Singhalea10a872016-08-23 15:31:45 -07002467void hdd_remove_passive_channels(struct wiphy *wiphy, uint32_t *chan_list,
2468 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469{
2470 uint8_t num_chan_temp = 0;
2471 int i, j, k;
2472
2473 for (i = 0; i < *num_channels; i++)
Dustin Browna30892e2016-10-12 17:28:36 -07002474 for (j = 0; j < NUM_NL80211_BANDS; j++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002475 if (wiphy->bands[j] == NULL)
2476 continue;
2477 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
2478 if ((chan_list[i] ==
2479 wiphy->bands[j]->channels[k].center_freq)
2480 && (!(wiphy->bands[j]->channels[k].flags &
Amar Singhalea10a872016-08-23 15:31:45 -07002481 IEEE80211_CHAN_PASSIVE_SCAN))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 ) {
2483 chan_list[num_chan_temp] = chan_list[i];
2484 num_chan_temp++;
2485 }
2486 }
2487 }
2488
2489 *num_channels = num_chan_temp;
2490}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491
2492/**
2493 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
2494 * @wiphy: Pointer to wireless phy
2495 * @wdev: Pointer to wireless device
2496 * @data: Pointer to data
2497 * @data_len: Data length
2498 *
2499 * Return: none
2500 */
2501static int
2502__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2503 struct wireless_dev
2504 *wdev, const void *data,
2505 int data_len)
2506{
2507 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2508 struct net_device *dev = wdev->netdev;
2509 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2510 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002511 uint8_t num_channels = 0, i, buf[256] = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2513 1];
2514 uint32_t requestId, maxChannels;
2515 tWifiBand wifiBand;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302516 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 struct sk_buff *reply_skb;
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002518 int ret, len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002520 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521
Anurag Chouhan6d760662016-02-20 16:05:43 +05302522 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 hdd_err("Command not allowed in FTM mode");
2524 return -EPERM;
2525 }
2526
2527 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302528 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002530
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302531 if (!pHddCtx->config->extscan_enabled) {
2532 hdd_err("extscan not supported");
2533 return -ENOTSUPP;
2534 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2536 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002537 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 return -EINVAL;
2539 }
2540
2541 /* Parse and fetch request Id */
2542 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002543 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 return -EINVAL;
2545 }
2546 requestId =
2547 nla_get_u32(tb
2548 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549
2550 /* Parse and fetch wifi band */
2551 if (!tb
2552 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002553 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 return -EINVAL;
2555 }
2556 wifiBand =
2557 nla_get_u32(tb
2558 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559
2560 if (!tb
2561 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002562 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 return -EINVAL;
2564 }
2565 maxChannels =
2566 nla_get_u32(tb
2567 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002568 hdd_notice("Req Id: %u Wifi band: %d Max channels: %d", requestId,
2569 wifiBand, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002570 status = sme_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal),
2571 wifiBand, chan_list,
2572 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302573 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002574 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 status);
2576 return -EINVAL;
2577 }
2578
Anurag Chouhan6d760662016-02-20 16:05:43 +05302579 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002580
2581 hdd_remove_dsrc_channels(wiphy, chan_list, &num_channels);
2582
Krunal Sonibe766b02016-03-10 13:00:44 -08002583 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584 !strncmp(hdd_get_fwpath(), "ap", 2))
Amar Singhalea10a872016-08-23 15:31:45 -07002585 hdd_remove_passive_channels(wiphy, chan_list,
2586 &num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002587
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002588 hdd_notice("Number of channels: %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 for (i = 0; i < num_channels; i++)
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002590 len += scnprintf(buf + len, sizeof(buf) - len,
2591 "%u ", chan_list[i]);
2592
2593 hdd_notice("Channels: %s", buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002594
2595 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2596 sizeof(u32) *
2597 num_channels +
2598 NLMSG_HDRLEN);
2599
2600 if (reply_skb) {
2601 if (nla_put_u32(reply_skb,
2602 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2603 num_channels) ||
2604 nla_put(reply_skb,
2605 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2606 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002607 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002608 kfree_skb(reply_skb);
2609 return -EINVAL;
2610 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302611 ret = cfg80211_vendor_cmd_reply(reply_skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302612 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 }
2614
Jeff Johnson630f9e72016-07-25 12:00:12 -07002615 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002616 return -EINVAL;
2617}
2618
2619/**
2620 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2621 * @wiphy: Pointer to wireless phy
2622 * @wdev: Pointer to wireless device
2623 * @data: Pointer to data
2624 * @data_len: Data length
2625 *
2626 * Return: 0 on success, negative errno on failure
2627 */
2628int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2629 struct wireless_dev *wdev,
2630 const void *data, int data_len)
2631{
2632 int ret = 0;
2633
2634 cds_ssr_protect(__func__);
2635 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2636 data_len);
2637 cds_ssr_unprotect(__func__);
2638
2639 return ret;
2640}
2641
2642/**
2643 * hdd_extscan_update_dwell_time_limits() - update dwell times
2644 * @req_msg: Pointer to request message
2645 * @bkt_idx: Index of current bucket being processed
2646 * @active_min: minimum active dwell time
2647 * @active_max: maximum active dwell time
2648 * @passive_min: minimum passive dwell time
2649 * @passive_max: maximum passive dwell time
2650 *
2651 * Return: none
2652 */
2653static void hdd_extscan_update_dwell_time_limits(
2654 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2655 uint32_t active_min, uint32_t active_max,
2656 uint32_t passive_min, uint32_t passive_max)
2657{
2658 /* update per-bucket dwell times */
2659 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2660 active_min) {
2661 req_msg->buckets[bkt_idx].min_dwell_time_active =
2662 active_min;
2663 }
2664 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2665 active_max) {
2666 req_msg->buckets[bkt_idx].max_dwell_time_active =
2667 active_max;
2668 }
2669 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2670 passive_min) {
2671 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2672 passive_min;
2673 }
2674 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2675 passive_max) {
2676 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2677 passive_max;
2678 }
2679 /* update dwell-time across all buckets */
2680 if (req_msg->min_dwell_time_active >
2681 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2682 req_msg->min_dwell_time_active =
2683 req_msg->buckets[bkt_idx].min_dwell_time_active;
2684 }
2685 if (req_msg->max_dwell_time_active <
2686 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2687 req_msg->max_dwell_time_active =
2688 req_msg->buckets[bkt_idx].max_dwell_time_active;
2689 }
2690 if (req_msg->min_dwell_time_passive >
2691 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2692 req_msg->min_dwell_time_passive =
2693 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2694 }
2695 if (req_msg->max_dwell_time_passive >
2696 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2697 req_msg->max_dwell_time_passive =
2698 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2699 }
2700}
2701
2702/**
2703 * hdd_extscan_channel_max_reached() - channel max reached
2704 * @req: extscan request structure
2705 * @total_channels: total number of channels
2706 *
2707 * Return: true if total channels reached max, false otherwise
2708 */
2709static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2710 uint8_t total_channels)
2711{
2712 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2713 hdd_warn(
2714 "max #of channels %d reached, take only first %d bucket(s)",
2715 total_channels, req->numBuckets);
2716 return true;
2717 }
2718 return false;
2719}
2720
2721/**
2722 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2723 * @hdd_ctx: HDD global context
2724 * @req_msg: Pointer to request structure
2725 * @tb: pointer to NL attributes
2726 *
2727 * Return: 0 on success; error number otherwise
2728 */
2729static int hdd_extscan_start_fill_bucket_channel_spec(
2730 hdd_context_t *hdd_ctx,
2731 tpSirWifiScanCmdReqParams req_msg,
2732 struct nlattr **tb)
2733{
2734 struct nlattr *bucket[
2735 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2736 struct nlattr *channel[
2737 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2738 struct nlattr *buckets;
2739 struct nlattr *channels;
2740 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302741 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002742 uint8_t bkt_index, j, num_channels, total_channels = 0;
2743 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2744
2745 uint32_t min_dwell_time_active_bucket =
2746 hdd_ctx->config->extscan_active_max_chn_time;
2747 uint32_t max_dwell_time_active_bucket =
2748 hdd_ctx->config->extscan_active_max_chn_time;
2749 uint32_t min_dwell_time_passive_bucket =
2750 hdd_ctx->config->extscan_passive_max_chn_time;
2751 uint32_t max_dwell_time_passive_bucket =
2752 hdd_ctx->config->extscan_passive_max_chn_time;
2753
2754 bkt_index = 0;
2755 req_msg->min_dwell_time_active =
2756 req_msg->max_dwell_time_active =
2757 hdd_ctx->config->extscan_active_max_chn_time;
2758
2759 req_msg->min_dwell_time_passive =
2760 req_msg->max_dwell_time_passive =
2761 hdd_ctx->config->extscan_passive_max_chn_time;
2762 req_msg->numBuckets = 0;
2763
2764 nla_for_each_nested(buckets,
2765 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
2766 if (nla_parse(bucket,
2767 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2768 nla_data(buckets), nla_len(buckets), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002769 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002770 return -EINVAL;
2771 }
2772
2773 /* Parse and fetch bucket spec */
2774 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002775 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002776 return -EINVAL;
2777 }
2778 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2779 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002780
2781 /* Parse and fetch wifi band */
2782 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002783 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002784 return -EINVAL;
2785 }
2786 req_msg->buckets[bkt_index].band = nla_get_u8(
2787 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002788
2789 /* Parse and fetch period */
2790 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002791 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002792 return -EINVAL;
2793 }
2794 req_msg->buckets[bkt_index].period = nla_get_u32(
2795 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796
2797 /* Parse and fetch report events */
2798 if (!bucket[
2799 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002800 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002801 return -EINVAL;
2802 }
2803 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2804 bucket[
2805 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002806
2807 /* Parse and fetch max period */
2808 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002809 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002810 return -EINVAL;
2811 }
2812 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2813 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814
Mukul Sharmafa937be2016-08-12 18:13:36 +05302815 /* Parse and fetch base */
2816 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]) {
2817 hdd_err("attr base failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002818 return -EINVAL;
2819 }
2820 req_msg->buckets[bkt_index].exponent = nla_get_u32(
Mukul Sharmafa937be2016-08-12 18:13:36 +05302821 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002822
2823 /* Parse and fetch step count */
2824 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002825 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002826 return -EINVAL;
2827 }
2828 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2829 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002830 hdd_notice("Bucket spec Index: %d Wifi band: %d period: %d report events: %d max period: %u base: %u Step count: %u",
2831 req_msg->buckets[bkt_index].bucket,
2832 req_msg->buckets[bkt_index].band,
2833 req_msg->buckets[bkt_index].period,
2834 req_msg->buckets[bkt_index].reportEvents,
2835 req_msg->buckets[bkt_index].max_period,
2836 req_msg->buckets[bkt_index].exponent,
2837 req_msg->buckets[bkt_index].step_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002838
2839 /* start with known good values for bucket dwell times */
2840 req_msg->buckets[bkt_index].min_dwell_time_active =
2841 req_msg->buckets[bkt_index].max_dwell_time_active =
2842 hdd_ctx->config->extscan_active_max_chn_time;
2843
2844 req_msg->buckets[bkt_index].min_dwell_time_passive =
2845 req_msg->buckets[bkt_index].max_dwell_time_passive =
2846 hdd_ctx->config->extscan_passive_max_chn_time;
2847
2848 /* Framework shall pass the channel list if the input WiFi band
2849 * is WIFI_BAND_UNSPECIFIED.
2850 * If the input WiFi band is specified (any value other than
2851 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2852 */
2853 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2854 if (hdd_extscan_channel_max_reached(req_msg,
2855 total_channels))
2856 return 0;
2857
2858 num_channels = 0;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002859 hdd_notice("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002860 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2861 req_msg->buckets[bkt_index].band,
2862 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302863 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002864 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865 status);
2866 return -EINVAL;
2867 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07002868 hdd_notice("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002869 num_channels);
2870
2871 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302872 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002873 (WLAN_EXTSCAN_MAX_CHANNELS -
2874 total_channels));
2875 hdd_info("Adj Num channels/bucket: %d total_channels: %d",
2876 req_msg->buckets[bkt_index].numChannels,
2877 total_channels);
2878 total_channels +=
2879 req_msg->buckets[bkt_index].numChannels;
2880
2881 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2882 j++) {
2883 req_msg->buckets[bkt_index].channels[j].channel =
2884 chan_list[j];
2885 req_msg->buckets[bkt_index].channels[j].
2886 chnlClass = 0;
2887 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2888 cds_freq_to_chan(chan_list[j]))) {
2889 req_msg->buckets[bkt_index].channels[j].
2890 passive = 1;
2891 req_msg->buckets[bkt_index].channels[j].
2892 dwellTimeMs =
2893 hdd_ctx->config->
2894 extscan_passive_max_chn_time;
2895 /* reconfigure per-bucket dwell time */
2896 if (min_dwell_time_passive_bucket >
2897 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2898 min_dwell_time_passive_bucket =
2899 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2900 }
2901 if (max_dwell_time_passive_bucket <
2902 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2903 max_dwell_time_passive_bucket =
2904 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2905 }
2906
2907 } else {
2908 req_msg->buckets[bkt_index].channels[j].
2909 passive = 0;
2910 req_msg->buckets[bkt_index].channels[j].
2911 dwellTimeMs =
2912 hdd_ctx->config->extscan_active_max_chn_time;
2913 /* reconfigure per-bucket dwell times */
2914 if (min_dwell_time_active_bucket >
2915 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2916 min_dwell_time_active_bucket =
2917 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2918 }
2919 if (max_dwell_time_active_bucket <
2920 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2921 max_dwell_time_active_bucket =
2922 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2923 }
2924
2925 }
2926
Jeff Johnson630f9e72016-07-25 12:00:12 -07002927 hdd_notice("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002928 req_msg->buckets[bkt_index].channels[j].channel,
2929 req_msg->buckets[bkt_index].channels[j].passive,
2930 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2931 req_msg->buckets[bkt_index].channels[j].chnlClass);
2932 }
2933
2934 hdd_extscan_update_dwell_time_limits(
2935 req_msg, bkt_index,
2936 min_dwell_time_active_bucket,
2937 max_dwell_time_active_bucket,
2938 min_dwell_time_passive_bucket,
2939 max_dwell_time_passive_bucket);
2940
Jeff Johnson630f9e72016-07-25 12:00:12 -07002941 hdd_notice("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 bkt_index,
2943 req_msg->buckets[bkt_index].min_dwell_time_active,
2944 req_msg->buckets[bkt_index].max_dwell_time_active,
2945 req_msg->buckets[bkt_index].min_dwell_time_passive,
2946 req_msg->buckets[bkt_index].max_dwell_time_passive);
2947
2948 bkt_index++;
2949 req_msg->numBuckets++;
2950 continue;
2951 }
2952
2953 /* Parse and fetch number of channels */
2954 if (!bucket[
2955 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002956 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 return -EINVAL;
2958 }
2959 req_msg->buckets[bkt_index].numChannels =
2960 nla_get_u32(bucket[
2961 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
2962 hdd_info("before trimming: num channels %d",
2963 req_msg->buckets[bkt_index].numChannels);
2964
2965 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302966 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
2968 hdd_info("Num channels/bucket: %d total_channels: %d",
2969 req_msg->buckets[bkt_index].numChannels,
2970 total_channels);
2971 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
2972 return 0;
2973
2974 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002975 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 return -EINVAL;
2977 }
2978
2979 j = 0;
2980 nla_for_each_nested(channels,
2981 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07002982 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
2983 hdd_extscan_channel_max_reached(req_msg,
2984 total_channels))
2985 break;
2986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 if (nla_parse(channel,
2988 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2989 nla_data(channels), nla_len(channels),
2990 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002991 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 return -EINVAL;
2993 }
2994
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 /* Parse and fetch channel */
2996 if (!channel[
2997 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002998 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002999 return -EINVAL;
3000 }
3001 req_msg->buckets[bkt_index].channels[j].channel =
3002 nla_get_u32(channel[
3003 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003004 hdd_notice("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003005 req_msg->buckets[bkt_index].channels[j].channel);
3006
3007 /* Parse and fetch dwell time */
3008 if (!channel[
3009 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003010 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003011 return -EINVAL;
3012 }
3013 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3014 nla_get_u32(channel[
3015 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
3016
3017 /* Override dwell time if required */
3018 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
3019 hdd_ctx->config->extscan_active_min_chn_time ||
3020 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
3021 hdd_ctx->config->extscan_active_max_chn_time) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003022 hdd_notice("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3024
3025 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3026 cds_freq_to_chan(
3027 req_msg->buckets[bkt_index].channels[j].channel))) {
3028 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3029 hdd_ctx->config->extscan_passive_max_chn_time;
3030 } else {
3031 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3032 hdd_ctx->config->extscan_active_max_chn_time;
3033 }
3034 }
3035
Jeff Johnson630f9e72016-07-25 12:00:12 -07003036 hdd_notice("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3038
3039 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3040 cds_freq_to_chan(
3041 req_msg->buckets[bkt_index].channels[j].channel))) {
3042 if (min_dwell_time_passive_bucket >
3043 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3044 min_dwell_time_passive_bucket =
3045 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3046 }
3047 if (max_dwell_time_passive_bucket <
3048 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3049 max_dwell_time_passive_bucket =
3050 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3051 }
3052 } else {
3053 if (min_dwell_time_active_bucket >
3054 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3055 min_dwell_time_active_bucket =
3056 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3057 }
3058 if (max_dwell_time_active_bucket <
3059 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3060 max_dwell_time_active_bucket =
3061 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3062 }
3063 }
3064
3065 /* Parse and fetch channel spec passive */
3066 if (!channel[
3067 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003068 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003069 return -EINVAL;
3070 }
3071 req_msg->buckets[bkt_index].channels[j].passive =
3072 nla_get_u8(channel[
3073 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003074 hdd_notice("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003075 req_msg->buckets[bkt_index].channels[j].passive);
3076 /* Override scan type if required */
3077 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3078 cds_freq_to_chan(
3079 req_msg->buckets[bkt_index].channels[j].channel))) {
3080 req_msg->buckets[bkt_index].channels[j].passive = true;
3081 } else {
3082 req_msg->buckets[bkt_index].channels[j].passive = false;
3083 }
3084 j++;
3085 total_channels++;
3086 }
3087
3088 hdd_extscan_update_dwell_time_limits(
3089 req_msg, bkt_index,
3090 min_dwell_time_active_bucket,
3091 max_dwell_time_active_bucket,
3092 min_dwell_time_passive_bucket,
3093 max_dwell_time_passive_bucket);
3094
Jeff Johnson630f9e72016-07-25 12:00:12 -07003095 hdd_notice("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096 bkt_index,
3097 req_msg->buckets[bkt_index].min_dwell_time_active,
3098 req_msg->buckets[bkt_index].max_dwell_time_active,
3099 req_msg->buckets[bkt_index].min_dwell_time_passive,
3100 req_msg->buckets[bkt_index].max_dwell_time_passive);
3101
3102 bkt_index++;
3103 req_msg->numBuckets++;
3104 }
3105
Jeff Johnson630f9e72016-07-25 12:00:12 -07003106 hdd_notice("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003107 req_msg->min_dwell_time_active,
3108 req_msg->max_dwell_time_active,
3109 req_msg->min_dwell_time_passive,
3110 req_msg->max_dwell_time_passive);
3111
3112 return 0;
3113}
3114
3115/*
3116 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3117 * @config_flags - [input] configuration flags.
3118 *
3119 * This function maps user space received configuration flags to
3120 * driver representation.
3121 *
3122 * Return: configuration flags
3123 */
3124static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3125{
3126 uint32_t configuration_flags = 0;
3127
3128 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3129 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3130
3131 return configuration_flags;
3132}
3133
3134/*
3135 * define short names for the global vendor params
3136 * used by __wlan_hdd_cfg80211_extscan_start()
3137 */
3138#define PARAM_MAX \
3139 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3140#define PARAM_REQUEST_ID \
3141 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3142#define PARAM_BASE_PERIOD \
3143 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3144#define PARAM_MAX_AP_PER_SCAN \
3145 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3146#define PARAM_RPT_THRHLD_PERCENT \
3147 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3148#define PARAM_RPT_THRHLD_NUM_SCANS \
3149 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3150#define PARAM_NUM_BUCKETS \
3151 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3152#define PARAM_CONFIG_FLAGS \
3153 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3154
3155/**
3156 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3157 * @wiphy: Pointer to wireless phy
3158 * @wdev: Pointer to wireless device
3159 * @data: Pointer to data
3160 * @data_len: Length of @data
3161 *
3162 * Return: 0 on success; error number otherwise
3163 */
3164static int
3165__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3166 struct wireless_dev *wdev,
3167 const void *data,
3168 int data_len)
3169{
3170 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3171 struct net_device *dev = wdev->netdev;
3172 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3173 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3174 struct nlattr *tb[PARAM_MAX + 1];
3175 struct hdd_ext_scan_context *context;
3176 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303177 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 int retval;
3179 unsigned long rc;
3180
Jeff Johnson1f61b612016-02-12 16:28:33 -08003181 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182
Anurag Chouhan6d760662016-02-20 16:05:43 +05303183 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003184 hdd_err("Command not allowed in FTM mode");
3185 return -EPERM;
3186 }
3187
3188 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303189 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303192 if (!pHddCtx->config->extscan_enabled) {
3193 hdd_err("extscan not supported");
3194 return -ENOTSUPP;
3195 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003196 if (nla_parse(tb, PARAM_MAX, data, data_len,
3197 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003198 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199 return -EINVAL;
3200 }
3201
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303202 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003203 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003204 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 return -ENOMEM;
3206 }
3207
3208 /* Parse and fetch request Id */
3209 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003210 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 goto fail;
3212 }
3213
3214 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3215 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216
3217 /* Parse and fetch base period */
3218 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003219 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 goto fail;
3221 }
3222 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003223
3224 /* Parse and fetch max AP per scan */
3225 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003226 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227 goto fail;
3228 }
3229 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230
3231 /* Parse and fetch report threshold percent */
3232 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003233 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 goto fail;
3235 }
3236 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237
3238 /* Parse and fetch report threshold num scans */
3239 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003240 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 goto fail;
3242 }
3243 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003244 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",
3245 pReqMsg->requestId, pReqMsg->sessionId,
3246 pReqMsg->basePeriod, pReqMsg->maxAPperScan,
3247 pReqMsg->report_threshold_percent,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 pReqMsg->report_threshold_num_scans);
3249
3250 /* Parse and fetch number of buckets */
3251 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003252 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003253 goto fail;
3254 }
3255 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3256 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3257 hdd_warn("Exceeded MAX number of buckets: %d",
3258 WLAN_EXTSCAN_MAX_BUCKETS);
3259 }
3260 hdd_info("Input: Number of Buckets %d", num_buckets);
3261
3262 /* This is optional attribute, if not present set it to 0 */
3263 if (!tb[PARAM_CONFIG_FLAGS])
3264 pReqMsg->configuration_flags = 0;
3265 else
3266 pReqMsg->configuration_flags =
3267 hdd_extscan_map_usr_drv_config_flags(
3268 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3269
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303270 pReqMsg->extscan_adaptive_dwell_mode =
3271 pHddCtx->config->extscan_adaptive_dwell_mode;
3272
Jeff Johnson630f9e72016-07-25 12:00:12 -07003273 hdd_notice("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003274 pReqMsg->configuration_flags);
3275
3276 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003277 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003278 goto fail;
3279 }
3280
3281 if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb))
3282 goto fail;
3283
3284 context = &ext_scan_context;
3285 spin_lock(&context->context_lock);
3286 INIT_COMPLETION(context->response_event);
3287 context->request_id = request_id = pReqMsg->requestId;
Mukul Sharmafa937be2016-08-12 18:13:36 +05303288 context->buckets_scanned = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 spin_unlock(&context->context_lock);
3290
3291 status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303292 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003293 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003294 goto fail;
3295 }
3296
Anurag Chouhan50220ce2016-02-18 20:11:33 +05303297 pHddCtx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Jeff Johnson630f9e72016-07-25 12:00:12 -07003298 hdd_notice("Timestamp since boot: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003299 pHddCtx->ext_scan_start_since_boot);
3300
3301 /* request was sent -- wait for the response */
3302 rc = wait_for_completion_timeout(&context->response_event,
3303 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3304
3305 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003306 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003307 retval = -ETIMEDOUT;
3308 } else {
3309 spin_lock(&context->context_lock);
3310 if (context->request_id == request_id)
3311 retval = context->response_status;
3312 else
3313 retval = -EINVAL;
3314 spin_unlock(&context->context_lock);
3315 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303316 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003317 return retval;
3318
3319fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303320 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003321 return -EINVAL;
3322}
3323/*
3324 * done with short names for the global vendor params
3325 * used by __wlan_hdd_cfg80211_extscan_start()
3326 */
3327#undef PARAM_MAX
3328#undef PARAM_REQUEST_ID
3329#undef PARAM_BASE_PERIOD
3330#undef PARAMS_MAX_AP_PER_SCAN
3331#undef PARAMS_RPT_THRHLD_PERCENT
3332#undef PARAMS_RPT_THRHLD_NUM_SCANS
3333#undef PARAMS_NUM_BUCKETS
3334#undef PARAM_CONFIG_FLAGS
3335
3336/**
3337 * wlan_hdd_cfg80211_extscan_start() - start extscan
3338 * @wiphy: Pointer to wireless phy.
3339 * @wdev: Pointer to wireless device.
3340 * @data: Pointer to input data.
3341 * @data_len: Length of @data.
3342 *
3343 * Return: 0 on success, negative errno on failure
3344 */
3345int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3346 struct wireless_dev *wdev,
3347 const void *data, int data_len)
3348{
3349 int ret = 0;
3350
3351 cds_ssr_protect(__func__);
3352 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3353 cds_ssr_unprotect(__func__);
3354
3355 return ret;
3356}
3357
3358
3359/*
3360 * define short names for the global vendor params
3361 * used by __wlan_hdd_cfg80211_extscan_stop()
3362 */
3363#define PARAM_MAX \
3364 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3365#define PARAM_REQUEST_ID \
3366 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3367
3368/**
3369 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3370 * @wiphy: Pointer to wireless phy
3371 * @wdev: Pointer to wireless device
3372 * @data: Pointer to data
3373 * @data_len: Data length
3374 *
3375 * Return: none
3376 */
3377static int
3378__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3379 struct wireless_dev *wdev,
3380 const void *data, int data_len)
3381{
3382 tpSirExtScanStopReqParams pReqMsg = NULL;
3383 struct net_device *dev = wdev->netdev;
3384 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3385 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3386 struct nlattr *tb[PARAM_MAX + 1];
3387 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303388 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 uint32_t request_id;
3390 int retval;
3391 unsigned long rc;
3392
Jeff Johnson1f61b612016-02-12 16:28:33 -08003393 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003394
Anurag Chouhan6d760662016-02-20 16:05:43 +05303395 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396 hdd_err("Command not allowed in FTM mode");
3397 return -EPERM;
3398 }
3399
3400 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303401 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003402 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003403
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303404 if (!pHddCtx->config->extscan_enabled) {
3405 hdd_err("extscan not supported");
3406 return -ENOTSUPP;
3407 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003408 if (nla_parse(tb, PARAM_MAX, data, data_len,
3409 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003410 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003411 return -EINVAL;
3412 }
3413
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303414 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003416 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 return -ENOMEM;
3418 }
3419
3420 /* Parse and fetch request Id */
3421 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003422 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003423 goto fail;
3424 }
3425
3426 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3427 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003428 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 pReqMsg->requestId, pReqMsg->sessionId);
3430
3431 context = &ext_scan_context;
3432 spin_lock(&context->context_lock);
3433 INIT_COMPLETION(context->response_event);
3434 context->request_id = request_id = pReqMsg->requestId;
3435 spin_unlock(&context->context_lock);
3436
3437 status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303438 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003439 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003440 goto fail;
3441 }
3442
3443 /* request was sent -- wait for the response */
3444 rc = wait_for_completion_timeout(&context->response_event,
3445 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3446
3447 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003448 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003449 retval = -ETIMEDOUT;
3450 } else {
3451 spin_lock(&context->context_lock);
3452 if (context->request_id == request_id)
3453 retval = context->response_status;
3454 else
3455 retval = -EINVAL;
3456 spin_unlock(&context->context_lock);
3457 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303458 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003459 return retval;
3460
3461fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303462 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463 return -EINVAL;
3464}
3465/*
3466 * done with short names for the global vendor params
3467 * used by wlan_hdd_cfg80211_extscan_stop()
3468 */
3469#undef PARAM_MAX
3470#undef PARAM_REQUEST_ID
3471
3472
3473/**
3474 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3475 * @wiphy: Pointer to wireless phy.
3476 * @wdev: Pointer to wireless device.
3477 * @data: Pointer to input data.
3478 * @data_len: Length of @data.
3479 *
3480 * Return: 0 on success, negative errno on failure
3481 */
3482int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3483 struct wireless_dev *wdev,
3484 const void *data, int data_len)
3485{
3486 int ret = 0;
3487
3488 cds_ssr_protect(__func__);
3489 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3490 cds_ssr_unprotect(__func__);
3491
3492 return ret;
3493}
3494
3495
3496/**
3497 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3498 * @wiphy: Pointer to wireless phy
3499 * @wdev: Pointer to wireless device
3500 * @data: Pointer to data
3501 * @data_len: Data length
3502 *
3503 * Return: none
3504 */
3505static int
3506__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3507 struct wireless_dev
3508 *wdev, const void *data,
3509 int data_len)
3510{
3511 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3512 struct net_device *dev = wdev->netdev;
3513 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3514 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3515 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3516 1];
3517 struct hdd_ext_scan_context *context;
3518 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303519 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 int retval;
3521 unsigned long rc;
3522
Jeff Johnson1f61b612016-02-12 16:28:33 -08003523 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003524
Anurag Chouhan6d760662016-02-20 16:05:43 +05303525 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526 hdd_err("Command not allowed in FTM mode");
3527 return -EPERM;
3528 }
3529
3530 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303531 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003533
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303534 if (!pHddCtx->config->extscan_enabled) {
3535 hdd_err("extscan not supported");
3536 return -ENOTSUPP;
3537 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3539 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003540 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 return -EINVAL;
3542 }
3543
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303544 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003545 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003546 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003547 return -ENOMEM;
3548 }
3549
3550 /* Parse and fetch request Id */
3551 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003552 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003553 goto fail;
3554 }
3555
3556 pReqMsg->requestId =
3557 nla_get_u32(tb
3558 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3559 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003560 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561 pReqMsg->requestId, pReqMsg->sessionId);
3562
3563 context = &ext_scan_context;
3564 spin_lock(&context->context_lock);
3565 INIT_COMPLETION(context->response_event);
3566 context->request_id = request_id = pReqMsg->requestId;
3567 spin_unlock(&context->context_lock);
3568
3569 status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303570 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003571 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572 goto fail;
3573 }
3574
3575 /* request was sent -- wait for the response */
3576 rc = wait_for_completion_timeout
3577 (&context->response_event,
3578 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3579 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003580 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581 retval = -ETIMEDOUT;
3582 } else {
3583 spin_lock(&context->context_lock);
3584 if (context->request_id == request_id)
3585 retval = context->response_status;
3586 else
3587 retval = -EINVAL;
3588 spin_unlock(&context->context_lock);
3589 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303590 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003591 return retval;
3592
3593fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303594 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595 return -EINVAL;
3596}
3597
3598/**
3599 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3600 * @wiphy: Pointer to wireless phy
3601 * @wdev: Pointer to wireless device
3602 * @data: Pointer to data
3603 * @data_len: Data length
3604 *
3605 * Return: 0 on success, negative errno on failure
3606 */
3607int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3608 struct wireless_dev *wdev,
3609 const void *data, int data_len)
3610{
3611 int ret = 0;
3612
3613 cds_ssr_protect(__func__);
3614 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3615 data, data_len);
3616 cds_ssr_unprotect(__func__);
3617
3618 return ret;
3619}
3620
3621/**
3622 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3623 * reset significant change
3624 * @wiphy: Pointer to wireless phy
3625 * @wdev: Pointer to wireless device
3626 * @data: Pointer to data
3627 * @data_len: Data length
3628 *
3629 * Return: none
3630 */
3631static int
3632__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3633 *wiphy,
3634 struct
3635 wireless_dev
3636 *wdev, const void *data,
3637 int data_len)
3638{
3639 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3640 struct net_device *dev = wdev->netdev;
3641 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3642 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3643 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3644 1];
3645 struct hdd_ext_scan_context *context;
3646 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303647 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003648 int retval;
3649 unsigned long rc;
3650
Jeff Johnson1f61b612016-02-12 16:28:33 -08003651 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003652
Anurag Chouhan6d760662016-02-20 16:05:43 +05303653 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 hdd_err("Command not allowed in FTM mode");
3655 return -EPERM;
3656 }
3657
3658 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303659 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003660 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303662 if (!pHddCtx->config->extscan_enabled) {
3663 hdd_err("extscan not supported");
3664 return -ENOTSUPP;
3665 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003666 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3667 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003668 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669 return -EINVAL;
3670 }
3671
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303672 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003673 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003674 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003675 return -ENOMEM;
3676 }
3677
3678 /* Parse and fetch request Id */
3679 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003680 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 goto fail;
3682 }
3683
3684 pReqMsg->requestId =
3685 nla_get_u32(tb
3686 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3687 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003688 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 pReqMsg->requestId, pReqMsg->sessionId);
3690
3691 context = &ext_scan_context;
3692 spin_lock(&context->context_lock);
3693 INIT_COMPLETION(context->response_event);
3694 context->request_id = request_id = pReqMsg->requestId;
3695 spin_unlock(&context->context_lock);
3696
3697 status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303698 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003699 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003700 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303701 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 return -EINVAL;
3703 }
3704
3705 /* request was sent -- wait for the response */
3706 rc = wait_for_completion_timeout(&context->response_event,
3707 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3708
3709 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003710 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003711 retval = -ETIMEDOUT;
3712 } else {
3713 spin_lock(&context->context_lock);
3714 if (context->request_id == request_id)
3715 retval = context->response_status;
3716 else
3717 retval = -EINVAL;
3718 spin_unlock(&context->context_lock);
3719 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303720 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003721 return retval;
3722
3723fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303724 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003725 return -EINVAL;
3726}
3727
3728/**
3729 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3730 * change
3731 * @wiphy: Pointer to wireless phy
3732 * @wdev: Pointer to wireless device
3733 * @data: Pointer to data
3734 * @data_len: Data length
3735 *
3736 * Return: 0 on success, negative errno on failure
3737 */
3738int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3739 struct wireless_dev *wdev,
3740 const void *data, int data_len)
3741{
3742 int ret = 0;
3743
3744 cds_ssr_protect(__func__);
3745 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3746 data, data_len);
3747 cds_ssr_unprotect(__func__);
3748
3749 return ret;
3750}
3751
3752
3753/**
3754 * hdd_extscan_epno_fill_network_list() - epno fill network list
3755 * @hddctx: HDD context
3756 * @req_msg: request message
3757 * @tb: vendor attribute table
3758 *
3759 * This function reads the network block NL vendor attributes from %tb and
3760 * fill in the epno request message.
3761 *
3762 * Return: 0 on success, error number otherwise
3763 */
3764static int hdd_extscan_epno_fill_network_list(
3765 hdd_context_t *hddctx,
3766 struct wifi_epno_params *req_msg,
3767 struct nlattr **tb)
3768{
3769 struct nlattr *network[
3770 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3771 struct nlattr *networks;
3772 int rem1, ssid_len;
3773 uint8_t index, *ssid;
3774
3775 index = 0;
3776 nla_for_each_nested(networks,
3777 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3778 rem1) {
3779 if (nla_parse(network,
3780 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3781 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003782 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 return -EINVAL;
3784 }
3785
3786 /* Parse and fetch ssid */
3787 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003788 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003789 return -EINVAL;
3790 }
3791 ssid_len = nla_len(
3792 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3793
3794 /* Decrement by 1, don't count null character */
3795 ssid_len--;
3796
3797 req_msg->networks[index].ssid.length = ssid_len;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003798 hdd_notice("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003799 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303800 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003801 ssid, ssid_len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003802 hdd_notice("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803 req_msg->networks[index].ssid.length,
3804 req_msg->networks[index].ssid.ssId);
3805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003806 /* Parse and fetch epno flags */
3807 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003808 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003809 return -EINVAL;
3810 }
3811 req_msg->networks[index].flags = nla_get_u8(
3812 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003813 hdd_notice("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814
3815 /* Parse and fetch auth bit */
3816 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003817 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003818 return -EINVAL;
3819 }
3820 req_msg->networks[index].auth_bit_field = nla_get_u8(
3821 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003822 hdd_notice("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003823 req_msg->networks[index].auth_bit_field);
3824
3825 index++;
3826 }
3827 return 0;
3828}
3829
3830/**
3831 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3832 * @wiphy: wiphy
3833 * @wdev: pointer to wireless dev
3834 * @data: data pointer
3835 * @data_len: data length
3836 *
3837 * This function reads the NL vendor attributes from %tb and
3838 * fill in the epno request message.
3839 *
3840 * Return: 0 on success, error number otherwise
3841 */
3842static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3843 struct wireless_dev *wdev,
3844 const void *data,
3845 int data_len)
3846{
3847 struct wifi_epno_params *req_msg = NULL;
3848 struct net_device *dev = wdev->netdev;
3849 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3850 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3851 struct nlattr *tb[
3852 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303853 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003854 uint32_t num_networks, len;
3855 int ret_val;
3856
Jeff Johnson1f61b612016-02-12 16:28:33 -08003857 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003858
3859 ret_val = wlan_hdd_validate_context(hdd_ctx);
3860 if (ret_val)
3861 return ret_val;
3862
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303863 if (!hdd_ctx->config->extscan_enabled) {
3864 hdd_err("extscan not supported");
3865 return -ENOTSUPP;
3866 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303867 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003868 hdd_err("Command not allowed in FTM mode");
3869 return -EPERM;
3870 }
3871
3872 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3873 data, data_len,
3874 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003875 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003876 return -EINVAL;
3877 }
3878
3879 /* Parse and fetch number of networks */
3880 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003881 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 return -EINVAL;
3883 }
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303884
3885 /*
3886 * num_networks is also used as EPNO SET/RESET request.
3887 * if num_networks is zero then it is treated as RESET.
3888 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889 num_networks = nla_get_u32(
3890 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003891
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303892 if (num_networks > MAX_EPNO_NETWORKS) {
3893 hdd_notice("num of nw: %d exceeded max: %d, resetting to: %d",
3894 num_networks, MAX_EPNO_NETWORKS, MAX_EPNO_NETWORKS);
3895 num_networks = MAX_EPNO_NETWORKS;
3896 }
3897
3898 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003899 len = sizeof(*req_msg) +
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303900 (num_networks * sizeof(struct wifi_epno_network));
3901
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303902 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003904 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905 return -ENOMEM;
3906 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 req_msg->num_networks = num_networks;
3908
3909 /* Parse and fetch request Id */
3910 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003911 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912 goto fail;
3913 }
3914 req_msg->request_id = nla_get_u32(
3915 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003916 hdd_notice("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917
3918 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003919 hdd_notice("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303921 if (num_networks) {
3922
3923 /* Parse and fetch min_5ghz_rssi */
3924 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]) {
3925 hdd_err("min_5ghz_rssi id failed");
3926 goto fail;
3927 }
3928 req_msg->min_5ghz_rssi = nla_get_u32(
3929 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]);
3930
3931 /* Parse and fetch min_24ghz_rssi */
3932 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]) {
3933 hdd_err("min_24ghz_rssi id failed");
3934 goto fail;
3935 }
3936 req_msg->min_24ghz_rssi = nla_get_u32(
3937 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]);
3938
3939 /* Parse and fetch initial_score_max */
3940 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]) {
3941 hdd_err("initial_score_max id failed");
3942 goto fail;
3943 }
3944 req_msg->initial_score_max = nla_get_u32(
3945 tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]);
3946
3947 /* Parse and fetch current_connection_bonus */
3948 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]) {
3949 hdd_err("current_connection_bonus id failed");
3950 goto fail;
3951 }
3952 req_msg->current_connection_bonus = nla_get_u32(
3953 tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]
3954 );
3955
3956 /* Parse and fetch same_network_bonus */
3957 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]) {
3958 hdd_err("same_network_bonus id failed");
3959 goto fail;
3960 }
3961 req_msg->same_network_bonus = nla_get_u32(
3962 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]);
3963
3964 /* Parse and fetch secure_bonus */
3965 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]) {
3966 hdd_err("secure_bonus id failed");
3967 goto fail;
3968 }
3969 req_msg->secure_bonus = nla_get_u32(
3970 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]);
3971
3972 /* Parse and fetch band_5ghz_bonus */
3973 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]) {
3974 hdd_err("band_5ghz_bonus id failed");
3975 goto fail;
3976 }
3977 req_msg->band_5ghz_bonus = nla_get_u32(
3978 tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]);
3979
3980 hdd_notice("min_5ghz_rssi: %d min_24ghz_rssi: %d",
3981 req_msg->min_5ghz_rssi,
3982 req_msg->min_24ghz_rssi);
3983 hdd_notice("initial_score_max: %d current_connection_bonus:%d",
3984 req_msg->initial_score_max,
3985 req_msg->current_connection_bonus);
3986 hdd_notice("Bonuses same_network: %d secure: %d band_5ghz: %d",
3987 req_msg->same_network_bonus,
3988 req_msg->secure_bonus,
3989 req_msg->band_5ghz_bonus);
3990
3991 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
3992 goto fail;
3993
3994 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995
3996 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303997 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003998 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 goto fail;
4000 }
4001
4002 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304003 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004004 return 0;
4005
4006fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304007 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 return -EINVAL;
4009}
4010
4011 /**
4012 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
4013 * @wiphy: wiphy
4014 * @wdev: pointer to wireless dev
4015 * @data: data pointer
4016 * @data_len: data length
4017 *
4018 * This function reads the NL vendor attributes from %tb and
4019 * fill in the epno request message.
4020 *
4021 * Return: 0 on success, error number otherwise
4022 */
4023int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
4024 struct wireless_dev *wdev,
4025 const void *data,
4026 int data_len)
4027{
4028 int ret;
4029
4030 cds_ssr_protect(__func__);
4031 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
4032 data, data_len);
4033 cds_ssr_unprotect(__func__);
4034
4035 return ret;
4036}
4037
4038/**
4039 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
4040 * @hddctx: HDD context
4041 * @req_msg: request message
4042 * @tb: vendor attribute table
4043 *
4044 * This function reads the network block NL vendor attributes from %tb and
4045 * fill in the passpoint request message.
4046 *
4047 * Return: 0 on success, error number otherwise
4048 */
4049static int hdd_extscan_passpoint_fill_network_list(
4050 hdd_context_t *hddctx,
4051 struct wifi_passpoint_req *req_msg,
4052 struct nlattr **tb)
4053{
4054 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
4055 struct nlattr *networks;
4056 int rem1, len;
4057 uint8_t index;
4058
4059 index = 0;
4060 nla_for_each_nested(networks,
4061 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
4062 rem1) {
4063 if (nla_parse(network,
4064 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
4065 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004066 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004067 return -EINVAL;
4068 }
4069
4070 /* Parse and fetch identifier */
4071 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004072 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 return -EINVAL;
4074 }
4075 req_msg->networks[index].id = nla_get_u32(
4076 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004077 hdd_notice("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078
4079 /* Parse and fetch realm */
4080 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004081 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 return -EINVAL;
4083 }
4084 len = nla_len(
4085 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
4086 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004087 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004088 return -EINVAL;
4089 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304090 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
4092 len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004093 hdd_notice("realm len %d", len);
4094 hdd_notice("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004095
4096 /* Parse and fetch roaming consortium ids */
4097 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004098 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004099 return -EINVAL;
4100 }
4101 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
4102 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
4103 sizeof(req_msg->networks[0].roaming_consortium_ids));
Jeff Johnson630f9e72016-07-25 12:00:12 -07004104 hdd_notice("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004105
4106 /* Parse and fetch plmn */
4107 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004108 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109 return -EINVAL;
4110 }
4111 nla_memcpy(&req_msg->networks[index].plmn,
4112 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
4113 SIR_PASSPOINT_PLMN_LEN);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004114 hdd_notice("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 req_msg->networks[index].plmn[0],
4116 req_msg->networks[index].plmn[1],
4117 req_msg->networks[index].plmn[2]);
4118
4119 index++;
4120 }
4121 return 0;
4122}
4123
4124/**
4125 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4126 * @wiphy: wiphy
4127 * @wdev: pointer to wireless dev
4128 * @data: data pointer
4129 * @data_len: data length
4130 *
4131 * This function reads the NL vendor attributes from %tb and
4132 * fill in the passpoint request message.
4133 *
4134 * Return: 0 on success, error number otherwise
4135 */
4136static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4137 struct wireless_dev *wdev,
4138 const void *data,
4139 int data_len)
4140{
4141 struct wifi_passpoint_req *req_msg = NULL;
4142 struct net_device *dev = wdev->netdev;
4143 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4144 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4145 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304146 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004147 uint32_t num_networks = 0;
4148 int ret;
4149
Jeff Johnson1f61b612016-02-12 16:28:33 -08004150 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151
4152 ret = wlan_hdd_validate_context(hdd_ctx);
4153 if (ret)
4154 return ret;
4155
Anurag Chouhan6d760662016-02-20 16:05:43 +05304156 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 hdd_err("Command not allowed in FTM mode");
4158 return -EPERM;
4159 }
4160
4161 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4162 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004163 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 return -EINVAL;
4165 }
4166
4167 /* Parse and fetch number of networks */
4168 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004169 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 return -EINVAL;
4171 }
4172 num_networks = nla_get_u32(
4173 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004174 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004175
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304176 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004177 (num_networks * sizeof(req_msg->networks[0])));
4178 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004179 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 return -ENOMEM;
4181 }
4182 req_msg->num_networks = num_networks;
4183
4184 /* Parse and fetch request Id */
4185 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004186 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 goto fail;
4188 }
4189 req_msg->request_id = nla_get_u32(
4190 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4191
4192 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004193 hdd_notice("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004194 req_msg->session_id);
4195
4196 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4197 goto fail;
4198
4199 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304200 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004201 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 goto fail;
4203 }
4204
4205 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304206 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 return 0;
4208
4209fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304210 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211 return -EINVAL;
4212}
4213
4214/**
4215 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4216 * @wiphy: wiphy
4217 * @wdev: pointer to wireless dev
4218 * @data: data pointer
4219 * @data_len: data length
4220 *
4221 * This function reads the NL vendor attributes from %tb and
4222 * fill in the passpoint request message.
4223 *
4224 * Return: 0 on success, error number otherwise
4225 */
4226int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4227 struct wireless_dev *wdev,
4228 const void *data,
4229 int data_len)
4230{
4231 int ret;
4232
4233 cds_ssr_protect(__func__);
4234 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4235 data, data_len);
4236 cds_ssr_unprotect(__func__);
4237
4238 return ret;
4239}
4240
4241/**
4242 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4243 * @wiphy: wiphy
4244 * @wdev: pointer to wireless dev
4245 * @data: data pointer
4246 * @data_len: data length
4247 *
4248 * This function resets passpoint networks list
4249 *
4250 * Return: 0 on success, error number otherwise
4251 */
4252static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4253 struct wireless_dev *wdev,
4254 const void *data,
4255 int data_len)
4256{
4257 struct wifi_passpoint_req *req_msg = NULL;
4258 struct net_device *dev = wdev->netdev;
4259 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4260 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304262 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 int ret;
4264
Jeff Johnson1f61b612016-02-12 16:28:33 -08004265 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004266
4267 ret = wlan_hdd_validate_context(hdd_ctx);
4268 if (ret)
4269 return ret;
4270
Anurag Chouhan6d760662016-02-20 16:05:43 +05304271 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 hdd_err("Command not allowed in FTM mode");
4273 return -EPERM;
4274 }
4275
4276 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4277 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004278 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 return -EINVAL;
4280 }
4281
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304282 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004284 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285 return -ENOMEM;
4286 }
4287
4288 /* Parse and fetch request Id */
4289 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004290 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004291 goto fail;
4292 }
4293 req_msg->request_id = nla_get_u32(
4294 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4295
4296 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004297 hdd_notice("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298 req_msg->request_id, req_msg->session_id);
4299
4300 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304301 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004302 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 goto fail;
4304 }
4305
4306 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304307 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308 return 0;
4309
4310fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304311 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 return -EINVAL;
4313}
4314
4315/**
4316 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4317 * @wiphy: wiphy
4318 * @wdev: pointer to wireless dev
4319 * @data: data pointer
4320 * @data_len: data length
4321 *
4322 * This function resets passpoint networks list
4323 *
4324 * Return: 0 on success, error number otherwise
4325 */
4326int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4327 struct wireless_dev *wdev,
4328 const void *data,
4329 int data_len)
4330{
4331 int ret;
4332
4333 cds_ssr_protect(__func__);
4334 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4335 data, data_len);
4336 cds_ssr_unprotect(__func__);
4337
4338 return ret;
4339}
4340
4341/*
4342 * define short names for the global vendor params
4343 * used by __wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4344 */
4345#define PARAM_MAX \
4346 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4347#define PARAM_REQUEST_ID \
4348 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4349#define PARAMS_LOST_SSID_SAMPLE_SIZE \
4350 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE
4351#define PARAMS_NUM_SSID \
4352 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID
4353#define THRESHOLD_PARAM \
4354 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM
4355#define PARAM_SSID \
4356 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID
4357#define PARAM_BAND \
4358 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND
4359#define PARAM_RSSI_LOW \
4360 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW
4361#define PARAM_RSSI_HIGH \
4362 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH
4363
4364/**
4365 * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4366 * @wiphy: Pointer to wireless phy
4367 * @wdev: Pointer to wireless device
4368 * @data: Pointer to data
4369 * @data_len: Data length
4370 *
4371 * Return: 0 on success, negative errno on failure
4372 */
4373static int
4374__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4375 struct wireless_dev *wdev,
4376 const void *data,
4377 int data_len)
4378{
4379 struct sir_set_ssid_hotlist_request *request;
4380 struct net_device *dev = wdev->netdev;
4381 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4382 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4383 struct nlattr *tb[PARAM_MAX + 1];
4384 struct nlattr *tb2[PARAM_MAX + 1];
4385 struct nlattr *ssids;
4386 struct hdd_ext_scan_context *context;
4387 uint32_t request_id;
4388 char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1];
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304389 int ssid_len, i, rem, ssid_str_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304390 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 int retval;
4392 unsigned long rc;
4393
Jeff Johnson1f61b612016-02-12 16:28:33 -08004394 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395
Anurag Chouhan6d760662016-02-20 16:05:43 +05304396 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004397 hdd_err("Command not allowed in FTM mode");
4398 return -EPERM;
4399 }
4400
4401 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304402 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304405 if (!hdd_ctx->config->extscan_enabled) {
4406 hdd_err("extscan not supported");
4407 return -ENOTSUPP;
4408 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004409 if (nla_parse(tb, PARAM_MAX,
4410 data, data_len,
4411 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004412 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004413 return -EINVAL;
4414 }
4415
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304416 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004418 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 return -ENOMEM;
4420 }
4421
4422 /* Parse and fetch request Id */
4423 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004424 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425 goto fail;
4426 }
4427
4428 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004429 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430
4431 /* Parse and fetch lost SSID sample size */
4432 if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004433 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434 goto fail;
4435 }
4436 request->lost_ssid_sample_size =
4437 nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004438 hdd_notice("Lost SSID Sample Size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 request->lost_ssid_sample_size);
4440
4441 /* Parse and fetch number of hotlist SSID */
4442 if (!tb[PARAMS_NUM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004443 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004444 goto fail;
4445 }
4446 request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004447 hdd_notice("Number of SSID %d", request->ssid_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004448
4449 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004450 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451
4452 i = 0;
4453 nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) {
4454 if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004455 hdd_err("Too Many SSIDs, %d exceeds %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004456 i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS);
4457 break;
4458 }
4459 if (nla_parse(tb2, PARAM_MAX,
4460 nla_data(ssids), nla_len(ssids),
4461 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004462 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 goto fail;
4464 }
4465
4466 /* Parse and fetch SSID */
4467 if (!tb2[PARAM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004468 hdd_err("attr ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004469 goto fail;
4470 }
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304471 ssid_str_len = nla_strlcpy(ssid_string,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004472 tb2[PARAM_SSID],
4473 sizeof(ssid_string));
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304474 if (ssid_str_len > SIR_MAC_MAX_SSID_LENGTH) {
4475 hdd_err("Invalid length exceeds max ssid length");
4476 goto fail;
4477 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07004478 hdd_notice("SSID %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 ssid_string);
4480 ssid_len = strlen(ssid_string);
4481 memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len);
4482 request->ssids[i].ssid.length = ssid_len;
4483
4484 /* Parse and fetch low RSSI */
4485 if (!tb2[PARAM_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004486 hdd_err("attr band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004487 goto fail;
4488 }
4489 request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004490 hdd_notice("band %d", request->ssids[i].band);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004491
4492 /* Parse and fetch low RSSI */
4493 if (!tb2[PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004494 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495 goto fail;
4496 }
4497 request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004498 hdd_notice("RSSI low %d", request->ssids[i].rssi_low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499
4500 /* Parse and fetch high RSSI */
4501 if (!tb2[PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004502 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004503 goto fail;
4504 }
4505 request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004506 hdd_notice("RSSI high %d", request->ssids[i].rssi_high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 i++;
4508 }
4509
4510 context = &ext_scan_context;
4511 spin_lock(&context->context_lock);
4512 INIT_COMPLETION(context->response_event);
4513 context->request_id = request_id = request->request_id;
4514 spin_unlock(&context->context_lock);
4515
4516 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304517 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004518 hdd_err("sme_set_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519 goto fail;
4520 }
4521
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304522 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004523
4524 /* request was sent -- wait for the response */
4525 rc = wait_for_completion_timeout(&context->response_event,
4526 msecs_to_jiffies
4527 (WLAN_WAIT_TIME_EXTSCAN));
4528 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004529 hdd_err("sme_set_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530 retval = -ETIMEDOUT;
4531 } else {
4532 spin_lock(&context->context_lock);
4533 if (context->request_id == request_id)
4534 retval = context->response_status;
4535 else
4536 retval = -EINVAL;
4537 spin_unlock(&context->context_lock);
4538 }
4539
4540 return retval;
4541
4542fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304543 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004544 return -EINVAL;
4545}
4546
4547/*
4548 * done with short names for the global vendor params
4549 * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4550 */
4551#undef PARAM_MAX
4552#undef PARAM_REQUEST_ID
4553#undef PARAMS_NUM_SSID
4554#undef THRESHOLD_PARAM
4555#undef PARAM_SSID
4556#undef PARAM_BAND
4557#undef PARAM_RSSI_LOW
4558#undef PARAM_RSSI_HIGH
4559
4560/**
4561 * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4562 * @wiphy: Pointer to wireless phy
4563 * @wdev: Pointer to wireless device
4564 * @data: Pointer to data
4565 * @data_len: Data length
4566 *
4567 * Return: 0 on success, negative errno on failure
4568 */
4569int
4570wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4571 struct wireless_dev *wdev,
4572 const void *data,
4573 int data_len)
4574{
4575 int ret;
4576
4577 cds_ssr_protect(__func__);
4578 ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data,
4579 data_len);
4580 cds_ssr_unprotect(__func__);
4581
4582 return ret;
4583}
4584
4585/*
4586 * define short names for the global vendor params
4587 * used by __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4588 */
4589#define PARAM_MAX \
4590 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4591#define PARAM_REQUEST_ID \
4592 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4593
4594/**
4595 * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4596 * @wiphy: Pointer to wireless phy
4597 * @wdev: Pointer to wireless device
4598 * @data: Pointer to data
4599 * @data_len: Data length
4600 *
4601 * Return: 0 on success, negative errno on failure
4602 */
4603static int
4604__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4605 struct wireless_dev *wdev,
4606 const void *data,
4607 int data_len)
4608{
4609 struct sir_set_ssid_hotlist_request *request;
4610 struct net_device *dev = wdev->netdev;
4611 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4612 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4613 struct nlattr *tb[PARAM_MAX + 1];
4614 struct hdd_ext_scan_context *context;
4615 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304616 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004617 int retval;
4618 unsigned long rc;
4619
Jeff Johnson1f61b612016-02-12 16:28:33 -08004620 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004621
Anurag Chouhan6d760662016-02-20 16:05:43 +05304622 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004623 hdd_err("Command not allowed in FTM mode");
4624 return -EPERM;
4625 }
4626
4627 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304628 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004629 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304631 if (!hdd_ctx->config->extscan_enabled) {
4632 hdd_err("extscan not supported");
4633 return -ENOTSUPP;
4634 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004635 if (nla_parse(tb, PARAM_MAX,
4636 data, data_len,
4637 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004638 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004639 return -EINVAL;
4640 }
4641
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304642 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004643 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004644 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004645 return -ENOMEM;
4646 }
4647
4648 /* Parse and fetch request Id */
4649 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004650 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 goto fail;
4652 }
4653
4654 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004655 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004656
4657 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004658 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004659
4660 request->lost_ssid_sample_size = 0;
4661 request->ssid_count = 0;
4662
4663 context = &ext_scan_context;
4664 spin_lock(&context->context_lock);
4665 INIT_COMPLETION(context->response_event);
4666 context->request_id = request_id = request->request_id;
4667 spin_unlock(&context->context_lock);
4668
4669 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304670 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004671 hdd_err("sme_reset_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672 goto fail;
4673 }
4674
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304675 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004676
4677 /* request was sent -- wait for the response */
4678 rc = wait_for_completion_timeout(&context->response_event,
4679 msecs_to_jiffies
4680 (WLAN_WAIT_TIME_EXTSCAN));
4681 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004682 hdd_err("sme_reset_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 retval = -ETIMEDOUT;
4684 } else {
4685 spin_lock(&context->context_lock);
4686 if (context->request_id == request_id)
4687 retval = context->response_status;
4688 else
4689 retval = -EINVAL;
4690 spin_unlock(&context->context_lock);
4691 }
4692
4693 return retval;
4694
4695fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304696 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 return -EINVAL;
4698}
4699
4700/*
4701 * done with short names for the global vendor params
4702 * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4703 */
4704#undef PARAM_MAX
4705#undef PARAM_REQUEST_ID
4706
4707/**
4708 * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4709 * @wiphy: Pointer to wireless phy
4710 * @wdev: Pointer to wireless device
4711 * @data: Pointer to data
4712 * @data_len: Data length
4713 *
4714 * Return: 0 on success, negative errno on failure
4715 */
4716int
4717wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4718 struct wireless_dev *wdev,
4719 const void *data,
4720 int data_len)
4721{
4722 int ret;
4723
4724 cds_ssr_protect(__func__);
4725 ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev,
4726 data, data_len);
4727 cds_ssr_unprotect(__func__);
4728
4729 return ret;
4730}
4731
4732/**
4733 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4734 * @hdd_ctx: Global HDD context
4735 *
4736 * Return: none
4737 */
4738#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4739static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4740{
4741 init_completion(&pHddCtx->ready_to_extwow);
4742}
4743#else
4744static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4745{
4746 return;
4747}
4748#endif
4749
4750/**
4751 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4752 * @hdd_ctx: Global HDD context
4753 *
4754 * Return: none
4755 */
4756void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx)
4757{
4758 wlan_hdd_init_completion_extwow(hdd_ctx);
4759 init_completion(&ext_scan_context.response_event);
4760 spin_lock_init(&ext_scan_context.context_lock);
4761}
4762
4763#endif /* FEATURE_WLAN_EXTSCAN */