blob: 3c75082b7fbe6a822a4423db2b66c38fd298cf30 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Jeff Johnson9dc96a02017-01-12 09:47:56 -08002 * Copyright (c) 2012-2017 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 },
Jeff Johnsonfa484bb2016-11-09 09:01:10 -0800183};
184
185static const struct nla_policy
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186wlan_hdd_extscan_results_policy[QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_MAX + 1] = {
187 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD] = {
188 .type = NLA_U16},
189 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY] = {
190 .type = NLA_U16},
191};
192
193/**
194 * wlan_hdd_cfg80211_extscan_get_capabilities_rsp() - response from target
195 * @ctx: Pointer to hdd context
196 * @data: Pointer to ext scan capabilities response from fw
197 *
198 * Return: None
199 */
200static void
201wlan_hdd_cfg80211_extscan_get_capabilities_rsp(void *ctx,
202 struct ext_scan_capabilities_response *data)
203{
204 struct hdd_ext_scan_context *context;
Jeff Johnson9755a512017-08-28 12:01:57 -0700205 struct hdd_context *hdd_ctx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206
207 ENTER();
208
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530209 if (wlan_hdd_validate_context(hdd_ctx))
210 return;
211 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700212 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 return;
214 }
215
216 context = &ext_scan_context;
217
218 spin_lock(&context->context_lock);
219 /* validate response received from target*/
220 if (context->request_id != data->requestId) {
221 spin_unlock(&context->context_lock);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800222 hdd_err("Target response id did not match. request_id: %d response_id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800223 context->request_id, data->requestId);
224 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 }
226
Jeff Johnson68755312017-02-10 11:46:55 -0800227 context->capability_response = *data;
228 complete(&context->response_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 spin_unlock(&context->context_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800230}
231
232/*
233 * define short names for the global vendor params
234 * used by hdd_extscan_nl_fill_bss()
235 */
236#define PARAM_TIME_STAMP \
237 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP
238#define PARAM_SSID \
239 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID
240#define PARAM_BSSID \
241 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID
242#define PARAM_CHANNEL \
243 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL
244#define PARAM_RSSI \
245 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI
246#define PARAM_RTT \
247 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT
248#define PARAM_RTT_SD \
249 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD
250#define PARAM_BEACON_PERIOD \
251 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD
252#define PARAM_CAPABILITY \
253 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY
254#define PARAM_IE_LENGTH \
255 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH
256#define PARAM_IE_DATA \
257 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA
258
259/** hdd_extscan_nl_fill_bss() - extscan nl fill bss
260 * @skb: socket buffer
261 * @ap: bss information
262 * @idx: nesting index
263 *
264 * Return: 0 on success; error number otherwise
265 */
266static int hdd_extscan_nl_fill_bss(struct sk_buff *skb, tSirWifiScanResult *ap,
267 int idx)
268{
269 struct nlattr *nla_ap;
270
271 nla_ap = nla_nest_start(skb, idx);
272 if (!nla_ap)
273 return -EINVAL;
274
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700275 if (hdd_wlan_nla_put_u64(skb, PARAM_TIME_STAMP, ap->ts) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 nla_put(skb, PARAM_SSID, sizeof(ap->ssid), ap->ssid) ||
277 nla_put(skb, PARAM_BSSID, sizeof(ap->bssid), ap->bssid.bytes) ||
278 nla_put_u32(skb, PARAM_CHANNEL, ap->channel) ||
279 nla_put_s32(skb, PARAM_RSSI, ap->rssi) ||
280 nla_put_u32(skb, PARAM_RTT, ap->rtt) ||
281 nla_put_u32(skb, PARAM_RTT_SD, ap->rtt_sd) ||
282 nla_put_u16(skb, PARAM_BEACON_PERIOD, ap->beaconPeriod) ||
283 nla_put_u16(skb, PARAM_CAPABILITY, ap->capability) ||
284 nla_put_u16(skb, PARAM_IE_LENGTH, ap->ieLength)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700285 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 return -EINVAL;
287 }
288
289 if (ap->ieLength)
290 if (nla_put(skb, PARAM_IE_DATA, ap->ieLength, ap->ieData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700291 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800292 return -EINVAL;
293 }
294
295 nla_nest_end(skb, nla_ap);
296
297 return 0;
298}
299/*
300 * done with short names for the global vendor params
301 * used by hdd_extscan_nl_fill_bss()
302 */
303#undef PARAM_TIME_STAMP
304#undef PARAM_SSID
305#undef PARAM_BSSID
306#undef PARAM_CHANNEL
307#undef PARAM_RSSI
308#undef PARAM_RTT
309#undef PARAM_RTT_SD
310#undef PARAM_BEACON_PERIOD
311#undef PARAM_CAPABILITY
312#undef PARAM_IE_LENGTH
313#undef PARAM_IE_DATA
314
315/** wlan_hdd_cfg80211_extscan_cached_results_ind() - get cached results
316 * @ctx: hdd global context
317 * @data: cached results
318 *
319 * This function reads the cached results %data, populated the NL
320 * attributes and sends the NL event to the upper layer.
321 *
322 * Return: none
323 */
324static void
325wlan_hdd_cfg80211_extscan_cached_results_ind(void *ctx,
326 struct extscan_cached_scan_results *data)
327{
Jeff Johnson9755a512017-08-28 12:01:57 -0700328 struct hdd_context *pHddCtx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800329 struct sk_buff *skb = NULL;
330 struct hdd_ext_scan_context *context;
331 struct extscan_cached_scan_result *result;
332 tSirWifiScanResult *ap;
333 uint32_t i, j, nl_buf_len;
334 bool ignore_cached_results = false;
335
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700336 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800337
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530338 if (wlan_hdd_validate_context(pHddCtx))
339 return;
340 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700341 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800342 return;
343 }
344
345 context = &ext_scan_context;
346 spin_lock(&context->context_lock);
347 ignore_cached_results = context->ignore_cached_results;
348 spin_unlock(&context->context_lock);
349
350 if (ignore_cached_results) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700351 hdd_err("Ignore the cached results received after timeout");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800352 return;
353 }
354
355#define EXTSCAN_CACHED_NEST_HDRLEN NLA_HDRLEN
356#define EXTSCAN_CACHED_NL_FIXED_TLV \
357 ((sizeof(data->request_id) + NLA_HDRLEN) + \
358 (sizeof(data->num_scan_ids) + NLA_HDRLEN) + \
359 (sizeof(data->more_data) + NLA_HDRLEN))
360#define EXTSCAN_CACHED_NL_SCAN_ID_TLV \
361 ((sizeof(result->scan_id) + NLA_HDRLEN) + \
362 (sizeof(result->flags) + NLA_HDRLEN) + \
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530363 (sizeof(result->num_results) + NLA_HDRLEN))+ \
364 (sizeof(result->buckets_scanned) + NLA_HDRLEN)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365#define EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV \
366 ((sizeof(ap->ts) + NLA_HDRLEN) + \
367 (sizeof(ap->ssid) + NLA_HDRLEN) + \
368 (sizeof(ap->bssid) + NLA_HDRLEN) + \
369 (sizeof(ap->channel) + NLA_HDRLEN) + \
370 (sizeof(ap->rssi) + NLA_HDRLEN) + \
371 (sizeof(ap->rtt) + NLA_HDRLEN) + \
372 (sizeof(ap->rtt_sd) + NLA_HDRLEN) + \
373 (sizeof(ap->beaconPeriod) + NLA_HDRLEN) + \
374 (sizeof(ap->capability) + NLA_HDRLEN) + \
375 (sizeof(ap->ieLength) + NLA_HDRLEN))
376#define EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV \
377 (ap->ieLength + NLA_HDRLEN)
378
379 nl_buf_len = NLMSG_HDRLEN;
380 nl_buf_len += EXTSCAN_CACHED_NL_FIXED_TLV;
381 if (data->num_scan_ids) {
382 nl_buf_len += sizeof(result->scan_id) + NLA_HDRLEN;
383 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
384 result = &data->result[0];
385 for (i = 0; i < data->num_scan_ids; i++) {
386 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
387 nl_buf_len += EXTSCAN_CACHED_NL_SCAN_ID_TLV;
388 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
389
390 ap = &result->ap[0];
391 for (j = 0; j < result->num_results; j++) {
392 nl_buf_len += EXTSCAN_CACHED_NEST_HDRLEN;
393 nl_buf_len +=
394 EXTSCAN_CACHED_NL_SCAN_RESULTS_TLV;
395 if (ap->ieLength)
396 nl_buf_len +=
397 EXTSCAN_CACHED_NL_SCAN_RESULTS_IE_DATA_TLV;
398 ap++;
399 }
400 result++;
401 }
402 }
403
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800404 skb = cfg80211_vendor_cmd_alloc_reply_skb(pHddCtx->wiphy, nl_buf_len);
405
406 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700407 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 goto fail;
409 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800410 hdd_debug("Req Id %u Num_scan_ids %u More Data %u",
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530411 data->request_id, data->num_scan_ids, data->more_data);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412
413 result = &data->result[0];
414 for (i = 0; i < data->num_scan_ids; i++) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800415 hdd_debug("[i=%d] scan_id %u flags %u num_results %u buckets scanned %u",
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530416 i, result->scan_id, result->flags, result->num_results,
417 result->buckets_scanned);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418
419 ap = &result->ap[0];
420 for (j = 0; j < result->num_results; j++) {
421 /*
422 * Firmware returns timestamp from ext scan start till
423 * BSSID was cached (in micro seconds). Add this with
424 * time gap between system boot up to ext scan start
425 * to derive the time since boot when the
426 * BSSID was cached.
427 */
428 ap->ts += pHddCtx->ext_scan_start_since_boot;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800429 hdd_debug("Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800430 "Ssid: %s "
431 "Bssid (" MAC_ADDRESS_STR ") "
432 "Channel %u "
433 "Rssi %d "
434 "RTT %u "
435 "RTT_SD %u "
436 "Beacon Period %u "
437 "Capability 0x%x "
438 "Ie length %d",
439 ap->ts,
440 ap->ssid,
441 MAC_ADDR_ARRAY(ap->bssid.bytes),
442 ap->channel,
443 ap->rssi,
444 ap->rtt,
445 ap->rtt_sd,
446 ap->beaconPeriod,
447 ap->capability,
448 ap->ieLength);
449 ap++;
450 }
451 result++;
452 }
453
454 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
455 data->request_id) ||
456 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530457 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800458 data->num_scan_ids) ||
459 nla_put_u8(skb,
460 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
461 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700462 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800463 goto fail;
464 }
465
466 if (data->num_scan_ids) {
467 struct nlattr *nla_results;
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -0700468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800469 result = &data->result[0];
470
471 if (nla_put_u32(skb,
472 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
473 result->scan_id)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700474 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800475 goto fail;
476 }
477 nla_results = nla_nest_start(skb,
478 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_LIST);
479 if (!nla_results)
480 goto fail;
481
482 for (i = 0; i < data->num_scan_ids; i++) {
483 struct nlattr *nla_result;
484 struct nlattr *nla_aps;
485
486 nla_result = nla_nest_start(skb, i);
487 if (!nla_result)
488 goto fail;
489
490 if (nla_put_u32(skb,
491 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_SCAN_ID,
492 result->scan_id) ||
493 nla_put_u32(skb,
494 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CACHED_RESULTS_FLAGS,
495 result->flags) ||
496 nla_put_u32(skb,
Mukul Sharmafa937be2016-08-12 18:13:36 +0530497 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
Mukul Sharmaf7cb3ab2016-08-12 19:53:52 +0530498 result->buckets_scanned) ||
Mukul Sharmafa937be2016-08-12 18:13:36 +0530499 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530500 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800501 result->num_results)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700502 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800503 goto fail;
504 }
505
506 nla_aps = nla_nest_start(skb,
507 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
508 if (!nla_aps)
509 goto fail;
510
511 ap = &result->ap[0];
512 for (j = 0; j < result->num_results; j++) {
513 if (hdd_extscan_nl_fill_bss(skb, ap, j))
514 goto fail;
515
516 ap++;
517 }
518 nla_nest_end(skb, nla_aps);
519 nla_nest_end(skb, nla_result);
520 result++;
521 }
522 nla_nest_end(skb, nla_results);
523 }
524
525 cfg80211_vendor_cmd_reply(skb);
526
527 if (!data->more_data) {
528 spin_lock(&context->context_lock);
529 context->response_status = 0;
530 complete(&context->response_event);
531 spin_unlock(&context->context_lock);
532 }
533 return;
534
535fail:
536 if (skb)
537 kfree_skb(skb);
538
539 spin_lock(&context->context_lock);
540 context->response_status = -EINVAL;
541 spin_unlock(&context->context_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542}
543
544/**
545 * wlan_hdd_cfg80211_extscan_hotlist_match_ind() - hot list match ind
546 * @ctx: Pointer to hdd context
547 * @pData: Pointer to ext scan result event
548 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800549 * This callback execute in atomic context and must not invoke any
550 * blocking calls.
551 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800552 * Return: none
553 */
554static void
555wlan_hdd_cfg80211_extscan_hotlist_match_ind(void *ctx,
556 struct extscan_hotlist_match *data)
557{
Jeff Johnson9755a512017-08-28 12:01:57 -0700558 struct hdd_context *pHddCtx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 struct sk_buff *skb = NULL;
560 uint32_t i, index;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800561 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562
563 ENTER();
564
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530565 if (wlan_hdd_validate_context(pHddCtx))
566 return;
567 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700568 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569 return;
570 }
571
572 if (data->ap_found)
573 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX;
574 else
575 index = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX;
576
577 skb = cfg80211_vendor_event_alloc(
578 pHddCtx->wiphy,
579 NULL,
580 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800581 index, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700584 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800585 return;
586 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800587 hdd_debug("Req Id: %u Num_APs: %u MoreData: %u ap_found: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588 data->requestId, data->numOfAps, data->moreData,
589 data->ap_found);
590
591 for (i = 0; i < data->numOfAps; i++) {
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530592 data->ap[i].ts = qdf_get_monotonic_boottime();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800594 hdd_debug("[i=%d] Timestamp %llu "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800595 "Ssid: %s "
596 "Bssid (" MAC_ADDRESS_STR ") "
597 "Channel %u "
598 "Rssi %d "
599 "RTT %u "
600 "RTT_SD %u",
601 i,
602 data->ap[i].ts,
603 data->ap[i].ssid,
604 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
605 data->ap[i].channel,
606 data->ap[i].rssi,
607 data->ap[i].rtt, data->ap[i].rtt_sd);
608 }
609
610 if (nla_put_u32(skb,
611 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
612 data->requestId) ||
613 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530614 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800615 data->numOfAps)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700616 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 goto fail;
618 }
619
620 if (data->numOfAps) {
621 struct nlattr *aps;
622
623 aps = nla_nest_start(skb,
624 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
625 if (!aps)
626 goto fail;
627
628 for (i = 0; i < data->numOfAps; i++) {
629 struct nlattr *ap;
630
631 ap = nla_nest_start(skb, i);
632 if (!ap)
633 goto fail;
634
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700635 if (hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
637 data->ap[i].ts) ||
638 nla_put(skb,
639 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
640 sizeof(data->ap[i].ssid),
641 data->ap[i].ssid) ||
642 nla_put(skb,
643 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
644 sizeof(data->ap[i].bssid),
645 data->ap[i].bssid.bytes) ||
646 nla_put_u32(skb,
647 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
648 data->ap[i].channel) ||
649 nla_put_s32(skb,
650 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
651 data->ap[i].rssi) ||
652 nla_put_u32(skb,
653 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
654 data->ap[i].rtt) ||
655 nla_put_u32(skb,
656 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
657 data->ap[i].rtt_sd))
658 goto fail;
659
660 nla_nest_end(skb, ap);
661 }
662 nla_nest_end(skb, aps);
663
664 if (nla_put_u8(skb,
665 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
666 data->moreData))
667 goto fail;
668 }
669
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800670 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530671 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800672 return;
673
674fail:
675 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676}
677
678/**
679 * wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind() -
680 * significant wifi change results indication
681 * @ctx: Pointer to hdd context
682 * @pData: Pointer to signif wifi change event
683 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800684 * This callback execute in atomic context and must not invoke any
685 * blocking calls.
686 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 * Return: none
688 */
689static void
690wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(
691 void *ctx,
692 tpSirWifiSignificantChangeEvent pData)
693{
Jeff Johnson9755a512017-08-28 12:01:57 -0700694 struct hdd_context *pHddCtx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 struct sk_buff *skb = NULL;
696 tSirWifiSignificantChange *ap_info;
697 int32_t *rssi;
698 uint32_t i, j;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800699 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700
701 ENTER();
702
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530703 if (wlan_hdd_validate_context(pHddCtx))
704 return;
705 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700706 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 return;
708 }
709
710 skb = cfg80211_vendor_event_alloc(
711 pHddCtx->wiphy,
712 NULL,
713 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
714 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800715 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716
717 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700718 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 return;
720 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800721 hdd_debug("Req Id %u Num results %u More Data %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 pData->requestId, pData->numResults, pData->moreData);
723
724 ap_info = &pData->ap[0];
725 for (i = 0; i < pData->numResults; i++) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800726 hdd_debug("[i=%d] "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727 "Bssid (" MAC_ADDRESS_STR ") "
728 "Channel %u "
729 "numOfRssi %d",
730 i,
731 MAC_ADDR_ARRAY(ap_info->bssid.bytes),
732 ap_info->channel, ap_info->numOfRssi);
733 rssi = &(ap_info)->rssi[0];
734 for (j = 0; j < ap_info->numOfRssi; j++)
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800735 hdd_debug("Rssi %d", *rssi++);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736
737 ap_info += ap_info->numOfRssi * sizeof(*rssi);
738 }
739
740 if (nla_put_u32(skb,
741 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
742 pData->requestId) ||
743 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530744 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800745 pData->numResults)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700746 hdd_err("put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747 goto fail;
748 }
749
750 if (pData->numResults) {
751 struct nlattr *aps;
752
753 aps = nla_nest_start(skb,
754 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
755 if (!aps)
756 goto fail;
757
758 ap_info = &pData->ap[0];
759 for (i = 0; i < pData->numResults; i++) {
760 struct nlattr *ap;
761
762 ap = nla_nest_start(skb, i);
763 if (!ap)
764 goto fail;
765
766 if (nla_put(skb,
767 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530768 QDF_MAC_ADDR_SIZE, ap_info->bssid.bytes) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 nla_put_u32(skb,
770 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL,
771 ap_info->channel) ||
772 nla_put_u32(skb,
773 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI,
774 ap_info->numOfRssi) ||
775 nla_put(skb,
776 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST,
777 sizeof(s32) * ap_info->numOfRssi,
778 &(ap_info)->rssi[0]))
779 goto fail;
780
781 nla_nest_end(skb, ap);
782
783 ap_info += ap_info->numOfRssi * sizeof(*rssi);
784 }
785 nla_nest_end(skb, aps);
786
787 if (nla_put_u8(skb,
788 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
789 pData->moreData))
790 goto fail;
791 }
792
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800793 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800794 return;
795
796fail:
797 kfree_skb(skb);
798 return;
799
800}
801
802/**
803 * wlan_hdd_cfg80211_extscan_full_scan_result_event() - full scan result event
804 * @ctx: Pointer to hdd context
805 * @pData: Pointer to full scan result event
806 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800807 * This callback execute in atomic context and must not invoke any
808 * blocking calls.
809 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800810 * Return: none
811 */
812static void
813wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx,
814 tpSirWifiFullScanResultEvent
815 pData)
816{
Jeff Johnson9755a512017-08-28 12:01:57 -0700817 struct hdd_context *pHddCtx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800818 struct sk_buff *skb = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 struct timespec ts;
Mukul Sharmafa937be2016-08-12 18:13:36 +0530820 struct hdd_ext_scan_context *context;
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700821
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800822 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -0700824 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530826 if (wlan_hdd_validate_context(pHddCtx))
827 return;
828 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700829 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830 return;
831 }
832
833 if ((sizeof(*pData) + pData->ap.ieLength) >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700834 hdd_err("Frame exceeded NL size limitation, drop it!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835 return;
836 }
837 skb = cfg80211_vendor_event_alloc(
838 pHddCtx->wiphy,
839 NULL,
840 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
841 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800842 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843
844 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700845 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 return;
847 }
848
849 pData->ap.channel = cds_chan_to_freq(pData->ap.channel);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700850
Jeff Johnson9dc96a02017-01-12 09:47:56 -0800851 /*
852 * Android does not want the time stamp from the frame.
853 * Instead it wants a monotonic increasing value since boot
854 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700855 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800856 pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Yuanyuan Liu2e03b412016-04-06 14:36:15 -0700857
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800858 hdd_debug("Req Id %u More Data %u", pData->requestId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859 pData->moreData);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800860 hdd_debug("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861 "Bssid (" MAC_ADDRESS_STR ") "
862 "Channel %u "
863 "Rssi %d "
864 "RTT %u "
865 "RTT_SD %u "
866 "Bcn Period %d "
867 "Capability 0x%X "
868 "IE Length %d",
869 pData->ap.ts,
870 pData->ap.ssid,
871 MAC_ADDR_ARRAY(pData->ap.bssid.bytes),
872 pData->ap.channel,
873 pData->ap.rssi,
874 pData->ap.rtt,
875 pData->ap.rtt_sd,
876 pData->ap.beaconPeriod,
877 pData->ap.capability, pData->ap.ieLength);
878
879 if (nla_put_u32(skb,
880 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
881 pData->requestId) ||
Dustin Brownbb7e2f52016-10-17 12:16:35 -0700882 hdd_wlan_nla_put_u64(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800883 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_TIME_STAMP,
884 pData->ap.ts) ||
885 nla_put(skb,
886 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_SSID,
887 sizeof(pData->ap.ssid),
888 pData->ap.ssid) ||
889 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BSSID,
890 sizeof(pData->ap.bssid),
891 pData->ap.bssid.bytes) ||
892 nla_put_u32(skb,
893 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CHANNEL,
894 pData->ap.channel) ||
895 nla_put_s32(skb,
896 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RSSI,
897 pData->ap.rssi) ||
898 nla_put_u32(skb,
899 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT,
900 pData->ap.rtt) ||
901 nla_put_u32(skb,
902 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_RTT_SD,
903 pData->ap.rtt_sd) ||
904 nla_put_u16(skb,
905 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD,
906 pData->ap.beaconPeriod) ||
907 nla_put_u16(skb,
908 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_CAPABILITY,
909 pData->ap.capability) ||
910 nla_put_u32(skb,
911 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_LENGTH,
912 pData->ap.ieLength) ||
913 nla_put_u8(skb,
914 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
915 pData->moreData)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700916 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 goto nla_put_failure;
918 }
919
920 if (pData->ap.ieLength) {
921 if (nla_put(skb,
922 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_IE_DATA,
923 pData->ap.ieLength, pData->ap.ieData))
924 goto nla_put_failure;
925 }
926
Mukul Sharmafa937be2016-08-12 18:13:36 +0530927 context = &ext_scan_context;
928 spin_lock(&context->context_lock);
929 if (nla_put_u32(skb,
930 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_BUCKETS_SCANNED,
931 context->buckets_scanned)) {
932 spin_unlock(&context->context_lock);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800933 hdd_debug("Failed to include buckets_scanned");
Mukul Sharmafa937be2016-08-12 18:13:36 +0530934 goto nla_put_failure;
935 }
936 spin_unlock(&context->context_lock);
937
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800938 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 return;
940
941nla_put_failure:
942 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943}
944
945/**
946 * wlan_hdd_cfg80211_extscan_scan_res_available_event() - scan result event
947 * @ctx: Pointer to hdd context
948 * @pData: Pointer to scan results available indication param
949 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800950 * This callback execute in atomic context and must not invoke any
951 * blocking calls.
952 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800953 * Return: none
954 */
955static void
956wlan_hdd_cfg80211_extscan_scan_res_available_event(
957 void *ctx,
958 tpSirExtScanResultsAvailableIndParams pData)
959{
Jeff Johnson9755a512017-08-28 12:01:57 -0700960 struct hdd_context *pHddCtx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800961 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800962 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800963
964 ENTER();
965
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530966 if (wlan_hdd_validate_context(pHddCtx))
967 return;
968 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700969 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800970 return;
971 }
972
973 skb = cfg80211_vendor_event_alloc(
974 pHddCtx->wiphy,
975 NULL,
976 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
977 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800978 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800979
980 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700981 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982 return;
983 }
984
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -0800985 hdd_debug("Req Id %u Num results %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800986 pData->requestId, pData->numResultsAvailable);
987 if (nla_put_u32(skb,
988 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
989 pData->requestId) ||
990 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +0530991 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992 pData->numResultsAvailable)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -0700993 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800994 goto nla_put_failure;
995 }
996
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -0800997 cfg80211_vendor_event(skb, flags);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530998 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800999 return;
1000
1001nla_put_failure:
1002 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001003}
1004
1005/**
1006 * wlan_hdd_cfg80211_extscan_scan_progress_event() - scan progress event
1007 * @ctx: Pointer to hdd context
1008 * @pData: Pointer to scan event indication param
1009 *
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001010 * This callback execute in atomic context and must not invoke any
1011 * blocking calls.
1012 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001013 * Return: none
1014 */
1015static void
1016wlan_hdd_cfg80211_extscan_scan_progress_event(void *ctx,
1017 tpSirExtScanOnScanEventIndParams
1018 pData)
1019{
Jeff Johnson9755a512017-08-28 12:01:57 -07001020 struct hdd_context *pHddCtx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001021 struct sk_buff *skb = NULL;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001022 int flags = cds_get_gfp_flags();
Mukul Sharmafa937be2016-08-12 18:13:36 +05301023 struct hdd_ext_scan_context *context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001024
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001025 /* ENTER() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001026
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301027 if (wlan_hdd_validate_context(pHddCtx))
1028 return;
1029 if (!pData) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001030 hdd_err("pData is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 return;
1032 }
1033
1034 skb = cfg80211_vendor_event_alloc(
1035 pHddCtx->wiphy,
1036 NULL,
1037 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1038 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001039 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001040
1041 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001042 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001043 return;
1044 }
Mukul Sharmafa937be2016-08-12 18:13:36 +05301045
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001046 hdd_debug("Request Id: %u Scan event type: %u Scan event status: %u buckets scanned: %u",
Mukul Sharmafa937be2016-08-12 18:13:36 +05301047 pData->requestId, pData->scanEventType, pData->status,
1048 pData->buckets_scanned);
1049
Mukul Sharmafa937be2016-08-12 18:13:36 +05301050 context = &ext_scan_context;
1051 spin_lock(&context->context_lock);
1052 if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT) {
1053 context->buckets_scanned = 0;
1054 pData->scanEventType = WIFI_EXTSCAN_RESULTS_AVAILABLE;
1055 spin_unlock(&context->context_lock);
1056 } else if (pData->scanEventType == WIFI_EXTSCAN_CYCLE_STARTED_EVENT) {
1057 context->buckets_scanned = pData->buckets_scanned;
1058 /* No need to report to user space */
1059 spin_unlock(&context->context_lock);
Mukul Sharma45114d92016-08-12 19:34:14 +05301060 goto nla_put_failure;
Mukul Sharmafa937be2016-08-12 18:13:36 +05301061 } else {
1062 spin_unlock(&context->context_lock);
1063 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001064
1065 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1066 pData->requestId) ||
1067 nla_put_u8(skb,
1068 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_EVENT_TYPE,
Mukul Sharmafa937be2016-08-12 18:13:36 +05301069 pData->scanEventType)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001070 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 goto nla_put_failure;
1072 }
1073
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001074 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 return;
1076
1077nla_put_failure:
1078 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001079}
1080
1081/**
1082 * wlan_hdd_cfg80211_extscan_epno_match_found() - pno match found
1083 * @hddctx: HDD context
1084 * @data: matched network data
1085 *
1086 * This function reads the matched network data and fills NL vendor attributes
1087 * and send it to upper layer.
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001088 * This callback execute in atomic context and must not invoke any
1089 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001090 *
1091 * Return: 0 on success, error number otherwise
1092 */
1093static void
1094wlan_hdd_cfg80211_extscan_epno_match_found(void *ctx,
1095 struct pno_match_found *data)
1096{
Jeff Johnson9755a512017-08-28 12:01:57 -07001097 struct hdd_context *pHddCtx = (struct hdd_context *)ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001098 struct sk_buff *skb = NULL;
1099 uint32_t len, i;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001100 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101
1102 ENTER();
1103
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301104 if (wlan_hdd_validate_context(pHddCtx))
1105 return;
1106 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001107 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001108 return;
1109 }
1110
1111 /*
1112 * If the number of match found APs including IE data exceeds NL 4K size
1113 * limitation, drop that beacon/probe rsp frame.
1114 */
1115 len = sizeof(*data) +
1116 (data->num_results + sizeof(tSirWifiScanResult));
1117 for (i = 0; i < data->num_results; i++)
1118 len += data->ap[i].ieLength;
1119
1120 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001121 hdd_err("Frame exceeded NL size limitation, drop it!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001122 return;
1123 }
1124
1125 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1126 NULL,
1127 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1128 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001129 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001130
1131 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001132 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001133 return;
1134 }
1135
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001136 hdd_debug("Req Id %u More Data %u num_results %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 data->request_id, data->more_data, data->num_results);
1138 for (i = 0; i < data->num_results; i++) {
1139 data->ap[i].channel = cds_chan_to_freq(data->ap[i].channel);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001140 hdd_debug("AP Info: Timestamp %llu) Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001141 "Bssid (" MAC_ADDRESS_STR ") "
1142 "Channel %u "
1143 "Rssi %d "
1144 "RTT %u "
1145 "RTT_SD %u "
1146 "Bcn Period %d "
1147 "Capability 0x%X "
1148 "IE Length %d",
1149 data->ap[i].ts,
1150 data->ap[i].ssid,
1151 MAC_ADDR_ARRAY(data->ap[i].bssid.bytes),
1152 data->ap[i].channel,
1153 data->ap[i].rssi,
1154 data->ap[i].rtt,
1155 data->ap[i].rtt_sd,
1156 data->ap[i].beaconPeriod,
1157 data->ap[i].capability,
1158 data->ap[i].ieLength);
1159 }
1160
1161 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1162 data->request_id) ||
1163 nla_put_u32(skb,
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05301164 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_RESULTS_AVAILABLE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001165 data->num_results) ||
1166 nla_put_u8(skb,
1167 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1168 data->more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001169 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001170 goto fail;
1171 }
1172
1173 if (data->num_results) {
1174 struct nlattr *nla_aps;
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -07001175
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001176 nla_aps = nla_nest_start(skb,
1177 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1178 if (!nla_aps)
1179 goto fail;
1180
1181 for (i = 0; i < data->num_results; i++) {
1182 if (hdd_extscan_nl_fill_bss(skb, &data->ap[i], i))
1183 goto fail;
1184 }
1185 nla_nest_end(skb, nla_aps);
1186 }
1187
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001188 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001189 return;
1190
1191fail:
1192 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001193}
1194
1195/**
1196 * wlan_hdd_cfg80211_passpoint_match_found() - passpoint match found
1197 * @hddctx: HDD context
1198 * @data: matched network data
1199 *
1200 * This function reads the match network %data and fill in the skb with
1201 * NL attributes and send up the NL event
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001202 * This callback execute in atomic context and must not invoke any
1203 * blocking calls.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204 *
1205 * Return: none
1206 */
1207static void
1208wlan_hdd_cfg80211_passpoint_match_found(void *ctx,
1209 struct wifi_passpoint_match *data)
1210{
Jeff Johnson9755a512017-08-28 12:01:57 -07001211 struct hdd_context *pHddCtx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212 struct sk_buff *skb = NULL;
1213 uint32_t len, i, num_matches = 1, more_data = 0;
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001214 struct nlattr *nla_aps, *nla_bss;
1215 int flags = cds_get_gfp_flags();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216
1217 ENTER();
1218
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301219 if (wlan_hdd_validate_context(pHddCtx))
1220 return;
1221 if (!data) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001222 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 return;
1224 }
1225
1226 len = sizeof(*data) + data->ap.ieLength + data->anqp_len;
1227 if (len >= EXTSCAN_EVENT_BUF_SIZE) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001228 hdd_err("Result exceeded NL size limitation, drop it");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 return;
1230 }
1231
1232 skb = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
1233 NULL,
1234 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1235 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX,
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001236 flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001237
1238 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001239 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240 return;
1241 }
1242
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001243 hdd_debug("Req Id %u Id %u ANQP length %u num_matches %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001244 data->request_id, data->id, data->anqp_len, num_matches);
1245 for (i = 0; i < num_matches; i++) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001246 hdd_debug("AP Info: Timestamp %llu Ssid: %s "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001247 "Bssid (" MAC_ADDRESS_STR ") "
1248 "Channel %u "
1249 "Rssi %d "
1250 "RTT %u "
1251 "RTT_SD %u "
1252 "Bcn Period %d "
1253 "Capability 0x%X "
1254 "IE Length %d",
1255 data->ap.ts,
1256 data->ap.ssid,
1257 MAC_ADDR_ARRAY(data->ap.bssid.bytes),
1258 data->ap.channel,
1259 data->ap.rssi,
1260 data->ap.rtt,
1261 data->ap.rtt_sd,
1262 data->ap.beaconPeriod,
1263 data->ap.capability,
1264 data->ap.ieLength);
1265 }
1266
1267 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_REQUEST_ID,
1268 data->request_id) ||
1269 nla_put_u32(skb,
1270 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES,
1271 num_matches) ||
1272 nla_put_u8(skb,
1273 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_SCAN_RESULT_MORE_DATA,
1274 more_data)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001275 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276 goto fail;
1277 }
1278
1279 nla_aps = nla_nest_start(skb,
1280 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST);
1281 if (!nla_aps)
1282 goto fail;
1283
1284 for (i = 0; i < num_matches; i++) {
1285 struct nlattr *nla_ap;
1286
1287 nla_ap = nla_nest_start(skb, i);
1288 if (!nla_ap)
1289 goto fail;
1290
1291 if (nla_put_u32(skb,
1292 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID,
1293 data->id) ||
1294 nla_put_u32(skb,
1295 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN,
1296 data->anqp_len)) {
1297 goto fail;
1298 }
1299
1300 if (data->anqp_len)
1301 if (nla_put(skb,
1302 QCA_WLAN_VENDOR_ATTR_EXTSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP,
1303 data->anqp_len, data->anqp))
1304 goto fail;
1305
1306 nla_bss = nla_nest_start(skb,
1307 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_LIST);
1308 if (!nla_bss)
1309 goto fail;
1310
1311 if (hdd_extscan_nl_fill_bss(skb, &data->ap, 0))
1312 goto fail;
1313
1314 nla_nest_end(skb, nla_bss);
1315 nla_nest_end(skb, nla_ap);
1316 }
1317 nla_nest_end(skb, nla_aps);
1318
Srinivas Girigowdafe3e5b32015-11-23 11:56:36 -08001319 cfg80211_vendor_event(skb, flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001320 return;
1321
1322fail:
1323 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001324}
1325
1326/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001327 * wlan_hdd_cfg80211_extscan_generic_rsp() -
1328 * Handle a generic ExtScan Response message
1329 * @ctx: HDD context registered with SME
1330 * @response: The ExtScan response from firmware
1331 *
1332 * This function will handle a generic ExtScan response message from
1333 * firmware and will communicate the result to the userspace thread
1334 * that is waiting for the response.
1335 *
1336 * Return: none
1337 */
1338static void
1339wlan_hdd_cfg80211_extscan_generic_rsp
1340 (void *ctx,
1341 struct sir_extscan_generic_response *response)
1342{
Jeff Johnson9755a512017-08-28 12:01:57 -07001343 struct hdd_context *hdd_ctx = ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344 struct hdd_ext_scan_context *context;
1345
1346 ENTER();
1347
1348 if (wlan_hdd_validate_context(hdd_ctx) || !response) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001349 hdd_err("HDD context is not valid or response(%p) is null",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001350 response);
1351 return;
1352 }
1353
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001354 hdd_debug("request %u status %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355 response->request_id, response->status);
1356
1357 context = &ext_scan_context;
1358 spin_lock(&context->context_lock);
1359 if (context->request_id == response->request_id) {
1360 context->response_status = response->status ? -EINVAL : 0;
1361 complete(&context->response_event);
1362 }
1363 spin_unlock(&context->context_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364}
1365
1366/**
1367 * wlan_hdd_cfg80211_extscan_callback() - ext scan callback
1368 * @ctx: Pointer to hdd context
1369 * @evType: Event type
1370 * @pMag: Pointer to message
1371 *
1372 * Return: none
1373 */
1374void wlan_hdd_cfg80211_extscan_callback(void *ctx, const uint16_t evType,
1375 void *pMsg)
1376{
Jeff Johnson9755a512017-08-28 12:01:57 -07001377 struct hdd_context *pHddCtx = (struct hdd_context *) ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001379 /* ENTER() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301380
1381 if (wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001382 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001383
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001384 hdd_debug("Rcvd Event %d", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385
1386 switch (evType) {
1387 case eSIR_EXTSCAN_CACHED_RESULTS_RSP:
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001388 /* There is no need to send this response to upper layer
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -07001389 * Just log the message
1390 */
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001391 hdd_debug("Rcvd eSIR_EXTSCAN_CACHED_RESULTS_RSP");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 break;
1393
1394 case eSIR_EXTSCAN_GET_CAPABILITIES_IND:
1395 wlan_hdd_cfg80211_extscan_get_capabilities_rsp(ctx,
1396 (struct ext_scan_capabilities_response *) pMsg);
1397 break;
1398
1399 case eSIR_EXTSCAN_HOTLIST_MATCH_IND:
1400 wlan_hdd_cfg80211_extscan_hotlist_match_ind(ctx, pMsg);
1401 break;
1402
1403 case eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND:
1404 wlan_hdd_cfg80211_extscan_signif_wifi_change_results_ind(ctx,
1405 (tpSirWifiSignificantChangeEvent) pMsg);
1406 break;
1407
1408 case eSIR_EXTSCAN_CACHED_RESULTS_IND:
1409 wlan_hdd_cfg80211_extscan_cached_results_ind(ctx, pMsg);
1410 break;
1411
1412 case eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND:
1413 wlan_hdd_cfg80211_extscan_scan_res_available_event(ctx,
1414 (tpSirExtScanResultsAvailableIndParams) pMsg);
1415 break;
1416
1417 case eSIR_EXTSCAN_FULL_SCAN_RESULT_IND:
1418 wlan_hdd_cfg80211_extscan_full_scan_result_event(ctx,
1419 (tpSirWifiFullScanResultEvent) pMsg);
1420 break;
1421
1422 case eSIR_EPNO_NETWORK_FOUND_IND:
1423 wlan_hdd_cfg80211_extscan_epno_match_found(ctx,
1424 (struct pno_match_found *)pMsg);
1425 break;
1426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001427 case eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND:
1428 wlan_hdd_cfg80211_extscan_scan_progress_event(ctx,
1429 (tpSirExtScanOnScanEventIndParams) pMsg);
1430 break;
1431
1432 case eSIR_PASSPOINT_NETWORK_FOUND_IND:
1433 wlan_hdd_cfg80211_passpoint_match_found(ctx,
1434 (struct wifi_passpoint_match *) pMsg);
1435 break;
1436
1437 case eSIR_EXTSCAN_START_RSP:
1438 case eSIR_EXTSCAN_STOP_RSP:
1439 case eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP:
1440 case eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP:
1441 case eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP:
1442 case eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP:
1443 case eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP:
1444 case eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP:
1445 wlan_hdd_cfg80211_extscan_generic_rsp(ctx, pMsg);
1446 break;
1447
1448 default:
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001449 hdd_err("Unknown event type: %u", evType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 break;
1451 }
1452}
1453
1454/*
1455 * define short names for the global vendor params
1456 * used by wlan_hdd_send_ext_scan_capability()
1457 */
1458#define PARAM_REQUEST_ID \
1459 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1460#define PARAM_STATUS \
1461 QCA_WLAN_VENDOR_ATTR_EXTSCAN_STATUS
1462#define MAX_SCAN_CACHE_SIZE \
1463 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE
1464#define MAX_SCAN_BUCKETS \
1465 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS
1466#define MAX_AP_CACHE_PER_SCAN \
1467 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN
1468#define MAX_RSSI_SAMPLE_SIZE \
1469 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE
1470#define MAX_SCAN_RPT_THRHOLD \
1471 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD
1472#define MAX_HOTLIST_BSSIDS \
1473 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS
1474#define MAX_SIGNIFICANT_WIFI_CHANGE_APS \
1475 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS
1476#define MAX_BSSID_HISTORY_ENTRIES \
1477 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES
1478#define MAX_HOTLIST_SSIDS \
1479 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS
1480#define MAX_NUM_EPNO_NETS \
1481 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
1482#define MAX_NUM_EPNO_NETS_BY_SSID \
1483 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID
1484#define MAX_NUM_WHITELISTED_SSID \
1485 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301486#define MAX_NUM_BLACKLISTED_BSSID \
1487 QCA_WLAN_VENDOR_ATTR_EXTSCAN_MAX_NUM_BLACKLISTED_BSSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488/**
1489 * wlan_hdd_send_ext_scan_capability - send ext scan capability to user space
1490 * @hdd_ctx: Pointer to hdd context
1491 *
1492 * Return: 0 for success, non-zero for failure
1493 */
Jeff Johnson9755a512017-08-28 12:01:57 -07001494static int wlan_hdd_send_ext_scan_capability(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001495{
1496 int ret;
1497 struct sk_buff *skb;
1498 struct ext_scan_capabilities_response *data;
1499 uint32_t nl_buf_len;
1500
1501 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301502 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001503 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001504
1505 data = &(ext_scan_context.capability_response);
1506
1507 nl_buf_len = NLMSG_HDRLEN;
1508 nl_buf_len += (sizeof(data->requestId) + NLA_HDRLEN) +
1509 (sizeof(data->status) + NLA_HDRLEN) +
1510 (sizeof(data->max_scan_cache_size) + NLA_HDRLEN) +
1511 (sizeof(data->max_scan_buckets) + NLA_HDRLEN) +
1512 (sizeof(data->max_ap_cache_per_scan) + NLA_HDRLEN) +
1513 (sizeof(data->max_rssi_sample_size) + NLA_HDRLEN) +
1514 (sizeof(data->max_scan_reporting_threshold) + NLA_HDRLEN) +
1515 (sizeof(data->max_hotlist_bssids) + NLA_HDRLEN) +
1516 (sizeof(data->max_significant_wifi_change_aps) + NLA_HDRLEN) +
1517 (sizeof(data->max_bssid_history_entries) + NLA_HDRLEN) +
1518 (sizeof(data->max_hotlist_ssids) + NLA_HDRLEN) +
1519 (sizeof(data->max_number_epno_networks) + NLA_HDRLEN) +
1520 (sizeof(data->max_number_epno_networks_by_ssid) + NLA_HDRLEN) +
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301521 (sizeof(data->max_number_of_white_listed_ssid) + NLA_HDRLEN) +
1522 (sizeof(data->max_number_of_black_listed_bssid) + NLA_HDRLEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001523
1524 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
1525
1526 if (!skb) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001527 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001528 return -ENOMEM;
1529 }
1530
1531
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001532 hdd_debug("Req Id %u", data->requestId);
1533 hdd_debug("Status %u", data->status);
1534 hdd_debug("Scan cache size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535 data->max_scan_cache_size);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001536 hdd_debug("Scan buckets %u", data->max_scan_buckets);
1537 hdd_debug("Max AP per scan %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001538 data->max_ap_cache_per_scan);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001539 hdd_debug("max_rssi_sample_size %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540 data->max_rssi_sample_size);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001541 hdd_debug("max_scan_reporting_threshold %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001542 data->max_scan_reporting_threshold);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001543 hdd_debug("max_hotlist_bssids %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544 data->max_hotlist_bssids);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001545 hdd_debug("max_significant_wifi_change_aps %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001546 data->max_significant_wifi_change_aps);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001547 hdd_debug("max_bssid_history_entries %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001548 data->max_bssid_history_entries);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001549 hdd_debug("max_hotlist_ssids %u", data->max_hotlist_ssids);
1550 hdd_debug("max_number_epno_networks %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001551 data->max_number_epno_networks);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001552 hdd_debug("max_number_epno_networks_by_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001553 data->max_number_epno_networks_by_ssid);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001554 hdd_debug("max_number_of_white_listed_ssid %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001555 data->max_number_of_white_listed_ssid);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001556 hdd_debug("max_number_of_black_listed_bssid (%u)",
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301557 data->max_number_of_black_listed_bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558
1559 if (nla_put_u32(skb, PARAM_REQUEST_ID, data->requestId) ||
1560 nla_put_u32(skb, PARAM_STATUS, data->status) ||
1561 nla_put_u32(skb, MAX_SCAN_CACHE_SIZE, data->max_scan_cache_size) ||
1562 nla_put_u32(skb, MAX_SCAN_BUCKETS, data->max_scan_buckets) ||
1563 nla_put_u32(skb, MAX_AP_CACHE_PER_SCAN,
1564 data->max_ap_cache_per_scan) ||
1565 nla_put_u32(skb, MAX_RSSI_SAMPLE_SIZE,
1566 data->max_rssi_sample_size) ||
1567 nla_put_u32(skb, MAX_SCAN_RPT_THRHOLD,
1568 data->max_scan_reporting_threshold) ||
1569 nla_put_u32(skb, MAX_HOTLIST_BSSIDS, data->max_hotlist_bssids) ||
1570 nla_put_u32(skb, MAX_SIGNIFICANT_WIFI_CHANGE_APS,
1571 data->max_significant_wifi_change_aps) ||
1572 nla_put_u32(skb, MAX_BSSID_HISTORY_ENTRIES,
1573 data->max_bssid_history_entries) ||
1574 nla_put_u32(skb, MAX_HOTLIST_SSIDS, data->max_hotlist_ssids) ||
1575 nla_put_u32(skb, MAX_NUM_EPNO_NETS,
1576 data->max_number_epno_networks) ||
1577 nla_put_u32(skb, MAX_NUM_EPNO_NETS_BY_SSID,
1578 data->max_number_epno_networks_by_ssid) ||
1579 nla_put_u32(skb, MAX_NUM_WHITELISTED_SSID,
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301580 data->max_number_of_white_listed_ssid) ||
1581 nla_put_u32(skb, MAX_NUM_BLACKLISTED_BSSID,
1582 data->max_number_of_black_listed_bssid)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001583 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001584 goto nla_put_failure;
1585 }
1586
1587 cfg80211_vendor_cmd_reply(skb);
1588 return 0;
1589
1590nla_put_failure:
1591 kfree_skb(skb);
1592 return -EINVAL;
1593}
1594/*
1595 * done with short names for the global vendor params
1596 * used by wlan_hdd_send_ext_scan_capability()
1597 */
1598#undef PARAM_REQUEST_ID
1599#undef PARAM_STATUS
1600#undef MAX_SCAN_CACHE_SIZE
1601#undef MAX_SCAN_BUCKETS
1602#undef MAX_AP_CACHE_PER_SCAN
1603#undef MAX_RSSI_SAMPLE_SIZE
1604#undef MAX_SCAN_RPT_THRHOLD
1605#undef MAX_HOTLIST_BSSIDS
1606#undef MAX_SIGNIFICANT_WIFI_CHANGE_APS
1607#undef MAX_BSSID_HISTORY_ENTRIES
1608#undef MAX_HOTLIST_SSIDS
1609#undef MAX_NUM_EPNO_NETS
1610#undef MAX_NUM_EPNO_NETS_BY_SSID
1611#undef MAX_NUM_WHITELISTED_SSID
Padma, Santhosh Kumar1ac02402016-11-02 18:04:14 +05301612#undef MAX_NUM_BLACKLISTED_BSSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613
1614/**
1615 * __wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1616 * @wiphy: Pointer to wireless phy
1617 * @wdev: Pointer to wireless device
1618 * @data: Pointer to data
1619 * @data_len: Data length
1620 *
1621 * Return: none
1622 */
1623static int __wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1624 struct wireless_dev *wdev,
1625 const void *data, int data_len)
1626{
1627 int ret;
1628 unsigned long rc;
1629 struct hdd_ext_scan_context *context;
1630 tpSirGetExtScanCapabilitiesReqParams pReqMsg = NULL;
1631 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07001632 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07001633 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001634 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1635 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301636 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001637
Jeff Johnson1f61b612016-02-12 16:28:33 -08001638 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639
Anurag Chouhan6d760662016-02-20 16:05:43 +05301640 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001641 hdd_err("Command not allowed in FTM mode");
1642 return -EPERM;
1643 }
1644
1645 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301646 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001647 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001648
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05301649 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
1650 hdd_err("Driver Modules are closed");
1651 return -EINVAL;
1652 }
1653
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301654 if (!pHddCtx->config->extscan_enabled) {
1655 hdd_err("extscan not supported");
1656 return -ENOTSUPP;
1657 }
Dustin Brown3fb15042017-08-15 15:54:49 -07001658 if (hdd_nla_parse(tb,
1659 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1660 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001661 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001662 return -EINVAL;
1663 }
1664
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301665 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001667 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668 return -ENOMEM;
1669 }
1670
1671 /* Parse and fetch request Id */
1672 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001673 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001674 goto fail;
1675 }
1676
1677 pReqMsg->requestId =
1678 nla_get_u32(tb
1679 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
1680 pReqMsg->sessionId = pAdapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001681 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001682 pReqMsg->requestId, pReqMsg->sessionId);
1683
1684 context = &ext_scan_context;
1685 spin_lock(&context->context_lock);
1686 context->request_id = pReqMsg->requestId;
1687 INIT_COMPLETION(context->response_event);
1688 spin_unlock(&context->context_lock);
1689
1690 status = sme_ext_scan_get_capabilities(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301691 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001692 hdd_err("sme_ext_scan_get_capabilities failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001693 status);
1694 goto fail;
1695 }
1696
1697 rc = wait_for_completion_timeout(&context->response_event,
1698 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1699 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001700 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001701 return -ETIMEDOUT;
1702 }
1703
1704 ret = wlan_hdd_send_ext_scan_capability(pHddCtx);
1705 if (ret)
Jeff Johnson630f9e72016-07-25 12:00:12 -07001706 hdd_err("Failed to send ext scan capability to user space");
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301707 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001708 return ret;
1709fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301710 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001711 return -EINVAL;
1712}
1713
1714/**
1715 * wlan_hdd_cfg80211_extscan_get_capabilities() - get ext scan capabilities
1716 * @wiphy: Pointer to wiphy
1717 * @wdev: Pointer to wdev
1718 * @data: Pointer to data
1719 * @data_len: Data length
1720 *
1721 * Return: 0 for success, non-zero for failure
1722 */
1723int wlan_hdd_cfg80211_extscan_get_capabilities(struct wiphy *wiphy,
1724 struct wireless_dev *wdev,
1725 const void *data, int data_len)
1726{
1727 int ret = 0;
1728
1729 cds_ssr_protect(__func__);
1730 ret = __wlan_hdd_cfg80211_extscan_get_capabilities(wiphy, wdev, data,
1731 data_len);
1732 cds_ssr_unprotect(__func__);
1733
1734 return ret;
1735}
1736
1737/*
1738 * define short names for the global vendor params
1739 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1740 */
1741#define PARAM_MAX \
1742 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1743#define PARAM_REQUEST_ID \
1744 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
1745#define PARAM_FLUSH \
1746 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH
1747/**
1748 * __wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1749 * @wiphy: wiphy pointer
1750 * @wdev: pointer to struct wireless_dev
1751 * @data: pointer to incoming NL vendor data
1752 * @data_len: length of @data
1753 *
1754 * This function parses the incoming NL vendor command data attributes and
1755 * invokes the SME Api and blocks on a completion variable.
1756 * Each WMI event with cached scan results data chunk results in
1757 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1758 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1759 *
1760 * If timeout happens before receiving all of the data, this function sets
1761 * a context variable @ignore_cached_results to %true, all of the next data
1762 * chunks are checked against this variable and dropped.
1763 *
1764 * Return: 0 on success; error number otherwise.
1765 */
1766static int __wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1767 struct wireless_dev
1768 *wdev, const void *data,
1769 int data_len)
1770{
1771 tpSirExtScanGetCachedResultsReqParams pReqMsg = NULL;
1772 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07001773 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07001774 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001775 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1776 1];
1777 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301778 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 int retval = 0;
1780 unsigned long rc;
1781
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001782 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001783
Anurag Chouhan6d760662016-02-20 16:05:43 +05301784 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001785 hdd_err("Command not allowed in FTM mode");
1786 return -EPERM;
1787 }
1788
1789 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301790 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001791 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001792
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301793 if (!pHddCtx->config->extscan_enabled) {
1794 hdd_err("extscan not supported");
1795 return -ENOTSUPP;
1796 }
Dustin Brown3fb15042017-08-15 15:54:49 -07001797 if (hdd_nla_parse(tb, PARAM_MAX, data, data_len,
1798 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001799 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001800 return -EINVAL;
1801 }
1802
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301803 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001804 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001805 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001806 return -ENOMEM;
1807 }
1808
1809 /* Parse and fetch request Id */
1810 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001811 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812 goto fail;
1813 }
1814
1815 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
1816 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001817
1818 /* Parse and fetch flush parameter */
1819 if (!tb[PARAM_FLUSH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001820 hdd_err("attr flush failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 goto fail;
1822 }
1823 pReqMsg->flush = nla_get_u8(tb[PARAM_FLUSH]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001824 hdd_debug("Req Id: %u Session Id: %d Flush: %d",
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001825 pReqMsg->requestId, pReqMsg->sessionId, pReqMsg->flush);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826
1827 context = &ext_scan_context;
1828 spin_lock(&context->context_lock);
1829 context->request_id = pReqMsg->requestId;
1830 context->ignore_cached_results = false;
1831 INIT_COMPLETION(context->response_event);
1832 spin_unlock(&context->context_lock);
1833
1834 status = sme_get_cached_results(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301835 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001836 hdd_err("sme_get_cached_results failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001837 goto fail;
1838 }
1839
1840 rc = wait_for_completion_timeout(&context->response_event,
1841 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
1842 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001843 hdd_err("Target response timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001844 retval = -ETIMEDOUT;
1845 spin_lock(&context->context_lock);
1846 context->ignore_cached_results = true;
1847 spin_unlock(&context->context_lock);
1848 } else {
1849 spin_lock(&context->context_lock);
1850 retval = context->response_status;
1851 spin_unlock(&context->context_lock);
1852 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 return retval;
1854
1855fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301856 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001857 return -EINVAL;
1858}
1859/*
1860 * done with short names for the global vendor params
1861 * used by wlan_hdd_cfg80211_extscan_get_cached_results()
1862 */
1863#undef PARAM_MAX
1864#undef PARAM_REQUEST_ID
1865#undef PARAM_FLUSH
1866
1867/**
1868 * wlan_hdd_cfg80211_extscan_get_cached_results() - extscan get cached results
1869 * @wiphy: wiphy pointer
1870 * @wdev: pointer to struct wireless_dev
1871 * @data: pointer to incoming NL vendor data
1872 * @data_len: length of @data
1873 *
1874 * This function parses the incoming NL vendor command data attributes and
1875 * invokes the SME Api and blocks on a completion variable.
1876 * Each WMI event with cached scan results data chunk results in
1877 * function call wlan_hdd_cfg80211_extscan_cached_results_ind and each
1878 * data chunk is sent up the layer in cfg80211_vendor_cmd_alloc_reply_skb.
1879 *
1880 * If timeout happens before receiving all of the data, this function sets
1881 * a context variable @ignore_cached_results to %true, all of the next data
1882 * chunks are checked against this variable and dropped.
1883 *
1884 * Return: 0 on success; error number otherwise.
1885 */
1886int wlan_hdd_cfg80211_extscan_get_cached_results(struct wiphy *wiphy,
1887 struct wireless_dev *wdev,
1888 const void *data, int data_len)
1889{
1890 int ret = 0;
1891
1892 cds_ssr_protect(__func__);
1893 ret = __wlan_hdd_cfg80211_extscan_get_cached_results(wiphy, wdev, data,
1894 data_len);
1895 cds_ssr_unprotect(__func__);
1896
1897 return ret;
1898}
1899
1900/**
1901 * __wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set bssid hot list
1902 * @wiphy: Pointer to wireless phy
1903 * @wdev: Pointer to wireless device
1904 * @data: Pointer to data
1905 * @data_len: Data length
1906 *
1907 * Return: none
1908 */
1909static int
1910__wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
1911 struct wireless_dev
1912 *wdev, const void *data,
1913 int data_len)
1914{
1915 tpSirExtScanSetBssidHotListReqParams pReqMsg = NULL;
1916 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07001917 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07001918 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
1920 1];
1921 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
1922 + 1];
1923 struct nlattr *apTh;
1924 struct hdd_ext_scan_context *context;
1925 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301926 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 uint8_t i;
1928 int rem, retval;
1929 unsigned long rc;
1930
Jeff Johnson1f61b612016-02-12 16:28:33 -08001931 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932
Anurag Chouhan6d760662016-02-20 16:05:43 +05301933 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934 hdd_err("Command not allowed in FTM mode");
1935 return -EPERM;
1936 }
1937
1938 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301939 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001941
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301942 if (!pHddCtx->config->extscan_enabled) {
1943 hdd_err("extscan not supported");
1944 return -ENOTSUPP;
1945 }
Dustin Brown3fb15042017-08-15 15:54:49 -07001946 if (hdd_nla_parse(tb,
1947 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
1948 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001949 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001950 return -EINVAL;
1951 }
1952
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301953 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001954 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001955 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001956 return -ENOMEM;
1957 }
1958
1959 /* Parse and fetch request Id */
1960 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001961 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 goto fail;
1963 }
1964
1965 pReqMsg->requestId =
1966 nla_get_u32(tb
1967 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001968 hdd_debug("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969
1970 /* Parse and fetch number of APs */
1971 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001972 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 goto fail;
1974 }
1975 pReqMsg->numAp =
1976 nla_get_u32(tb
1977 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_NUM_AP]);
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08001978 if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_HOTLIST_APS) {
1979 hdd_err("Number of AP: %u exceeds max: %u",
1980 pReqMsg->numAp, WLAN_EXTSCAN_MAX_HOTLIST_APS);
1981 goto fail;
1982 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 pReqMsg->sessionId = pAdapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001984 hdd_debug("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 pReqMsg->numAp, pReqMsg->sessionId);
1986
1987 /* Parse and fetch lost ap sample size */
1988 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07001989 hdd_err("attr lost ap sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001990 goto fail;
1991 }
1992
1993 pReqMsg->lost_ap_sample_size = nla_get_u32(
1994 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08001995 hdd_debug("Lost ap sample size %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001996 pReqMsg->lost_ap_sample_size);
1997
SaidiReddy Yenugaa1917382017-03-28 17:04:37 +05301998 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM]) {
1999 hdd_err("attr ap threshold failed");
2000 goto fail;
2001 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 i = 0;
2003 nla_for_each_nested(apTh,
2004 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2005 rem) {
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002006 if (i == pReqMsg->numAp) {
2007 hdd_warn("Ignoring excess AP");
2008 break;
2009 }
2010
Dustin Brown3fb15042017-08-15 15:54:49 -07002011 if (hdd_nla_parse(tb2,
2012 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2013 nla_data(apTh), nla_len(apTh),
2014 wlan_hdd_extscan_config_policy)) {
2015 hdd_err("hdd_nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 goto fail;
2017 }
2018
2019 /* Parse and fetch MAC address */
2020 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002021 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022 goto fail;
2023 }
2024 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2025 tb2
2026 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302027 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002028 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002029 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2030
2031 /* Parse and fetch low RSSI */
2032 if (!tb2
2033 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002034 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035 goto fail;
2036 }
2037 pReqMsg->ap[i].low =
2038 nla_get_s32(tb2
2039 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002040 hdd_debug("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002041
2042 /* Parse and fetch high RSSI */
2043 if (!tb2
2044 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002045 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002046 goto fail;
2047 }
2048 pReqMsg->ap[i].high =
2049 nla_get_s32(tb2
2050 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002051 hdd_debug("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002052
2053 i++;
2054 }
2055
Srinivas Girigowda60a4f9d2016-12-07 14:35:39 -08002056 if (i < pReqMsg->numAp) {
2057 hdd_warn("Number of AP %u less than expected %u",
2058 i, pReqMsg->numAp);
2059 pReqMsg->numAp = i;
2060 }
2061
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002062 context = &ext_scan_context;
2063 spin_lock(&context->context_lock);
2064 INIT_COMPLETION(context->response_event);
2065 context->request_id = request_id = pReqMsg->requestId;
2066 spin_unlock(&context->context_lock);
2067
2068 status = sme_set_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302069 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002070 hdd_err("sme_set_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 goto fail;
2072 }
2073
2074 /* request was sent -- wait for the response */
2075 rc = wait_for_completion_timeout
2076 (&context->response_event,
2077 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2078
2079 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002080 hdd_err("sme_set_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002081 retval = -ETIMEDOUT;
2082 } else {
2083 spin_lock(&context->context_lock);
2084 if (context->request_id == request_id)
2085 retval = context->response_status;
2086 else
2087 retval = -EINVAL;
2088 spin_unlock(&context->context_lock);
2089 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302090 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002091 return retval;
2092
2093fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302094 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002095 return -EINVAL;
2096}
2097
2098/**
2099 * wlan_hdd_cfg80211_extscan_set_bssid_hotlist() - set ext scan bssid hotlist
2100 * @wiphy: Pointer to wiphy
2101 * @wdev: Pointer to wdev
2102 * @data: Pointer to data
2103 * @data_len: Data length
2104 *
2105 * Return: 0 for success, non-zero for failure
2106 */
2107int wlan_hdd_cfg80211_extscan_set_bssid_hotlist(struct wiphy *wiphy,
2108 struct wireless_dev *wdev,
2109 const void *data, int data_len)
2110{
2111 int ret = 0;
2112
2113 cds_ssr_protect(__func__);
2114 ret = __wlan_hdd_cfg80211_extscan_set_bssid_hotlist(wiphy, wdev, data,
2115 data_len);
2116 cds_ssr_unprotect(__func__);
2117
2118 return ret;
2119}
2120
2121
2122/**
Srinivas Girigowdacf2d0af2017-03-25 12:03:15 -07002123 * __wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002124 * @wiphy: Pointer to wireless phy
2125 * @wdev: Pointer to wireless device
2126 * @data: Pointer to data
2127 * @data_len: Data length
2128 *
2129 * Return: none
2130 */
2131static int
2132__wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2133 struct wireless_dev
2134 *wdev, const void *data,
2135 int data_len)
2136{
2137 tpSirExtScanSetSigChangeReqParams pReqMsg = NULL;
2138 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07002139 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07002140 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002141 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2142 1];
2143 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
2144 + 1];
2145 struct nlattr *apTh;
2146 struct hdd_ext_scan_context *context;
2147 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302148 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002149 uint8_t i;
2150 int rem, retval;
2151 unsigned long rc;
2152
Jeff Johnson1f61b612016-02-12 16:28:33 -08002153 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002154
Anurag Chouhan6d760662016-02-20 16:05:43 +05302155 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156 hdd_err("Command not allowed in FTM mode");
2157 return -EPERM;
2158 }
2159
2160 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302161 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002162 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002163
Dustin Brown3fb15042017-08-15 15:54:49 -07002164 if (hdd_nla_parse(tb,
2165 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2166 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002167 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002168 return -EINVAL;
2169 }
2170
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302171 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002173 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 return -ENOMEM;
2175 }
2176
2177 /* Parse and fetch request Id */
2178 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002179 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002180 goto fail;
2181 }
2182
2183 pReqMsg->requestId =
2184 nla_get_u32(tb
2185 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002186 hdd_debug("Req Id %d", pReqMsg->requestId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187
2188 /* Parse and fetch RSSI sample size */
2189 if (!tb
2190 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002191 hdd_err("attr RSSI sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192 goto fail;
2193 }
2194 pReqMsg->rssiSampleSize =
2195 nla_get_u32(tb
2196 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002197 hdd_debug("RSSI sample size %u", pReqMsg->rssiSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002198
2199 /* Parse and fetch lost AP sample size */
2200 if (!tb
2201 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002202 hdd_err("attr lost AP sample size failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002203 goto fail;
2204 }
2205 pReqMsg->lostApSampleSize =
2206 nla_get_u32(tb
2207 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002208 hdd_debug("Lost AP sample size %u", pReqMsg->lostApSampleSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002209
2210 /* Parse and fetch AP min breacing */
2211 if (!tb
2212 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002213 hdd_err("attr AP min breaching");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002214 goto fail;
2215 }
2216 pReqMsg->minBreaching =
2217 nla_get_u32(tb
2218 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002219 hdd_debug("AP min breaching %u", pReqMsg->minBreaching);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220
2221 /* Parse and fetch number of APs */
2222 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002223 hdd_err("attr number of AP failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224 goto fail;
2225 }
2226 pReqMsg->numAp =
2227 nla_get_u32(tb
2228 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP]);
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002229 if (pReqMsg->numAp > WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS) {
2230 hdd_err("Number of AP %u exceeds max %u",
2231 pReqMsg->numAp,
2232 WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS);
2233 goto fail;
2234 }
2235
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002236 pReqMsg->sessionId = pAdapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002237 hdd_debug("Number of AP %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002238 pReqMsg->numAp, pReqMsg->sessionId);
2239
SaidiReddy Yenuga6f4763d2017-03-28 17:09:56 +05302240 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM]) {
2241 hdd_err("attr ap threshold failed");
2242 goto fail;
2243 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002244 i = 0;
2245 nla_for_each_nested(apTh,
2246 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM],
2247 rem) {
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002248
2249 if (i == pReqMsg->numAp) {
2250 hdd_warn("Ignoring excess AP");
2251 break;
2252 }
2253
Dustin Brown3fb15042017-08-15 15:54:49 -07002254 if (hdd_nla_parse(tb2,
2255 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2256 nla_data(apTh), nla_len(apTh),
2257 wlan_hdd_extscan_config_policy)) {
2258 hdd_err("hdd_nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002259 goto fail;
2260 }
2261
2262 /* Parse and fetch MAC address */
2263 if (!tb2[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002264 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002265 goto fail;
2266 }
2267 nla_memcpy(pReqMsg->ap[i].bssid.bytes,
2268 tb2
2269 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302270 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002271 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002272 MAC_ADDR_ARRAY(pReqMsg->ap[i].bssid.bytes));
2273
2274 /* Parse and fetch low RSSI */
2275 if (!tb2
2276 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002277 hdd_err("attr low RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 goto fail;
2279 }
2280 pReqMsg->ap[i].low =
2281 nla_get_s32(tb2
2282 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002283 hdd_debug("RSSI low %d", pReqMsg->ap[i].low);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002284
2285 /* Parse and fetch high RSSI */
2286 if (!tb2
2287 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002288 hdd_err("attr high RSSI failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002289 goto fail;
2290 }
2291 pReqMsg->ap[i].high =
2292 nla_get_s32(tb2
2293 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002294 hdd_debug("RSSI High %d", pReqMsg->ap[i].high);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295
2296 i++;
2297 }
Prakash Dhavalib0888ed2016-11-29 08:54:18 -08002298 if (i < pReqMsg->numAp) {
2299 hdd_warn("Number of AP %u less than expected %u",
2300 i, pReqMsg->numAp);
2301 pReqMsg->numAp = i;
2302 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303
2304 context = &ext_scan_context;
2305 spin_lock(&context->context_lock);
2306 INIT_COMPLETION(context->response_event);
2307 context->request_id = request_id = pReqMsg->requestId;
2308 spin_unlock(&context->context_lock);
2309
2310 status = sme_set_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302311 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002312 hdd_err("sme_set_significant_change failed(err=%d)", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302313 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002314 return -EINVAL;
2315 }
2316
2317 /* request was sent -- wait for the response */
2318 rc = wait_for_completion_timeout(&context->response_event,
2319 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
2320
2321 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002322 hdd_err("sme_set_significant_change timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323 retval = -ETIMEDOUT;
2324 } else {
2325 spin_lock(&context->context_lock);
2326 if (context->request_id == request_id)
2327 retval = context->response_status;
2328 else
2329 retval = -EINVAL;
2330 spin_unlock(&context->context_lock);
2331 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302332 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333 return retval;
2334
2335fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302336 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 return -EINVAL;
2338}
2339
2340/**
2341 * wlan_hdd_cfg80211_extscan_set_significant_change() - set significant change
2342 * @wiphy: Pointer to wireless phy
2343 * @wdev: Pointer to wireless device
2344 * @data: Pointer to data
2345 * @data_len: Data length
2346 *
2347 * Return: 0 on success, negative errno on failure
2348 */
2349int wlan_hdd_cfg80211_extscan_set_significant_change(struct wiphy *wiphy,
2350 struct wireless_dev *wdev,
2351 const void *data, int data_len)
2352{
2353 int ret = 0;
2354
2355 cds_ssr_protect(__func__);
2356 ret = __wlan_hdd_cfg80211_extscan_set_significant_change(wiphy, wdev,
2357 data, data_len);
2358 cds_ssr_unprotect(__func__);
2359
2360 return ret;
2361}
2362
2363/**
2364 * hdd_remove_dsrc_channels () - remove dsrc chanels
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002365 * @hdd_ctx: hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002366 * @wiphy: Pointer to wireless phy
2367 * @chan_list: channel list
2368 * @num_channels: number of channels
2369 *
2370 * Return: none
2371 */
Jeff Johnson9755a512017-08-28 12:01:57 -07002372static void hdd_remove_dsrc_channels(struct hdd_context *hdd_ctx,
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002373 struct wiphy *wiphy, uint32_t *chan_list,
Jeff Johnsoncd2a0792016-10-05 15:17:13 -07002374 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002375{
2376 uint8_t num_chan_temp = 0;
2377 int i;
2378
2379 for (i = 0; i < *num_channels; i++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002380 if (!WLAN_REG_IS_11P_CH(wlan_reg_freq_to_chan(hdd_ctx->hdd_pdev,
2381 chan_list[i]))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 chan_list[num_chan_temp] = chan_list[i];
2383 num_chan_temp++;
2384 }
2385 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386 *num_channels = num_chan_temp;
2387}
2388
2389/**
Amar Singhalea10a872016-08-23 15:31:45 -07002390 * hdd_remove_passive_channels () - remove passive channels
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391 * @wiphy: Pointer to wireless phy
2392 * @chan_list: channel list
2393 * @num_channels: number of channels
2394 *
2395 * Return: none
2396 */
Amar Singhal25b10f92016-11-14 16:53:25 -08002397static void hdd_remove_passive_channels(struct wiphy *wiphy,
2398 uint32_t *chan_list,
2399 uint8_t *num_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400{
2401 uint8_t num_chan_temp = 0;
2402 int i, j, k;
2403
2404 for (i = 0; i < *num_channels; i++)
Srinivas Girigowda5da651b2017-08-04 11:22:54 -07002405 for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002406 if (wiphy->bands[j] == NULL)
2407 continue;
2408 for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
2409 if ((chan_list[i] ==
2410 wiphy->bands[j]->channels[k].center_freq)
2411 && (!(wiphy->bands[j]->channels[k].flags &
Amar Singhalea10a872016-08-23 15:31:45 -07002412 IEEE80211_CHAN_PASSIVE_SCAN))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 ) {
2414 chan_list[num_chan_temp] = chan_list[i];
2415 num_chan_temp++;
2416 }
2417 }
2418 }
2419
2420 *num_channels = num_chan_temp;
2421}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422
2423/**
2424 * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
2425 * @wiphy: Pointer to wireless phy
2426 * @wdev: Pointer to wireless device
2427 * @data: Pointer to data
2428 * @data_len: Data length
2429 *
2430 * Return: none
2431 */
2432static int
2433__wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2434 struct wireless_dev
2435 *wdev, const void *data,
2436 int data_len)
2437{
Jeff Johnson9755a512017-08-28 12:01:57 -07002438 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002439 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07002440 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002442 uint8_t num_channels = 0, i, buf[256] = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
2444 1];
2445 uint32_t requestId, maxChannels;
2446 tWifiBand wifiBand;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302447 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002448 struct sk_buff *reply_skb;
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002449 int ret, len = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002451 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452
Anurag Chouhan6d760662016-02-20 16:05:43 +05302453 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 hdd_err("Command not allowed in FTM mode");
2455 return -EPERM;
2456 }
2457
2458 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302459 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302462 if (!pHddCtx->config->extscan_enabled) {
2463 hdd_err("extscan not supported");
2464 return -ENOTSUPP;
2465 }
Dustin Brown3fb15042017-08-15 15:54:49 -07002466 if (hdd_nla_parse(tb,
2467 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2468 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002469 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 return -EINVAL;
2471 }
2472
2473 /* Parse and fetch request Id */
2474 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002475 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 return -EINVAL;
2477 }
2478 requestId =
2479 nla_get_u32(tb
2480 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481
2482 /* Parse and fetch wifi band */
2483 if (!tb
2484 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002485 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 return -EINVAL;
2487 }
2488 wifiBand =
2489 nla_get_u32(tb
2490 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491
2492 if (!tb
2493 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002494 hdd_err("attr max channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495 return -EINVAL;
2496 }
2497 maxChannels =
2498 nla_get_u32(tb
2499 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS]);
Manjeet Singhdb485182016-11-09 19:11:01 +05302500
2501 if (maxChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) {
2502 hdd_err("Max channels %d exceeded Valid channel list len %d",
2503 maxChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2504 return -EINVAL;
2505 }
2506
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002507 hdd_debug("Req Id: %u Wifi band: %d Max channels: %d", requestId,
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002508 wifiBand, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 status = sme_get_valid_channels_by_band((tHalHandle) (pHddCtx->hHal),
2510 wifiBand, chan_list,
2511 &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302512 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002513 hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 status);
2515 return -EINVAL;
2516 }
2517
Anurag Chouhan6d760662016-02-20 16:05:43 +05302518 num_channels = QDF_MIN(num_channels, maxChannels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002520 hdd_remove_dsrc_channels(pHddCtx, wiphy, chan_list, &num_channels);
Krunal Sonibe766b02016-03-10 13:00:44 -08002521 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 !strncmp(hdd_get_fwpath(), "ap", 2))
Amar Singhalea10a872016-08-23 15:31:45 -07002523 hdd_remove_passive_channels(wiphy, chan_list,
2524 &num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002526 hdd_debug("Number of channels: %d", num_channels);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 for (i = 0; i < num_channels; i++)
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002528 len += scnprintf(buf + len, sizeof(buf) - len,
2529 "%u ", chan_list[i]);
2530
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002531 hdd_debug("Channels: %s", buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002532
2533 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2534 sizeof(u32) *
2535 num_channels +
2536 NLMSG_HDRLEN);
2537
2538 if (reply_skb) {
2539 if (nla_put_u32(reply_skb,
2540 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS,
2541 num_channels) ||
2542 nla_put(reply_skb,
2543 QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS,
2544 sizeof(u32) * num_channels, chan_list)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002545 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546 kfree_skb(reply_skb);
2547 return -EINVAL;
2548 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302549 ret = cfg80211_vendor_cmd_reply(reply_skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302550 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551 }
2552
Jeff Johnson630f9e72016-07-25 12:00:12 -07002553 hdd_err("valid channels: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 return -EINVAL;
2555}
2556
2557/**
2558 * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
2559 * @wiphy: Pointer to wireless phy
2560 * @wdev: Pointer to wireless device
2561 * @data: Pointer to data
2562 * @data_len: Data length
2563 *
2564 * Return: 0 on success, negative errno on failure
2565 */
2566int wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
2567 struct wireless_dev *wdev,
2568 const void *data, int data_len)
2569{
2570 int ret = 0;
2571
2572 cds_ssr_protect(__func__);
2573 ret = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev, data,
2574 data_len);
2575 cds_ssr_unprotect(__func__);
2576
2577 return ret;
2578}
2579
2580/**
2581 * hdd_extscan_update_dwell_time_limits() - update dwell times
2582 * @req_msg: Pointer to request message
2583 * @bkt_idx: Index of current bucket being processed
2584 * @active_min: minimum active dwell time
2585 * @active_max: maximum active dwell time
2586 * @passive_min: minimum passive dwell time
2587 * @passive_max: maximum passive dwell time
2588 *
2589 * Return: none
2590 */
2591static void hdd_extscan_update_dwell_time_limits(
2592 tpSirWifiScanCmdReqParams req_msg, uint32_t bkt_idx,
2593 uint32_t active_min, uint32_t active_max,
2594 uint32_t passive_min, uint32_t passive_max)
2595{
2596 /* update per-bucket dwell times */
2597 if (req_msg->buckets[bkt_idx].min_dwell_time_active >
2598 active_min) {
2599 req_msg->buckets[bkt_idx].min_dwell_time_active =
2600 active_min;
2601 }
2602 if (req_msg->buckets[bkt_idx].max_dwell_time_active <
2603 active_max) {
2604 req_msg->buckets[bkt_idx].max_dwell_time_active =
2605 active_max;
2606 }
2607 if (req_msg->buckets[bkt_idx].min_dwell_time_passive >
2608 passive_min) {
2609 req_msg->buckets[bkt_idx].min_dwell_time_passive =
2610 passive_min;
2611 }
2612 if (req_msg->buckets[bkt_idx].max_dwell_time_passive <
2613 passive_max) {
2614 req_msg->buckets[bkt_idx].max_dwell_time_passive =
2615 passive_max;
2616 }
2617 /* update dwell-time across all buckets */
2618 if (req_msg->min_dwell_time_active >
2619 req_msg->buckets[bkt_idx].min_dwell_time_active) {
2620 req_msg->min_dwell_time_active =
2621 req_msg->buckets[bkt_idx].min_dwell_time_active;
2622 }
2623 if (req_msg->max_dwell_time_active <
2624 req_msg->buckets[bkt_idx].max_dwell_time_active) {
2625 req_msg->max_dwell_time_active =
2626 req_msg->buckets[bkt_idx].max_dwell_time_active;
2627 }
2628 if (req_msg->min_dwell_time_passive >
2629 req_msg->buckets[bkt_idx].min_dwell_time_passive) {
2630 req_msg->min_dwell_time_passive =
2631 req_msg->buckets[bkt_idx].min_dwell_time_passive;
2632 }
2633 if (req_msg->max_dwell_time_passive >
2634 req_msg->buckets[bkt_idx].max_dwell_time_passive) {
2635 req_msg->max_dwell_time_passive =
2636 req_msg->buckets[bkt_idx].max_dwell_time_passive;
2637 }
2638}
2639
2640/**
2641 * hdd_extscan_channel_max_reached() - channel max reached
2642 * @req: extscan request structure
2643 * @total_channels: total number of channels
2644 *
2645 * Return: true if total channels reached max, false otherwise
2646 */
2647static bool hdd_extscan_channel_max_reached(tSirWifiScanCmdReqParams *req,
2648 uint8_t total_channels)
2649{
2650 if (total_channels == WLAN_EXTSCAN_MAX_CHANNELS) {
2651 hdd_warn(
2652 "max #of channels %d reached, take only first %d bucket(s)",
2653 total_channels, req->numBuckets);
2654 return true;
2655 }
2656 return false;
2657}
2658
2659/**
2660 * hdd_extscan_start_fill_bucket_channel_spec() - fill bucket channel spec
2661 * @hdd_ctx: HDD global context
2662 * @req_msg: Pointer to request structure
2663 * @tb: pointer to NL attributes
2664 *
2665 * Return: 0 on success; error number otherwise
2666 */
2667static int hdd_extscan_start_fill_bucket_channel_spec(
Jeff Johnson9755a512017-08-28 12:01:57 -07002668 struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669 tpSirWifiScanCmdReqParams req_msg,
2670 struct nlattr **tb)
2671{
2672 struct nlattr *bucket[
2673 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2674 struct nlattr *channel[
2675 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX + 1];
2676 struct nlattr *buckets;
2677 struct nlattr *channels;
2678 int rem1, rem2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302679 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002680 uint8_t bkt_index, j, num_channels, total_channels = 0;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002681 uint32_t expected_buckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682 uint32_t chan_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2683
2684 uint32_t min_dwell_time_active_bucket =
2685 hdd_ctx->config->extscan_active_max_chn_time;
2686 uint32_t max_dwell_time_active_bucket =
2687 hdd_ctx->config->extscan_active_max_chn_time;
2688 uint32_t min_dwell_time_passive_bucket =
2689 hdd_ctx->config->extscan_passive_max_chn_time;
2690 uint32_t max_dwell_time_passive_bucket =
2691 hdd_ctx->config->extscan_passive_max_chn_time;
2692
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002693 req_msg->min_dwell_time_active =
2694 req_msg->max_dwell_time_active =
2695 hdd_ctx->config->extscan_active_max_chn_time;
2696
2697 req_msg->min_dwell_time_passive =
2698 req_msg->max_dwell_time_passive =
2699 hdd_ctx->config->extscan_passive_max_chn_time;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002700
2701 expected_buckets = req_msg->numBuckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002702 req_msg->numBuckets = 0;
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002703 bkt_index = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704
2705 nla_for_each_nested(buckets,
2706 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
Jeff Johnsonfae3c522016-11-11 17:57:13 -08002707
2708 if (bkt_index >= expected_buckets) {
2709 hdd_warn("ignoring excess buckets");
2710 break;
2711 }
2712
Dustin Brown3fb15042017-08-15 15:54:49 -07002713 if (hdd_nla_parse(bucket,
2714 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2715 nla_data(buckets), nla_len(buckets),
2716 wlan_hdd_extscan_config_policy)) {
2717 hdd_err("hdd_nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718 return -EINVAL;
2719 }
2720
2721 /* Parse and fetch bucket spec */
2722 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002723 hdd_err("attr bucket index failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002724 return -EINVAL;
2725 }
2726 req_msg->buckets[bkt_index].bucket = nla_get_u8(
2727 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_INDEX]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002728
2729 /* Parse and fetch wifi band */
2730 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002731 hdd_err("attr wifi band failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002732 return -EINVAL;
2733 }
2734 req_msg->buckets[bkt_index].band = nla_get_u8(
2735 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BAND]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736
2737 /* Parse and fetch period */
2738 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002739 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740 return -EINVAL;
2741 }
2742 req_msg->buckets[bkt_index].period = nla_get_u32(
2743 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002744
2745 /* Parse and fetch report events */
2746 if (!bucket[
2747 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002748 hdd_err("attr report events failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002749 return -EINVAL;
2750 }
2751 req_msg->buckets[bkt_index].reportEvents = nla_get_u8(
2752 bucket[
2753 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_REPORT_EVENTS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002754
2755 /* Parse and fetch max period */
2756 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002757 hdd_err("attr max period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002758 return -EINVAL;
2759 }
2760 req_msg->buckets[bkt_index].max_period = nla_get_u32(
2761 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_MAX_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002762
Mukul Sharmafa937be2016-08-12 18:13:36 +05302763 /* Parse and fetch base */
2764 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]) {
2765 hdd_err("attr base failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 return -EINVAL;
2767 }
2768 req_msg->buckets[bkt_index].exponent = nla_get_u32(
Mukul Sharmafa937be2016-08-12 18:13:36 +05302769 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_BASE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002770
2771 /* Parse and fetch step count */
2772 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002773 hdd_err("attr step count failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002774 return -EINVAL;
2775 }
2776 req_msg->buckets[bkt_index].step_count = nla_get_u32(
2777 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_STEP_COUNT]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002778 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 -07002779 req_msg->buckets[bkt_index].bucket,
2780 req_msg->buckets[bkt_index].band,
2781 req_msg->buckets[bkt_index].period,
2782 req_msg->buckets[bkt_index].reportEvents,
2783 req_msg->buckets[bkt_index].max_period,
2784 req_msg->buckets[bkt_index].exponent,
2785 req_msg->buckets[bkt_index].step_count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786
2787 /* start with known good values for bucket dwell times */
2788 req_msg->buckets[bkt_index].min_dwell_time_active =
2789 req_msg->buckets[bkt_index].max_dwell_time_active =
2790 hdd_ctx->config->extscan_active_max_chn_time;
2791
2792 req_msg->buckets[bkt_index].min_dwell_time_passive =
2793 req_msg->buckets[bkt_index].max_dwell_time_passive =
2794 hdd_ctx->config->extscan_passive_max_chn_time;
2795
2796 /* Framework shall pass the channel list if the input WiFi band
2797 * is WIFI_BAND_UNSPECIFIED.
2798 * If the input WiFi band is specified (any value other than
2799 * WIFI_BAND_UNSPECIFIED) then driver populates the channel list
2800 */
2801 if (req_msg->buckets[bkt_index].band != WIFI_BAND_UNSPECIFIED) {
2802 if (hdd_extscan_channel_max_reached(req_msg,
2803 total_channels))
2804 return 0;
2805
2806 num_channels = 0;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002807 hdd_debug("WiFi band is specified, driver to fill channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002808 status = sme_get_valid_channels_by_band(hdd_ctx->hHal,
2809 req_msg->buckets[bkt_index].band,
2810 chan_list, &num_channels);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302811 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002812 hdd_err("sme_GetValidChannelsByBand failed (err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002813 status);
2814 return -EINVAL;
2815 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002816 hdd_debug("before trimming, num_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 num_channels);
2818
2819 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302820 QDF_MIN(num_channels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 (WLAN_EXTSCAN_MAX_CHANNELS -
2822 total_channels));
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002823 hdd_debug("Adj Num channels/bucket: %d total_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824 req_msg->buckets[bkt_index].numChannels,
2825 total_channels);
2826 total_channels +=
2827 req_msg->buckets[bkt_index].numChannels;
2828
2829 for (j = 0; j < req_msg->buckets[bkt_index].numChannels;
2830 j++) {
2831 req_msg->buckets[bkt_index].channels[j].channel =
2832 chan_list[j];
2833 req_msg->buckets[bkt_index].channels[j].
2834 chnlClass = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002835 if ((wlan_reg_get_channel_state(
2836 hdd_ctx->hdd_pdev,
2837 cds_freq_to_chan(chan_list[j]))) !=
2838 CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 req_msg->buckets[bkt_index].channels[j].
2840 passive = 1;
2841 req_msg->buckets[bkt_index].channels[j].
2842 dwellTimeMs =
2843 hdd_ctx->config->
2844 extscan_passive_max_chn_time;
2845 /* reconfigure per-bucket dwell time */
2846 if (min_dwell_time_passive_bucket >
2847 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2848 min_dwell_time_passive_bucket =
2849 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2850 }
2851 if (max_dwell_time_passive_bucket <
2852 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2853 max_dwell_time_passive_bucket =
2854 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2855 }
2856
2857 } else {
2858 req_msg->buckets[bkt_index].channels[j].
2859 passive = 0;
2860 req_msg->buckets[bkt_index].channels[j].
2861 dwellTimeMs =
2862 hdd_ctx->config->extscan_active_max_chn_time;
2863 /* reconfigure per-bucket dwell times */
2864 if (min_dwell_time_active_bucket >
2865 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2866 min_dwell_time_active_bucket =
2867 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2868 }
2869 if (max_dwell_time_active_bucket <
2870 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2871 max_dwell_time_active_bucket =
2872 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
2873 }
2874
2875 }
2876
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002877 hdd_debug("Channel: %u Passive: %u Dwell time: %u ms Class: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002878 req_msg->buckets[bkt_index].channels[j].channel,
2879 req_msg->buckets[bkt_index].channels[j].passive,
2880 req_msg->buckets[bkt_index].channels[j].dwellTimeMs,
2881 req_msg->buckets[bkt_index].channels[j].chnlClass);
2882 }
2883
2884 hdd_extscan_update_dwell_time_limits(
2885 req_msg, bkt_index,
2886 min_dwell_time_active_bucket,
2887 max_dwell_time_active_bucket,
2888 min_dwell_time_passive_bucket,
2889 max_dwell_time_passive_bucket);
2890
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002891 hdd_debug("bkt_index:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 bkt_index,
2893 req_msg->buckets[bkt_index].min_dwell_time_active,
2894 req_msg->buckets[bkt_index].max_dwell_time_active,
2895 req_msg->buckets[bkt_index].min_dwell_time_passive,
2896 req_msg->buckets[bkt_index].max_dwell_time_passive);
2897
2898 bkt_index++;
2899 req_msg->numBuckets++;
2900 continue;
2901 }
2902
2903 /* Parse and fetch number of channels */
2904 if (!bucket[
2905 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002906 hdd_err("attr num channels failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 return -EINVAL;
2908 }
2909 req_msg->buckets[bkt_index].numChannels =
2910 nla_get_u32(bucket[
2911 QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002912 hdd_debug("before trimming: num channels %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002913 req_msg->buckets[bkt_index].numChannels);
2914
2915 req_msg->buckets[bkt_index].numChannels =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302916 QDF_MIN(req_msg->buckets[bkt_index].numChannels,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 (WLAN_EXTSCAN_MAX_CHANNELS - total_channels));
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002918 hdd_debug("Num channels/bucket: %d total_channels: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002919 req_msg->buckets[bkt_index].numChannels,
2920 total_channels);
2921 if (hdd_extscan_channel_max_reached(req_msg, total_channels))
2922 return 0;
2923
2924 if (!bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002925 hdd_err("attr channel spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 return -EINVAL;
2927 }
2928
2929 j = 0;
2930 nla_for_each_nested(channels,
2931 bucket[QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC], rem2) {
Jeff Johnson56951332015-10-29 11:26:02 -07002932 if ((j >= req_msg->buckets[bkt_index].numChannels) ||
2933 hdd_extscan_channel_max_reached(req_msg,
2934 total_channels))
2935 break;
2936
Dustin Brown3fb15042017-08-15 15:54:49 -07002937 if (hdd_nla_parse(channel,
2938 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
2939 nla_data(channels), nla_len(channels),
2940 wlan_hdd_extscan_config_policy)) {
2941 hdd_err("hdd_nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002942 return -EINVAL;
2943 }
2944
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 /* Parse and fetch channel */
2946 if (!channel[
2947 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002948 hdd_err("attr channel failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 return -EINVAL;
2950 }
2951 req_msg->buckets[bkt_index].channels[j].channel =
2952 nla_get_u32(channel[
2953 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_CHANNEL]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002954 hdd_debug("channel %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002955 req_msg->buckets[bkt_index].channels[j].channel);
2956
2957 /* Parse and fetch dwell time */
2958 if (!channel[
2959 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07002960 hdd_err("attr dwelltime failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002961 return -EINVAL;
2962 }
2963 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2964 nla_get_u32(channel[
2965 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_DWELL_TIME]);
2966
2967 /* Override dwell time if required */
2968 if (req_msg->buckets[bkt_index].channels[j].dwellTimeMs <
2969 hdd_ctx->config->extscan_active_min_chn_time ||
2970 req_msg->buckets[bkt_index].channels[j].dwellTimeMs >
2971 hdd_ctx->config->extscan_active_max_chn_time) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002972 hdd_debug("WiFi band is unspecified, dwellTime:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002973 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
2974
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002975 if ((wlan_reg_get_channel_state(
2976 hdd_ctx->hdd_pdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977 cds_freq_to_chan(
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002978 req_msg->buckets[bkt_index].
2979 channels[j].channel)))
2980 != CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2982 hdd_ctx->config->extscan_passive_max_chn_time;
2983 } else {
2984 req_msg->buckets[bkt_index].channels[j].dwellTimeMs =
2985 hdd_ctx->config->extscan_active_max_chn_time;
2986 }
2987 }
2988
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08002989 hdd_debug("New Dwell time %u ms",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 req_msg->buckets[bkt_index].channels[j].dwellTimeMs);
2991
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002992 if ((wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
2993 cds_freq_to_chan(
2994 req_msg->buckets[bkt_index].
2995 channels[j].channel)))
2996 != CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002997 if (min_dwell_time_passive_bucket >
2998 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
2999 min_dwell_time_passive_bucket =
3000 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3001 }
3002 if (max_dwell_time_passive_bucket <
3003 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3004 max_dwell_time_passive_bucket =
3005 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3006 }
3007 } else {
3008 if (min_dwell_time_active_bucket >
3009 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3010 min_dwell_time_active_bucket =
3011 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3012 }
3013 if (max_dwell_time_active_bucket <
3014 req_msg->buckets[bkt_index].channels[j].dwellTimeMs) {
3015 max_dwell_time_active_bucket =
3016 req_msg->buckets[bkt_index].channels[j].dwellTimeMs;
3017 }
3018 }
3019
3020 /* Parse and fetch channel spec passive */
3021 if (!channel[
3022 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003023 hdd_err("attr channel spec passive failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003024 return -EINVAL;
3025 }
3026 req_msg->buckets[bkt_index].channels[j].passive =
3027 nla_get_u8(channel[
3028 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CHANNEL_SPEC_PASSIVE]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003029 hdd_debug("Chnl spec passive %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003030 req_msg->buckets[bkt_index].channels[j].passive);
3031 /* Override scan type if required */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003032 if ((wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3033 cds_freq_to_chan(
3034 req_msg->buckets[bkt_index].
3035 channels[j].channel)))
3036 != CHANNEL_STATE_ENABLE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003037 req_msg->buckets[bkt_index].channels[j].passive = true;
3038 } else {
3039 req_msg->buckets[bkt_index].channels[j].passive = false;
3040 }
3041 j++;
3042 total_channels++;
3043 }
3044
3045 hdd_extscan_update_dwell_time_limits(
3046 req_msg, bkt_index,
3047 min_dwell_time_active_bucket,
3048 max_dwell_time_active_bucket,
3049 min_dwell_time_passive_bucket,
3050 max_dwell_time_passive_bucket);
3051
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003052 hdd_debug("bktIndex:%d actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003053 bkt_index,
3054 req_msg->buckets[bkt_index].min_dwell_time_active,
3055 req_msg->buckets[bkt_index].max_dwell_time_active,
3056 req_msg->buckets[bkt_index].min_dwell_time_passive,
3057 req_msg->buckets[bkt_index].max_dwell_time_passive);
3058
3059 bkt_index++;
3060 req_msg->numBuckets++;
3061 }
3062
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003063 hdd_debug("Global: actv_min:%d actv_max:%d pass_min:%d pass_max:%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003064 req_msg->min_dwell_time_active,
3065 req_msg->max_dwell_time_active,
3066 req_msg->min_dwell_time_passive,
3067 req_msg->max_dwell_time_passive);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003068 return 0;
3069}
3070
3071/*
3072 * hdd_extscan_map_usr_drv_config_flags() - map userspace to driver config flags
3073 * @config_flags - [input] configuration flags.
3074 *
3075 * This function maps user space received configuration flags to
3076 * driver representation.
3077 *
3078 * Return: configuration flags
3079 */
3080static uint32_t hdd_extscan_map_usr_drv_config_flags(uint32_t config_flags)
3081{
3082 uint32_t configuration_flags = 0;
3083
3084 if (config_flags & EXTSCAN_LP_EXTENDED_BATCHING)
3085 configuration_flags |= EXTSCAN_LP_EXTENDED_BATCHING;
3086
3087 return configuration_flags;
3088}
3089
3090/*
3091 * define short names for the global vendor params
3092 * used by __wlan_hdd_cfg80211_extscan_start()
3093 */
3094#define PARAM_MAX \
3095 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3096#define PARAM_REQUEST_ID \
3097 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3098#define PARAM_BASE_PERIOD \
3099 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_BASE_PERIOD
3100#define PARAM_MAX_AP_PER_SCAN \
3101 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN
3102#define PARAM_RPT_THRHLD_PERCENT \
3103 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT
3104#define PARAM_RPT_THRHLD_NUM_SCANS \
3105 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS
3106#define PARAM_NUM_BUCKETS \
3107 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS
3108#define PARAM_CONFIG_FLAGS \
3109 QCA_WLAN_VENDOR_ATTR_EXTSCAN_CONFIGURATION_FLAGS
3110
3111/**
3112 * __wlan_hdd_cfg80211_extscan_start() - ext scan start
3113 * @wiphy: Pointer to wireless phy
3114 * @wdev: Pointer to wireless device
3115 * @data: Pointer to data
3116 * @data_len: Length of @data
3117 *
3118 * Return: 0 on success; error number otherwise
3119 */
3120static int
3121__wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3122 struct wireless_dev *wdev,
3123 const void *data,
3124 int data_len)
3125{
3126 tpSirWifiScanCmdReqParams pReqMsg = NULL;
3127 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07003128 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07003129 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003130 struct nlattr *tb[PARAM_MAX + 1];
3131 struct hdd_ext_scan_context *context;
3132 uint32_t request_id, num_buckets;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303133 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003134 int retval;
3135 unsigned long rc;
3136
Jeff Johnson1f61b612016-02-12 16:28:33 -08003137 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003138
Anurag Chouhan6d760662016-02-20 16:05:43 +05303139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003140 hdd_err("Command not allowed in FTM mode");
3141 return -EPERM;
3142 }
3143
3144 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303145 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003147
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303148 if (!pHddCtx->config->extscan_enabled) {
3149 hdd_err("extscan not supported");
3150 return -ENOTSUPP;
3151 }
Dustin Brown3fb15042017-08-15 15:54:49 -07003152 if (hdd_nla_parse(tb, PARAM_MAX, data, data_len,
3153 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003154 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003155 return -EINVAL;
3156 }
3157
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303158 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003159 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003160 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003161 return -ENOMEM;
3162 }
3163
3164 /* Parse and fetch request Id */
3165 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003166 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003167 goto fail;
3168 }
3169
3170 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3171 pReqMsg->sessionId = pAdapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172
3173 /* Parse and fetch base period */
3174 if (!tb[PARAM_BASE_PERIOD]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003175 hdd_err("attr base period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003176 goto fail;
3177 }
3178 pReqMsg->basePeriod = nla_get_u32(tb[PARAM_BASE_PERIOD]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003179
3180 /* Parse and fetch max AP per scan */
3181 if (!tb[PARAM_MAX_AP_PER_SCAN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003182 hdd_err("attr max_ap_per_scan failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003183 goto fail;
3184 }
3185 pReqMsg->maxAPperScan = nla_get_u32(tb[PARAM_MAX_AP_PER_SCAN]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003186
3187 /* Parse and fetch report threshold percent */
3188 if (!tb[PARAM_RPT_THRHLD_PERCENT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003189 hdd_err("attr report_threshold percent failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003190 goto fail;
3191 }
3192 pReqMsg->report_threshold_percent = nla_get_u8(tb[PARAM_RPT_THRHLD_PERCENT]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003193
3194 /* Parse and fetch report threshold num scans */
3195 if (!tb[PARAM_RPT_THRHLD_NUM_SCANS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003196 hdd_err("attr report_threshold num scans failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003197 goto fail;
3198 }
3199 pReqMsg->report_threshold_num_scans = nla_get_u8(tb[PARAM_RPT_THRHLD_NUM_SCANS]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003200 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 -07003201 pReqMsg->requestId, pReqMsg->sessionId,
3202 pReqMsg->basePeriod, pReqMsg->maxAPperScan,
3203 pReqMsg->report_threshold_percent,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003204 pReqMsg->report_threshold_num_scans);
3205
3206 /* Parse and fetch number of buckets */
3207 if (!tb[PARAM_NUM_BUCKETS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003208 hdd_err("attr number of buckets failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003209 goto fail;
3210 }
3211 num_buckets = nla_get_u8(tb[PARAM_NUM_BUCKETS]);
3212 if (num_buckets > WLAN_EXTSCAN_MAX_BUCKETS) {
3213 hdd_warn("Exceeded MAX number of buckets: %d",
3214 WLAN_EXTSCAN_MAX_BUCKETS);
Jeff Johnsonfae3c522016-11-11 17:57:13 -08003215 num_buckets = WLAN_EXTSCAN_MAX_BUCKETS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 }
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003217 hdd_debug("Input: Number of Buckets %d", num_buckets);
Jeff Johnsonfae3c522016-11-11 17:57:13 -08003218 pReqMsg->numBuckets = num_buckets;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003219
3220 /* This is optional attribute, if not present set it to 0 */
3221 if (!tb[PARAM_CONFIG_FLAGS])
3222 pReqMsg->configuration_flags = 0;
3223 else
3224 pReqMsg->configuration_flags =
3225 hdd_extscan_map_usr_drv_config_flags(
3226 nla_get_u32(tb[PARAM_CONFIG_FLAGS]));
3227
Gupta, Kapil96c7f2f2016-04-25 19:13:41 +05303228 pReqMsg->extscan_adaptive_dwell_mode =
3229 pHddCtx->config->extscan_adaptive_dwell_mode;
3230
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003231 hdd_debug("Configuration flags: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003232 pReqMsg->configuration_flags);
3233
3234 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003235 hdd_err("attr bucket spec failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 goto fail;
3237 }
3238
3239 if (hdd_extscan_start_fill_bucket_channel_spec(pHddCtx, pReqMsg, tb))
3240 goto fail;
3241
3242 context = &ext_scan_context;
3243 spin_lock(&context->context_lock);
3244 INIT_COMPLETION(context->response_event);
3245 context->request_id = request_id = pReqMsg->requestId;
Mukul Sharmafa937be2016-08-12 18:13:36 +05303246 context->buckets_scanned = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003247 spin_unlock(&context->context_lock);
3248
3249 status = sme_ext_scan_start(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303250 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003251 hdd_err("sme_ext_scan_start failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003252 goto fail;
3253 }
3254
Anurag Chouhan50220ce2016-02-18 20:11:33 +05303255 pHddCtx->ext_scan_start_since_boot = qdf_get_monotonic_boottime();
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003256 hdd_debug("Timestamp since boot: %llu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003257 pHddCtx->ext_scan_start_since_boot);
3258
3259 /* request was sent -- wait for the response */
3260 rc = wait_for_completion_timeout(&context->response_event,
3261 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3262
3263 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003264 hdd_err("sme_ext_scan_start timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003265 retval = -ETIMEDOUT;
3266 } else {
3267 spin_lock(&context->context_lock);
3268 if (context->request_id == request_id)
3269 retval = context->response_status;
3270 else
3271 retval = -EINVAL;
3272 spin_unlock(&context->context_lock);
3273 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303274 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003275 return retval;
3276
3277fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303278 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003279 return -EINVAL;
3280}
3281/*
3282 * done with short names for the global vendor params
3283 * used by __wlan_hdd_cfg80211_extscan_start()
3284 */
3285#undef PARAM_MAX
3286#undef PARAM_REQUEST_ID
3287#undef PARAM_BASE_PERIOD
3288#undef PARAMS_MAX_AP_PER_SCAN
3289#undef PARAMS_RPT_THRHLD_PERCENT
3290#undef PARAMS_RPT_THRHLD_NUM_SCANS
3291#undef PARAMS_NUM_BUCKETS
3292#undef PARAM_CONFIG_FLAGS
3293
3294/**
3295 * wlan_hdd_cfg80211_extscan_start() - start extscan
3296 * @wiphy: Pointer to wireless phy.
3297 * @wdev: Pointer to wireless device.
3298 * @data: Pointer to input data.
3299 * @data_len: Length of @data.
3300 *
3301 * Return: 0 on success, negative errno on failure
3302 */
3303int wlan_hdd_cfg80211_extscan_start(struct wiphy *wiphy,
3304 struct wireless_dev *wdev,
3305 const void *data, int data_len)
3306{
3307 int ret = 0;
3308
3309 cds_ssr_protect(__func__);
3310 ret = __wlan_hdd_cfg80211_extscan_start(wiphy, wdev, data, data_len);
3311 cds_ssr_unprotect(__func__);
3312
3313 return ret;
3314}
3315
3316
3317/*
3318 * define short names for the global vendor params
3319 * used by __wlan_hdd_cfg80211_extscan_stop()
3320 */
3321#define PARAM_MAX \
3322 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
3323#define PARAM_REQUEST_ID \
3324 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
3325
3326/**
3327 * __wlan_hdd_cfg80211_extscan_stop() - ext scan stop
3328 * @wiphy: Pointer to wireless phy
3329 * @wdev: Pointer to wireless device
3330 * @data: Pointer to data
3331 * @data_len: Data length
3332 *
3333 * Return: none
3334 */
3335static int
3336__wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3337 struct wireless_dev *wdev,
3338 const void *data, int data_len)
3339{
3340 tpSirExtScanStopReqParams pReqMsg = NULL;
3341 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07003342 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07003343 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003344 struct nlattr *tb[PARAM_MAX + 1];
3345 struct hdd_ext_scan_context *context;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303346 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 uint32_t request_id;
3348 int retval;
3349 unsigned long rc;
3350
Jeff Johnson1f61b612016-02-12 16:28:33 -08003351 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352
Anurag Chouhan6d760662016-02-20 16:05:43 +05303353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003354 hdd_err("Command not allowed in FTM mode");
3355 return -EPERM;
3356 }
3357
3358 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303359 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003360 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003361
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303362 if (!pHddCtx->config->extscan_enabled) {
3363 hdd_err("extscan not supported");
3364 return -ENOTSUPP;
3365 }
Dustin Brown3fb15042017-08-15 15:54:49 -07003366 if (hdd_nla_parse(tb, PARAM_MAX, data, data_len,
3367 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003368 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003369 return -EINVAL;
3370 }
3371
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303372 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003373 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003374 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003375 return -ENOMEM;
3376 }
3377
3378 /* Parse and fetch request Id */
3379 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003380 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003381 goto fail;
3382 }
3383
3384 pReqMsg->requestId = nla_get_u32(tb[PARAM_REQUEST_ID]);
3385 pReqMsg->sessionId = pAdapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003386 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003387 pReqMsg->requestId, pReqMsg->sessionId);
3388
3389 context = &ext_scan_context;
3390 spin_lock(&context->context_lock);
3391 INIT_COMPLETION(context->response_event);
3392 context->request_id = request_id = pReqMsg->requestId;
3393 spin_unlock(&context->context_lock);
3394
3395 status = sme_ext_scan_stop(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303396 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003397 hdd_err("sme_ext_scan_stop failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003398 goto fail;
3399 }
3400
3401 /* request was sent -- wait for the response */
3402 rc = wait_for_completion_timeout(&context->response_event,
3403 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3404
3405 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003406 hdd_err("sme_ext_scan_stop timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003407 retval = -ETIMEDOUT;
3408 } else {
3409 spin_lock(&context->context_lock);
3410 if (context->request_id == request_id)
3411 retval = context->response_status;
3412 else
3413 retval = -EINVAL;
3414 spin_unlock(&context->context_lock);
3415 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303416 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417 return retval;
3418
3419fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303420 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003421 return -EINVAL;
3422}
3423/*
3424 * done with short names for the global vendor params
3425 * used by wlan_hdd_cfg80211_extscan_stop()
3426 */
3427#undef PARAM_MAX
3428#undef PARAM_REQUEST_ID
3429
3430
3431/**
3432 * wlan_hdd_cfg80211_extscan_stop() - stop extscan
3433 * @wiphy: Pointer to wireless phy.
3434 * @wdev: Pointer to wireless device.
3435 * @data: Pointer to input data.
3436 * @data_len: Length of @data.
3437 *
3438 * Return: 0 on success, negative errno on failure
3439 */
3440int wlan_hdd_cfg80211_extscan_stop(struct wiphy *wiphy,
3441 struct wireless_dev *wdev,
3442 const void *data, int data_len)
3443{
3444 int ret = 0;
3445
3446 cds_ssr_protect(__func__);
3447 ret = __wlan_hdd_cfg80211_extscan_stop(wiphy, wdev, data, data_len);
3448 cds_ssr_unprotect(__func__);
3449
3450 return ret;
3451}
3452
3453
3454/**
3455 * __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hotlist
3456 * @wiphy: Pointer to wireless phy
3457 * @wdev: Pointer to wireless device
3458 * @data: Pointer to data
3459 * @data_len: Data length
3460 *
3461 * Return: none
3462 */
3463static int
3464__wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3465 struct wireless_dev
3466 *wdev, const void *data,
3467 int data_len)
3468{
3469 tpSirExtScanResetBssidHotlistReqParams pReqMsg = NULL;
3470 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07003471 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07003472 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3474 1];
3475 struct hdd_ext_scan_context *context;
3476 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303477 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003478 int retval;
3479 unsigned long rc;
3480
Jeff Johnson1f61b612016-02-12 16:28:33 -08003481 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482
Anurag Chouhan6d760662016-02-20 16:05:43 +05303483 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003484 hdd_err("Command not allowed in FTM mode");
3485 return -EPERM;
3486 }
3487
3488 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303489 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303492 if (!pHddCtx->config->extscan_enabled) {
3493 hdd_err("extscan not supported");
3494 return -ENOTSUPP;
3495 }
Dustin Brown3fb15042017-08-15 15:54:49 -07003496 if (hdd_nla_parse(tb,
3497 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3498 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003499 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003500 return -EINVAL;
3501 }
3502
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303503 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003504 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003505 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506 return -ENOMEM;
3507 }
3508
3509 /* Parse and fetch request Id */
3510 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003511 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003512 goto fail;
3513 }
3514
3515 pReqMsg->requestId =
3516 nla_get_u32(tb
3517 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3518 pReqMsg->sessionId = pAdapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003519 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003520 pReqMsg->requestId, pReqMsg->sessionId);
3521
3522 context = &ext_scan_context;
3523 spin_lock(&context->context_lock);
3524 INIT_COMPLETION(context->response_event);
3525 context->request_id = request_id = pReqMsg->requestId;
3526 spin_unlock(&context->context_lock);
3527
3528 status = sme_reset_bss_hotlist(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303529 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003530 hdd_err("sme_reset_bss_hotlist failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 goto fail;
3532 }
3533
3534 /* request was sent -- wait for the response */
3535 rc = wait_for_completion_timeout
3536 (&context->response_event,
3537 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3538 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003539 hdd_err("sme_reset_bss_hotlist timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003540 retval = -ETIMEDOUT;
3541 } else {
3542 spin_lock(&context->context_lock);
3543 if (context->request_id == request_id)
3544 retval = context->response_status;
3545 else
3546 retval = -EINVAL;
3547 spin_unlock(&context->context_lock);
3548 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303549 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003550 return retval;
3551
3552fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303553 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554 return -EINVAL;
3555}
3556
3557/**
3558 * wlan_hdd_cfg80211_extscan_reset_bssid_hotlist() - reset bssid hot list
3559 * @wiphy: Pointer to wireless phy
3560 * @wdev: Pointer to wireless device
3561 * @data: Pointer to data
3562 * @data_len: Data length
3563 *
3564 * Return: 0 on success, negative errno on failure
3565 */
3566int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
3567 struct wireless_dev *wdev,
3568 const void *data, int data_len)
3569{
3570 int ret = 0;
3571
3572 cds_ssr_protect(__func__);
3573 ret = __wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(wiphy, wdev,
3574 data, data_len);
3575 cds_ssr_unprotect(__func__);
3576
3577 return ret;
3578}
3579
3580/**
3581 * __wlan_hdd_cfg80211_extscan_reset_significant_change() -
3582 * reset significant change
3583 * @wiphy: Pointer to wireless phy
3584 * @wdev: Pointer to wireless device
3585 * @data: Pointer to data
3586 * @data_len: Data length
3587 *
3588 * Return: none
3589 */
3590static int
3591__wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy
3592 *wiphy,
3593 struct
3594 wireless_dev
3595 *wdev, const void *data,
3596 int data_len)
3597{
3598 tpSirExtScanResetSignificantChangeReqParams pReqMsg = NULL;
3599 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07003600 struct hdd_adapter *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07003601 struct hdd_context *pHddCtx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX +
3603 1];
3604 struct hdd_ext_scan_context *context;
3605 uint32_t request_id;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303606 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 int retval;
3608 unsigned long rc;
3609
Jeff Johnson1f61b612016-02-12 16:28:33 -08003610 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003611
Anurag Chouhan6d760662016-02-20 16:05:43 +05303612 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003613 hdd_err("Command not allowed in FTM mode");
3614 return -EPERM;
3615 }
3616
3617 retval = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303618 if (0 != retval)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003619 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003620
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303621 if (!pHddCtx->config->extscan_enabled) {
3622 hdd_err("extscan not supported");
3623 return -ENOTSUPP;
3624 }
Dustin Brown3fb15042017-08-15 15:54:49 -07003625
3626 if (hdd_nla_parse(tb,
3627 QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
3628 data, data_len, wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003629 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003630 return -EINVAL;
3631 }
3632
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303633 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003634 if (!pReqMsg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003635 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003636 return -ENOMEM;
3637 }
3638
3639 /* Parse and fetch request Id */
3640 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003641 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003642 goto fail;
3643 }
3644
3645 pReqMsg->requestId =
3646 nla_get_u32(tb
3647 [QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
3648 pReqMsg->sessionId = pAdapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003649 hdd_debug("Req Id %d Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003650 pReqMsg->requestId, pReqMsg->sessionId);
3651
3652 context = &ext_scan_context;
3653 spin_lock(&context->context_lock);
3654 INIT_COMPLETION(context->response_event);
3655 context->request_id = request_id = pReqMsg->requestId;
3656 spin_unlock(&context->context_lock);
3657
3658 status = sme_reset_significant_change(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303659 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003660 hdd_err("sme_reset_significant_change failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661 status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303662 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003663 return -EINVAL;
3664 }
3665
3666 /* request was sent -- wait for the response */
3667 rc = wait_for_completion_timeout(&context->response_event,
3668 msecs_to_jiffies(WLAN_WAIT_TIME_EXTSCAN));
3669
3670 if (!rc) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003671 hdd_err("sme_ResetSignificantChange timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003672 retval = -ETIMEDOUT;
3673 } else {
3674 spin_lock(&context->context_lock);
3675 if (context->request_id == request_id)
3676 retval = context->response_status;
3677 else
3678 retval = -EINVAL;
3679 spin_unlock(&context->context_lock);
3680 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303681 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003682 return retval;
3683
3684fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303685 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003686 return -EINVAL;
3687}
3688
3689/**
3690 * wlan_hdd_cfg80211_extscan_reset_significant_change() - reset significant
3691 * change
3692 * @wiphy: Pointer to wireless phy
3693 * @wdev: Pointer to wireless device
3694 * @data: Pointer to data
3695 * @data_len: Data length
3696 *
3697 * Return: 0 on success, negative errno on failure
3698 */
3699int wlan_hdd_cfg80211_extscan_reset_significant_change(struct wiphy *wiphy,
3700 struct wireless_dev *wdev,
3701 const void *data, int data_len)
3702{
3703 int ret = 0;
3704
3705 cds_ssr_protect(__func__);
3706 ret = __wlan_hdd_cfg80211_extscan_reset_significant_change(wiphy, wdev,
3707 data, data_len);
3708 cds_ssr_unprotect(__func__);
3709
3710 return ret;
3711}
3712
3713
3714/**
3715 * hdd_extscan_epno_fill_network_list() - epno fill network list
3716 * @hddctx: HDD context
3717 * @req_msg: request message
3718 * @tb: vendor attribute table
3719 *
3720 * This function reads the network block NL vendor attributes from %tb and
3721 * fill in the epno request message.
3722 *
3723 * Return: 0 on success, error number otherwise
3724 */
3725static int hdd_extscan_epno_fill_network_list(
Jeff Johnson9755a512017-08-28 12:01:57 -07003726 struct hdd_context *hddctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003727 struct wifi_epno_params *req_msg,
3728 struct nlattr **tb)
3729{
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003730 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003731 struct nlattr *networks;
3732 int rem1, ssid_len;
3733 uint8_t index, *ssid;
Jeff Johnson14305e62016-11-11 17:37:54 -08003734 uint32_t expected_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003735
Jeff Johnson14305e62016-11-11 17:37:54 -08003736 expected_networks = req_msg->num_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003737 index = 0;
SaidiReddy Yenugac5332022017-03-28 17:16:48 +05303738
3739 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST]) {
3740 hdd_err("attr networks list failed");
3741 return -EINVAL;
3742 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003743 nla_for_each_nested(networks,
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003744 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST],
3745 rem1) {
Jeff Johnson14305e62016-11-11 17:37:54 -08003746
3747 if (index == expected_networks) {
3748 hdd_warn("ignoring excess networks");
3749 break;
3750 }
3751
Dustin Brown3fb15042017-08-15 15:54:49 -07003752 if (hdd_nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3753 nla_data(networks), nla_len(networks),
3754 wlan_hdd_pno_config_policy)) {
3755 hdd_err("hdd_nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003756 return -EINVAL;
3757 }
3758
3759 /* Parse and fetch ssid */
3760 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003761 hdd_err("attr network ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003762 return -EINVAL;
3763 }
3764 ssid_len = nla_len(
3765 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
3766
Dustin Brown3fb15042017-08-15 15:54:49 -07003767 /* hdd_nla_parse will detect overflow but not underflow */
Jeff Johnsonfa484bb2016-11-09 09:01:10 -08003768 if (0 == ssid_len) {
3769 hdd_err("zero ssid length");
3770 return -EINVAL;
3771 }
3772
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003773 /* Decrement by 1, don't count null character */
3774 ssid_len--;
3775
3776 req_msg->networks[index].ssid.length = ssid_len;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003777 hdd_debug("network ssid length %d", ssid_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 ssid = nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID]);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303779 qdf_mem_copy(req_msg->networks[index].ssid.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003780 ssid, ssid_len);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003781 hdd_debug("Ssid (%.*s)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003782 req_msg->networks[index].ssid.length,
3783 req_msg->networks[index].ssid.ssId);
3784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003785 /* Parse and fetch epno flags */
3786 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003787 hdd_err("attr epno flags failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003788 return -EINVAL;
3789 }
3790 req_msg->networks[index].flags = nla_get_u8(
3791 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003792 hdd_debug("flags %u", req_msg->networks[index].flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003793
3794 /* Parse and fetch auth bit */
3795 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003796 hdd_err("attr auth bit failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003797 return -EINVAL;
3798 }
3799 req_msg->networks[index].auth_bit_field = nla_get_u8(
3800 network[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003801 hdd_debug("auth bit %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003802 req_msg->networks[index].auth_bit_field);
3803
3804 index++;
3805 }
Jeff Johnson14305e62016-11-11 17:37:54 -08003806 req_msg->num_networks = index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003807 return 0;
3808}
3809
3810/**
3811 * __wlan_hdd_cfg80211_set_epno_list() - epno set network list
3812 * @wiphy: wiphy
3813 * @wdev: pointer to wireless dev
3814 * @data: data pointer
3815 * @data_len: data length
3816 *
3817 * This function reads the NL vendor attributes from %tb and
3818 * fill in the epno request message.
3819 *
3820 * Return: 0 on success, error number otherwise
3821 */
3822static int __wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
3823 struct wireless_dev *wdev,
3824 const void *data,
3825 int data_len)
3826{
3827 struct wifi_epno_params *req_msg = NULL;
3828 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07003829 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07003830 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 struct nlattr *tb[
3832 QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303833 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003834 uint32_t num_networks, len;
3835 int ret_val;
3836
Jeff Johnson1f61b612016-02-12 16:28:33 -08003837 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003838
3839 ret_val = wlan_hdd_validate_context(hdd_ctx);
3840 if (ret_val)
3841 return ret_val;
3842
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303843 if (!hdd_ctx->config->extscan_enabled) {
3844 hdd_err("extscan not supported");
3845 return -ENOTSUPP;
3846 }
Dustin Brown3fb15042017-08-15 15:54:49 -07003847
Anurag Chouhan6d760662016-02-20 16:05:43 +05303848 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849 hdd_err("Command not allowed in FTM mode");
3850 return -EPERM;
3851 }
3852
Dustin Brown3fb15042017-08-15 15:54:49 -07003853 if (hdd_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
3854 data, data_len, wlan_hdd_pno_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003855 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003856 return -EINVAL;
3857 }
3858
3859 /* Parse and fetch number of networks */
3860 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003861 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003862 return -EINVAL;
3863 }
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303864
3865 /*
3866 * num_networks is also used as EPNO SET/RESET request.
3867 * if num_networks is zero then it is treated as RESET.
3868 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003869 num_networks = nla_get_u32(
3870 tb[QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003871
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303872 if (num_networks > MAX_EPNO_NETWORKS) {
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003873 hdd_debug("num of nw: %d exceeded max: %d, resetting to: %d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303874 num_networks, MAX_EPNO_NETWORKS, MAX_EPNO_NETWORKS);
3875 num_networks = MAX_EPNO_NETWORKS;
3876 }
3877
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003878 hdd_debug("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 len = sizeof(*req_msg) +
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303880 (num_networks * sizeof(struct wifi_epno_network));
3881
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303882 req_msg = qdf_mem_malloc(len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003884 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 return -ENOMEM;
3886 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003887 req_msg->num_networks = num_networks;
3888
3889 /* Parse and fetch request Id */
3890 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003891 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892 goto fail;
3893 }
3894 req_msg->request_id = nla_get_u32(
3895 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003896 hdd_debug("Req Id %u", req_msg->request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897
3898 req_msg->session_id = adapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003899 hdd_debug("Session Id %d", req_msg->session_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003900
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303901 if (num_networks) {
3902
3903 /* Parse and fetch min_5ghz_rssi */
3904 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]) {
3905 hdd_err("min_5ghz_rssi id failed");
3906 goto fail;
3907 }
3908 req_msg->min_5ghz_rssi = nla_get_u32(
3909 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI]);
3910
3911 /* Parse and fetch min_24ghz_rssi */
3912 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]) {
3913 hdd_err("min_24ghz_rssi id failed");
3914 goto fail;
3915 }
3916 req_msg->min_24ghz_rssi = nla_get_u32(
3917 tb[QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI]);
3918
3919 /* Parse and fetch initial_score_max */
3920 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]) {
3921 hdd_err("initial_score_max id failed");
3922 goto fail;
3923 }
3924 req_msg->initial_score_max = nla_get_u32(
3925 tb[QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX]);
3926
3927 /* Parse and fetch current_connection_bonus */
3928 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]) {
3929 hdd_err("current_connection_bonus id failed");
3930 goto fail;
3931 }
3932 req_msg->current_connection_bonus = nla_get_u32(
3933 tb[QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS]
3934 );
3935
3936 /* Parse and fetch same_network_bonus */
3937 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]) {
3938 hdd_err("same_network_bonus id failed");
3939 goto fail;
3940 }
3941 req_msg->same_network_bonus = nla_get_u32(
3942 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS]);
3943
3944 /* Parse and fetch secure_bonus */
3945 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]) {
3946 hdd_err("secure_bonus id failed");
3947 goto fail;
3948 }
3949 req_msg->secure_bonus = nla_get_u32(
3950 tb[QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS]);
3951
3952 /* Parse and fetch band_5ghz_bonus */
3953 if (!tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]) {
3954 hdd_err("band_5ghz_bonus id failed");
3955 goto fail;
3956 }
3957 req_msg->band_5ghz_bonus = nla_get_u32(
3958 tb[QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS]);
3959
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003960 hdd_debug("min_5ghz_rssi: %d min_24ghz_rssi: %d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303961 req_msg->min_5ghz_rssi,
3962 req_msg->min_24ghz_rssi);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003963 hdd_debug("initial_score_max: %d current_connection_bonus:%d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303964 req_msg->initial_score_max,
3965 req_msg->current_connection_bonus);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08003966 hdd_debug("Bonuses same_network: %d secure: %d band_5ghz: %d",
Mukul Sharmae8c919f2016-10-02 20:35:15 +05303967 req_msg->same_network_bonus,
3968 req_msg->secure_bonus,
3969 req_msg->band_5ghz_bonus);
3970
3971 if (hdd_extscan_epno_fill_network_list(hdd_ctx, req_msg, tb))
3972 goto fail;
3973
3974 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003975
3976 status = sme_set_epno_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303977 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07003978 hdd_err("sme_set_epno_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 goto fail;
3980 }
3981
3982 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303983 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003984 return 0;
3985
3986fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303987 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003988 return -EINVAL;
3989}
3990
Jeff Johnson9dc96a02017-01-12 09:47:56 -08003991/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003992 * wlan_hdd_cfg80211_set_epno_list() - epno set network list
3993 * @wiphy: wiphy
3994 * @wdev: pointer to wireless dev
3995 * @data: data pointer
3996 * @data_len: data length
3997 *
3998 * This function reads the NL vendor attributes from %tb and
3999 * fill in the epno request message.
4000 *
4001 * Return: 0 on success, error number otherwise
4002 */
4003int wlan_hdd_cfg80211_set_epno_list(struct wiphy *wiphy,
4004 struct wireless_dev *wdev,
4005 const void *data,
4006 int data_len)
4007{
4008 int ret;
4009
4010 cds_ssr_protect(__func__);
4011 ret = __wlan_hdd_cfg80211_set_epno_list(wiphy, wdev,
4012 data, data_len);
4013 cds_ssr_unprotect(__func__);
4014
4015 return ret;
4016}
4017
4018/**
4019 * hdd_extscan_passpoint_fill_network_list() - passpoint fill network list
4020 * @hddctx: HDD context
4021 * @req_msg: request message
4022 * @tb: vendor attribute table
4023 *
4024 * This function reads the network block NL vendor attributes from %tb and
4025 * fill in the passpoint request message.
4026 *
4027 * Return: 0 on success, error number otherwise
4028 */
4029static int hdd_extscan_passpoint_fill_network_list(
Jeff Johnson9755a512017-08-28 12:01:57 -07004030 struct hdd_context *hddctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 struct wifi_passpoint_req *req_msg,
4032 struct nlattr **tb)
4033{
4034 struct nlattr *network[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
4035 struct nlattr *networks;
4036 int rem1, len;
4037 uint8_t index;
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004038 uint32_t expected_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004039
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004040 expected_networks = req_msg->num_networks;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004041 index = 0;
SaidiReddy Yenuga8c85acb2017-03-28 17:23:55 +05304042
4043 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY]) {
4044 hdd_err("attr network array failed");
4045 return -EINVAL;
4046 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004047 nla_for_each_nested(networks,
4048 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY],
4049 rem1) {
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004050
4051 if (index == expected_networks) {
4052 hdd_warn("ignoring excess networks");
4053 break;
4054 }
4055
Dustin Brown3fb15042017-08-15 15:54:49 -07004056 if (hdd_nla_parse(network, QCA_WLAN_VENDOR_ATTR_PNO_MAX,
4057 nla_data(networks), nla_len(networks),
4058 wlan_hdd_pno_config_policy)) {
4059 hdd_err("hdd_nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004060 return -EINVAL;
4061 }
4062
4063 /* Parse and fetch identifier */
4064 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004065 hdd_err("attr passpoint id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004066 return -EINVAL;
4067 }
4068 req_msg->networks[index].id = nla_get_u32(
4069 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID]);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004070 hdd_debug("Id %u", req_msg->networks[index].id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004071
4072 /* Parse and fetch realm */
4073 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004074 hdd_err("attr realm failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 return -EINVAL;
4076 }
4077 len = nla_len(
4078 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]);
4079 if (len < 0 || len > SIR_PASSPOINT_REALM_LEN) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004080 hdd_err("Invalid realm size %d", len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004081 return -EINVAL;
4082 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304083 qdf_mem_copy(req_msg->networks[index].realm,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004084 nla_data(network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM]),
4085 len);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004086 hdd_debug("realm len %d", len);
4087 hdd_debug("realm: %s", req_msg->networks[index].realm);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004088
4089 /* Parse and fetch roaming consortium ids */
4090 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004091 hdd_err("attr roaming consortium ids failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004092 return -EINVAL;
4093 }
4094 nla_memcpy(&req_msg->networks[index].roaming_consortium_ids,
4095 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID],
4096 sizeof(req_msg->networks[0].roaming_consortium_ids));
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004097 hdd_debug("roaming consortium ids");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004098
4099 /* Parse and fetch plmn */
4100 if (!network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004101 hdd_err("attr plmn failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004102 return -EINVAL;
4103 }
4104 nla_memcpy(&req_msg->networks[index].plmn,
4105 network[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN],
4106 SIR_PASSPOINT_PLMN_LEN);
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004107 hdd_debug("plmn %02x:%02x:%02x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 req_msg->networks[index].plmn[0],
4109 req_msg->networks[index].plmn[1],
4110 req_msg->networks[index].plmn[2]);
4111
4112 index++;
4113 }
Jeff Johnson1263a5d2016-11-18 11:44:29 -08004114 req_msg->num_networks = index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004115 return 0;
4116}
4117
4118/**
4119 * __wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4120 * @wiphy: wiphy
4121 * @wdev: pointer to wireless dev
4122 * @data: data pointer
4123 * @data_len: data length
4124 *
4125 * This function reads the NL vendor attributes from %tb and
4126 * fill in the passpoint request message.
4127 *
4128 * Return: 0 on success, error number otherwise
4129 */
4130static int __wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4131 struct wireless_dev *wdev,
4132 const void *data,
4133 int data_len)
4134{
4135 struct wifi_passpoint_req *req_msg = NULL;
4136 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07004137 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07004138 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304140 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004141 uint32_t num_networks = 0;
4142 int ret;
4143
Jeff Johnson1f61b612016-02-12 16:28:33 -08004144 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004145
4146 ret = wlan_hdd_validate_context(hdd_ctx);
4147 if (ret)
4148 return ret;
4149
Anurag Chouhan6d760662016-02-20 16:05:43 +05304150 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004151 hdd_err("Command not allowed in FTM mode");
4152 return -EPERM;
4153 }
4154
Dustin Brown3fb15042017-08-15 15:54:49 -07004155 if (hdd_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4156 wlan_hdd_pno_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004157 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 return -EINVAL;
4159 }
4160
4161 /* Parse and fetch number of networks */
4162 if (!tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004163 hdd_err("attr num networks failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 return -EINVAL;
4165 }
4166 num_networks = nla_get_u32(
4167 tb[QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM]);
Jeff Johnson96f93a32016-11-18 11:02:24 -08004168 if (num_networks > SIR_PASSPOINT_LIST_MAX_NETWORKS) {
4169 hdd_err("num networks %u exceeds max %u",
4170 num_networks, SIR_PASSPOINT_LIST_MAX_NETWORKS);
4171 return -EINVAL;
4172 }
4173
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004174 hdd_debug("num networks %u", num_networks);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004175
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304176 req_msg = qdf_mem_malloc(sizeof(*req_msg) +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004177 (num_networks * sizeof(req_msg->networks[0])));
4178 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004179 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 return -ENOMEM;
4181 }
4182 req_msg->num_networks = num_networks;
4183
4184 /* Parse and fetch request Id */
4185 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004186 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004187 goto fail;
4188 }
4189 req_msg->request_id = nla_get_u32(
4190 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4191
4192 req_msg->session_id = adapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004193 hdd_debug("Req Id %u Session Id %d", req_msg->request_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004194 req_msg->session_id);
4195
4196 if (hdd_extscan_passpoint_fill_network_list(hdd_ctx, req_msg, tb))
4197 goto fail;
4198
4199 status = sme_set_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304200 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004201 hdd_err("sme_set_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004202 goto fail;
4203 }
4204
4205 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304206 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004207 return 0;
4208
4209fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304210 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004211 return -EINVAL;
4212}
4213
4214/**
4215 * wlan_hdd_cfg80211_set_passpoint_list() - set passpoint network list
4216 * @wiphy: wiphy
4217 * @wdev: pointer to wireless dev
4218 * @data: data pointer
4219 * @data_len: data length
4220 *
4221 * This function reads the NL vendor attributes from %tb and
4222 * fill in the passpoint request message.
4223 *
4224 * Return: 0 on success, error number otherwise
4225 */
4226int wlan_hdd_cfg80211_set_passpoint_list(struct wiphy *wiphy,
4227 struct wireless_dev *wdev,
4228 const void *data,
4229 int data_len)
4230{
4231 int ret;
4232
4233 cds_ssr_protect(__func__);
4234 ret = __wlan_hdd_cfg80211_set_passpoint_list(wiphy, wdev,
4235 data, data_len);
4236 cds_ssr_unprotect(__func__);
4237
4238 return ret;
4239}
4240
4241/**
4242 * __wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4243 * @wiphy: wiphy
4244 * @wdev: pointer to wireless dev
4245 * @data: data pointer
4246 * @data_len: data length
4247 *
4248 * This function resets passpoint networks list
4249 *
4250 * Return: 0 on success, error number otherwise
4251 */
4252static int __wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4253 struct wireless_dev *wdev,
4254 const void *data,
4255 int data_len)
4256{
4257 struct wifi_passpoint_req *req_msg = NULL;
4258 struct net_device *dev = wdev->netdev;
Jeff Johnson652d45b2017-08-29 14:35:56 -07004259 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson9755a512017-08-28 12:01:57 -07004260 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PNO_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304262 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004263 int ret;
4264
Jeff Johnson1f61b612016-02-12 16:28:33 -08004265 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004266
4267 ret = wlan_hdd_validate_context(hdd_ctx);
4268 if (ret)
4269 return ret;
4270
Anurag Chouhan6d760662016-02-20 16:05:43 +05304271 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 hdd_err("Command not allowed in FTM mode");
4273 return -EPERM;
4274 }
4275
Dustin Brown3fb15042017-08-15 15:54:49 -07004276 if (hdd_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PNO_MAX, data, data_len,
4277 wlan_hdd_extscan_config_policy)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004278 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 return -EINVAL;
4280 }
4281
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304282 req_msg = qdf_mem_malloc(sizeof(*req_msg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004283 if (!req_msg) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004284 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285 return -ENOMEM;
4286 }
4287
4288 /* Parse and fetch request Id */
4289 if (!tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004290 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004291 goto fail;
4292 }
4293 req_msg->request_id = nla_get_u32(
4294 tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID]);
4295
4296 req_msg->session_id = adapter->sessionId;
Srinivas Girigowda5736c5c2017-03-06 16:31:40 -08004297 hdd_debug("Req Id %u Session Id %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298 req_msg->request_id, req_msg->session_id);
4299
4300 status = sme_reset_passpoint_list(hdd_ctx->hHal, req_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304301 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson630f9e72016-07-25 12:00:12 -07004302 hdd_err("sme_reset_passpoint_list failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004303 goto fail;
4304 }
4305
4306 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304307 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004308 return 0;
4309
4310fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304311 qdf_mem_free(req_msg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 return -EINVAL;
4313}
4314
4315/**
4316 * wlan_hdd_cfg80211_reset_passpoint_list() - reset passpoint network list
4317 * @wiphy: wiphy
4318 * @wdev: pointer to wireless dev
4319 * @data: data pointer
4320 * @data_len: data length
4321 *
4322 * This function resets passpoint networks list
4323 *
4324 * Return: 0 on success, error number otherwise
4325 */
4326int wlan_hdd_cfg80211_reset_passpoint_list(struct wiphy *wiphy,
4327 struct wireless_dev *wdev,
4328 const void *data,
4329 int data_len)
4330{
4331 int ret;
4332
4333 cds_ssr_protect(__func__);
4334 ret = __wlan_hdd_cfg80211_reset_passpoint_list(wiphy, wdev,
4335 data, data_len);
4336 cds_ssr_unprotect(__func__);
4337
4338 return ret;
4339}
4340
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341/**
4342 * wlan_hdd_init_completion_extwow() - Initialize ext wow variable
4343 * @hdd_ctx: Global HDD context
4344 *
4345 * Return: none
4346 */
4347#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
Jeff Johnson9755a512017-08-28 12:01:57 -07004348static inline void wlan_hdd_init_completion_extwow(struct hdd_context *pHddCtx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004349{
4350 init_completion(&pHddCtx->ready_to_extwow);
4351}
4352#else
Jeff Johnson9755a512017-08-28 12:01:57 -07004353static inline void wlan_hdd_init_completion_extwow(struct hdd_context *pHddCtx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355}
4356#endif
4357
4358/**
4359 * wlan_hdd_cfg80211_extscan_init() - Initialize the ExtScan feature
4360 * @hdd_ctx: Global HDD context
4361 *
4362 * Return: none
4363 */
Jeff Johnson9755a512017-08-28 12:01:57 -07004364void wlan_hdd_cfg80211_extscan_init(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004365{
4366 wlan_hdd_init_completion_extwow(hdd_ctx);
4367 init_completion(&ext_scan_context.response_event);
4368 spin_lock_init(&ext_scan_context.context_lock);
4369}
4370
4371#endif /* FEATURE_WLAN_EXTSCAN */