blob: b81bab3665dea404df04e1bdaae1bab4471e607f [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**
23 * DOC: wlan_hdd_ext_scan.c
24 *
25 * WLAN Host Device Driver EXT SCAN feature implementation
26 *
27 */
28
29#ifdef FEATURE_WLAN_EXTSCAN
30
Jeff Johnson630f9e72016-07-25 12:00:12 -070031/* denote that this file does not allow legacy hddLog */
32#define HDD_DISALLOW_LEGACY_HDDLOG 1
33
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080034#include "wlan_hdd_ext_scan.h"
35#include "cds_utils.h"
36#include "cds_sched.h"
37
38/* amount of time to wait for a synchronous request/response operation */
39#define WLAN_WAIT_TIME_EXTSCAN 1000
40
41/**
42 * struct hdd_ext_scan_context - hdd ext scan context
43 * @request_id: userspace-assigned ID associated with the request
44 * @response_event: Ext scan wait event
45 * @response_status: Status returned by FW in response to a request
46 * @ignore_cached_results: Flag to ignore cached results or not
47 * @context_lock: Spinlock to serialize all context accesses
48 * @capability_response: Ext scan capability response data from target
Mukul Sharmafa937be2016-08-12 18:13:36 +053049 * @buckets_scanned: bitmask of buckets scanned in extscan cycle
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050 */
51struct hdd_ext_scan_context {
52 uint32_t request_id;
53 int response_status;
54 bool ignore_cached_results;
55 struct completion response_event;
56 spinlock_t context_lock;
57 struct ext_scan_capabilities_response capability_response;
Mukul Sharmafa937be2016-08-12 18:13:36 +053058 uint32_t buckets_scanned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080059};
60static struct hdd_ext_scan_context ext_scan_context;
61
62static const struct nla_policy wlan_hdd_extscan_config_policy
63[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] = {
64 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = {
65 .type = NLA_U32},
66 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = {
67 .type = NLA_U32},
68 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = {.type = NLA_U32},
69 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = {
70 .type = NLA_U32},
71 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = {.type = NLA_U8},
72 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = {.type = NLA_U8},
73
74 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = {.type = NLA_U8},
75 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = {.type = NLA_U8},
76 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = {.type = NLA_U32},
77 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] = {
78 .type = NLA_U8},
79 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] = {
80 .type = NLA_U32},
81 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] = {
82 .type = NLA_U32},
83 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] = {
84 .type = NLA_U32},
85 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT] = {
86 .type = NLA_U8},
87 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS] = {
88 .type = NLA_U8 },
89 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] = {
90 .type = NLA_U8},
91 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = {
92 .type = NLA_U8},
93
94 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = {
95 .type = NLA_U32},
96 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = {
97 .type = NLA_UNSPEC},
98 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = {
99 .type = NLA_S32},
100 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = {
101 .type = NLA_S32},
102 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = {
103 .type = NLA_U32},
104 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] = {
105 .type = NLA_U32},
106 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] = {
107 .type = NLA_U32},
108 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = {
109 .type = NLA_U32},
110 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = {
111 .type = NLA_U32},
112 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = {
113 .type = NLA_U32},
114 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
115 .type = NLA_U32 },
116 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
117 .type = NLA_BINARY,
118 .len = IEEE80211_MAX_SSID_LEN },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800119 [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
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700294 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295
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) + \
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530321 (sizeof(result->num_results) + NLA_HDRLEN))+ \
322 (sizeof(result->buckets_scanned) + NLA_HDRLEN)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800323#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
324 ((sizeof(ap->ts) + NLA_HDRLEN) + \
325 (sizeof(ap->ssid) + NLA_HDRLEN) + \
326 (sizeof(ap->bssid) + NLA_HDRLEN) + \
327 (sizeof(ap->channel) + NLA_HDRLEN) + \
328 (sizeof(ap->rssi) + NLA_HDRLEN) + \
329 (sizeof(ap->rtt) + NLA_HDRLEN) + \
330 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
331 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
332 (sizeof(ap->capability) + NLA_HDRLEN) + \
333 (sizeof(ap->ieLength) + NLA_HDRLEN))
334#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
335 (ap->ieLength + NLA_HDRLEN)
336
337 nl_buf_len = NLMSG_HDRLEN;
338 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
339 if (data->num_scan_ids) {
340 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
341 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
342 result = &data->result[0];
343 for (i = 0; i < data->num_scan_ids; i++) {
344 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
345 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
346 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
347
348 ap = &result->ap[0];
349 for (j = 0; j < result->num_results; j++) {
350 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
351 nl_buf_len +=
352 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
353 if (ap->ieLength)
354 nl_buf_len +=
355 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
356 ap++;
357 }
358 result++;
359 }
360 }
361
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 }
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530368 hdd_notice("Req Id %u Num_scan_ids %u More Data %u",
369 data->request_id, data->num_scan_ids, data->more_data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370
371 result = &data->result[0];
372 for (i = 0; i < data->num_scan_ids; i++) {
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530373 hdd_notice("[i=%d] scan_id %u flags %u num_results %u buckets scanned %u",
374 i, result->scan_id, result->flags, result->num_results,
375 result->buckets_scanned);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800376
377 ap = &result->ap[0];
378 for (j = 0; j < result->num_results; j++) {
379 /*
380 * Firmware returns timestamp from ext scan start till
381 * BSSID was cached (in micro seconds). Add this with
382 * time gap between system boot up to ext scan start
383 * to derive the time since boot when the
384 * BSSID was cached.
385 */
386 ap->ts += pHddCtx->ext_scan_start_since_boot;
Jeff Johnson630f9e72016-07-25 12:00:12 -0700387 hdd_notice("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 "Ssid: %s "
389 "Bssid (" MAC_ADDRESS_STR ") "
390 "Channel %u "
391 "Rssi %d "
392 "RTT %u "
393 "RTT_SD %u "
394 "Beacon Period %u "
395 "Capability 0x%x "
396 "Ie length %d",
397 ap->ts,
398 ap->ssid,
399 MAC_ADDR_ARRAY(ap->bssid.bytes),
400 ap->channel,
401 ap->rssi,
402 ap->rtt,
403 ap->rtt_sd,
404 ap->beaconPeriod,
405 ap->capability,
406 ap->ieLength);
407 ap++;
408 }
409 result++;
410 }
411
412 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
413 data->request_id) ||
414 nla_put_u32(skb,
415 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
416 data->num_scan_ids) ||
417 nla_put_u8(skb,
418 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
419 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700420 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 goto fail;
422 }
423
424 if (data->num_scan_ids) {
425 struct nlattr *nla_results;
426 result = &data->result[0];
427
428 if (nla_put_u32(skb,
429 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
430 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700431 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800432 goto fail;
433 }
434 nla_results = nla_nest_start(skb,
435 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
436 if (!nla_results)
437 goto fail;
438
439 for (i = 0; i < data->num_scan_ids; i++) {
440 struct nlattr *nla_result;
441 struct nlattr *nla_aps;
442
443 nla_result = nla_nest_start(skb, i);
444 if (!nla_result)
445 goto fail;
446
447 if (nla_put_u32(skb,
448 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
449 result->scan_id) ||
450 nla_put_u32(skb,
451 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
452 result->flags) ||
453 nla_put_u32(skb,
Mukul Sharmafa937be2016-08-12 18:13:36 +0530454 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530455 result->buckets_scanned) ||
Mukul Sharmafa937be2016-08-12 18:13:36 +0530456 nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800457 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
458 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700459 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460 goto fail;
461 }
462
463 nla_aps = nla_nest_start(skb,
464 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
465 if (!nla_aps)
466 goto fail;
467
468 ap = &result->ap[0];
469 for (j = 0; j < result->num_results; j++) {
470 if (hdd_extscan_nl_fill_bss(skb, ap, j))
471 goto fail;
472
473 ap++;
474 }
475 nla_nest_end(skb, nla_aps);
476 nla_nest_end(skb, nla_result);
477 result++;
478 }
479 nla_nest_end(skb, nla_results);
480 }
481
482 cfg80211_vendor_cmd_reply(skb);
483
484 if (!data->more_data) {
485 spin_lock(&context->context_lock);
486 context->response_status = 0;
487 complete(&context->response_event);
488 spin_unlock(&context->context_lock);
489 }
490 return;
491
492fail:
493 if (skb)
494 kfree_skb(skb);
495
496 spin_lock(&context->context_lock);
497 context->response_status = -EINVAL;
498 spin_unlock(&context->context_lock);
499
500 return;
501}
502
503/**
504 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
505 * @ctx: Pointer to hdd context
506 * @pData: Pointer to ext scan result event
507 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800508 * This callback execute in atomic context and must not invoke any
509 * blocking calls.
510 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800511 * Return: none
512 */
513static void
514wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
515 struct extscan_hotlist_match *data)
516{
517 hdd_context_t *pHddCtx = ctx;
518 struct sk_buff *skb = NULL;
519 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800520 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800521
522 ENTER();
523
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530524 if (wlan_hdd_validate_context(pHddCtx))
525 return;
526 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700527 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 return;
529 }
530
531 if (data->ap_found)
532 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
533 else
534 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
535
536 skb = cfg80211_vendor_event_alloc(
537 pHddCtx->wiphy,
538 NULL,
539 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800540 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541
542 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700543 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800544 return;
545 }
546 hdd_info("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
547 data->requestId, data->numOfAps, data->moreData,
548 data->ap_found);
549
550 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530551 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552
Jeff Johnson630f9e72016-07-25 12:00:12 -0700553 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800554 "Ssid: %s "
555 "Bssid (" MAC_ADDRESS_STR ") "
556 "Channel %u "
557 "Rssi %d "
558 "RTT %u "
559 "RTT_SD %u",
560 i,
561 data->ap[i].ts,
562 data->ap[i].ssid,
563 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
564 data->ap[i].channel,
565 data->ap[i].rssi,
566 data->ap[i].rtt, data->ap[i].rtt_sd);
567 }
568
569 if (nla_put_u32(skb,
570 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
571 data->requestId) ||
572 nla_put_u32(skb,
573 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
574 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700575 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800576 goto fail;
577 }
578
579 if (data->numOfAps) {
580 struct nlattr *aps;
581
582 aps = nla_nest_start(skb,
583 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
584 if (!aps)
585 goto fail;
586
587 for (i = 0; i < data->numOfAps; i++) {
588 struct nlattr *ap;
589
590 ap = nla_nest_start(skb, i);
591 if (!ap)
592 goto fail;
593
594 if (nla_put_u64(skb,
595 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
596 data->ap[i].ts) ||
597 nla_put(skb,
598 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
599 sizeof(data->ap[i].ssid),
600 data->ap[i].ssid) ||
601 nla_put(skb,
602 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
603 sizeof(data->ap[i].bssid),
604 data->ap[i].bssid.bytes) ||
605 nla_put_u32(skb,
606 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
607 data->ap[i].channel) ||
608 nla_put_s32(skb,
609 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
610 data->ap[i].rssi) ||
611 nla_put_u32(skb,
612 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
613 data->ap[i].rtt) ||
614 nla_put_u32(skb,
615 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
616 data->ap[i].rtt_sd))
617 goto fail;
618
619 nla_nest_end(skb, ap);
620 }
621 nla_nest_end(skb, aps);
622
623 if (nla_put_u8(skb,
624 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
625 data->moreData))
626 goto fail;
627 }
628
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800629 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530630 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631 return;
632
633fail:
634 kfree_skb(skb);
635 return;
636}
637
638/**
639 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
640 * significant wifi change results indication
641 * @ctx: Pointer to hdd context
642 * @pData: Pointer to signif wifi change event
643 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800644 * This callback execute in atomic context and must not invoke any
645 * blocking calls.
646 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800647 * Return: none
648 */
649static void
650wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
651 void *ctx,
652 tpSirWifiSignificantChangeEvent pData)
653{
654 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
655 struct sk_buff *skb = NULL;
656 tSirWifiSignificantChange *ap_info;
657 int32_t *rssi;
658 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800659 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660
661 ENTER();
662
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530663 if (wlan_hdd_validate_context(pHddCtx))
664 return;
665 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700666 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 return;
668 }
669
670 skb = cfg80211_vendor_event_alloc(
671 pHddCtx->wiphy,
672 NULL,
673 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
674 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800675 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676
677 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700678 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679 return;
680 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700681 hdd_notice("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800682 pData->requestId, pData->numResults, pData->moreData);
683
684 ap_info = &pData->ap[0];
685 for (i = 0; i < pData->numResults; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700686 hdd_notice("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 "Bssid (" MAC_ADDRESS_STR ") "
688 "Channel %u "
689 "numOfRssi %d",
690 i,
691 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
692 ap_info->channel, ap_info->numOfRssi);
693 rssi = &(ap_info)->rssi[0];
694 for (j = 0; j < ap_info->numOfRssi; j++)
Jeff Johnson630f9e72016-07-25 12:00:12 -0700695 hdd_notice("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696
697 ap_info += ap_info->numOfRssi * sizeof(*rssi);
698 }
699
700 if (nla_put_u32(skb,
701 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
702 pData->requestId) ||
703 nla_put_u32(skb,
704 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
705 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700706 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 goto fail;
708 }
709
710 if (pData->numResults) {
711 struct nlattr *aps;
712
713 aps = nla_nest_start(skb,
714 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
715 if (!aps)
716 goto fail;
717
718 ap_info = &pData->ap[0];
719 for (i = 0; i < pData->numResults; i++) {
720 struct nlattr *ap;
721
722 ap = nla_nest_start(skb, i);
723 if (!ap)
724 goto fail;
725
726 if (nla_put(skb,
727 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530728 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800729 nla_put_u32(skb,
730 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
731 ap_info->channel) ||
732 nla_put_u32(skb,
733 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
734 ap_info->numOfRssi) ||
735 nla_put(skb,
736 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
737 sizeof(s32) * ap_info->numOfRssi,
738 &(ap_info)->rssi[0]))
739 goto fail;
740
741 nla_nest_end(skb, ap);
742
743 ap_info += ap_info->numOfRssi * sizeof(*rssi);
744 }
745 nla_nest_end(skb, aps);
746
747 if (nla_put_u8(skb,
748 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
749 pData->moreData))
750 goto fail;
751 }
752
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800753 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800754 return;
755
756fail:
757 kfree_skb(skb);
758 return;
759
760}
761
762/**
763 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
764 * @ctx: Pointer to hdd context
765 * @pData: Pointer to full scan result event
766 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800767 * This callback execute in atomic context and must not invoke any
768 * blocking calls.
769 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800770 * Return: none
771 */
772static void
773wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
774 tpSirWifiFullScanResultEvent
775 pData)
776{
777 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
778 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800779 struct timespec ts;
Mukul Sharmafa937be2016-08-12 18:13:36 +0530780 struct hdd_ext_scan_context *context;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700781
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800782 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700784 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800785
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530786 if (wlan_hdd_validate_context(pHddCtx))
787 return;
788 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700789 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800790 return;
791 }
792
793 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700794 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795 return;
796 }
797 skb = cfg80211_vendor_event_alloc(
798 pHddCtx->wiphy,
799 NULL,
800 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
801 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800802 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800803
804 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700805 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800806 return;
807 }
808
809 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700810
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800811 /* Android does not want the time stamp from the frame.
812 Instead it wants a monotonic increasing value since boot */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700813 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700815
Jeff Johnson630f9e72016-07-25 12:00:12 -0700816 hdd_notice("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817 pData->moreData);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700818 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 "Bssid (" MAC_ADDRESS_STR ") "
820 "Channel %u "
821 "Rssi %d "
822 "RTT %u "
823 "RTT_SD %u "
824 "Bcn Period %d "
825 "Capability 0x%X "
826 "IE Length %d",
827 pData->ap.ts,
828 pData->ap.ssid,
829 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
830 pData->ap.channel,
831 pData->ap.rssi,
832 pData->ap.rtt,
833 pData->ap.rtt_sd,
834 pData->ap.beaconPeriod,
835 pData->ap.capability, pData->ap.ieLength);
836
837 if (nla_put_u32(skb,
838 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
839 pData->requestId) ||
840 nla_put_u64(skb,
841 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
842 pData->ap.ts) ||
843 nla_put(skb,
844 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
845 sizeof(pData->ap.ssid),
846 pData->ap.ssid) ||
847 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
848 sizeof(pData->ap.bssid),
849 pData->ap.bssid.bytes) ||
850 nla_put_u32(skb,
851 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
852 pData->ap.channel) ||
853 nla_put_s32(skb,
854 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
855 pData->ap.rssi) ||
856 nla_put_u32(skb,
857 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
858 pData->ap.rtt) ||
859 nla_put_u32(skb,
860 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
861 pData->ap.rtt_sd) ||
862 nla_put_u16(skb,
863 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
864 pData->ap.beaconPeriod) ||
865 nla_put_u16(skb,
866 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
867 pData->ap.capability) ||
868 nla_put_u32(skb,
869 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
870 pData->ap.ieLength) ||
871 nla_put_u8(skb,
872 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
873 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700874 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800875 goto nla_put_failure;
876 }
877
878 if (pData->ap.ieLength) {
879 if (nla_put(skb,
880 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
881 pData->ap.ieLength, pData->ap.ieData))
882 goto nla_put_failure;
883 }
884
Mukul Sharmafa937be2016-08-12 18:13:36 +0530885 context = &ext_scan_context;
886 spin_lock(&context->context_lock);
887 if (nla_put_u32(skb,
888 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
889 context->buckets_scanned)) {
890 spin_unlock(&context->context_lock);
891 hdd_notice("Failed to include buckets_scanned");
892 goto nla_put_failure;
893 }
894 spin_unlock(&context->context_lock);
895
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800896 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800897 return;
898
899nla_put_failure:
900 kfree_skb(skb);
901 return;
902}
903
904/**
905 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
906 * @ctx: Pointer to hdd context
907 * @pData: Pointer to scan results available indication param
908 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800909 * This callback execute in atomic context and must not invoke any
910 * blocking calls.
911 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912 * Return: none
913 */
914static void
915wlan_hdd_cfg80211_extscan_scan_res_available_event(
916 void *ctx,
917 tpSirExtScanResultsAvailableIndParams pData)
918{
919 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
920 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800921 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922
923 ENTER();
924
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530925 if (wlan_hdd_validate_context(pHddCtx))
926 return;
927 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700928 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800929 return;
930 }
931
932 skb = cfg80211_vendor_event_alloc(
933 pHddCtx->wiphy,
934 NULL,
935 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
936 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800937 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800938
939 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700940 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941 return;
942 }
943
Jeff Johnson630f9e72016-07-25 12:00:12 -0700944 hdd_notice("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800945 pData->requestId, pData->numResultsAvailable);
946 if (nla_put_u32(skb,
947 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
948 pData->requestId) ||
949 nla_put_u32(skb,
950 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
951 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700952 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800953 goto nla_put_failure;
954 }
955
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800956 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530957 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800958 return;
959
960nla_put_failure:
961 kfree_skb(skb);
962 return;
963}
964
965/**
966 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
967 * @ctx: Pointer to hdd context
968 * @pData: Pointer to scan event indication param
969 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800970 * This callback execute in atomic context and must not invoke any
971 * blocking calls.
972 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800973 * Return: none
974 */
975static void
976wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
977 tpSirExtScanOnScanEventIndParams
978 pData)
979{
980 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
981 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800982 int flags = cds_get_gfp_flags();
Mukul Sharmafa937be2016-08-12 18:13:36 +0530983 struct hdd_ext_scan_context *context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800984
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700985 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530987 if (wlan_hdd_validate_context(pHddCtx))
988 return;
989 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700990 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 return;
992 }
993
994 skb = cfg80211_vendor_event_alloc(
995 pHddCtx->wiphy,
996 NULL,
997 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
998 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800999 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000
1001 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001002 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001003 return;
1004 }
Mukul Sharmafa937be2016-08-12 18:13:36 +05301005
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001006 hdd_notice("Request Id: %u Scan event type: %u Scan event status: %u buckets scanned: %u",
Mukul Sharmafa937be2016-08-12 18:13:36 +05301007 pData->requestId, pData->scanEventType, pData->status,
1008 pData->buckets_scanned);
1009
Mukul Sharmafa937be2016-08-12 18:13:36 +05301010 context = &ext_scan_context;
1011 spin_lock(&context->context_lock);
1012 if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT) {
1013 context->buckets_scanned = 0;
1014 pData->scanEventType = WIFI_EXTSCAN_RESULTS_AVAILABLE;
1015 spin_unlock(&context->context_lock);
1016 } else if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_STARTED_EVENT) {
1017 context->buckets_scanned = pData->buckets_scanned;
1018 /* No need to report to user space */
1019 spin_unlock(&context->context_lock);
Mukul Sharma45114d92016-08-12 19:34:14 +05301020 goto nla_put_failure;
Mukul Sharmafa937be2016-08-12 18:13:36 +05301021 } else {
1022 spin_unlock(&context->context_lock);
1023 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001024
1025 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1026 pData->requestId) ||
1027 nla_put_u8(skb,
1028 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
Mukul Sharmafa937be2016-08-12 18:13:36 +05301029 pData->scanEventType)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001030 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 goto nla_put_failure;
1032 }
1033
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001034 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001035 return;
1036
1037nla_put_failure:
1038 kfree_skb(skb);
1039 return;
1040}
1041
1042/**
1043 * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found
1044 * @hddctx: HDD context
1045 * @data: matched network data
1046 *
1047 * This function reads the matched network data and fills NL vendor attributes
1048 * and send it to upper layer.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001049 * This callback execute in atomic context and must not invoke any
1050 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001051 *
1052 * Return: 0 on success, error number otherwise
1053 */
1054static void
1055wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
1056 struct pno_match_found *data)
1057{
1058 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
1059 struct sk_buff *skb = NULL;
1060 uint32_t len, i;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001061 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001062
1063 ENTER();
1064
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301065 if (wlan_hdd_validate_context(pHddCtx))
1066 return;
1067 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001068 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 return;
1070 }
1071
1072 /*
1073 * If the number of match found APs including IE data exceeds NL 4K size
1074 * limitation, drop that beacon/probe rsp frame.
1075 */
1076 len = sizeof(*data) +
1077 (data->num_results + sizeof(tSirWifiScanResult));
1078 for (i = 0; i < data->num_results; i++)
1079 len += data->ap[i].ieLength;
1080
1081 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001082 hdd_err("Frame exceeded NL size limitation, drop it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001083 return;
1084 }
1085
1086 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1087 NULL,
1088 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1089 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001090 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001091
1092 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001093 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001094 return;
1095 }
1096
Jeff Johnson630f9e72016-07-25 12:00:12 -07001097 hdd_notice("Req Id %u More Data %u num_results %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001098 data->request_id, data->more_data, data->num_results);
1099 for (i = 0; i < data->num_results; i++) {
1100 data->ap[i].channel = cds_chan_to_freq(data->ap[i].channel);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001101 hdd_notice("AP Info: Timestamp %llu) Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001102 "Bssid (" MAC_ADDRESS_STR ") "
1103 "Channel %u "
1104 "Rssi %d "
1105 "RTT %u "
1106 "RTT_SD %u "
1107 "Bcn Period %d "
1108 "Capability 0x%X "
1109 "IE Length %d",
1110 data->ap[i].ts,
1111 data->ap[i].ssid,
1112 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
1113 data->ap[i].channel,
1114 data->ap[i].rssi,
1115 data->ap[i].rtt,
1116 data->ap[i].rtt_sd,
1117 data->ap[i].beaconPeriod,
1118 data->ap[i].capability,
1119 data->ap[i].ieLength);
1120 }
1121
1122 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1123 data->request_id) ||
1124 nla_put_u32(skb,
1125 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1126 data->num_results) ||
1127 nla_put_u8(skb,
1128 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1129 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001130 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131 goto fail;
1132 }
1133
1134 if (data->num_results) {
1135 struct nlattr *nla_aps;
1136 nla_aps = nla_nest_start(skb,
1137 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1138 if (!nla_aps)
1139 goto fail;
1140
1141 for (i = 0; i < data->num_results; i++) {
1142 if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i))
1143 goto fail;
1144 }
1145 nla_nest_end(skb, nla_aps);
1146 }
1147
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001148 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001149 return;
1150
1151fail:
1152 kfree_skb(skb);
1153 return;
1154}
1155
1156/**
1157 * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found
1158 * @hddctx: HDD context
1159 * @data: matched network data
1160 *
1161 * This function reads the match network %data and fill in the skb with
1162 * NL attributes and send up the NL event
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001163 * This callback execute in atomic context and must not invoke any
1164 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 *
1166 * Return: none
1167 */
1168static void
1169wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
1170 struct wifi_passpoint_match *data)
1171{
1172 hdd_context_t *pHddCtx = ctx;
1173 struct sk_buff *skb = NULL;
1174 uint32_t len, i, num_matches = 1, more_data = 0;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001175 struct nlattr *nla_aps, *nla_bss;
1176 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001177
1178 ENTER();
1179
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301180 if (wlan_hdd_validate_context(pHddCtx))
1181 return;
1182 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001183 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001184 return;
1185 }
1186
1187 len = sizeof(*data) + data->ap.ieLength + data->anqp_len;
1188 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001189 hdd_err("Result exceeded NL size limitation, drop it");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001190 return;
1191 }
1192
1193 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1194 NULL,
1195 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1196 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001197 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001198
1199 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001200 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001201 return;
1202 }
1203
Jeff Johnson630f9e72016-07-25 12:00:12 -07001204 hdd_notice("Req Id %u Id %u ANQP length %u num_matches %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001205 data->request_id, data->id, data->anqp_len, num_matches);
1206 for (i = 0; i < num_matches; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001207 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001208 "Bssid (" MAC_ADDRESS_STR ") "
1209 "Channel %u "
1210 "Rssi %d "
1211 "RTT %u "
1212 "RTT_SD %u "
1213 "Bcn Period %d "
1214 "Capability 0x%X "
1215 "IE Length %d",
1216 data->ap.ts,
1217 data->ap.ssid,
1218 MAC_ADDR_ARRAY(data->ap.bssid.bytes),
1219 data->ap.channel,
1220 data->ap.rssi,
1221 data->ap.rtt,
1222 data->ap.rtt_sd,
1223 data->ap.beaconPeriod,
1224 data->ap.capability,
1225 data->ap.ieLength);
1226 }
1227
1228 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1229 data->request_id) ||
1230 nla_put_u32(skb,
1231 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES,
1232 num_matches) ||
1233 nla_put_u8(skb,
1234 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1235 more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001236 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237 goto fail;
1238 }
1239
1240 nla_aps = nla_nest_start(skb,
1241 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST);
1242 if (!nla_aps)
1243 goto fail;
1244
1245 for (i = 0; i < num_matches; i++) {
1246 struct nlattr *nla_ap;
1247
1248 nla_ap = nla_nest_start(skb, i);
1249 if (!nla_ap)
1250 goto fail;
1251
1252 if (nla_put_u32(skb,
1253 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID,
1254 data->id) ||
1255 nla_put_u32(skb,
1256 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN,
1257 data->anqp_len)) {
1258 goto fail;
1259 }
1260
1261 if (data->anqp_len)
1262 if (nla_put(skb,
1263 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP,
1264 data->anqp_len, data->anqp))
1265 goto fail;
1266
1267 nla_bss = nla_nest_start(skb,
1268 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1269 if (!nla_bss)
1270 goto fail;
1271
1272 if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0))
1273 goto fail;
1274
1275 nla_nest_end(skb, nla_bss);
1276 nla_nest_end(skb, nla_ap);
1277 }
1278 nla_nest_end(skb, nla_aps);
1279
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001280 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001281 return;
1282
1283fail:
1284 kfree_skb(skb);
1285 return;
1286}
1287
1288/**
1289 * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() -
1290 * Handle an SSID hotlist match event
1291 * @ctx: HDD context registered with SME
1292 * @event: The SSID hotlist match event
1293 *
1294 * This function will take an SSID match event that was generated by
1295 * firmware and will convert it into a cfg80211 vendor event which is
1296 * sent to userspace.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001297 * This callback execute in atomic context and must not invoke any
1298 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 *
1300 * Return: none
1301 */
1302static void
1303wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
1304 tpSirWifiScanResultEvent event)
1305{
1306 hdd_context_t *hdd_ctx = ctx;
1307 struct sk_buff *skb;
1308 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001309 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310
1311 ENTER();
1312
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301313 if (wlan_hdd_validate_context(hdd_ctx))
1314 return;
1315 if (!event) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001316 hdd_err("event is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001317 return;
1318 }
1319
1320 if (event->ap_found) {
1321 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001322 hdd_notice("SSID hotlist found");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 } else {
1324 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001325 hdd_notice("SSID hotlist lost");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 }
1327
1328 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1329 NULL,
1330 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001331 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332
1333 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001334 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001335 return;
1336 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07001337 hdd_notice("Req Id %u, Num results %u, More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001338 event->requestId, event->numOfAps, event->moreData);
1339
1340 for (i = 0; i < event->numOfAps; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001341 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001342 "Ssid: %s "
1343 "Bssid (" MAC_ADDRESS_STR ") "
1344 "Channel %u "
1345 "Rssi %d "
1346 "RTT %u "
1347 "RTT_SD %u",
1348 i,
1349 event->ap[i].ts,
1350 event->ap[i].ssid,
1351 MAC_ADDR_ARRAY(event->ap[i].bssid.bytes),
1352 event->ap[i].channel,
1353 event->ap[i].rssi,
1354 event->ap[i].rtt,
1355 event->ap[i].rtt_sd);
1356 }
1357
1358 if (nla_put_u32(skb,
1359 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1360 event->requestId) ||
1361 nla_put_u32(skb,
1362 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1363 event->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001364 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001365 goto fail;
1366 }
1367
1368 if (event->numOfAps) {
1369 struct nlattr *aps;
1370 aps = nla_nest_start(skb,
1371 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1372 if (!aps) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001373 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 goto fail;
1375 }
1376
1377 for (i = 0; i < event->numOfAps; i++) {
1378 struct nlattr *ap;
1379
1380 ap = nla_nest_start(skb, i);
1381 if (!ap) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001382 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 goto fail;
1384 }
1385
1386 if (nla_put_u64(skb,
1387 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
1388 event->ap[i].ts) ||
1389 nla_put(skb,
1390 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
1391 sizeof(event->ap[i].ssid),
1392 event->ap[i].ssid) ||
1393 nla_put(skb,
1394 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
1395 sizeof(event->ap[i].bssid),
1396 event->ap[i].bssid.bytes) ||
1397 nla_put_u32(skb,
1398 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
1399 event->ap[i].channel) ||
1400 nla_put_s32(skb,
1401 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
1402 event->ap[i].rssi) ||
1403 nla_put_u32(skb,
1404 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
1405 event->ap[i].rtt) ||
1406 nla_put_u32(skb,
1407 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
1408 event->ap[i].rtt_sd)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001409 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001410 goto fail;
1411 }
1412 nla_nest_end(skb, ap);
1413 }
1414 nla_nest_end(skb, aps);
1415
1416 if (nla_put_u8(skb,
1417 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1418 event->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001419 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001420 goto fail;
1421 }
1422 }
1423
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001424 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001425 return;
1426
1427fail:
1428 kfree_skb(skb);
1429 return;
1430}
1431
1432/**
1433 * wlan_hdd_cfg80211_extscan_generic_rsp() -
1434 * Handle a generic ExtScan Response message
1435 * @ctx: HDD context registered with SME
1436 * @response: The ExtScan response from firmware
1437 *
1438 * This function will handle a generic ExtScan response message from
1439 * firmware and will communicate the result to the userspace thread
1440 * that is waiting for the response.
1441 *
1442 * Return: none
1443 */
1444static void
1445wlan_hdd_cfg80211_extscan_generic_rsp
1446 (void *ctx,
1447 struct sir_extscan_generic_response *response)
1448{
1449 hdd_context_t *hdd_ctx = ctx;
1450 struct hdd_ext_scan_context *context;
1451
1452 ENTER();
1453
1454 if (wlan_hdd_validate_context(hdd_ctx) || !response) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001455 hdd_err("HDD context is not valid or response(%p) is null",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 response);
1457 return;
1458 }
1459
Jeff Johnson630f9e72016-07-25 12:00:12 -07001460 hdd_notice("request %u status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 response->request_id, response->status);
1462
1463 context = &ext_scan_context;
1464 spin_lock(&context->context_lock);
1465 if (context->request_id == response->request_id) {
1466 context->response_status = response->status ? -EINVAL : 0;
1467 complete(&context->response_event);
1468 }
1469 spin_unlock(&context->context_lock);
1470
1471 return;
1472}
1473
1474/**
1475 * wlan_hdd_cfg80211_extscan_callback() - ext scan callback
1476 * @ctx: Pointer to hdd context
1477 * @evType: Event type
1478 * @pMag: Pointer to message
1479 *
1480 * Return: none
1481 */
1482void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType,
1483 void *pMsg)
1484{
1485 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1486
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001487 /* ENTER() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301488
1489 if (wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001490 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491
Jeff Johnson630f9e72016-07-25 12:00:12 -07001492 hdd_notice("Rcvd Event %d", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001493
1494 switch (evType) {
1495 case eSIR_EXTSCAN_CACHED_RESULTS_RSP:
1496 /* There is no need to send this response to upper layer
1497 Just log the message */
Jeff Johnson630f9e72016-07-25 12:00:12 -07001498 hdd_notice("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 break;
1500
1501 case eSIR_EXTSCAN_GET_CAPABILITIES_IND:
1502 wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx,
1503 (struct ext_scan_capabilities_response *) pMsg);
1504 break;
1505
1506 case eSIR_EXTSCAN_HOTLIST_MATCH_IND:
1507 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
1508 break;
1509
1510 case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND:
1511 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx,
1512 (tpSirWifiSignificantChangeEvent) pMsg);
1513 break;
1514
1515 case eSIR_EXTSCAN_CACHED_RESULTS_IND:
1516 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
1517 break;
1518
1519 case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND:
1520 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx,
1521 (tpSirExtScanResultsAvailableIndParams) pMsg);
1522 break;
1523
1524 case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND:
1525 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx,
1526 (tpSirWifiFullScanResultEvent) pMsg);
1527 break;
1528
1529 case eSIR_EPNO_NETWORK_FOUND_IND:
1530 wlan_hdd_cfg80211_extscan_epno_match_found(ctx,
1531 (struct pno_match_found *)pMsg);
1532 break;
1533
1534 case eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND:
1535 wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx,
1536 (tpSirWifiScanResultEvent)pMsg);
1537 break;
1538
1539 case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND:
1540 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx,
1541 (tpSirExtScanOnScanEventIndParams) pMsg);
1542 break;
1543
1544 case eSIR_PASSPOINT_NETWORK_FOUND_IND:
1545 wlan_hdd_cfg80211_passpoint_match_found(ctx,
1546 (struct wifi_passpoint_match *) pMsg);
1547 break;
1548
1549 case eSIR_EXTSCAN_START_RSP:
1550 case eSIR_EXTSCAN_STOP_RSP:
1551 case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP:
1552 case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP:
1553 case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP:
1554 case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP:
1555 case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP:
1556 case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP:
1557 wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg);
1558 break;
1559
1560 default:
Jeff Johnson630f9e72016-07-25 12:00:12 -07001561 hdd_err("Unknown event type %u", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001562 break;
1563 }
1564}
1565
1566/*
1567 * define short names for the global vendor params
1568 * used by wlan_hdd_send_ext_scan_capability()
1569 */
1570#define PARAM_REQUEST_ID \
1571 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1572#define PARAM_STATUS \
1573 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1574#define MAX_SCAN_CACHE_SIZE \
1575 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1576#define MAX_SCAN_BUCKETS \
1577 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1578#define MAX_AP_CACHE_PER_SCAN \
1579 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1580#define MAX_RSSI_SAMPLE_SIZE \
1581 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1582#define MAX_SCAN_RPT_THRHOLD \
1583 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1584#define MAX_HOTLIST_BSSIDS \
1585 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1586#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1587 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1588#define MAX_BSSID_HISTORY_ENTRIES \
1589 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1590#define MAX_HOTLIST_SSIDS \
1591 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1592#define MAX_NUM_EPNO_NETS \
1593 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1594#define MAX_NUM_EPNO_NETS_BY_SSID \
1595 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1596#define MAX_NUM_WHITELISTED_SSID \
1597 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
1598
1599/**
1600 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1601 * @hdd_ctx: Pointer to hdd context
1602 *
1603 * Return: 0 for success, non-zero for failure
1604 */
1605static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx)
1606{
1607 int ret;
1608 struct sk_buff *skb;
1609 struct ext_scan_capabilities_response *data;
1610 uint32_t nl_buf_len;
1611
1612 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301613 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001614 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615
1616 data = &(ext_scan_context.capability_response);
1617
1618 nl_buf_len = NLMSG_HDRLEN;
1619 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1620 (sizeof(data->status) + NLA_HDRLEN) +
1621 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1622 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1623 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1624 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1625 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1626 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1627 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1628 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1629 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1630 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1631 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
1632 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN);
1633
1634 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1635
1636 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001637 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638 return -ENOMEM;
1639 }
1640
1641
Jeff Johnson630f9e72016-07-25 12:00:12 -07001642 hdd_notice("Req Id %u", data->requestId);
1643 hdd_notice("Status %u", data->status);
1644 hdd_notice("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001645 data->max_scan_cache_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001646 hdd_notice("Scan buckets %u", data->max_scan_buckets);
1647 hdd_notice("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 data->max_ap_cache_per_scan);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001649 hdd_notice("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650 data->max_rssi_sample_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001651 hdd_notice("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001652 data->max_scan_reporting_threshold);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001653 hdd_notice("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001654 data->max_hotlist_bssids);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001655 hdd_notice("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001656 data->max_significant_wifi_change_aps);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001657 hdd_notice("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 data->max_bssid_history_entries);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001659 hdd_notice("max_hotlist_ssids %u", data->max_hotlist_ssids);
1660 hdd_notice("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001661 data->max_number_epno_networks);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001662 hdd_notice("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001663 data->max_number_epno_networks_by_ssid);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001664 hdd_notice("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001665 data->max_number_of_white_listed_ssid);
1666
1667 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1668 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1669 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1670 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1671 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1672 data->max_ap_cache_per_scan) ||
1673 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1674 data->max_rssi_sample_size) ||
1675 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1676 data->max_scan_reporting_threshold) ||
1677 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1678 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1679 data->max_significant_wifi_change_aps) ||
1680 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1681 data->max_bssid_history_entries) ||
1682 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1683 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1684 data->max_number_epno_networks) ||
1685 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1686 data->max_number_epno_networks_by_ssid) ||
1687 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
1688 data->max_number_of_white_listed_ssid)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001689 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001690 goto nla_put_failure;
1691 }
1692
1693 cfg80211_vendor_cmd_reply(skb);
1694 return 0;
1695
1696nla_put_failure:
1697 kfree_skb(skb);
1698 return -EINVAL;
1699}
1700/*
1701 * done with short names for the global vendor params
1702 * used by wlan_hdd_send_ext_scan_capability()
1703 */
1704#undef PARAM_REQUEST_ID
1705#undef PARAM_STATUS
1706#undef MAX_SCAN_CACHE_SIZE
1707#undef MAX_SCAN_BUCKETS
1708#undef MAX_AP_CACHE_PER_SCAN
1709#undef MAX_RSSI_SAMPLE_SIZE
1710#undef MAX_SCAN_RPT_THRHOLD
1711#undef MAX_HOTLIST_BSSIDS
1712#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1713#undef MAX_BSSID_HISTORY_ENTRIES
1714#undef MAX_HOTLIST_SSIDS
1715#undef MAX_NUM_EPNO_NETS
1716#undef MAX_NUM_EPNO_NETS_BY_SSID
1717#undef MAX_NUM_WHITELISTED_SSID
1718
1719/**
1720 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1721 * @wiphy: Pointer to wireless phy
1722 * @wdev: Pointer to wireless device
1723 * @data: Pointer to data
1724 * @data_len: Data length
1725 *
1726 * Return: none
1727 */
1728static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1729 struct wireless_dev *wdev,
1730 const void *data, int data_len)
1731{
1732 int ret;
1733 unsigned long rc;
1734 struct hdd_ext_scan_context *context;
1735 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1736 struct net_device *dev = wdev->netdev;
1737 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1738 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1739 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1740 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301741 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742
Jeff Johnson1f61b612016-02-12 16:28:33 -08001743 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001744
Anurag Chouhan6d760662016-02-20 16:05:43 +05301745 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001746 hdd_err("Command not allowed in FTM mode");
1747 return -EPERM;
1748 }
1749
1750 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301751 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301754 if (!pHddCtx->config->extscan_enabled) {
1755 hdd_err("extscan not supported");
1756 return -ENOTSUPP;
1757 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001758 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1759 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001760 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001761 return -EINVAL;
1762 }
1763
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301764 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001765 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001766 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 return -ENOMEM;
1768 }
1769
1770 /* Parse and fetch request Id */
1771 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001772 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001773 goto fail;
1774 }
1775
1776 pReqMsg->requestId =
1777 nla_get_u32(tb
1778 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
1779 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001780 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781 pReqMsg->requestId, pReqMsg->sessionId);
1782
1783 context = &ext_scan_context;
1784 spin_lock(&context->context_lock);
1785 context->request_id = pReqMsg->requestId;
1786 INIT_COMPLETION(context->response_event);
1787 spin_unlock(&context->context_lock);
1788
1789 status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301790 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001791 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001792 status);
1793 goto fail;
1794 }
1795
1796 rc = wait_for_completion_timeout(&context->response_event,
1797 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1798 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001799 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001800 return -ETIMEDOUT;
1801 }
1802
1803 ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
1804 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001805 hdd_err("Failed to send ext scan capability to user space");
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301806 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001807 return ret;
1808fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301809 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 return -EINVAL;
1811}
1812
1813/**
1814 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1815 * @wiphy: Pointer to wiphy
1816 * @wdev: Pointer to wdev
1817 * @data: Pointer to data
1818 * @data_len: Data length
1819 *
1820 * Return: 0 for success, non-zero for failure
1821 */
1822int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1823 struct wireless_dev *wdev,
1824 const void *data, int data_len)
1825{
1826 int ret = 0;
1827
1828 cds_ssr_protect(__func__);
1829 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1830 data_len);
1831 cds_ssr_unprotect(__func__);
1832
1833 return ret;
1834}
1835
1836/*
1837 * define short names for the global vendor params
1838 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1839 */
1840#define PARAM_MAX \
1841 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1842#define PARAM_REQUEST_ID \
1843 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1844#define PARAM_FLUSH \
1845 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1846/**
1847 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1848 * @wiphy: wiphy pointer
1849 * @wdev: pointer to struct wireless_dev
1850 * @data: pointer to incoming NL vendor data
1851 * @data_len: length of @data
1852 *
1853 * This function parses the incoming NL vendor command data attributes and
1854 * invokes the SME Api and blocks on a completion variable.
1855 * Each WMI event with cached scan results data chunk results in
1856 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1857 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1858 *
1859 * If timeout happens before receiving all of the data, this function sets
1860 * a context variable @ignore_cached_results to %true, all of the next data
1861 * chunks are checked against this variable and dropped.
1862 *
1863 * Return: 0 on success; error number otherwise.
1864 */
1865static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1866 struct wireless_dev
1867 *wdev, const void *data,
1868 int data_len)
1869{
1870 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1871 struct net_device *dev = wdev->netdev;
1872 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1873 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1874 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1875 1];
1876 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301877 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001878 int retval = 0;
1879 unsigned long rc;
1880
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001881 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882
Anurag Chouhan6d760662016-02-20 16:05:43 +05301883 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 hdd_err("Command not allowed in FTM mode");
1885 return -EPERM;
1886 }
1887
1888 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301889 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301892 if (!pHddCtx->config->extscan_enabled) {
1893 hdd_err("extscan not supported");
1894 return -ENOTSUPP;
1895 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 if (nla_parse(tb, PARAM_MAX, data, data_len,
1897 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001898 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001899 return -EINVAL;
1900 }
1901
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301902 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001904 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 return -ENOMEM;
1906 }
1907
1908 /* Parse and fetch request Id */
1909 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001910 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 goto fail;
1912 }
1913
1914 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
1915 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001916
1917 /* Parse and fetch flush parameter */
1918 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001919 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001920 goto fail;
1921 }
1922 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001923 hdd_notice("Req Id: %u Session Id: %d Flush: %d",
1924 pReqMsg->requestId, pReqMsg->sessionId, pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001925
1926 context = &ext_scan_context;
1927 spin_lock(&context->context_lock);
1928 context->request_id = pReqMsg->requestId;
1929 context->ignore_cached_results = false;
1930 INIT_COMPLETION(context->response_event);
1931 spin_unlock(&context->context_lock);
1932
1933 status = sme_get_cached_results(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301934 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001935 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 goto fail;
1937 }
1938
1939 rc = wait_for_completion_timeout(&context->response_event,
1940 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1941 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001942 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 retval = -ETIMEDOUT;
1944 spin_lock(&context->context_lock);
1945 context->ignore_cached_results = true;
1946 spin_unlock(&context->context_lock);
1947 } else {
1948 spin_lock(&context->context_lock);
1949 retval = context->response_status;
1950 spin_unlock(&context->context_lock);
1951 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001952 return retval;
1953
1954fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301955 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956 return -EINVAL;
1957}
1958/*
1959 * done with short names for the global vendor params
1960 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1961 */
1962#undef PARAM_MAX
1963#undef PARAM_REQUEST_ID
1964#undef PARAM_FLUSH
1965
1966/**
1967 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1968 * @wiphy: wiphy pointer
1969 * @wdev: pointer to struct wireless_dev
1970 * @data: pointer to incoming NL vendor data
1971 * @data_len: length of @data
1972 *
1973 * This function parses the incoming NL vendor command data attributes and
1974 * invokes the SME Api and blocks on a completion variable.
1975 * Each WMI event with cached scan results data chunk results in
1976 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1977 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1978 *
1979 * If timeout happens before receiving all of the data, this function sets
1980 * a context variable @ignore_cached_results to %true, all of the next data
1981 * chunks are checked against this variable and dropped.
1982 *
1983 * Return: 0 on success; error number otherwise.
1984 */
1985int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1986 struct wireless_dev *wdev,
1987 const void *data, int data_len)
1988{
1989 int ret = 0;
1990
1991 cds_ssr_protect(__func__);
1992 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
1993 data_len);
1994 cds_ssr_unprotect(__func__);
1995
1996 return ret;
1997}
1998
1999/**
2000 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
2001 * @wiphy: Pointer to wireless phy
2002 * @wdev: Pointer to wireless device
2003 * @data: Pointer to data
2004 * @data_len: Data length
2005 *
2006 * Return: none
2007 */
2008static int
2009__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2010 struct wireless_dev
2011 *wdev, const void *data,
2012 int data_len)
2013{
2014 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
2015 struct net_device *dev = wdev->netdev;
2016 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2017 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2018 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2019 1];
2020 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2021 + 1];
2022 struct nlattr *apTh;
2023 struct hdd_ext_scan_context *context;
2024 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302025 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026 uint8_t i;
2027 int rem, retval;
2028 unsigned long rc;
2029
Jeff Johnson1f61b612016-02-12 16:28:33 -08002030 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002031
Anurag Chouhan6d760662016-02-20 16:05:43 +05302032 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033 hdd_err("Command not allowed in FTM mode");
2034 return -EPERM;
2035 }
2036
2037 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302038 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002039 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302041 if (!pHddCtx->config->extscan_enabled) {
2042 hdd_err("extscan not supported");
2043 return -ENOTSUPP;
2044 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2046 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002047 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002048 return -EINVAL;
2049 }
2050
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302051 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002053 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002054 return -ENOMEM;
2055 }
2056
2057 /* Parse and fetch request Id */
2058 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002059 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002060 goto fail;
2061 }
2062
2063 pReqMsg->requestId =
2064 nla_get_u32(tb
2065 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002066 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002067
2068 /* Parse and fetch number of APs */
2069 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002070 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 goto fail;
2072 }
2073 pReqMsg->numAp =
2074 nla_get_u32(tb
2075 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
2076 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002077 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 pReqMsg->numAp, pReqMsg->sessionId);
2079
2080 /* Parse and fetch lost ap sample size */
2081 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002082 hdd_err("attr lost ap sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002083 goto fail;
2084 }
2085
2086 pReqMsg->lost_ap_sample_size = nla_get_u32(
2087 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002088 hdd_notice("Lost ap sample size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002089 pReqMsg->lost_ap_sample_size);
2090
2091 i = 0;
2092 nla_for_each_nested(apTh,
2093 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2094 rem) {
2095 if (nla_parse
2096 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2097 nla_data(apTh), nla_len(apTh),
2098 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002099 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002100 goto fail;
2101 }
2102
2103 /* Parse and fetch MAC address */
2104 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002105 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002106 goto fail;
2107 }
2108 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2109 tb2
2110 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302111 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002112 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002113 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2114
2115 /* Parse and fetch low RSSI */
2116 if (!tb2
2117 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002118 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002119 goto fail;
2120 }
2121 pReqMsg->ap[i].low =
2122 nla_get_s32(tb2
2123 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002124 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002125
2126 /* Parse and fetch high RSSI */
2127 if (!tb2
2128 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002129 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 goto fail;
2131 }
2132 pReqMsg->ap[i].high =
2133 nla_get_s32(tb2
2134 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002135 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002136
2137 i++;
2138 }
2139
2140 context = &ext_scan_context;
2141 spin_lock(&context->context_lock);
2142 INIT_COMPLETION(context->response_event);
2143 context->request_id = request_id = pReqMsg->requestId;
2144 spin_unlock(&context->context_lock);
2145
2146 status = sme_set_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302147 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002148 hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002149 goto fail;
2150 }
2151
2152 /* request was sent -- wait for the response */
2153 rc = wait_for_completion_timeout
2154 (&context->response_event,
2155 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2156
2157 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002158 hdd_err("sme_set_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002159 retval = -ETIMEDOUT;
2160 } else {
2161 spin_lock(&context->context_lock);
2162 if (context->request_id == request_id)
2163 retval = context->response_status;
2164 else
2165 retval = -EINVAL;
2166 spin_unlock(&context->context_lock);
2167 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302168 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002169 return retval;
2170
2171fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302172 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173 return -EINVAL;
2174}
2175
2176/**
2177 * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist
2178 * @wiphy: Pointer to wiphy
2179 * @wdev: Pointer to wdev
2180 * @data: Pointer to data
2181 * @data_len: Data length
2182 *
2183 * Return: 0 for success, non-zero for failure
2184 */
2185int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2186 struct wireless_dev *wdev,
2187 const void *data, int data_len)
2188{
2189 int ret = 0;
2190
2191 cds_ssr_protect(__func__);
2192 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
2193 data_len);
2194 cds_ssr_unprotect(__func__);
2195
2196 return ret;
2197}
2198
2199
2200/**
2201 * __wlan_hdd_cfg80211_extscan_set_significant_change () - set significant change
2202 * @wiphy: Pointer to wireless phy
2203 * @wdev: Pointer to wireless device
2204 * @data: Pointer to data
2205 * @data_len: Data length
2206 *
2207 * Return: none
2208 */
2209static int
2210__wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2211 struct wireless_dev
2212 *wdev, const void *data,
2213 int data_len)
2214{
2215 tpSirExtScanSetSigChangeReqParams pReqMsg = NULL;
2216 struct net_device *dev = wdev->netdev;
2217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2218 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2219 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2220 1];
2221 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2222 + 1];
2223 struct nlattr *apTh;
2224 struct hdd_ext_scan_context *context;
2225 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302226 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 uint8_t i;
2228 int rem, retval;
2229 unsigned long rc;
2230
Jeff Johnson1f61b612016-02-12 16:28:33 -08002231 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002232
Anurag Chouhan6d760662016-02-20 16:05:43 +05302233 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 hdd_err("Command not allowed in FTM mode");
2235 return -EPERM;
2236 }
2237
2238 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302239 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002240 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241
2242 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2243 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002244 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002245 return -EINVAL;
2246 }
2247
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302248 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002250 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002251 return -ENOMEM;
2252 }
2253
2254 /* Parse and fetch request Id */
2255 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002256 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002257 goto fail;
2258 }
2259
2260 pReqMsg->requestId =
2261 nla_get_u32(tb
2262 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002263 hdd_notice("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002264
2265 /* Parse and fetch RSSI sample size */
2266 if (!tb
2267 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002268 hdd_err("attr RSSI sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002269 goto fail;
2270 }
2271 pReqMsg->rssiSampleSize =
2272 nla_get_u32(tb
2273 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002274 hdd_notice("RSSI sample size %u", pReqMsg->rssiSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275
2276 /* Parse and fetch lost AP sample size */
2277 if (!tb
2278 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002279 hdd_err("attr lost AP sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 goto fail;
2281 }
2282 pReqMsg->lostApSampleSize =
2283 nla_get_u32(tb
2284 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002285 hdd_notice("Lost AP sample size %u", pReqMsg->lostApSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002286
2287 /* Parse and fetch AP min breacing */
2288 if (!tb
2289 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002290 hdd_err("attr AP min breaching");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291 goto fail;
2292 }
2293 pReqMsg->minBreaching =
2294 nla_get_u32(tb
2295 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002296 hdd_notice("AP min breaching %u", pReqMsg->minBreaching);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002297
2298 /* Parse and fetch number of APs */
2299 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002300 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002301 goto fail;
2302 }
2303 pReqMsg->numAp =
2304 nla_get_u32(tb
2305 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
2306 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002307 hdd_notice("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 pReqMsg->numAp, pReqMsg->sessionId);
2309
2310 i = 0;
2311 nla_for_each_nested(apTh,
2312 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2313 rem) {
2314 if (nla_parse
2315 (tb2, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2316 nla_data(apTh), nla_len(apTh),
2317 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002318 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002319 goto fail;
2320 }
2321
2322 /* Parse and fetch MAC address */
2323 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002324 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002325 goto fail;
2326 }
2327 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2328 tb2
2329 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302330 QDF_MAC_ADDR_SIZE);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002331 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2333
2334 /* Parse and fetch low RSSI */
2335 if (!tb2
2336 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002337 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 goto fail;
2339 }
2340 pReqMsg->ap[i].low =
2341 nla_get_s32(tb2
2342 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002343 hdd_notice("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344
2345 /* Parse and fetch high RSSI */
2346 if (!tb2
2347 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002348 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002349 goto fail;
2350 }
2351 pReqMsg->ap[i].high =
2352 nla_get_s32(tb2
2353 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002354 hdd_notice("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355
2356 i++;
2357 }
2358
2359 context = &ext_scan_context;
2360 spin_lock(&context->context_lock);
2361 INIT_COMPLETION(context->response_event);
2362 context->request_id = request_id = pReqMsg->requestId;
2363 spin_unlock(&context->context_lock);
2364
2365 status = sme_set_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302366 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002367 hdd_err("sme_set_significant_change failed(err=%d)", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302368 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002369 return -EINVAL;
2370 }
2371
2372 /* request was sent -- wait for the response */
2373 rc = wait_for_completion_timeout(&context->response_event,
2374 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2375
2376 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002377 hdd_err("sme_set_significant_change timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 retval = -ETIMEDOUT;
2379 } else {
2380 spin_lock(&context->context_lock);
2381 if (context->request_id == request_id)
2382 retval = context->response_status;
2383 else
2384 retval = -EINVAL;
2385 spin_unlock(&context->context_lock);
2386 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302387 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002388 return retval;
2389
2390fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302391 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002392 return -EINVAL;
2393}
2394
2395/**
2396 * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
2397 * @wiphy: Pointer to wireless phy
2398 * @wdev: Pointer to wireless device
2399 * @data: Pointer to data
2400 * @data_len: Data length
2401 *
2402 * Return: 0 on success, negative errno on failure
2403 */
2404int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2405 struct wireless_dev *wdev,
2406 const void *data, int data_len)
2407{
2408 int ret = 0;
2409
2410 cds_ssr_protect(__func__);
2411 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev,
2412 data, data_len);
2413 cds_ssr_unprotect(__func__);
2414
2415 return ret;
2416}
2417
2418/**
2419 * hdd_remove_dsrc_channels () - remove dsrc chanels
2420 * @wiphy: Pointer to wireless phy
2421 * @chan_list: channel list
2422 * @num_channels: number of channels
2423 *
2424 * Return: none
2425 */
Jeff Johnsoncd2a0792016-10-05 15:17:13 -07002426static void hdd_remove_dsrc_channels(struct wiphy *wiphy, uint32_t *chan_list,
2427 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002428{
2429 uint8_t num_chan_temp = 0;
2430 int i;
2431
2432 for (i = 0; i < *num_channels; i++) {
2433 if (!cds_is_dsrc_channel(chan_list[i])) {
2434 chan_list[num_chan_temp] = chan_list[i];
2435 num_chan_temp++;
2436 }
2437 }
2438
2439 *num_channels = num_chan_temp;
2440}
2441
2442/**
2443 * hdd_remove_indoor_channels () - remove indoor channels
2444 * @wiphy: Pointer to wireless phy
2445 * @chan_list: channel list
2446 * @num_channels: number of channels
2447 *
2448 * Return: none
2449 */
2450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
Jeff Johnsoncd2a0792016-10-05 15:17:13 -07002451static void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2452 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453{
2454 uint8_t num_chan_temp = 0;
2455 int i, j, k;
2456
2457 for (i = 0; i < *num_channels; i++)
2458 for (j = 0; j < IEEE80211_NUM_BANDS; j++) {
2459 if (wiphy->bands[j] == NULL)
2460 continue;
2461 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
2462 if ((chan_list[i] ==
2463 wiphy->bands[j]->channels[k].center_freq)
2464 && (!(wiphy->bands[j]->channels[k].flags &
2465 IEEE80211_CHAN_INDOOR_ONLY))
2466 ) {
2467 chan_list[num_chan_temp] = chan_list[i];
2468 num_chan_temp++;
2469 }
2470 }
2471 }
2472
2473 *num_channels = num_chan_temp;
2474}
2475#else
Jeff Johnsoncd2a0792016-10-05 15:17:13 -07002476static void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2477 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478{
2479 *num_channels = 0;
2480}
2481#endif
2482
2483/**
2484 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
2485 * @wiphy: Pointer to wireless phy
2486 * @wdev: Pointer to wireless device
2487 * @data: Pointer to data
2488 * @data_len: Data length
2489 *
2490 * Return: none
2491 */
2492static int
2493__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2494 struct wireless_dev
2495 *wdev, const void *data,
2496 int data_len)
2497{
2498 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2499 struct net_device *dev = wdev->netdev;
2500 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2501 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002502 uint8_t num_channels = 0, i, buf[256] = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002503 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2504 1];
2505 uint32_t requestId, maxChannels;
2506 tWifiBand wifiBand;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302507 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508 struct sk_buff *reply_skb;
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002509 int ret, len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002511 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512
Anurag Chouhan6d760662016-02-20 16:05:43 +05302513 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 hdd_err("Command not allowed in FTM mode");
2515 return -EPERM;
2516 }
2517
2518 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302519 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302522 if (!pHddCtx->config->extscan_enabled) {
2523 hdd_err("extscan not supported");
2524 return -ENOTSUPP;
2525 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2527 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002528 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529 return -EINVAL;
2530 }
2531
2532 /* Parse and fetch request Id */
2533 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002534 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535 return -EINVAL;
2536 }
2537 requestId =
2538 nla_get_u32(tb
2539 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002540
2541 /* Parse and fetch wifi band */
2542 if (!tb
2543 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002544 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 return -EINVAL;
2546 }
2547 wifiBand =
2548 nla_get_u32(tb
2549 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002550
2551 if (!tb
2552 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002553 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 return -EINVAL;
2555 }
2556 maxChannels =
2557 nla_get_u32(tb
2558 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002559 hdd_notice("Req Id: %u Wifi band: %d Max channels: %d", requestId,
2560 wifiBand, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 status = sme_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal),
2562 wifiBand, chan_list,
2563 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302564 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002565 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002566 status);
2567 return -EINVAL;
2568 }
2569
Anurag Chouhan6d760662016-02-20 16:05:43 +05302570 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002571
2572 hdd_remove_dsrc_channels(wiphy, chan_list, &num_channels);
2573
Krunal Sonibe766b02016-03-10 13:00:44 -08002574 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 !strncmp(hdd_get_fwpath(), "ap", 2))
2576 hdd_remove_indoor_channels(wiphy, chan_list, &num_channels);
2577
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002578 hdd_notice("Number of channels: %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579 for (i = 0; i < num_channels; i++)
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002580 len += scnprintf(buf + len, sizeof(buf) - len,
2581 "%u ", chan_list[i]);
2582
2583 hdd_notice("Channels: %s", buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002584
2585 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2586 sizeof(u32) *
2587 num_channels +
2588 NLMSG_HDRLEN);
2589
2590 if (reply_skb) {
2591 if (nla_put_u32(reply_skb,
2592 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2593 num_channels) ||
2594 nla_put(reply_skb,
2595 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2596 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002597 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002598 kfree_skb(reply_skb);
2599 return -EINVAL;
2600 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302601 ret = cfg80211_vendor_cmd_reply(reply_skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302602 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002603 }
2604
Jeff Johnson630f9e72016-07-25 12:00:12 -07002605 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002606 return -EINVAL;
2607}
2608
2609/**
2610 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2611 * @wiphy: Pointer to wireless phy
2612 * @wdev: Pointer to wireless device
2613 * @data: Pointer to data
2614 * @data_len: Data length
2615 *
2616 * Return: 0 on success, negative errno on failure
2617 */
2618int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2619 struct wireless_dev *wdev,
2620 const void *data, int data_len)
2621{
2622 int ret = 0;
2623
2624 cds_ssr_protect(__func__);
2625 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2626 data_len);
2627 cds_ssr_unprotect(__func__);
2628
2629 return ret;
2630}
2631
2632/**
2633 * hdd_extscan_update_dwell_time_limits() - update dwell times
2634 * @req_msg: Pointer to request message
2635 * @bkt_idx: Index of current bucket being processed
2636 * @active_min: minimum active dwell time
2637 * @active_max: maximum active dwell time
2638 * @passive_min: minimum passive dwell time
2639 * @passive_max: maximum passive dwell time
2640 *
2641 * Return: none
2642 */
2643static void hdd_extscan_update_dwell_time_limits(
2644 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2645 uint32_t active_min, uint32_t active_max,
2646 uint32_t passive_min, uint32_t passive_max)
2647{
2648 /* update per-bucket dwell times */
2649 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2650 active_min) {
2651 req_msg->buckets[bkt_idx].min_dwell_time_active =
2652 active_min;
2653 }
2654 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2655 active_max) {
2656 req_msg->buckets[bkt_idx].max_dwell_time_active =
2657 active_max;
2658 }
2659 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2660 passive_min) {
2661 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2662 passive_min;
2663 }
2664 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2665 passive_max) {
2666 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2667 passive_max;
2668 }
2669 /* update dwell-time across all buckets */
2670 if (req_msg->min_dwell_time_active >
2671 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2672 req_msg->min_dwell_time_active =
2673 req_msg->buckets[bkt_idx].min_dwell_time_active;
2674 }
2675 if (req_msg->max_dwell_time_active <
2676 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2677 req_msg->max_dwell_time_active =
2678 req_msg->buckets[bkt_idx].max_dwell_time_active;
2679 }
2680 if (req_msg->min_dwell_time_passive >
2681 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2682 req_msg->min_dwell_time_passive =
2683 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2684 }
2685 if (req_msg->max_dwell_time_passive >
2686 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2687 req_msg->max_dwell_time_passive =
2688 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2689 }
2690}
2691
2692/**
2693 * hdd_extscan_channel_max_reached() - channel max reached
2694 * @req: extscan request structure
2695 * @total_channels: total number of channels
2696 *
2697 * Return: true if total channels reached max, false otherwise
2698 */
2699static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2700 uint8_t total_channels)
2701{
2702 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2703 hdd_warn(
2704 "max #of channels %d reached, take only first %d bucket(s)",
2705 total_channels, req->numBuckets);
2706 return true;
2707 }
2708 return false;
2709}
2710
2711/**
2712 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2713 * @hdd_ctx: HDD global context
2714 * @req_msg: Pointer to request structure
2715 * @tb: pointer to NL attributes
2716 *
2717 * Return: 0 on success; error number otherwise
2718 */
2719static int hdd_extscan_start_fill_bucket_channel_spec(
2720 hdd_context_t *hdd_ctx,
2721 tpSirWifiScanCmdReqParams req_msg,
2722 struct nlattr **tb)
2723{
2724 struct nlattr *bucket[
2725 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2726 struct nlattr *channel[
2727 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2728 struct nlattr *buckets;
2729 struct nlattr *channels;
2730 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302731 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002732 uint8_t bkt_index, j, num_channels, total_channels = 0;
2733 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2734
2735 uint32_t min_dwell_time_active_bucket =
2736 hdd_ctx->config->extscan_active_max_chn_time;
2737 uint32_t max_dwell_time_active_bucket =
2738 hdd_ctx->config->extscan_active_max_chn_time;
2739 uint32_t min_dwell_time_passive_bucket =
2740 hdd_ctx->config->extscan_passive_max_chn_time;
2741 uint32_t max_dwell_time_passive_bucket =
2742 hdd_ctx->config->extscan_passive_max_chn_time;
2743
2744 bkt_index = 0;
2745 req_msg->min_dwell_time_active =
2746 req_msg->max_dwell_time_active =
2747 hdd_ctx->config->extscan_active_max_chn_time;
2748
2749 req_msg->min_dwell_time_passive =
2750 req_msg->max_dwell_time_passive =
2751 hdd_ctx->config->extscan_passive_max_chn_time;
2752 req_msg->numBuckets = 0;
2753
2754 nla_for_each_nested(buckets,
2755 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
2756 if (nla_parse(bucket,
2757 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2758 nla_data(buckets), nla_len(buckets), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002759 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760 return -EINVAL;
2761 }
2762
2763 /* Parse and fetch bucket spec */
2764 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002765 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 return -EINVAL;
2767 }
2768 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2769 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002770
2771 /* Parse and fetch wifi band */
2772 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002773 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002774 return -EINVAL;
2775 }
2776 req_msg->buckets[bkt_index].band = nla_get_u8(
2777 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002778
2779 /* Parse and fetch period */
2780 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002781 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782 return -EINVAL;
2783 }
2784 req_msg->buckets[bkt_index].period = nla_get_u32(
2785 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786
2787 /* Parse and fetch report events */
2788 if (!bucket[
2789 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002790 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 return -EINVAL;
2792 }
2793 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2794 bucket[
2795 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796
2797 /* Parse and fetch max period */
2798 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002799 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 return -EINVAL;
2801 }
2802 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2803 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002804
Mukul Sharmafa937be2016-08-12 18:13:36 +05302805 /* Parse and fetch base */
2806 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]) {
2807 hdd_err("attr base failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808 return -EINVAL;
2809 }
2810 req_msg->buckets[bkt_index].exponent = nla_get_u32(
Mukul Sharmafa937be2016-08-12 18:13:36 +05302811 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812
2813 /* Parse and fetch step count */
2814 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002815 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 return -EINVAL;
2817 }
2818 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2819 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002820 hdd_notice("Bucket spec Index: %d Wifi band: %d period: %d report events: %d max period: %u base: %u Step count: %u",
2821 req_msg->buckets[bkt_index].bucket,
2822 req_msg->buckets[bkt_index].band,
2823 req_msg->buckets[bkt_index].period,
2824 req_msg->buckets[bkt_index].reportEvents,
2825 req_msg->buckets[bkt_index].max_period,
2826 req_msg->buckets[bkt_index].exponent,
2827 req_msg->buckets[bkt_index].step_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002828
2829 /* start with known good values for bucket dwell times */
2830 req_msg->buckets[bkt_index].min_dwell_time_active =
2831 req_msg->buckets[bkt_index].max_dwell_time_active =
2832 hdd_ctx->config->extscan_active_max_chn_time;
2833
2834 req_msg->buckets[bkt_index].min_dwell_time_passive =
2835 req_msg->buckets[bkt_index].max_dwell_time_passive =
2836 hdd_ctx->config->extscan_passive_max_chn_time;
2837
2838 /* Framework shall pass the channel list if the input WiFi band
2839 * is WIFI_BAND_UNSPECIFIED.
2840 * If the input WiFi band is specified (any value other than
2841 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2842 */
2843 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2844 if (hdd_extscan_channel_max_reached(req_msg,
2845 total_channels))
2846 return 0;
2847
2848 num_channels = 0;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002849 hdd_notice("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002850 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2851 req_msg->buckets[bkt_index].band,
2852 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302853 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002854 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002855 status);
2856 return -EINVAL;
2857 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07002858 hdd_notice("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002859 num_channels);
2860
2861 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302862 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002863 (WLAN_EXTSCAN_MAX_CHANNELS -
2864 total_channels));
2865 hdd_info("Adj Num channels/bucket: %d total_channels: %d",
2866 req_msg->buckets[bkt_index].numChannels,
2867 total_channels);
2868 total_channels +=
2869 req_msg->buckets[bkt_index].numChannels;
2870
2871 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2872 j++) {
2873 req_msg->buckets[bkt_index].channels[j].channel =
2874 chan_list[j];
2875 req_msg->buckets[bkt_index].channels[j].
2876 chnlClass = 0;
2877 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2878 cds_freq_to_chan(chan_list[j]))) {
2879 req_msg->buckets[bkt_index].channels[j].
2880 passive = 1;
2881 req_msg->buckets[bkt_index].channels[j].
2882 dwellTimeMs =
2883 hdd_ctx->config->
2884 extscan_passive_max_chn_time;
2885 /* reconfigure per-bucket dwell time */
2886 if (min_dwell_time_passive_bucket >
2887 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2888 min_dwell_time_passive_bucket =
2889 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2890 }
2891 if (max_dwell_time_passive_bucket <
2892 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2893 max_dwell_time_passive_bucket =
2894 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2895 }
2896
2897 } else {
2898 req_msg->buckets[bkt_index].channels[j].
2899 passive = 0;
2900 req_msg->buckets[bkt_index].channels[j].
2901 dwellTimeMs =
2902 hdd_ctx->config->extscan_active_max_chn_time;
2903 /* reconfigure per-bucket dwell times */
2904 if (min_dwell_time_active_bucket >
2905 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2906 min_dwell_time_active_bucket =
2907 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2908 }
2909 if (max_dwell_time_active_bucket <
2910 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2911 max_dwell_time_active_bucket =
2912 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2913 }
2914
2915 }
2916
Jeff Johnson630f9e72016-07-25 12:00:12 -07002917 hdd_notice("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918 req_msg->buckets[bkt_index].channels[j].channel,
2919 req_msg->buckets[bkt_index].channels[j].passive,
2920 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2921 req_msg->buckets[bkt_index].channels[j].chnlClass);
2922 }
2923
2924 hdd_extscan_update_dwell_time_limits(
2925 req_msg, bkt_index,
2926 min_dwell_time_active_bucket,
2927 max_dwell_time_active_bucket,
2928 min_dwell_time_passive_bucket,
2929 max_dwell_time_passive_bucket);
2930
Jeff Johnson630f9e72016-07-25 12:00:12 -07002931 hdd_notice("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002932 bkt_index,
2933 req_msg->buckets[bkt_index].min_dwell_time_active,
2934 req_msg->buckets[bkt_index].max_dwell_time_active,
2935 req_msg->buckets[bkt_index].min_dwell_time_passive,
2936 req_msg->buckets[bkt_index].max_dwell_time_passive);
2937
2938 bkt_index++;
2939 req_msg->numBuckets++;
2940 continue;
2941 }
2942
2943 /* Parse and fetch number of channels */
2944 if (!bucket[
2945 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002946 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002947 return -EINVAL;
2948 }
2949 req_msg->buckets[bkt_index].numChannels =
2950 nla_get_u32(bucket[
2951 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
2952 hdd_info("before trimming: num channels %d",
2953 req_msg->buckets[bkt_index].numChannels);
2954
2955 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302956 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
2958 hdd_info("Num channels/bucket: %d total_channels: %d",
2959 req_msg->buckets[bkt_index].numChannels,
2960 total_channels);
2961 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
2962 return 0;
2963
2964 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002965 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002966 return -EINVAL;
2967 }
2968
2969 j = 0;
2970 nla_for_each_nested(channels,
2971 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07002972 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
2973 hdd_extscan_channel_max_reached(req_msg,
2974 total_channels))
2975 break;
2976
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977 if (nla_parse(channel,
2978 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2979 nla_data(channels), nla_len(channels),
2980 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002981 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 return -EINVAL;
2983 }
2984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 /* Parse and fetch channel */
2986 if (!channel[
2987 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002988 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002989 return -EINVAL;
2990 }
2991 req_msg->buckets[bkt_index].channels[j].channel =
2992 nla_get_u32(channel[
2993 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002994 hdd_notice("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 req_msg->buckets[bkt_index].channels[j].channel);
2996
2997 /* Parse and fetch dwell time */
2998 if (!channel[
2999 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003000 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 return -EINVAL;
3002 }
3003 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3004 nla_get_u32(channel[
3005 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
3006
3007 /* Override dwell time if required */
3008 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
3009 hdd_ctx->config->extscan_active_min_chn_time ||
3010 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
3011 hdd_ctx->config->extscan_active_max_chn_time) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003012 hdd_notice("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3014
3015 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3016 cds_freq_to_chan(
3017 req_msg->buckets[bkt_index].channels[j].channel))) {
3018 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3019 hdd_ctx->config->extscan_passive_max_chn_time;
3020 } else {
3021 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3022 hdd_ctx->config->extscan_active_max_chn_time;
3023 }
3024 }
3025
Jeff Johnson630f9e72016-07-25 12:00:12 -07003026 hdd_notice("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3028
3029 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3030 cds_freq_to_chan(
3031 req_msg->buckets[bkt_index].channels[j].channel))) {
3032 if (min_dwell_time_passive_bucket >
3033 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3034 min_dwell_time_passive_bucket =
3035 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3036 }
3037 if (max_dwell_time_passive_bucket <
3038 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3039 max_dwell_time_passive_bucket =
3040 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3041 }
3042 } else {
3043 if (min_dwell_time_active_bucket >
3044 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3045 min_dwell_time_active_bucket =
3046 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3047 }
3048 if (max_dwell_time_active_bucket <
3049 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3050 max_dwell_time_active_bucket =
3051 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3052 }
3053 }
3054
3055 /* Parse and fetch channel spec passive */
3056 if (!channel[
3057 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003058 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003059 return -EINVAL;
3060 }
3061 req_msg->buckets[bkt_index].channels[j].passive =
3062 nla_get_u8(channel[
3063 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003064 hdd_notice("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 req_msg->buckets[bkt_index].channels[j].passive);
3066 /* Override scan type if required */
3067 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3068 cds_freq_to_chan(
3069 req_msg->buckets[bkt_index].channels[j].channel))) {
3070 req_msg->buckets[bkt_index].channels[j].passive = true;
3071 } else {
3072 req_msg->buckets[bkt_index].channels[j].passive = false;
3073 }
3074 j++;
3075 total_channels++;
3076 }
3077
3078 hdd_extscan_update_dwell_time_limits(
3079 req_msg, bkt_index,
3080 min_dwell_time_active_bucket,
3081 max_dwell_time_active_bucket,
3082 min_dwell_time_passive_bucket,
3083 max_dwell_time_passive_bucket);
3084
Jeff Johnson630f9e72016-07-25 12:00:12 -07003085 hdd_notice("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003086 bkt_index,
3087 req_msg->buckets[bkt_index].min_dwell_time_active,
3088 req_msg->buckets[bkt_index].max_dwell_time_active,
3089 req_msg->buckets[bkt_index].min_dwell_time_passive,
3090 req_msg->buckets[bkt_index].max_dwell_time_passive);
3091
3092 bkt_index++;
3093 req_msg->numBuckets++;
3094 }
3095
Jeff Johnson630f9e72016-07-25 12:00:12 -07003096 hdd_notice("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003097 req_msg->min_dwell_time_active,
3098 req_msg->max_dwell_time_active,
3099 req_msg->min_dwell_time_passive,
3100 req_msg->max_dwell_time_passive);
3101
3102 return 0;
3103}
3104
3105/*
3106 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3107 * @config_flags - [input] configuration flags.
3108 *
3109 * This function maps user space received configuration flags to
3110 * driver representation.
3111 *
3112 * Return: configuration flags
3113 */
3114static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3115{
3116 uint32_t configuration_flags = 0;
3117
3118 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3119 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3120
3121 return configuration_flags;
3122}
3123
3124/*
3125 * define short names for the global vendor params
3126 * used by __wlan_hdd_cfg80211_extscan_start()
3127 */
3128#define PARAM_MAX \
3129 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3130#define PARAM_REQUEST_ID \
3131 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3132#define PARAM_BASE_PERIOD \
3133 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3134#define PARAM_MAX_AP_PER_SCAN \
3135 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3136#define PARAM_RPT_THRHLD_PERCENT \
3137 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3138#define PARAM_RPT_THRHLD_NUM_SCANS \
3139 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3140#define PARAM_NUM_BUCKETS \
3141 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3142#define PARAM_CONFIG_FLAGS \
3143 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3144
3145/**
3146 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3147 * @wiphy: Pointer to wireless phy
3148 * @wdev: Pointer to wireless device
3149 * @data: Pointer to data
3150 * @data_len: Length of @data
3151 *
3152 * Return: 0 on success; error number otherwise
3153 */
3154static int
3155__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3156 struct wireless_dev *wdev,
3157 const void *data,
3158 int data_len)
3159{
3160 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3161 struct net_device *dev = wdev->netdev;
3162 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3163 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3164 struct nlattr *tb[PARAM_MAX + 1];
3165 struct hdd_ext_scan_context *context;
3166 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303167 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003168 int retval;
3169 unsigned long rc;
3170
Jeff Johnson1f61b612016-02-12 16:28:33 -08003171 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172
Anurag Chouhan6d760662016-02-20 16:05:43 +05303173 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 hdd_err("Command not allowed in FTM mode");
3175 return -EPERM;
3176 }
3177
3178 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303179 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003181
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303182 if (!pHddCtx->config->extscan_enabled) {
3183 hdd_err("extscan not supported");
3184 return -ENOTSUPP;
3185 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186 if (nla_parse(tb, PARAM_MAX, data, data_len,
3187 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003188 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003189 return -EINVAL;
3190 }
3191
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303192 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003194 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 return -ENOMEM;
3196 }
3197
3198 /* Parse and fetch request Id */
3199 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003200 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201 goto fail;
3202 }
3203
3204 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3205 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206
3207 /* Parse and fetch base period */
3208 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003209 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 goto fail;
3211 }
3212 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003213
3214 /* Parse and fetch max AP per scan */
3215 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003216 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217 goto fail;
3218 }
3219 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220
3221 /* Parse and fetch report threshold percent */
3222 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003223 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224 goto fail;
3225 }
3226 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227
3228 /* Parse and fetch report threshold num scans */
3229 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003230 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003231 goto fail;
3232 }
3233 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003234 hdd_notice("Req Id: %d Session Id: %d Base Period: %d Max AP per Scan: %d Report Threshold percent: %d Report Threshold num scans: %d",
3235 pReqMsg->requestId, pReqMsg->sessionId,
3236 pReqMsg->basePeriod, pReqMsg->maxAPperScan,
3237 pReqMsg->report_threshold_percent,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238 pReqMsg->report_threshold_num_scans);
3239
3240 /* Parse and fetch number of buckets */
3241 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003242 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243 goto fail;
3244 }
3245 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3246 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3247 hdd_warn("Exceeded MAX number of buckets: %d",
3248 WLAN_EXTSCAN_MAX_BUCKETS);
3249 }
3250 hdd_info("Input: Number of Buckets %d", num_buckets);
3251
3252 /* This is optional attribute, if not present set it to 0 */
3253 if (!tb[PARAM_CONFIG_FLAGS])
3254 pReqMsg->configuration_flags = 0;
3255 else
3256 pReqMsg->configuration_flags =
3257 hdd_extscan_map_usr_drv_config_flags(
3258 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3259
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303260 pReqMsg->extscan_adaptive_dwell_mode =
3261 pHddCtx->config->extscan_adaptive_dwell_mode;
3262
Jeff Johnson630f9e72016-07-25 12:00:12 -07003263 hdd_notice("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264 pReqMsg->configuration_flags);
3265
3266 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003267 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003268 goto fail;
3269 }
3270
3271 if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb))
3272 goto fail;
3273
3274 context = &ext_scan_context;
3275 spin_lock(&context->context_lock);
3276 INIT_COMPLETION(context->response_event);
3277 context->request_id = request_id = pReqMsg->requestId;
Mukul Sharmafa937be2016-08-12 18:13:36 +05303278 context->buckets_scanned = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 spin_unlock(&context->context_lock);
3280
3281 status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303282 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003283 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003284 goto fail;
3285 }
3286
Anurag Chouhan50220ce2016-02-18 20:11:33 +05303287 pHddCtx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Jeff Johnson630f9e72016-07-25 12:00:12 -07003288 hdd_notice("Timestamp since boot: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003289 pHddCtx->ext_scan_start_since_boot);
3290
3291 /* request was sent -- wait for the response */
3292 rc = wait_for_completion_timeout(&context->response_event,
3293 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3294
3295 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003296 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003297 retval = -ETIMEDOUT;
3298 } else {
3299 spin_lock(&context->context_lock);
3300 if (context->request_id == request_id)
3301 retval = context->response_status;
3302 else
3303 retval = -EINVAL;
3304 spin_unlock(&context->context_lock);
3305 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303306 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003307 return retval;
3308
3309fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303310 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311 return -EINVAL;
3312}
3313/*
3314 * done with short names for the global vendor params
3315 * used by __wlan_hdd_cfg80211_extscan_start()
3316 */
3317#undef PARAM_MAX
3318#undef PARAM_REQUEST_ID
3319#undef PARAM_BASE_PERIOD
3320#undef PARAMS_MAX_AP_PER_SCAN
3321#undef PARAMS_RPT_THRHLD_PERCENT
3322#undef PARAMS_RPT_THRHLD_NUM_SCANS
3323#undef PARAMS_NUM_BUCKETS
3324#undef PARAM_CONFIG_FLAGS
3325
3326/**
3327 * wlan_hdd_cfg80211_extscan_start() - start extscan
3328 * @wiphy: Pointer to wireless phy.
3329 * @wdev: Pointer to wireless device.
3330 * @data: Pointer to input data.
3331 * @data_len: Length of @data.
3332 *
3333 * Return: 0 on success, negative errno on failure
3334 */
3335int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3336 struct wireless_dev *wdev,
3337 const void *data, int data_len)
3338{
3339 int ret = 0;
3340
3341 cds_ssr_protect(__func__);
3342 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3343 cds_ssr_unprotect(__func__);
3344
3345 return ret;
3346}
3347
3348
3349/*
3350 * define short names for the global vendor params
3351 * used by __wlan_hdd_cfg80211_extscan_stop()
3352 */
3353#define PARAM_MAX \
3354 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3355#define PARAM_REQUEST_ID \
3356 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3357
3358/**
3359 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3360 * @wiphy: Pointer to wireless phy
3361 * @wdev: Pointer to wireless device
3362 * @data: Pointer to data
3363 * @data_len: Data length
3364 *
3365 * Return: none
3366 */
3367static int
3368__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3369 struct wireless_dev *wdev,
3370 const void *data, int data_len)
3371{
3372 tpSirExtScanStopReqParams pReqMsg = NULL;
3373 struct net_device *dev = wdev->netdev;
3374 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3375 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3376 struct nlattr *tb[PARAM_MAX + 1];
3377 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303378 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003379 uint32_t request_id;
3380 int retval;
3381 unsigned long rc;
3382
Jeff Johnson1f61b612016-02-12 16:28:33 -08003383 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003384
Anurag Chouhan6d760662016-02-20 16:05:43 +05303385 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003386 hdd_err("Command not allowed in FTM mode");
3387 return -EPERM;
3388 }
3389
3390 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303391 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003392 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003393
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303394 if (!pHddCtx->config->extscan_enabled) {
3395 hdd_err("extscan not supported");
3396 return -ENOTSUPP;
3397 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398 if (nla_parse(tb, PARAM_MAX, data, data_len,
3399 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003400 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003401 return -EINVAL;
3402 }
3403
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303404 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003405 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003406 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407 return -ENOMEM;
3408 }
3409
3410 /* Parse and fetch request Id */
3411 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003412 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003413 goto fail;
3414 }
3415
3416 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3417 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003418 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003419 pReqMsg->requestId, pReqMsg->sessionId);
3420
3421 context = &ext_scan_context;
3422 spin_lock(&context->context_lock);
3423 INIT_COMPLETION(context->response_event);
3424 context->request_id = request_id = pReqMsg->requestId;
3425 spin_unlock(&context->context_lock);
3426
3427 status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303428 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003429 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003430 goto fail;
3431 }
3432
3433 /* request was sent -- wait for the response */
3434 rc = wait_for_completion_timeout(&context->response_event,
3435 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3436
3437 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003438 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003439 retval = -ETIMEDOUT;
3440 } else {
3441 spin_lock(&context->context_lock);
3442 if (context->request_id == request_id)
3443 retval = context->response_status;
3444 else
3445 retval = -EINVAL;
3446 spin_unlock(&context->context_lock);
3447 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303448 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003449 return retval;
3450
3451fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303452 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003453 return -EINVAL;
3454}
3455/*
3456 * done with short names for the global vendor params
3457 * used by wlan_hdd_cfg80211_extscan_stop()
3458 */
3459#undef PARAM_MAX
3460#undef PARAM_REQUEST_ID
3461
3462
3463/**
3464 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3465 * @wiphy: Pointer to wireless phy.
3466 * @wdev: Pointer to wireless device.
3467 * @data: Pointer to input data.
3468 * @data_len: Length of @data.
3469 *
3470 * Return: 0 on success, negative errno on failure
3471 */
3472int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3473 struct wireless_dev *wdev,
3474 const void *data, int data_len)
3475{
3476 int ret = 0;
3477
3478 cds_ssr_protect(__func__);
3479 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3480 cds_ssr_unprotect(__func__);
3481
3482 return ret;
3483}
3484
3485
3486/**
3487 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3488 * @wiphy: Pointer to wireless phy
3489 * @wdev: Pointer to wireless device
3490 * @data: Pointer to data
3491 * @data_len: Data length
3492 *
3493 * Return: none
3494 */
3495static int
3496__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3497 struct wireless_dev
3498 *wdev, const void *data,
3499 int data_len)
3500{
3501 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3502 struct net_device *dev = wdev->netdev;
3503 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3504 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3505 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3506 1];
3507 struct hdd_ext_scan_context *context;
3508 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303509 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003510 int retval;
3511 unsigned long rc;
3512
Jeff Johnson1f61b612016-02-12 16:28:33 -08003513 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514
Anurag Chouhan6d760662016-02-20 16:05:43 +05303515 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003516 hdd_err("Command not allowed in FTM mode");
3517 return -EPERM;
3518 }
3519
3520 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303521 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303524 if (!pHddCtx->config->extscan_enabled) {
3525 hdd_err("extscan not supported");
3526 return -ENOTSUPP;
3527 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3529 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003530 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 return -EINVAL;
3532 }
3533
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303534 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003535 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003536 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537 return -ENOMEM;
3538 }
3539
3540 /* Parse and fetch request Id */
3541 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003542 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003543 goto fail;
3544 }
3545
3546 pReqMsg->requestId =
3547 nla_get_u32(tb
3548 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3549 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003550 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003551 pReqMsg->requestId, pReqMsg->sessionId);
3552
3553 context = &ext_scan_context;
3554 spin_lock(&context->context_lock);
3555 INIT_COMPLETION(context->response_event);
3556 context->request_id = request_id = pReqMsg->requestId;
3557 spin_unlock(&context->context_lock);
3558
3559 status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303560 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003561 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 goto fail;
3563 }
3564
3565 /* request was sent -- wait for the response */
3566 rc = wait_for_completion_timeout
3567 (&context->response_event,
3568 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3569 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003570 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003571 retval = -ETIMEDOUT;
3572 } else {
3573 spin_lock(&context->context_lock);
3574 if (context->request_id == request_id)
3575 retval = context->response_status;
3576 else
3577 retval = -EINVAL;
3578 spin_unlock(&context->context_lock);
3579 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303580 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003581 return retval;
3582
3583fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303584 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003585 return -EINVAL;
3586}
3587
3588/**
3589 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3590 * @wiphy: Pointer to wireless phy
3591 * @wdev: Pointer to wireless device
3592 * @data: Pointer to data
3593 * @data_len: Data length
3594 *
3595 * Return: 0 on success, negative errno on failure
3596 */
3597int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3598 struct wireless_dev *wdev,
3599 const void *data, int data_len)
3600{
3601 int ret = 0;
3602
3603 cds_ssr_protect(__func__);
3604 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3605 data, data_len);
3606 cds_ssr_unprotect(__func__);
3607
3608 return ret;
3609}
3610
3611/**
3612 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3613 * reset significant change
3614 * @wiphy: Pointer to wireless phy
3615 * @wdev: Pointer to wireless device
3616 * @data: Pointer to data
3617 * @data_len: Data length
3618 *
3619 * Return: none
3620 */
3621static int
3622__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3623 *wiphy,
3624 struct
3625 wireless_dev
3626 *wdev, const void *data,
3627 int data_len)
3628{
3629 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3630 struct net_device *dev = wdev->netdev;
3631 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3632 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3633 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3634 1];
3635 struct hdd_ext_scan_context *context;
3636 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303637 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638 int retval;
3639 unsigned long rc;
3640
Jeff Johnson1f61b612016-02-12 16:28:33 -08003641 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642
Anurag Chouhan6d760662016-02-20 16:05:43 +05303643 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 hdd_err("Command not allowed in FTM mode");
3645 return -EPERM;
3646 }
3647
3648 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303649 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003651
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303652 if (!pHddCtx->config->extscan_enabled) {
3653 hdd_err("extscan not supported");
3654 return -ENOTSUPP;
3655 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3657 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003658 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003659 return -EINVAL;
3660 }
3661
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303662 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003663 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003664 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003665 return -ENOMEM;
3666 }
3667
3668 /* Parse and fetch request Id */
3669 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003670 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003671 goto fail;
3672 }
3673
3674 pReqMsg->requestId =
3675 nla_get_u32(tb
3676 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3677 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003678 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003679 pReqMsg->requestId, pReqMsg->sessionId);
3680
3681 context = &ext_scan_context;
3682 spin_lock(&context->context_lock);
3683 INIT_COMPLETION(context->response_event);
3684 context->request_id = request_id = pReqMsg->requestId;
3685 spin_unlock(&context->context_lock);
3686
3687 status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303688 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003689 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303691 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 return -EINVAL;
3693 }
3694
3695 /* request was sent -- wait for the response */
3696 rc = wait_for_completion_timeout(&context->response_event,
3697 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3698
3699 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003700 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003701 retval = -ETIMEDOUT;
3702 } else {
3703 spin_lock(&context->context_lock);
3704 if (context->request_id == request_id)
3705 retval = context->response_status;
3706 else
3707 retval = -EINVAL;
3708 spin_unlock(&context->context_lock);
3709 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303710 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003711 return retval;
3712
3713fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303714 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715 return -EINVAL;
3716}
3717
3718/**
3719 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3720 * change
3721 * @wiphy: Pointer to wireless phy
3722 * @wdev: Pointer to wireless device
3723 * @data: Pointer to data
3724 * @data_len: Data length
3725 *
3726 * Return: 0 on success, negative errno on failure
3727 */
3728int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3729 struct wireless_dev *wdev,
3730 const void *data, int data_len)
3731{
3732 int ret = 0;
3733
3734 cds_ssr_protect(__func__);
3735 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3736 data, data_len);
3737 cds_ssr_unprotect(__func__);
3738
3739 return ret;
3740}
3741
3742
3743/**
3744 * hdd_extscan_epno_fill_network_list() - epno fill network list
3745 * @hddctx: HDD context
3746 * @req_msg: request message
3747 * @tb: vendor attribute table
3748 *
3749 * This function reads the network block NL vendor attributes from %tb and
3750 * fill in the epno request message.
3751 *
3752 * Return: 0 on success, error number otherwise
3753 */
3754static int hdd_extscan_epno_fill_network_list(
3755 hdd_context_t *hddctx,
3756 struct wifi_epno_params *req_msg,
3757 struct nlattr **tb)
3758{
3759 struct nlattr *network[
3760 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3761 struct nlattr *networks;
3762 int rem1, ssid_len;
3763 uint8_t index, *ssid;
3764
3765 index = 0;
3766 nla_for_each_nested(networks,
3767 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3768 rem1) {
3769 if (nla_parse(network,
3770 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3771 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003772 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003773 return -EINVAL;
3774 }
3775
3776 /* Parse and fetch ssid */
3777 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003778 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003779 return -EINVAL;
3780 }
3781 ssid_len = nla_len(
3782 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3783
3784 /* Decrement by 1, don't count null character */
3785 ssid_len--;
3786
3787 req_msg->networks[index].ssid.length = ssid_len;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003788 hdd_notice("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003789 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303790 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003791 ssid, ssid_len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003792 hdd_notice("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793 req_msg->networks[index].ssid.length,
3794 req_msg->networks[index].ssid.ssId);
3795
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003796 /* Parse and fetch epno flags */
3797 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003798 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003799 return -EINVAL;
3800 }
3801 req_msg->networks[index].flags = nla_get_u8(
3802 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003803 hdd_notice("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003804
3805 /* Parse and fetch auth bit */
3806 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003807 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003808 return -EINVAL;
3809 }
3810 req_msg->networks[index].auth_bit_field = nla_get_u8(
3811 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003812 hdd_notice("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 req_msg->networks[index].auth_bit_field);
3814
3815 index++;
3816 }
3817 return 0;
3818}
3819
3820/**
3821 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3822 * @wiphy: wiphy
3823 * @wdev: pointer to wireless dev
3824 * @data: data pointer
3825 * @data_len: data length
3826 *
3827 * This function reads the NL vendor attributes from %tb and
3828 * fill in the epno request message.
3829 *
3830 * Return: 0 on success, error number otherwise
3831 */
3832static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3833 struct wireless_dev *wdev,
3834 const void *data,
3835 int data_len)
3836{
3837 struct wifi_epno_params *req_msg = NULL;
3838 struct net_device *dev = wdev->netdev;
3839 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3840 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3841 struct nlattr *tb[
3842 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303843 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003844 uint32_t num_networks, len;
3845 int ret_val;
3846
Jeff Johnson1f61b612016-02-12 16:28:33 -08003847 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003848
3849 ret_val = wlan_hdd_validate_context(hdd_ctx);
3850 if (ret_val)
3851 return ret_val;
3852
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303853 if (!hdd_ctx->config->extscan_enabled) {
3854 hdd_err("extscan not supported");
3855 return -ENOTSUPP;
3856 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05303857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003858 hdd_err("Command not allowed in FTM mode");
3859 return -EPERM;
3860 }
3861
3862 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3863 data, data_len,
3864 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003865 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 return -EINVAL;
3867 }
3868
3869 /* Parse and fetch number of networks */
3870 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003871 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 return -EINVAL;
3873 }
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303874
3875 /*
3876 * num_networks is also used as EPNO SET/RESET request.
3877 * if num_networks is zero then it is treated as RESET.
3878 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 num_networks = nla_get_u32(
3880 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303882 if (num_networks > MAX_EPNO_NETWORKS) {
3883 hdd_notice("num of nw: %d exceeded max: %d, resetting to: %d",
3884 num_networks, MAX_EPNO_NETWORKS, MAX_EPNO_NETWORKS);
3885 num_networks = MAX_EPNO_NETWORKS;
3886 }
3887
3888 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889 len = sizeof(*req_msg) +
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303890 (num_networks * sizeof(struct wifi_epno_network));
3891
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303892 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003894 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 return -ENOMEM;
3896 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303897 qdf_mem_zero(req_msg, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 req_msg->num_networks = num_networks;
3899
3900 /* Parse and fetch request Id */
3901 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003902 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903 goto fail;
3904 }
3905 req_msg->request_id = nla_get_u32(
3906 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003907 hdd_notice("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908
3909 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003910 hdd_notice("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003911
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303912 if (num_networks) {
3913
3914 /* Parse and fetch min_5ghz_rssi */
3915 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]) {
3916 hdd_err("min_5ghz_rssi id failed");
3917 goto fail;
3918 }
3919 req_msg->min_5ghz_rssi = nla_get_u32(
3920 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]);
3921
3922 /* Parse and fetch min_24ghz_rssi */
3923 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]) {
3924 hdd_err("min_24ghz_rssi id failed");
3925 goto fail;
3926 }
3927 req_msg->min_24ghz_rssi = nla_get_u32(
3928 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]);
3929
3930 /* Parse and fetch initial_score_max */
3931 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]) {
3932 hdd_err("initial_score_max id failed");
3933 goto fail;
3934 }
3935 req_msg->initial_score_max = nla_get_u32(
3936 tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]);
3937
3938 /* Parse and fetch current_connection_bonus */
3939 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]) {
3940 hdd_err("current_connection_bonus id failed");
3941 goto fail;
3942 }
3943 req_msg->current_connection_bonus = nla_get_u32(
3944 tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]
3945 );
3946
3947 /* Parse and fetch same_network_bonus */
3948 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]) {
3949 hdd_err("same_network_bonus id failed");
3950 goto fail;
3951 }
3952 req_msg->same_network_bonus = nla_get_u32(
3953 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]);
3954
3955 /* Parse and fetch secure_bonus */
3956 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]) {
3957 hdd_err("secure_bonus id failed");
3958 goto fail;
3959 }
3960 req_msg->secure_bonus = nla_get_u32(
3961 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]);
3962
3963 /* Parse and fetch band_5ghz_bonus */
3964 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]) {
3965 hdd_err("band_5ghz_bonus id failed");
3966 goto fail;
3967 }
3968 req_msg->band_5ghz_bonus = nla_get_u32(
3969 tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]);
3970
3971 hdd_notice("min_5ghz_rssi: %d min_24ghz_rssi: %d",
3972 req_msg->min_5ghz_rssi,
3973 req_msg->min_24ghz_rssi);
3974 hdd_notice("initial_score_max: %d current_connection_bonus:%d",
3975 req_msg->initial_score_max,
3976 req_msg->current_connection_bonus);
3977 hdd_notice("Bonuses same_network: %d secure: %d band_5ghz: %d",
3978 req_msg->same_network_bonus,
3979 req_msg->secure_bonus,
3980 req_msg->band_5ghz_bonus);
3981
3982 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
3983 goto fail;
3984
3985 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003986
3987 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303988 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003989 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003990 goto fail;
3991 }
3992
3993 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303994 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 return 0;
3996
3997fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303998 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 return -EINVAL;
4000}
4001
4002 /**
4003 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
4004 * @wiphy: wiphy
4005 * @wdev: pointer to wireless dev
4006 * @data: data pointer
4007 * @data_len: data length
4008 *
4009 * This function reads the NL vendor attributes from %tb and
4010 * fill in the epno request message.
4011 *
4012 * Return: 0 on success, error number otherwise
4013 */
4014int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
4015 struct wireless_dev *wdev,
4016 const void *data,
4017 int data_len)
4018{
4019 int ret;
4020
4021 cds_ssr_protect(__func__);
4022 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
4023 data, data_len);
4024 cds_ssr_unprotect(__func__);
4025
4026 return ret;
4027}
4028
4029/**
4030 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
4031 * @hddctx: HDD context
4032 * @req_msg: request message
4033 * @tb: vendor attribute table
4034 *
4035 * This function reads the network block NL vendor attributes from %tb and
4036 * fill in the passpoint request message.
4037 *
4038 * Return: 0 on success, error number otherwise
4039 */
4040static int hdd_extscan_passpoint_fill_network_list(
4041 hdd_context_t *hddctx,
4042 struct wifi_passpoint_req *req_msg,
4043 struct nlattr **tb)
4044{
4045 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
4046 struct nlattr *networks;
4047 int rem1, len;
4048 uint8_t index;
4049
4050 index = 0;
4051 nla_for_each_nested(networks,
4052 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
4053 rem1) {
4054 if (nla_parse(network,
4055 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
4056 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004057 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004058 return -EINVAL;
4059 }
4060
4061 /* Parse and fetch identifier */
4062 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004063 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064 return -EINVAL;
4065 }
4066 req_msg->networks[index].id = nla_get_u32(
4067 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004068 hdd_notice("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004069
4070 /* Parse and fetch realm */
4071 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004072 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 return -EINVAL;
4074 }
4075 len = nla_len(
4076 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
4077 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004078 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079 return -EINVAL;
4080 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304081 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004082 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
4083 len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004084 hdd_notice("realm len %d", len);
4085 hdd_notice("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004086
4087 /* Parse and fetch roaming consortium ids */
4088 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004089 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004090 return -EINVAL;
4091 }
4092 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
4093 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
4094 sizeof(req_msg->networks[0].roaming_consortium_ids));
Jeff Johnson630f9e72016-07-25 12:00:12 -07004095 hdd_notice("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004096
4097 /* Parse and fetch plmn */
4098 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004099 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100 return -EINVAL;
4101 }
4102 nla_memcpy(&req_msg->networks[index].plmn,
4103 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
4104 SIR_PASSPOINT_PLMN_LEN);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004105 hdd_notice("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106 req_msg->networks[index].plmn[0],
4107 req_msg->networks[index].plmn[1],
4108 req_msg->networks[index].plmn[2]);
4109
4110 index++;
4111 }
4112 return 0;
4113}
4114
4115/**
4116 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4117 * @wiphy: wiphy
4118 * @wdev: pointer to wireless dev
4119 * @data: data pointer
4120 * @data_len: data length
4121 *
4122 * This function reads the NL vendor attributes from %tb and
4123 * fill in the passpoint request message.
4124 *
4125 * Return: 0 on success, error number otherwise
4126 */
4127static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4128 struct wireless_dev *wdev,
4129 const void *data,
4130 int data_len)
4131{
4132 struct wifi_passpoint_req *req_msg = NULL;
4133 struct net_device *dev = wdev->netdev;
4134 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4135 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4136 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304137 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 uint32_t num_networks = 0;
4139 int ret;
4140
Jeff Johnson1f61b612016-02-12 16:28:33 -08004141 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004142
4143 ret = wlan_hdd_validate_context(hdd_ctx);
4144 if (ret)
4145 return ret;
4146
Anurag Chouhan6d760662016-02-20 16:05:43 +05304147 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004148 hdd_err("Command not allowed in FTM mode");
4149 return -EPERM;
4150 }
4151
4152 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4153 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004154 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004155 return -EINVAL;
4156 }
4157
4158 /* Parse and fetch number of networks */
4159 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004160 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161 return -EINVAL;
4162 }
4163 num_networks = nla_get_u32(
4164 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004165 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004166
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304167 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168 (num_networks * sizeof(req_msg->networks[0])));
4169 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004170 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004171 return -ENOMEM;
4172 }
4173 req_msg->num_networks = num_networks;
4174
4175 /* Parse and fetch request Id */
4176 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004177 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178 goto fail;
4179 }
4180 req_msg->request_id = nla_get_u32(
4181 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4182
4183 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004184 hdd_notice("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004185 req_msg->session_id);
4186
4187 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4188 goto fail;
4189
4190 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304191 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004192 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004193 goto fail;
4194 }
4195
4196 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304197 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004198 return 0;
4199
4200fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304201 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 return -EINVAL;
4203}
4204
4205/**
4206 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4207 * @wiphy: wiphy
4208 * @wdev: pointer to wireless dev
4209 * @data: data pointer
4210 * @data_len: data length
4211 *
4212 * This function reads the NL vendor attributes from %tb and
4213 * fill in the passpoint request message.
4214 *
4215 * Return: 0 on success, error number otherwise
4216 */
4217int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4218 struct wireless_dev *wdev,
4219 const void *data,
4220 int data_len)
4221{
4222 int ret;
4223
4224 cds_ssr_protect(__func__);
4225 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4226 data, data_len);
4227 cds_ssr_unprotect(__func__);
4228
4229 return ret;
4230}
4231
4232/**
4233 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4234 * @wiphy: wiphy
4235 * @wdev: pointer to wireless dev
4236 * @data: data pointer
4237 * @data_len: data length
4238 *
4239 * This function resets passpoint networks list
4240 *
4241 * Return: 0 on success, error number otherwise
4242 */
4243static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4244 struct wireless_dev *wdev,
4245 const void *data,
4246 int data_len)
4247{
4248 struct wifi_passpoint_req *req_msg = NULL;
4249 struct net_device *dev = wdev->netdev;
4250 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4251 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4252 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304253 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004254 int ret;
4255
Jeff Johnson1f61b612016-02-12 16:28:33 -08004256 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004257
4258 ret = wlan_hdd_validate_context(hdd_ctx);
4259 if (ret)
4260 return ret;
4261
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 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4268 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004269 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004270 return -EINVAL;
4271 }
4272
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304273 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004274 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004275 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 return -ENOMEM;
4277 }
4278
4279 /* Parse and fetch request Id */
4280 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004281 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004282 goto fail;
4283 }
4284 req_msg->request_id = nla_get_u32(
4285 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4286
4287 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004288 hdd_notice("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289 req_msg->request_id, req_msg->session_id);
4290
4291 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304292 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004293 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004294 goto fail;
4295 }
4296
4297 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304298 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299 return 0;
4300
4301fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304302 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 return -EINVAL;
4304}
4305
4306/**
4307 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4308 * @wiphy: wiphy
4309 * @wdev: pointer to wireless dev
4310 * @data: data pointer
4311 * @data_len: data length
4312 *
4313 * This function resets passpoint networks list
4314 *
4315 * Return: 0 on success, error number otherwise
4316 */
4317int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4318 struct wireless_dev *wdev,
4319 const void *data,
4320 int data_len)
4321{
4322 int ret;
4323
4324 cds_ssr_protect(__func__);
4325 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4326 data, data_len);
4327 cds_ssr_unprotect(__func__);
4328
4329 return ret;
4330}
4331
4332/*
4333 * define short names for the global vendor params
4334 * used by __wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4335 */
4336#define PARAM_MAX \
4337 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4338#define PARAM_REQUEST_ID \
4339 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4340#define PARAMS_LOST_SSID_SAMPLE_SIZE \
4341 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE
4342#define PARAMS_NUM_SSID \
4343 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID
4344#define THRESHOLD_PARAM \
4345 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM
4346#define PARAM_SSID \
4347 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID
4348#define PARAM_BAND \
4349 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND
4350#define PARAM_RSSI_LOW \
4351 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW
4352#define PARAM_RSSI_HIGH \
4353 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH
4354
4355/**
4356 * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4357 * @wiphy: Pointer to wireless phy
4358 * @wdev: Pointer to wireless device
4359 * @data: Pointer to data
4360 * @data_len: Data length
4361 *
4362 * Return: 0 on success, negative errno on failure
4363 */
4364static int
4365__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4366 struct wireless_dev *wdev,
4367 const void *data,
4368 int data_len)
4369{
4370 struct sir_set_ssid_hotlist_request *request;
4371 struct net_device *dev = wdev->netdev;
4372 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4373 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4374 struct nlattr *tb[PARAM_MAX + 1];
4375 struct nlattr *tb2[PARAM_MAX + 1];
4376 struct nlattr *ssids;
4377 struct hdd_ext_scan_context *context;
4378 uint32_t request_id;
4379 char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1];
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304380 int ssid_len, i, rem, ssid_str_len;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304381 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 int retval;
4383 unsigned long rc;
4384
Jeff Johnson1f61b612016-02-12 16:28:33 -08004385 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386
Anurag Chouhan6d760662016-02-20 16:05:43 +05304387 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388 hdd_err("Command not allowed in FTM mode");
4389 return -EPERM;
4390 }
4391
4392 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304393 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304396 if (!hdd_ctx->config->extscan_enabled) {
4397 hdd_err("extscan not supported");
4398 return -ENOTSUPP;
4399 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 if (nla_parse(tb, PARAM_MAX,
4401 data, data_len,
4402 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004403 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004404 return -EINVAL;
4405 }
4406
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304407 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004408 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004409 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 return -ENOMEM;
4411 }
4412
4413 /* Parse and fetch request Id */
4414 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004415 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004416 goto fail;
4417 }
4418
4419 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004420 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004421
4422 /* Parse and fetch lost SSID sample size */
4423 if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004424 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425 goto fail;
4426 }
4427 request->lost_ssid_sample_size =
4428 nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004429 hdd_notice("Lost SSID Sample Size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430 request->lost_ssid_sample_size);
4431
4432 /* Parse and fetch number of hotlist SSID */
4433 if (!tb[PARAMS_NUM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004434 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004435 goto fail;
4436 }
4437 request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004438 hdd_notice("Number of SSID %d", request->ssid_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439
4440 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004441 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004442
4443 i = 0;
4444 nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) {
4445 if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004446 hdd_err("Too Many SSIDs, %d exceeds %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447 i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS);
4448 break;
4449 }
4450 if (nla_parse(tb2, PARAM_MAX,
4451 nla_data(ssids), nla_len(ssids),
4452 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004453 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004454 goto fail;
4455 }
4456
4457 /* Parse and fetch SSID */
4458 if (!tb2[PARAM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004459 hdd_err("attr ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004460 goto fail;
4461 }
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304462 ssid_str_len = nla_strlcpy(ssid_string,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463 tb2[PARAM_SSID],
4464 sizeof(ssid_string));
Anurag Chouhan172a7c32016-09-12 14:54:15 +05304465 if (ssid_str_len > SIR_MAC_MAX_SSID_LENGTH) {
4466 hdd_err("Invalid length exceeds max ssid length");
4467 goto fail;
4468 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07004469 hdd_notice("SSID %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004470 ssid_string);
4471 ssid_len = strlen(ssid_string);
4472 memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len);
4473 request->ssids[i].ssid.length = ssid_len;
4474
4475 /* Parse and fetch low RSSI */
4476 if (!tb2[PARAM_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004477 hdd_err("attr band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004478 goto fail;
4479 }
4480 request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004481 hdd_notice("band %d", request->ssids[i].band);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482
4483 /* Parse and fetch low RSSI */
4484 if (!tb2[PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004485 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004486 goto fail;
4487 }
4488 request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004489 hdd_notice("RSSI low %d", request->ssids[i].rssi_low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490
4491 /* Parse and fetch high RSSI */
4492 if (!tb2[PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004493 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494 goto fail;
4495 }
4496 request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004497 hdd_notice("RSSI high %d", request->ssids[i].rssi_high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004498 i++;
4499 }
4500
4501 context = &ext_scan_context;
4502 spin_lock(&context->context_lock);
4503 INIT_COMPLETION(context->response_event);
4504 context->request_id = request_id = request->request_id;
4505 spin_unlock(&context->context_lock);
4506
4507 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304508 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004509 hdd_err("sme_set_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004510 goto fail;
4511 }
4512
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304513 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004514
4515 /* request was sent -- wait for the response */
4516 rc = wait_for_completion_timeout(&context->response_event,
4517 msecs_to_jiffies
4518 (WLAN_WAIT_TIME_EXTSCAN));
4519 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004520 hdd_err("sme_set_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004521 retval = -ETIMEDOUT;
4522 } else {
4523 spin_lock(&context->context_lock);
4524 if (context->request_id == request_id)
4525 retval = context->response_status;
4526 else
4527 retval = -EINVAL;
4528 spin_unlock(&context->context_lock);
4529 }
4530
4531 return retval;
4532
4533fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304534 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535 return -EINVAL;
4536}
4537
4538/*
4539 * done with short names for the global vendor params
4540 * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4541 */
4542#undef PARAM_MAX
4543#undef PARAM_REQUEST_ID
4544#undef PARAMS_NUM_SSID
4545#undef THRESHOLD_PARAM
4546#undef PARAM_SSID
4547#undef PARAM_BAND
4548#undef PARAM_RSSI_LOW
4549#undef PARAM_RSSI_HIGH
4550
4551/**
4552 * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4553 * @wiphy: Pointer to wireless phy
4554 * @wdev: Pointer to wireless device
4555 * @data: Pointer to data
4556 * @data_len: Data length
4557 *
4558 * Return: 0 on success, negative errno on failure
4559 */
4560int
4561wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4562 struct wireless_dev *wdev,
4563 const void *data,
4564 int data_len)
4565{
4566 int ret;
4567
4568 cds_ssr_protect(__func__);
4569 ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data,
4570 data_len);
4571 cds_ssr_unprotect(__func__);
4572
4573 return ret;
4574}
4575
4576/*
4577 * define short names for the global vendor params
4578 * used by __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4579 */
4580#define PARAM_MAX \
4581 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4582#define PARAM_REQUEST_ID \
4583 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4584
4585/**
4586 * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4587 * @wiphy: Pointer to wireless phy
4588 * @wdev: Pointer to wireless device
4589 * @data: Pointer to data
4590 * @data_len: Data length
4591 *
4592 * Return: 0 on success, negative errno on failure
4593 */
4594static int
4595__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4596 struct wireless_dev *wdev,
4597 const void *data,
4598 int data_len)
4599{
4600 struct sir_set_ssid_hotlist_request *request;
4601 struct net_device *dev = wdev->netdev;
4602 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4603 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4604 struct nlattr *tb[PARAM_MAX + 1];
4605 struct hdd_ext_scan_context *context;
4606 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304607 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 int retval;
4609 unsigned long rc;
4610
Jeff Johnson1f61b612016-02-12 16:28:33 -08004611 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612
Anurag Chouhan6d760662016-02-20 16:05:43 +05304613 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004614 hdd_err("Command not allowed in FTM mode");
4615 return -EPERM;
4616 }
4617
4618 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304619 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004621
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05304622 if (!hdd_ctx->config->extscan_enabled) {
4623 hdd_err("extscan not supported");
4624 return -ENOTSUPP;
4625 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004626 if (nla_parse(tb, PARAM_MAX,
4627 data, data_len,
4628 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004629 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004630 return -EINVAL;
4631 }
4632
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304633 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004634 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004635 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004636 return -ENOMEM;
4637 }
4638
4639 /* Parse and fetch request Id */
4640 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004641 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004642 goto fail;
4643 }
4644
4645 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004646 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004647
4648 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004649 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004650
4651 request->lost_ssid_sample_size = 0;
4652 request->ssid_count = 0;
4653
4654 context = &ext_scan_context;
4655 spin_lock(&context->context_lock);
4656 INIT_COMPLETION(context->response_event);
4657 context->request_id = request_id = request->request_id;
4658 spin_unlock(&context->context_lock);
4659
4660 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304661 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004662 hdd_err("sme_reset_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004663 goto fail;
4664 }
4665
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304666 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004667
4668 /* request was sent -- wait for the response */
4669 rc = wait_for_completion_timeout(&context->response_event,
4670 msecs_to_jiffies
4671 (WLAN_WAIT_TIME_EXTSCAN));
4672 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004673 hdd_err("sme_reset_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 retval = -ETIMEDOUT;
4675 } else {
4676 spin_lock(&context->context_lock);
4677 if (context->request_id == request_id)
4678 retval = context->response_status;
4679 else
4680 retval = -EINVAL;
4681 spin_unlock(&context->context_lock);
4682 }
4683
4684 return retval;
4685
4686fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304687 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688 return -EINVAL;
4689}
4690
4691/*
4692 * done with short names for the global vendor params
4693 * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4694 */
4695#undef PARAM_MAX
4696#undef PARAM_REQUEST_ID
4697
4698/**
4699 * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4700 * @wiphy: Pointer to wireless phy
4701 * @wdev: Pointer to wireless device
4702 * @data: Pointer to data
4703 * @data_len: Data length
4704 *
4705 * Return: 0 on success, negative errno on failure
4706 */
4707int
4708wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4709 struct wireless_dev *wdev,
4710 const void *data,
4711 int data_len)
4712{
4713 int ret;
4714
4715 cds_ssr_protect(__func__);
4716 ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev,
4717 data, data_len);
4718 cds_ssr_unprotect(__func__);
4719
4720 return ret;
4721}
4722
4723/**
4724 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4725 * @hdd_ctx: Global HDD context
4726 *
4727 * Return: none
4728 */
4729#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4730static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4731{
4732 init_completion(&pHddCtx->ready_to_extwow);
4733}
4734#else
4735static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4736{
4737 return;
4738}
4739#endif
4740
4741/**
4742 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4743 * @hdd_ctx: Global HDD context
4744 *
4745 * Return: none
4746 */
4747void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx)
4748{
4749 wlan_hdd_init_completion_extwow(hdd_ctx);
4750 init_completion(&ext_scan_context.response_event);
4751 spin_lock_init(&ext_scan_context.context_lock);
4752}
4753
4754#endif /* FEATURE_WLAN_EXTSCAN */