blob: 6d99b958331d44e3d766bc8aa46f8529f53a0344 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/**
23 * DOC: wlan_hdd_ext_scan.c
24 *
25 * WLAN Host Device Driver EXT SCAN feature implementation
26 *
27 */
28
29#ifdef FEATURE_WLAN_EXTSCAN
30
Jeff Johnson630f9e72016-07-25 12:00:12 -070031/* denote that this file does not allow legacy hddLog */
32#define HDD_DISALLOW_LEGACY_HDDLOG 1
33
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080034#include "wlan_hdd_ext_scan.h"
35#include "cds_utils.h"
36#include "cds_sched.h"
37
38/* amount of time to wait for a synchronous request/response operation */
39#define WLAN_WAIT_TIME_EXTSCAN 1000
40
41/**
42 * struct hdd_ext_scan_context - hdd ext scan context
43 * @request_id: userspace-assigned ID associated with the request
44 * @response_event: Ext scan wait event
45 * @response_status: Status returned by FW in response to a request
46 * @ignore_cached_results: Flag to ignore cached results or not
47 * @context_lock: Spinlock to serialize all context accesses
48 * @capability_response: Ext scan capability response data from target
Mukul Sharmafa937be2016-08-12 18:13:36 +053049 * @buckets_scanned: bitmask of buckets scanned in extscan cycle
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050 */
51struct hdd_ext_scan_context {
52 uint32_t request_id;
53 int response_status;
54 bool ignore_cached_results;
55 struct completion response_event;
56 spinlock_t context_lock;
57 struct ext_scan_capabilities_response capability_response;
Mukul Sharmafa937be2016-08-12 18:13:36 +053058 uint32_t buckets_scanned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080059};
60static struct hdd_ext_scan_context ext_scan_context;
61
62static const struct nla_policy wlan_hdd_extscan_config_policy
63[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] = {
64 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = {
65 .type = NLA_U32},
66 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = {
67 .type = NLA_U32},
68 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = {.type = NLA_U32},
69 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = {
70 .type = NLA_U32},
71 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = {.type = NLA_U8},
72 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = {.type = NLA_U8},
73
74 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = {.type = NLA_U8},
75 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = {.type = NLA_U8},
76 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = {.type = NLA_U32},
77 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] = {
78 .type = NLA_U8},
79 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] = {
80 .type = NLA_U32},
81 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] = {
82 .type = NLA_U32},
83 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] = {
84 .type = NLA_U32},
85 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT] = {
86 .type = NLA_U8},
87 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS] = {
88 .type = NLA_U8 },
89 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] = {
90 .type = NLA_U8},
91 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = {
92 .type = NLA_U8},
93
94 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = {
95 .type = NLA_U32},
96 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = {
97 .type = NLA_UNSPEC},
98 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = {
99 .type = NLA_S32},
100 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = {
101 .type = NLA_S32},
102 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = {
103 .type = NLA_U32},
104 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] = {
105 .type = NLA_U32},
106 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] = {
107 .type = NLA_U32},
108 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = {
109 .type = NLA_U32},
110 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = {
111 .type = NLA_U32},
112 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = {
113 .type = NLA_U32},
114 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
115 .type = NLA_U32 },
116 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
117 .type = NLA_BINARY,
118 .len = IEEE80211_MAX_SSID_LEN },
119 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD] = {
120 .type = NLA_S8 },
121 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
122 .type = NLA_U8 },
123 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
124 .type = NLA_U8 },
125 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = {
126 .type = NLA_BINARY,
127 .len = IEEE80211_MAX_SSID_LEN + 1 },
128 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = {
129 .type = NLA_U32 },
130 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID] = {
131 .type = NLA_U32 },
132 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND] = {
133 .type = NLA_U8 },
134 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = {
135 .type = NLA_S32 },
136 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = {
137 .type = NLA_S32 },
138 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = {
139 .type = NLA_U32 },
140};
141
142static const struct nla_policy
143wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
144 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
145 .type = NLA_U16},
146 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = {
147 .type = NLA_U16},
148};
149
150/**
151 * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
152 * @ctx: Pointer to hdd context
153 * @data: Pointer to ext scan capabilities response from fw
154 *
155 * Return: None
156 */
157static void
158wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx,
159 struct ext_scan_capabilities_response *data)
160{
161 struct hdd_ext_scan_context *context;
162 hdd_context_t *hdd_ctx = ctx;
163
164 ENTER();
165
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530166 if (wlan_hdd_validate_context(hdd_ctx))
167 return;
168 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700169 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 return;
171 }
172
173 context = &ext_scan_context;
174
175 spin_lock(&context->context_lock);
176 /* validate response received from target*/
177 if (context->request_id != data->requestId) {
178 spin_unlock(&context->context_lock);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700179 hdd_err("Target response id did not match: request_id %d response_id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 context->request_id, data->requestId);
181 return;
182 } else {
183 context->capability_response = *data;
184 complete(&context->response_event);
185 }
186
187 spin_unlock(&context->context_lock);
188
189 return;
190}
191
192/*
193 * define short names for the global vendor params
194 * used by hdd_extscan_nl_fill_bss()
195 */
196#define PARAM_TIME_STAMP \
197 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
198#define PARAM_SSID \
199 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID
200#define PARAM_BSSID \
201 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID
202#define PARAM_CHANNEL \
203 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL
204#define PARAM_RSSI \
205 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI
206#define PARAM_RTT \
207 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT
208#define PARAM_RTT_SD \
209 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD
210#define PARAM_BEACON_PERIOD \
211 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD
212#define PARAM_CAPABILITY \
213 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY
214#define PARAM_IE_LENGTH \
215 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
216#define PARAM_IE_DATA \
217 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA
218
219/** hdd_extscan_nl_fill_bss() - extscan nl fill bss
220 * @skb: socket buffer
221 * @ap: bss information
222 * @idx: nesting index
223 *
224 * Return: 0 on success; error number otherwise
225 */
226static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap,
227 int idx)
228{
229 struct nlattr *nla_ap;
230
231 nla_ap = nla_nest_start(skb, idx);
232 if (!nla_ap)
233 return -EINVAL;
234
235 if (nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) ||
236 nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) ||
237 nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid.bytes) ||
238 nla_put_u32(skb, PARAM_CHANNEL, ap->channel) ||
239 nla_put_s32(skb, PARAM_RSSI, ap->rssi) ||
240 nla_put_u32(skb, PARAM_RTT, ap->rtt) ||
241 nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) ||
242 nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) ||
243 nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) ||
244 nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700245 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246 return -EINVAL;
247 }
248
249 if (ap->ieLength)
250 if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700251 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252 return -EINVAL;
253 }
254
255 nla_nest_end(skb, nla_ap);
256
257 return 0;
258}
259/*
260 * done with short names for the global vendor params
261 * used by hdd_extscan_nl_fill_bss()
262 */
263#undef PARAM_TIME_STAMP
264#undef PARAM_SSID
265#undef PARAM_BSSID
266#undef PARAM_CHANNEL
267#undef PARAM_RSSI
268#undef PARAM_RTT
269#undef PARAM_RTT_SD
270#undef PARAM_BEACON_PERIOD
271#undef PARAM_CAPABILITY
272#undef PARAM_IE_LENGTH
273#undef PARAM_IE_DATA
274
275/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results
276 * @ctx: hdd global context
277 * @data: cached results
278 *
279 * This function reads the cached results %data, populated the NL
280 * attributes and sends the NL event to the upper layer.
281 *
282 * Return: none
283 */
284static void
285wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
286 struct extscan_cached_scan_results *data)
287{
288 hdd_context_t *pHddCtx = ctx;
289 struct sk_buff *skb = NULL;
290 struct hdd_ext_scan_context *context;
291 struct extscan_cached_scan_result *result;
292 tSirWifiScanResult *ap;
293 uint32_t i, j, nl_buf_len;
294 bool ignore_cached_results = false;
295
296 ENTER();
297
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530298 if (wlan_hdd_validate_context(pHddCtx))
299 return;
300 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700301 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800302 return;
303 }
304
305 context = &ext_scan_context;
306 spin_lock(&context->context_lock);
307 ignore_cached_results = context->ignore_cached_results;
308 spin_unlock(&context->context_lock);
309
310 if (ignore_cached_results) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700311 hdd_err("Ignore the cached results received after timeout");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800312 return;
313 }
314
315#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN
316#define EXTSCAN_CACHED_NL_FIXED_TLV \
317 ((sizeof(data->request_id) + NLA_HDRLEN) + \
318 (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \
Mukul Sharmafa937be2016-08-12 18:13:36 +0530319 (sizeof(data->buckets_scanned) + NLA_HDRLEN)+ \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800320 (sizeof(data->more_data) + NLA_HDRLEN))
321#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \
322 ((sizeof(result->scan_id) + NLA_HDRLEN) + \
323 (sizeof(result->flags) + NLA_HDRLEN) + \
324 (sizeof(result->num_results) + NLA_HDRLEN))
325#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
326 ((sizeof(ap->ts) + NLA_HDRLEN) + \
327 (sizeof(ap->ssid) + NLA_HDRLEN) + \
328 (sizeof(ap->bssid) + NLA_HDRLEN) + \
329 (sizeof(ap->channel) + NLA_HDRLEN) + \
330 (sizeof(ap->rssi) + NLA_HDRLEN) + \
331 (sizeof(ap->rtt) + NLA_HDRLEN) + \
332 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
333 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
334 (sizeof(ap->capability) + NLA_HDRLEN) + \
335 (sizeof(ap->ieLength) + NLA_HDRLEN))
336#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
337 (ap->ieLength + NLA_HDRLEN)
338
339 nl_buf_len = NLMSG_HDRLEN;
340 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
341 if (data->num_scan_ids) {
342 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
343 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
344 result = &data->result[0];
345 for (i = 0; i < data->num_scan_ids; i++) {
346 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
347 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
348 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
349
350 ap = &result->ap[0];
351 for (j = 0; j < result->num_results; j++) {
352 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
353 nl_buf_len +=
354 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
355 if (ap->ieLength)
356 nl_buf_len +=
357 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
358 ap++;
359 }
360 result++;
361 }
362 }
363
Jeff Johnson630f9e72016-07-25 12:00:12 -0700364 hdd_notice("nl_buf_len = %u", nl_buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len);
366
367 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700368 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369 goto fail;
370 }
Mukul Sharmafa937be2016-08-12 18:13:36 +0530371 hdd_notice("Req Id %u Num_scan_ids %u More Data %u buckets_scanned %u",
372 data->request_id, data->num_scan_ids, data->more_data,
373 data->buckets_scanned);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374
375 result = &data->result[0];
376 for (i = 0; i < data->num_scan_ids; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700377 hdd_notice("[i=%d] scan_id %u flags %u num_results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 i, result->scan_id, result->flags, result->num_results);
379
380 ap = &result->ap[0];
381 for (j = 0; j < result->num_results; j++) {
382 /*
383 * Firmware returns timestamp from ext scan start till
384 * BSSID was cached (in micro seconds). Add this with
385 * time gap between system boot up to ext scan start
386 * to derive the time since boot when the
387 * BSSID was cached.
388 */
389 ap->ts += pHddCtx->ext_scan_start_since_boot;
Jeff Johnson630f9e72016-07-25 12:00:12 -0700390 hdd_notice("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 "Ssid: %s "
392 "Bssid (" MAC_ADDRESS_STR ") "
393 "Channel %u "
394 "Rssi %d "
395 "RTT %u "
396 "RTT_SD %u "
397 "Beacon Period %u "
398 "Capability 0x%x "
399 "Ie length %d",
400 ap->ts,
401 ap->ssid,
402 MAC_ADDR_ARRAY(ap->bssid.bytes),
403 ap->channel,
404 ap->rssi,
405 ap->rtt,
406 ap->rtt_sd,
407 ap->beaconPeriod,
408 ap->capability,
409 ap->ieLength);
410 ap++;
411 }
412 result++;
413 }
414
415 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
416 data->request_id) ||
417 nla_put_u32(skb,
418 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
419 data->num_scan_ids) ||
420 nla_put_u8(skb,
421 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
422 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700423 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800424 goto fail;
425 }
426
427 if (data->num_scan_ids) {
428 struct nlattr *nla_results;
429 result = &data->result[0];
430
431 if (nla_put_u32(skb,
432 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
433 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700434 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435 goto fail;
436 }
437 nla_results = nla_nest_start(skb,
438 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
439 if (!nla_results)
440 goto fail;
441
442 for (i = 0; i < data->num_scan_ids; i++) {
443 struct nlattr *nla_result;
444 struct nlattr *nla_aps;
445
446 nla_result = nla_nest_start(skb, i);
447 if (!nla_result)
448 goto fail;
449
450 if (nla_put_u32(skb,
451 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
452 result->scan_id) ||
453 nla_put_u32(skb,
454 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
455 result->flags) ||
456 nla_put_u32(skb,
Mukul Sharmafa937be2016-08-12 18:13:36 +0530457 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
458 data->buckets_scanned) ||
459 nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
461 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700462 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800463 goto fail;
464 }
465
466 nla_aps = nla_nest_start(skb,
467 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
468 if (!nla_aps)
469 goto fail;
470
471 ap = &result->ap[0];
472 for (j = 0; j < result->num_results; j++) {
473 if (hdd_extscan_nl_fill_bss(skb, ap, j))
474 goto fail;
475
476 ap++;
477 }
478 nla_nest_end(skb, nla_aps);
479 nla_nest_end(skb, nla_result);
480 result++;
481 }
482 nla_nest_end(skb, nla_results);
483 }
484
485 cfg80211_vendor_cmd_reply(skb);
486
487 if (!data->more_data) {
488 spin_lock(&context->context_lock);
489 context->response_status = 0;
490 complete(&context->response_event);
491 spin_unlock(&context->context_lock);
492 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530493 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800494 return;
495
496fail:
497 if (skb)
498 kfree_skb(skb);
499
500 spin_lock(&context->context_lock);
501 context->response_status = -EINVAL;
502 spin_unlock(&context->context_lock);
503
504 return;
505}
506
507/**
508 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
509 * @ctx: Pointer to hdd context
510 * @pData: Pointer to ext scan result event
511 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800512 * This callback execute in atomic context and must not invoke any
513 * blocking calls.
514 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 * Return: none
516 */
517static void
518wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
519 struct extscan_hotlist_match *data)
520{
521 hdd_context_t *pHddCtx = ctx;
522 struct sk_buff *skb = NULL;
523 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800524 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525
526 ENTER();
527
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530528 if (wlan_hdd_validate_context(pHddCtx))
529 return;
530 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700531 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800532 return;
533 }
534
535 if (data->ap_found)
536 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
537 else
538 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
539
540 skb = cfg80211_vendor_event_alloc(
541 pHddCtx->wiphy,
542 NULL,
543 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800544 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545
546 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700547 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 return;
549 }
550 hdd_info("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
551 data->requestId, data->numOfAps, data->moreData,
552 data->ap_found);
553
554 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530555 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556
Jeff Johnson630f9e72016-07-25 12:00:12 -0700557 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 "Ssid: %s "
559 "Bssid (" MAC_ADDRESS_STR ") "
560 "Channel %u "
561 "Rssi %d "
562 "RTT %u "
563 "RTT_SD %u",
564 i,
565 data->ap[i].ts,
566 data->ap[i].ssid,
567 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
568 data->ap[i].channel,
569 data->ap[i].rssi,
570 data->ap[i].rtt, data->ap[i].rtt_sd);
571 }
572
573 if (nla_put_u32(skb,
574 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
575 data->requestId) ||
576 nla_put_u32(skb,
577 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
578 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700579 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 goto fail;
581 }
582
583 if (data->numOfAps) {
584 struct nlattr *aps;
585
586 aps = nla_nest_start(skb,
587 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
588 if (!aps)
589 goto fail;
590
591 for (i = 0; i < data->numOfAps; i++) {
592 struct nlattr *ap;
593
594 ap = nla_nest_start(skb, i);
595 if (!ap)
596 goto fail;
597
598 if (nla_put_u64(skb,
599 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
600 data->ap[i].ts) ||
601 nla_put(skb,
602 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
603 sizeof(data->ap[i].ssid),
604 data->ap[i].ssid) ||
605 nla_put(skb,
606 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
607 sizeof(data->ap[i].bssid),
608 data->ap[i].bssid.bytes) ||
609 nla_put_u32(skb,
610 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
611 data->ap[i].channel) ||
612 nla_put_s32(skb,
613 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
614 data->ap[i].rssi) ||
615 nla_put_u32(skb,
616 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
617 data->ap[i].rtt) ||
618 nla_put_u32(skb,
619 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
620 data->ap[i].rtt_sd))
621 goto fail;
622
623 nla_nest_end(skb, ap);
624 }
625 nla_nest_end(skb, aps);
626
627 if (nla_put_u8(skb,
628 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
629 data->moreData))
630 goto fail;
631 }
632
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800633 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530634 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 return;
636
637fail:
638 kfree_skb(skb);
639 return;
640}
641
642/**
643 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
644 * significant wifi change results indication
645 * @ctx: Pointer to hdd context
646 * @pData: Pointer to signif wifi change event
647 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800648 * This callback execute in atomic context and must not invoke any
649 * blocking calls.
650 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 * Return: none
652 */
653static void
654wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
655 void *ctx,
656 tpSirWifiSignificantChangeEvent pData)
657{
658 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
659 struct sk_buff *skb = NULL;
660 tSirWifiSignificantChange *ap_info;
661 int32_t *rssi;
662 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800663 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664
665 ENTER();
666
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530667 if (wlan_hdd_validate_context(pHddCtx))
668 return;
669 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700670 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671 return;
672 }
673
674 skb = cfg80211_vendor_event_alloc(
675 pHddCtx->wiphy,
676 NULL,
677 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
678 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800679 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680
681 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700682 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683 return;
684 }
Jeff Johnson630f9e72016-07-25 12:00:12 -0700685 hdd_notice("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 pData->requestId, pData->numResults, pData->moreData);
687
688 ap_info = &pData->ap[0];
689 for (i = 0; i < pData->numResults; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700690 hdd_notice("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800691 "Bssid (" MAC_ADDRESS_STR ") "
692 "Channel %u "
693 "numOfRssi %d",
694 i,
695 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
696 ap_info->channel, ap_info->numOfRssi);
697 rssi = &(ap_info)->rssi[0];
698 for (j = 0; j < ap_info->numOfRssi; j++)
Jeff Johnson630f9e72016-07-25 12:00:12 -0700699 hdd_notice("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700
701 ap_info += ap_info->numOfRssi * sizeof(*rssi);
702 }
703
704 if (nla_put_u32(skb,
705 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
706 pData->requestId) ||
707 nla_put_u32(skb,
708 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
709 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700710 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 goto fail;
712 }
713
714 if (pData->numResults) {
715 struct nlattr *aps;
716
717 aps = nla_nest_start(skb,
718 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
719 if (!aps)
720 goto fail;
721
722 ap_info = &pData->ap[0];
723 for (i = 0; i < pData->numResults; i++) {
724 struct nlattr *ap;
725
726 ap = nla_nest_start(skb, i);
727 if (!ap)
728 goto fail;
729
730 if (nla_put(skb,
731 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530732 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800733 nla_put_u32(skb,
734 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
735 ap_info->channel) ||
736 nla_put_u32(skb,
737 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
738 ap_info->numOfRssi) ||
739 nla_put(skb,
740 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
741 sizeof(s32) * ap_info->numOfRssi,
742 &(ap_info)->rssi[0]))
743 goto fail;
744
745 nla_nest_end(skb, ap);
746
747 ap_info += ap_info->numOfRssi * sizeof(*rssi);
748 }
749 nla_nest_end(skb, aps);
750
751 if (nla_put_u8(skb,
752 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
753 pData->moreData))
754 goto fail;
755 }
756
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800757 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758 return;
759
760fail:
761 kfree_skb(skb);
762 return;
763
764}
765
766/**
767 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
768 * @ctx: Pointer to hdd context
769 * @pData: Pointer to full scan result event
770 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800771 * This callback execute in atomic context and must not invoke any
772 * blocking calls.
773 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800774 * Return: none
775 */
776static void
777wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
778 tpSirWifiFullScanResultEvent
779 pData)
780{
781 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
782 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 struct timespec ts;
Mukul Sharmafa937be2016-08-12 18:13:36 +0530784 struct hdd_ext_scan_context *context;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700785
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800786 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787
788 ENTER();
789
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530790 if (wlan_hdd_validate_context(pHddCtx))
791 return;
792 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700793 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 return;
795 }
796
797 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700798 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 return;
800 }
801 skb = cfg80211_vendor_event_alloc(
802 pHddCtx->wiphy,
803 NULL,
804 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
805 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800806 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807
808 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700809 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 return;
811 }
812
813 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 /* Android does not want the time stamp from the frame.
816 Instead it wants a monotonic increasing value since boot */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700817 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700819
Jeff Johnson630f9e72016-07-25 12:00:12 -0700820 hdd_notice("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821 pData->moreData);
Jeff Johnson630f9e72016-07-25 12:00:12 -0700822 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823 "Bssid (" MAC_ADDRESS_STR ") "
824 "Channel %u "
825 "Rssi %d "
826 "RTT %u "
827 "RTT_SD %u "
828 "Bcn Period %d "
829 "Capability 0x%X "
830 "IE Length %d",
831 pData->ap.ts,
832 pData->ap.ssid,
833 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
834 pData->ap.channel,
835 pData->ap.rssi,
836 pData->ap.rtt,
837 pData->ap.rtt_sd,
838 pData->ap.beaconPeriod,
839 pData->ap.capability, pData->ap.ieLength);
840
841 if (nla_put_u32(skb,
842 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
843 pData->requestId) ||
844 nla_put_u64(skb,
845 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
846 pData->ap.ts) ||
847 nla_put(skb,
848 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
849 sizeof(pData->ap.ssid),
850 pData->ap.ssid) ||
851 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
852 sizeof(pData->ap.bssid),
853 pData->ap.bssid.bytes) ||
854 nla_put_u32(skb,
855 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
856 pData->ap.channel) ||
857 nla_put_s32(skb,
858 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
859 pData->ap.rssi) ||
860 nla_put_u32(skb,
861 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
862 pData->ap.rtt) ||
863 nla_put_u32(skb,
864 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
865 pData->ap.rtt_sd) ||
866 nla_put_u16(skb,
867 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
868 pData->ap.beaconPeriod) ||
869 nla_put_u16(skb,
870 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
871 pData->ap.capability) ||
872 nla_put_u32(skb,
873 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
874 pData->ap.ieLength) ||
875 nla_put_u8(skb,
876 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
877 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700878 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800879 goto nla_put_failure;
880 }
881
882 if (pData->ap.ieLength) {
883 if (nla_put(skb,
884 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
885 pData->ap.ieLength, pData->ap.ieData))
886 goto nla_put_failure;
887 }
888
Mukul Sharmafa937be2016-08-12 18:13:36 +0530889 context = &ext_scan_context;
890 spin_lock(&context->context_lock);
891 if (nla_put_u32(skb,
892 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
893 context->buckets_scanned)) {
894 spin_unlock(&context->context_lock);
895 hdd_notice("Failed to include buckets_scanned");
896 goto nla_put_failure;
897 }
898 spin_unlock(&context->context_lock);
899
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800900 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530901 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 return;
903
904nla_put_failure:
905 kfree_skb(skb);
906 return;
907}
908
909/**
910 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
911 * @ctx: Pointer to hdd context
912 * @pData: Pointer to scan results available indication param
913 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800914 * This callback execute in atomic context and must not invoke any
915 * blocking calls.
916 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 * Return: none
918 */
919static void
920wlan_hdd_cfg80211_extscan_scan_res_available_event(
921 void *ctx,
922 tpSirExtScanResultsAvailableIndParams pData)
923{
924 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
925 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800926 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800927
928 ENTER();
929
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530930 if (wlan_hdd_validate_context(pHddCtx))
931 return;
932 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700933 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800934 return;
935 }
936
937 skb = cfg80211_vendor_event_alloc(
938 pHddCtx->wiphy,
939 NULL,
940 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
941 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800942 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943
944 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700945 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800946 return;
947 }
948
Jeff Johnson630f9e72016-07-25 12:00:12 -0700949 hdd_notice("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800950 pData->requestId, pData->numResultsAvailable);
951 if (nla_put_u32(skb,
952 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
953 pData->requestId) ||
954 nla_put_u32(skb,
955 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
956 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700957 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800958 goto nla_put_failure;
959 }
960
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800961 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530962 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963 return;
964
965nla_put_failure:
966 kfree_skb(skb);
967 return;
968}
969
970/**
971 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
972 * @ctx: Pointer to hdd context
973 * @pData: Pointer to scan event indication param
974 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800975 * This callback execute in atomic context and must not invoke any
976 * blocking calls.
977 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 * Return: none
979 */
980static void
981wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
982 tpSirExtScanOnScanEventIndParams
983 pData)
984{
985 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
986 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800987 int flags = cds_get_gfp_flags();
Mukul Sharmafa937be2016-08-12 18:13:36 +0530988 struct hdd_ext_scan_context *context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989
990 ENTER();
991
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530992 if (wlan_hdd_validate_context(pHddCtx))
993 return;
994 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700995 hdd_err("pData is null");
Mukul Sharma45114d92016-08-12 19:34:14 +0530996 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997 return;
998 }
999
1000 skb = cfg80211_vendor_event_alloc(
1001 pHddCtx->wiphy,
1002 NULL,
1003 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1004 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001005 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006
1007 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001008 hdd_err("cfg80211_vendor_event_alloc failed");
Mukul Sharma45114d92016-08-12 19:34:14 +05301009 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010 return;
1011 }
Mukul Sharmafa937be2016-08-12 18:13:36 +05301012
1013 hdd_notice("Request Id %u Scan event type %u Scan event status %u buckets scanned %u",
1014 pData->requestId, pData->scanEventType, pData->status,
1015 pData->buckets_scanned);
1016
Mukul Sharmafa937be2016-08-12 18:13:36 +05301017 context = &ext_scan_context;
1018 spin_lock(&context->context_lock);
1019 if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT) {
1020 context->buckets_scanned = 0;
1021 pData->scanEventType = WIFI_EXTSCAN_RESULTS_AVAILABLE;
1022 spin_unlock(&context->context_lock);
1023 } else if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_STARTED_EVENT) {
1024 context->buckets_scanned = pData->buckets_scanned;
1025 /* No need to report to user space */
1026 spin_unlock(&context->context_lock);
Mukul Sharma45114d92016-08-12 19:34:14 +05301027 goto nla_put_failure;
Mukul Sharmafa937be2016-08-12 18:13:36 +05301028 } else {
1029 spin_unlock(&context->context_lock);
1030 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031
1032 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1033 pData->requestId) ||
1034 nla_put_u8(skb,
1035 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
Mukul Sharmafa937be2016-08-12 18:13:36 +05301036 pData->scanEventType)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001037 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001038 goto nla_put_failure;
1039 }
1040
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001041 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301042 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043 return;
1044
1045nla_put_failure:
1046 kfree_skb(skb);
Mukul Sharma45114d92016-08-12 19:34:14 +05301047 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048 return;
1049}
1050
1051/**
1052 * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found
1053 * @hddctx: HDD context
1054 * @data: matched network data
1055 *
1056 * This function reads the matched network data and fills NL vendor attributes
1057 * and send it to upper layer.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001058 * This callback execute in atomic context and must not invoke any
1059 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 *
1061 * Return: 0 on success, error number otherwise
1062 */
1063static void
1064wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
1065 struct pno_match_found *data)
1066{
1067 hdd_context_t *pHddCtx = (hdd_context_t *)ctx;
1068 struct sk_buff *skb = NULL;
1069 uint32_t len, i;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001070 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071
1072 ENTER();
1073
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301074 if (wlan_hdd_validate_context(pHddCtx))
1075 return;
1076 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001077 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 return;
1079 }
1080
1081 /*
1082 * If the number of match found APs including IE data exceeds NL 4K size
1083 * limitation, drop that beacon/probe rsp frame.
1084 */
1085 len = sizeof(*data) +
1086 (data->num_results + sizeof(tSirWifiScanResult));
1087 for (i = 0; i < data->num_results; i++)
1088 len += data->ap[i].ieLength;
1089
1090 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001091 hdd_err("Frame exceeded NL size limitation, drop it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001092 return;
1093 }
1094
1095 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1096 NULL,
1097 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1098 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001099 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001100
1101 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001102 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001103 return;
1104 }
1105
Jeff Johnson630f9e72016-07-25 12:00:12 -07001106 hdd_notice("Req Id %u More Data %u num_results %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001107 data->request_id, data->more_data, data->num_results);
1108 for (i = 0; i < data->num_results; i++) {
1109 data->ap[i].channel = cds_chan_to_freq(data->ap[i].channel);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001110 hdd_notice("AP Info: Timestamp %llu) Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 "Bssid (" MAC_ADDRESS_STR ") "
1112 "Channel %u "
1113 "Rssi %d "
1114 "RTT %u "
1115 "RTT_SD %u "
1116 "Bcn Period %d "
1117 "Capability 0x%X "
1118 "IE Length %d",
1119 data->ap[i].ts,
1120 data->ap[i].ssid,
1121 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
1122 data->ap[i].channel,
1123 data->ap[i].rssi,
1124 data->ap[i].rtt,
1125 data->ap[i].rtt_sd,
1126 data->ap[i].beaconPeriod,
1127 data->ap[i].capability,
1128 data->ap[i].ieLength);
1129 }
1130
1131 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1132 data->request_id) ||
1133 nla_put_u32(skb,
1134 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1135 data->num_results) ||
1136 nla_put_u8(skb,
1137 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1138 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001139 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 goto fail;
1141 }
1142
1143 if (data->num_results) {
1144 struct nlattr *nla_aps;
1145 nla_aps = nla_nest_start(skb,
1146 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1147 if (!nla_aps)
1148 goto fail;
1149
1150 for (i = 0; i < data->num_results; i++) {
1151 if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i))
1152 goto fail;
1153 }
1154 nla_nest_end(skb, nla_aps);
1155 }
1156
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001157 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001158 return;
1159
1160fail:
1161 kfree_skb(skb);
1162 return;
1163}
1164
1165/**
1166 * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found
1167 * @hddctx: HDD context
1168 * @data: matched network data
1169 *
1170 * This function reads the match network %data and fill in the skb with
1171 * NL attributes and send up the NL event
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001172 * This callback execute in atomic context and must not invoke any
1173 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 *
1175 * Return: none
1176 */
1177static void
1178wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
1179 struct wifi_passpoint_match *data)
1180{
1181 hdd_context_t *pHddCtx = ctx;
1182 struct sk_buff *skb = NULL;
1183 uint32_t len, i, num_matches = 1, more_data = 0;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001184 struct nlattr *nla_aps, *nla_bss;
1185 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001186
1187 ENTER();
1188
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301189 if (wlan_hdd_validate_context(pHddCtx))
1190 return;
1191 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001192 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001193 return;
1194 }
1195
1196 len = sizeof(*data) + data->ap.ieLength + data->anqp_len;
1197 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001198 hdd_err("Result exceeded NL size limitation, drop it");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 return;
1200 }
1201
1202 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1203 NULL,
1204 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1205 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001206 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207
1208 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001209 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210 return;
1211 }
1212
Jeff Johnson630f9e72016-07-25 12:00:12 -07001213 hdd_notice("Req Id %u Id %u ANQP length %u num_matches %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001214 data->request_id, data->id, data->anqp_len, num_matches);
1215 for (i = 0; i < num_matches; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001216 hdd_notice("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001217 "Bssid (" MAC_ADDRESS_STR ") "
1218 "Channel %u "
1219 "Rssi %d "
1220 "RTT %u "
1221 "RTT_SD %u "
1222 "Bcn Period %d "
1223 "Capability 0x%X "
1224 "IE Length %d",
1225 data->ap.ts,
1226 data->ap.ssid,
1227 MAC_ADDR_ARRAY(data->ap.bssid.bytes),
1228 data->ap.channel,
1229 data->ap.rssi,
1230 data->ap.rtt,
1231 data->ap.rtt_sd,
1232 data->ap.beaconPeriod,
1233 data->ap.capability,
1234 data->ap.ieLength);
1235 }
1236
1237 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1238 data->request_id) ||
1239 nla_put_u32(skb,
1240 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES,
1241 num_matches) ||
1242 nla_put_u8(skb,
1243 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1244 more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001245 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001246 goto fail;
1247 }
1248
1249 nla_aps = nla_nest_start(skb,
1250 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST);
1251 if (!nla_aps)
1252 goto fail;
1253
1254 for (i = 0; i < num_matches; i++) {
1255 struct nlattr *nla_ap;
1256
1257 nla_ap = nla_nest_start(skb, i);
1258 if (!nla_ap)
1259 goto fail;
1260
1261 if (nla_put_u32(skb,
1262 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID,
1263 data->id) ||
1264 nla_put_u32(skb,
1265 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN,
1266 data->anqp_len)) {
1267 goto fail;
1268 }
1269
1270 if (data->anqp_len)
1271 if (nla_put(skb,
1272 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP,
1273 data->anqp_len, data->anqp))
1274 goto fail;
1275
1276 nla_bss = nla_nest_start(skb,
1277 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1278 if (!nla_bss)
1279 goto fail;
1280
1281 if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0))
1282 goto fail;
1283
1284 nla_nest_end(skb, nla_bss);
1285 nla_nest_end(skb, nla_ap);
1286 }
1287 nla_nest_end(skb, nla_aps);
1288
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001289 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001290 return;
1291
1292fail:
1293 kfree_skb(skb);
1294 return;
1295}
1296
1297/**
1298 * wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind() -
1299 * Handle an SSID hotlist match event
1300 * @ctx: HDD context registered with SME
1301 * @event: The SSID hotlist match event
1302 *
1303 * This function will take an SSID match event that was generated by
1304 * firmware and will convert it into a cfg80211 vendor event which is
1305 * sent to userspace.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001306 * This callback execute in atomic context and must not invoke any
1307 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001308 *
1309 * Return: none
1310 */
1311static void
1312wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(void *ctx,
1313 tpSirWifiScanResultEvent event)
1314{
1315 hdd_context_t *hdd_ctx = ctx;
1316 struct sk_buff *skb;
1317 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001318 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001319
1320 ENTER();
1321
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301322 if (wlan_hdd_validate_context(hdd_ctx))
1323 return;
1324 if (!event) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001325 hdd_err("event is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001326 return;
1327 }
1328
1329 if (event->ap_found) {
1330 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001331 hdd_notice("SSID hotlist found");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001332 } else {
1333 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001334 hdd_notice("SSID hotlist lost");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001335 }
1336
1337 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1338 NULL,
1339 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001340 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001341
1342 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001343 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344 return;
1345 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07001346 hdd_notice("Req Id %u, Num results %u, More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347 event->requestId, event->numOfAps, event->moreData);
1348
1349 for (i = 0; i < event->numOfAps; i++) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001350 hdd_notice("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001351 "Ssid: %s "
1352 "Bssid (" MAC_ADDRESS_STR ") "
1353 "Channel %u "
1354 "Rssi %d "
1355 "RTT %u "
1356 "RTT_SD %u",
1357 i,
1358 event->ap[i].ts,
1359 event->ap[i].ssid,
1360 MAC_ADDR_ARRAY(event->ap[i].bssid.bytes),
1361 event->ap[i].channel,
1362 event->ap[i].rssi,
1363 event->ap[i].rtt,
1364 event->ap[i].rtt_sd);
1365 }
1366
1367 if (nla_put_u32(skb,
1368 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1369 event->requestId) ||
1370 nla_put_u32(skb,
1371 QCA_WLAN_VENDOR_ATTR_EXTSCAN_NUM_RESULTS_AVAILABLE,
1372 event->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001373 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 goto fail;
1375 }
1376
1377 if (event->numOfAps) {
1378 struct nlattr *aps;
1379 aps = nla_nest_start(skb,
1380 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1381 if (!aps) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001382 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383 goto fail;
1384 }
1385
1386 for (i = 0; i < event->numOfAps; i++) {
1387 struct nlattr *ap;
1388
1389 ap = nla_nest_start(skb, i);
1390 if (!ap) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001391 hdd_err("nest fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 goto fail;
1393 }
1394
1395 if (nla_put_u64(skb,
1396 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
1397 event->ap[i].ts) ||
1398 nla_put(skb,
1399 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
1400 sizeof(event->ap[i].ssid),
1401 event->ap[i].ssid) ||
1402 nla_put(skb,
1403 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
1404 sizeof(event->ap[i].bssid),
1405 event->ap[i].bssid.bytes) ||
1406 nla_put_u32(skb,
1407 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
1408 event->ap[i].channel) ||
1409 nla_put_s32(skb,
1410 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
1411 event->ap[i].rssi) ||
1412 nla_put_u32(skb,
1413 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
1414 event->ap[i].rtt) ||
1415 nla_put_u32(skb,
1416 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
1417 event->ap[i].rtt_sd)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001418 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001419 goto fail;
1420 }
1421 nla_nest_end(skb, ap);
1422 }
1423 nla_nest_end(skb, aps);
1424
1425 if (nla_put_u8(skb,
1426 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1427 event->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001428 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001429 goto fail;
1430 }
1431 }
1432
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001433 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434 return;
1435
1436fail:
1437 kfree_skb(skb);
1438 return;
1439}
1440
1441/**
1442 * wlan_hdd_cfg80211_extscan_generic_rsp() -
1443 * Handle a generic ExtScan Response message
1444 * @ctx: HDD context registered with SME
1445 * @response: The ExtScan response from firmware
1446 *
1447 * This function will handle a generic ExtScan response message from
1448 * firmware and will communicate the result to the userspace thread
1449 * that is waiting for the response.
1450 *
1451 * Return: none
1452 */
1453static void
1454wlan_hdd_cfg80211_extscan_generic_rsp
1455 (void *ctx,
1456 struct sir_extscan_generic_response *response)
1457{
1458 hdd_context_t *hdd_ctx = ctx;
1459 struct hdd_ext_scan_context *context;
1460
1461 ENTER();
1462
1463 if (wlan_hdd_validate_context(hdd_ctx) || !response) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001464 hdd_err("HDD context is not valid or response(%p) is null",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 response);
1466 return;
1467 }
1468
Jeff Johnson630f9e72016-07-25 12:00:12 -07001469 hdd_notice("request %u status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470 response->request_id, response->status);
1471
1472 context = &ext_scan_context;
1473 spin_lock(&context->context_lock);
1474 if (context->request_id == response->request_id) {
1475 context->response_status = response->status ? -EINVAL : 0;
1476 complete(&context->response_event);
1477 }
1478 spin_unlock(&context->context_lock);
1479
1480 return;
1481}
1482
1483/**
1484 * wlan_hdd_cfg80211_extscan_callback() - ext scan callback
1485 * @ctx: Pointer to hdd context
1486 * @evType: Event type
1487 * @pMag: Pointer to message
1488 *
1489 * Return: none
1490 */
1491void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType,
1492 void *pMsg)
1493{
1494 hdd_context_t *pHddCtx = (hdd_context_t *) ctx;
1495
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301496 ENTER();
1497
1498 if (wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001499 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001500
Jeff Johnson630f9e72016-07-25 12:00:12 -07001501 hdd_notice("Rcvd Event %d", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502
1503 switch (evType) {
1504 case eSIR_EXTSCAN_CACHED_RESULTS_RSP:
1505 /* There is no need to send this response to upper layer
1506 Just log the message */
Jeff Johnson630f9e72016-07-25 12:00:12 -07001507 hdd_notice("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001508 break;
1509
1510 case eSIR_EXTSCAN_GET_CAPABILITIES_IND:
1511 wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx,
1512 (struct ext_scan_capabilities_response *) pMsg);
1513 break;
1514
1515 case eSIR_EXTSCAN_HOTLIST_MATCH_IND:
1516 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
1517 break;
1518
1519 case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND:
1520 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx,
1521 (tpSirWifiSignificantChangeEvent) pMsg);
1522 break;
1523
1524 case eSIR_EXTSCAN_CACHED_RESULTS_IND:
1525 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
1526 break;
1527
1528 case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND:
1529 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx,
1530 (tpSirExtScanResultsAvailableIndParams) pMsg);
1531 break;
1532
1533 case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND:
1534 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx,
1535 (tpSirWifiFullScanResultEvent) pMsg);
1536 break;
1537
1538 case eSIR_EPNO_NETWORK_FOUND_IND:
1539 wlan_hdd_cfg80211_extscan_epno_match_found(ctx,
1540 (struct pno_match_found *)pMsg);
1541 break;
1542
1543 case eSIR_EXTSCAN_HOTLIST_SSID_MATCH_IND:
1544 wlan_hdd_cfg80211_extscan_hotlist_ssid_match_ind(ctx,
1545 (tpSirWifiScanResultEvent)pMsg);
1546 break;
1547
1548 case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND:
1549 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx,
1550 (tpSirExtScanOnScanEventIndParams) pMsg);
1551 break;
1552
1553 case eSIR_PASSPOINT_NETWORK_FOUND_IND:
1554 wlan_hdd_cfg80211_passpoint_match_found(ctx,
1555 (struct wifi_passpoint_match *) pMsg);
1556 break;
1557
1558 case eSIR_EXTSCAN_START_RSP:
1559 case eSIR_EXTSCAN_STOP_RSP:
1560 case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP:
1561 case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP:
1562 case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP:
1563 case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP:
1564 case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP:
1565 case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP:
1566 wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg);
1567 break;
1568
1569 default:
Jeff Johnson630f9e72016-07-25 12:00:12 -07001570 hdd_err("Unknown event type %u", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001571 break;
1572 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301573 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001574}
1575
1576/*
1577 * define short names for the global vendor params
1578 * used by wlan_hdd_send_ext_scan_capability()
1579 */
1580#define PARAM_REQUEST_ID \
1581 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1582#define PARAM_STATUS \
1583 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1584#define MAX_SCAN_CACHE_SIZE \
1585 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1586#define MAX_SCAN_BUCKETS \
1587 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1588#define MAX_AP_CACHE_PER_SCAN \
1589 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1590#define MAX_RSSI_SAMPLE_SIZE \
1591 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1592#define MAX_SCAN_RPT_THRHOLD \
1593 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1594#define MAX_HOTLIST_BSSIDS \
1595 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1596#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1597 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1598#define MAX_BSSID_HISTORY_ENTRIES \
1599 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1600#define MAX_HOTLIST_SSIDS \
1601 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1602#define MAX_NUM_EPNO_NETS \
1603 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1604#define MAX_NUM_EPNO_NETS_BY_SSID \
1605 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1606#define MAX_NUM_WHITELISTED_SSID \
1607 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
1608
1609/**
1610 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1611 * @hdd_ctx: Pointer to hdd context
1612 *
1613 * Return: 0 for success, non-zero for failure
1614 */
1615static int wlan_hdd_send_ext_scan_capability(hdd_context_t *hdd_ctx)
1616{
1617 int ret;
1618 struct sk_buff *skb;
1619 struct ext_scan_capabilities_response *data;
1620 uint32_t nl_buf_len;
1621
1622 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301623 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001624 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001625
1626 data = &(ext_scan_context.capability_response);
1627
1628 nl_buf_len = NLMSG_HDRLEN;
1629 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1630 (sizeof(data->status) + NLA_HDRLEN) +
1631 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1632 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1633 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1634 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1635 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1636 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1637 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1638 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1639 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1640 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1641 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
1642 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN);
1643
1644 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1645
1646 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001647 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648 return -ENOMEM;
1649 }
1650
1651
Jeff Johnson630f9e72016-07-25 12:00:12 -07001652 hdd_notice("Req Id %u", data->requestId);
1653 hdd_notice("Status %u", data->status);
1654 hdd_notice("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001655 data->max_scan_cache_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001656 hdd_notice("Scan buckets %u", data->max_scan_buckets);
1657 hdd_notice("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001658 data->max_ap_cache_per_scan);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001659 hdd_notice("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001660 data->max_rssi_sample_size);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001661 hdd_notice("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 data->max_scan_reporting_threshold);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001663 hdd_notice("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001664 data->max_hotlist_bssids);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001665 hdd_notice("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 data->max_significant_wifi_change_aps);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001667 hdd_notice("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668 data->max_bssid_history_entries);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001669 hdd_notice("max_hotlist_ssids %u", data->max_hotlist_ssids);
1670 hdd_notice("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671 data->max_number_epno_networks);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001672 hdd_notice("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673 data->max_number_epno_networks_by_ssid);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001674 hdd_notice("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001675 data->max_number_of_white_listed_ssid);
1676
1677 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1678 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1679 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1680 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1681 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1682 data->max_ap_cache_per_scan) ||
1683 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1684 data->max_rssi_sample_size) ||
1685 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1686 data->max_scan_reporting_threshold) ||
1687 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1688 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1689 data->max_significant_wifi_change_aps) ||
1690 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1691 data->max_bssid_history_entries) ||
1692 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1693 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1694 data->max_number_epno_networks) ||
1695 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1696 data->max_number_epno_networks_by_ssid) ||
1697 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
1698 data->max_number_of_white_listed_ssid)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001699 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001700 goto nla_put_failure;
1701 }
1702
1703 cfg80211_vendor_cmd_reply(skb);
1704 return 0;
1705
1706nla_put_failure:
1707 kfree_skb(skb);
1708 return -EINVAL;
1709}
1710/*
1711 * done with short names for the global vendor params
1712 * used by wlan_hdd_send_ext_scan_capability()
1713 */
1714#undef PARAM_REQUEST_ID
1715#undef PARAM_STATUS
1716#undef MAX_SCAN_CACHE_SIZE
1717#undef MAX_SCAN_BUCKETS
1718#undef MAX_AP_CACHE_PER_SCAN
1719#undef MAX_RSSI_SAMPLE_SIZE
1720#undef MAX_SCAN_RPT_THRHOLD
1721#undef MAX_HOTLIST_BSSIDS
1722#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1723#undef MAX_BSSID_HISTORY_ENTRIES
1724#undef MAX_HOTLIST_SSIDS
1725#undef MAX_NUM_EPNO_NETS
1726#undef MAX_NUM_EPNO_NETS_BY_SSID
1727#undef MAX_NUM_WHITELISTED_SSID
1728
1729/**
1730 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1731 * @wiphy: Pointer to wireless phy
1732 * @wdev: Pointer to wireless device
1733 * @data: Pointer to data
1734 * @data_len: Data length
1735 *
1736 * Return: none
1737 */
1738static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1739 struct wireless_dev *wdev,
1740 const void *data, int data_len)
1741{
1742 int ret;
1743 unsigned long rc;
1744 struct hdd_ext_scan_context *context;
1745 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1746 struct net_device *dev = wdev->netdev;
1747 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1748 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1749 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1750 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301751 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752
Jeff Johnson1f61b612016-02-12 16:28:33 -08001753 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754
Anurag Chouhan6d760662016-02-20 16:05:43 +05301755 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756 hdd_err("Command not allowed in FTM mode");
1757 return -EPERM;
1758 }
1759
1760 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301761 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763
1764 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1765 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001766 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 return -EINVAL;
1768 }
1769
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301770 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001771 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001772 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001773 return -ENOMEM;
1774 }
1775
1776 /* Parse and fetch request Id */
1777 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001778 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 goto fail;
1780 }
1781
1782 pReqMsg->requestId =
1783 nla_get_u32(tb
1784 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
1785 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001786 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001787 pReqMsg->requestId, pReqMsg->sessionId);
1788
1789 context = &ext_scan_context;
1790 spin_lock(&context->context_lock);
1791 context->request_id = pReqMsg->requestId;
1792 INIT_COMPLETION(context->response_event);
1793 spin_unlock(&context->context_lock);
1794
1795 status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301796 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001797 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 status);
1799 goto fail;
1800 }
1801
1802 rc = wait_for_completion_timeout(&context->response_event,
1803 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1804 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001805 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001806 return -ETIMEDOUT;
1807 }
1808
1809 ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
1810 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001811 hdd_err("Failed to send ext scan capability to user space");
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301812 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001813 return ret;
1814fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301815 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001816 return -EINVAL;
1817}
1818
1819/**
1820 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1821 * @wiphy: Pointer to wiphy
1822 * @wdev: Pointer to wdev
1823 * @data: Pointer to data
1824 * @data_len: Data length
1825 *
1826 * Return: 0 for success, non-zero for failure
1827 */
1828int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1829 struct wireless_dev *wdev,
1830 const void *data, int data_len)
1831{
1832 int ret = 0;
1833
1834 cds_ssr_protect(__func__);
1835 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1836 data_len);
1837 cds_ssr_unprotect(__func__);
1838
1839 return ret;
1840}
1841
1842/*
1843 * define short names for the global vendor params
1844 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1845 */
1846#define PARAM_MAX \
1847 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1848#define PARAM_REQUEST_ID \
1849 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1850#define PARAM_FLUSH \
1851 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1852/**
1853 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1854 * @wiphy: wiphy pointer
1855 * @wdev: pointer to struct wireless_dev
1856 * @data: pointer to incoming NL vendor data
1857 * @data_len: length of @data
1858 *
1859 * This function parses the incoming NL vendor command data attributes and
1860 * invokes the SME Api and blocks on a completion variable.
1861 * Each WMI event with cached scan results data chunk results in
1862 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1863 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1864 *
1865 * If timeout happens before receiving all of the data, this function sets
1866 * a context variable @ignore_cached_results to %true, all of the next data
1867 * chunks are checked against this variable and dropped.
1868 *
1869 * Return: 0 on success; error number otherwise.
1870 */
1871static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1872 struct wireless_dev
1873 *wdev, const void *data,
1874 int data_len)
1875{
1876 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1877 struct net_device *dev = wdev->netdev;
1878 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1879 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1880 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1881 1];
1882 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301883 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001884 int retval = 0;
1885 unsigned long rc;
1886
Jeff Johnson1f61b612016-02-12 16:28:33 -08001887 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001888
Anurag Chouhan6d760662016-02-20 16:05:43 +05301889 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 hdd_err("Command not allowed in FTM mode");
1891 return -EPERM;
1892 }
1893
1894 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301895 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897
1898 if (nla_parse(tb, PARAM_MAX, data, data_len,
1899 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001900 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 return -EINVAL;
1902 }
1903
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301904 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001906 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907 return -ENOMEM;
1908 }
1909
1910 /* Parse and fetch request Id */
1911 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001912 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001913 goto fail;
1914 }
1915
1916 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
1917 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07001918 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 pReqMsg->requestId, pReqMsg->sessionId);
1920
1921 /* Parse and fetch flush parameter */
1922 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001923 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001924 goto fail;
1925 }
1926 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07001927 hdd_notice("Flush %d", pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928
1929 context = &ext_scan_context;
1930 spin_lock(&context->context_lock);
1931 context->request_id = pReqMsg->requestId;
1932 context->ignore_cached_results = false;
1933 INIT_COMPLETION(context->response_event);
1934 spin_unlock(&context->context_lock);
1935
1936 status = sme_get_cached_results(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301937 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001938 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001939 goto fail;
1940 }
1941
1942 rc = wait_for_completion_timeout(&context->response_event,
1943 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1944 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001945 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 retval = -ETIMEDOUT;
1947 spin_lock(&context->context_lock);
1948 context->ignore_cached_results = true;
1949 spin_unlock(&context->context_lock);
1950 } else {
1951 spin_lock(&context->context_lock);
1952 retval = context->response_status;
1953 spin_unlock(&context->context_lock);
1954 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301955 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956 return retval;
1957
1958fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301959 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 return -EINVAL;
1961}
1962/*
1963 * done with short names for the global vendor params
1964 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1965 */
1966#undef PARAM_MAX
1967#undef PARAM_REQUEST_ID
1968#undef PARAM_FLUSH
1969
1970/**
1971 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1972 * @wiphy: wiphy pointer
1973 * @wdev: pointer to struct wireless_dev
1974 * @data: pointer to incoming NL vendor data
1975 * @data_len: length of @data
1976 *
1977 * This function parses the incoming NL vendor command data attributes and
1978 * invokes the SME Api and blocks on a completion variable.
1979 * Each WMI event with cached scan results data chunk results in
1980 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1981 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1982 *
1983 * If timeout happens before receiving all of the data, this function sets
1984 * a context variable @ignore_cached_results to %true, all of the next data
1985 * chunks are checked against this variable and dropped.
1986 *
1987 * Return: 0 on success; error number otherwise.
1988 */
1989int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1990 struct wireless_dev *wdev,
1991 const void *data, int data_len)
1992{
1993 int ret = 0;
1994
1995 cds_ssr_protect(__func__);
1996 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
1997 data_len);
1998 cds_ssr_unprotect(__func__);
1999
2000 return ret;
2001}
2002
2003/**
2004 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
2005 * @wiphy: Pointer to wireless phy
2006 * @wdev: Pointer to wireless device
2007 * @data: Pointer to data
2008 * @data_len: Data length
2009 *
2010 * Return: none
2011 */
2012static int
2013__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2014 struct wireless_dev
2015 *wdev, const void *data,
2016 int data_len)
2017{
2018 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
2019 struct net_device *dev = wdev->netdev;
2020 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2021 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2022 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2023 1];
2024 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2025 + 1];
2026 struct nlattr *apTh;
2027 struct hdd_ext_scan_context *context;
2028 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302029 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002030 uint8_t i;
2031 int rem, retval;
2032 unsigned long rc;
2033
Jeff Johnson1f61b612016-02-12 16:28:33 -08002034 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035
Anurag Chouhan6d760662016-02-20 16:05:43 +05302036 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002037 hdd_err("Command not allowed in FTM mode");
2038 return -EPERM;
2039 }
2040
2041 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302042 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002043 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044
2045 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 */
2426void hdd_remove_dsrc_channels(struct wiphy *wiphy, uint32_t *chan_list,
2427 uint8_t *num_channels)
2428{
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))
2451void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2452 uint8_t *num_channels)
2453{
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
2476void hdd_remove_indoor_channels(struct wiphy *wiphy, uint32_t *chan_list,
2477 uint8_t *num_channels)
2478{
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};
2502 uint8_t num_channels = 0;
2503 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;
2509 uint8_t i;
2510 int ret;
2511
Jeff Johnson1f61b612016-02-12 16:28:33 -08002512 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002513
Anurag Chouhan6d760662016-02-20 16:05:43 +05302514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002515 hdd_err("Command not allowed in FTM mode");
2516 return -EPERM;
2517 }
2518
2519 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302520 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002521 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522
2523 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2524 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002525 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002526 return -EINVAL;
2527 }
2528
2529 /* Parse and fetch request Id */
2530 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002531 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532 return -EINVAL;
2533 }
2534 requestId =
2535 nla_get_u32(tb
2536 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002537 hdd_notice("Req Id %d", requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538
2539 /* Parse and fetch wifi band */
2540 if (!tb
2541 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002542 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543 return -EINVAL;
2544 }
2545 wifiBand =
2546 nla_get_u32(tb
2547 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002548 hdd_notice("Wifi band %d", wifiBand);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549
2550 if (!tb
2551 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002552 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 return -EINVAL;
2554 }
2555 maxChannels =
2556 nla_get_u32(tb
2557 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002558 hdd_notice("Max channels %d", maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002559 status = sme_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal),
2560 wifiBand, chan_list,
2561 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302562 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002563 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002564 status);
2565 return -EINVAL;
2566 }
2567
Anurag Chouhan6d760662016-02-20 16:05:43 +05302568 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002569
2570 hdd_remove_dsrc_channels(wiphy, chan_list, &num_channels);
2571
Krunal Sonibe766b02016-03-10 13:00:44 -08002572 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002573 !strncmp(hdd_get_fwpath(), "ap", 2))
2574 hdd_remove_indoor_channels(wiphy, chan_list, &num_channels);
2575
Jeff Johnson630f9e72016-07-25 12:00:12 -07002576 hdd_notice("Number of channels %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577 for (i = 0; i < num_channels; i++)
Jeff Johnson630f9e72016-07-25 12:00:12 -07002578 hdd_notice("Channel: %u ", chan_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002579
2580 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2581 sizeof(u32) *
2582 num_channels +
2583 NLMSG_HDRLEN);
2584
2585 if (reply_skb) {
2586 if (nla_put_u32(reply_skb,
2587 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2588 num_channels) ||
2589 nla_put(reply_skb,
2590 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2591 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002592 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 kfree_skb(reply_skb);
2594 return -EINVAL;
2595 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302596 ret = cfg80211_vendor_cmd_reply(reply_skb);
2597 EXIT();
2598 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002599 }
2600
Jeff Johnson630f9e72016-07-25 12:00:12 -07002601 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002602 return -EINVAL;
2603}
2604
2605/**
2606 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2607 * @wiphy: Pointer to wireless phy
2608 * @wdev: Pointer to wireless device
2609 * @data: Pointer to data
2610 * @data_len: Data length
2611 *
2612 * Return: 0 on success, negative errno on failure
2613 */
2614int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2615 struct wireless_dev *wdev,
2616 const void *data, int data_len)
2617{
2618 int ret = 0;
2619
2620 cds_ssr_protect(__func__);
2621 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2622 data_len);
2623 cds_ssr_unprotect(__func__);
2624
2625 return ret;
2626}
2627
2628/**
2629 * hdd_extscan_update_dwell_time_limits() - update dwell times
2630 * @req_msg: Pointer to request message
2631 * @bkt_idx: Index of current bucket being processed
2632 * @active_min: minimum active dwell time
2633 * @active_max: maximum active dwell time
2634 * @passive_min: minimum passive dwell time
2635 * @passive_max: maximum passive dwell time
2636 *
2637 * Return: none
2638 */
2639static void hdd_extscan_update_dwell_time_limits(
2640 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2641 uint32_t active_min, uint32_t active_max,
2642 uint32_t passive_min, uint32_t passive_max)
2643{
2644 /* update per-bucket dwell times */
2645 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2646 active_min) {
2647 req_msg->buckets[bkt_idx].min_dwell_time_active =
2648 active_min;
2649 }
2650 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2651 active_max) {
2652 req_msg->buckets[bkt_idx].max_dwell_time_active =
2653 active_max;
2654 }
2655 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2656 passive_min) {
2657 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2658 passive_min;
2659 }
2660 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2661 passive_max) {
2662 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2663 passive_max;
2664 }
2665 /* update dwell-time across all buckets */
2666 if (req_msg->min_dwell_time_active >
2667 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2668 req_msg->min_dwell_time_active =
2669 req_msg->buckets[bkt_idx].min_dwell_time_active;
2670 }
2671 if (req_msg->max_dwell_time_active <
2672 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2673 req_msg->max_dwell_time_active =
2674 req_msg->buckets[bkt_idx].max_dwell_time_active;
2675 }
2676 if (req_msg->min_dwell_time_passive >
2677 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2678 req_msg->min_dwell_time_passive =
2679 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2680 }
2681 if (req_msg->max_dwell_time_passive >
2682 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2683 req_msg->max_dwell_time_passive =
2684 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2685 }
2686}
2687
2688/**
2689 * hdd_extscan_channel_max_reached() - channel max reached
2690 * @req: extscan request structure
2691 * @total_channels: total number of channels
2692 *
2693 * Return: true if total channels reached max, false otherwise
2694 */
2695static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2696 uint8_t total_channels)
2697{
2698 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2699 hdd_warn(
2700 "max #of channels %d reached, take only first %d bucket(s)",
2701 total_channels, req->numBuckets);
2702 return true;
2703 }
2704 return false;
2705}
2706
2707/**
2708 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2709 * @hdd_ctx: HDD global context
2710 * @req_msg: Pointer to request structure
2711 * @tb: pointer to NL attributes
2712 *
2713 * Return: 0 on success; error number otherwise
2714 */
2715static int hdd_extscan_start_fill_bucket_channel_spec(
2716 hdd_context_t *hdd_ctx,
2717 tpSirWifiScanCmdReqParams req_msg,
2718 struct nlattr **tb)
2719{
2720 struct nlattr *bucket[
2721 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2722 struct nlattr *channel[
2723 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2724 struct nlattr *buckets;
2725 struct nlattr *channels;
2726 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302727 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728 uint8_t bkt_index, j, num_channels, total_channels = 0;
2729 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2730
2731 uint32_t min_dwell_time_active_bucket =
2732 hdd_ctx->config->extscan_active_max_chn_time;
2733 uint32_t max_dwell_time_active_bucket =
2734 hdd_ctx->config->extscan_active_max_chn_time;
2735 uint32_t min_dwell_time_passive_bucket =
2736 hdd_ctx->config->extscan_passive_max_chn_time;
2737 uint32_t max_dwell_time_passive_bucket =
2738 hdd_ctx->config->extscan_passive_max_chn_time;
2739
2740 bkt_index = 0;
2741 req_msg->min_dwell_time_active =
2742 req_msg->max_dwell_time_active =
2743 hdd_ctx->config->extscan_active_max_chn_time;
2744
2745 req_msg->min_dwell_time_passive =
2746 req_msg->max_dwell_time_passive =
2747 hdd_ctx->config->extscan_passive_max_chn_time;
2748 req_msg->numBuckets = 0;
2749
2750 nla_for_each_nested(buckets,
2751 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
2752 if (nla_parse(bucket,
2753 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2754 nla_data(buckets), nla_len(buckets), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002755 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 return -EINVAL;
2757 }
2758
2759 /* Parse and fetch bucket spec */
2760 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002761 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002762 return -EINVAL;
2763 }
2764 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2765 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002766 hdd_notice("Bucket spec Index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767 req_msg->buckets[bkt_index].bucket);
2768
2769 /* Parse and fetch wifi band */
2770 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002771 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002772 return -EINVAL;
2773 }
2774 req_msg->buckets[bkt_index].band = nla_get_u8(
2775 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002776 hdd_notice("Wifi band %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 req_msg->buckets[bkt_index].band);
2778
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]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002786 hdd_notice("period %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 req_msg->buckets[bkt_index].period);
2788
2789 /* Parse and fetch report events */
2790 if (!bucket[
2791 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002792 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002793 return -EINVAL;
2794 }
2795 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2796 bucket[
2797 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002798 hdd_notice("report events %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002799 req_msg->buckets[bkt_index].reportEvents);
2800
2801 /* Parse and fetch max period */
2802 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002803 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002804 return -EINVAL;
2805 }
2806 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2807 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002808 hdd_notice("max period %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002809 req_msg->buckets[bkt_index].max_period);
2810
Mukul Sharmafa937be2016-08-12 18:13:36 +05302811 /* Parse and fetch base */
2812 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]) {
2813 hdd_err("attr base failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 return -EINVAL;
2815 }
2816 req_msg->buckets[bkt_index].exponent = nla_get_u32(
Mukul Sharmafa937be2016-08-12 18:13:36 +05302817 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]);
2818 hdd_notice("base %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002819 req_msg->buckets[bkt_index].exponent);
2820
2821 /* Parse and fetch step count */
2822 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002823 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824 return -EINVAL;
2825 }
2826 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2827 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002828 hdd_notice("Step count %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 req_msg->buckets[bkt_index].step_count);
2830
2831 /* start with known good values for bucket dwell times */
2832 req_msg->buckets[bkt_index].min_dwell_time_active =
2833 req_msg->buckets[bkt_index].max_dwell_time_active =
2834 hdd_ctx->config->extscan_active_max_chn_time;
2835
2836 req_msg->buckets[bkt_index].min_dwell_time_passive =
2837 req_msg->buckets[bkt_index].max_dwell_time_passive =
2838 hdd_ctx->config->extscan_passive_max_chn_time;
2839
2840 /* Framework shall pass the channel list if the input WiFi band
2841 * is WIFI_BAND_UNSPECIFIED.
2842 * If the input WiFi band is specified (any value other than
2843 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2844 */
2845 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2846 if (hdd_extscan_channel_max_reached(req_msg,
2847 total_channels))
2848 return 0;
2849
2850 num_channels = 0;
Jeff Johnson630f9e72016-07-25 12:00:12 -07002851 hdd_notice("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2853 req_msg->buckets[bkt_index].band,
2854 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302855 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002856 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002857 status);
2858 return -EINVAL;
2859 }
Jeff Johnson630f9e72016-07-25 12:00:12 -07002860 hdd_notice("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002861 num_channels);
2862
2863 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302864 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002865 (WLAN_EXTSCAN_MAX_CHANNELS -
2866 total_channels));
2867 hdd_info("Adj Num channels/bucket: %d total_channels: %d",
2868 req_msg->buckets[bkt_index].numChannels,
2869 total_channels);
2870 total_channels +=
2871 req_msg->buckets[bkt_index].numChannels;
2872
2873 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2874 j++) {
2875 req_msg->buckets[bkt_index].channels[j].channel =
2876 chan_list[j];
2877 req_msg->buckets[bkt_index].channels[j].
2878 chnlClass = 0;
2879 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
2880 cds_freq_to_chan(chan_list[j]))) {
2881 req_msg->buckets[bkt_index].channels[j].
2882 passive = 1;
2883 req_msg->buckets[bkt_index].channels[j].
2884 dwellTimeMs =
2885 hdd_ctx->config->
2886 extscan_passive_max_chn_time;
2887 /* reconfigure per-bucket dwell time */
2888 if (min_dwell_time_passive_bucket >
2889 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2890 min_dwell_time_passive_bucket =
2891 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2892 }
2893 if (max_dwell_time_passive_bucket <
2894 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2895 max_dwell_time_passive_bucket =
2896 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2897 }
2898
2899 } else {
2900 req_msg->buckets[bkt_index].channels[j].
2901 passive = 0;
2902 req_msg->buckets[bkt_index].channels[j].
2903 dwellTimeMs =
2904 hdd_ctx->config->extscan_active_max_chn_time;
2905 /* reconfigure per-bucket dwell times */
2906 if (min_dwell_time_active_bucket >
2907 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2908 min_dwell_time_active_bucket =
2909 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2910 }
2911 if (max_dwell_time_active_bucket <
2912 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2913 max_dwell_time_active_bucket =
2914 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2915 }
2916
2917 }
2918
Jeff Johnson630f9e72016-07-25 12:00:12 -07002919 hdd_notice("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 req_msg->buckets[bkt_index].channels[j].channel,
2921 req_msg->buckets[bkt_index].channels[j].passive,
2922 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2923 req_msg->buckets[bkt_index].channels[j].chnlClass);
2924 }
2925
2926 hdd_extscan_update_dwell_time_limits(
2927 req_msg, bkt_index,
2928 min_dwell_time_active_bucket,
2929 max_dwell_time_active_bucket,
2930 min_dwell_time_passive_bucket,
2931 max_dwell_time_passive_bucket);
2932
Jeff Johnson630f9e72016-07-25 12:00:12 -07002933 hdd_notice("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 bkt_index,
2935 req_msg->buckets[bkt_index].min_dwell_time_active,
2936 req_msg->buckets[bkt_index].max_dwell_time_active,
2937 req_msg->buckets[bkt_index].min_dwell_time_passive,
2938 req_msg->buckets[bkt_index].max_dwell_time_passive);
2939
2940 bkt_index++;
2941 req_msg->numBuckets++;
2942 continue;
2943 }
2944
2945 /* Parse and fetch number of channels */
2946 if (!bucket[
2947 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002948 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 return -EINVAL;
2950 }
2951 req_msg->buckets[bkt_index].numChannels =
2952 nla_get_u32(bucket[
2953 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
2954 hdd_info("before trimming: num channels %d",
2955 req_msg->buckets[bkt_index].numChannels);
2956
2957 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302958 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002959 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
2960 hdd_info("Num channels/bucket: %d total_channels: %d",
2961 req_msg->buckets[bkt_index].numChannels,
2962 total_channels);
2963 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
2964 return 0;
2965
2966 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002967 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002968 return -EINVAL;
2969 }
2970
2971 j = 0;
2972 nla_for_each_nested(channels,
2973 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07002974 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
2975 hdd_extscan_channel_max_reached(req_msg,
2976 total_channels))
2977 break;
2978
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979 if (nla_parse(channel,
2980 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2981 nla_data(channels), nla_len(channels),
2982 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002983 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 return -EINVAL;
2985 }
2986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002987 /* Parse and fetch channel */
2988 if (!channel[
2989 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002990 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002991 return -EINVAL;
2992 }
2993 req_msg->buckets[bkt_index].channels[j].channel =
2994 nla_get_u32(channel[
2995 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07002996 hdd_notice("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997 req_msg->buckets[bkt_index].channels[j].channel);
2998
2999 /* Parse and fetch dwell time */
3000 if (!channel[
3001 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003002 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003003 return -EINVAL;
3004 }
3005 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3006 nla_get_u32(channel[
3007 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
3008
3009 /* Override dwell time if required */
3010 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
3011 hdd_ctx->config->extscan_active_min_chn_time ||
3012 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
3013 hdd_ctx->config->extscan_active_max_chn_time) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003014 hdd_notice("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3016
3017 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3018 cds_freq_to_chan(
3019 req_msg->buckets[bkt_index].channels[j].channel))) {
3020 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3021 hdd_ctx->config->extscan_passive_max_chn_time;
3022 } else {
3023 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
3024 hdd_ctx->config->extscan_active_max_chn_time;
3025 }
3026 }
3027
Jeff Johnson630f9e72016-07-25 12:00:12 -07003028 hdd_notice("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003029 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
3030
3031 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3032 cds_freq_to_chan(
3033 req_msg->buckets[bkt_index].channels[j].channel))) {
3034 if (min_dwell_time_passive_bucket >
3035 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3036 min_dwell_time_passive_bucket =
3037 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3038 }
3039 if (max_dwell_time_passive_bucket <
3040 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3041 max_dwell_time_passive_bucket =
3042 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3043 }
3044 } else {
3045 if (min_dwell_time_active_bucket >
3046 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3047 min_dwell_time_active_bucket =
3048 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3049 }
3050 if (max_dwell_time_active_bucket <
3051 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3052 max_dwell_time_active_bucket =
3053 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3054 }
3055 }
3056
3057 /* Parse and fetch channel spec passive */
3058 if (!channel[
3059 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003060 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 return -EINVAL;
3062 }
3063 req_msg->buckets[bkt_index].channels[j].passive =
3064 nla_get_u8(channel[
3065 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003066 hdd_notice("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067 req_msg->buckets[bkt_index].channels[j].passive);
3068 /* Override scan type if required */
3069 if (CDS_IS_PASSIVE_OR_DISABLE_CH(
3070 cds_freq_to_chan(
3071 req_msg->buckets[bkt_index].channels[j].channel))) {
3072 req_msg->buckets[bkt_index].channels[j].passive = true;
3073 } else {
3074 req_msg->buckets[bkt_index].channels[j].passive = false;
3075 }
3076 j++;
3077 total_channels++;
3078 }
3079
3080 hdd_extscan_update_dwell_time_limits(
3081 req_msg, bkt_index,
3082 min_dwell_time_active_bucket,
3083 max_dwell_time_active_bucket,
3084 min_dwell_time_passive_bucket,
3085 max_dwell_time_passive_bucket);
3086
Jeff Johnson630f9e72016-07-25 12:00:12 -07003087 hdd_notice("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003088 bkt_index,
3089 req_msg->buckets[bkt_index].min_dwell_time_active,
3090 req_msg->buckets[bkt_index].max_dwell_time_active,
3091 req_msg->buckets[bkt_index].min_dwell_time_passive,
3092 req_msg->buckets[bkt_index].max_dwell_time_passive);
3093
3094 bkt_index++;
3095 req_msg->numBuckets++;
3096 }
3097
Jeff Johnson630f9e72016-07-25 12:00:12 -07003098 hdd_notice("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 req_msg->min_dwell_time_active,
3100 req_msg->max_dwell_time_active,
3101 req_msg->min_dwell_time_passive,
3102 req_msg->max_dwell_time_passive);
3103
3104 return 0;
3105}
3106
3107/*
3108 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3109 * @config_flags - [input] configuration flags.
3110 *
3111 * This function maps user space received configuration flags to
3112 * driver representation.
3113 *
3114 * Return: configuration flags
3115 */
3116static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3117{
3118 uint32_t configuration_flags = 0;
3119
3120 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3121 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3122
3123 return configuration_flags;
3124}
3125
3126/*
3127 * define short names for the global vendor params
3128 * used by __wlan_hdd_cfg80211_extscan_start()
3129 */
3130#define PARAM_MAX \
3131 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3132#define PARAM_REQUEST_ID \
3133 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3134#define PARAM_BASE_PERIOD \
3135 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3136#define PARAM_MAX_AP_PER_SCAN \
3137 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3138#define PARAM_RPT_THRHLD_PERCENT \
3139 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3140#define PARAM_RPT_THRHLD_NUM_SCANS \
3141 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3142#define PARAM_NUM_BUCKETS \
3143 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3144#define PARAM_CONFIG_FLAGS \
3145 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3146
3147/**
3148 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3149 * @wiphy: Pointer to wireless phy
3150 * @wdev: Pointer to wireless device
3151 * @data: Pointer to data
3152 * @data_len: Length of @data
3153 *
3154 * Return: 0 on success; error number otherwise
3155 */
3156static int
3157__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3158 struct wireless_dev *wdev,
3159 const void *data,
3160 int data_len)
3161{
3162 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3163 struct net_device *dev = wdev->netdev;
3164 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3165 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3166 struct nlattr *tb[PARAM_MAX + 1];
3167 struct hdd_ext_scan_context *context;
3168 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303169 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 int retval;
3171 unsigned long rc;
3172
Jeff Johnson1f61b612016-02-12 16:28:33 -08003173 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174
Anurag Chouhan6d760662016-02-20 16:05:43 +05303175 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 hdd_err("Command not allowed in FTM mode");
3177 return -EPERM;
3178 }
3179
3180 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303181 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003182 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003183
3184 if (nla_parse(tb, PARAM_MAX, data, data_len,
3185 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003186 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187 return -EINVAL;
3188 }
3189
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303190 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003192 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193 return -ENOMEM;
3194 }
3195
3196 /* Parse and fetch request Id */
3197 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003198 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003199 goto fail;
3200 }
3201
3202 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3203 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003204 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 pReqMsg->requestId,
3206 pReqMsg->sessionId);
3207
3208 /* Parse and fetch base period */
3209 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003210 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 goto fail;
3212 }
3213 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003214 hdd_notice("Base Period %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 pReqMsg->basePeriod);
3216
3217 /* Parse and fetch max AP per scan */
3218 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003219 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003220 goto fail;
3221 }
3222 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003223 hdd_notice("Max AP per Scan %d", pReqMsg->maxAPperScan);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224
3225 /* Parse and fetch report threshold percent */
3226 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003227 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003228 goto fail;
3229 }
3230 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003231 hdd_notice("Report Threshold percent %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 pReqMsg->report_threshold_percent);
3233
3234 /* Parse and fetch report threshold num scans */
3235 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003236 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003237 goto fail;
3238 }
3239 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003240 hdd_notice("Report Threshold num scans %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003241 pReqMsg->report_threshold_num_scans);
3242
3243 /* Parse and fetch number of buckets */
3244 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003245 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003246 goto fail;
3247 }
3248 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3249 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3250 hdd_warn("Exceeded MAX number of buckets: %d",
3251 WLAN_EXTSCAN_MAX_BUCKETS);
3252 }
3253 hdd_info("Input: Number of Buckets %d", num_buckets);
3254
3255 /* This is optional attribute, if not present set it to 0 */
3256 if (!tb[PARAM_CONFIG_FLAGS])
3257 pReqMsg->configuration_flags = 0;
3258 else
3259 pReqMsg->configuration_flags =
3260 hdd_extscan_map_usr_drv_config_flags(
3261 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3262
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303263 pReqMsg->extscan_adaptive_dwell_mode =
3264 pHddCtx->config->extscan_adaptive_dwell_mode;
3265
Jeff Johnson630f9e72016-07-25 12:00:12 -07003266 hdd_notice("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 pReqMsg->configuration_flags);
3268
3269 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003270 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271 goto fail;
3272 }
3273
3274 if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb))
3275 goto fail;
3276
3277 context = &ext_scan_context;
3278 spin_lock(&context->context_lock);
3279 INIT_COMPLETION(context->response_event);
3280 context->request_id = request_id = pReqMsg->requestId;
Mukul Sharmafa937be2016-08-12 18:13:36 +05303281 context->buckets_scanned = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282 spin_unlock(&context->context_lock);
3283
3284 status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303285 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003286 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 goto fail;
3288 }
3289
Anurag Chouhan50220ce2016-02-18 20:11:33 +05303290 pHddCtx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Jeff Johnson630f9e72016-07-25 12:00:12 -07003291 hdd_notice("Timestamp since boot: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003292 pHddCtx->ext_scan_start_since_boot);
3293
3294 /* request was sent -- wait for the response */
3295 rc = wait_for_completion_timeout(&context->response_event,
3296 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3297
3298 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003299 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003300 retval = -ETIMEDOUT;
3301 } else {
3302 spin_lock(&context->context_lock);
3303 if (context->request_id == request_id)
3304 retval = context->response_status;
3305 else
3306 retval = -EINVAL;
3307 spin_unlock(&context->context_lock);
3308 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303309 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003310 return retval;
3311
3312fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303313 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314 return -EINVAL;
3315}
3316/*
3317 * done with short names for the global vendor params
3318 * used by __wlan_hdd_cfg80211_extscan_start()
3319 */
3320#undef PARAM_MAX
3321#undef PARAM_REQUEST_ID
3322#undef PARAM_BASE_PERIOD
3323#undef PARAMS_MAX_AP_PER_SCAN
3324#undef PARAMS_RPT_THRHLD_PERCENT
3325#undef PARAMS_RPT_THRHLD_NUM_SCANS
3326#undef PARAMS_NUM_BUCKETS
3327#undef PARAM_CONFIG_FLAGS
3328
3329/**
3330 * wlan_hdd_cfg80211_extscan_start() - start extscan
3331 * @wiphy: Pointer to wireless phy.
3332 * @wdev: Pointer to wireless device.
3333 * @data: Pointer to input data.
3334 * @data_len: Length of @data.
3335 *
3336 * Return: 0 on success, negative errno on failure
3337 */
3338int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3339 struct wireless_dev *wdev,
3340 const void *data, int data_len)
3341{
3342 int ret = 0;
3343
3344 cds_ssr_protect(__func__);
3345 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3346 cds_ssr_unprotect(__func__);
3347
3348 return ret;
3349}
3350
3351
3352/*
3353 * define short names for the global vendor params
3354 * used by __wlan_hdd_cfg80211_extscan_stop()
3355 */
3356#define PARAM_MAX \
3357 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3358#define PARAM_REQUEST_ID \
3359 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3360
3361/**
3362 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3363 * @wiphy: Pointer to wireless phy
3364 * @wdev: Pointer to wireless device
3365 * @data: Pointer to data
3366 * @data_len: Data length
3367 *
3368 * Return: none
3369 */
3370static int
3371__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3372 struct wireless_dev *wdev,
3373 const void *data, int data_len)
3374{
3375 tpSirExtScanStopReqParams pReqMsg = NULL;
3376 struct net_device *dev = wdev->netdev;
3377 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3378 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3379 struct nlattr *tb[PARAM_MAX + 1];
3380 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303381 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003382 uint32_t request_id;
3383 int retval;
3384 unsigned long rc;
3385
Jeff Johnson1f61b612016-02-12 16:28:33 -08003386 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387
Anurag Chouhan6d760662016-02-20 16:05:43 +05303388 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 hdd_err("Command not allowed in FTM mode");
3390 return -EPERM;
3391 }
3392
3393 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303394 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003396
3397 if (nla_parse(tb, PARAM_MAX, data, data_len,
3398 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003399 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003400 return -EINVAL;
3401 }
3402
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303403 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003404 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003405 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003406 return -ENOMEM;
3407 }
3408
3409 /* Parse and fetch request Id */
3410 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003411 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003412 goto fail;
3413 }
3414
3415 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3416 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003417 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003418 pReqMsg->requestId, pReqMsg->sessionId);
3419
3420 context = &ext_scan_context;
3421 spin_lock(&context->context_lock);
3422 INIT_COMPLETION(context->response_event);
3423 context->request_id = request_id = pReqMsg->requestId;
3424 spin_unlock(&context->context_lock);
3425
3426 status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303427 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003428 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 goto fail;
3430 }
3431
3432 /* request was sent -- wait for the response */
3433 rc = wait_for_completion_timeout(&context->response_event,
3434 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3435
3436 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003437 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 retval = -ETIMEDOUT;
3439 } else {
3440 spin_lock(&context->context_lock);
3441 if (context->request_id == request_id)
3442 retval = context->response_status;
3443 else
3444 retval = -EINVAL;
3445 spin_unlock(&context->context_lock);
3446 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303447 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003448 return retval;
3449
3450fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303451 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003452 return -EINVAL;
3453}
3454/*
3455 * done with short names for the global vendor params
3456 * used by wlan_hdd_cfg80211_extscan_stop()
3457 */
3458#undef PARAM_MAX
3459#undef PARAM_REQUEST_ID
3460
3461
3462/**
3463 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3464 * @wiphy: Pointer to wireless phy.
3465 * @wdev: Pointer to wireless device.
3466 * @data: Pointer to input data.
3467 * @data_len: Length of @data.
3468 *
3469 * Return: 0 on success, negative errno on failure
3470 */
3471int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3472 struct wireless_dev *wdev,
3473 const void *data, int data_len)
3474{
3475 int ret = 0;
3476
3477 cds_ssr_protect(__func__);
3478 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3479 cds_ssr_unprotect(__func__);
3480
3481 return ret;
3482}
3483
3484
3485/**
3486 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3487 * @wiphy: Pointer to wireless phy
3488 * @wdev: Pointer to wireless device
3489 * @data: Pointer to data
3490 * @data_len: Data length
3491 *
3492 * Return: none
3493 */
3494static int
3495__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3496 struct wireless_dev
3497 *wdev, const void *data,
3498 int data_len)
3499{
3500 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3501 struct net_device *dev = wdev->netdev;
3502 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3503 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3504 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3505 1];
3506 struct hdd_ext_scan_context *context;
3507 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303508 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003509 int retval;
3510 unsigned long rc;
3511
Jeff Johnson1f61b612016-02-12 16:28:33 -08003512 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513
Anurag Chouhan6d760662016-02-20 16:05:43 +05303514 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003515 hdd_err("Command not allowed in FTM mode");
3516 return -EPERM;
3517 }
3518
3519 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303520 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003521 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522
3523 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3524 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003525 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526 return -EINVAL;
3527 }
3528
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303529 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003530 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003531 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003532 return -ENOMEM;
3533 }
3534
3535 /* Parse and fetch request Id */
3536 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003537 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003538 goto fail;
3539 }
3540
3541 pReqMsg->requestId =
3542 nla_get_u32(tb
3543 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3544 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003545 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003546 pReqMsg->requestId, pReqMsg->sessionId);
3547
3548 context = &ext_scan_context;
3549 spin_lock(&context->context_lock);
3550 INIT_COMPLETION(context->response_event);
3551 context->request_id = request_id = pReqMsg->requestId;
3552 spin_unlock(&context->context_lock);
3553
3554 status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303555 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003556 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557 goto fail;
3558 }
3559
3560 /* request was sent -- wait for the response */
3561 rc = wait_for_completion_timeout
3562 (&context->response_event,
3563 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3564 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003565 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003566 retval = -ETIMEDOUT;
3567 } else {
3568 spin_lock(&context->context_lock);
3569 if (context->request_id == request_id)
3570 retval = context->response_status;
3571 else
3572 retval = -EINVAL;
3573 spin_unlock(&context->context_lock);
3574 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303575 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 return retval;
3577
3578fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303579 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003580 return -EINVAL;
3581}
3582
3583/**
3584 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3585 * @wiphy: Pointer to wireless phy
3586 * @wdev: Pointer to wireless device
3587 * @data: Pointer to data
3588 * @data_len: Data length
3589 *
3590 * Return: 0 on success, negative errno on failure
3591 */
3592int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3593 struct wireless_dev *wdev,
3594 const void *data, int data_len)
3595{
3596 int ret = 0;
3597
3598 cds_ssr_protect(__func__);
3599 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3600 data, data_len);
3601 cds_ssr_unprotect(__func__);
3602
3603 return ret;
3604}
3605
3606/**
3607 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3608 * reset significant change
3609 * @wiphy: Pointer to wireless phy
3610 * @wdev: Pointer to wireless device
3611 * @data: Pointer to data
3612 * @data_len: Data length
3613 *
3614 * Return: none
3615 */
3616static int
3617__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3618 *wiphy,
3619 struct
3620 wireless_dev
3621 *wdev, const void *data,
3622 int data_len)
3623{
3624 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3625 struct net_device *dev = wdev->netdev;
3626 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3627 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
3628 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3629 1];
3630 struct hdd_ext_scan_context *context;
3631 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303632 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003633 int retval;
3634 unsigned long rc;
3635
Jeff Johnson1f61b612016-02-12 16:28:33 -08003636 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637
Anurag Chouhan6d760662016-02-20 16:05:43 +05303638 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003639 hdd_err("Command not allowed in FTM mode");
3640 return -EPERM;
3641 }
3642
3643 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303644 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003645 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003646
3647 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3648 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003649 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 return -EINVAL;
3651 }
3652
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303653 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003655 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003656 return -ENOMEM;
3657 }
3658
3659 /* Parse and fetch request Id */
3660 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003661 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 goto fail;
3663 }
3664
3665 pReqMsg->requestId =
3666 nla_get_u32(tb
3667 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3668 pReqMsg->sessionId = pAdapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003669 hdd_notice("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670 pReqMsg->requestId, pReqMsg->sessionId);
3671
3672 context = &ext_scan_context;
3673 spin_lock(&context->context_lock);
3674 INIT_COMPLETION(context->response_event);
3675 context->request_id = request_id = pReqMsg->requestId;
3676 spin_unlock(&context->context_lock);
3677
3678 status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303679 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003680 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303682 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003683 return -EINVAL;
3684 }
3685
3686 /* request was sent -- wait for the response */
3687 rc = wait_for_completion_timeout(&context->response_event,
3688 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3689
3690 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003691 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003692 retval = -ETIMEDOUT;
3693 } else {
3694 spin_lock(&context->context_lock);
3695 if (context->request_id == request_id)
3696 retval = context->response_status;
3697 else
3698 retval = -EINVAL;
3699 spin_unlock(&context->context_lock);
3700 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303701 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003702 return retval;
3703
3704fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303705 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003706 return -EINVAL;
3707}
3708
3709/**
3710 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3711 * change
3712 * @wiphy: Pointer to wireless phy
3713 * @wdev: Pointer to wireless device
3714 * @data: Pointer to data
3715 * @data_len: Data length
3716 *
3717 * Return: 0 on success, negative errno on failure
3718 */
3719int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3720 struct wireless_dev *wdev,
3721 const void *data, int data_len)
3722{
3723 int ret = 0;
3724
3725 cds_ssr_protect(__func__);
3726 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3727 data, data_len);
3728 cds_ssr_unprotect(__func__);
3729
3730 return ret;
3731}
3732
3733
3734/**
3735 * hdd_extscan_epno_fill_network_list() - epno fill network list
3736 * @hddctx: HDD context
3737 * @req_msg: request message
3738 * @tb: vendor attribute table
3739 *
3740 * This function reads the network block NL vendor attributes from %tb and
3741 * fill in the epno request message.
3742 *
3743 * Return: 0 on success, error number otherwise
3744 */
3745static int hdd_extscan_epno_fill_network_list(
3746 hdd_context_t *hddctx,
3747 struct wifi_epno_params *req_msg,
3748 struct nlattr **tb)
3749{
3750 struct nlattr *network[
3751 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
3752 struct nlattr *networks;
3753 int rem1, ssid_len;
3754 uint8_t index, *ssid;
3755
3756 index = 0;
3757 nla_for_each_nested(networks,
3758 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3759 rem1) {
3760 if (nla_parse(network,
3761 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3762 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003763 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003764 return -EINVAL;
3765 }
3766
3767 /* Parse and fetch ssid */
3768 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003769 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003770 return -EINVAL;
3771 }
3772 ssid_len = nla_len(
3773 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3774
3775 /* Decrement by 1, don't count null character */
3776 ssid_len--;
3777
3778 req_msg->networks[index].ssid.length = ssid_len;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003779 hdd_notice("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303781 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 ssid, ssid_len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003783 hdd_notice("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003784 req_msg->networks[index].ssid.length,
3785 req_msg->networks[index].ssid.ssId);
3786
3787 /* Parse and fetch rssi threshold */
3788 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003789 hdd_err("attr rssi threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003790 return -EINVAL;
3791 }
3792 req_msg->networks[index].rssi_threshold = nla_get_s8(
3793 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003794 hdd_notice("rssi threshold %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003795 req_msg->networks[index].rssi_threshold);
3796
3797 /* Parse and fetch epno flags */
3798 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003799 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003800 return -EINVAL;
3801 }
3802 req_msg->networks[index].flags = nla_get_u8(
3803 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003804 hdd_notice("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003805
3806 /* Parse and fetch auth bit */
3807 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003808 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003809 return -EINVAL;
3810 }
3811 req_msg->networks[index].auth_bit_field = nla_get_u8(
3812 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003813 hdd_notice("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814 req_msg->networks[index].auth_bit_field);
3815
3816 index++;
3817 }
3818 return 0;
3819}
3820
3821/**
3822 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3823 * @wiphy: wiphy
3824 * @wdev: pointer to wireless dev
3825 * @data: data pointer
3826 * @data_len: data length
3827 *
3828 * This function reads the NL vendor attributes from %tb and
3829 * fill in the epno request message.
3830 *
3831 * Return: 0 on success, error number otherwise
3832 */
3833static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3834 struct wireless_dev *wdev,
3835 const void *data,
3836 int data_len)
3837{
3838 struct wifi_epno_params *req_msg = NULL;
3839 struct net_device *dev = wdev->netdev;
3840 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3841 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3842 struct nlattr *tb[
3843 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303844 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 uint32_t num_networks, len;
3846 int ret_val;
3847
Jeff Johnson1f61b612016-02-12 16:28:33 -08003848 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849
3850 ret_val = wlan_hdd_validate_context(hdd_ctx);
3851 if (ret_val)
3852 return ret_val;
3853
Anurag Chouhan6d760662016-02-20 16:05:43 +05303854 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003855 hdd_err("Command not allowed in FTM mode");
3856 return -EPERM;
3857 }
3858
3859 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3860 data, data_len,
3861 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003862 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003863 return -EINVAL;
3864 }
3865
3866 /* Parse and fetch number of networks */
3867 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003868 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869 return -EINVAL;
3870 }
3871 num_networks = nla_get_u32(
3872 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003873 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874
3875 len = sizeof(*req_msg) +
3876 (num_networks * sizeof(struct wifi_epno_network));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303877 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003879 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003880 return -ENOMEM;
3881 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303882 qdf_mem_zero(req_msg, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883 req_msg->num_networks = num_networks;
3884
3885 /* Parse and fetch request Id */
3886 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003887 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003888 goto fail;
3889 }
3890 req_msg->request_id = nla_get_u32(
3891 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003892 hdd_notice("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893
3894 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07003895 hdd_notice("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896
3897 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
3898 goto fail;
3899
3900 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303901 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003902 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003903 goto fail;
3904 }
3905
3906 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303907 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908 return 0;
3909
3910fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303911 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003912 return -EINVAL;
3913}
3914
3915 /**
3916 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
3917 * @wiphy: wiphy
3918 * @wdev: pointer to wireless dev
3919 * @data: data pointer
3920 * @data_len: data length
3921 *
3922 * This function reads the NL vendor attributes from %tb and
3923 * fill in the epno request message.
3924 *
3925 * Return: 0 on success, error number otherwise
3926 */
3927int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3928 struct wireless_dev *wdev,
3929 const void *data,
3930 int data_len)
3931{
3932 int ret;
3933
3934 cds_ssr_protect(__func__);
3935 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
3936 data, data_len);
3937 cds_ssr_unprotect(__func__);
3938
3939 return ret;
3940}
3941
3942/**
3943 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
3944 * @hddctx: HDD context
3945 * @req_msg: request message
3946 * @tb: vendor attribute table
3947 *
3948 * This function reads the network block NL vendor attributes from %tb and
3949 * fill in the passpoint request message.
3950 *
3951 * Return: 0 on success, error number otherwise
3952 */
3953static int hdd_extscan_passpoint_fill_network_list(
3954 hdd_context_t *hddctx,
3955 struct wifi_passpoint_req *req_msg,
3956 struct nlattr **tb)
3957{
3958 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
3959 struct nlattr *networks;
3960 int rem1, len;
3961 uint8_t index;
3962
3963 index = 0;
3964 nla_for_each_nested(networks,
3965 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
3966 rem1) {
3967 if (nla_parse(network,
3968 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3969 nla_data(networks), nla_len(networks), NULL)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003970 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003971 return -EINVAL;
3972 }
3973
3974 /* Parse and fetch identifier */
3975 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003976 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003977 return -EINVAL;
3978 }
3979 req_msg->networks[index].id = nla_get_u32(
3980 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003981 hdd_notice("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003982
3983 /* Parse and fetch realm */
3984 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003985 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003986 return -EINVAL;
3987 }
3988 len = nla_len(
3989 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
3990 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003991 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 return -EINVAL;
3993 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303994 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003995 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
3996 len);
Jeff Johnson630f9e72016-07-25 12:00:12 -07003997 hdd_notice("realm len %d", len);
3998 hdd_notice("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999
4000 /* Parse and fetch roaming consortium ids */
4001 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004002 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003 return -EINVAL;
4004 }
4005 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
4006 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
4007 sizeof(req_msg->networks[0].roaming_consortium_ids));
Jeff Johnson630f9e72016-07-25 12:00:12 -07004008 hdd_notice("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009
4010 /* Parse and fetch plmn */
4011 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004012 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013 return -EINVAL;
4014 }
4015 nla_memcpy(&req_msg->networks[index].plmn,
4016 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
4017 SIR_PASSPOINT_PLMN_LEN);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004018 hdd_notice("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004019 req_msg->networks[index].plmn[0],
4020 req_msg->networks[index].plmn[1],
4021 req_msg->networks[index].plmn[2]);
4022
4023 index++;
4024 }
4025 return 0;
4026}
4027
4028/**
4029 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4030 * @wiphy: wiphy
4031 * @wdev: pointer to wireless dev
4032 * @data: data pointer
4033 * @data_len: data length
4034 *
4035 * This function reads the 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 __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4041 struct wireless_dev *wdev,
4042 const void *data,
4043 int data_len)
4044{
4045 struct wifi_passpoint_req *req_msg = NULL;
4046 struct net_device *dev = wdev->netdev;
4047 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4048 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4049 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304050 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051 uint32_t num_networks = 0;
4052 int ret;
4053
Jeff Johnson1f61b612016-02-12 16:28:33 -08004054 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055
4056 ret = wlan_hdd_validate_context(hdd_ctx);
4057 if (ret)
4058 return ret;
4059
Anurag Chouhan6d760662016-02-20 16:05:43 +05304060 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 hdd_err("Command not allowed in FTM mode");
4062 return -EPERM;
4063 }
4064
4065 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4066 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004067 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004068 return -EINVAL;
4069 }
4070
4071 /* Parse and fetch number of networks */
4072 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004073 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004074 return -EINVAL;
4075 }
4076 num_networks = nla_get_u32(
4077 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004078 hdd_notice("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304080 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 (num_networks * sizeof(req_msg->networks[0])));
4082 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004083 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 return -ENOMEM;
4085 }
4086 req_msg->num_networks = num_networks;
4087
4088 /* Parse and fetch request Id */
4089 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004090 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 goto fail;
4092 }
4093 req_msg->request_id = nla_get_u32(
4094 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4095
4096 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004097 hdd_notice("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098 req_msg->session_id);
4099
4100 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4101 goto fail;
4102
4103 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304104 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004105 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004106 goto fail;
4107 }
4108
4109 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304110 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004111 return 0;
4112
4113fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304114 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 return -EINVAL;
4116}
4117
4118/**
4119 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4120 * @wiphy: wiphy
4121 * @wdev: pointer to wireless dev
4122 * @data: data pointer
4123 * @data_len: data length
4124 *
4125 * This function reads the NL vendor attributes from %tb and
4126 * fill in the passpoint request message.
4127 *
4128 * Return: 0 on success, error number otherwise
4129 */
4130int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4131 struct wireless_dev *wdev,
4132 const void *data,
4133 int data_len)
4134{
4135 int ret;
4136
4137 cds_ssr_protect(__func__);
4138 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4139 data, data_len);
4140 cds_ssr_unprotect(__func__);
4141
4142 return ret;
4143}
4144
4145/**
4146 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4147 * @wiphy: wiphy
4148 * @wdev: pointer to wireless dev
4149 * @data: data pointer
4150 * @data_len: data length
4151 *
4152 * This function resets passpoint networks list
4153 *
4154 * Return: 0 on success, error number otherwise
4155 */
4156static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4157 struct wireless_dev *wdev,
4158 const void *data,
4159 int data_len)
4160{
4161 struct wifi_passpoint_req *req_msg = NULL;
4162 struct net_device *dev = wdev->netdev;
4163 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4164 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4165 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304166 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004167 int ret;
4168
Jeff Johnson1f61b612016-02-12 16:28:33 -08004169 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170
4171 ret = wlan_hdd_validate_context(hdd_ctx);
4172 if (ret)
4173 return ret;
4174
Anurag Chouhan6d760662016-02-20 16:05:43 +05304175 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176 hdd_err("Command not allowed in FTM mode");
4177 return -EPERM;
4178 }
4179
4180 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4181 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004182 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004183 return -EINVAL;
4184 }
4185
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304186 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004188 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189 return -ENOMEM;
4190 }
4191
4192 /* Parse and fetch request Id */
4193 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004194 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004195 goto fail;
4196 }
4197 req_msg->request_id = nla_get_u32(
4198 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4199
4200 req_msg->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004201 hdd_notice("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 req_msg->request_id, req_msg->session_id);
4203
4204 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304205 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004206 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 goto fail;
4208 }
4209
4210 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304211 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004212 return 0;
4213
4214fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304215 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004216 return -EINVAL;
4217}
4218
4219/**
4220 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4221 * @wiphy: wiphy
4222 * @wdev: pointer to wireless dev
4223 * @data: data pointer
4224 * @data_len: data length
4225 *
4226 * This function resets passpoint networks list
4227 *
4228 * Return: 0 on success, error number otherwise
4229 */
4230int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4231 struct wireless_dev *wdev,
4232 const void *data,
4233 int data_len)
4234{
4235 int ret;
4236
4237 cds_ssr_protect(__func__);
4238 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4239 data, data_len);
4240 cds_ssr_unprotect(__func__);
4241
4242 return ret;
4243}
4244
4245/*
4246 * define short names for the global vendor params
4247 * used by __wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4248 */
4249#define PARAM_MAX \
4250 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4251#define PARAM_REQUEST_ID \
4252 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4253#define PARAMS_LOST_SSID_SAMPLE_SIZE \
4254 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE
4255#define PARAMS_NUM_SSID \
4256 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID
4257#define THRESHOLD_PARAM \
4258 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM
4259#define PARAM_SSID \
4260 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID
4261#define PARAM_BAND \
4262 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND
4263#define PARAM_RSSI_LOW \
4264 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW
4265#define PARAM_RSSI_HIGH \
4266 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH
4267
4268/**
4269 * __wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4270 * @wiphy: Pointer to wireless phy
4271 * @wdev: Pointer to wireless device
4272 * @data: Pointer to data
4273 * @data_len: Data length
4274 *
4275 * Return: 0 on success, negative errno on failure
4276 */
4277static int
4278__wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4279 struct wireless_dev *wdev,
4280 const void *data,
4281 int data_len)
4282{
4283 struct sir_set_ssid_hotlist_request *request;
4284 struct net_device *dev = wdev->netdev;
4285 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4286 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4287 struct nlattr *tb[PARAM_MAX + 1];
4288 struct nlattr *tb2[PARAM_MAX + 1];
4289 struct nlattr *ssids;
4290 struct hdd_ext_scan_context *context;
4291 uint32_t request_id;
4292 char ssid_string[SIR_MAC_MAX_SSID_LENGTH + 1];
4293 int ssid_len, i, rem;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304294 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004295 int retval;
4296 unsigned long rc;
4297
Jeff Johnson1f61b612016-02-12 16:28:33 -08004298 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004299
Anurag Chouhan6d760662016-02-20 16:05:43 +05304300 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301 hdd_err("Command not allowed in FTM mode");
4302 return -EPERM;
4303 }
4304
4305 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304306 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004307 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308
4309 if (nla_parse(tb, PARAM_MAX,
4310 data, data_len,
4311 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004312 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313 return -EINVAL;
4314 }
4315
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304316 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004317 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004318 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004319 return -ENOMEM;
4320 }
4321
4322 /* Parse and fetch request Id */
4323 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004324 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 goto fail;
4326 }
4327
4328 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004329 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004330
4331 /* Parse and fetch lost SSID sample size */
4332 if (!tb[PARAMS_LOST_SSID_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004333 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004334 goto fail;
4335 }
4336 request->lost_ssid_sample_size =
4337 nla_get_u32(tb[PARAMS_LOST_SSID_SAMPLE_SIZE]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004338 hdd_notice("Lost SSID Sample Size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004339 request->lost_ssid_sample_size);
4340
4341 /* Parse and fetch number of hotlist SSID */
4342 if (!tb[PARAMS_NUM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004343 hdd_err("attr number of Ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344 goto fail;
4345 }
4346 request->ssid_count = nla_get_u32(tb[PARAMS_NUM_SSID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004347 hdd_notice("Number of SSID %d", request->ssid_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348
4349 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004350 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351
4352 i = 0;
4353 nla_for_each_nested(ssids, tb[THRESHOLD_PARAM], rem) {
4354 if (i >= WLAN_EXTSCAN_MAX_HOTLIST_SSIDS) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004355 hdd_err("Too Many SSIDs, %d exceeds %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356 i, WLAN_EXTSCAN_MAX_HOTLIST_SSIDS);
4357 break;
4358 }
4359 if (nla_parse(tb2, PARAM_MAX,
4360 nla_data(ssids), nla_len(ssids),
4361 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004362 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363 goto fail;
4364 }
4365
4366 /* Parse and fetch SSID */
4367 if (!tb2[PARAM_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004368 hdd_err("attr ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 goto fail;
4370 }
4371 nla_memcpy(ssid_string,
4372 tb2[PARAM_SSID],
4373 sizeof(ssid_string));
Jeff Johnson630f9e72016-07-25 12:00:12 -07004374 hdd_notice("SSID %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 ssid_string);
4376 ssid_len = strlen(ssid_string);
4377 memcpy(request->ssids[i].ssid.ssId, ssid_string, ssid_len);
4378 request->ssids[i].ssid.length = ssid_len;
4379
4380 /* Parse and fetch low RSSI */
4381 if (!tb2[PARAM_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004382 hdd_err("attr band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 goto fail;
4384 }
4385 request->ssids[i].band = nla_get_u8(tb2[PARAM_BAND]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004386 hdd_notice("band %d", request->ssids[i].band);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004387
4388 /* Parse and fetch low RSSI */
4389 if (!tb2[PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004390 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 goto fail;
4392 }
4393 request->ssids[i].rssi_low = nla_get_s32(tb2[PARAM_RSSI_LOW]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004394 hdd_notice("RSSI low %d", request->ssids[i].rssi_low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395
4396 /* Parse and fetch high RSSI */
4397 if (!tb2[PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004398 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004399 goto fail;
4400 }
4401 request->ssids[i].rssi_high = nla_get_u32(tb2[PARAM_RSSI_HIGH]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004402 hdd_notice("RSSI high %d", request->ssids[i].rssi_high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004403 i++;
4404 }
4405
4406 context = &ext_scan_context;
4407 spin_lock(&context->context_lock);
4408 INIT_COMPLETION(context->response_event);
4409 context->request_id = request_id = request->request_id;
4410 spin_unlock(&context->context_lock);
4411
4412 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304413 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004414 hdd_err("sme_set_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 goto fail;
4416 }
4417
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304418 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419
4420 /* request was sent -- wait for the response */
4421 rc = wait_for_completion_timeout(&context->response_event,
4422 msecs_to_jiffies
4423 (WLAN_WAIT_TIME_EXTSCAN));
4424 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004425 hdd_err("sme_set_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 retval = -ETIMEDOUT;
4427 } else {
4428 spin_lock(&context->context_lock);
4429 if (context->request_id == request_id)
4430 retval = context->response_status;
4431 else
4432 retval = -EINVAL;
4433 spin_unlock(&context->context_lock);
4434 }
4435
4436 return retval;
4437
4438fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304439 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004440 return -EINVAL;
4441}
4442
4443/*
4444 * done with short names for the global vendor params
4445 * used by wlan_hdd_cfg80211_extscan_set_ssid_hotlist()
4446 */
4447#undef PARAM_MAX
4448#undef PARAM_REQUEST_ID
4449#undef PARAMS_NUM_SSID
4450#undef THRESHOLD_PARAM
4451#undef PARAM_SSID
4452#undef PARAM_BAND
4453#undef PARAM_RSSI_LOW
4454#undef PARAM_RSSI_HIGH
4455
4456/**
4457 * wlan_hdd_cfg80211_extscan_set_ssid_hotlist() - set ssid hot list
4458 * @wiphy: Pointer to wireless phy
4459 * @wdev: Pointer to wireless device
4460 * @data: Pointer to data
4461 * @data_len: Data length
4462 *
4463 * Return: 0 on success, negative errno on failure
4464 */
4465int
4466wlan_hdd_cfg80211_extscan_set_ssid_hotlist(struct wiphy *wiphy,
4467 struct wireless_dev *wdev,
4468 const void *data,
4469 int data_len)
4470{
4471 int ret;
4472
4473 cds_ssr_protect(__func__);
4474 ret = __wlan_hdd_cfg80211_extscan_set_ssid_hotlist(wiphy, wdev, data,
4475 data_len);
4476 cds_ssr_unprotect(__func__);
4477
4478 return ret;
4479}
4480
4481/*
4482 * define short names for the global vendor params
4483 * used by __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4484 */
4485#define PARAM_MAX \
4486 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
4487#define PARAM_REQUEST_ID \
4488 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
4489
4490/**
4491 * __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4492 * @wiphy: Pointer to wireless phy
4493 * @wdev: Pointer to wireless device
4494 * @data: Pointer to data
4495 * @data_len: Data length
4496 *
4497 * Return: 0 on success, negative errno on failure
4498 */
4499static int
4500__wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4501 struct wireless_dev *wdev,
4502 const void *data,
4503 int data_len)
4504{
4505 struct sir_set_ssid_hotlist_request *request;
4506 struct net_device *dev = wdev->netdev;
4507 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4508 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4509 struct nlattr *tb[PARAM_MAX + 1];
4510 struct hdd_ext_scan_context *context;
4511 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304512 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004513 int retval;
4514 unsigned long rc;
4515
Jeff Johnson1f61b612016-02-12 16:28:33 -08004516 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004517
Anurag Chouhan6d760662016-02-20 16:05:43 +05304518 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004519 hdd_err("Command not allowed in FTM mode");
4520 return -EPERM;
4521 }
4522
4523 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304524 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004525 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004526
4527 if (nla_parse(tb, PARAM_MAX,
4528 data, data_len,
4529 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004530 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004531 return -EINVAL;
4532 }
4533
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304534 request = qdf_mem_malloc(sizeof(*request));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004535 if (!request) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004536 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004537 return -ENOMEM;
4538 }
4539
4540 /* Parse and fetch request Id */
4541 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004542 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004543 goto fail;
4544 }
4545
4546 request->request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson630f9e72016-07-25 12:00:12 -07004547 hdd_notice("Request Id %d", request->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004548
4549 request->session_id = adapter->sessionId;
Jeff Johnson630f9e72016-07-25 12:00:12 -07004550 hdd_notice("Session Id %d", request->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551
4552 request->lost_ssid_sample_size = 0;
4553 request->ssid_count = 0;
4554
4555 context = &ext_scan_context;
4556 spin_lock(&context->context_lock);
4557 INIT_COMPLETION(context->response_event);
4558 context->request_id = request_id = request->request_id;
4559 spin_unlock(&context->context_lock);
4560
4561 status = sme_set_ssid_hotlist(hdd_ctx->hHal, request);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304562 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004563 hdd_err("sme_reset_ssid_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564 goto fail;
4565 }
4566
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304567 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568
4569 /* request was sent -- wait for the response */
4570 rc = wait_for_completion_timeout(&context->response_event,
4571 msecs_to_jiffies
4572 (WLAN_WAIT_TIME_EXTSCAN));
4573 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004574 hdd_err("sme_reset_ssid_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 retval = -ETIMEDOUT;
4576 } else {
4577 spin_lock(&context->context_lock);
4578 if (context->request_id == request_id)
4579 retval = context->response_status;
4580 else
4581 retval = -EINVAL;
4582 spin_unlock(&context->context_lock);
4583 }
4584
4585 return retval;
4586
4587fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304588 qdf_mem_free(request);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 return -EINVAL;
4590}
4591
4592/*
4593 * done with short names for the global vendor params
4594 * used by wlan_hdd_cfg80211_extscan_reset_ssid_hotlist()
4595 */
4596#undef PARAM_MAX
4597#undef PARAM_REQUEST_ID
4598
4599/**
4600 * wlan_hdd_cfg80211_extscan_reset_ssid_hotlist() - reset ssid hot list
4601 * @wiphy: Pointer to wireless phy
4602 * @wdev: Pointer to wireless device
4603 * @data: Pointer to data
4604 * @data_len: Data length
4605 *
4606 * Return: 0 on success, negative errno on failure
4607 */
4608int
4609wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(struct wiphy *wiphy,
4610 struct wireless_dev *wdev,
4611 const void *data,
4612 int data_len)
4613{
4614 int ret;
4615
4616 cds_ssr_protect(__func__);
4617 ret = __wlan_hdd_cfg80211_extscan_reset_ssid_hotlist(wiphy, wdev,
4618 data, data_len);
4619 cds_ssr_unprotect(__func__);
4620
4621 return ret;
4622}
4623
4624/**
4625 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4626 * @hdd_ctx: Global HDD context
4627 *
4628 * Return: none
4629 */
4630#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
4631static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4632{
4633 init_completion(&pHddCtx->ready_to_extwow);
4634}
4635#else
4636static inline void wlan_hdd_init_completion_extwow(hdd_context_t *pHddCtx)
4637{
4638 return;
4639}
4640#endif
4641
4642/**
4643 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4644 * @hdd_ctx: Global HDD context
4645 *
4646 * Return: none
4647 */
4648void wlan_hdd_cfg80211_extscan_init(hdd_context_t *hdd_ctx)
4649{
4650 wlan_hdd_init_completion_extwow(hdd_ctx);
4651 init_completion(&ext_scan_context.response_event);
4652 spin_lock_init(&ext_scan_context.context_lock);
4653}
4654
4655#endif /* FEATURE_WLAN_EXTSCAN */