blob: 0da507555e52b559d7a9dd3307810acebca493a3 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Dustin Brown4ea21db2018-01-05 14:13:17 -08002 * Copyright (c) 2012-2018 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
31#include "wlan_hdd_ext_scan.h"
Amar Singhalea10a872016-08-23 15:31:45 -070032#include "wlan_hdd_regulatory.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033#include "cds_utils.h"
34#include "cds_sched.h"
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080035#include <qca_vendor.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036
37/* amount of time to wait for a synchronous request/response operation */
38#define WLAN_WAIT_TIME_EXTSCAN 1000
39
40/**
41 * struct hdd_ext_scan_context - hdd ext scan context
42 * @request_id: userspace-assigned ID associated with the request
43 * @response_event: Ext scan wait event
44 * @response_status: Status returned by FW in response to a request
45 * @ignore_cached_results: Flag to ignore cached results or not
46 * @context_lock: Spinlock to serialize all context accesses
47 * @capability_response: Ext scan capability response data from target
Mukul Sharmafa937be2016-08-12 18:13:36 +053048 * @buckets_scanned: bitmask of buckets scanned in extscan cycle
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080049 */
50struct hdd_ext_scan_context {
51 uint32_t request_id;
52 int response_status;
53 bool ignore_cached_results;
54 struct completion response_event;
55 spinlock_t context_lock;
56 struct ext_scan_capabilities_response capability_response;
Mukul Sharmafa937be2016-08-12 18:13:36 +053057 uint32_t buckets_scanned;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080058};
59static struct hdd_ext_scan_context ext_scan_context;
60
61static const struct nla_policy wlan_hdd_extscan_config_policy
62[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1] = {
63 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID] = {
64 .type = NLA_U32},
65 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND] = {
66 .type = NLA_U32},
SaidiReddy Yenuga88680b02017-05-26 18:26:09 +053067 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS] = {
68 .type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080069 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL] = {.type = NLA_U32},
70 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME] = {
71 .type = NLA_U32},
72 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE] = {.type = NLA_U8},
73 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CLASS] = {.type = NLA_U8},
74
75 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX] = {.type = NLA_U8},
76 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND] = {.type = NLA_U8},
77 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD] = {.type = NLA_U32},
78 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS] = {
79 .type = NLA_U8},
80 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS] = {
81 .type = NLA_U32},
82 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD] = {
83 .type = NLA_U32},
84 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN] = {
85 .type = NLA_U32},
86 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT] = {
87 .type = NLA_U8},
88 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS] = {
89 .type = NLA_U8 },
90 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS] = {
91 .type = NLA_U8},
92 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH] = {
93 .type = NLA_U8},
94
95 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] = {
96 .type = NLA_U32},
97 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = {
Jeff Johnson19a5a7e2017-06-15 14:51:26 -070098 .type = NLA_UNSPEC,
99 .len = QDF_MAC_ADDR_SIZE},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] = {
101 .type = NLA_S32},
102 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] = {
103 .type = NLA_S32},
104 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_CHANNEL] = {
105 .type = NLA_U32},
106 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP] = {
107 .type = NLA_U32},
108 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE] = {
109 .type = NLA_U32},
110 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE] = {
111 .type = NLA_U32},
112 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING] = {
113 .type = NLA_U32},
114 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP] = {
115 .type = NLA_U32},
Jeff Johnson20b5dc32017-06-01 11:03:19 -0700116 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD] = {
117 .type = NLA_U32},
118 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE] = {
119 .type = NLA_U32},
120 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT] = {
121 .type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800122 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_SSID] = {
123 .type = NLA_BINARY,
124 .len = IEEE80211_MAX_SSID_LEN + 1 },
125 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE] = {
126 .type = NLA_U32 },
127 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_HOTLIST_PARAMS_NUM_SSID] = {
128 .type = NLA_U32 },
129 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_BAND] = {
130 .type = NLA_U8 },
131 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW] = {
132 .type = NLA_S32 },
133 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH] = {
134 .type = NLA_S32 },
135 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS] = {
136 .type = NLA_U32 },
SaidiReddy Yenugadec1bfc2017-06-05 16:11:56 +0530137 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE] = {
138 .type = NLA_U32},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139};
140
141static const struct nla_policy
Jeff Johnsonfa484bb2016-11-09 09:01:10 -0800142wlan_hdd_pno_config_policy[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1] = {
Jeff Johnsona6e61b12017-06-02 15:44:36 -0700143 [QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM] = {
144 .type = NLA_U32
145 },
146 [QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID] = {
147 .type = NLA_U32
148 },
Jeff Johnsonfa484bb2016-11-09 09:01:10 -0800149 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS] = {
150 .type = NLA_U32
151 },
152 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID] = {
153 .type = NLA_BINARY,
154 .len = IEEE80211_MAX_SSID_LEN + 1
155 },
156 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS] = {
157 .type = NLA_U8
158 },
159 [QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT] = {
160 .type = NLA_U8
161 },
Jeff Johnsona6e61b12017-06-02 15:44:36 -0700162 [QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI] = {
163 .type = NLA_U32
164 },
165 [QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI] = {
166 .type = NLA_U32
167 },
168 [QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX] = {
169 .type = NLA_U32
170 },
171 [QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS] = {
172 .type = NLA_U32
173 },
174 [QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS] = {
175 .type = NLA_U32
176 },
177 [QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS] = {
178 .type = NLA_U32
179 },
180 [QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS] = {
181 .type = NLA_U32
182 },
Ashish Kumar Dhanotiya1f6df4d2017-08-21 14:07:23 +0530183 [QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID] = {
184 .type = NLA_U32
185 },
Jeff Johnsonfa484bb2016-11-09 09:01:10 -0800186};
187
188static const struct nla_policy
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
190 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
191 .type = NLA_U16},
192 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = {
193 .type = NLA_U16},
194};
195
196/**
197 * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
198 * @ctx: Pointer to hdd context
199 * @data: Pointer to ext scan capabilities response from fw
200 *
201 * Return: None
202 */
203static void
204wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx,
205 struct ext_scan_capabilities_response *data)
206{
207 struct hdd_ext_scan_context *context;
Jeff Johnson9755a512017-08-28 12:01:57 -0700208 struct hdd_context *hdd_ctx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209
Dustin Brown491d54b2018-03-14 12:39:11 -0700210 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800211
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530212 if (wlan_hdd_validate_context(hdd_ctx))
213 return;
214 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700215 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 return;
217 }
218
219 context = &ext_scan_context;
220
221 spin_lock(&context->context_lock);
222 /* validate response received from target*/
223 if (context->request_id != data->requestId) {
224 spin_unlock(&context->context_lock);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800225 hdd_err("Target response id did not match. request_id: %d response_id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800226 context->request_id, data->requestId);
227 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 }
229
Jeff Johnson68755312017-02-10 11:46:55 -0800230 context->capability_response = *data;
231 complete(&context->response_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 spin_unlock(&context->context_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233}
234
235/*
236 * define short names for the global vendor params
237 * used by hdd_extscan_nl_fill_bss()
238 */
239#define PARAM_TIME_STAMP \
240 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
241#define PARAM_SSID \
242 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID
243#define PARAM_BSSID \
244 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID
245#define PARAM_CHANNEL \
246 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL
247#define PARAM_RSSI \
248 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI
249#define PARAM_RTT \
250 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT
251#define PARAM_RTT_SD \
252 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD
253#define PARAM_BEACON_PERIOD \
254 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD
255#define PARAM_CAPABILITY \
256 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY
257#define PARAM_IE_LENGTH \
258 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
259#define PARAM_IE_DATA \
260 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA
261
262/** hdd_extscan_nl_fill_bss() - extscan nl fill bss
263 * @skb: socket buffer
264 * @ap: bss information
265 * @idx: nesting index
266 *
267 * Return: 0 on success; error number otherwise
268 */
269static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap,
270 int idx)
271{
272 struct nlattr *nla_ap;
273
274 nla_ap = nla_nest_start(skb, idx);
275 if (!nla_ap)
276 return -EINVAL;
277
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700278 if (hdd_wlan_nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) ||
280 nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid.bytes) ||
281 nla_put_u32(skb, PARAM_CHANNEL, ap->channel) ||
282 nla_put_s32(skb, PARAM_RSSI, ap->rssi) ||
283 nla_put_u32(skb, PARAM_RTT, ap->rtt) ||
284 nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) ||
285 nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) ||
286 nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) ||
287 nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700288 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289 return -EINVAL;
290 }
291
292 if (ap->ieLength)
293 if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700294 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 return -EINVAL;
296 }
297
298 nla_nest_end(skb, nla_ap);
299
300 return 0;
301}
302/*
303 * done with short names for the global vendor params
304 * used by hdd_extscan_nl_fill_bss()
305 */
306#undef PARAM_TIME_STAMP
307#undef PARAM_SSID
308#undef PARAM_BSSID
309#undef PARAM_CHANNEL
310#undef PARAM_RSSI
311#undef PARAM_RTT
312#undef PARAM_RTT_SD
313#undef PARAM_BEACON_PERIOD
314#undef PARAM_CAPABILITY
315#undef PARAM_IE_LENGTH
316#undef PARAM_IE_DATA
317
318/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results
319 * @ctx: hdd global context
320 * @data: cached results
321 *
322 * This function reads the cached results %data, populated the NL
323 * attributes and sends the NL event to the upper layer.
324 *
325 * Return: none
326 */
327static void
328wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
329 struct extscan_cached_scan_results *data)
330{
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700331 struct hdd_context *hdd_ctx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800332 struct sk_buff *skb = NULL;
333 struct hdd_ext_scan_context *context;
334 struct extscan_cached_scan_result *result;
335 tSirWifiScanResult *ap;
336 uint32_t i, j, nl_buf_len;
337 bool ignore_cached_results = false;
338
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700339 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700341 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530342 return;
343 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700344 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345 return;
346 }
347
348 context = &ext_scan_context;
349 spin_lock(&context->context_lock);
350 ignore_cached_results = context->ignore_cached_results;
351 spin_unlock(&context->context_lock);
352
353 if (ignore_cached_results) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700354 hdd_err("Ignore the cached results received after timeout");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800355 return;
356 }
357
358#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN
359#define EXTSCAN_CACHED_NL_FIXED_TLV \
360 ((sizeof(data->request_id) + NLA_HDRLEN) + \
361 (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \
362 (sizeof(data->more_data) + NLA_HDRLEN))
363#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \
364 ((sizeof(result->scan_id) + NLA_HDRLEN) + \
365 (sizeof(result->flags) + NLA_HDRLEN) + \
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530366 (sizeof(result->num_results) + NLA_HDRLEN))+ \
367 (sizeof(result->buckets_scanned) + NLA_HDRLEN)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
369 ((sizeof(ap->ts) + NLA_HDRLEN) + \
370 (sizeof(ap->ssid) + NLA_HDRLEN) + \
371 (sizeof(ap->bssid) + NLA_HDRLEN) + \
372 (sizeof(ap->channel) + NLA_HDRLEN) + \
373 (sizeof(ap->rssi) + NLA_HDRLEN) + \
374 (sizeof(ap->rtt) + NLA_HDRLEN) + \
375 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
376 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
377 (sizeof(ap->capability) + NLA_HDRLEN) + \
378 (sizeof(ap->ieLength) + NLA_HDRLEN))
379#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
380 (ap->ieLength + NLA_HDRLEN)
381
382 nl_buf_len = NLMSG_HDRLEN;
383 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
384 if (data->num_scan_ids) {
385 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
386 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
387 result = &data->result[0];
388 for (i = 0; i < data->num_scan_ids; i++) {
389 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
390 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
391 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
392
393 ap = &result->ap[0];
394 for (j = 0; j < result->num_results; j++) {
395 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
396 nl_buf_len +=
397 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
398 if (ap->ieLength)
399 nl_buf_len +=
400 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
401 ap++;
402 }
403 result++;
404 }
405 }
406
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700407 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408
409 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700410 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 goto fail;
412 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800413 hdd_debug("Req Id %u Num_scan_ids %u More Data %u",
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530414 data->request_id, data->num_scan_ids, data->more_data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415
416 result = &data->result[0];
417 for (i = 0; i < data->num_scan_ids; i++) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800418 hdd_debug("[i=%d] scan_id %u flags %u num_results %u buckets scanned %u",
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530419 i, result->scan_id, result->flags, result->num_results,
420 result->buckets_scanned);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421
422 ap = &result->ap[0];
423 for (j = 0; j < result->num_results; j++) {
424 /*
425 * Firmware returns timestamp from ext scan start till
426 * BSSID was cached (in micro seconds). Add this with
427 * time gap between system boot up to ext scan start
428 * to derive the time since boot when the
429 * BSSID was cached.
430 */
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700431 ap->ts += hdd_ctx->ext_scan_start_since_boot;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800432 hdd_debug("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 "Ssid: %s "
434 "Bssid (" MAC_ADDRESS_STR ") "
435 "Channel %u "
436 "Rssi %d "
437 "RTT %u "
438 "RTT_SD %u "
439 "Beacon Period %u "
440 "Capability 0x%x "
441 "Ie length %d",
442 ap->ts,
443 ap->ssid,
444 MAC_ADDR_ARRAY(ap->bssid.bytes),
445 ap->channel,
446 ap->rssi,
447 ap->rtt,
448 ap->rtt_sd,
449 ap->beaconPeriod,
450 ap->capability,
451 ap->ieLength);
452 ap++;
453 }
454 result++;
455 }
456
457 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
458 data->request_id) ||
459 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530460 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800461 data->num_scan_ids) ||
462 nla_put_u8(skb,
463 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
464 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700465 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466 goto fail;
467 }
468
469 if (data->num_scan_ids) {
470 struct nlattr *nla_results;
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -0700471
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800472 result = &data->result[0];
473
474 if (nla_put_u32(skb,
475 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
476 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700477 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800478 goto fail;
479 }
480 nla_results = nla_nest_start(skb,
481 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
482 if (!nla_results)
483 goto fail;
484
485 for (i = 0; i < data->num_scan_ids; i++) {
486 struct nlattr *nla_result;
487 struct nlattr *nla_aps;
488
489 nla_result = nla_nest_start(skb, i);
490 if (!nla_result)
491 goto fail;
492
493 if (nla_put_u32(skb,
494 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
495 result->scan_id) ||
496 nla_put_u32(skb,
497 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
498 result->flags) ||
499 nla_put_u32(skb,
Mukul Sharmafa937be2016-08-12 18:13:36 +0530500 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530501 result->buckets_scanned) ||
Mukul Sharmafa937be2016-08-12 18:13:36 +0530502 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530503 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700505 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800506 goto fail;
507 }
508
509 nla_aps = nla_nest_start(skb,
510 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
511 if (!nla_aps)
512 goto fail;
513
514 ap = &result->ap[0];
515 for (j = 0; j < result->num_results; j++) {
516 if (hdd_extscan_nl_fill_bss(skb, ap, j))
517 goto fail;
518
519 ap++;
520 }
521 nla_nest_end(skb, nla_aps);
522 nla_nest_end(skb, nla_result);
523 result++;
524 }
525 nla_nest_end(skb, nla_results);
526 }
527
528 cfg80211_vendor_cmd_reply(skb);
529
530 if (!data->more_data) {
531 spin_lock(&context->context_lock);
532 context->response_status = 0;
533 complete(&context->response_event);
534 spin_unlock(&context->context_lock);
535 }
536 return;
537
538fail:
539 if (skb)
540 kfree_skb(skb);
541
542 spin_lock(&context->context_lock);
543 context->response_status = -EINVAL;
544 spin_unlock(&context->context_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545}
546
547/**
548 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
549 * @ctx: Pointer to hdd context
550 * @pData: Pointer to ext scan result event
551 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800552 * This callback execute in atomic context and must not invoke any
553 * blocking calls.
554 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800555 * Return: none
556 */
557static void
558wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
559 struct extscan_hotlist_match *data)
560{
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700561 struct hdd_context *hdd_ctx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562 struct sk_buff *skb = NULL;
563 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800564 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565
Dustin Brown491d54b2018-03-14 12:39:11 -0700566 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800567
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700568 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530569 return;
570 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700571 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 return;
573 }
574
575 if (data->ap_found)
576 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
577 else
578 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
579
580 skb = cfg80211_vendor_event_alloc(
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700581 hdd_ctx->wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582 NULL,
583 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800584 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585
586 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700587 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 return;
589 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800590 hdd_debug("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 data->requestId, data->numOfAps, data->moreData,
592 data->ap_found);
593
594 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530595 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800596
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800597 hdd_debug("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 "Ssid: %s "
599 "Bssid (" MAC_ADDRESS_STR ") "
600 "Channel %u "
601 "Rssi %d "
602 "RTT %u "
603 "RTT_SD %u",
604 i,
605 data->ap[i].ts,
606 data->ap[i].ssid,
607 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
608 data->ap[i].channel,
609 data->ap[i].rssi,
610 data->ap[i].rtt, data->ap[i].rtt_sd);
611 }
612
613 if (nla_put_u32(skb,
614 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
615 data->requestId) ||
616 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530617 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700619 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620 goto fail;
621 }
622
623 if (data->numOfAps) {
624 struct nlattr *aps;
625
626 aps = nla_nest_start(skb,
627 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
628 if (!aps)
629 goto fail;
630
631 for (i = 0; i < data->numOfAps; i++) {
632 struct nlattr *ap;
633
634 ap = nla_nest_start(skb, i);
635 if (!ap)
636 goto fail;
637
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700638 if (hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
640 data->ap[i].ts) ||
641 nla_put(skb,
642 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
643 sizeof(data->ap[i].ssid),
644 data->ap[i].ssid) ||
645 nla_put(skb,
646 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
647 sizeof(data->ap[i].bssid),
648 data->ap[i].bssid.bytes) ||
649 nla_put_u32(skb,
650 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
651 data->ap[i].channel) ||
652 nla_put_s32(skb,
653 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
654 data->ap[i].rssi) ||
655 nla_put_u32(skb,
656 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
657 data->ap[i].rtt) ||
658 nla_put_u32(skb,
659 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
660 data->ap[i].rtt_sd))
661 goto fail;
662
663 nla_nest_end(skb, ap);
664 }
665 nla_nest_end(skb, aps);
666
667 if (nla_put_u8(skb,
668 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
669 data->moreData))
670 goto fail;
671 }
672
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800673 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -0700674 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 return;
676
677fail:
678 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800679}
680
681/**
682 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
683 * significant wifi change results indication
684 * @ctx: Pointer to hdd context
685 * @pData: Pointer to signif wifi change event
686 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800687 * This callback execute in atomic context and must not invoke any
688 * blocking calls.
689 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 * Return: none
691 */
692static void
693wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
694 void *ctx,
695 tpSirWifiSignificantChangeEvent pData)
696{
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700697 struct hdd_context *hdd_ctx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 struct sk_buff *skb = NULL;
699 tSirWifiSignificantChange *ap_info;
700 int32_t *rssi;
701 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800702 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703
Dustin Brown491d54b2018-03-14 12:39:11 -0700704 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700706 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530707 return;
708 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700709 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 return;
711 }
712
713 skb = cfg80211_vendor_event_alloc(
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700714 hdd_ctx->wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 NULL,
716 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
717 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800718 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719
720 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700721 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 return;
723 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800724 hdd_debug("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800725 pData->requestId, pData->numResults, pData->moreData);
726
727 ap_info = &pData->ap[0];
728 for (i = 0; i < pData->numResults; i++) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800729 hdd_debug("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800730 "Bssid (" MAC_ADDRESS_STR ") "
731 "Channel %u "
732 "numOfRssi %d",
733 i,
734 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
735 ap_info->channel, ap_info->numOfRssi);
736 rssi = &(ap_info)->rssi[0];
737 for (j = 0; j < ap_info->numOfRssi; j++)
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800738 hdd_debug("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800739
740 ap_info += ap_info->numOfRssi * sizeof(*rssi);
741 }
742
743 if (nla_put_u32(skb,
744 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
745 pData->requestId) ||
746 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530747 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800748 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700749 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800750 goto fail;
751 }
752
753 if (pData->numResults) {
754 struct nlattr *aps;
755
756 aps = nla_nest_start(skb,
757 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
758 if (!aps)
759 goto fail;
760
761 ap_info = &pData->ap[0];
762 for (i = 0; i < pData->numResults; i++) {
763 struct nlattr *ap;
764
765 ap = nla_nest_start(skb, i);
766 if (!ap)
767 goto fail;
768
769 if (nla_put(skb,
770 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530771 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 nla_put_u32(skb,
773 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
774 ap_info->channel) ||
775 nla_put_u32(skb,
776 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
777 ap_info->numOfRssi) ||
778 nla_put(skb,
779 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
780 sizeof(s32) * ap_info->numOfRssi,
781 &(ap_info)->rssi[0]))
782 goto fail;
783
784 nla_nest_end(skb, ap);
785
786 ap_info += ap_info->numOfRssi * sizeof(*rssi);
787 }
788 nla_nest_end(skb, aps);
789
790 if (nla_put_u8(skb,
791 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
792 pData->moreData))
793 goto fail;
794 }
795
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800796 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800797 return;
798
799fail:
800 kfree_skb(skb);
801 return;
802
803}
804
805/**
806 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
807 * @ctx: Pointer to hdd context
808 * @pData: Pointer to full scan result event
809 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800810 * This callback execute in atomic context and must not invoke any
811 * blocking calls.
812 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800813 * Return: none
814 */
815static void
816wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
817 tpSirWifiFullScanResultEvent
818 pData)
819{
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700820 struct hdd_context *hdd_ctx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800821 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 struct timespec ts;
Mukul Sharmafa937be2016-08-12 18:13:36 +0530823 struct hdd_ext_scan_context *context;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700824
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800825 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700827 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700829 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530830 return;
831 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700832 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 return;
834 }
835
836 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700837 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 return;
839 }
840 skb = cfg80211_vendor_event_alloc(
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700841 hdd_ctx->wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842 NULL,
843 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
844 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800845 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846
847 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700848 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 return;
850 }
851
852 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700853
Jeff Johnson9dc96a02017-01-12 09:47:56 -0800854 /*
855 * Android does not want the time stamp from the frame.
856 * Instead it wants a monotonic increasing value since boot
857 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700858 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700860
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800861 hdd_debug("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862 pData->moreData);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800863 hdd_debug("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800864 "Bssid (" MAC_ADDRESS_STR ") "
865 "Channel %u "
866 "Rssi %d "
867 "RTT %u "
868 "RTT_SD %u "
869 "Bcn Period %d "
870 "Capability 0x%X "
871 "IE Length %d",
872 pData->ap.ts,
873 pData->ap.ssid,
874 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
875 pData->ap.channel,
876 pData->ap.rssi,
877 pData->ap.rtt,
878 pData->ap.rtt_sd,
879 pData->ap.beaconPeriod,
880 pData->ap.capability, pData->ap.ieLength);
881
882 if (nla_put_u32(skb,
883 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
884 pData->requestId) ||
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700885 hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
887 pData->ap.ts) ||
888 nla_put(skb,
889 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
890 sizeof(pData->ap.ssid),
891 pData->ap.ssid) ||
892 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
893 sizeof(pData->ap.bssid),
894 pData->ap.bssid.bytes) ||
895 nla_put_u32(skb,
896 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
897 pData->ap.channel) ||
898 nla_put_s32(skb,
899 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
900 pData->ap.rssi) ||
901 nla_put_u32(skb,
902 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
903 pData->ap.rtt) ||
904 nla_put_u32(skb,
905 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
906 pData->ap.rtt_sd) ||
907 nla_put_u16(skb,
908 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
909 pData->ap.beaconPeriod) ||
910 nla_put_u16(skb,
911 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
912 pData->ap.capability) ||
913 nla_put_u32(skb,
914 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
915 pData->ap.ieLength) ||
916 nla_put_u8(skb,
917 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
918 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700919 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920 goto nla_put_failure;
921 }
922
923 if (pData->ap.ieLength) {
924 if (nla_put(skb,
925 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
926 pData->ap.ieLength, pData->ap.ieData))
927 goto nla_put_failure;
928 }
929
Mukul Sharmafa937be2016-08-12 18:13:36 +0530930 context = &ext_scan_context;
931 spin_lock(&context->context_lock);
932 if (nla_put_u32(skb,
933 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
934 context->buckets_scanned)) {
935 spin_unlock(&context->context_lock);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800936 hdd_debug("Failed to include buckets_scanned");
Mukul Sharmafa937be2016-08-12 18:13:36 +0530937 goto nla_put_failure;
938 }
939 spin_unlock(&context->context_lock);
940
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800941 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 return;
943
944nla_put_failure:
945 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800946}
947
948/**
949 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
950 * @ctx: Pointer to hdd context
951 * @pData: Pointer to scan results available indication param
952 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800953 * This callback execute in atomic context and must not invoke any
954 * blocking calls.
955 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800956 * Return: none
957 */
958static void
959wlan_hdd_cfg80211_extscan_scan_res_available_event(
960 void *ctx,
961 tpSirExtScanResultsAvailableIndParams pData)
962{
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700963 struct hdd_context *hdd_ctx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800964 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800965 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800966
Dustin Brown491d54b2018-03-14 12:39:11 -0700967 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700969 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530970 return;
971 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700972 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800973 return;
974 }
975
976 skb = cfg80211_vendor_event_alloc(
Jeff Johnsonc6dda512017-09-03 09:17:05 -0700977 hdd_ctx->wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 NULL,
979 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
980 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800981 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982
983 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700984 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800985 return;
986 }
987
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800988 hdd_debug("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989 pData->requestId, pData->numResultsAvailable);
990 if (nla_put_u32(skb,
991 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
992 pData->requestId) ||
993 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530994 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700996 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800997 goto nla_put_failure;
998 }
999
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001000 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07001001 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001002 return;
1003
1004nla_put_failure:
1005 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006}
1007
1008/**
1009 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
1010 * @ctx: Pointer to hdd context
1011 * @pData: Pointer to scan event indication param
1012 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001013 * This callback execute in atomic context and must not invoke any
1014 * blocking calls.
1015 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001016 * Return: none
1017 */
1018static void
1019wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
1020 tpSirExtScanOnScanEventIndParams
1021 pData)
1022{
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001023 struct hdd_context *hdd_ctx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001024 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001025 int flags = cds_get_gfp_flags();
Mukul Sharmafa937be2016-08-12 18:13:36 +05301026 struct hdd_ext_scan_context *context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001027
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001028 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001029
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001030 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301031 return;
1032 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001033 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001034 return;
1035 }
1036
1037 skb = cfg80211_vendor_event_alloc(
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001038 hdd_ctx->wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001039 NULL,
1040 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1041 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001042 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043
1044 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001045 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001046 return;
1047 }
Mukul Sharmafa937be2016-08-12 18:13:36 +05301048
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001049 hdd_debug("Request Id: %u Scan event type: %u Scan event status: %u buckets scanned: %u",
Mukul Sharmafa937be2016-08-12 18:13:36 +05301050 pData->requestId, pData->scanEventType, pData->status,
1051 pData->buckets_scanned);
1052
Mukul Sharmafa937be2016-08-12 18:13:36 +05301053 context = &ext_scan_context;
1054 spin_lock(&context->context_lock);
1055 if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT) {
1056 context->buckets_scanned = 0;
1057 pData->scanEventType = WIFI_EXTSCAN_RESULTS_AVAILABLE;
1058 spin_unlock(&context->context_lock);
1059 } else if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_STARTED_EVENT) {
1060 context->buckets_scanned = pData->buckets_scanned;
1061 /* No need to report to user space */
1062 spin_unlock(&context->context_lock);
Mukul Sharma45114d92016-08-12 19:34:14 +05301063 goto nla_put_failure;
Mukul Sharmafa937be2016-08-12 18:13:36 +05301064 } else {
1065 spin_unlock(&context->context_lock);
1066 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067
1068 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1069 pData->requestId) ||
1070 nla_put_u8(skb,
1071 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
Mukul Sharmafa937be2016-08-12 18:13:36 +05301072 pData->scanEventType)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001073 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074 goto nla_put_failure;
1075 }
1076
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001077 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001078 return;
1079
1080nla_put_failure:
1081 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082}
1083
1084/**
1085 * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found
1086 * @hddctx: HDD context
1087 * @data: matched network data
1088 *
1089 * This function reads the matched network data and fills NL vendor attributes
1090 * and send it to upper layer.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001091 * This callback execute in atomic context and must not invoke any
1092 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001093 *
1094 * Return: 0 on success, error number otherwise
1095 */
1096static void
1097wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
1098 struct pno_match_found *data)
1099{
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001100 struct hdd_context *hdd_ctx = (struct hdd_context *)ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101 struct sk_buff *skb = NULL;
1102 uint32_t len, i;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001103 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001104
Dustin Brown491d54b2018-03-14 12:39:11 -07001105 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001106
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001107 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301108 return;
1109 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001110 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111 return;
1112 }
1113
1114 /*
1115 * If the number of match found APs including IE data exceeds NL 4K size
1116 * limitation, drop that beacon/probe rsp frame.
1117 */
1118 len = sizeof(*data) +
1119 (data->num_results + sizeof(tSirWifiScanResult));
1120 for (i = 0; i < data->num_results; i++)
1121 len += data->ap[i].ieLength;
1122
1123 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001124 hdd_err("Frame exceeded NL size limitation, drop it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001125 return;
1126 }
1127
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001128 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001129 NULL,
1130 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1131 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001132 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001133
1134 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001135 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 return;
1137 }
1138
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001139 hdd_debug("Req Id %u More Data %u num_results %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 data->request_id, data->more_data, data->num_results);
1141 for (i = 0; i < data->num_results; i++) {
1142 data->ap[i].channel = cds_chan_to_freq(data->ap[i].channel);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001143 hdd_debug("AP Info: Timestamp %llu) Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 "Bssid (" MAC_ADDRESS_STR ") "
1145 "Channel %u "
1146 "Rssi %d "
1147 "RTT %u "
1148 "RTT_SD %u "
1149 "Bcn Period %d "
1150 "Capability 0x%X "
1151 "IE Length %d",
1152 data->ap[i].ts,
1153 data->ap[i].ssid,
1154 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
1155 data->ap[i].channel,
1156 data->ap[i].rssi,
1157 data->ap[i].rtt,
1158 data->ap[i].rtt_sd,
1159 data->ap[i].beaconPeriod,
1160 data->ap[i].capability,
1161 data->ap[i].ieLength);
1162 }
1163
1164 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1165 data->request_id) ||
1166 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301167 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001168 data->num_results) ||
1169 nla_put_u8(skb,
1170 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1171 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001172 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001173 goto fail;
1174 }
1175
1176 if (data->num_results) {
1177 struct nlattr *nla_aps;
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -07001178
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001179 nla_aps = nla_nest_start(skb,
1180 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1181 if (!nla_aps)
1182 goto fail;
1183
1184 for (i = 0; i < data->num_results; i++) {
1185 if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i))
1186 goto fail;
1187 }
1188 nla_nest_end(skb, nla_aps);
1189 }
1190
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001191 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001192 return;
1193
1194fail:
1195 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196}
1197
1198/**
1199 * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found
1200 * @hddctx: HDD context
1201 * @data: matched network data
1202 *
1203 * This function reads the match network %data and fill in the skb with
1204 * NL attributes and send up the NL event
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001205 * This callback execute in atomic context and must not invoke any
1206 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207 *
1208 * Return: none
1209 */
1210static void
1211wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
1212 struct wifi_passpoint_match *data)
1213{
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001214 struct hdd_context *hdd_ctx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 struct sk_buff *skb = NULL;
1216 uint32_t len, i, num_matches = 1, more_data = 0;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001217 struct nlattr *nla_aps, *nla_bss;
1218 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219
Dustin Brown491d54b2018-03-14 12:39:11 -07001220 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001222 if (wlan_hdd_validate_context(hdd_ctx))
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301223 return;
1224 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001225 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001226 return;
1227 }
1228
1229 len = sizeof(*data) + data->ap.ieLength + data->anqp_len;
1230 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001231 hdd_err("Result exceeded NL size limitation, drop it");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001232 return;
1233 }
1234
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001235 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 NULL,
1237 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1238 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001239 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240
1241 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001242 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243 return;
1244 }
1245
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001246 hdd_debug("Req Id %u Id %u ANQP length %u num_matches %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001247 data->request_id, data->id, data->anqp_len, num_matches);
1248 for (i = 0; i < num_matches; i++) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001249 hdd_debug("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250 "Bssid (" MAC_ADDRESS_STR ") "
1251 "Channel %u "
1252 "Rssi %d "
1253 "RTT %u "
1254 "RTT_SD %u "
1255 "Bcn Period %d "
1256 "Capability 0x%X "
1257 "IE Length %d",
1258 data->ap.ts,
1259 data->ap.ssid,
1260 MAC_ADDR_ARRAY(data->ap.bssid.bytes),
1261 data->ap.channel,
1262 data->ap.rssi,
1263 data->ap.rtt,
1264 data->ap.rtt_sd,
1265 data->ap.beaconPeriod,
1266 data->ap.capability,
1267 data->ap.ieLength);
1268 }
1269
1270 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1271 data->request_id) ||
1272 nla_put_u32(skb,
1273 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES,
1274 num_matches) ||
1275 nla_put_u8(skb,
1276 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1277 more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001278 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001279 goto fail;
1280 }
1281
1282 nla_aps = nla_nest_start(skb,
1283 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST);
1284 if (!nla_aps)
1285 goto fail;
1286
1287 for (i = 0; i < num_matches; i++) {
1288 struct nlattr *nla_ap;
1289
1290 nla_ap = nla_nest_start(skb, i);
1291 if (!nla_ap)
1292 goto fail;
1293
1294 if (nla_put_u32(skb,
1295 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID,
1296 data->id) ||
1297 nla_put_u32(skb,
1298 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN,
1299 data->anqp_len)) {
1300 goto fail;
1301 }
1302
1303 if (data->anqp_len)
1304 if (nla_put(skb,
1305 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP,
1306 data->anqp_len, data->anqp))
1307 goto fail;
1308
1309 nla_bss = nla_nest_start(skb,
1310 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1311 if (!nla_bss)
1312 goto fail;
1313
1314 if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0))
1315 goto fail;
1316
1317 nla_nest_end(skb, nla_bss);
1318 nla_nest_end(skb, nla_ap);
1319 }
1320 nla_nest_end(skb, nla_aps);
1321
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001322 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 return;
1324
1325fail:
1326 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327}
1328
1329/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330 * wlan_hdd_cfg80211_extscan_generic_rsp() -
1331 * Handle a generic ExtScan Response message
1332 * @ctx: HDD context registered with SME
1333 * @response: The ExtScan response from firmware
1334 *
1335 * This function will handle a generic ExtScan response message from
1336 * firmware and will communicate the result to the userspace thread
1337 * that is waiting for the response.
1338 *
1339 * Return: none
1340 */
1341static void
1342wlan_hdd_cfg80211_extscan_generic_rsp
1343 (void *ctx,
1344 struct sir_extscan_generic_response *response)
1345{
Jeff Johnson9755a512017-08-28 12:01:57 -07001346 struct hdd_context *hdd_ctx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347 struct hdd_ext_scan_context *context;
1348
Dustin Brown491d54b2018-03-14 12:39:11 -07001349 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350
1351 if (wlan_hdd_validate_context(hdd_ctx) || !response) {
Jeff Johnson36e74c42017-09-18 08:15:42 -07001352 hdd_err("HDD context is not valid or response(%pK) is null",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353 response);
1354 return;
1355 }
1356
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001357 hdd_debug("request %u status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001358 response->request_id, response->status);
1359
1360 context = &ext_scan_context;
1361 spin_lock(&context->context_lock);
1362 if (context->request_id == response->request_id) {
1363 context->response_status = response->status ? -EINVAL : 0;
1364 complete(&context->response_event);
1365 }
1366 spin_unlock(&context->context_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367}
1368
1369/**
1370 * wlan_hdd_cfg80211_extscan_callback() - ext scan callback
1371 * @ctx: Pointer to hdd context
1372 * @evType: Event type
1373 * @pMag: Pointer to message
1374 *
1375 * Return: none
1376 */
1377void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType,
1378 void *pMsg)
1379{
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001380 struct hdd_context *hdd_ctx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001381
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001382 /* ENTER() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301383
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001384 if (wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001387 hdd_debug("Rcvd Event %d", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388
1389 switch (evType) {
1390 case eSIR_EXTSCAN_CACHED_RESULTS_RSP:
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001391 /* There is no need to send this response to upper layer
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -07001392 * Just log the message
1393 */
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001394 hdd_debug("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395 break;
1396
1397 case eSIR_EXTSCAN_GET_CAPABILITIES_IND:
1398 wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx,
1399 (struct ext_scan_capabilities_response *) pMsg);
1400 break;
1401
1402 case eSIR_EXTSCAN_HOTLIST_MATCH_IND:
1403 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
1404 break;
1405
1406 case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND:
1407 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx,
1408 (tpSirWifiSignificantChangeEvent) pMsg);
1409 break;
1410
1411 case eSIR_EXTSCAN_CACHED_RESULTS_IND:
1412 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
1413 break;
1414
1415 case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND:
1416 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx,
1417 (tpSirExtScanResultsAvailableIndParams) pMsg);
1418 break;
1419
1420 case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND:
1421 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx,
1422 (tpSirWifiFullScanResultEvent) pMsg);
1423 break;
1424
1425 case eSIR_EPNO_NETWORK_FOUND_IND:
1426 wlan_hdd_cfg80211_extscan_epno_match_found(ctx,
1427 (struct pno_match_found *)pMsg);
1428 break;
1429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001430 case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND:
1431 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx,
1432 (tpSirExtScanOnScanEventIndParams) pMsg);
1433 break;
1434
1435 case eSIR_PASSPOINT_NETWORK_FOUND_IND:
1436 wlan_hdd_cfg80211_passpoint_match_found(ctx,
1437 (struct wifi_passpoint_match *) pMsg);
1438 break;
1439
1440 case eSIR_EXTSCAN_START_RSP:
1441 case eSIR_EXTSCAN_STOP_RSP:
1442 case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP:
1443 case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP:
1444 case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP:
1445 case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP:
1446 case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP:
1447 case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP:
1448 wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg);
1449 break;
1450
1451 default:
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001452 hdd_err("Unknown event type: %u", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001453 break;
1454 }
1455}
1456
1457/*
1458 * define short names for the global vendor params
1459 * used by wlan_hdd_send_ext_scan_capability()
1460 */
1461#define PARAM_REQUEST_ID \
1462 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1463#define PARAM_STATUS \
1464 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1465#define MAX_SCAN_CACHE_SIZE \
1466 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1467#define MAX_SCAN_BUCKETS \
1468 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1469#define MAX_AP_CACHE_PER_SCAN \
1470 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1471#define MAX_RSSI_SAMPLE_SIZE \
1472 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1473#define MAX_SCAN_RPT_THRHOLD \
1474 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1475#define MAX_HOTLIST_BSSIDS \
1476 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1477#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1478 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1479#define MAX_BSSID_HISTORY_ENTRIES \
1480 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1481#define MAX_HOTLIST_SSIDS \
1482 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1483#define MAX_NUM_EPNO_NETS \
1484 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1485#define MAX_NUM_EPNO_NETS_BY_SSID \
1486 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1487#define MAX_NUM_WHITELISTED_SSID \
1488 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301489#define MAX_NUM_BLACKLISTED_BSSID \
1490 QCA_WLAN_VENDOR_ATTR_EXTSCAN_MAX_NUM_BLACKLISTED_BSSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001491/**
1492 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1493 * @hdd_ctx: Pointer to hdd context
1494 *
1495 * Return: 0 for success, non-zero for failure
1496 */
Jeff Johnson9755a512017-08-28 12:01:57 -07001497static int wlan_hdd_send_ext_scan_capability(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498{
1499 int ret;
1500 struct sk_buff *skb;
1501 struct ext_scan_capabilities_response *data;
1502 uint32_t nl_buf_len;
1503
1504 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301505 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001506 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001507
1508 data = &(ext_scan_context.capability_response);
1509
1510 nl_buf_len = NLMSG_HDRLEN;
1511 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1512 (sizeof(data->status) + NLA_HDRLEN) +
1513 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1514 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1515 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1516 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1517 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1518 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1519 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1520 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1521 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1522 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1523 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301524 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN) +
1525 (sizeof(data->max_number_of_black_listed_bssid) + NLA_HDRLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001526
1527 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1528
1529 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001530 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001531 return -ENOMEM;
1532 }
1533
1534
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001535 hdd_debug("Req Id %u", data->requestId);
1536 hdd_debug("Status %u", data->status);
1537 hdd_debug("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 data->max_scan_cache_size);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001539 hdd_debug("Scan buckets %u", data->max_scan_buckets);
1540 hdd_debug("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 data->max_ap_cache_per_scan);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001542 hdd_debug("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001543 data->max_rssi_sample_size);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001544 hdd_debug("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 data->max_scan_reporting_threshold);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001546 hdd_debug("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 data->max_hotlist_bssids);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001548 hdd_debug("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549 data->max_significant_wifi_change_aps);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001550 hdd_debug("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551 data->max_bssid_history_entries);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001552 hdd_debug("max_hotlist_ssids %u", data->max_hotlist_ssids);
1553 hdd_debug("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554 data->max_number_epno_networks);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001555 hdd_debug("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 data->max_number_epno_networks_by_ssid);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001557 hdd_debug("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 data->max_number_of_white_listed_ssid);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001559 hdd_debug("max_number_of_black_listed_bssid (%u)",
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301560 data->max_number_of_black_listed_bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561
1562 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1563 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1564 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1565 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1566 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1567 data->max_ap_cache_per_scan) ||
1568 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1569 data->max_rssi_sample_size) ||
1570 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1571 data->max_scan_reporting_threshold) ||
1572 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1573 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1574 data->max_significant_wifi_change_aps) ||
1575 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1576 data->max_bssid_history_entries) ||
1577 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1578 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1579 data->max_number_epno_networks) ||
1580 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1581 data->max_number_epno_networks_by_ssid) ||
1582 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
Jeff Johnson59eb5fd2017-10-05 09:42:39 -07001583 data->max_number_of_white_listed_ssid) ||
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301584 nla_put_u32(skb, MAX_NUM_BLACKLISTED_BSSID,
Jeff Johnson59eb5fd2017-10-05 09:42:39 -07001585 data->max_number_of_black_listed_bssid)) {
1586 hdd_err("nla put fail");
1587 goto nla_put_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001588 }
1589
1590 cfg80211_vendor_cmd_reply(skb);
1591 return 0;
1592
1593nla_put_failure:
1594 kfree_skb(skb);
1595 return -EINVAL;
1596}
1597/*
1598 * done with short names for the global vendor params
1599 * used by wlan_hdd_send_ext_scan_capability()
1600 */
1601#undef PARAM_REQUEST_ID
1602#undef PARAM_STATUS
1603#undef MAX_SCAN_CACHE_SIZE
1604#undef MAX_SCAN_BUCKETS
1605#undef MAX_AP_CACHE_PER_SCAN
1606#undef MAX_RSSI_SAMPLE_SIZE
1607#undef MAX_SCAN_RPT_THRHOLD
1608#undef MAX_HOTLIST_BSSIDS
1609#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1610#undef MAX_BSSID_HISTORY_ENTRIES
1611#undef MAX_HOTLIST_SSIDS
1612#undef MAX_NUM_EPNO_NETS
1613#undef MAX_NUM_EPNO_NETS_BY_SSID
1614#undef MAX_NUM_WHITELISTED_SSID
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301615#undef MAX_NUM_BLACKLISTED_BSSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001616
1617/**
1618 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1619 * @wiphy: Pointer to wireless phy
1620 * @wdev: Pointer to wireless device
1621 * @data: Pointer to data
1622 * @data_len: Data length
1623 *
1624 * Return: none
1625 */
1626static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1627 struct wireless_dev *wdev,
1628 const void *data, int data_len)
1629{
1630 int ret;
1631 unsigned long rc;
1632 struct hdd_ext_scan_context *context;
1633 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1634 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07001635 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001636 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001637 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1638 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301639 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001640
Dustin Brownfdf17c12018-03-14 12:55:34 -07001641 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001642
Anurag Chouhan6d760662016-02-20 16:05:43 +05301643 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001644 hdd_err("Command not allowed in FTM mode");
1645 return -EPERM;
1646 }
1647
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001648 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301649 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001651
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001652 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05301653 hdd_err("Driver Modules are closed");
1654 return -EINVAL;
1655 }
1656
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001657 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301658 hdd_err("extscan not supported");
1659 return -ENOTSUPP;
1660 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08001661 if (wlan_cfg80211_nla_parse(tb,
1662 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1663 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001664 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001665 return -EINVAL;
1666 }
1667
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301668 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001669 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001670 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001671 return -ENOMEM;
1672 }
1673
1674 /* Parse and fetch request Id */
1675 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001676 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677 goto fail;
1678 }
1679
1680 pReqMsg->requestId =
1681 nla_get_u32(tb
1682 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07001683 pReqMsg->sessionId = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001684 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 pReqMsg->requestId, pReqMsg->sessionId);
1686
1687 context = &ext_scan_context;
1688 spin_lock(&context->context_lock);
1689 context->request_id = pReqMsg->requestId;
1690 INIT_COMPLETION(context->response_event);
1691 spin_unlock(&context->context_lock);
1692
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001693 status = sme_ext_scan_get_capabilities(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301694 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001695 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001696 status);
1697 goto fail;
1698 }
1699
1700 rc = wait_for_completion_timeout(&context->response_event,
1701 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1702 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001703 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001704 return -ETIMEDOUT;
1705 }
1706
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001707 ret = wlan_hdd_send_ext_scan_capability(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001708 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001709 hdd_err("Failed to send ext scan capability to user space");
Dustin Browne74003f2018-03-14 12:51:58 -07001710 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001711 return ret;
1712fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301713 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001714 return -EINVAL;
1715}
1716
1717/**
1718 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1719 * @wiphy: Pointer to wiphy
1720 * @wdev: Pointer to wdev
1721 * @data: Pointer to data
1722 * @data_len: Data length
1723 *
1724 * Return: 0 for success, non-zero for failure
1725 */
1726int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1727 struct wireless_dev *wdev,
1728 const void *data, int data_len)
1729{
1730 int ret = 0;
1731
1732 cds_ssr_protect(__func__);
1733 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1734 data_len);
1735 cds_ssr_unprotect(__func__);
1736
1737 return ret;
1738}
1739
1740/*
1741 * define short names for the global vendor params
1742 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1743 */
1744#define PARAM_MAX \
1745 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1746#define PARAM_REQUEST_ID \
1747 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1748#define PARAM_FLUSH \
1749 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1750/**
1751 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1752 * @wiphy: wiphy pointer
1753 * @wdev: pointer to struct wireless_dev
1754 * @data: pointer to incoming NL vendor data
1755 * @data_len: length of @data
1756 *
1757 * This function parses the incoming NL vendor command data attributes and
1758 * invokes the SME Api and blocks on a completion variable.
1759 * Each WMI event with cached scan results data chunk results in
1760 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1761 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1762 *
1763 * If timeout happens before receiving all of the data, this function sets
1764 * a context variable @ignore_cached_results to %true, all of the next data
1765 * chunks are checked against this variable and dropped.
1766 *
1767 * Return: 0 on success; error number otherwise.
1768 */
1769static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1770 struct wireless_dev
1771 *wdev, const void *data,
1772 int data_len)
1773{
1774 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1775 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07001776 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001777 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1779 1];
1780 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301781 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001782 int retval = 0;
1783 unsigned long rc;
1784
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001785 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001786
Anurag Chouhan6d760662016-02-20 16:05:43 +05301787 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001788 hdd_err("Command not allowed in FTM mode");
1789 return -EPERM;
1790 }
1791
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001792 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301793 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001796 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301797 hdd_err("extscan not supported");
1798 return -ENOTSUPP;
1799 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08001800 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len,
1801 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001802 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001803 return -EINVAL;
1804 }
1805
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301806 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001807 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001808 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809 return -ENOMEM;
1810 }
1811
1812 /* Parse and fetch request Id */
1813 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001814 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001815 goto fail;
1816 }
1817
1818 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07001819 pReqMsg->sessionId = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820
1821 /* Parse and fetch flush parameter */
1822 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001823 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 goto fail;
1825 }
1826 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001827 hdd_debug("Req Id: %u Session Id: %d Flush: %d",
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001828 pReqMsg->requestId, pReqMsg->sessionId, pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001829
1830 context = &ext_scan_context;
1831 spin_lock(&context->context_lock);
1832 context->request_id = pReqMsg->requestId;
1833 context->ignore_cached_results = false;
1834 INIT_COMPLETION(context->response_event);
1835 spin_unlock(&context->context_lock);
1836
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001837 status = sme_get_cached_results(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301838 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001839 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001840 goto fail;
1841 }
1842
1843 rc = wait_for_completion_timeout(&context->response_event,
1844 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1845 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001846 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001847 retval = -ETIMEDOUT;
1848 spin_lock(&context->context_lock);
1849 context->ignore_cached_results = true;
1850 spin_unlock(&context->context_lock);
1851 } else {
1852 spin_lock(&context->context_lock);
1853 retval = context->response_status;
1854 spin_unlock(&context->context_lock);
1855 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856 return retval;
1857
1858fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301859 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001860 return -EINVAL;
1861}
1862/*
1863 * done with short names for the global vendor params
1864 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1865 */
1866#undef PARAM_MAX
1867#undef PARAM_REQUEST_ID
1868#undef PARAM_FLUSH
1869
1870/**
1871 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1872 * @wiphy: wiphy pointer
1873 * @wdev: pointer to struct wireless_dev
1874 * @data: pointer to incoming NL vendor data
1875 * @data_len: length of @data
1876 *
1877 * This function parses the incoming NL vendor command data attributes and
1878 * invokes the SME Api and blocks on a completion variable.
1879 * Each WMI event with cached scan results data chunk results in
1880 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1881 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1882 *
1883 * If timeout happens before receiving all of the data, this function sets
1884 * a context variable @ignore_cached_results to %true, all of the next data
1885 * chunks are checked against this variable and dropped.
1886 *
1887 * Return: 0 on success; error number otherwise.
1888 */
1889int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1890 struct wireless_dev *wdev,
1891 const void *data, int data_len)
1892{
1893 int ret = 0;
1894
1895 cds_ssr_protect(__func__);
1896 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
1897 data_len);
1898 cds_ssr_unprotect(__func__);
1899
1900 return ret;
1901}
1902
1903/**
1904 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
1905 * @wiphy: Pointer to wireless phy
1906 * @wdev: Pointer to wireless device
1907 * @data: Pointer to data
1908 * @data_len: Data length
1909 *
1910 * Return: none
1911 */
1912static int
1913__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
1914 struct wireless_dev
1915 *wdev, const void *data,
1916 int data_len)
1917{
1918 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
1919 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07001920 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001921 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1923 1];
1924 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1925 + 1];
1926 struct nlattr *apTh;
1927 struct hdd_ext_scan_context *context;
1928 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301929 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 uint8_t i;
1931 int rem, retval;
1932 unsigned long rc;
1933
Dustin Brownfdf17c12018-03-14 12:55:34 -07001934 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001935
Anurag Chouhan6d760662016-02-20 16:05:43 +05301936 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937 hdd_err("Command not allowed in FTM mode");
1938 return -EPERM;
1939 }
1940
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001941 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301942 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001944
Jeff Johnsonc6dda512017-09-03 09:17:05 -07001945 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301946 hdd_err("extscan not supported");
1947 return -ENOTSUPP;
1948 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08001949 if (wlan_cfg80211_nla_parse(tb,
1950 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1951 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001952 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001953 return -EINVAL;
1954 }
1955
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301956 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001958 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001959 return -ENOMEM;
1960 }
1961
1962 /* Parse and fetch request Id */
1963 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001964 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 goto fail;
1966 }
1967
1968 pReqMsg->requestId =
1969 nla_get_u32(tb
1970 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001971 hdd_debug("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972
1973 /* Parse and fetch number of APs */
1974 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001975 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 goto fail;
1977 }
1978 pReqMsg->numAp =
1979 nla_get_u32(tb
1980 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08001981 if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_HOTLIST_APS) {
1982 hdd_err("Number of AP: %u exceeds max: %u",
1983 pReqMsg->numAp, WLAN_EXTSCAN_MAX_HOTLIST_APS);
1984 goto fail;
1985 }
Jeff Johnson1b780e42017-10-31 14:11:45 -07001986 pReqMsg->sessionId = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001987 hdd_debug("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001988 pReqMsg->numAp, pReqMsg->sessionId);
1989
1990 /* Parse and fetch lost ap sample size */
1991 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001992 hdd_err("attr lost ap sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 goto fail;
1994 }
1995
1996 pReqMsg->lost_ap_sample_size = nla_get_u32(
1997 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001998 hdd_debug("Lost ap sample size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001999 pReqMsg->lost_ap_sample_size);
2000
SaidiReddy Yenugaa1917382017-03-28 17:04:37 +05302001 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM]) {
2002 hdd_err("attr ap threshold failed");
2003 goto fail;
2004 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002005 i = 0;
2006 nla_for_each_nested(apTh,
2007 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2008 rem) {
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002009 if (i == pReqMsg->numAp) {
2010 hdd_warn("Ignoring excess AP");
2011 break;
2012 }
2013
Dustin Brown4ea21db2018-01-05 14:13:17 -08002014 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07002015 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2016 nla_data(apTh), nla_len(apTh),
2017 wlan_hdd_extscan_config_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08002018 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002019 goto fail;
2020 }
2021
2022 /* Parse and fetch MAC address */
2023 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002024 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 goto fail;
2026 }
2027 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2028 tb2
2029 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302030 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002031 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002032 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2033
2034 /* Parse and fetch low RSSI */
2035 if (!tb2
2036 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002037 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002038 goto fail;
2039 }
2040 pReqMsg->ap[i].low =
2041 nla_get_s32(tb2
2042 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002043 hdd_debug("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002044
2045 /* Parse and fetch high RSSI */
2046 if (!tb2
2047 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002048 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002049 goto fail;
2050 }
2051 pReqMsg->ap[i].high =
2052 nla_get_s32(tb2
2053 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002054 hdd_debug("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002055
2056 i++;
2057 }
2058
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002059 if (i < pReqMsg->numAp) {
2060 hdd_warn("Number of AP %u less than expected %u",
2061 i, pReqMsg->numAp);
2062 pReqMsg->numAp = i;
2063 }
2064
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002065 context = &ext_scan_context;
2066 spin_lock(&context->context_lock);
2067 INIT_COMPLETION(context->response_event);
2068 context->request_id = request_id = pReqMsg->requestId;
2069 spin_unlock(&context->context_lock);
2070
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002071 status = sme_set_bss_hotlist(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302072 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002073 hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002074 goto fail;
2075 }
2076
2077 /* request was sent -- wait for the response */
2078 rc = wait_for_completion_timeout
2079 (&context->response_event,
2080 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2081
2082 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002083 hdd_err("sme_set_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002084 retval = -ETIMEDOUT;
2085 } else {
2086 spin_lock(&context->context_lock);
2087 if (context->request_id == request_id)
2088 retval = context->response_status;
2089 else
2090 retval = -EINVAL;
2091 spin_unlock(&context->context_lock);
2092 }
Dustin Browne74003f2018-03-14 12:51:58 -07002093 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002094 return retval;
2095
2096fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302097 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002098 return -EINVAL;
2099}
2100
2101/**
2102 * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist
2103 * @wiphy: Pointer to wiphy
2104 * @wdev: Pointer to wdev
2105 * @data: Pointer to data
2106 * @data_len: Data length
2107 *
2108 * Return: 0 for success, non-zero for failure
2109 */
2110int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2111 struct wireless_dev *wdev,
2112 const void *data, int data_len)
2113{
2114 int ret = 0;
2115
2116 cds_ssr_protect(__func__);
2117 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
2118 data_len);
2119 cds_ssr_unprotect(__func__);
2120
2121 return ret;
2122}
2123
2124
2125/**
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -07002126 * __wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127 * @wiphy: Pointer to wireless phy
2128 * @wdev: Pointer to wireless device
2129 * @data: Pointer to data
2130 * @data_len: Data length
2131 *
2132 * Return: none
2133 */
2134static int
2135__wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2136 struct wireless_dev
2137 *wdev, const void *data,
2138 int data_len)
2139{
2140 tpSirExtScanSetSigChangeReqParams pReqMsg = NULL;
2141 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07002142 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002143 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002144 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2145 1];
2146 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2147 + 1];
2148 struct nlattr *apTh;
2149 struct hdd_ext_scan_context *context;
2150 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302151 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002152 uint8_t i;
2153 int rem, retval;
2154 unsigned long rc;
2155
Dustin Brownfdf17c12018-03-14 12:55:34 -07002156 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002157
Anurag Chouhan6d760662016-02-20 16:05:43 +05302158 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002159 hdd_err("Command not allowed in FTM mode");
2160 return -EPERM;
2161 }
2162
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002163 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302164 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002166
Dustin Brown4ea21db2018-01-05 14:13:17 -08002167 if (wlan_cfg80211_nla_parse(tb,
2168 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2169 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002170 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 return -EINVAL;
2172 }
2173
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302174 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002176 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002177 return -ENOMEM;
2178 }
2179
2180 /* Parse and fetch request Id */
2181 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002182 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002183 goto fail;
2184 }
2185
2186 pReqMsg->requestId =
2187 nla_get_u32(tb
2188 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002189 hdd_debug("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190
2191 /* Parse and fetch RSSI sample size */
2192 if (!tb
2193 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002194 hdd_err("attr RSSI sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 goto fail;
2196 }
2197 pReqMsg->rssiSampleSize =
2198 nla_get_u32(tb
2199 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002200 hdd_debug("RSSI sample size %u", pReqMsg->rssiSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201
2202 /* Parse and fetch lost AP sample size */
2203 if (!tb
2204 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002205 hdd_err("attr lost AP sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 goto fail;
2207 }
2208 pReqMsg->lostApSampleSize =
2209 nla_get_u32(tb
2210 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002211 hdd_debug("Lost AP sample size %u", pReqMsg->lostApSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212
2213 /* Parse and fetch AP min breacing */
2214 if (!tb
2215 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002216 hdd_err("attr AP min breaching");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217 goto fail;
2218 }
2219 pReqMsg->minBreaching =
2220 nla_get_u32(tb
2221 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002222 hdd_debug("AP min breaching %u", pReqMsg->minBreaching);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002223
2224 /* Parse and fetch number of APs */
2225 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002226 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002227 goto fail;
2228 }
2229 pReqMsg->numAp =
2230 nla_get_u32(tb
2231 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002232 if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS) {
2233 hdd_err("Number of AP %u exceeds max %u",
2234 pReqMsg->numAp,
2235 WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS);
2236 goto fail;
2237 }
2238
Jeff Johnson1b780e42017-10-31 14:11:45 -07002239 pReqMsg->sessionId = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002240 hdd_debug("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002241 pReqMsg->numAp, pReqMsg->sessionId);
2242
SaidiReddy Yenuga6f4763d2017-03-28 17:09:56 +05302243 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM]) {
2244 hdd_err("attr ap threshold failed");
2245 goto fail;
2246 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002247 i = 0;
2248 nla_for_each_nested(apTh,
2249 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2250 rem) {
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002251
2252 if (i == pReqMsg->numAp) {
2253 hdd_warn("Ignoring excess AP");
2254 break;
2255 }
2256
Dustin Brown4ea21db2018-01-05 14:13:17 -08002257 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07002258 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2259 nla_data(apTh), nla_len(apTh),
2260 wlan_hdd_extscan_config_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08002261 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002262 goto fail;
2263 }
2264
2265 /* Parse and fetch MAC address */
2266 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002267 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002268 goto fail;
2269 }
2270 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2271 tb2
2272 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302273 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002274 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002275 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2276
2277 /* Parse and fetch low RSSI */
2278 if (!tb2
2279 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002280 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002281 goto fail;
2282 }
2283 pReqMsg->ap[i].low =
2284 nla_get_s32(tb2
2285 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002286 hdd_debug("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002287
2288 /* Parse and fetch high RSSI */
2289 if (!tb2
2290 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002291 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002292 goto fail;
2293 }
2294 pReqMsg->ap[i].high =
2295 nla_get_s32(tb2
2296 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002297 hdd_debug("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002298
2299 i++;
2300 }
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002301 if (i < pReqMsg->numAp) {
2302 hdd_warn("Number of AP %u less than expected %u",
2303 i, pReqMsg->numAp);
2304 pReqMsg->numAp = i;
2305 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002306
2307 context = &ext_scan_context;
2308 spin_lock(&context->context_lock);
2309 INIT_COMPLETION(context->response_event);
2310 context->request_id = request_id = pReqMsg->requestId;
2311 spin_unlock(&context->context_lock);
2312
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002313 status = sme_set_significant_change(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302314 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002315 hdd_err("sme_set_significant_change failed(err=%d)", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302316 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 return -EINVAL;
2318 }
2319
2320 /* request was sent -- wait for the response */
2321 rc = wait_for_completion_timeout(&context->response_event,
2322 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2323
2324 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002325 hdd_err("sme_set_significant_change timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 retval = -ETIMEDOUT;
2327 } else {
2328 spin_lock(&context->context_lock);
2329 if (context->request_id == request_id)
2330 retval = context->response_status;
2331 else
2332 retval = -EINVAL;
2333 spin_unlock(&context->context_lock);
2334 }
Dustin Browne74003f2018-03-14 12:51:58 -07002335 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002336 return retval;
2337
2338fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302339 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002340 return -EINVAL;
2341}
2342
2343/**
2344 * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
2345 * @wiphy: Pointer to wireless phy
2346 * @wdev: Pointer to wireless device
2347 * @data: Pointer to data
2348 * @data_len: Data length
2349 *
2350 * Return: 0 on success, negative errno on failure
2351 */
2352int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2353 struct wireless_dev *wdev,
2354 const void *data, int data_len)
2355{
2356 int ret = 0;
2357
2358 cds_ssr_protect(__func__);
2359 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev,
2360 data, data_len);
2361 cds_ssr_unprotect(__func__);
2362
2363 return ret;
2364}
2365
2366/**
2367 * hdd_remove_dsrc_channels () - remove dsrc chanels
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002368 * @hdd_ctx: hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002369 * @wiphy: Pointer to wireless phy
2370 * @chan_list: channel list
2371 * @num_channels: number of channels
2372 *
2373 * Return: none
2374 */
Jeff Johnson9755a512017-08-28 12:01:57 -07002375static void hdd_remove_dsrc_channels(struct hdd_context *hdd_ctx,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002376 struct wiphy *wiphy, uint32_t *chan_list,
Jeff Johnsoncd2a0792016-10-05 15:17:13 -07002377 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378{
2379 uint8_t num_chan_temp = 0;
2380 int i;
2381
2382 for (i = 0; i < *num_channels; i++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002383 if (!WLAN_REG_IS_11P_CH(wlan_reg_freq_to_chan(hdd_ctx->hdd_pdev,
2384 chan_list[i]))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 chan_list[num_chan_temp] = chan_list[i];
2386 num_chan_temp++;
2387 }
2388 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002389 *num_channels = num_chan_temp;
2390}
2391
2392/**
Amar Singhalea10a872016-08-23 15:31:45 -07002393 * hdd_remove_passive_channels () - remove passive channels
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002394 * @wiphy: Pointer to wireless phy
2395 * @chan_list: channel list
2396 * @num_channels: number of channels
2397 *
2398 * Return: none
2399 */
Amar Singhal25b10f92016-11-14 16:53:25 -08002400static void hdd_remove_passive_channels(struct wiphy *wiphy,
2401 uint32_t *chan_list,
2402 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002403{
2404 uint8_t num_chan_temp = 0;
2405 int i, j, k;
2406
2407 for (i = 0; i < *num_channels; i++)
Srinivas Girigowda5da651b2017-08-04 11:22:54 -07002408 for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409 if (wiphy->bands[j] == NULL)
2410 continue;
2411 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
2412 if ((chan_list[i] ==
2413 wiphy->bands[j]->channels[k].center_freq)
2414 && (!(wiphy->bands[j]->channels[k].flags &
Amar Singhalea10a872016-08-23 15:31:45 -07002415 IEEE80211_CHAN_PASSIVE_SCAN))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416 ) {
2417 chan_list[num_chan_temp] = chan_list[i];
2418 num_chan_temp++;
2419 }
2420 }
2421 }
2422
2423 *num_channels = num_chan_temp;
2424}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425
2426/**
2427 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
2428 * @wiphy: Pointer to wireless phy
2429 * @wdev: Pointer to wireless device
2430 * @data: Pointer to data
2431 * @data_len: Data length
2432 *
2433 * Return: none
2434 */
2435static int
2436__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2437 struct wireless_dev
2438 *wdev, const void *data,
2439 int data_len)
2440{
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002441 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07002443 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002445 uint8_t num_channels = 0, i, buf[256] = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2447 1];
2448 uint32_t requestId, maxChannels;
2449 tWifiBand wifiBand;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302450 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 struct sk_buff *reply_skb;
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002452 int ret, len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002454 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455
Anurag Chouhan6d760662016-02-20 16:05:43 +05302456 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002457 hdd_err("Command not allowed in FTM mode");
2458 return -EPERM;
2459 }
2460
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002461 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302462 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002463 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002465 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302466 hdd_err("extscan not supported");
2467 return -ENOTSUPP;
2468 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08002469 if (wlan_cfg80211_nla_parse(tb,
2470 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2471 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002472 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 return -EINVAL;
2474 }
2475
2476 /* Parse and fetch request Id */
2477 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002478 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002479 return -EINVAL;
2480 }
2481 requestId =
2482 nla_get_u32(tb
2483 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484
2485 /* Parse and fetch wifi band */
2486 if (!tb
2487 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002488 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 return -EINVAL;
2490 }
2491 wifiBand =
2492 nla_get_u32(tb
2493 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494
2495 if (!tb
2496 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002497 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002498 return -EINVAL;
2499 }
2500 maxChannels =
2501 nla_get_u32(tb
2502 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Manjeet Singhdb485182016-11-09 19:11:01 +05302503
2504 if (maxChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) {
2505 hdd_err("Max channels %d exceeded Valid channel list len %d",
2506 maxChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2507 return -EINVAL;
2508 }
2509
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002510 hdd_debug("Req Id: %u Wifi band: %d Max channels: %d", requestId,
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002511 wifiBand, maxChannels);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002512 status = sme_get_valid_channels_by_band((tHalHandle) (hdd_ctx->hHal),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002513 wifiBand, chan_list,
2514 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302515 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002516 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 status);
2518 return -EINVAL;
2519 }
2520
Anurag Chouhan6d760662016-02-20 16:05:43 +05302521 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522
Jeff Johnsonc6dda512017-09-03 09:17:05 -07002523 hdd_remove_dsrc_channels(hdd_ctx, wiphy, chan_list, &num_channels);
Jeff Johnson7058aa82017-10-02 13:29:09 -07002524 if ((QDF_SAP_MODE == adapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525 !strncmp(hdd_get_fwpath(), "ap", 2))
Amar Singhalea10a872016-08-23 15:31:45 -07002526 hdd_remove_passive_channels(wiphy, chan_list,
2527 &num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002528
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002529 hdd_debug("Number of channels: %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002530 for (i = 0; i < num_channels; i++)
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002531 len += scnprintf(buf + len, sizeof(buf) - len,
2532 "%u ", chan_list[i]);
2533
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002534 hdd_debug("Channels: %s", buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002535
2536 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2537 sizeof(u32) *
2538 num_channels +
2539 NLMSG_HDRLEN);
2540
2541 if (reply_skb) {
2542 if (nla_put_u32(reply_skb,
2543 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2544 num_channels) ||
2545 nla_put(reply_skb,
2546 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2547 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002548 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 kfree_skb(reply_skb);
2550 return -EINVAL;
2551 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302552 ret = cfg80211_vendor_cmd_reply(reply_skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302553 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 }
2555
Jeff Johnson630f9e72016-07-25 12:00:12 -07002556 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 return -EINVAL;
2558}
2559
2560/**
2561 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2562 * @wiphy: Pointer to wireless phy
2563 * @wdev: Pointer to wireless device
2564 * @data: Pointer to data
2565 * @data_len: Data length
2566 *
2567 * Return: 0 on success, negative errno on failure
2568 */
2569int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2570 struct wireless_dev *wdev,
2571 const void *data, int data_len)
2572{
2573 int ret = 0;
2574
2575 cds_ssr_protect(__func__);
2576 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2577 data_len);
2578 cds_ssr_unprotect(__func__);
2579
2580 return ret;
2581}
2582
2583/**
2584 * hdd_extscan_update_dwell_time_limits() - update dwell times
2585 * @req_msg: Pointer to request message
2586 * @bkt_idx: Index of current bucket being processed
2587 * @active_min: minimum active dwell time
2588 * @active_max: maximum active dwell time
2589 * @passive_min: minimum passive dwell time
2590 * @passive_max: maximum passive dwell time
2591 *
2592 * Return: none
2593 */
2594static void hdd_extscan_update_dwell_time_limits(
2595 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2596 uint32_t active_min, uint32_t active_max,
2597 uint32_t passive_min, uint32_t passive_max)
2598{
2599 /* update per-bucket dwell times */
2600 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2601 active_min) {
2602 req_msg->buckets[bkt_idx].min_dwell_time_active =
2603 active_min;
2604 }
2605 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2606 active_max) {
2607 req_msg->buckets[bkt_idx].max_dwell_time_active =
2608 active_max;
2609 }
2610 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2611 passive_min) {
2612 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2613 passive_min;
2614 }
2615 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2616 passive_max) {
2617 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2618 passive_max;
2619 }
2620 /* update dwell-time across all buckets */
2621 if (req_msg->min_dwell_time_active >
2622 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2623 req_msg->min_dwell_time_active =
2624 req_msg->buckets[bkt_idx].min_dwell_time_active;
2625 }
2626 if (req_msg->max_dwell_time_active <
2627 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2628 req_msg->max_dwell_time_active =
2629 req_msg->buckets[bkt_idx].max_dwell_time_active;
2630 }
2631 if (req_msg->min_dwell_time_passive >
2632 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2633 req_msg->min_dwell_time_passive =
2634 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2635 }
2636 if (req_msg->max_dwell_time_passive >
2637 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2638 req_msg->max_dwell_time_passive =
2639 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2640 }
2641}
2642
2643/**
2644 * hdd_extscan_channel_max_reached() - channel max reached
2645 * @req: extscan request structure
2646 * @total_channels: total number of channels
2647 *
2648 * Return: true if total channels reached max, false otherwise
2649 */
2650static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2651 uint8_t total_channels)
2652{
2653 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2654 hdd_warn(
2655 "max #of channels %d reached, take only first %d bucket(s)",
2656 total_channels, req->numBuckets);
2657 return true;
2658 }
2659 return false;
2660}
2661
2662/**
2663 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2664 * @hdd_ctx: HDD global context
2665 * @req_msg: Pointer to request structure
2666 * @tb: pointer to NL attributes
2667 *
2668 * Return: 0 on success; error number otherwise
2669 */
2670static int hdd_extscan_start_fill_bucket_channel_spec(
Jeff Johnson9755a512017-08-28 12:01:57 -07002671 struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 tpSirWifiScanCmdReqParams req_msg,
2673 struct nlattr **tb)
2674{
2675 struct nlattr *bucket[
2676 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2677 struct nlattr *channel[
2678 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2679 struct nlattr *buckets;
2680 struct nlattr *channels;
2681 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302682 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 uint8_t bkt_index, j, num_channels, total_channels = 0;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002684 uint32_t expected_buckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2686
2687 uint32_t min_dwell_time_active_bucket =
2688 hdd_ctx->config->extscan_active_max_chn_time;
2689 uint32_t max_dwell_time_active_bucket =
2690 hdd_ctx->config->extscan_active_max_chn_time;
2691 uint32_t min_dwell_time_passive_bucket =
2692 hdd_ctx->config->extscan_passive_max_chn_time;
2693 uint32_t max_dwell_time_passive_bucket =
2694 hdd_ctx->config->extscan_passive_max_chn_time;
2695
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 req_msg->min_dwell_time_active =
2697 req_msg->max_dwell_time_active =
2698 hdd_ctx->config->extscan_active_max_chn_time;
2699
2700 req_msg->min_dwell_time_passive =
2701 req_msg->max_dwell_time_passive =
2702 hdd_ctx->config->extscan_passive_max_chn_time;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002703
2704 expected_buckets = req_msg->numBuckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705 req_msg->numBuckets = 0;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002706 bkt_index = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002707
2708 nla_for_each_nested(buckets,
2709 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002710
2711 if (bkt_index >= expected_buckets) {
2712 hdd_warn("ignoring excess buckets");
2713 break;
2714 }
2715
Dustin Brown4ea21db2018-01-05 14:13:17 -08002716 if (wlan_cfg80211_nla_parse(bucket,
Dustin Brown3fb15042017-08-15 15:54:49 -07002717 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2718 nla_data(buckets), nla_len(buckets),
2719 wlan_hdd_extscan_config_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08002720 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 return -EINVAL;
2722 }
2723
2724 /* Parse and fetch bucket spec */
2725 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002726 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727 return -EINVAL;
2728 }
2729 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2730 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731
2732 /* Parse and fetch wifi band */
2733 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002734 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002735 return -EINVAL;
2736 }
2737 req_msg->buckets[bkt_index].band = nla_get_u8(
2738 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002739
2740 /* Parse and fetch period */
2741 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002742 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 return -EINVAL;
2744 }
2745 req_msg->buckets[bkt_index].period = nla_get_u32(
2746 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747
2748 /* Parse and fetch report events */
2749 if (!bucket[
2750 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002751 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002752 return -EINVAL;
2753 }
2754 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2755 bucket[
2756 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002757
2758 /* Parse and fetch max period */
2759 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002760 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 return -EINVAL;
2762 }
2763 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2764 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002765
Mukul Sharmafa937be2016-08-12 18:13:36 +05302766 /* Parse and fetch base */
2767 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]) {
2768 hdd_err("attr base failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 return -EINVAL;
2770 }
2771 req_msg->buckets[bkt_index].exponent = nla_get_u32(
Mukul Sharmafa937be2016-08-12 18:13:36 +05302772 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773
2774 /* Parse and fetch step count */
2775 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002776 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 return -EINVAL;
2778 }
2779 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2780 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002781 hdd_debug("Bucket spec Index: %d Wifi band: %d period: %d report events: %d max period: %u base: %u Step count: %u",
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002782 req_msg->buckets[bkt_index].bucket,
2783 req_msg->buckets[bkt_index].band,
2784 req_msg->buckets[bkt_index].period,
2785 req_msg->buckets[bkt_index].reportEvents,
2786 req_msg->buckets[bkt_index].max_period,
2787 req_msg->buckets[bkt_index].exponent,
2788 req_msg->buckets[bkt_index].step_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002789
2790 /* start with known good values for bucket dwell times */
2791 req_msg->buckets[bkt_index].min_dwell_time_active =
2792 req_msg->buckets[bkt_index].max_dwell_time_active =
2793 hdd_ctx->config->extscan_active_max_chn_time;
2794
2795 req_msg->buckets[bkt_index].min_dwell_time_passive =
2796 req_msg->buckets[bkt_index].max_dwell_time_passive =
2797 hdd_ctx->config->extscan_passive_max_chn_time;
2798
2799 /* Framework shall pass the channel list if the input WiFi band
2800 * is WIFI_BAND_UNSPECIFIED.
2801 * If the input WiFi band is specified (any value other than
2802 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2803 */
2804 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2805 if (hdd_extscan_channel_max_reached(req_msg,
2806 total_channels))
2807 return 0;
2808
2809 num_channels = 0;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002810 hdd_debug("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002811 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2812 req_msg->buckets[bkt_index].band,
2813 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302814 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002815 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002816 status);
2817 return -EINVAL;
2818 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002819 hdd_debug("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 num_channels);
2821
2822 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302823 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824 (WLAN_EXTSCAN_MAX_CHANNELS -
2825 total_channels));
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002826 hdd_debug("Adj Num channels/bucket: %d total_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002827 req_msg->buckets[bkt_index].numChannels,
2828 total_channels);
2829 total_channels +=
2830 req_msg->buckets[bkt_index].numChannels;
2831
2832 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2833 j++) {
2834 req_msg->buckets[bkt_index].channels[j].channel =
2835 chan_list[j];
2836 req_msg->buckets[bkt_index].channels[j].
2837 chnlClass = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002838 if ((wlan_reg_get_channel_state(
2839 hdd_ctx->hdd_pdev,
2840 cds_freq_to_chan(chan_list[j]))) !=
2841 CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002842 req_msg->buckets[bkt_index].channels[j].
2843 passive = 1;
2844 req_msg->buckets[bkt_index].channels[j].
2845 dwellTimeMs =
2846 hdd_ctx->config->
2847 extscan_passive_max_chn_time;
2848 /* reconfigure per-bucket dwell time */
2849 if (min_dwell_time_passive_bucket >
2850 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2851 min_dwell_time_passive_bucket =
2852 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2853 }
2854 if (max_dwell_time_passive_bucket <
2855 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2856 max_dwell_time_passive_bucket =
2857 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2858 }
2859
2860 } else {
2861 req_msg->buckets[bkt_index].channels[j].
2862 passive = 0;
2863 req_msg->buckets[bkt_index].channels[j].
2864 dwellTimeMs =
2865 hdd_ctx->config->extscan_active_max_chn_time;
2866 /* reconfigure per-bucket dwell times */
2867 if (min_dwell_time_active_bucket >
2868 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2869 min_dwell_time_active_bucket =
2870 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2871 }
2872 if (max_dwell_time_active_bucket <
2873 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2874 max_dwell_time_active_bucket =
2875 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2876 }
2877
2878 }
2879
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002880 hdd_debug("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881 req_msg->buckets[bkt_index].channels[j].channel,
2882 req_msg->buckets[bkt_index].channels[j].passive,
2883 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2884 req_msg->buckets[bkt_index].channels[j].chnlClass);
2885 }
2886
2887 hdd_extscan_update_dwell_time_limits(
2888 req_msg, bkt_index,
2889 min_dwell_time_active_bucket,
2890 max_dwell_time_active_bucket,
2891 min_dwell_time_passive_bucket,
2892 max_dwell_time_passive_bucket);
2893
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002894 hdd_debug("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002895 bkt_index,
2896 req_msg->buckets[bkt_index].min_dwell_time_active,
2897 req_msg->buckets[bkt_index].max_dwell_time_active,
2898 req_msg->buckets[bkt_index].min_dwell_time_passive,
2899 req_msg->buckets[bkt_index].max_dwell_time_passive);
2900
2901 bkt_index++;
2902 req_msg->numBuckets++;
2903 continue;
2904 }
2905
2906 /* Parse and fetch number of channels */
2907 if (!bucket[
2908 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002909 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002910 return -EINVAL;
2911 }
2912 req_msg->buckets[bkt_index].numChannels =
2913 nla_get_u32(bucket[
2914 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002915 hdd_debug("before trimming: num channels %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002916 req_msg->buckets[bkt_index].numChannels);
2917
2918 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302919 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002920 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002921 hdd_debug("Num channels/bucket: %d total_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 req_msg->buckets[bkt_index].numChannels,
2923 total_channels);
2924 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
2925 return 0;
2926
2927 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002928 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 return -EINVAL;
2930 }
2931
2932 j = 0;
2933 nla_for_each_nested(channels,
2934 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07002935 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
2936 hdd_extscan_channel_max_reached(req_msg,
2937 total_channels))
2938 break;
2939
Dustin Brown4ea21db2018-01-05 14:13:17 -08002940 if (wlan_cfg80211_nla_parse(channel,
Dustin Brown3fb15042017-08-15 15:54:49 -07002941 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2942 nla_data(channels), nla_len(channels),
2943 wlan_hdd_extscan_config_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08002944 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 return -EINVAL;
2946 }
2947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002948 /* Parse and fetch channel */
2949 if (!channel[
2950 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002951 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002952 return -EINVAL;
2953 }
2954 req_msg->buckets[bkt_index].channels[j].channel =
2955 nla_get_u32(channel[
2956 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002957 hdd_debug("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 req_msg->buckets[bkt_index].channels[j].channel);
2959
2960 /* Parse and fetch dwell time */
2961 if (!channel[
2962 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002963 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002964 return -EINVAL;
2965 }
2966 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2967 nla_get_u32(channel[
2968 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
2969
2970 /* Override dwell time if required */
2971 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
2972 hdd_ctx->config->extscan_active_min_chn_time ||
2973 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
2974 hdd_ctx->config->extscan_active_max_chn_time) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002975 hdd_debug("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
2977
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002978 if ((wlan_reg_get_channel_state(
2979 hdd_ctx->hdd_pdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002980 cds_freq_to_chan(
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002981 req_msg->buckets[bkt_index].
2982 channels[j].channel)))
2983 != CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2985 hdd_ctx->config->extscan_passive_max_chn_time;
2986 } else {
2987 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2988 hdd_ctx->config->extscan_active_max_chn_time;
2989 }
2990 }
2991
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002992 hdd_debug("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002993 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
2994
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002995 if ((wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
2996 cds_freq_to_chan(
2997 req_msg->buckets[bkt_index].
2998 channels[j].channel)))
2999 != CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003000 if (min_dwell_time_passive_bucket >
3001 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3002 min_dwell_time_passive_bucket =
3003 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3004 }
3005 if (max_dwell_time_passive_bucket <
3006 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3007 max_dwell_time_passive_bucket =
3008 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3009 }
3010 } else {
3011 if (min_dwell_time_active_bucket >
3012 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3013 min_dwell_time_active_bucket =
3014 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3015 }
3016 if (max_dwell_time_active_bucket <
3017 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3018 max_dwell_time_active_bucket =
3019 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3020 }
3021 }
3022
3023 /* Parse and fetch channel spec passive */
3024 if (!channel[
3025 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003026 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003027 return -EINVAL;
3028 }
3029 req_msg->buckets[bkt_index].channels[j].passive =
3030 nla_get_u8(channel[
3031 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003032 hdd_debug("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 req_msg->buckets[bkt_index].channels[j].passive);
3034 /* Override scan type if required */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003035 if ((wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3036 cds_freq_to_chan(
3037 req_msg->buckets[bkt_index].
3038 channels[j].channel)))
3039 != CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 req_msg->buckets[bkt_index].channels[j].passive = true;
3041 } else {
3042 req_msg->buckets[bkt_index].channels[j].passive = false;
3043 }
3044 j++;
3045 total_channels++;
3046 }
3047
3048 hdd_extscan_update_dwell_time_limits(
3049 req_msg, bkt_index,
3050 min_dwell_time_active_bucket,
3051 max_dwell_time_active_bucket,
3052 min_dwell_time_passive_bucket,
3053 max_dwell_time_passive_bucket);
3054
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003055 hdd_debug("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003056 bkt_index,
3057 req_msg->buckets[bkt_index].min_dwell_time_active,
3058 req_msg->buckets[bkt_index].max_dwell_time_active,
3059 req_msg->buckets[bkt_index].min_dwell_time_passive,
3060 req_msg->buckets[bkt_index].max_dwell_time_passive);
3061
3062 bkt_index++;
3063 req_msg->numBuckets++;
3064 }
3065
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003066 hdd_debug("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067 req_msg->min_dwell_time_active,
3068 req_msg->max_dwell_time_active,
3069 req_msg->min_dwell_time_passive,
3070 req_msg->max_dwell_time_passive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003071 return 0;
3072}
3073
3074/*
3075 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3076 * @config_flags - [input] configuration flags.
3077 *
3078 * This function maps user space received configuration flags to
3079 * driver representation.
3080 *
3081 * Return: configuration flags
3082 */
3083static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3084{
3085 uint32_t configuration_flags = 0;
3086
3087 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3088 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3089
3090 return configuration_flags;
3091}
3092
3093/*
3094 * define short names for the global vendor params
3095 * used by __wlan_hdd_cfg80211_extscan_start()
3096 */
3097#define PARAM_MAX \
3098 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3099#define PARAM_REQUEST_ID \
3100 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3101#define PARAM_BASE_PERIOD \
3102 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3103#define PARAM_MAX_AP_PER_SCAN \
3104 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3105#define PARAM_RPT_THRHLD_PERCENT \
3106 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3107#define PARAM_RPT_THRHLD_NUM_SCANS \
3108 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3109#define PARAM_NUM_BUCKETS \
3110 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3111#define PARAM_CONFIG_FLAGS \
3112 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3113
3114/**
3115 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3116 * @wiphy: Pointer to wireless phy
3117 * @wdev: Pointer to wireless device
3118 * @data: Pointer to data
3119 * @data_len: Length of @data
3120 *
3121 * Return: 0 on success; error number otherwise
3122 */
3123static int
3124__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3125 struct wireless_dev *wdev,
3126 const void *data,
3127 int data_len)
3128{
3129 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3130 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07003131 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003132 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003133 struct nlattr *tb[PARAM_MAX + 1];
3134 struct hdd_ext_scan_context *context;
3135 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303136 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003137 int retval;
3138 unsigned long rc;
3139
Dustin Brownfdf17c12018-03-14 12:55:34 -07003140 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003141
Anurag Chouhan6d760662016-02-20 16:05:43 +05303142 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003143 hdd_err("Command not allowed in FTM mode");
3144 return -EPERM;
3145 }
3146
Jeff Johnson7058aa82017-10-02 13:29:09 -07003147 if (QDF_NDI_MODE == adapter->device_mode) {
Naveen Rawat1b916572017-09-25 10:54:29 -07003148 hdd_err("Command not allowed for NDI interface");
3149 return -EPERM;
3150 }
3151
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003152 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303153 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003156 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303157 hdd_err("extscan not supported");
3158 return -ENOTSUPP;
3159 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08003160 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len,
3161 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003162 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163 return -EINVAL;
3164 }
3165
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303166 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003168 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169 return -ENOMEM;
3170 }
3171
3172 /* Parse and fetch request Id */
3173 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003174 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 goto fail;
3176 }
3177
3178 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07003179 pReqMsg->sessionId = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180
3181 /* Parse and fetch base period */
3182 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003183 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003184 goto fail;
3185 }
3186 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003187
3188 /* Parse and fetch max AP per scan */
3189 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003190 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003191 goto fail;
3192 }
3193 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194
3195 /* Parse and fetch report threshold percent */
3196 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003197 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 goto fail;
3199 }
3200 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003201
3202 /* Parse and fetch report threshold num scans */
3203 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003204 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003205 goto fail;
3206 }
3207 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003208 hdd_debug("Req Id: %d Session Id: %d Base Period: %d Max AP per Scan: %d Report Threshold percent: %d Report Threshold num scans: %d",
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07003209 pReqMsg->requestId, pReqMsg->sessionId,
3210 pReqMsg->basePeriod, pReqMsg->maxAPperScan,
3211 pReqMsg->report_threshold_percent,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003212 pReqMsg->report_threshold_num_scans);
3213
3214 /* Parse and fetch number of buckets */
3215 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003216 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003217 goto fail;
3218 }
3219 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3220 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3221 hdd_warn("Exceeded MAX number of buckets: %d",
3222 WLAN_EXTSCAN_MAX_BUCKETS);
Jeff Johnsonfae3c522016-11-11 17:57:13 -08003223 num_buckets = WLAN_EXTSCAN_MAX_BUCKETS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003224 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003225 hdd_debug("Input: Number of Buckets %d", num_buckets);
Jeff Johnsonfae3c522016-11-11 17:57:13 -08003226 pReqMsg->numBuckets = num_buckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003227
3228 /* This is optional attribute, if not present set it to 0 */
3229 if (!tb[PARAM_CONFIG_FLAGS])
3230 pReqMsg->configuration_flags = 0;
3231 else
3232 pReqMsg->configuration_flags =
3233 hdd_extscan_map_usr_drv_config_flags(
3234 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3235
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303236 pReqMsg->extscan_adaptive_dwell_mode =
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003237 hdd_ctx->config->extscan_adaptive_dwell_mode;
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303238
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003239 hdd_debug("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 pReqMsg->configuration_flags);
3241
3242 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003243 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244 goto fail;
3245 }
3246
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003247 if (hdd_extscan_start_fill_bucket_channel_spec(hdd_ctx, pReqMsg, tb))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248 goto fail;
3249
3250 context = &ext_scan_context;
3251 spin_lock(&context->context_lock);
3252 INIT_COMPLETION(context->response_event);
3253 context->request_id = request_id = pReqMsg->requestId;
Mukul Sharmafa937be2016-08-12 18:13:36 +05303254 context->buckets_scanned = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003255 spin_unlock(&context->context_lock);
3256
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003257 status = sme_ext_scan_start(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303258 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003259 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003260 goto fail;
3261 }
3262
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003263 hdd_ctx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003264 hdd_debug("Timestamp since boot: %llu",
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003265 hdd_ctx->ext_scan_start_since_boot);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003266
3267 /* request was sent -- wait for the response */
3268 rc = wait_for_completion_timeout(&context->response_event,
3269 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3270
3271 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003272 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003273 retval = -ETIMEDOUT;
3274 } else {
3275 spin_lock(&context->context_lock);
3276 if (context->request_id == request_id)
3277 retval = context->response_status;
3278 else
3279 retval = -EINVAL;
3280 spin_unlock(&context->context_lock);
3281 }
Dustin Browne74003f2018-03-14 12:51:58 -07003282 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003283 return retval;
3284
3285fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303286 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003287 return -EINVAL;
3288}
3289/*
3290 * done with short names for the global vendor params
3291 * used by __wlan_hdd_cfg80211_extscan_start()
3292 */
3293#undef PARAM_MAX
3294#undef PARAM_REQUEST_ID
3295#undef PARAM_BASE_PERIOD
3296#undef PARAMS_MAX_AP_PER_SCAN
3297#undef PARAMS_RPT_THRHLD_PERCENT
3298#undef PARAMS_RPT_THRHLD_NUM_SCANS
3299#undef PARAMS_NUM_BUCKETS
3300#undef PARAM_CONFIG_FLAGS
3301
3302/**
3303 * wlan_hdd_cfg80211_extscan_start() - start extscan
3304 * @wiphy: Pointer to wireless phy.
3305 * @wdev: Pointer to wireless device.
3306 * @data: Pointer to input data.
3307 * @data_len: Length of @data.
3308 *
3309 * Return: 0 on success, negative errno on failure
3310 */
3311int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3312 struct wireless_dev *wdev,
3313 const void *data, int data_len)
3314{
3315 int ret = 0;
3316
3317 cds_ssr_protect(__func__);
3318 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3319 cds_ssr_unprotect(__func__);
3320
3321 return ret;
3322}
3323
3324
3325/*
3326 * define short names for the global vendor params
3327 * used by __wlan_hdd_cfg80211_extscan_stop()
3328 */
3329#define PARAM_MAX \
3330 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3331#define PARAM_REQUEST_ID \
3332 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3333
3334/**
3335 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3336 * @wiphy: Pointer to wireless phy
3337 * @wdev: Pointer to wireless device
3338 * @data: Pointer to data
3339 * @data_len: Data length
3340 *
3341 * Return: none
3342 */
3343static int
3344__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3345 struct wireless_dev *wdev,
3346 const void *data, int data_len)
3347{
3348 tpSirExtScanStopReqParams pReqMsg = NULL;
3349 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07003350 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003351 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 struct nlattr *tb[PARAM_MAX + 1];
3353 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303354 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003355 uint32_t request_id;
3356 int retval;
3357 unsigned long rc;
3358
Dustin Brownfdf17c12018-03-14 12:55:34 -07003359 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360
Anurag Chouhan6d760662016-02-20 16:05:43 +05303361 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362 hdd_err("Command not allowed in FTM mode");
3363 return -EPERM;
3364 }
3365
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003366 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303367 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003368 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003370 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303371 hdd_err("extscan not supported");
3372 return -ENOTSUPP;
3373 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08003374 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len,
3375 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003376 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003377 return -EINVAL;
3378 }
3379
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303380 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003381 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003382 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003383 return -ENOMEM;
3384 }
3385
3386 /* Parse and fetch request Id */
3387 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003388 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003389 goto fail;
3390 }
3391
3392 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07003393 pReqMsg->sessionId = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003394 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003395 pReqMsg->requestId, pReqMsg->sessionId);
3396
3397 context = &ext_scan_context;
3398 spin_lock(&context->context_lock);
3399 INIT_COMPLETION(context->response_event);
3400 context->request_id = request_id = pReqMsg->requestId;
3401 spin_unlock(&context->context_lock);
3402
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003403 status = sme_ext_scan_stop(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303404 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003405 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003406 goto fail;
3407 }
3408
3409 /* request was sent -- wait for the response */
3410 rc = wait_for_completion_timeout(&context->response_event,
3411 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3412
3413 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003414 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003415 retval = -ETIMEDOUT;
3416 } else {
3417 spin_lock(&context->context_lock);
3418 if (context->request_id == request_id)
3419 retval = context->response_status;
3420 else
3421 retval = -EINVAL;
3422 spin_unlock(&context->context_lock);
3423 }
Dustin Browne74003f2018-03-14 12:51:58 -07003424 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 return retval;
3426
3427fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303428 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003429 return -EINVAL;
3430}
3431/*
3432 * done with short names for the global vendor params
3433 * used by wlan_hdd_cfg80211_extscan_stop()
3434 */
3435#undef PARAM_MAX
3436#undef PARAM_REQUEST_ID
3437
3438
3439/**
3440 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3441 * @wiphy: Pointer to wireless phy.
3442 * @wdev: Pointer to wireless device.
3443 * @data: Pointer to input data.
3444 * @data_len: Length of @data.
3445 *
3446 * Return: 0 on success, negative errno on failure
3447 */
3448int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3449 struct wireless_dev *wdev,
3450 const void *data, int data_len)
3451{
3452 int ret = 0;
3453
3454 cds_ssr_protect(__func__);
3455 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3456 cds_ssr_unprotect(__func__);
3457
3458 return ret;
3459}
3460
3461
3462/**
3463 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3464 * @wiphy: Pointer to wireless phy
3465 * @wdev: Pointer to wireless device
3466 * @data: Pointer to data
3467 * @data_len: Data length
3468 *
3469 * Return: none
3470 */
3471static int
3472__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3473 struct wireless_dev
3474 *wdev, const void *data,
3475 int data_len)
3476{
3477 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3478 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07003479 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003480 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003481 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3482 1];
3483 struct hdd_ext_scan_context *context;
3484 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303485 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486 int retval;
3487 unsigned long rc;
3488
Dustin Brownfdf17c12018-03-14 12:55:34 -07003489 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490
Anurag Chouhan6d760662016-02-20 16:05:43 +05303491 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 hdd_err("Command not allowed in FTM mode");
3493 return -EPERM;
3494 }
3495
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003496 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303497 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003499
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003500 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303501 hdd_err("extscan not supported");
3502 return -ENOTSUPP;
3503 }
Dustin Brown4ea21db2018-01-05 14:13:17 -08003504 if (wlan_cfg80211_nla_parse(tb,
3505 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3506 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003507 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003508 return -EINVAL;
3509 }
3510
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303511 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003513 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003514 return -ENOMEM;
3515 }
3516
3517 /* Parse and fetch request Id */
3518 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003519 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 goto fail;
3521 }
3522
3523 pReqMsg->requestId =
3524 nla_get_u32(tb
3525 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07003526 pReqMsg->sessionId = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003527 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528 pReqMsg->requestId, pReqMsg->sessionId);
3529
3530 context = &ext_scan_context;
3531 spin_lock(&context->context_lock);
3532 INIT_COMPLETION(context->response_event);
3533 context->request_id = request_id = pReqMsg->requestId;
3534 spin_unlock(&context->context_lock);
3535
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003536 status = sme_reset_bss_hotlist(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303537 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003538 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003539 goto fail;
3540 }
3541
3542 /* request was sent -- wait for the response */
3543 rc = wait_for_completion_timeout
3544 (&context->response_event,
3545 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3546 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003547 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003548 retval = -ETIMEDOUT;
3549 } else {
3550 spin_lock(&context->context_lock);
3551 if (context->request_id == request_id)
3552 retval = context->response_status;
3553 else
3554 retval = -EINVAL;
3555 spin_unlock(&context->context_lock);
3556 }
Dustin Browne74003f2018-03-14 12:51:58 -07003557 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 return retval;
3559
3560fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303561 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003562 return -EINVAL;
3563}
3564
3565/**
3566 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3567 * @wiphy: Pointer to wireless phy
3568 * @wdev: Pointer to wireless device
3569 * @data: Pointer to data
3570 * @data_len: Data length
3571 *
3572 * Return: 0 on success, negative errno on failure
3573 */
3574int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3575 struct wireless_dev *wdev,
3576 const void *data, int data_len)
3577{
3578 int ret = 0;
3579
3580 cds_ssr_protect(__func__);
3581 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3582 data, data_len);
3583 cds_ssr_unprotect(__func__);
3584
3585 return ret;
3586}
3587
3588/**
3589 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3590 * reset significant change
3591 * @wiphy: Pointer to wireless phy
3592 * @wdev: Pointer to wireless device
3593 * @data: Pointer to data
3594 * @data_len: Data length
3595 *
3596 * Return: none
3597 */
3598static int
3599__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3600 *wiphy,
3601 struct
3602 wireless_dev
3603 *wdev, const void *data,
3604 int data_len)
3605{
3606 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3607 struct net_device *dev = wdev->netdev;
Jeff Johnson7058aa82017-10-02 13:29:09 -07003608 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003609 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003610 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3611 1];
3612 struct hdd_ext_scan_context *context;
3613 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303614 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003615 int retval;
3616 unsigned long rc;
3617
Dustin Brownfdf17c12018-03-14 12:55:34 -07003618 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003619
Anurag Chouhan6d760662016-02-20 16:05:43 +05303620 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003621 hdd_err("Command not allowed in FTM mode");
3622 return -EPERM;
3623 }
3624
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003625 retval = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303626 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003627 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003628
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003629 if (!hdd_ctx->config->extscan_enabled) {
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303630 hdd_err("extscan not supported");
3631 return -ENOTSUPP;
3632 }
Dustin Brown3fb15042017-08-15 15:54:49 -07003633
Dustin Brown4ea21db2018-01-05 14:13:17 -08003634 if (wlan_cfg80211_nla_parse(tb,
3635 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3636 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003637 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638 return -EINVAL;
3639 }
3640
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303641 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003643 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003644 return -ENOMEM;
3645 }
3646
3647 /* Parse and fetch request Id */
3648 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003649 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 goto fail;
3651 }
3652
3653 pReqMsg->requestId =
3654 nla_get_u32(tb
3655 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07003656 pReqMsg->sessionId = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003657 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003658 pReqMsg->requestId, pReqMsg->sessionId);
3659
3660 context = &ext_scan_context;
3661 spin_lock(&context->context_lock);
3662 INIT_COMPLETION(context->response_event);
3663 context->request_id = request_id = pReqMsg->requestId;
3664 spin_unlock(&context->context_lock);
3665
Jeff Johnsonc6dda512017-09-03 09:17:05 -07003666 status = sme_reset_significant_change(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303667 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003668 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003669 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303670 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003671 return -EINVAL;
3672 }
3673
3674 /* request was sent -- wait for the response */
3675 rc = wait_for_completion_timeout(&context->response_event,
3676 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3677
3678 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003679 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003680 retval = -ETIMEDOUT;
3681 } else {
3682 spin_lock(&context->context_lock);
3683 if (context->request_id == request_id)
3684 retval = context->response_status;
3685 else
3686 retval = -EINVAL;
3687 spin_unlock(&context->context_lock);
3688 }
Dustin Browne74003f2018-03-14 12:51:58 -07003689 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003690 return retval;
3691
3692fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303693 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003694 return -EINVAL;
3695}
3696
3697/**
3698 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3699 * change
3700 * @wiphy: Pointer to wireless phy
3701 * @wdev: Pointer to wireless device
3702 * @data: Pointer to data
3703 * @data_len: Data length
3704 *
3705 * Return: 0 on success, negative errno on failure
3706 */
3707int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3708 struct wireless_dev *wdev,
3709 const void *data, int data_len)
3710{
3711 int ret = 0;
3712
3713 cds_ssr_protect(__func__);
3714 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3715 data, data_len);
3716 cds_ssr_unprotect(__func__);
3717
3718 return ret;
3719}
3720
3721
3722/**
3723 * hdd_extscan_epno_fill_network_list() - epno fill network list
3724 * @hddctx: HDD context
3725 * @req_msg: request message
3726 * @tb: vendor attribute table
3727 *
3728 * This function reads the network block NL vendor attributes from %tb and
3729 * fill in the epno request message.
3730 *
3731 * Return: 0 on success, error number otherwise
3732 */
3733static int hdd_extscan_epno_fill_network_list(
Jeff Johnson9755a512017-08-28 12:01:57 -07003734 struct hdd_context *hddctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735 struct wifi_epno_params *req_msg,
3736 struct nlattr **tb)
3737{
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003738 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003739 struct nlattr *networks;
3740 int rem1, ssid_len;
3741 uint8_t index, *ssid;
Jeff Johnson14305e62016-11-11 17:37:54 -08003742 uint32_t expected_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743
Jeff Johnson14305e62016-11-11 17:37:54 -08003744 expected_networks = req_msg->num_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003745 index = 0;
SaidiReddy Yenugac5332022017-03-28 17:16:48 +05303746
3747 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST]) {
3748 hdd_err("attr networks list failed");
3749 return -EINVAL;
3750 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003751 nla_for_each_nested(networks,
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003752 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3753 rem1) {
Jeff Johnson14305e62016-11-11 17:37:54 -08003754
3755 if (index == expected_networks) {
3756 hdd_warn("ignoring excess networks");
3757 break;
3758 }
3759
Dustin Brown4ea21db2018-01-05 14:13:17 -08003760 if (wlan_cfg80211_nla_parse(network,
3761 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3762 nla_data(networks),
3763 nla_len(networks),
3764 wlan_hdd_pno_config_policy)) {
3765 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003766 return -EINVAL;
3767 }
3768
3769 /* Parse and fetch ssid */
3770 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003771 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003772 return -EINVAL;
3773 }
3774 ssid_len = nla_len(
3775 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3776
Dustin Brown4ea21db2018-01-05 14:13:17 -08003777 /* nla_parse will detect overflow but not underflow */
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003778 if (0 == ssid_len) {
3779 hdd_err("zero ssid length");
3780 return -EINVAL;
3781 }
3782
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 /* Decrement by 1, don't count null character */
3784 ssid_len--;
3785
3786 req_msg->networks[index].ssid.length = ssid_len;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003787 hdd_debug("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303789 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003790 ssid, ssid_len);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003791 hdd_debug("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 req_msg->networks[index].ssid.length,
3793 req_msg->networks[index].ssid.ssId);
3794
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003795 /* Parse and fetch epno flags */
3796 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003797 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 return -EINVAL;
3799 }
3800 req_msg->networks[index].flags = nla_get_u8(
3801 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003802 hdd_debug("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803
3804 /* Parse and fetch auth bit */
3805 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003806 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 return -EINVAL;
3808 }
3809 req_msg->networks[index].auth_bit_field = nla_get_u8(
3810 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003811 hdd_debug("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003812 req_msg->networks[index].auth_bit_field);
3813
3814 index++;
3815 }
Jeff Johnson14305e62016-11-11 17:37:54 -08003816 req_msg->num_networks = index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 return 0;
3818}
3819
3820/**
3821 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3822 * @wiphy: wiphy
3823 * @wdev: pointer to wireless dev
3824 * @data: data pointer
3825 * @data_len: data length
3826 *
3827 * This function reads the NL vendor attributes from %tb and
3828 * fill in the epno request message.
3829 *
3830 * Return: 0 on success, error number otherwise
3831 */
3832static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3833 struct wireless_dev *wdev,
3834 const void *data,
3835 int data_len)
3836{
3837 struct wifi_epno_params *req_msg = NULL;
3838 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07003839 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07003840 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003841 struct nlattr *tb[
3842 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303843 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003844 uint32_t num_networks, len;
3845 int ret_val;
3846
Dustin Brownfdf17c12018-03-14 12:55:34 -07003847 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003848
3849 ret_val = wlan_hdd_validate_context(hdd_ctx);
3850 if (ret_val)
3851 return ret_val;
3852
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303853 if (!hdd_ctx->config->extscan_enabled) {
3854 hdd_err("extscan not supported");
3855 return -ENOTSUPP;
3856 }
Dustin Brown3fb15042017-08-15 15:54:49 -07003857
Anurag Chouhan6d760662016-02-20 16:05:43 +05303858 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003859 hdd_err("Command not allowed in FTM mode");
3860 return -EPERM;
3861 }
3862
Dustin Brown4ea21db2018-01-05 14:13:17 -08003863 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data,
3864 data_len, wlan_hdd_pno_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003865 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003866 return -EINVAL;
3867 }
3868
3869 /* Parse and fetch number of networks */
3870 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003871 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003872 return -EINVAL;
3873 }
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303874
3875 /*
3876 * num_networks is also used as EPNO SET/RESET request.
3877 * if num_networks is zero then it is treated as RESET.
3878 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 num_networks = nla_get_u32(
3880 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003881
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303882 if (num_networks > MAX_EPNO_NETWORKS) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003883 hdd_debug("num of nw: %d exceeded max: %d, resetting to: %d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303884 num_networks, MAX_EPNO_NETWORKS, MAX_EPNO_NETWORKS);
3885 num_networks = MAX_EPNO_NETWORKS;
3886 }
3887
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003888 hdd_debug("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003889 len = sizeof(*req_msg) +
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303890 (num_networks * sizeof(struct wifi_epno_network));
3891
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303892 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003894 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003895 return -ENOMEM;
3896 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897 req_msg->num_networks = num_networks;
3898
3899 /* Parse and fetch request Id */
Ashish Kumar Dhanotiya1f6df4d2017-08-21 14:07:23 +05303900 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003901 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902 goto fail;
3903 }
3904 req_msg->request_id = nla_get_u32(
Ashish Kumar Dhanotiya1f6df4d2017-08-21 14:07:23 +05303905 tb[QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003906 hdd_debug("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907
Jeff Johnson1b780e42017-10-31 14:11:45 -07003908 req_msg->session_id = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003909 hdd_debug("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003910
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303911 if (num_networks) {
3912
3913 /* Parse and fetch min_5ghz_rssi */
3914 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]) {
3915 hdd_err("min_5ghz_rssi id failed");
3916 goto fail;
3917 }
3918 req_msg->min_5ghz_rssi = nla_get_u32(
3919 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]);
3920
3921 /* Parse and fetch min_24ghz_rssi */
3922 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]) {
3923 hdd_err("min_24ghz_rssi id failed");
3924 goto fail;
3925 }
3926 req_msg->min_24ghz_rssi = nla_get_u32(
3927 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]);
3928
3929 /* Parse and fetch initial_score_max */
3930 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]) {
3931 hdd_err("initial_score_max id failed");
3932 goto fail;
3933 }
3934 req_msg->initial_score_max = nla_get_u32(
3935 tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]);
3936
3937 /* Parse and fetch current_connection_bonus */
3938 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]) {
3939 hdd_err("current_connection_bonus id failed");
3940 goto fail;
3941 }
3942 req_msg->current_connection_bonus = nla_get_u32(
3943 tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]
3944 );
3945
3946 /* Parse and fetch same_network_bonus */
3947 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]) {
3948 hdd_err("same_network_bonus id failed");
3949 goto fail;
3950 }
3951 req_msg->same_network_bonus = nla_get_u32(
3952 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]);
3953
3954 /* Parse and fetch secure_bonus */
3955 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]) {
3956 hdd_err("secure_bonus id failed");
3957 goto fail;
3958 }
3959 req_msg->secure_bonus = nla_get_u32(
3960 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]);
3961
3962 /* Parse and fetch band_5ghz_bonus */
3963 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]) {
3964 hdd_err("band_5ghz_bonus id failed");
3965 goto fail;
3966 }
3967 req_msg->band_5ghz_bonus = nla_get_u32(
3968 tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]);
3969
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003970 hdd_debug("min_5ghz_rssi: %d min_24ghz_rssi: %d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303971 req_msg->min_5ghz_rssi,
3972 req_msg->min_24ghz_rssi);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003973 hdd_debug("initial_score_max: %d current_connection_bonus:%d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303974 req_msg->initial_score_max,
3975 req_msg->current_connection_bonus);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003976 hdd_debug("Bonuses same_network: %d secure: %d band_5ghz: %d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303977 req_msg->same_network_bonus,
3978 req_msg->secure_bonus,
3979 req_msg->band_5ghz_bonus);
3980
3981 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
3982 goto fail;
3983
3984 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003985
3986 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303987 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003988 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003989 goto fail;
3990 }
3991
Dustin Browne74003f2018-03-14 12:51:58 -07003992 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303993 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994 return 0;
3995
3996fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303997 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998 return -EINVAL;
3999}
4000
Jeff Johnson9dc96a02017-01-12 09:47:56 -08004001/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004002 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
4003 * @wiphy: wiphy
4004 * @wdev: pointer to wireless dev
4005 * @data: data pointer
4006 * @data_len: data length
4007 *
4008 * This function reads the NL vendor attributes from %tb and
4009 * fill in the epno request message.
4010 *
4011 * Return: 0 on success, error number otherwise
4012 */
4013int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
4014 struct wireless_dev *wdev,
4015 const void *data,
4016 int data_len)
4017{
4018 int ret;
4019
4020 cds_ssr_protect(__func__);
4021 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
4022 data, data_len);
4023 cds_ssr_unprotect(__func__);
4024
4025 return ret;
4026}
4027
4028/**
4029 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
4030 * @hddctx: HDD context
4031 * @req_msg: request message
4032 * @tb: vendor attribute table
4033 *
4034 * This function reads the network block NL vendor attributes from %tb and
4035 * fill in the passpoint request message.
4036 *
4037 * Return: 0 on success, error number otherwise
4038 */
4039static int hdd_extscan_passpoint_fill_network_list(
Jeff Johnson9755a512017-08-28 12:01:57 -07004040 struct hdd_context *hddctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041 struct wifi_passpoint_req *req_msg,
4042 struct nlattr **tb)
4043{
4044 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
4045 struct nlattr *networks;
4046 int rem1, len;
4047 uint8_t index;
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004048 uint32_t expected_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004050 expected_networks = req_msg->num_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051 index = 0;
SaidiReddy Yenuga8c85acb2017-03-28 17:23:55 +05304052
4053 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY]) {
4054 hdd_err("attr network array failed");
4055 return -EINVAL;
4056 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 nla_for_each_nested(networks,
4058 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
4059 rem1) {
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004060
4061 if (index == expected_networks) {
4062 hdd_warn("ignoring excess networks");
4063 break;
4064 }
4065
Dustin Brown4ea21db2018-01-05 14:13:17 -08004066 if (wlan_cfg80211_nla_parse(network,
4067 QCA_WLAN_VENDOR_ATTR_PNO_MAX,
4068 nla_data(networks),
4069 nla_len(networks),
4070 wlan_hdd_pno_config_policy)) {
4071 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004072 return -EINVAL;
4073 }
4074
4075 /* Parse and fetch identifier */
4076 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004077 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078 return -EINVAL;
4079 }
4080 req_msg->networks[index].id = nla_get_u32(
4081 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004082 hdd_debug("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004083
4084 /* Parse and fetch realm */
4085 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004086 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004087 return -EINVAL;
4088 }
4089 len = nla_len(
4090 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
4091 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004092 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004093 return -EINVAL;
4094 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304095 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004096 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
4097 len);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004098 hdd_debug("realm len %d", len);
4099 hdd_debug("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004100
4101 /* Parse and fetch roaming consortium ids */
4102 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004103 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004104 return -EINVAL;
4105 }
4106 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
4107 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
4108 sizeof(req_msg->networks[0].roaming_consortium_ids));
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004109 hdd_debug("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004110
4111 /* Parse and fetch plmn */
4112 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004113 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004114 return -EINVAL;
4115 }
4116 nla_memcpy(&req_msg->networks[index].plmn,
4117 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
4118 SIR_PASSPOINT_PLMN_LEN);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004119 hdd_debug("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120 req_msg->networks[index].plmn[0],
4121 req_msg->networks[index].plmn[1],
4122 req_msg->networks[index].plmn[2]);
4123
4124 index++;
4125 }
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004126 req_msg->num_networks = index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127 return 0;
4128}
4129
4130/**
4131 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4132 * @wiphy: wiphy
4133 * @wdev: pointer to wireless dev
4134 * @data: data pointer
4135 * @data_len: data length
4136 *
4137 * This function reads the NL vendor attributes from %tb and
4138 * fill in the passpoint request message.
4139 *
4140 * Return: 0 on success, error number otherwise
4141 */
4142static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4143 struct wireless_dev *wdev,
4144 const void *data,
4145 int data_len)
4146{
4147 struct wifi_passpoint_req *req_msg = NULL;
4148 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07004149 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07004150 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304152 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153 uint32_t num_networks = 0;
4154 int ret;
4155
Dustin Brownfdf17c12018-03-14 12:55:34 -07004156 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157
4158 ret = wlan_hdd_validate_context(hdd_ctx);
4159 if (ret)
4160 return ret;
4161
Anurag Chouhan6d760662016-02-20 16:05:43 +05304162 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 hdd_err("Command not allowed in FTM mode");
4164 return -EPERM;
4165 }
4166
Dustin Brown4ea21db2018-01-05 14:13:17 -08004167 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data,
4168 data_len, wlan_hdd_pno_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004169 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 return -EINVAL;
4171 }
4172
4173 /* Parse and fetch number of networks */
4174 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004175 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004176 return -EINVAL;
4177 }
4178 num_networks = nla_get_u32(
4179 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson96f93a32016-11-18 11:02:24 -08004180 if (num_networks > SIR_PASSPOINT_LIST_MAX_NETWORKS) {
4181 hdd_err("num networks %u exceeds max %u",
4182 num_networks, SIR_PASSPOINT_LIST_MAX_NETWORKS);
4183 return -EINVAL;
4184 }
4185
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004186 hdd_debug("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304188 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004189 (num_networks * sizeof(req_msg->networks[0])));
4190 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004191 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192 return -ENOMEM;
4193 }
4194 req_msg->num_networks = num_networks;
4195
4196 /* Parse and fetch request Id */
4197 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004198 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004199 goto fail;
4200 }
4201 req_msg->request_id = nla_get_u32(
4202 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4203
Jeff Johnson1b780e42017-10-31 14:11:45 -07004204 req_msg->session_id = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004205 hdd_debug("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004206 req_msg->session_id);
4207
4208 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4209 goto fail;
4210
4211 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304212 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004213 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004214 goto fail;
4215 }
4216
Dustin Browne74003f2018-03-14 12:51:58 -07004217 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304218 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219 return 0;
4220
4221fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304222 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004223 return -EINVAL;
4224}
4225
4226/**
4227 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4228 * @wiphy: wiphy
4229 * @wdev: pointer to wireless dev
4230 * @data: data pointer
4231 * @data_len: data length
4232 *
4233 * This function reads the NL vendor attributes from %tb and
4234 * fill in the passpoint request message.
4235 *
4236 * Return: 0 on success, error number otherwise
4237 */
4238int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4239 struct wireless_dev *wdev,
4240 const void *data,
4241 int data_len)
4242{
4243 int ret;
4244
4245 cds_ssr_protect(__func__);
4246 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4247 data, data_len);
4248 cds_ssr_unprotect(__func__);
4249
4250 return ret;
4251}
4252
4253/**
4254 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4255 * @wiphy: wiphy
4256 * @wdev: pointer to wireless dev
4257 * @data: data pointer
4258 * @data_len: data length
4259 *
4260 * This function resets passpoint networks list
4261 *
4262 * Return: 0 on success, error number otherwise
4263 */
4264static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4265 struct wireless_dev *wdev,
4266 const void *data,
4267 int data_len)
4268{
4269 struct wifi_passpoint_req *req_msg = NULL;
4270 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07004271 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07004272 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004273 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304274 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275 int ret;
4276
Dustin Brownfdf17c12018-03-14 12:55:34 -07004277 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004278
4279 ret = wlan_hdd_validate_context(hdd_ctx);
4280 if (ret)
4281 return ret;
4282
Anurag Chouhan6d760662016-02-20 16:05:43 +05304283 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 hdd_err("Command not allowed in FTM mode");
4285 return -EPERM;
4286 }
4287
Dustin Brown4ea21db2018-01-05 14:13:17 -08004288 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data,
4289 data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004290 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004291 return -EINVAL;
4292 }
4293
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304294 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004295 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004296 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004297 return -ENOMEM;
4298 }
4299
4300 /* Parse and fetch request Id */
4301 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004302 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 goto fail;
4304 }
4305 req_msg->request_id = nla_get_u32(
4306 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4307
Jeff Johnson1b780e42017-10-31 14:11:45 -07004308 req_msg->session_id = adapter->session_id;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004309 hdd_debug("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004310 req_msg->request_id, req_msg->session_id);
4311
4312 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304313 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004314 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004315 goto fail;
4316 }
4317
Dustin Browne74003f2018-03-14 12:51:58 -07004318 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304319 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004320 return 0;
4321
4322fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304323 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 return -EINVAL;
4325}
4326
4327/**
4328 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4329 * @wiphy: wiphy
4330 * @wdev: pointer to wireless dev
4331 * @data: data pointer
4332 * @data_len: data length
4333 *
4334 * This function resets passpoint networks list
4335 *
4336 * Return: 0 on success, error number otherwise
4337 */
4338int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4339 struct wireless_dev *wdev,
4340 const void *data,
4341 int data_len)
4342{
4343 int ret;
4344
4345 cds_ssr_protect(__func__);
4346 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4347 data, data_len);
4348 cds_ssr_unprotect(__func__);
4349
4350 return ret;
4351}
4352
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353/**
4354 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4355 * @hdd_ctx: Global HDD context
4356 *
4357 * Return: none
4358 */
4359#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
Jeff Johnsonc6dda512017-09-03 09:17:05 -07004360static inline void wlan_hdd_init_completion_extwow(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004361{
Jeff Johnsonc6dda512017-09-03 09:17:05 -07004362 init_completion(&hdd_ctx->ready_to_extwow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363}
4364#else
Jeff Johnsonc6dda512017-09-03 09:17:05 -07004365static inline void wlan_hdd_init_completion_extwow(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004366{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367}
4368#endif
4369
4370/**
4371 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4372 * @hdd_ctx: Global HDD context
4373 *
4374 * Return: none
4375 */
Jeff Johnson9755a512017-08-28 12:01:57 -07004376void wlan_hdd_cfg80211_extscan_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377{
4378 wlan_hdd_init_completion_extwow(hdd_ctx);
4379 init_completion(&ext_scan_context.response_event);
4380 spin_lock_init(&ext_scan_context.context_lock);
4381}
4382
4383#endif /* FEATURE_WLAN_EXTSCAN */