blob: 36a521165437ecefb54a4a134ed65f769c542779 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**
23 * DOC: wlan_hdd_ext_scan.c
24 *
25 * WLAN Host Device Driver EXT SCAN feature implementation
26 *
27 */
28
29#ifdef FEATURE_WLAN_EXTSCAN
30
Jeff Johnson630f9e72016-07-25 12:00:12 -070031/* denote that this file does not allow legacy hddLog */
32#define HDD_DISALLOW_LEGACY_HDDLOG 1
33
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080034#include "wlan_hdd_ext_scan.h"
35#include "cds_utils.h"
36#include "cds_sched.h"
37
38/* amount of time to wait for a synchronous request/response operation */
39#define WLAN_WAIT_TIME_EXTSCAN 1000
40
41/**
42 * struct hdd_ext_scan_context - hdd ext scan context
43 * @request_id: userspace-assigned ID associated with the request
44 * @response_event: Ext scan wait event
45 * @response_status: Status returned by FW in response to a request
46 * @ignore_cached_results: Flag to ignore cached results or not
47 * @context_lock: Spinlock to serialize all context accesses
48 * @capability_response: Ext scan capability response data from target
49 */
50struct hdd_ext_scan_context {
51 uint32_t request_id;
52 int response_status;
53 bool ignore_cached_results;
54 struct completion response_event;
55 spinlock_t context_lock;
56 struct ext_scan_capabilities_response capability_response;
57};
58static struct hdd_ext_scan_context ext_scan_context;
59
60static const struct nla_policy wlan_hdd_extscan_config_policy
61[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] = {
62 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = {
63 .type = NLA_U32},
64 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = {
65 .type = NLA_U32},
66 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = {.type = NLA_U32},
67 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = {
68 .type = NLA_U32},
69 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = {.type = NLA_U8},
70 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = {.type = NLA_U8},
71
72 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = {.type = NLA_U8},
73 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = {.type = NLA_U8},
74 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = {.type = NLA_U32},
75 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] = {
76 .type = NLA_U8},
77 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] = {
78 .type = NLA_U32},
79 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] = {
80 .type = NLA_U32},
81 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] = {
82 .type = NLA_U32},
83 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT] = {
84 .type = NLA_U8},
85 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS] = {
86 .type = NLA_U8 },
87 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] = {
88 .type = NLA_U8},
89 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = {
90 .type = NLA_U8},
91
92 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = {
93 .type = NLA_U32},
94 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = {
95 .type = NLA_UNSPEC},
96 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = {
97 .type = NLA_S32},
98 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = {
99 .type = NLA_S32},
100 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = {
101 .type = NLA_U32},
102 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] = {
103 .type = NLA_U32},
104 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] = {
105 .type = NLA_U32},
106 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = {
107 .type = NLA_U32},
108 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = {
109 .type = NLA_U32},
110 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = {
111 .type = NLA_U32},
112 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
113 .type = NLA_U32 },
114 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
115 .type = NLA_BINARY,
116 .len = IEEE80211_MAX_SSID_LEN },
117 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD] = {
118 .type = NLA_S8 },
119 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
120 .type = NLA_U8 },
121 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
122 .type = NLA_U8 },
123 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = {
124 .type = NLA_BINARY,
125 .len = IEEE80211_MAX_SSID_LEN + 1 },
126 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = {
127 .type = NLA_U32 },
128 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID] = {
129 .type = NLA_U32 },
130 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND] = {
131 .type = NLA_U8 },
132 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = {
133 .type = NLA_S32 },
134 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = {
135 .type = NLA_S32 },
136 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = {
137 .type = NLA_U32 },
138};
139
140static const struct nla_policy
141wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
142 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
143 .type = NLA_U16},
144 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = {
145 .type = NLA_U16},
146};
147
148/**
149 * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
150 * @ctx: Pointer to hdd context
151 * @data: Pointer to ext scan capabilities response from fw
152 *
153 * Return: None
154 */
155static void
156wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx,
157 struct ext_scan_capabilities_response *data)
158{
159 struct hdd_ext_scan_context *context;
160 hdd_context_t *hdd_ctx = ctx;
161
162 ENTER();
163
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530164 if (wlan_hdd_validate_context(hdd_ctx))
165 return;
166 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700167 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 return;
169 }
170
171 context = &ext_scan_context;
172
173 spin_lock(&context->context_lock);
174 /* validate response received from target*/
175 if (context->request_id != data->requestId) {
176 spin_unlock(&context->context_lock);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700177 hdd_err("Target response id did not match: request_id %d response_id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800178 context->request_id, data->requestId);
179 return;
180 } else {
181 context->capability_response = *data;
182 complete(&context->response_event);
183 }
184
185 spin_unlock(&context->context_lock);
186
187 return;
188}
189
190/*
191 * define short names for the global vendor params
192 * used by hdd_extscan_nl_fill_bss()
193 */
194#define PARAM_TIME_STAMP \
195 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
196#define PARAM_SSID \
197 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID
198#define PARAM_BSSID \
199 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID
200#define PARAM_CHANNEL \
201 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL
202#define PARAM_RSSI \
203 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI
204#define PARAM_RTT \
205 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT
206#define PARAM_RTT_SD \
207 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD
208#define PARAM_BEACON_PERIOD \
209 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD
210#define PARAM_CAPABILITY \
211 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY
212#define PARAM_IE_LENGTH \
213 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
214#define PARAM_IE_DATA \
215 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA
216
217/** hdd_extscan_nl_fill_bss() - extscan nl fill bss
218 * @skb: socket buffer
219 * @ap: bss information
220 * @idx: nesting index
221 *
222 * Return: 0 on success; error number otherwise
223 */
224static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap,
225 int idx)
226{
227 struct nlattr *nla_ap;
228
229 nla_ap = nla_nest_start(skb, idx);
230 if (!nla_ap)
231 return -EINVAL;
232
233 if (nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) ||
234 nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) ||
235 nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid.bytes) ||
236 nla_put_u32(skb, PARAM_CHANNEL, ap->channel) ||
237 nla_put_s32(skb, PARAM_RSSI, ap->rssi) ||
238 nla_put_u32(skb, PARAM_RTT, ap->rtt) ||
239 nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) ||
240 nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) ||
241 nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) ||
242 nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700243 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800244 return -EINVAL;
245 }
246
247 if (ap->ieLength)
248 if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700249 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250 return -EINVAL;
251 }
252
253 nla_nest_end(skb, nla_ap);
254
255 return 0;
256}
257/*
258 * done with short names for the global vendor params
259 * used by hdd_extscan_nl_fill_bss()
260 */
261#undef PARAM_TIME_STAMP
262#undef PARAM_SSID
263#undef PARAM_BSSID
264#undef PARAM_CHANNEL
265#undef PARAM_RSSI
266#undef PARAM_RTT
267#undef PARAM_RTT_SD
268#undef PARAM_BEACON_PERIOD
269#undef PARAM_CAPABILITY
270#undef PARAM_IE_LENGTH
271#undef PARAM_IE_DATA
272
273/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results
274 * @ctx: hdd global context
275 * @data: cached results
276 *
277 * This function reads the cached results %data, populated the NL
278 * attributes and sends the NL event to the upper layer.
279 *
280 * Return: none
281 */
282static void
283wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
284 struct extscan_cached_scan_results *data)
285{
286 hdd_context_t *pHddCtx = ctx;
287 struct sk_buff *skb = NULL;
288 struct hdd_ext_scan_context *context;
289 struct extscan_cached_scan_result *result;
290 tSirWifiScanResult *ap;
291 uint32_t i, j, nl_buf_len;
292 bool ignore_cached_results = false;
293
294 ENTER();
295
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530296 if (wlan_hdd_validate_context(pHddCtx))
297 return;
298 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700299 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 return;
301 }
302
303 context = &ext_scan_context;
304 spin_lock(&context->context_lock);
305 ignore_cached_results = context->ignore_cached_results;
306 spin_unlock(&context->context_lock);
307
308 if (ignore_cached_results) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700309 hdd_err("Ignore the cached results received after timeout");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800310 return;
311 }
312
313#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN
314#define EXTSCAN_CACHED_NL_FIXED_TLV \
315 ((sizeof(data->request_id) + NLA_HDRLEN) + \
316 (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \
317 (sizeof(data->more_data) + NLA_HDRLEN))
318#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \
319 ((sizeof(result->scan_id) + NLA_HDRLEN) + \
320 (sizeof(result->flags) + NLA_HDRLEN) + \
321 (sizeof(result->num_results) + NLA_HDRLEN))
322#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
323 ((sizeof(ap->ts) + NLA_HDRLEN) + \
324 (sizeof(ap->ssid) + NLA_HDRLEN) + \
325 (sizeof(ap->bssid) + NLA_HDRLEN) + \
326 (sizeof(ap->channel) + NLA_HDRLEN) + \
327 (sizeof(ap->rssi) + NLA_HDRLEN) + \
328 (sizeof(ap->rtt) + NLA_HDRLEN) + \
329 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
330 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
331 (sizeof(ap->capability) + NLA_HDRLEN) + \
332 (sizeof(ap->ieLength) + NLA_HDRLEN))
333#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
334 (ap->ieLength + NLA_HDRLEN)
335
336 nl_buf_len = NLMSG_HDRLEN;
337 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
338 if (data->num_scan_ids) {
339 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
340 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
341 result = &data->result[0];
342 for (i = 0; i < data->num_scan_ids; i++) {
343 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
344 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
345 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
346
347 ap = &result->ap[0];
348 for (j = 0; j < result->num_results; j++) {
349 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
350 nl_buf_len +=
351 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
352 if (ap->ieLength)
353 nl_buf_len +=
354 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
355 ap++;
356 }
357 result++;
358 }
359 }
360
Jeff Johnson630f9e72016-07-25 12:00:12 -0700361 hdd_notice("nl_buf_len = %u", nl_buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362 skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len);
363
364 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700365 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366 goto fail;
367 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700368 hdd_notice("Req Id %u Num_scan_ids %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369 data->request_id, data->num_scan_ids, data->more_data);
370
371 result = &data->result[0];
372 for (i = 0; i < data->num_scan_ids; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700373 hdd_notice("[i=%d] scan_id %u flags %u num_results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374 i, result->scan_id, result->flags, result->num_results);
375
376 ap = &result->ap[0];
377 for (j = 0; j < result->num_results; j++) {
378 /*
379 * Firmware returns timestamp from ext scan start till
380 * BSSID was cached (in micro seconds). Add this with
381 * time gap between system boot up to ext scan start
382 * to derive the time since boot when the
383 * BSSID was cached.
384 */
385 ap->ts += pHddCtx->ext_scan_start_since_boot;
Jeff Johnson630f9e72016-07-25 12:00:12 -0700386 hdd_notice("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800387 "Ssid: %s "
388 "Bssid (" MAC_ADDRESS_STR ") "
389 "Channel %u "
390 "Rssi %d "
391 "RTT %u "
392 "RTT_SD %u "
393 "Beacon Period %u "
394 "Capability 0x%x "
395 "Ie length %d",
396 ap->ts,
397 ap->ssid,
398 MAC_ADDR_ARRAY(ap->bssid.bytes),
399 ap->channel,
400 ap->rssi,
401 ap->rtt,
402 ap->rtt_sd,
403 ap->beaconPeriod,
404 ap->capability,
405 ap->ieLength);
406 ap++;
407 }
408 result++;
409 }
410
411 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
412 data->request_id) ||
413 nla_put_u32(skb,
414 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
415 data->num_scan_ids) ||
416 nla_put_u8(skb,
417 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
418 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700419 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420 goto fail;
421 }
422
423 if (data->num_scan_ids) {
424 struct nlattr *nla_results;
425 result = &data->result[0];
426
427 if (nla_put_u32(skb,
428 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
429 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700430 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800431 goto fail;
432 }
433 nla_results = nla_nest_start(skb,
434 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
435 if (!nla_results)
436 goto fail;
437
438 for (i = 0; i < data->num_scan_ids; i++) {
439 struct nlattr *nla_result;
440 struct nlattr *nla_aps;
441
442 nla_result = nla_nest_start(skb, i);
443 if (!nla_result)
444 goto fail;
445
446 if (nla_put_u32(skb,
447 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
448 result->scan_id) ||
449 nla_put_u32(skb,
450 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
451 result->flags) ||
452 nla_put_u32(skb,
453 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
454 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700455 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800456 goto fail;
457 }
458
459 nla_aps = nla_nest_start(skb,
460 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
461 if (!nla_aps)
462 goto fail;
463
464 ap = &result->ap[0];
465 for (j = 0; j < result->num_results; j++) {
466 if (hdd_extscan_nl_fill_bss(skb, ap, j))
467 goto fail;
468
469 ap++;
470 }
471 nla_nest_end(skb, nla_aps);
472 nla_nest_end(skb, nla_result);
473 result++;
474 }
475 nla_nest_end(skb, nla_results);
476 }
477
478 cfg80211_vendor_cmd_reply(skb);
479
480 if (!data->more_data) {
481 spin_lock(&context->context_lock);
482 context->response_status = 0;
483 complete(&context->response_event);
484 spin_unlock(&context->context_lock);
485 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530486 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800487 return;
488
489fail:
490 if (skb)
491 kfree_skb(skb);
492
493 spin_lock(&context->context_lock);
494 context->response_status = -EINVAL;
495 spin_unlock(&context->context_lock);
496
497 return;
498}
499
500/**
501 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
502 * @ctx: Pointer to hdd context
503 * @pData: Pointer to ext scan result event
504 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800505 * This callback execute in atomic context and must not invoke any
506 * blocking calls.
507 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 * Return: none
509 */
510static void
511wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
512 struct extscan_hotlist_match *data)
513{
514 hdd_context_t *pHddCtx = ctx;
515 struct sk_buff *skb = NULL;
516 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800517 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800518
519 ENTER();
520
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530521 if (wlan_hdd_validate_context(pHddCtx))
522 return;
523 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700524 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 return;
526 }
527
528 if (data->ap_found)
529 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
530 else
531 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
532
533 skb = cfg80211_vendor_event_alloc(
534 pHddCtx->wiphy,
535 NULL,
536 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800537 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538
539 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700540 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 return;
542 }
543 hdd_info("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
544 data->requestId, data->numOfAps, data->moreData,
545 data->ap_found);
546
547 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530548 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549
Jeff Johnson630f9e72016-07-25 12:00:12 -0700550 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551 "Ssid: %s "
552 "Bssid (" MAC_ADDRESS_STR ") "
553 "Channel %u "
554 "Rssi %d "
555 "RTT %u "
556 "RTT_SD %u",
557 i,
558 data->ap[i].ts,
559 data->ap[i].ssid,
560 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
561 data->ap[i].channel,
562 data->ap[i].rssi,
563 data->ap[i].rtt, data->ap[i].rtt_sd);
564 }
565
566 if (nla_put_u32(skb,
567 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
568 data->requestId) ||
569 nla_put_u32(skb,
570 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
571 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700572 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800573 goto fail;
574 }
575
576 if (data->numOfAps) {
577 struct nlattr *aps;
578
579 aps = nla_nest_start(skb,
580 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
581 if (!aps)
582 goto fail;
583
584 for (i = 0; i < data->numOfAps; i++) {
585 struct nlattr *ap;
586
587 ap = nla_nest_start(skb, i);
588 if (!ap)
589 goto fail;
590
591 if (nla_put_u64(skb,
592 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
593 data->ap[i].ts) ||
594 nla_put(skb,
595 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
596 sizeof(data->ap[i].ssid),
597 data->ap[i].ssid) ||
598 nla_put(skb,
599 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
600 sizeof(data->ap[i].bssid),
601 data->ap[i].bssid.bytes) ||
602 nla_put_u32(skb,
603 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
604 data->ap[i].channel) ||
605 nla_put_s32(skb,
606 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
607 data->ap[i].rssi) ||
608 nla_put_u32(skb,
609 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
610 data->ap[i].rtt) ||
611 nla_put_u32(skb,
612 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
613 data->ap[i].rtt_sd))
614 goto fail;
615
616 nla_nest_end(skb, ap);
617 }
618 nla_nest_end(skb, aps);
619
620 if (nla_put_u8(skb,
621 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
622 data->moreData))
623 goto fail;
624 }
625
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800626 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530627 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628 return;
629
630fail:
631 kfree_skb(skb);
632 return;
633}
634
635/**
636 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
637 * significant wifi change results indication
638 * @ctx: Pointer to hdd context
639 * @pData: Pointer to signif wifi change event
640 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800641 * This callback execute in atomic context and must not invoke any
642 * blocking calls.
643 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800644 * Return: none
645 */
646static void
647wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
648 void *ctx,
649 tpSirWifiSignificantChangeEvent pData)
650{
651 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
652 struct sk_buff *skb = NULL;
653 tSirWifiSignificantChange *ap_info;
654 int32_t *rssi;
655 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800656 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657
658 ENTER();
659
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530660 if (wlan_hdd_validate_context(pHddCtx))
661 return;
662 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700663 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 return;
665 }
666
667 skb = cfg80211_vendor_event_alloc(
668 pHddCtx->wiphy,
669 NULL,
670 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
671 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800672 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800673
674 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700675 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 return;
677 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700678 hdd_notice("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 pData->requestId, pData->numResults, pData->moreData);
680
681 ap_info = &pData->ap[0];
682 for (i = 0; i < pData->numResults; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700683 hdd_notice("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800684 "Bssid (" MAC_ADDRESS_STR ") "
685 "Channel %u "
686 "numOfRssi %d",
687 i,
688 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
689 ap_info->channel, ap_info->numOfRssi);
690 rssi = &(ap_info)->rssi[0];
691 for (j = 0; j < ap_info->numOfRssi; j++)
Jeff Johnson630f9e72016-07-25 12:00:12 -0700692 hdd_notice("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693
694 ap_info += ap_info->numOfRssi * sizeof(*rssi);
695 }
696
697 if (nla_put_u32(skb,
698 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
699 pData->requestId) ||
700 nla_put_u32(skb,
701 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
702 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700703 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 goto fail;
705 }
706
707 if (pData->numResults) {
708 struct nlattr *aps;
709
710 aps = nla_nest_start(skb,
711 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
712 if (!aps)
713 goto fail;
714
715 ap_info = &pData->ap[0];
716 for (i = 0; i < pData->numResults; i++) {
717 struct nlattr *ap;
718
719 ap = nla_nest_start(skb, i);
720 if (!ap)
721 goto fail;
722
723 if (nla_put(skb,
724 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530725 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 nla_put_u32(skb,
727 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
728 ap_info->channel) ||
729 nla_put_u32(skb,
730 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
731 ap_info->numOfRssi) ||
732 nla_put(skb,
733 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
734 sizeof(s32) * ap_info->numOfRssi,
735 &(ap_info)->rssi[0]))
736 goto fail;
737
738 nla_nest_end(skb, ap);
739
740 ap_info += ap_info->numOfRssi * sizeof(*rssi);
741 }
742 nla_nest_end(skb, aps);
743
744 if (nla_put_u8(skb,
745 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
746 pData->moreData))
747 goto fail;
748 }
749
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800750 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751 return;
752
753fail:
754 kfree_skb(skb);
755 return;
756
757}
758
759/**
760 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
761 * @ctx: Pointer to hdd context
762 * @pData: Pointer to full scan result event
763 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800764 * This callback execute in atomic context and must not invoke any
765 * blocking calls.
766 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 * Return: none
768 */
769static void
770wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
771 tpSirWifiFullScanResultEvent
772 pData)
773{
774 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
775 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 struct timespec ts;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700777
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800778 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779
780 ENTER();
781
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530782 if (wlan_hdd_validate_context(pHddCtx))
783 return;
784 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700785 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800786 return;
787 }
788
789 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700790 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 return;
792 }
793 skb = cfg80211_vendor_event_alloc(
794 pHddCtx->wiphy,
795 NULL,
796 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
797 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800798 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799
800 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700801 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800802 return;
803 }
804
805 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 /* Android does not want the time stamp from the frame.
808 Instead it wants a monotonic increasing value since boot */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700809 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700811
Jeff Johnson630f9e72016-07-25 12:00:12 -0700812 hdd_notice("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 pData->moreData);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700814 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 "Bssid (" MAC_ADDRESS_STR ") "
816 "Channel %u "
817 "Rssi %d "
818 "RTT %u "
819 "RTT_SD %u "
820 "Bcn Period %d "
821 "Capability 0x%X "
822 "IE Length %d",
823 pData->ap.ts,
824 pData->ap.ssid,
825 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
826 pData->ap.channel,
827 pData->ap.rssi,
828 pData->ap.rtt,
829 pData->ap.rtt_sd,
830 pData->ap.beaconPeriod,
831 pData->ap.capability, pData->ap.ieLength);
832
833 if (nla_put_u32(skb,
834 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
835 pData->requestId) ||
836 nla_put_u64(skb,
837 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
838 pData->ap.ts) ||
839 nla_put(skb,
840 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
841 sizeof(pData->ap.ssid),
842 pData->ap.ssid) ||
843 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
844 sizeof(pData->ap.bssid),
845 pData->ap.bssid.bytes) ||
846 nla_put_u32(skb,
847 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
848 pData->ap.channel) ||
849 nla_put_s32(skb,
850 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
851 pData->ap.rssi) ||
852 nla_put_u32(skb,
853 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
854 pData->ap.rtt) ||
855 nla_put_u32(skb,
856 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
857 pData->ap.rtt_sd) ||
858 nla_put_u16(skb,
859 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
860 pData->ap.beaconPeriod) ||
861 nla_put_u16(skb,
862 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
863 pData->ap.capability) ||
864 nla_put_u32(skb,
865 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
866 pData->ap.ieLength) ||
867 nla_put_u8(skb,
868 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
869 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700870 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800871 goto nla_put_failure;
872 }
873
874 if (pData->ap.ieLength) {
875 if (nla_put(skb,
876 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
877 pData->ap.ieLength, pData->ap.ieData))
878 goto nla_put_failure;
879 }
880
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800881 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530882 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883 return;
884
885nla_put_failure:
886 kfree_skb(skb);
887 return;
888}
889
890/**
891 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
892 * @ctx: Pointer to hdd context
893 * @pData: Pointer to scan results available indication param
894 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800895 * This callback execute in atomic context and must not invoke any
896 * blocking calls.
897 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800898 * Return: none
899 */
900static void
901wlan_hdd_cfg80211_extscan_scan_res_available_event(
902 void *ctx,
903 tpSirExtScanResultsAvailableIndParams pData)
904{
905 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
906 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800907 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908
909 ENTER();
910
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530911 if (wlan_hdd_validate_context(pHddCtx))
912 return;
913 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700914 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800915 return;
916 }
917
918 skb = cfg80211_vendor_event_alloc(
919 pHddCtx->wiphy,
920 NULL,
921 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
922 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800923 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800924
925 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700926 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800927 return;
928 }
929
Jeff Johnson630f9e72016-07-25 12:00:12 -0700930 hdd_notice("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 pData->requestId, pData->numResultsAvailable);
932 if (nla_put_u32(skb,
933 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
934 pData->requestId) ||
935 nla_put_u32(skb,
936 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
937 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700938 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 goto nla_put_failure;
940 }
941
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800942 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530943 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944 return;
945
946nla_put_failure:
947 kfree_skb(skb);
948 return;
949}
950
951/**
952 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
953 * @ctx: Pointer to hdd context
954 * @pData: Pointer to scan event indication param
955 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800956 * This callback execute in atomic context and must not invoke any
957 * blocking calls.
958 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800959 * Return: none
960 */
961static void
962wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
963 tpSirExtScanOnScanEventIndParams
964 pData)
965{
966 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
967 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800968 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969
970 ENTER();
971
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530972 if (wlan_hdd_validate_context(pHddCtx))
973 return;
974 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700975 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 return;
977 }
978
979 skb = cfg80211_vendor_event_alloc(
980 pHddCtx->wiphy,
981 NULL,
982 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
983 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800984 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985
986 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700987 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988 return;
989 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700990 hdd_notice("Req Id %u Scan event type %u Scan event status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 pData->requestId, pData->scanEventType, pData->status);
992
993 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
994 pData->requestId) ||
995 nla_put_u8(skb,
996 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
997 pData->scanEventType) ||
998 nla_put_u32(skb,
999 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_STATUS,
1000 pData->status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001001 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001002 goto nla_put_failure;
1003 }
1004
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001005 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301006 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001007 return;
1008
1009nla_put_failure:
1010 kfree_skb(skb);
1011 return;
1012}
1013
1014/**
1015 * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found
1016 * @hddctx: HDD context
1017 * @data: matched network data
1018 *
1019 * This function reads the matched network data and fills NL vendor attributes
1020 * and send it to upper layer.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001021 * This callback execute in atomic context and must not invoke any
1022 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001023 *
1024 * Return: 0 on success, error number otherwise
1025 */
1026static void
1027wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
1028 struct pno_match_found *data)
1029{
1030 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
1031 struct sk_buff *skb = NULL;
1032 uint32_t len, i;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001033 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001034
1035 ENTER();
1036
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301037 if (wlan_hdd_validate_context(pHddCtx))
1038 return;
1039 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001040 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001041 return;
1042 }
1043
1044 /*
1045 * If the number of match found APs including IE data exceeds NL 4K size
1046 * limitation, drop that beacon/probe rsp frame.
1047 */
1048 len = sizeof(*data) +
1049 (data->num_results + sizeof(tSirWifiScanResult));
1050 for (i = 0; i < data->num_results; i++)
1051 len += data->ap[i].ieLength;
1052
1053 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001054 hdd_err("Frame exceeded NL size limitation, drop it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001055 return;
1056 }
1057
1058 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1059 NULL,
1060 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1061 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001062 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063
1064 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001065 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 return;
1067 }
1068
Jeff Johnson630f9e72016-07-25 12:00:12 -07001069 hdd_notice("Req Id %u More Data %u num_results %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001070 data->request_id, data->more_data, data->num_results);
1071 for (i = 0; i < data->num_results; i++) {
1072 data->ap[i].channel = cds_chan_to_freq(data->ap[i].channel);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001073 hdd_notice("AP Info: Timestamp %llu) Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 "Bssid (" MAC_ADDRESS_STR ") "
1075 "Channel %u "
1076 "Rssi %d "
1077 "RTT %u "
1078 "RTT_SD %u "
1079 "Bcn Period %d "
1080 "Capability 0x%X "
1081 "IE Length %d",
1082 data->ap[i].ts,
1083 data->ap[i].ssid,
1084 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
1085 data->ap[i].channel,
1086 data->ap[i].rssi,
1087 data->ap[i].rtt,
1088 data->ap[i].rtt_sd,
1089 data->ap[i].beaconPeriod,
1090 data->ap[i].capability,
1091 data->ap[i].ieLength);
1092 }
1093
1094 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1095 data->request_id) ||
1096 nla_put_u32(skb,
1097 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1098 data->num_results) ||
1099 nla_put_u8(skb,
1100 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1101 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001102 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 goto fail;
1104 }
1105
1106 if (data->num_results) {
1107 struct nlattr *nla_aps;
1108 nla_aps = nla_nest_start(skb,
1109 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1110 if (!nla_aps)
1111 goto fail;
1112
1113 for (i = 0; i < data->num_results; i++) {
1114 if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i))
1115 goto fail;
1116 }
1117 nla_nest_end(skb, nla_aps);
1118 }
1119
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001120 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 return;
1122
1123fail:
1124 kfree_skb(skb);
1125 return;
1126}
1127
1128/**
1129 * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found
1130 * @hddctx: HDD context
1131 * @data: matched network data
1132 *
1133 * This function reads the match network %data and fill in the skb with
1134 * NL attributes and send up the NL event
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001135 * This callback execute in atomic context and must not invoke any
1136 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 *
1138 * Return: none
1139 */
1140static void
1141wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
1142 struct wifi_passpoint_match *data)
1143{
1144 hdd_context_t *pHddCtx = ctx;
1145 struct sk_buff *skb = NULL;
1146 uint32_t len, i, num_matches = 1, more_data = 0;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001147 struct nlattr *nla_aps, *nla_bss;
1148 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001149
1150 ENTER();
1151
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301152 if (wlan_hdd_validate_context(pHddCtx))
1153 return;
1154 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001155 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001156 return;
1157 }
1158
1159 len = sizeof(*data) + data->ap.ieLength + data->anqp_len;
1160 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001161 hdd_err("Result exceeded NL size limitation, drop it");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001162 return;
1163 }
1164
1165 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1166 NULL,
1167 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1168 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001169 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001170
1171 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001172 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001173 return;
1174 }
1175
Jeff Johnson630f9e72016-07-25 12:00:12 -07001176 hdd_notice("Req Id %u Id %u ANQP length %u num_matches %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001177 data->request_id, data->id, data->anqp_len, num_matches);
1178 for (i = 0; i < num_matches; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001179 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001180 "Bssid (" MAC_ADDRESS_STR ") "
1181 "Channel %u "
1182 "Rssi %d "
1183 "RTT %u "
1184 "RTT_SD %u "
1185 "Bcn Period %d "
1186 "Capability 0x%X "
1187 "IE Length %d",
1188 data->ap.ts,
1189 data->ap.ssid,
1190 MAC_ADDR_ARRAY(data->ap.bssid.bytes),
1191 data->ap.channel,
1192 data->ap.rssi,
1193 data->ap.rtt,
1194 data->ap.rtt_sd,
1195 data->ap.beaconPeriod,
1196 data->ap.capability,
1197 data->ap.ieLength);
1198 }
1199
1200 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1201 data->request_id) ||
1202 nla_put_u32(skb,
1203 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES,
1204 num_matches) ||
1205 nla_put_u8(skb,
1206 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1207 more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001208 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001209 goto fail;
1210 }
1211
1212 nla_aps = nla_nest_start(skb,
1213 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST);
1214 if (!nla_aps)
1215 goto fail;
1216
1217 for (i = 0; i < num_matches; i++) {
1218 struct nlattr *nla_ap;
1219
1220 nla_ap = nla_nest_start(skb, i);
1221 if (!nla_ap)
1222 goto fail;
1223
1224 if (nla_put_u32(skb,
1225 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID,
1226 data->id) ||
1227 nla_put_u32(skb,
1228 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN,
1229 data->anqp_len)) {
1230 goto fail;
1231 }
1232
1233 if (data->anqp_len)
1234 if (nla_put(skb,
1235 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP,
1236 data->anqp_len, data->anqp))
1237 goto fail;
1238
1239 nla_bss = nla_nest_start(skb,
1240 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1241 if (!nla_bss)
1242 goto fail;
1243
1244 if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0))
1245 goto fail;
1246
1247 nla_nest_end(skb, nla_bss);
1248 nla_nest_end(skb, nla_ap);
1249 }
1250 nla_nest_end(skb, nla_aps);
1251
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001252 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 return;
1254
1255fail:
1256 kfree_skb(skb);
1257 return;
1258}
1259
1260/**
1261 * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() -
1262 * Handle an SSID hotlist match event
1263 * @ctx: HDD context registered with SME
1264 * @event: The SSID hotlist match event
1265 *
1266 * This function will take an SSID match event that was generated by
1267 * firmware and will convert it into a cfg80211 vendor event which is
1268 * sent to userspace.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001269 * This callback execute in atomic context and must not invoke any
1270 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 *
1272 * Return: none
1273 */
1274static void
1275wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
1276 tpSirWifiScanResultEvent event)
1277{
1278 hdd_context_t *hdd_ctx = ctx;
1279 struct sk_buff *skb;
1280 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001281 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282
1283 ENTER();
1284
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301285 if (wlan_hdd_validate_context(hdd_ctx))
1286 return;
1287 if (!event) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001288 hdd_err("event is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001289 return;
1290 }
1291
1292 if (event->ap_found) {
1293 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001294 hdd_notice("SSID hotlist found");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 } else {
1296 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001297 hdd_notice("SSID hotlist lost");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 }
1299
1300 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1301 NULL,
1302 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001303 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001304
1305 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001306 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001307 return;
1308 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07001309 hdd_notice("Req Id %u, Num results %u, More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310 event->requestId, event->numOfAps, event->moreData);
1311
1312 for (i = 0; i < event->numOfAps; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001313 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001314 "Ssid: %s "
1315 "Bssid (" MAC_ADDRESS_STR ") "
1316 "Channel %u "
1317 "Rssi %d "
1318 "RTT %u "
1319 "RTT_SD %u",
1320 i,
1321 event->ap[i].ts,
1322 event->ap[i].ssid,
1323 MAC_ADDR_ARRAY(event->ap[i].bssid.bytes),
1324 event->ap[i].channel,
1325 event->ap[i].rssi,
1326 event->ap[i].rtt,
1327 event->ap[i].rtt_sd);
1328 }
1329
1330 if (nla_put_u32(skb,
1331 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1332 event->requestId) ||
1333 nla_put_u32(skb,
1334 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1335 event->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001336 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001337 goto fail;
1338 }
1339
1340 if (event->numOfAps) {
1341 struct nlattr *aps;
1342 aps = nla_nest_start(skb,
1343 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1344 if (!aps) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001345 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001346 goto fail;
1347 }
1348
1349 for (i = 0; i < event->numOfAps; i++) {
1350 struct nlattr *ap;
1351
1352 ap = nla_nest_start(skb, i);
1353 if (!ap) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001354 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355 goto fail;
1356 }
1357
1358 if (nla_put_u64(skb,
1359 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
1360 event->ap[i].ts) ||
1361 nla_put(skb,
1362 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
1363 sizeof(event->ap[i].ssid),
1364 event->ap[i].ssid) ||
1365 nla_put(skb,
1366 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
1367 sizeof(event->ap[i].bssid),
1368 event->ap[i].bssid.bytes) ||
1369 nla_put_u32(skb,
1370 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
1371 event->ap[i].channel) ||
1372 nla_put_s32(skb,
1373 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
1374 event->ap[i].rssi) ||
1375 nla_put_u32(skb,
1376 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
1377 event->ap[i].rtt) ||
1378 nla_put_u32(skb,
1379 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
1380 event->ap[i].rtt_sd)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001381 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 goto fail;
1383 }
1384 nla_nest_end(skb, ap);
1385 }
1386 nla_nest_end(skb, aps);
1387
1388 if (nla_put_u8(skb,
1389 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1390 event->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001391 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 goto fail;
1393 }
1394 }
1395
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001396 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001397 return;
1398
1399fail:
1400 kfree_skb(skb);
1401 return;
1402}
1403
1404/**
1405 * wlan_hdd_cfg80211_extscan_generic_rsp() -
1406 * Handle a generic ExtScan Response message
1407 * @ctx: HDD context registered with SME
1408 * @response: The ExtScan response from firmware
1409 *
1410 * This function will handle a generic ExtScan response message from
1411 * firmware and will communicate the result to the userspace thread
1412 * that is waiting for the response.
1413 *
1414 * Return: none
1415 */
1416static void
1417wlan_hdd_cfg80211_extscan_generic_rsp
1418 (void *ctx,
1419 struct sir_extscan_generic_response *response)
1420{
1421 hdd_context_t *hdd_ctx = ctx;
1422 struct hdd_ext_scan_context *context;
1423
1424 ENTER();
1425
1426 if (wlan_hdd_validate_context(hdd_ctx) || !response) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001427 hdd_err("HDD context is not valid or response(%p) is null",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001428 response);
1429 return;
1430 }
1431
Jeff Johnson630f9e72016-07-25 12:00:12 -07001432 hdd_notice("request %u status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001433 response->request_id, response->status);
1434
1435 context = &ext_scan_context;
1436 spin_lock(&context->context_lock);
1437 if (context->request_id == response->request_id) {
1438 context->response_status = response->status ? -EINVAL : 0;
1439 complete(&context->response_event);
1440 }
1441 spin_unlock(&context->context_lock);
1442
1443 return;
1444}
1445
1446/**
1447 * wlan_hdd_cfg80211_extscan_callback() - ext scan callback
1448 * @ctx: Pointer to hdd context
1449 * @evType: Event type
1450 * @pMag: Pointer to message
1451 *
1452 * Return: none
1453 */
1454void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType,
1455 void *pMsg)
1456{
1457 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1458
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301459 ENTER();
1460
1461 if (wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001463
Jeff Johnson630f9e72016-07-25 12:00:12 -07001464 hdd_notice("Rcvd Event %d", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465
1466 switch (evType) {
1467 case eSIR_EXTSCAN_CACHED_RESULTS_RSP:
1468 /* There is no need to send this response to upper layer
1469 Just log the message */
Jeff Johnson630f9e72016-07-25 12:00:12 -07001470 hdd_notice("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001471 break;
1472
1473 case eSIR_EXTSCAN_GET_CAPABILITIES_IND:
1474 wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx,
1475 (struct ext_scan_capabilities_response *) pMsg);
1476 break;
1477
1478 case eSIR_EXTSCAN_HOTLIST_MATCH_IND:
1479 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
1480 break;
1481
1482 case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND:
1483 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx,
1484 (tpSirWifiSignificantChangeEvent) pMsg);
1485 break;
1486
1487 case eSIR_EXTSCAN_CACHED_RESULTS_IND:
1488 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
1489 break;
1490
1491 case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND:
1492 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx,
1493 (tpSirExtScanResultsAvailableIndParams) pMsg);
1494 break;
1495
1496 case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND:
1497 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx,
1498 (tpSirWifiFullScanResultEvent) pMsg);
1499 break;
1500
1501 case eSIR_EPNO_NETWORK_FOUND_IND:
1502 wlan_hdd_cfg80211_extscan_epno_match_found(ctx,
1503 (struct pno_match_found *)pMsg);
1504 break;
1505
1506 case eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND:
1507 wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx,
1508 (tpSirWifiScanResultEvent)pMsg);
1509 break;
1510
1511 case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND:
1512 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx,
1513 (tpSirExtScanOnScanEventIndParams) pMsg);
1514 break;
1515
1516 case eSIR_PASSPOINT_NETWORK_FOUND_IND:
1517 wlan_hdd_cfg80211_passpoint_match_found(ctx,
1518 (struct wifi_passpoint_match *) pMsg);
1519 break;
1520
1521 case eSIR_EXTSCAN_START_RSP:
1522 case eSIR_EXTSCAN_STOP_RSP:
1523 case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP:
1524 case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP:
1525 case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP:
1526 case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP:
1527 case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP:
1528 case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP:
1529 wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg);
1530 break;
1531
1532 default:
Jeff Johnson630f9e72016-07-25 12:00:12 -07001533 hdd_err("Unknown event type %u", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001534 break;
1535 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301536 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537}
1538
1539/*
1540 * define short names for the global vendor params
1541 * used by wlan_hdd_send_ext_scan_capability()
1542 */
1543#define PARAM_REQUEST_ID \
1544 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1545#define PARAM_STATUS \
1546 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1547#define MAX_SCAN_CACHE_SIZE \
1548 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1549#define MAX_SCAN_BUCKETS \
1550 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1551#define MAX_AP_CACHE_PER_SCAN \
1552 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1553#define MAX_RSSI_SAMPLE_SIZE \
1554 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1555#define MAX_SCAN_RPT_THRHOLD \
1556 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1557#define MAX_HOTLIST_BSSIDS \
1558 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1559#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1560 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1561#define MAX_BSSID_HISTORY_ENTRIES \
1562 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1563#define MAX_HOTLIST_SSIDS \
1564 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1565#define MAX_NUM_EPNO_NETS \
1566 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1567#define MAX_NUM_EPNO_NETS_BY_SSID \
1568 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1569#define MAX_NUM_WHITELISTED_SSID \
1570 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
1571
1572/**
1573 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1574 * @hdd_ctx: Pointer to hdd context
1575 *
1576 * Return: 0 for success, non-zero for failure
1577 */
1578static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx)
1579{
1580 int ret;
1581 struct sk_buff *skb;
1582 struct ext_scan_capabilities_response *data;
1583 uint32_t nl_buf_len;
1584
1585 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301586 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001587 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001588
1589 data = &(ext_scan_context.capability_response);
1590
1591 nl_buf_len = NLMSG_HDRLEN;
1592 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1593 (sizeof(data->status) + NLA_HDRLEN) +
1594 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1595 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1596 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1597 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1598 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1599 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1600 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1601 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1602 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1603 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1604 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
1605 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN);
1606
1607 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1608
1609 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001610 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001611 return -ENOMEM;
1612 }
1613
1614
Jeff Johnson630f9e72016-07-25 12:00:12 -07001615 hdd_notice("Req Id %u", data->requestId);
1616 hdd_notice("Status %u", data->status);
1617 hdd_notice("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001618 data->max_scan_cache_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001619 hdd_notice("Scan buckets %u", data->max_scan_buckets);
1620 hdd_notice("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001621 data->max_ap_cache_per_scan);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001622 hdd_notice("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001623 data->max_rssi_sample_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001624 hdd_notice("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625 data->max_scan_reporting_threshold);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001626 hdd_notice("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001627 data->max_hotlist_bssids);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001628 hdd_notice("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001629 data->max_significant_wifi_change_aps);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001630 hdd_notice("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001631 data->max_bssid_history_entries);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001632 hdd_notice("max_hotlist_ssids %u", data->max_hotlist_ssids);
1633 hdd_notice("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001634 data->max_number_epno_networks);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001635 hdd_notice("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001636 data->max_number_epno_networks_by_ssid);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001637 hdd_notice("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638 data->max_number_of_white_listed_ssid);
1639
1640 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1641 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1642 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1643 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1644 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1645 data->max_ap_cache_per_scan) ||
1646 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1647 data->max_rssi_sample_size) ||
1648 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1649 data->max_scan_reporting_threshold) ||
1650 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1651 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1652 data->max_significant_wifi_change_aps) ||
1653 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1654 data->max_bssid_history_entries) ||
1655 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1656 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1657 data->max_number_epno_networks) ||
1658 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1659 data->max_number_epno_networks_by_ssid) ||
1660 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
1661 data->max_number_of_white_listed_ssid)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001662 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001663 goto nla_put_failure;
1664 }
1665
1666 cfg80211_vendor_cmd_reply(skb);
1667 return 0;
1668
1669nla_put_failure:
1670 kfree_skb(skb);
1671 return -EINVAL;
1672}
1673/*
1674 * done with short names for the global vendor params
1675 * used by wlan_hdd_send_ext_scan_capability()
1676 */
1677#undef PARAM_REQUEST_ID
1678#undef PARAM_STATUS
1679#undef MAX_SCAN_CACHE_SIZE
1680#undef MAX_SCAN_BUCKETS
1681#undef MAX_AP_CACHE_PER_SCAN
1682#undef MAX_RSSI_SAMPLE_SIZE
1683#undef MAX_SCAN_RPT_THRHOLD
1684#undef MAX_HOTLIST_BSSIDS
1685#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1686#undef MAX_BSSID_HISTORY_ENTRIES
1687#undef MAX_HOTLIST_SSIDS
1688#undef MAX_NUM_EPNO_NETS
1689#undef MAX_NUM_EPNO_NETS_BY_SSID
1690#undef MAX_NUM_WHITELISTED_SSID
1691
1692/**
1693 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1694 * @wiphy: Pointer to wireless phy
1695 * @wdev: Pointer to wireless device
1696 * @data: Pointer to data
1697 * @data_len: Data length
1698 *
1699 * Return: none
1700 */
1701static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1702 struct wireless_dev *wdev,
1703 const void *data, int data_len)
1704{
1705 int ret;
1706 unsigned long rc;
1707 struct hdd_ext_scan_context *context;
1708 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1709 struct net_device *dev = wdev->netdev;
1710 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1711 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1712 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1713 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301714 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001715
Jeff Johnson1f61b612016-02-12 16:28:33 -08001716 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001717
Anurag Chouhan6d760662016-02-20 16:05:43 +05301718 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001719 hdd_err("Command not allowed in FTM mode");
1720 return -EPERM;
1721 }
1722
1723 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301724 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001725 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001726
1727 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1728 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001729 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 return -EINVAL;
1731 }
1732
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301733 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001734 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001735 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 return -ENOMEM;
1737 }
1738
1739 /* Parse and fetch request Id */
1740 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001741 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742 goto fail;
1743 }
1744
1745 pReqMsg->requestId =
1746 nla_get_u32(tb
1747 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
1748 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001749 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001750 pReqMsg->requestId, pReqMsg->sessionId);
1751
1752 context = &ext_scan_context;
1753 spin_lock(&context->context_lock);
1754 context->request_id = pReqMsg->requestId;
1755 INIT_COMPLETION(context->response_event);
1756 spin_unlock(&context->context_lock);
1757
1758 status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301759 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001760 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001761 status);
1762 goto fail;
1763 }
1764
1765 rc = wait_for_completion_timeout(&context->response_event,
1766 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1767 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001768 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001769 return -ETIMEDOUT;
1770 }
1771
1772 ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
1773 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001774 hdd_err("Failed to send ext scan capability to user space");
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301775 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001776 return ret;
1777fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301778 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 return -EINVAL;
1780}
1781
1782/**
1783 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1784 * @wiphy: Pointer to wiphy
1785 * @wdev: Pointer to wdev
1786 * @data: Pointer to data
1787 * @data_len: Data length
1788 *
1789 * Return: 0 for success, non-zero for failure
1790 */
1791int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1792 struct wireless_dev *wdev,
1793 const void *data, int data_len)
1794{
1795 int ret = 0;
1796
1797 cds_ssr_protect(__func__);
1798 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1799 data_len);
1800 cds_ssr_unprotect(__func__);
1801
1802 return ret;
1803}
1804
1805/*
1806 * define short names for the global vendor params
1807 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1808 */
1809#define PARAM_MAX \
1810 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1811#define PARAM_REQUEST_ID \
1812 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1813#define PARAM_FLUSH \
1814 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1815/**
1816 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1817 * @wiphy: wiphy pointer
1818 * @wdev: pointer to struct wireless_dev
1819 * @data: pointer to incoming NL vendor data
1820 * @data_len: length of @data
1821 *
1822 * This function parses the incoming NL vendor command data attributes and
1823 * invokes the SME Api and blocks on a completion variable.
1824 * Each WMI event with cached scan results data chunk results in
1825 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1826 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1827 *
1828 * If timeout happens before receiving all of the data, this function sets
1829 * a context variable @ignore_cached_results to %true, all of the next data
1830 * chunks are checked against this variable and dropped.
1831 *
1832 * Return: 0 on success; error number otherwise.
1833 */
1834static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1835 struct wireless_dev
1836 *wdev, const void *data,
1837 int data_len)
1838{
1839 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1840 struct net_device *dev = wdev->netdev;
1841 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1842 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1843 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1844 1];
1845 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301846 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 int retval = 0;
1848 unsigned long rc;
1849
Jeff Johnson1f61b612016-02-12 16:28:33 -08001850 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851
Anurag Chouhan6d760662016-02-20 16:05:43 +05301852 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 hdd_err("Command not allowed in FTM mode");
1854 return -EPERM;
1855 }
1856
1857 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301858 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860
1861 if (nla_parse(tb, PARAM_MAX, data, data_len,
1862 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001863 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001864 return -EINVAL;
1865 }
1866
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301867 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001869 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870 return -ENOMEM;
1871 }
1872
1873 /* Parse and fetch request Id */
1874 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001875 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001876 goto fail;
1877 }
1878
1879 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
1880 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001881 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 pReqMsg->requestId, pReqMsg->sessionId);
1883
1884 /* Parse and fetch flush parameter */
1885 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001886 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001887 goto fail;
1888 }
1889 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001890 hdd_notice("Flush %d", pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891
1892 context = &ext_scan_context;
1893 spin_lock(&context->context_lock);
1894 context->request_id = pReqMsg->requestId;
1895 context->ignore_cached_results = false;
1896 INIT_COMPLETION(context->response_event);
1897 spin_unlock(&context->context_lock);
1898
1899 status = sme_get_cached_results(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301900 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001901 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001902 goto fail;
1903 }
1904
1905 rc = wait_for_completion_timeout(&context->response_event,
1906 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1907 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001908 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001909 retval = -ETIMEDOUT;
1910 spin_lock(&context->context_lock);
1911 context->ignore_cached_results = true;
1912 spin_unlock(&context->context_lock);
1913 } else {
1914 spin_lock(&context->context_lock);
1915 retval = context->response_status;
1916 spin_unlock(&context->context_lock);
1917 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301918 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 return retval;
1920
1921fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301922 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001923 return -EINVAL;
1924}
1925/*
1926 * done with short names for the global vendor params
1927 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1928 */
1929#undef PARAM_MAX
1930#undef PARAM_REQUEST_ID
1931#undef PARAM_FLUSH
1932
1933/**
1934 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1935 * @wiphy: wiphy pointer
1936 * @wdev: pointer to struct wireless_dev
1937 * @data: pointer to incoming NL vendor data
1938 * @data_len: length of @data
1939 *
1940 * This function parses the incoming NL vendor command data attributes and
1941 * invokes the SME Api and blocks on a completion variable.
1942 * Each WMI event with cached scan results data chunk results in
1943 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1944 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1945 *
1946 * If timeout happens before receiving all of the data, this function sets
1947 * a context variable @ignore_cached_results to %true, all of the next data
1948 * chunks are checked against this variable and dropped.
1949 *
1950 * Return: 0 on success; error number otherwise.
1951 */
1952int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1953 struct wireless_dev *wdev,
1954 const void *data, int data_len)
1955{
1956 int ret = 0;
1957
1958 cds_ssr_protect(__func__);
1959 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
1960 data_len);
1961 cds_ssr_unprotect(__func__);
1962
1963 return ret;
1964}
1965
1966/**
1967 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
1968 * @wiphy: Pointer to wireless phy
1969 * @wdev: Pointer to wireless device
1970 * @data: Pointer to data
1971 * @data_len: Data length
1972 *
1973 * Return: none
1974 */
1975static int
1976__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
1977 struct wireless_dev
1978 *wdev, const void *data,
1979 int data_len)
1980{
1981 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
1982 struct net_device *dev = wdev->netdev;
1983 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1984 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1985 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1986 1];
1987 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1988 + 1];
1989 struct nlattr *apTh;
1990 struct hdd_ext_scan_context *context;
1991 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301992 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 uint8_t i;
1994 int rem, retval;
1995 unsigned long rc;
1996
Jeff Johnson1f61b612016-02-12 16:28:33 -08001997 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998
Anurag Chouhan6d760662016-02-20 16:05:43 +05301999 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002000 hdd_err("Command not allowed in FTM mode");
2001 return -EPERM;
2002 }
2003
2004 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302005 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002006 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007
2008 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2009 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002010 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002011 return -EINVAL;
2012 }
2013
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302014 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002015 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002016 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002017 return -ENOMEM;
2018 }
2019
2020 /* Parse and fetch request Id */
2021 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002022 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023 goto fail;
2024 }
2025
2026 pReqMsg->requestId =
2027 nla_get_u32(tb
2028 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002029 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002030
2031 /* Parse and fetch number of APs */
2032 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002033 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002034 goto fail;
2035 }
2036 pReqMsg->numAp =
2037 nla_get_u32(tb
2038 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
2039 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002040 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041 pReqMsg->numAp, pReqMsg->sessionId);
2042
2043 /* Parse and fetch lost ap sample size */
2044 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002045 hdd_err("attr lost ap sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046 goto fail;
2047 }
2048
2049 pReqMsg->lost_ap_sample_size = nla_get_u32(
2050 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002051 hdd_notice("Lost ap sample size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 pReqMsg->lost_ap_sample_size);
2053
2054 i = 0;
2055 nla_for_each_nested(apTh,
2056 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2057 rem) {
2058 if (nla_parse
2059 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2060 nla_data(apTh), nla_len(apTh),
2061 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002062 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002063 goto fail;
2064 }
2065
2066 /* Parse and fetch MAC address */
2067 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002068 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002069 goto fail;
2070 }
2071 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2072 tb2
2073 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302074 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002075 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002076 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2077
2078 /* Parse and fetch low RSSI */
2079 if (!tb2
2080 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002081 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 goto fail;
2083 }
2084 pReqMsg->ap[i].low =
2085 nla_get_s32(tb2
2086 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002087 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002088
2089 /* Parse and fetch high RSSI */
2090 if (!tb2
2091 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002092 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093 goto fail;
2094 }
2095 pReqMsg->ap[i].high =
2096 nla_get_s32(tb2
2097 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002098 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002099
2100 i++;
2101 }
2102
2103 context = &ext_scan_context;
2104 spin_lock(&context->context_lock);
2105 INIT_COMPLETION(context->response_event);
2106 context->request_id = request_id = pReqMsg->requestId;
2107 spin_unlock(&context->context_lock);
2108
2109 status = sme_set_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302110 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002111 hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002112 goto fail;
2113 }
2114
2115 /* request was sent -- wait for the response */
2116 rc = wait_for_completion_timeout
2117 (&context->response_event,
2118 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2119
2120 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002121 hdd_err("sme_set_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002122 retval = -ETIMEDOUT;
2123 } else {
2124 spin_lock(&context->context_lock);
2125 if (context->request_id == request_id)
2126 retval = context->response_status;
2127 else
2128 retval = -EINVAL;
2129 spin_unlock(&context->context_lock);
2130 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302131 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002132 return retval;
2133
2134fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302135 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002136 return -EINVAL;
2137}
2138
2139/**
2140 * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist
2141 * @wiphy: Pointer to wiphy
2142 * @wdev: Pointer to wdev
2143 * @data: Pointer to data
2144 * @data_len: Data length
2145 *
2146 * Return: 0 for success, non-zero for failure
2147 */
2148int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2149 struct wireless_dev *wdev,
2150 const void *data, int data_len)
2151{
2152 int ret = 0;
2153
2154 cds_ssr_protect(__func__);
2155 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
2156 data_len);
2157 cds_ssr_unprotect(__func__);
2158
2159 return ret;
2160}
2161
2162
2163/**
2164 * __wlan_hdd_cfg80211_extscan_set_significant_change () - set significant change
2165 * @wiphy: Pointer to wireless phy
2166 * @wdev: Pointer to wireless device
2167 * @data: Pointer to data
2168 * @data_len: Data length
2169 *
2170 * Return: none
2171 */
2172static int
2173__wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2174 struct wireless_dev
2175 *wdev, const void *data,
2176 int data_len)
2177{
2178 tpSirExtScanSetSigChangeReqParams pReqMsg = NULL;
2179 struct net_device *dev = wdev->netdev;
2180 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2181 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2182 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2183 1];
2184 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2185 + 1];
2186 struct nlattr *apTh;
2187 struct hdd_ext_scan_context *context;
2188 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302189 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190 uint8_t i;
2191 int rem, retval;
2192 unsigned long rc;
2193
Jeff Johnson1f61b612016-02-12 16:28:33 -08002194 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195
Anurag Chouhan6d760662016-02-20 16:05:43 +05302196 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002197 hdd_err("Command not allowed in FTM mode");
2198 return -EPERM;
2199 }
2200
2201 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302202 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204
2205 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2206 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002207 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002208 return -EINVAL;
2209 }
2210
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302211 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002213 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 return -ENOMEM;
2215 }
2216
2217 /* Parse and fetch request Id */
2218 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002219 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220 goto fail;
2221 }
2222
2223 pReqMsg->requestId =
2224 nla_get_u32(tb
2225 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002226 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227
2228 /* Parse and fetch RSSI sample size */
2229 if (!tb
2230 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002231 hdd_err("attr RSSI sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232 goto fail;
2233 }
2234 pReqMsg->rssiSampleSize =
2235 nla_get_u32(tb
2236 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002237 hdd_notice("RSSI sample size %u", pReqMsg->rssiSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238
2239 /* Parse and fetch lost AP sample size */
2240 if (!tb
2241 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002242 hdd_err("attr lost AP sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002243 goto fail;
2244 }
2245 pReqMsg->lostApSampleSize =
2246 nla_get_u32(tb
2247 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002248 hdd_notice("Lost AP sample size %u", pReqMsg->lostApSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249
2250 /* Parse and fetch AP min breacing */
2251 if (!tb
2252 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002253 hdd_err("attr AP min breaching");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 goto fail;
2255 }
2256 pReqMsg->minBreaching =
2257 nla_get_u32(tb
2258 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002259 hdd_notice("AP min breaching %u", pReqMsg->minBreaching);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002260
2261 /* Parse and fetch number of APs */
2262 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002263 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264 goto fail;
2265 }
2266 pReqMsg->numAp =
2267 nla_get_u32(tb
2268 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
2269 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002270 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002271 pReqMsg->numAp, pReqMsg->sessionId);
2272
2273 i = 0;
2274 nla_for_each_nested(apTh,
2275 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2276 rem) {
2277 if (nla_parse
2278 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2279 nla_data(apTh), nla_len(apTh),
2280 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002281 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002282 goto fail;
2283 }
2284
2285 /* Parse and fetch MAC address */
2286 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002287 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002288 goto fail;
2289 }
2290 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2291 tb2
2292 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302293 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002294 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2296
2297 /* Parse and fetch low RSSI */
2298 if (!tb2
2299 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002300 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 goto fail;
2302 }
2303 pReqMsg->ap[i].low =
2304 nla_get_s32(tb2
2305 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002306 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002307
2308 /* Parse and fetch high RSSI */
2309 if (!tb2
2310 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002311 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 goto fail;
2313 }
2314 pReqMsg->ap[i].high =
2315 nla_get_s32(tb2
2316 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002317 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002318
2319 i++;
2320 }
2321
2322 context = &ext_scan_context;
2323 spin_lock(&context->context_lock);
2324 INIT_COMPLETION(context->response_event);
2325 context->request_id = request_id = pReqMsg->requestId;
2326 spin_unlock(&context->context_lock);
2327
2328 status = sme_set_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302329 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002330 hdd_err("sme_set_significant_change failed(err=%d)", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302331 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 return -EINVAL;
2333 }
2334
2335 /* request was sent -- wait for the response */
2336 rc = wait_for_completion_timeout(&context->response_event,
2337 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2338
2339 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002340 hdd_err("sme_set_significant_change timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002341 retval = -ETIMEDOUT;
2342 } else {
2343 spin_lock(&context->context_lock);
2344 if (context->request_id == request_id)
2345 retval = context->response_status;
2346 else
2347 retval = -EINVAL;
2348 spin_unlock(&context->context_lock);
2349 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302350 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 return retval;
2352
2353fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302354 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355 return -EINVAL;
2356}
2357
2358/**
2359 * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
2360 * @wiphy: Pointer to wireless phy
2361 * @wdev: Pointer to wireless device
2362 * @data: Pointer to data
2363 * @data_len: Data length
2364 *
2365 * Return: 0 on success, negative errno on failure
2366 */
2367int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2368 struct wireless_dev *wdev,
2369 const void *data, int data_len)
2370{
2371 int ret = 0;
2372
2373 cds_ssr_protect(__func__);
2374 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev,
2375 data, data_len);
2376 cds_ssr_unprotect(__func__);
2377
2378 return ret;
2379}
2380
2381/**
2382 * hdd_remove_dsrc_channels () - remove dsrc chanels
2383 * @wiphy: Pointer to wireless phy
2384 * @chan_list: channel list
2385 * @num_channels: number of channels
2386 *
2387 * Return: none
2388 */
2389void hdd_remove_dsrc_channels(struct wiphy *wiphy, uint32_t *chan_list,
2390 uint8_t *num_channels)
2391{
2392 uint8_t num_chan_temp = 0;
2393 int i;
2394
2395 for (i = 0; i < *num_channels; i++) {
2396 if (!cds_is_dsrc_channel(chan_list[i])) {
2397 chan_list[num_chan_temp] = chan_list[i];
2398 num_chan_temp++;
2399 }
2400 }
2401
2402 *num_channels = num_chan_temp;
2403}
2404
2405/**
2406 * hdd_remove_indoor_channels () - remove indoor channels
2407 * @wiphy: Pointer to wireless phy
2408 * @chan_list: channel list
2409 * @num_channels: number of channels
2410 *
2411 * Return: none
2412 */
2413#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
2414void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2415 uint8_t *num_channels)
2416{
2417 uint8_t num_chan_temp = 0;
2418 int i, j, k;
2419
2420 for (i = 0; i < *num_channels; i++)
2421 for (j = 0; j < IEEE80211_NUM_BANDS; j++) {
2422 if (wiphy->bands[j] == NULL)
2423 continue;
2424 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
2425 if ((chan_list[i] ==
2426 wiphy->bands[j]->channels[k].center_freq)
2427 && (!(wiphy->bands[j]->channels[k].flags &
2428 IEEE80211_CHAN_INDOOR_ONLY))
2429 ) {
2430 chan_list[num_chan_temp] = chan_list[i];
2431 num_chan_temp++;
2432 }
2433 }
2434 }
2435
2436 *num_channels = num_chan_temp;
2437}
2438#else
2439void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2440 uint8_t *num_channels)
2441{
2442 *num_channels = 0;
2443}
2444#endif
2445
2446/**
2447 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
2448 * @wiphy: Pointer to wireless phy
2449 * @wdev: Pointer to wireless device
2450 * @data: Pointer to data
2451 * @data_len: Data length
2452 *
2453 * Return: none
2454 */
2455static int
2456__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2457 struct wireless_dev
2458 *wdev, const void *data,
2459 int data_len)
2460{
2461 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2462 struct net_device *dev = wdev->netdev;
2463 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2464 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2465 uint8_t num_channels = 0;
2466 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2467 1];
2468 uint32_t requestId, maxChannels;
2469 tWifiBand wifiBand;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302470 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002471 struct sk_buff *reply_skb;
2472 uint8_t i;
2473 int ret;
2474
Jeff Johnson1f61b612016-02-12 16:28:33 -08002475 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476
Anurag Chouhan6d760662016-02-20 16:05:43 +05302477 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 hdd_err("Command not allowed in FTM mode");
2479 return -EPERM;
2480 }
2481
2482 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302483 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485
2486 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2487 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002488 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 return -EINVAL;
2490 }
2491
2492 /* Parse and fetch request Id */
2493 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002494 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 return -EINVAL;
2496 }
2497 requestId =
2498 nla_get_u32(tb
2499 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002500 hdd_notice("Req Id %d", requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002501
2502 /* Parse and fetch wifi band */
2503 if (!tb
2504 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002505 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 return -EINVAL;
2507 }
2508 wifiBand =
2509 nla_get_u32(tb
2510 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002511 hdd_notice("Wifi band %d", wifiBand);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512
2513 if (!tb
2514 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002515 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 return -EINVAL;
2517 }
2518 maxChannels =
2519 nla_get_u32(tb
2520 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002521 hdd_notice("Max channels %d", maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 status = sme_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal),
2523 wifiBand, chan_list,
2524 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302525 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002526 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 status);
2528 return -EINVAL;
2529 }
2530
Anurag Chouhan6d760662016-02-20 16:05:43 +05302531 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532
2533 hdd_remove_dsrc_channels(wiphy, chan_list, &num_channels);
2534
Krunal Sonibe766b02016-03-10 13:00:44 -08002535 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 !strncmp(hdd_get_fwpath(), "ap", 2))
2537 hdd_remove_indoor_channels(wiphy, chan_list, &num_channels);
2538
Jeff Johnson630f9e72016-07-25 12:00:12 -07002539 hdd_notice("Number of channels %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540 for (i = 0; i < num_channels; i++)
Jeff Johnson630f9e72016-07-25 12:00:12 -07002541 hdd_notice("Channel: %u ", chan_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002542
2543 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2544 sizeof(u32) *
2545 num_channels +
2546 NLMSG_HDRLEN);
2547
2548 if (reply_skb) {
2549 if (nla_put_u32(reply_skb,
2550 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2551 num_channels) ||
2552 nla_put(reply_skb,
2553 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2554 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002555 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002556 kfree_skb(reply_skb);
2557 return -EINVAL;
2558 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302559 ret = cfg80211_vendor_cmd_reply(reply_skb);
2560 EXIT();
2561 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 }
2563
Jeff Johnson630f9e72016-07-25 12:00:12 -07002564 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002565 return -EINVAL;
2566}
2567
2568/**
2569 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2570 * @wiphy: Pointer to wireless phy
2571 * @wdev: Pointer to wireless device
2572 * @data: Pointer to data
2573 * @data_len: Data length
2574 *
2575 * Return: 0 on success, negative errno on failure
2576 */
2577int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2578 struct wireless_dev *wdev,
2579 const void *data, int data_len)
2580{
2581 int ret = 0;
2582
2583 cds_ssr_protect(__func__);
2584 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2585 data_len);
2586 cds_ssr_unprotect(__func__);
2587
2588 return ret;
2589}
2590
2591/**
2592 * hdd_extscan_update_dwell_time_limits() - update dwell times
2593 * @req_msg: Pointer to request message
2594 * @bkt_idx: Index of current bucket being processed
2595 * @active_min: minimum active dwell time
2596 * @active_max: maximum active dwell time
2597 * @passive_min: minimum passive dwell time
2598 * @passive_max: maximum passive dwell time
2599 *
2600 * Return: none
2601 */
2602static void hdd_extscan_update_dwell_time_limits(
2603 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2604 uint32_t active_min, uint32_t active_max,
2605 uint32_t passive_min, uint32_t passive_max)
2606{
2607 /* update per-bucket dwell times */
2608 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2609 active_min) {
2610 req_msg->buckets[bkt_idx].min_dwell_time_active =
2611 active_min;
2612 }
2613 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2614 active_max) {
2615 req_msg->buckets[bkt_idx].max_dwell_time_active =
2616 active_max;
2617 }
2618 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2619 passive_min) {
2620 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2621 passive_min;
2622 }
2623 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2624 passive_max) {
2625 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2626 passive_max;
2627 }
2628 /* update dwell-time across all buckets */
2629 if (req_msg->min_dwell_time_active >
2630 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2631 req_msg->min_dwell_time_active =
2632 req_msg->buckets[bkt_idx].min_dwell_time_active;
2633 }
2634 if (req_msg->max_dwell_time_active <
2635 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2636 req_msg->max_dwell_time_active =
2637 req_msg->buckets[bkt_idx].max_dwell_time_active;
2638 }
2639 if (req_msg->min_dwell_time_passive >
2640 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2641 req_msg->min_dwell_time_passive =
2642 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2643 }
2644 if (req_msg->max_dwell_time_passive >
2645 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2646 req_msg->max_dwell_time_passive =
2647 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2648 }
2649}
2650
2651/**
2652 * hdd_extscan_channel_max_reached() - channel max reached
2653 * @req: extscan request structure
2654 * @total_channels: total number of channels
2655 *
2656 * Return: true if total channels reached max, false otherwise
2657 */
2658static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2659 uint8_t total_channels)
2660{
2661 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2662 hdd_warn(
2663 "max #of channels %d reached, take only first %d bucket(s)",
2664 total_channels, req->numBuckets);
2665 return true;
2666 }
2667 return false;
2668}
2669
2670/**
2671 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2672 * @hdd_ctx: HDD global context
2673 * @req_msg: Pointer to request structure
2674 * @tb: pointer to NL attributes
2675 *
2676 * Return: 0 on success; error number otherwise
2677 */
2678static int hdd_extscan_start_fill_bucket_channel_spec(
2679 hdd_context_t *hdd_ctx,
2680 tpSirWifiScanCmdReqParams req_msg,
2681 struct nlattr **tb)
2682{
2683 struct nlattr *bucket[
2684 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2685 struct nlattr *channel[
2686 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2687 struct nlattr *buckets;
2688 struct nlattr *channels;
2689 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302690 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002691 uint8_t bkt_index, j, num_channels, total_channels = 0;
2692 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2693
2694 uint32_t min_dwell_time_active_bucket =
2695 hdd_ctx->config->extscan_active_max_chn_time;
2696 uint32_t max_dwell_time_active_bucket =
2697 hdd_ctx->config->extscan_active_max_chn_time;
2698 uint32_t min_dwell_time_passive_bucket =
2699 hdd_ctx->config->extscan_passive_max_chn_time;
2700 uint32_t max_dwell_time_passive_bucket =
2701 hdd_ctx->config->extscan_passive_max_chn_time;
2702
2703 bkt_index = 0;
2704 req_msg->min_dwell_time_active =
2705 req_msg->max_dwell_time_active =
2706 hdd_ctx->config->extscan_active_max_chn_time;
2707
2708 req_msg->min_dwell_time_passive =
2709 req_msg->max_dwell_time_passive =
2710 hdd_ctx->config->extscan_passive_max_chn_time;
2711 req_msg->numBuckets = 0;
2712
2713 nla_for_each_nested(buckets,
2714 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
2715 if (nla_parse(bucket,
2716 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2717 nla_data(buckets), nla_len(buckets), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002718 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002719 return -EINVAL;
2720 }
2721
2722 /* Parse and fetch bucket spec */
2723 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002724 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002725 return -EINVAL;
2726 }
2727 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2728 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002729 hdd_notice("Bucket spec Index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002730 req_msg->buckets[bkt_index].bucket);
2731
2732 /* Parse and fetch wifi band */
2733 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002734 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 return -EINVAL;
2736 }
2737 req_msg->buckets[bkt_index].band = nla_get_u8(
2738 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002739 hdd_notice("Wifi band %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 req_msg->buckets[bkt_index].band);
2741
2742 /* Parse and fetch period */
2743 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002744 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002745 return -EINVAL;
2746 }
2747 req_msg->buckets[bkt_index].period = nla_get_u32(
2748 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002749 hdd_notice("period %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 req_msg->buckets[bkt_index].period);
2751
2752 /* Parse and fetch report events */
2753 if (!bucket[
2754 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002755 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 return -EINVAL;
2757 }
2758 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2759 bucket[
2760 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002761 hdd_notice("report events %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002762 req_msg->buckets[bkt_index].reportEvents);
2763
2764 /* Parse and fetch max period */
2765 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002766 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767 return -EINVAL;
2768 }
2769 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2770 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002771 hdd_notice("max period %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 req_msg->buckets[bkt_index].max_period);
2773
2774 /* Parse and fetch exponent */
2775 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002776 hdd_err("attr exponent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 return -EINVAL;
2778 }
2779 req_msg->buckets[bkt_index].exponent = nla_get_u32(
2780 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_EXPONENT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002781 hdd_notice("exponent %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782 req_msg->buckets[bkt_index].exponent);
2783
2784 /* Parse and fetch step count */
2785 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002786 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 return -EINVAL;
2788 }
2789 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2790 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002791 hdd_notice("Step count %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002792 req_msg->buckets[bkt_index].step_count);
2793
2794 /* start with known good values for bucket dwell times */
2795 req_msg->buckets[bkt_index].min_dwell_time_active =
2796 req_msg->buckets[bkt_index].max_dwell_time_active =
2797 hdd_ctx->config->extscan_active_max_chn_time;
2798
2799 req_msg->buckets[bkt_index].min_dwell_time_passive =
2800 req_msg->buckets[bkt_index].max_dwell_time_passive =
2801 hdd_ctx->config->extscan_passive_max_chn_time;
2802
2803 /* Framework shall pass the channel list if the input WiFi band
2804 * is WIFI_BAND_UNSPECIFIED.
2805 * If the input WiFi band is specified (any value other than
2806 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2807 */
2808 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2809 if (hdd_extscan_channel_max_reached(req_msg,
2810 total_channels))
2811 return 0;
2812
2813 num_channels = 0;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002814 hdd_notice("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002815 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2816 req_msg->buckets[bkt_index].band,
2817 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302818 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002819 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 status);
2821 return -EINVAL;
2822 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07002823 hdd_notice("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824 num_channels);
2825
2826 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302827 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828 (WLAN_EXTSCAN_MAX_CHANNELS -
2829 total_channels));
2830 hdd_info("Adj Num channels/bucket: %d total_channels: %d",
2831 req_msg->buckets[bkt_index].numChannels,
2832 total_channels);
2833 total_channels +=
2834 req_msg->buckets[bkt_index].numChannels;
2835
2836 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2837 j++) {
2838 req_msg->buckets[bkt_index].channels[j].channel =
2839 chan_list[j];
2840 req_msg->buckets[bkt_index].channels[j].
2841 chnlClass = 0;
2842 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2843 cds_freq_to_chan(chan_list[j]))) {
2844 req_msg->buckets[bkt_index].channels[j].
2845 passive = 1;
2846 req_msg->buckets[bkt_index].channels[j].
2847 dwellTimeMs =
2848 hdd_ctx->config->
2849 extscan_passive_max_chn_time;
2850 /* reconfigure per-bucket dwell time */
2851 if (min_dwell_time_passive_bucket >
2852 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2853 min_dwell_time_passive_bucket =
2854 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2855 }
2856 if (max_dwell_time_passive_bucket <
2857 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2858 max_dwell_time_passive_bucket =
2859 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2860 }
2861
2862 } else {
2863 req_msg->buckets[bkt_index].channels[j].
2864 passive = 0;
2865 req_msg->buckets[bkt_index].channels[j].
2866 dwellTimeMs =
2867 hdd_ctx->config->extscan_active_max_chn_time;
2868 /* reconfigure per-bucket dwell times */
2869 if (min_dwell_time_active_bucket >
2870 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2871 min_dwell_time_active_bucket =
2872 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2873 }
2874 if (max_dwell_time_active_bucket <
2875 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2876 max_dwell_time_active_bucket =
2877 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2878 }
2879
2880 }
2881
Jeff Johnson630f9e72016-07-25 12:00:12 -07002882 hdd_notice("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 req_msg->buckets[bkt_index].channels[j].channel,
2884 req_msg->buckets[bkt_index].channels[j].passive,
2885 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2886 req_msg->buckets[bkt_index].channels[j].chnlClass);
2887 }
2888
2889 hdd_extscan_update_dwell_time_limits(
2890 req_msg, bkt_index,
2891 min_dwell_time_active_bucket,
2892 max_dwell_time_active_bucket,
2893 min_dwell_time_passive_bucket,
2894 max_dwell_time_passive_bucket);
2895
Jeff Johnson630f9e72016-07-25 12:00:12 -07002896 hdd_notice("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 bkt_index,
2898 req_msg->buckets[bkt_index].min_dwell_time_active,
2899 req_msg->buckets[bkt_index].max_dwell_time_active,
2900 req_msg->buckets[bkt_index].min_dwell_time_passive,
2901 req_msg->buckets[bkt_index].max_dwell_time_passive);
2902
2903 bkt_index++;
2904 req_msg->numBuckets++;
2905 continue;
2906 }
2907
2908 /* Parse and fetch number of channels */
2909 if (!bucket[
2910 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002911 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 return -EINVAL;
2913 }
2914 req_msg->buckets[bkt_index].numChannels =
2915 nla_get_u32(bucket[
2916 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
2917 hdd_info("before trimming: num channels %d",
2918 req_msg->buckets[bkt_index].numChannels);
2919
2920 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302921 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
2923 hdd_info("Num channels/bucket: %d total_channels: %d",
2924 req_msg->buckets[bkt_index].numChannels,
2925 total_channels);
2926 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
2927 return 0;
2928
2929 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002930 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 return -EINVAL;
2932 }
2933
2934 j = 0;
2935 nla_for_each_nested(channels,
2936 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07002937 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
2938 hdd_extscan_channel_max_reached(req_msg,
2939 total_channels))
2940 break;
2941
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 if (nla_parse(channel,
2943 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2944 nla_data(channels), nla_len(channels),
2945 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002946 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 return -EINVAL;
2948 }
2949
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 /* Parse and fetch channel */
2951 if (!channel[
2952 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002953 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 return -EINVAL;
2955 }
2956 req_msg->buckets[bkt_index].channels[j].channel =
2957 nla_get_u32(channel[
2958 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002959 hdd_notice("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002960 req_msg->buckets[bkt_index].channels[j].channel);
2961
2962 /* Parse and fetch dwell time */
2963 if (!channel[
2964 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002965 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966 return -EINVAL;
2967 }
2968 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2969 nla_get_u32(channel[
2970 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
2971
2972 /* Override dwell time if required */
2973 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
2974 hdd_ctx->config->extscan_active_min_chn_time ||
2975 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
2976 hdd_ctx->config->extscan_active_max_chn_time) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002977 hdd_notice("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002978 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
2979
2980 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2981 cds_freq_to_chan(
2982 req_msg->buckets[bkt_index].channels[j].channel))) {
2983 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2984 hdd_ctx->config->extscan_passive_max_chn_time;
2985 } else {
2986 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2987 hdd_ctx->config->extscan_active_max_chn_time;
2988 }
2989 }
2990
Jeff Johnson630f9e72016-07-25 12:00:12 -07002991 hdd_notice("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002992 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
2993
2994 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2995 cds_freq_to_chan(
2996 req_msg->buckets[bkt_index].channels[j].channel))) {
2997 if (min_dwell_time_passive_bucket >
2998 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2999 min_dwell_time_passive_bucket =
3000 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3001 }
3002 if (max_dwell_time_passive_bucket <
3003 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3004 max_dwell_time_passive_bucket =
3005 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3006 }
3007 } else {
3008 if (min_dwell_time_active_bucket >
3009 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3010 min_dwell_time_active_bucket =
3011 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3012 }
3013 if (max_dwell_time_active_bucket <
3014 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3015 max_dwell_time_active_bucket =
3016 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3017 }
3018 }
3019
3020 /* Parse and fetch channel spec passive */
3021 if (!channel[
3022 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003023 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 return -EINVAL;
3025 }
3026 req_msg->buckets[bkt_index].channels[j].passive =
3027 nla_get_u8(channel[
3028 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003029 hdd_notice("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 req_msg->buckets[bkt_index].channels[j].passive);
3031 /* Override scan type if required */
3032 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3033 cds_freq_to_chan(
3034 req_msg->buckets[bkt_index].channels[j].channel))) {
3035 req_msg->buckets[bkt_index].channels[j].passive = true;
3036 } else {
3037 req_msg->buckets[bkt_index].channels[j].passive = false;
3038 }
3039 j++;
3040 total_channels++;
3041 }
3042
3043 hdd_extscan_update_dwell_time_limits(
3044 req_msg, bkt_index,
3045 min_dwell_time_active_bucket,
3046 max_dwell_time_active_bucket,
3047 min_dwell_time_passive_bucket,
3048 max_dwell_time_passive_bucket);
3049
Jeff Johnson630f9e72016-07-25 12:00:12 -07003050 hdd_notice("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003051 bkt_index,
3052 req_msg->buckets[bkt_index].min_dwell_time_active,
3053 req_msg->buckets[bkt_index].max_dwell_time_active,
3054 req_msg->buckets[bkt_index].min_dwell_time_passive,
3055 req_msg->buckets[bkt_index].max_dwell_time_passive);
3056
3057 bkt_index++;
3058 req_msg->numBuckets++;
3059 }
3060
Jeff Johnson630f9e72016-07-25 12:00:12 -07003061 hdd_notice("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003062 req_msg->min_dwell_time_active,
3063 req_msg->max_dwell_time_active,
3064 req_msg->min_dwell_time_passive,
3065 req_msg->max_dwell_time_passive);
3066
3067 return 0;
3068}
3069
3070/*
3071 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3072 * @config_flags - [input] configuration flags.
3073 *
3074 * This function maps user space received configuration flags to
3075 * driver representation.
3076 *
3077 * Return: configuration flags
3078 */
3079static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3080{
3081 uint32_t configuration_flags = 0;
3082
3083 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3084 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3085
3086 return configuration_flags;
3087}
3088
3089/*
3090 * define short names for the global vendor params
3091 * used by __wlan_hdd_cfg80211_extscan_start()
3092 */
3093#define PARAM_MAX \
3094 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3095#define PARAM_REQUEST_ID \
3096 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3097#define PARAM_BASE_PERIOD \
3098 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3099#define PARAM_MAX_AP_PER_SCAN \
3100 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3101#define PARAM_RPT_THRHLD_PERCENT \
3102 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3103#define PARAM_RPT_THRHLD_NUM_SCANS \
3104 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3105#define PARAM_NUM_BUCKETS \
3106 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3107#define PARAM_CONFIG_FLAGS \
3108 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3109
3110/**
3111 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3112 * @wiphy: Pointer to wireless phy
3113 * @wdev: Pointer to wireless device
3114 * @data: Pointer to data
3115 * @data_len: Length of @data
3116 *
3117 * Return: 0 on success; error number otherwise
3118 */
3119static int
3120__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3121 struct wireless_dev *wdev,
3122 const void *data,
3123 int data_len)
3124{
3125 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3126 struct net_device *dev = wdev->netdev;
3127 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3128 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3129 struct nlattr *tb[PARAM_MAX + 1];
3130 struct hdd_ext_scan_context *context;
3131 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303132 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003133 int retval;
3134 unsigned long rc;
3135
Jeff Johnson1f61b612016-02-12 16:28:33 -08003136 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137
Anurag Chouhan6d760662016-02-20 16:05:43 +05303138 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003139 hdd_err("Command not allowed in FTM mode");
3140 return -EPERM;
3141 }
3142
3143 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303144 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003145 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146
3147 if (nla_parse(tb, PARAM_MAX, data, data_len,
3148 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003149 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150 return -EINVAL;
3151 }
3152
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303153 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003155 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003156 return -ENOMEM;
3157 }
3158
3159 /* Parse and fetch request Id */
3160 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003161 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003162 goto fail;
3163 }
3164
3165 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3166 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003167 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 pReqMsg->requestId,
3169 pReqMsg->sessionId);
3170
3171 /* Parse and fetch base period */
3172 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003173 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 goto fail;
3175 }
3176 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003177 hdd_notice("Base Period %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 pReqMsg->basePeriod);
3179
3180 /* Parse and fetch max AP per scan */
3181 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003182 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003183 goto fail;
3184 }
3185 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003186 hdd_notice("Max AP per Scan %d", pReqMsg->maxAPperScan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187
3188 /* Parse and fetch report threshold percent */
3189 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003190 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 goto fail;
3192 }
3193 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003194 hdd_notice("Report Threshold percent %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 pReqMsg->report_threshold_percent);
3196
3197 /* Parse and fetch report threshold num scans */
3198 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003199 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003200 goto fail;
3201 }
3202 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003203 hdd_notice("Report Threshold num scans %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204 pReqMsg->report_threshold_num_scans);
3205
3206 /* Parse and fetch number of buckets */
3207 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003208 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209 goto fail;
3210 }
3211 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3212 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3213 hdd_warn("Exceeded MAX number of buckets: %d",
3214 WLAN_EXTSCAN_MAX_BUCKETS);
3215 }
3216 hdd_info("Input: Number of Buckets %d", num_buckets);
3217
3218 /* This is optional attribute, if not present set it to 0 */
3219 if (!tb[PARAM_CONFIG_FLAGS])
3220 pReqMsg->configuration_flags = 0;
3221 else
3222 pReqMsg->configuration_flags =
3223 hdd_extscan_map_usr_drv_config_flags(
3224 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3225
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303226 pReqMsg->extscan_adaptive_dwell_mode =
3227 pHddCtx->config->extscan_adaptive_dwell_mode;
3228
Jeff Johnson630f9e72016-07-25 12:00:12 -07003229 hdd_notice("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 pReqMsg->configuration_flags);
3231
3232 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003233 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 goto fail;
3235 }
3236
3237 if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb))
3238 goto fail;
3239
3240 context = &ext_scan_context;
3241 spin_lock(&context->context_lock);
3242 INIT_COMPLETION(context->response_event);
3243 context->request_id = request_id = pReqMsg->requestId;
3244 spin_unlock(&context->context_lock);
3245
3246 status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303247 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003248 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003249 goto fail;
3250 }
3251
Anurag Chouhan50220ce2016-02-18 20:11:33 +05303252 pHddCtx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Jeff Johnson630f9e72016-07-25 12:00:12 -07003253 hdd_notice("Timestamp since boot: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003254 pHddCtx->ext_scan_start_since_boot);
3255
3256 /* request was sent -- wait for the response */
3257 rc = wait_for_completion_timeout(&context->response_event,
3258 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3259
3260 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003261 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003262 retval = -ETIMEDOUT;
3263 } else {
3264 spin_lock(&context->context_lock);
3265 if (context->request_id == request_id)
3266 retval = context->response_status;
3267 else
3268 retval = -EINVAL;
3269 spin_unlock(&context->context_lock);
3270 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303271 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003272 return retval;
3273
3274fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303275 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003276 return -EINVAL;
3277}
3278/*
3279 * done with short names for the global vendor params
3280 * used by __wlan_hdd_cfg80211_extscan_start()
3281 */
3282#undef PARAM_MAX
3283#undef PARAM_REQUEST_ID
3284#undef PARAM_BASE_PERIOD
3285#undef PARAMS_MAX_AP_PER_SCAN
3286#undef PARAMS_RPT_THRHLD_PERCENT
3287#undef PARAMS_RPT_THRHLD_NUM_SCANS
3288#undef PARAMS_NUM_BUCKETS
3289#undef PARAM_CONFIG_FLAGS
3290
3291/**
3292 * wlan_hdd_cfg80211_extscan_start() - start extscan
3293 * @wiphy: Pointer to wireless phy.
3294 * @wdev: Pointer to wireless device.
3295 * @data: Pointer to input data.
3296 * @data_len: Length of @data.
3297 *
3298 * Return: 0 on success, negative errno on failure
3299 */
3300int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3301 struct wireless_dev *wdev,
3302 const void *data, int data_len)
3303{
3304 int ret = 0;
3305
3306 cds_ssr_protect(__func__);
3307 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3308 cds_ssr_unprotect(__func__);
3309
3310 return ret;
3311}
3312
3313
3314/*
3315 * define short names for the global vendor params
3316 * used by __wlan_hdd_cfg80211_extscan_stop()
3317 */
3318#define PARAM_MAX \
3319 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3320#define PARAM_REQUEST_ID \
3321 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3322
3323/**
3324 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3325 * @wiphy: Pointer to wireless phy
3326 * @wdev: Pointer to wireless device
3327 * @data: Pointer to data
3328 * @data_len: Data length
3329 *
3330 * Return: none
3331 */
3332static int
3333__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3334 struct wireless_dev *wdev,
3335 const void *data, int data_len)
3336{
3337 tpSirExtScanStopReqParams pReqMsg = NULL;
3338 struct net_device *dev = wdev->netdev;
3339 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3340 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3341 struct nlattr *tb[PARAM_MAX + 1];
3342 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303343 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344 uint32_t request_id;
3345 int retval;
3346 unsigned long rc;
3347
Jeff Johnson1f61b612016-02-12 16:28:33 -08003348 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003349
Anurag Chouhan6d760662016-02-20 16:05:43 +05303350 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003351 hdd_err("Command not allowed in FTM mode");
3352 return -EPERM;
3353 }
3354
3355 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303356 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003357 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003358
3359 if (nla_parse(tb, PARAM_MAX, data, data_len,
3360 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003361 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362 return -EINVAL;
3363 }
3364
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303365 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003366 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003367 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003368 return -ENOMEM;
3369 }
3370
3371 /* Parse and fetch request Id */
3372 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003373 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003374 goto fail;
3375 }
3376
3377 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3378 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003379 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003380 pReqMsg->requestId, pReqMsg->sessionId);
3381
3382 context = &ext_scan_context;
3383 spin_lock(&context->context_lock);
3384 INIT_COMPLETION(context->response_event);
3385 context->request_id = request_id = pReqMsg->requestId;
3386 spin_unlock(&context->context_lock);
3387
3388 status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303389 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003390 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003391 goto fail;
3392 }
3393
3394 /* request was sent -- wait for the response */
3395 rc = wait_for_completion_timeout(&context->response_event,
3396 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3397
3398 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003399 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 retval = -ETIMEDOUT;
3401 } else {
3402 spin_lock(&context->context_lock);
3403 if (context->request_id == request_id)
3404 retval = context->response_status;
3405 else
3406 retval = -EINVAL;
3407 spin_unlock(&context->context_lock);
3408 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303409 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003410 return retval;
3411
3412fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303413 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003414 return -EINVAL;
3415}
3416/*
3417 * done with short names for the global vendor params
3418 * used by wlan_hdd_cfg80211_extscan_stop()
3419 */
3420#undef PARAM_MAX
3421#undef PARAM_REQUEST_ID
3422
3423
3424/**
3425 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3426 * @wiphy: Pointer to wireless phy.
3427 * @wdev: Pointer to wireless device.
3428 * @data: Pointer to input data.
3429 * @data_len: Length of @data.
3430 *
3431 * Return: 0 on success, negative errno on failure
3432 */
3433int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3434 struct wireless_dev *wdev,
3435 const void *data, int data_len)
3436{
3437 int ret = 0;
3438
3439 cds_ssr_protect(__func__);
3440 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3441 cds_ssr_unprotect(__func__);
3442
3443 return ret;
3444}
3445
3446
3447/**
3448 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3449 * @wiphy: Pointer to wireless phy
3450 * @wdev: Pointer to wireless device
3451 * @data: Pointer to data
3452 * @data_len: Data length
3453 *
3454 * Return: none
3455 */
3456static int
3457__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3458 struct wireless_dev
3459 *wdev, const void *data,
3460 int data_len)
3461{
3462 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3463 struct net_device *dev = wdev->netdev;
3464 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3465 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3466 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3467 1];
3468 struct hdd_ext_scan_context *context;
3469 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303470 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003471 int retval;
3472 unsigned long rc;
3473
Jeff Johnson1f61b612016-02-12 16:28:33 -08003474 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003475
Anurag Chouhan6d760662016-02-20 16:05:43 +05303476 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003477 hdd_err("Command not allowed in FTM mode");
3478 return -EPERM;
3479 }
3480
3481 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303482 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003483 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484
3485 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3486 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003487 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003488 return -EINVAL;
3489 }
3490
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303491 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003493 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003494 return -ENOMEM;
3495 }
3496
3497 /* Parse and fetch request Id */
3498 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003499 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 goto fail;
3501 }
3502
3503 pReqMsg->requestId =
3504 nla_get_u32(tb
3505 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3506 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003507 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508 pReqMsg->requestId, pReqMsg->sessionId);
3509
3510 context = &ext_scan_context;
3511 spin_lock(&context->context_lock);
3512 INIT_COMPLETION(context->response_event);
3513 context->request_id = request_id = pReqMsg->requestId;
3514 spin_unlock(&context->context_lock);
3515
3516 status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303517 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003518 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 goto fail;
3520 }
3521
3522 /* request was sent -- wait for the response */
3523 rc = wait_for_completion_timeout
3524 (&context->response_event,
3525 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3526 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003527 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528 retval = -ETIMEDOUT;
3529 } else {
3530 spin_lock(&context->context_lock);
3531 if (context->request_id == request_id)
3532 retval = context->response_status;
3533 else
3534 retval = -EINVAL;
3535 spin_unlock(&context->context_lock);
3536 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303537 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538 return retval;
3539
3540fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303541 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003542 return -EINVAL;
3543}
3544
3545/**
3546 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3547 * @wiphy: Pointer to wireless phy
3548 * @wdev: Pointer to wireless device
3549 * @data: Pointer to data
3550 * @data_len: Data length
3551 *
3552 * Return: 0 on success, negative errno on failure
3553 */
3554int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3555 struct wireless_dev *wdev,
3556 const void *data, int data_len)
3557{
3558 int ret = 0;
3559
3560 cds_ssr_protect(__func__);
3561 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3562 data, data_len);
3563 cds_ssr_unprotect(__func__);
3564
3565 return ret;
3566}
3567
3568/**
3569 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3570 * reset significant change
3571 * @wiphy: Pointer to wireless phy
3572 * @wdev: Pointer to wireless device
3573 * @data: Pointer to data
3574 * @data_len: Data length
3575 *
3576 * Return: none
3577 */
3578static int
3579__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3580 *wiphy,
3581 struct
3582 wireless_dev
3583 *wdev, const void *data,
3584 int data_len)
3585{
3586 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3587 struct net_device *dev = wdev->netdev;
3588 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3589 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3590 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3591 1];
3592 struct hdd_ext_scan_context *context;
3593 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303594 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003595 int retval;
3596 unsigned long rc;
3597
Jeff Johnson1f61b612016-02-12 16:28:33 -08003598 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003599
Anurag Chouhan6d760662016-02-20 16:05:43 +05303600 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003601 hdd_err("Command not allowed in FTM mode");
3602 return -EPERM;
3603 }
3604
3605 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303606 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003608
3609 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3610 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003611 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003612 return -EINVAL;
3613 }
3614
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303615 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003616 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003617 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003618 return -ENOMEM;
3619 }
3620
3621 /* Parse and fetch request Id */
3622 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003623 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003624 goto fail;
3625 }
3626
3627 pReqMsg->requestId =
3628 nla_get_u32(tb
3629 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3630 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003631 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 pReqMsg->requestId, pReqMsg->sessionId);
3633
3634 context = &ext_scan_context;
3635 spin_lock(&context->context_lock);
3636 INIT_COMPLETION(context->response_event);
3637 context->request_id = request_id = pReqMsg->requestId;
3638 spin_unlock(&context->context_lock);
3639
3640 status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303641 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003642 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003643 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303644 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003645 return -EINVAL;
3646 }
3647
3648 /* request was sent -- wait for the response */
3649 rc = wait_for_completion_timeout(&context->response_event,
3650 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3651
3652 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003653 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 retval = -ETIMEDOUT;
3655 } else {
3656 spin_lock(&context->context_lock);
3657 if (context->request_id == request_id)
3658 retval = context->response_status;
3659 else
3660 retval = -EINVAL;
3661 spin_unlock(&context->context_lock);
3662 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303663 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003664 return retval;
3665
3666fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303667 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003668 return -EINVAL;
3669}
3670
3671/**
3672 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3673 * change
3674 * @wiphy: Pointer to wireless phy
3675 * @wdev: Pointer to wireless device
3676 * @data: Pointer to data
3677 * @data_len: Data length
3678 *
3679 * Return: 0 on success, negative errno on failure
3680 */
3681int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3682 struct wireless_dev *wdev,
3683 const void *data, int data_len)
3684{
3685 int ret = 0;
3686
3687 cds_ssr_protect(__func__);
3688 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3689 data, data_len);
3690 cds_ssr_unprotect(__func__);
3691
3692 return ret;
3693}
3694
3695
3696/**
3697 * hdd_extscan_epno_fill_network_list() - epno fill network list
3698 * @hddctx: HDD context
3699 * @req_msg: request message
3700 * @tb: vendor attribute table
3701 *
3702 * This function reads the network block NL vendor attributes from %tb and
3703 * fill in the epno request message.
3704 *
3705 * Return: 0 on success, error number otherwise
3706 */
3707static int hdd_extscan_epno_fill_network_list(
3708 hdd_context_t *hddctx,
3709 struct wifi_epno_params *req_msg,
3710 struct nlattr **tb)
3711{
3712 struct nlattr *network[
3713 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3714 struct nlattr *networks;
3715 int rem1, ssid_len;
3716 uint8_t index, *ssid;
3717
3718 index = 0;
3719 nla_for_each_nested(networks,
3720 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3721 rem1) {
3722 if (nla_parse(network,
3723 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3724 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003725 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003726 return -EINVAL;
3727 }
3728
3729 /* Parse and fetch ssid */
3730 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003731 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003732 return -EINVAL;
3733 }
3734 ssid_len = nla_len(
3735 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3736
3737 /* Decrement by 1, don't count null character */
3738 ssid_len--;
3739
3740 req_msg->networks[index].ssid.length = ssid_len;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003741 hdd_notice("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303743 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003744 ssid, ssid_len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003745 hdd_notice("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003746 req_msg->networks[index].ssid.length,
3747 req_msg->networks[index].ssid.ssId);
3748
3749 /* Parse and fetch rssi threshold */
3750 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003751 hdd_err("attr rssi threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752 return -EINVAL;
3753 }
3754 req_msg->networks[index].rssi_threshold = nla_get_s8(
3755 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003756 hdd_notice("rssi threshold %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757 req_msg->networks[index].rssi_threshold);
3758
3759 /* Parse and fetch epno flags */
3760 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003761 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762 return -EINVAL;
3763 }
3764 req_msg->networks[index].flags = nla_get_u8(
3765 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003766 hdd_notice("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003767
3768 /* Parse and fetch auth bit */
3769 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003770 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003771 return -EINVAL;
3772 }
3773 req_msg->networks[index].auth_bit_field = nla_get_u8(
3774 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003775 hdd_notice("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003776 req_msg->networks[index].auth_bit_field);
3777
3778 index++;
3779 }
3780 return 0;
3781}
3782
3783/**
3784 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3785 * @wiphy: wiphy
3786 * @wdev: pointer to wireless dev
3787 * @data: data pointer
3788 * @data_len: data length
3789 *
3790 * This function reads the NL vendor attributes from %tb and
3791 * fill in the epno request message.
3792 *
3793 * Return: 0 on success, error number otherwise
3794 */
3795static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3796 struct wireless_dev *wdev,
3797 const void *data,
3798 int data_len)
3799{
3800 struct wifi_epno_params *req_msg = NULL;
3801 struct net_device *dev = wdev->netdev;
3802 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3803 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3804 struct nlattr *tb[
3805 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303806 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 uint32_t num_networks, len;
3808 int ret_val;
3809
Jeff Johnson1f61b612016-02-12 16:28:33 -08003810 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811
3812 ret_val = wlan_hdd_validate_context(hdd_ctx);
3813 if (ret_val)
3814 return ret_val;
3815
Anurag Chouhan6d760662016-02-20 16:05:43 +05303816 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 hdd_err("Command not allowed in FTM mode");
3818 return -EPERM;
3819 }
3820
3821 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3822 data, data_len,
3823 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003824 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 return -EINVAL;
3826 }
3827
3828 /* Parse and fetch number of networks */
3829 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003830 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 return -EINVAL;
3832 }
3833 num_networks = nla_get_u32(
3834 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003835 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836
3837 len = sizeof(*req_msg) +
3838 (num_networks * sizeof(struct wifi_epno_network));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303839 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003840 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003841 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003842 return -ENOMEM;
3843 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303844 qdf_mem_zero(req_msg, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 req_msg->num_networks = num_networks;
3846
3847 /* Parse and fetch request Id */
3848 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003849 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850 goto fail;
3851 }
3852 req_msg->request_id = nla_get_u32(
3853 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003854 hdd_notice("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855
3856 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003857 hdd_notice("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003858
3859 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
3860 goto fail;
3861
3862 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303863 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003864 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003865 goto fail;
3866 }
3867
3868 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303869 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003870 return 0;
3871
3872fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303873 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 return -EINVAL;
3875}
3876
3877 /**
3878 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
3879 * @wiphy: wiphy
3880 * @wdev: pointer to wireless dev
3881 * @data: data pointer
3882 * @data_len: data length
3883 *
3884 * This function reads the NL vendor attributes from %tb and
3885 * fill in the epno request message.
3886 *
3887 * Return: 0 on success, error number otherwise
3888 */
3889int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3890 struct wireless_dev *wdev,
3891 const void *data,
3892 int data_len)
3893{
3894 int ret;
3895
3896 cds_ssr_protect(__func__);
3897 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
3898 data, data_len);
3899 cds_ssr_unprotect(__func__);
3900
3901 return ret;
3902}
3903
3904/**
3905 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
3906 * @hddctx: HDD context
3907 * @req_msg: request message
3908 * @tb: vendor attribute table
3909 *
3910 * This function reads the network block NL vendor attributes from %tb and
3911 * fill in the passpoint request message.
3912 *
3913 * Return: 0 on success, error number otherwise
3914 */
3915static int hdd_extscan_passpoint_fill_network_list(
3916 hdd_context_t *hddctx,
3917 struct wifi_passpoint_req *req_msg,
3918 struct nlattr **tb)
3919{
3920 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
3921 struct nlattr *networks;
3922 int rem1, len;
3923 uint8_t index;
3924
3925 index = 0;
3926 nla_for_each_nested(networks,
3927 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
3928 rem1) {
3929 if (nla_parse(network,
3930 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3931 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003932 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933 return -EINVAL;
3934 }
3935
3936 /* Parse and fetch identifier */
3937 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003938 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003939 return -EINVAL;
3940 }
3941 req_msg->networks[index].id = nla_get_u32(
3942 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003943 hdd_notice("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003944
3945 /* Parse and fetch realm */
3946 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003947 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003948 return -EINVAL;
3949 }
3950 len = nla_len(
3951 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
3952 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003953 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003954 return -EINVAL;
3955 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303956 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003957 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
3958 len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003959 hdd_notice("realm len %d", len);
3960 hdd_notice("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003961
3962 /* Parse and fetch roaming consortium ids */
3963 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003964 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003965 return -EINVAL;
3966 }
3967 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
3968 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
3969 sizeof(req_msg->networks[0].roaming_consortium_ids));
Jeff Johnson630f9e72016-07-25 12:00:12 -07003970 hdd_notice("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971
3972 /* Parse and fetch plmn */
3973 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003974 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975 return -EINVAL;
3976 }
3977 nla_memcpy(&req_msg->networks[index].plmn,
3978 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
3979 SIR_PASSPOINT_PLMN_LEN);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003980 hdd_notice("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003981 req_msg->networks[index].plmn[0],
3982 req_msg->networks[index].plmn[1],
3983 req_msg->networks[index].plmn[2]);
3984
3985 index++;
3986 }
3987 return 0;
3988}
3989
3990/**
3991 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
3992 * @wiphy: wiphy
3993 * @wdev: pointer to wireless dev
3994 * @data: data pointer
3995 * @data_len: data length
3996 *
3997 * This function reads the NL vendor attributes from %tb and
3998 * fill in the passpoint request message.
3999 *
4000 * Return: 0 on success, error number otherwise
4001 */
4002static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4003 struct wireless_dev *wdev,
4004 const void *data,
4005 int data_len)
4006{
4007 struct wifi_passpoint_req *req_msg = NULL;
4008 struct net_device *dev = wdev->netdev;
4009 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4010 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4011 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304012 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013 uint32_t num_networks = 0;
4014 int ret;
4015
Jeff Johnson1f61b612016-02-12 16:28:33 -08004016 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004017
4018 ret = wlan_hdd_validate_context(hdd_ctx);
4019 if (ret)
4020 return ret;
4021
Anurag Chouhan6d760662016-02-20 16:05:43 +05304022 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004023 hdd_err("Command not allowed in FTM mode");
4024 return -EPERM;
4025 }
4026
4027 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4028 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004029 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 return -EINVAL;
4031 }
4032
4033 /* Parse and fetch number of networks */
4034 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004035 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 return -EINVAL;
4037 }
4038 num_networks = nla_get_u32(
4039 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004040 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304042 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 (num_networks * sizeof(req_msg->networks[0])));
4044 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004045 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046 return -ENOMEM;
4047 }
4048 req_msg->num_networks = num_networks;
4049
4050 /* Parse and fetch request Id */
4051 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004052 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004053 goto fail;
4054 }
4055 req_msg->request_id = nla_get_u32(
4056 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4057
4058 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004059 hdd_notice("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004060 req_msg->session_id);
4061
4062 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4063 goto fail;
4064
4065 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304066 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004067 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004068 goto fail;
4069 }
4070
4071 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304072 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 return 0;
4074
4075fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304076 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004077 return -EINVAL;
4078}
4079
4080/**
4081 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4082 * @wiphy: wiphy
4083 * @wdev: pointer to wireless dev
4084 * @data: data pointer
4085 * @data_len: data length
4086 *
4087 * This function reads the NL vendor attributes from %tb and
4088 * fill in the passpoint request message.
4089 *
4090 * Return: 0 on success, error number otherwise
4091 */
4092int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4093 struct wireless_dev *wdev,
4094 const void *data,
4095 int data_len)
4096{
4097 int ret;
4098
4099 cds_ssr_protect(__func__);
4100 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4101 data, data_len);
4102 cds_ssr_unprotect(__func__);
4103
4104 return ret;
4105}
4106
4107/**
4108 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4109 * @wiphy: wiphy
4110 * @wdev: pointer to wireless dev
4111 * @data: data pointer
4112 * @data_len: data length
4113 *
4114 * This function resets passpoint networks list
4115 *
4116 * Return: 0 on success, error number otherwise
4117 */
4118static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4119 struct wireless_dev *wdev,
4120 const void *data,
4121 int data_len)
4122{
4123 struct wifi_passpoint_req *req_msg = NULL;
4124 struct net_device *dev = wdev->netdev;
4125 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4126 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4127 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304128 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004129 int ret;
4130
Jeff Johnson1f61b612016-02-12 16:28:33 -08004131 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004132
4133 ret = wlan_hdd_validate_context(hdd_ctx);
4134 if (ret)
4135 return ret;
4136
Anurag Chouhan6d760662016-02-20 16:05:43 +05304137 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 hdd_err("Command not allowed in FTM mode");
4139 return -EPERM;
4140 }
4141
4142 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4143 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004144 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004145 return -EINVAL;
4146 }
4147
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304148 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004149 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004150 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151 return -ENOMEM;
4152 }
4153
4154 /* Parse and fetch request Id */
4155 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004156 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157 goto fail;
4158 }
4159 req_msg->request_id = nla_get_u32(
4160 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4161
4162 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004163 hdd_notice("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 req_msg->request_id, req_msg->session_id);
4165
4166 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304167 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004168 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004169 goto fail;
4170 }
4171
4172 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304173 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004174 return 0;
4175
4176fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304177 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178 return -EINVAL;
4179}
4180
4181/**
4182 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4183 * @wiphy: wiphy
4184 * @wdev: pointer to wireless dev
4185 * @data: data pointer
4186 * @data_len: data length
4187 *
4188 * This function resets passpoint networks list
4189 *
4190 * Return: 0 on success, error number otherwise
4191 */
4192int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4193 struct wireless_dev *wdev,
4194 const void *data,
4195 int data_len)
4196{
4197 int ret;
4198
4199 cds_ssr_protect(__func__);
4200 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4201 data, data_len);
4202 cds_ssr_unprotect(__func__);
4203
4204 return ret;
4205}
4206
4207/*
4208 * define short names for the global vendor params
4209 * used by __wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4210 */
4211#define PARAM_MAX \
4212 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4213#define PARAM_REQUEST_ID \
4214 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4215#define PARAMS_LOST_SSID_SAMPLE_SIZE \
4216 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE
4217#define PARAMS_NUM_SSID \
4218 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID
4219#define THRESHOLD_PARAM \
4220 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM
4221#define PARAM_SSID \
4222 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID
4223#define PARAM_BAND \
4224 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND
4225#define PARAM_RSSI_LOW \
4226 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW
4227#define PARAM_RSSI_HIGH \
4228 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH
4229
4230/**
4231 * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4232 * @wiphy: Pointer to wireless phy
4233 * @wdev: Pointer to wireless device
4234 * @data: Pointer to data
4235 * @data_len: Data length
4236 *
4237 * Return: 0 on success, negative errno on failure
4238 */
4239static int
4240__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4241 struct wireless_dev *wdev,
4242 const void *data,
4243 int data_len)
4244{
4245 struct sir_set_ssid_hotlist_request *request;
4246 struct net_device *dev = wdev->netdev;
4247 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4248 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4249 struct nlattr *tb[PARAM_MAX + 1];
4250 struct nlattr *tb2[PARAM_MAX + 1];
4251 struct nlattr *ssids;
4252 struct hdd_ext_scan_context *context;
4253 uint32_t request_id;
4254 char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1];
4255 int ssid_len, i, rem;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304256 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004257 int retval;
4258 unsigned long rc;
4259
Jeff Johnson1f61b612016-02-12 16:28:33 -08004260 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261
Anurag Chouhan6d760662016-02-20 16:05:43 +05304262 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 hdd_err("Command not allowed in FTM mode");
4264 return -EPERM;
4265 }
4266
4267 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304268 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004269 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004270
4271 if (nla_parse(tb, PARAM_MAX,
4272 data, data_len,
4273 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004274 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275 return -EINVAL;
4276 }
4277
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304278 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004280 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004281 return -ENOMEM;
4282 }
4283
4284 /* Parse and fetch request Id */
4285 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004286 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004287 goto fail;
4288 }
4289
4290 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004291 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004292
4293 /* Parse and fetch lost SSID sample size */
4294 if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004295 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004296 goto fail;
4297 }
4298 request->lost_ssid_sample_size =
4299 nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004300 hdd_notice("Lost SSID Sample Size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 request->lost_ssid_sample_size);
4302
4303 /* Parse and fetch number of hotlist SSID */
4304 if (!tb[PARAMS_NUM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004305 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004306 goto fail;
4307 }
4308 request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004309 hdd_notice("Number of SSID %d", request->ssid_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310
4311 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004312 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313
4314 i = 0;
4315 nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) {
4316 if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004317 hdd_err("Too Many SSIDs, %d exceeds %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS);
4319 break;
4320 }
4321 if (nla_parse(tb2, PARAM_MAX,
4322 nla_data(ssids), nla_len(ssids),
4323 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004324 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 goto fail;
4326 }
4327
4328 /* Parse and fetch SSID */
4329 if (!tb2[PARAM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004330 hdd_err("attr ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004331 goto fail;
4332 }
4333 nla_memcpy(ssid_string,
4334 tb2[PARAM_SSID],
4335 sizeof(ssid_string));
Jeff Johnson630f9e72016-07-25 12:00:12 -07004336 hdd_notice("SSID %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004337 ssid_string);
4338 ssid_len = strlen(ssid_string);
4339 memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len);
4340 request->ssids[i].ssid.length = ssid_len;
4341
4342 /* Parse and fetch low RSSI */
4343 if (!tb2[PARAM_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004344 hdd_err("attr band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 goto fail;
4346 }
4347 request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004348 hdd_notice("band %d", request->ssids[i].band);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349
4350 /* Parse and fetch low RSSI */
4351 if (!tb2[PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004352 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353 goto fail;
4354 }
4355 request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004356 hdd_notice("RSSI low %d", request->ssids[i].rssi_low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357
4358 /* Parse and fetch high RSSI */
4359 if (!tb2[PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004360 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361 goto fail;
4362 }
4363 request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004364 hdd_notice("RSSI high %d", request->ssids[i].rssi_high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365 i++;
4366 }
4367
4368 context = &ext_scan_context;
4369 spin_lock(&context->context_lock);
4370 INIT_COMPLETION(context->response_event);
4371 context->request_id = request_id = request->request_id;
4372 spin_unlock(&context->context_lock);
4373
4374 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304375 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004376 hdd_err("sme_set_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377 goto fail;
4378 }
4379
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304380 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381
4382 /* request was sent -- wait for the response */
4383 rc = wait_for_completion_timeout(&context->response_event,
4384 msecs_to_jiffies
4385 (WLAN_WAIT_TIME_EXTSCAN));
4386 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004387 hdd_err("sme_set_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388 retval = -ETIMEDOUT;
4389 } else {
4390 spin_lock(&context->context_lock);
4391 if (context->request_id == request_id)
4392 retval = context->response_status;
4393 else
4394 retval = -EINVAL;
4395 spin_unlock(&context->context_lock);
4396 }
4397
4398 return retval;
4399
4400fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304401 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004402 return -EINVAL;
4403}
4404
4405/*
4406 * done with short names for the global vendor params
4407 * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4408 */
4409#undef PARAM_MAX
4410#undef PARAM_REQUEST_ID
4411#undef PARAMS_NUM_SSID
4412#undef THRESHOLD_PARAM
4413#undef PARAM_SSID
4414#undef PARAM_BAND
4415#undef PARAM_RSSI_LOW
4416#undef PARAM_RSSI_HIGH
4417
4418/**
4419 * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4420 * @wiphy: Pointer to wireless phy
4421 * @wdev: Pointer to wireless device
4422 * @data: Pointer to data
4423 * @data_len: Data length
4424 *
4425 * Return: 0 on success, negative errno on failure
4426 */
4427int
4428wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4429 struct wireless_dev *wdev,
4430 const void *data,
4431 int data_len)
4432{
4433 int ret;
4434
4435 cds_ssr_protect(__func__);
4436 ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data,
4437 data_len);
4438 cds_ssr_unprotect(__func__);
4439
4440 return ret;
4441}
4442
4443/*
4444 * define short names for the global vendor params
4445 * used by __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4446 */
4447#define PARAM_MAX \
4448 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4449#define PARAM_REQUEST_ID \
4450 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4451
4452/**
4453 * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4454 * @wiphy: Pointer to wireless phy
4455 * @wdev: Pointer to wireless device
4456 * @data: Pointer to data
4457 * @data_len: Data length
4458 *
4459 * Return: 0 on success, negative errno on failure
4460 */
4461static int
4462__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4463 struct wireless_dev *wdev,
4464 const void *data,
4465 int data_len)
4466{
4467 struct sir_set_ssid_hotlist_request *request;
4468 struct net_device *dev = wdev->netdev;
4469 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4470 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4471 struct nlattr *tb[PARAM_MAX + 1];
4472 struct hdd_ext_scan_context *context;
4473 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304474 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004475 int retval;
4476 unsigned long rc;
4477
Jeff Johnson1f61b612016-02-12 16:28:33 -08004478 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479
Anurag Chouhan6d760662016-02-20 16:05:43 +05304480 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004481 hdd_err("Command not allowed in FTM mode");
4482 return -EPERM;
4483 }
4484
4485 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304486 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004487 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004488
4489 if (nla_parse(tb, PARAM_MAX,
4490 data, data_len,
4491 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004492 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004493 return -EINVAL;
4494 }
4495
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304496 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004498 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004499 return -ENOMEM;
4500 }
4501
4502 /* Parse and fetch request Id */
4503 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004504 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004505 goto fail;
4506 }
4507
4508 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004509 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510
4511 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004512 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513
4514 request->lost_ssid_sample_size = 0;
4515 request->ssid_count = 0;
4516
4517 context = &ext_scan_context;
4518 spin_lock(&context->context_lock);
4519 INIT_COMPLETION(context->response_event);
4520 context->request_id = request_id = request->request_id;
4521 spin_unlock(&context->context_lock);
4522
4523 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304524 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004525 hdd_err("sme_reset_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526 goto fail;
4527 }
4528
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304529 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530
4531 /* request was sent -- wait for the response */
4532 rc = wait_for_completion_timeout(&context->response_event,
4533 msecs_to_jiffies
4534 (WLAN_WAIT_TIME_EXTSCAN));
4535 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004536 hdd_err("sme_reset_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537 retval = -ETIMEDOUT;
4538 } else {
4539 spin_lock(&context->context_lock);
4540 if (context->request_id == request_id)
4541 retval = context->response_status;
4542 else
4543 retval = -EINVAL;
4544 spin_unlock(&context->context_lock);
4545 }
4546
4547 return retval;
4548
4549fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304550 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 return -EINVAL;
4552}
4553
4554/*
4555 * done with short names for the global vendor params
4556 * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4557 */
4558#undef PARAM_MAX
4559#undef PARAM_REQUEST_ID
4560
4561/**
4562 * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4563 * @wiphy: Pointer to wireless phy
4564 * @wdev: Pointer to wireless device
4565 * @data: Pointer to data
4566 * @data_len: Data length
4567 *
4568 * Return: 0 on success, negative errno on failure
4569 */
4570int
4571wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4572 struct wireless_dev *wdev,
4573 const void *data,
4574 int data_len)
4575{
4576 int ret;
4577
4578 cds_ssr_protect(__func__);
4579 ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev,
4580 data, data_len);
4581 cds_ssr_unprotect(__func__);
4582
4583 return ret;
4584}
4585
4586/**
4587 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4588 * @hdd_ctx: Global HDD context
4589 *
4590 * Return: none
4591 */
4592#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4593static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4594{
4595 init_completion(&pHddCtx->ready_to_extwow);
4596}
4597#else
4598static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4599{
4600 return;
4601}
4602#endif
4603
4604/**
4605 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4606 * @hdd_ctx: Global HDD context
4607 *
4608 * Return: none
4609 */
4610void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx)
4611{
4612 wlan_hdd_init_completion_extwow(hdd_ctx);
4613 init_completion(&ext_scan_context.response_event);
4614 spin_lock_init(&ext_scan_context.context_lock);
4615}
4616
4617#endif /* FEATURE_WLAN_EXTSCAN */