1 /*
2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: wlan_hdd_scan.c
22 *
23 * WLAN Host Device Driver scan implementation
24 */
25
26 #include <linux/wireless.h>
27 #include <net/cfg80211.h>
28
29 #include "wlan_hdd_includes.h"
30 #include "cds_api.h"
31 #include "cds_api.h"
32 #include "ani_global.h"
33 #include "dot11f.h"
34 #include "cds_sched.h"
35 #include "osif_sync.h"
36 #include "wlan_hdd_p2p.h"
37 #include "wlan_hdd_trace.h"
38 #include "wlan_hdd_scan.h"
39 #include "wlan_policy_mgr_api.h"
40 #include "wlan_hdd_power.h"
41 #include "wma_api.h"
42 #include "cds_utils.h"
43 #include "wlan_p2p_ucfg_api.h"
44 #include "cfg_ucfg_api.h"
45
46 #include <qca_vendor.h>
47 #include <wlan_cfg80211_scan.h>
48 #include "wlan_utility.h"
49 #include "wlan_hdd_object_manager.h"
50 #include "nan_ucfg_api.h"
51
52 #define SCAN_DONE_EVENT_BUF_SIZE 4096
53 #define RATE_MASK 0x7f
54
55 /**
56 * hdd_vendor_scan_callback() - Scan completed callback event
57 * @adapter: HDD adapter
58 * @req: Scan request
59 * @aborted: true scan aborted false scan success
60 *
61 * This function sends scan completed callback event to NL.
62 *
63 * Return: none
64 */
hdd_vendor_scan_callback(struct hdd_adapter * adapter,struct cfg80211_scan_request * req,bool aborted)65 static void hdd_vendor_scan_callback(struct hdd_adapter *adapter,
66 struct cfg80211_scan_request *req,
67 bool aborted)
68 {
69 struct hdd_context *hddctx = WLAN_HDD_GET_CTX(adapter);
70 struct sk_buff *skb;
71 struct nlattr *attr;
72 int i;
73 uint8_t scan_status;
74 uint64_t cookie;
75 enum qca_nl80211_vendor_subcmds_index index =
76 QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX;
77
78 hdd_enter();
79
80 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
81 hdd_err("Invalid adapter magic");
82 qdf_mem_free(req);
83 return;
84 }
85 skb = wlan_cfg80211_vendor_event_alloc(hddctx->wiphy, &adapter->wdev,
86 SCAN_DONE_EVENT_BUF_SIZE +
87 4 + NLMSG_HDRLEN,
88 index, GFP_KERNEL);
89 if (!skb) {
90 hdd_err("skb alloc failed");
91 qdf_mem_free(req);
92 return;
93 }
94
95 cookie = (uintptr_t)req;
96 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS);
97 if (!attr)
98 goto nla_put_failure;
99 for (i = 0; i < req->n_ssids; i++) {
100 if (nla_put(skb, i, req->ssids[i].ssid_len,
101 req->ssids[i].ssid)) {
102 hdd_err("Failed to add ssid");
103 goto nla_put_failure;
104 }
105 }
106 nla_nest_end(skb, attr);
107 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES);
108 if (!attr)
109 goto nla_put_failure;
110 for (i = 0; i < req->n_channels; i++) {
111 if (nla_put_u32(skb, i, req->channels[i]->center_freq)) {
112 hdd_err("Failed to add channel");
113 goto nla_put_failure;
114 }
115 }
116 nla_nest_end(skb, attr);
117
118 if (req->ie &&
119 nla_put(skb, QCA_WLAN_VENDOR_ATTR_SCAN_IE, req->ie_len,
120 req->ie)) {
121 hdd_err("Failed to add scan ie");
122 goto nla_put_failure;
123 }
124 if (req->flags &&
125 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS, req->flags)) {
126 hdd_err("Failed to add scan flags");
127 goto nla_put_failure;
128 }
129 if (hdd_wlan_nla_put_u64(skb,
130 QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE,
131 cookie)) {
132 hdd_err("Failed to add scan cookie");
133 goto nla_put_failure;
134 }
135 scan_status = (aborted == true) ? VENDOR_SCAN_STATUS_ABORTED :
136 VENDOR_SCAN_STATUS_NEW_RESULTS;
137 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, scan_status)) {
138 hdd_err("Failed to add scan status");
139 goto nla_put_failure;
140 }
141 wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
142 hdd_info("scan complete event sent to NL");
143 qdf_mem_free(req);
144 return;
145
146 nla_put_failure:
147 wlan_cfg80211_vendor_free_skb(skb);
148 qdf_mem_free(req);
149 }
150
151 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
152 /**
153 * hdd_cfg80211_scan_done() - Scan completed callback to cfg80211
154 * @adapter: Pointer to the adapter
155 * @req : Scan request
156 * @aborted : true scan aborted false scan success
157 *
158 * This function notifies scan done to cfg80211
159 *
160 * Return: none
161 */
hdd_cfg80211_scan_done(struct hdd_adapter * adapter,struct cfg80211_scan_request * req,bool aborted)162 static void hdd_cfg80211_scan_done(struct hdd_adapter *adapter,
163 struct cfg80211_scan_request *req,
164 bool aborted)
165 {
166 struct cfg80211_scan_info info = {
167 .aborted = aborted
168 };
169
170 if (adapter->dev->flags & IFF_UP)
171 cfg80211_scan_done(req, &info);
172 }
173 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
174 /**
175 * hdd_cfg80211_scan_done() - Scan completed callback to cfg80211
176 * @adapter: Pointer to the adapter
177 * @req : Scan request
178 * @aborted : true scan aborted false scan success
179 *
180 * This function notifies scan done to cfg80211
181 *
182 * Return: none
183 */
hdd_cfg80211_scan_done(struct hdd_adapter * adapter,struct cfg80211_scan_request * req,bool aborted)184 static void hdd_cfg80211_scan_done(struct hdd_adapter *adapter,
185 struct cfg80211_scan_request *req,
186 bool aborted)
187 {
188 if (adapter->dev->flags & IFF_UP)
189 cfg80211_scan_done(req, aborted);
190 }
191 #else
192 /**
193 * hdd_cfg80211_scan_done() - Scan completed callback to cfg80211
194 * @adapter: Pointer to the adapter
195 * @req : Scan request
196 * @aborted : true scan aborted false scan success
197 *
198 * This function notifies scan done to cfg80211
199 *
200 * Return: none
201 */
hdd_cfg80211_scan_done(struct hdd_adapter * adapter,struct cfg80211_scan_request * req,bool aborted)202 static void hdd_cfg80211_scan_done(struct hdd_adapter *adapter,
203 struct cfg80211_scan_request *req,
204 bool aborted)
205 {
206 cfg80211_scan_done(req, aborted);
207 }
208 #endif
209
210 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
211 /**
212 * wlan_hdd_sap_skip_scan_check() - The function will check OBSS
213 * scan skip or not for SAP.
214 * @hdd_ctx: pointer to hdd context.
215 * @request: pointer to scan request.
216 *
217 * This function will check the scan request's chan list against the
218 * previous ACS scan chan list. If all the chan are covered by
219 * previous ACS scan, we can skip the scan and return scan complete
220 * to save the SAP starting time.
221 *
222 * Return: true to skip the scan,
223 * false to continue the scan
224 */
wlan_hdd_sap_skip_scan_check(struct hdd_context * hdd_ctx,struct cfg80211_scan_request * request)225 static bool wlan_hdd_sap_skip_scan_check(struct hdd_context *hdd_ctx,
226 struct cfg80211_scan_request *request)
227 {
228 int i, j;
229 bool skip;
230
231 hdd_debug("HDD_ACS_SKIP_STATUS = %d",
232 hdd_ctx->skip_acs_scan_status);
233 if (hdd_ctx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN)
234 return false;
235 qdf_spin_lock(&hdd_ctx->acs_skip_lock);
236 if (!hdd_ctx->last_acs_freq_list ||
237 hdd_ctx->num_of_channels == 0 ||
238 request->n_channels == 0) {
239 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
240 return false;
241 }
242 skip = true;
243 for (i = 0; i < request->n_channels ; i++) {
244 bool find = false;
245
246 for (j = 0; j < hdd_ctx->num_of_channels; j++) {
247 if (hdd_ctx->last_acs_freq_list[j] ==
248 request->channels[i]->center_freq) {
249 find = true;
250 break;
251 }
252 }
253 if (!find) {
254 skip = false;
255 hdd_debug("Freq %d isn't in ACS freq list",
256 request->channels[i]->center_freq);
257 break;
258 }
259 }
260 qdf_spin_unlock(&hdd_ctx->acs_skip_lock);
261 return skip;
262 }
263 #else
wlan_hdd_sap_skip_scan_check(struct hdd_context * hdd_ctx,struct cfg80211_scan_request * request)264 static bool wlan_hdd_sap_skip_scan_check(struct hdd_context *hdd_ctx,
265 struct cfg80211_scan_request *request)
266 {
267 return false;
268 }
269 #endif
270
wlan_hdd_cfg80211_scan_block(struct hdd_adapter * adapter)271 void wlan_hdd_cfg80211_scan_block(struct hdd_adapter *adapter)
272 {
273 struct cfg80211_scan_request *request;
274 struct scan_req *blocked_scan_req;
275 qdf_list_node_t *node;
276
277 if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
278 hdd_err("HDD adapter context is invalid");
279 return;
280 }
281
282 qdf_mutex_acquire(&adapter->blocked_scan_request_q_lock);
283
284 while (!qdf_list_empty(&adapter->blocked_scan_request_q)) {
285 qdf_list_remove_front(&adapter->blocked_scan_request_q,
286 &node);
287 blocked_scan_req = qdf_container_of(node, struct scan_req,
288 node);
289 request = blocked_scan_req->scan_request;
290 request->n_ssids = 0;
291 request->n_channels = 0;
292 if (blocked_scan_req->source == NL_SCAN) {
293 hdd_err("Scan aborted. Null result sent");
294 hdd_cfg80211_scan_done(adapter, request, true);
295 } else {
296 hdd_err("Vendor scan aborted. Null result sent");
297 hdd_vendor_scan_callback(adapter, request, true);
298 }
299 qdf_mem_free(blocked_scan_req);
300 }
301
302 qdf_mutex_release(&adapter->blocked_scan_request_q_lock);
303 }
304
hdd_init_scan_reject_params(struct hdd_context * hdd_ctx)305 void hdd_init_scan_reject_params(struct hdd_context *hdd_ctx)
306 {
307 if (hdd_ctx) {
308 hdd_ctx->last_scan_reject_timestamp = 0;
309 hdd_ctx->last_scan_reject_vdev_id = WLAN_UMAC_VDEV_ID_MAX;
310 hdd_ctx->last_scan_reject_reason = 0;
311 hdd_ctx->scan_reject_cnt = 0;
312 }
313 }
314
315 /*
316 * wlan_hdd_update_scan_ies() - API to update the scan IEs of scan request
317 * with already stored default scan IEs
318 *
319 * @adapter: Pointer to HDD adapter
320 * @scan_info: Pointer to scan info in HDD adapter
321 * @scan_ie: Pointer to scan IE in scan request
322 * @scan_ie_len: Pointer to scan IE length in scan request
323 *
324 * Return: 0 on success; error number otherwise
325 */
wlan_hdd_update_scan_ies(struct hdd_adapter * adapter,struct hdd_scan_info * scan_info,uint8_t * scan_ie,uint16_t * scan_ie_len)326 static int wlan_hdd_update_scan_ies(struct hdd_adapter *adapter,
327 struct hdd_scan_info *scan_info, uint8_t *scan_ie,
328 uint16_t *scan_ie_len)
329 {
330 uint16_t rem_len = scan_info->default_scan_ies_len;
331 uint8_t *temp_ie = scan_info->default_scan_ies;
332 uint8_t *current_ie;
333 const uint8_t *mbo_ie;
334 uint8_t elem_id;
335 uint16_t elem_len;
336 bool add_ie = false;
337
338 if (!scan_info->default_scan_ies_len || !scan_info->default_scan_ies)
339 return 0;
340
341 mbo_ie = wlan_get_vendor_ie_ptr_from_oui(MBO_OUI_TYPE,
342 MBO_OUI_TYPE_SIZE, scan_ie,
343 *scan_ie_len);
344 while (rem_len >= 2) {
345 current_ie = temp_ie;
346 elem_id = *temp_ie++;
347 elem_len = *temp_ie++;
348 rem_len -= 2;
349
350 if (elem_len > rem_len) {
351 hdd_err("Invalid element len %d for elem %d", elem_len,
352 elem_id);
353 return 0;
354 }
355
356 switch (elem_id) {
357 case DOT11F_EID_EXTCAP:
358 if (!wlan_get_ie_ptr_from_eid(DOT11F_EID_EXTCAP,
359 scan_ie, *scan_ie_len))
360 add_ie = true;
361 break;
362 case WLAN_ELEMID_VENDOR:
363 /* Donot add MBO IE if its already present */
364 if ((!mbo_ie &&
365 0 == qdf_mem_cmp(&temp_ie[0], MBO_OUI_TYPE,
366 MBO_OUI_TYPE_SIZE)) ||
367 (0 == qdf_mem_cmp(&temp_ie[0], QCN_OUI_TYPE,
368 QCN_OUI_TYPE_SIZE)))
369 add_ie = true;
370 break;
371 }
372
373 if (add_ie && (((*scan_ie_len) + elem_len) >
374 SIR_MAC_MAX_ADD_IE_LENGTH)){
375 hdd_err("Not enough buffer to save default scan IE's");
376 return 0;
377 }
378
379 if (add_ie) {
380 qdf_mem_copy(scan_ie + (*scan_ie_len),
381 current_ie, elem_len + 2);
382 (*scan_ie_len) += (elem_len + 2);
383 add_ie = false;
384 }
385
386 temp_ie += elem_len;
387 rem_len -= elem_len;
388 }
389 return 0;
390 }
391
392 static int
wlan_hdd_enqueue_blocked_scan_request(struct net_device * dev,struct cfg80211_scan_request * request,uint8_t source)393 wlan_hdd_enqueue_blocked_scan_request(struct net_device *dev,
394 struct cfg80211_scan_request *request,
395 uint8_t source)
396 {
397 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
398 struct scan_req *blocked_scan_req =
399 qdf_mem_malloc(sizeof(*blocked_scan_req));
400 int ret = 0;
401
402 if (!blocked_scan_req)
403 return -EINVAL;
404
405 blocked_scan_req->dev = dev;
406 blocked_scan_req->scan_request = request;
407 blocked_scan_req->source = source;
408 blocked_scan_req->scan_id = 0;
409
410 qdf_mutex_acquire(&adapter->blocked_scan_request_q_lock);
411 if (qdf_list_size(&adapter->blocked_scan_request_q) <
412 WLAN_MAX_SCAN_COUNT)
413 qdf_list_insert_back(&adapter->blocked_scan_request_q,
414 &blocked_scan_req->node);
415 else
416 ret = -EINVAL;
417 qdf_mutex_release(&adapter->blocked_scan_request_q_lock);
418
419 if (ret) {
420 hdd_err("Maximum number of block scan request reached!");
421 qdf_mem_free(blocked_scan_req);
422 }
423
424 return ret;
425 }
426
427 /* Define short name to use in cds_trigger_recovery */
428 #define SCAN_FAILURE QDF_SCAN_ATTEMPT_FAILURES
429
430 /**
431 * __wlan_hdd_cfg80211_scan() - API to process cfg80211 scan request
432 * @wiphy: Pointer to wiphy
433 * @request: Pointer to scan request
434 * @source: scan request source(NL/Vendor scan)
435 *
436 * This API responds to scan trigger and update cfg80211 scan database
437 * later, scan dump command can be used to receive scan results
438 *
439 * Return: 0 for success, non zero for failure
440 */
__wlan_hdd_cfg80211_scan(struct wiphy * wiphy,struct cfg80211_scan_request * request,uint8_t source)441 static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
442 struct cfg80211_scan_request *request,
443 uint8_t source)
444 {
445 struct net_device *dev = request->wdev->netdev;
446 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
447 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
448 int status;
449 struct hdd_scan_info *scan_info = NULL;
450 struct hdd_adapter *con_sap_adapter;
451 struct hdd_ap_ctx *ap_ctx;
452 qdf_freq_t con_dfs_ch_freq;
453 uint8_t curr_vdev_id;
454 enum scan_reject_states curr_reason;
455 static uint32_t scan_ebusy_cnt;
456 struct scan_params params = {0};
457 bool self_recovery;
458 struct wlan_objmgr_vdev *vdev;
459 QDF_STATUS qdf_status;
460 bool enable_connected_scan;
461 enum phy_ch_width con_dfs_ch_width;
462
463 if (cds_is_fw_down()) {
464 hdd_err("firmware is down, scan cmd cannot be processed");
465 return -EINVAL;
466 }
467
468 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
469 hdd_err("Command not allowed in FTM mode");
470 return -EINVAL;
471 }
472
473 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
474 return -EINVAL;
475
476 status = wlan_hdd_validate_context(hdd_ctx);
477 if (0 != status)
478 return status;
479
480 qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
481 TRACE_CODE_HDD_CFG80211_SCAN,
482 adapter->deflink->vdev_id, request->n_channels);
483
484 if (!sme_is_session_id_valid(hdd_ctx->mac_handle,
485 adapter->deflink->vdev_id))
486 return -EINVAL;
487
488 qdf_status = ucfg_mlme_get_self_recovery(hdd_ctx->psoc, &self_recovery);
489 if (QDF_IS_STATUS_ERROR(qdf_status)) {
490 hdd_err("Failed to get self recovery ini config");
491 return -EIO;
492 }
493
494 enable_connected_scan = ucfg_scan_is_connected_scan_enabled(
495 hdd_ctx->psoc);
496 if (!enable_connected_scan &&
497 hdd_cm_is_vdev_associated(adapter->deflink)) {
498 hdd_info("enable_connected_scan is false, Aborting scan");
499 if (wlan_hdd_enqueue_blocked_scan_request(dev, request, source))
500 return -EAGAIN;
501 schedule_work(&adapter->scan_block_work);
502 return 0;
503 }
504
505 /*
506 * NDI and monitor mode don't need scan from userspace to establish
507 * connection and it does not support scan request either.
508 */
509 if (QDF_NDI_MODE == adapter->device_mode ||
510 QDF_MONITOR_MODE == adapter->device_mode) {
511 hdd_err("Scan not supported for %s",
512 qdf_opmode_str(adapter->device_mode));
513 return -EINVAL;
514 }
515
516 scan_info = &adapter->scan_info;
517
518 /* Block All Scan during DFS operation and send null scan result */
519
520 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
521 if (con_sap_adapter) {
522 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(con_sap_adapter->deflink);
523 con_dfs_ch_freq = ap_ctx->sap_config.chan_freq;
524 con_dfs_ch_width = ap_ctx->sap_config.ch_params.ch_width;
525 if (con_dfs_ch_freq == AUTO_CHANNEL_SELECT)
526 con_dfs_ch_freq = ap_ctx->operating_chan_freq;
527
528 if (!policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
529 !policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(
530 hdd_ctx->psoc) &&
531 (wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_dfs_ch_freq) ||
532 (wlan_reg_is_5ghz_ch_freq(con_dfs_ch_freq) &&
533 con_dfs_ch_width == CH_WIDTH_160MHZ))) {
534 /* Provide empty scan result during DFS operation since
535 * scanning not supported during DFS. Reason is
536 * following case:
537 * DFS is supported only in SCC for MBSSID Mode.
538 * We shall not return EBUSY or ENOTSUPP as when Primary
539 * AP is operating in DFS channel and secondary AP is
540 * started. Though we force SCC in driver, the hostapd
541 * issues obss scan before starting secAP. This results
542 * in MCC in DFS mode. Thus we return null scan result.
543 * If we return scan failure hostapd fails secondary AP
544 * startup.
545 */
546 hdd_err("##In DFS Master mode. Scan aborted");
547 if (wlan_hdd_enqueue_blocked_scan_request(dev, request,
548 source))
549 return -EAGAIN;
550 schedule_work(&adapter->scan_block_work);
551 return 0;
552 }
553 }
554
555 /* Check if scan is allowed at this point of time */
556 if (hdd_is_connection_in_progress(&curr_vdev_id, &curr_reason)) {
557 scan_ebusy_cnt++;
558 hdd_err_rl("Scan not allowed. scan_ebusy_cnt: %d Session %d Reason %d",
559 scan_ebusy_cnt, curr_vdev_id, curr_reason);
560 if (hdd_ctx->last_scan_reject_vdev_id != curr_vdev_id ||
561 hdd_ctx->last_scan_reject_reason != curr_reason ||
562 !hdd_ctx->last_scan_reject_timestamp) {
563 hdd_ctx->last_scan_reject_vdev_id = curr_vdev_id;
564 hdd_ctx->last_scan_reject_reason = curr_reason;
565 hdd_ctx->last_scan_reject_timestamp = jiffies +
566 msecs_to_jiffies(SCAN_REJECT_THRESHOLD_TIME);
567 hdd_ctx->scan_reject_cnt = 0;
568 } else {
569 hdd_ctx->scan_reject_cnt++;
570 if ((hdd_ctx->scan_reject_cnt >=
571 SCAN_REJECT_THRESHOLD) &&
572 qdf_system_time_after(jiffies,
573 hdd_ctx->last_scan_reject_timestamp)) {
574 hdd_err("scan reject threshold reached Session %d Reason %d count %d reject timestamp %lu jiffies %lu",
575 curr_vdev_id, curr_reason,
576 hdd_ctx->scan_reject_cnt,
577 hdd_ctx->last_scan_reject_timestamp,
578 jiffies);
579 hdd_ctx->last_scan_reject_timestamp = 0;
580 hdd_ctx->scan_reject_cnt = 0;
581 if (cds_is_fatal_event_enabled()) {
582 cds_flush_logs(WLAN_LOG_TYPE_FATAL,
583 WLAN_LOG_INDICATOR_HOST_DRIVER,
584 WLAN_LOG_REASON_SCAN_NOT_ALLOWED,
585 false,
586 self_recovery);
587 } else {
588 hdd_err("Triggering SSR due to scan stuck");
589 cds_trigger_recovery(SCAN_FAILURE);
590 }
591 }
592 }
593 return -EBUSY;
594 }
595
596 hdd_init_scan_reject_params(hdd_ctx);
597
598 /* Check whether SAP scan can be skipped or not */
599 if (adapter->device_mode == QDF_SAP_MODE &&
600 wlan_hdd_sap_skip_scan_check(hdd_ctx, request)) {
601 hdd_debug("sap scan skipped");
602 if (wlan_hdd_enqueue_blocked_scan_request(dev, request, source))
603 return -EAGAIN;
604 schedule_work(&adapter->scan_block_work);
605 return 0;
606 }
607
608 params.source = source;
609 params.default_ie.len = 0;
610 /* Store the Scan IE's in Adapter*/
611 if (request->ie_len) {
612 if (request->ie_len > SIR_MAC_MAX_ADD_IE_LENGTH) {
613 hdd_debug("Invalid ie_len: %zu", request->ie_len);
614 return -EINVAL;
615 }
616
617 /* save this for future association (join requires this) */
618 memset(&scan_info->scan_add_ie, 0, sizeof(scan_info->scan_add_ie));
619 memcpy(scan_info->scan_add_ie.addIEdata, request->ie,
620 request->ie_len);
621 scan_info->scan_add_ie.length = request->ie_len;
622
623 wlan_hdd_update_scan_ies(adapter, scan_info,
624 scan_info->scan_add_ie.addIEdata,
625 &scan_info->scan_add_ie.length);
626 } else {
627 if (scan_info->default_scan_ies &&
628 scan_info->default_scan_ies_len) {
629 qdf_mem_copy(scan_info->scan_add_ie.addIEdata,
630 scan_info->default_scan_ies,
631 scan_info->default_scan_ies_len);
632 scan_info->scan_add_ie.length =
633 scan_info->default_scan_ies_len;
634 params.default_ie.ptr =
635 qdf_mem_malloc(scan_info->default_scan_ies_len);
636 if (params.default_ie.ptr) {
637 qdf_mem_copy(params.default_ie.ptr,
638 scan_info->default_scan_ies,
639 scan_info->default_scan_ies_len);
640 params.default_ie.len =
641 scan_info->default_scan_ies_len;
642 }
643 }
644 }
645
646 if (QDF_P2P_CLIENT_MODE == adapter->device_mode ||
647 QDF_P2P_DEVICE_MODE == adapter->device_mode) {
648 /* Disable NAN Discovery if enabled */
649 ucfg_nan_disable_concurrency(hdd_ctx->psoc);
650 }
651
652 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_SCAN_ID);
653 if (!vdev) {
654 status = -EINVAL;
655 goto error;
656 }
657
658 if ((request->n_ssids == 1) && (request->ssids) &&
659 (request->ssids[0].ssid_len > 7) &&
660 !qdf_mem_cmp(&request->ssids[0], "DIRECT-", 7))
661 ucfg_p2p_status_scan(vdev);
662
663 /* If this a scan on SAP adapter, use scan priority high */
664 if (adapter->device_mode == QDF_SAP_MODE)
665 params.priority = SCAN_PRIORITY_HIGH;
666 else
667 /* Use default scan priority */
668 params.priority = SCAN_PRIORITY_COUNT;
669
670 status = ucfg_mlme_get_scan_probe_unicast_ra(
671 hdd_ctx->psoc,
672 ¶ms.scan_probe_unicast_ra);
673 if (QDF_IS_STATUS_ERROR(status))
674 hdd_err("Failed to get unicast probe req ra cfg");
675
676 params.mld_id = ucfg_mlme_get_eht_mld_id(hdd_ctx->psoc);
677 hdd_debug("MLD ID: %d", params.mld_id);
678
679 status = wlan_cfg80211_scan(vdev, request, ¶ms);
680 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SCAN_ID);
681 error:
682 if (params.default_ie.ptr)
683 qdf_mem_free(params.default_ie.ptr);
684
685 return status;
686 }
687
688 #undef SCAN_FAILURE
689
690 /**
691 * wlan_hdd_cfg80211_scan() - API to process cfg80211 scan request
692 * @wiphy: Pointer to wiphy
693 * @request: Pointer to scan request
694 *
695 * This API responds to scan trigger and update cfg80211 scan database
696 * later, scan dump command can be used to receive scan results
697 *
698 * Return: 0 for success, non zero for failure
699 */
wlan_hdd_cfg80211_scan(struct wiphy * wiphy,struct cfg80211_scan_request * request)700 int wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
701 struct cfg80211_scan_request *request)
702 {
703 int errno;
704 struct osif_vdev_sync *vdev_sync;
705
706 errno = osif_vdev_sync_op_start(request->wdev->netdev, &vdev_sync);
707 if (errno)
708 return errno;
709
710 errno = __wlan_hdd_cfg80211_scan(wiphy, request, NL_SCAN);
711
712 osif_vdev_sync_op_stop(vdev_sync);
713
714 return errno;
715 }
716
717 /**
718 * wlan_hdd_get_rates() -API to get the rates from scan request
719 * @wiphy: Pointer to wiphy
720 * @band: Band
721 * @rates: array of rates
722 * @rate_count: number of rates
723 *
724 * Return: o for failure, rate bitmap for success
725 */
wlan_hdd_get_rates(struct wiphy * wiphy,enum nl80211_band band,const u8 * rates,unsigned int rate_count)726 static uint32_t wlan_hdd_get_rates(struct wiphy *wiphy,
727 enum nl80211_band band,
728 const u8 *rates, unsigned int rate_count)
729 {
730 uint32_t j, count, rate_bitmap = 0;
731 uint32_t rate;
732 bool found;
733
734 for (count = 0; count < rate_count; count++) {
735 rate = ((rates[count]) & RATE_MASK) * 5;
736 found = false;
737 for (j = 0; j < wiphy->bands[band]->n_bitrates; j++) {
738 if (wiphy->bands[band]->bitrates[j].bitrate == rate) {
739 found = true;
740 rate_bitmap |= (1 << j);
741 break;
742 }
743 }
744 if (!found)
745 return 0;
746 }
747 return rate_bitmap;
748 }
749
750 /**
751 * wlan_hdd_send_scan_start_event() -API to send the scan start event
752 * @wiphy: Pointer to wiphy
753 * @wdev: Pointer to net device
754 * @cookie: scan identifier
755 *
756 * Return: return 0 on success and negative error code on failure
757 */
wlan_hdd_send_scan_start_event(struct wiphy * wiphy,struct wireless_dev * wdev,uint64_t cookie)758 static int wlan_hdd_send_scan_start_event(struct wiphy *wiphy,
759 struct wireless_dev *wdev, uint64_t cookie)
760 {
761 struct sk_buff *skb;
762 int ret;
763 enum qca_nl80211_vendor_subcmds_index index =
764 QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX;
765
766 skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u64) +
767 NLA_HDRLEN + NLMSG_HDRLEN);
768 if (!skb) {
769 hdd_err(" reply skb alloc failed");
770 return -ENOMEM;
771 }
772
773 if (hdd_wlan_nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE,
774 cookie)) {
775 hdd_err("nla put fail");
776 wlan_cfg80211_vendor_free_skb(skb);
777 return -EINVAL;
778 }
779
780 ret = wlan_cfg80211_vendor_cmd_reply(skb);
781
782 /* Send a scan started event to supplicant */
783 skb = wlan_cfg80211_vendor_event_alloc(wiphy, wdev,
784 sizeof(u64) + 4 + NLMSG_HDRLEN,
785 index, GFP_KERNEL);
786 if (!skb) {
787 hdd_err("skb alloc failed");
788 return -ENOMEM;
789 }
790
791 if (hdd_wlan_nla_put_u64(skb, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE,
792 cookie)) {
793 wlan_cfg80211_vendor_free_skb(skb);
794 return -EINVAL;
795 }
796
797 wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
798 return ret;
799 }
800
801 /**
802 * wlan_hdd_copy_bssid() - API to copy the bssid to vendor Scan request
803 * @request: Pointer to vendor scan request
804 * @bssid: Pointer to BSSID
805 *
806 * This API copies the specific BSSID received from Supplicant and copies it to
807 * the vendor Scan request
808 *
809 * Return: None
810 */
811 #if defined(CFG80211_SCAN_BSSID) || \
812 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
wlan_hdd_copy_bssid(struct cfg80211_scan_request * request,uint8_t * bssid)813 static inline void wlan_hdd_copy_bssid(struct cfg80211_scan_request *request,
814 uint8_t *bssid)
815 {
816 qdf_mem_copy(request->bssid, bssid, QDF_MAC_ADDR_SIZE);
817 }
818 #else
wlan_hdd_copy_bssid(struct cfg80211_scan_request * request,uint8_t * bssid)819 static inline void wlan_hdd_copy_bssid(struct cfg80211_scan_request *request,
820 uint8_t *bssid)
821 {
822 }
823 #endif
824
hdd_process_vendor_acs_response(struct hdd_adapter * adapter)825 static void hdd_process_vendor_acs_response(struct hdd_adapter *adapter)
826 {
827 qdf_mc_timer_t *vendor_acs_timer;
828
829 if (!test_bit(VENDOR_ACS_RESPONSE_PENDING,
830 &adapter->deflink->link_flags)) {
831 return;
832 }
833
834 vendor_acs_timer = &adapter->deflink->session.ap.vendor_acs_timer;
835 if (QDF_TIMER_STATE_RUNNING ==
836 qdf_mc_timer_get_current_state(vendor_acs_timer)) {
837 qdf_mc_timer_stop(vendor_acs_timer);
838 }
839 }
840
841 #if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
842 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
843 /**
844 * wlan_hdd_vendor_scan_random_attr() - check and fill scan randomization attrs
845 * @wiphy: Pointer to wiphy
846 * @request: Pointer to scan request
847 * @adapter: Pointer to hdd adapter
848 * @tb: Pointer to nl attributes
849 *
850 * This function is invoked to check whether vendor scan needs
851 * probe req source addr, if so populates mac_addr and mac_addr_mask
852 * in scan request with nl attrs.
853 *
854 * Return: 0 - on success, negative value on failure
855 */
wlan_hdd_vendor_scan_random_attr(struct wiphy * wiphy,struct cfg80211_scan_request * request,struct hdd_adapter * adapter,struct nlattr ** tb)856 static int wlan_hdd_vendor_scan_random_attr(struct wiphy *wiphy,
857 struct cfg80211_scan_request *request,
858 struct hdd_adapter *adapter,
859 struct nlattr **tb)
860 {
861 uint32_t i;
862 int32_t len = QDF_MAC_ADDR_SIZE;
863
864 if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
865 return 0;
866
867 if (!(wiphy->features & NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR) ||
868 (hdd_cm_is_vdev_connected(adapter->deflink))) {
869 hdd_err("SCAN RANDOMIZATION not supported");
870 return -EOPNOTSUPP;
871 }
872
873 if (!tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC] &&
874 !tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK]) {
875 qdf_mem_zero(request->mac_addr, len);
876 qdf_mem_zero(request->mac_addr_mask, len);
877 request->mac_addr[0] = 0x2;
878 request->mac_addr_mask[0] = 0x3;
879
880 return 0;
881 }
882
883 if (!tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC] ||
884 !tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK])
885 return -EINVAL;
886
887 if ((nla_len(tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC]) != len) ||
888 (nla_len(tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK]) != len))
889 return -EINVAL;
890
891 qdf_mem_copy(request->mac_addr,
892 nla_data(tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC]), len);
893
894 qdf_mem_copy(request->mac_addr_mask,
895 nla_data(tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK]), len);
896
897 /* avoid configure on multicast address */
898 if (!cds_is_group_addr(request->mac_addr_mask) ||
899 cds_is_group_addr(request->mac_addr))
900 return -EINVAL;
901
902 for (i = 0; i < ETH_ALEN; i++)
903 request->mac_addr[i] &= request->mac_addr_mask[i];
904
905 return 0;
906 }
907 #else
wlan_hdd_vendor_scan_random_attr(struct wiphy * wiphy,struct cfg80211_scan_request * request,struct hdd_adapter * adapter,struct nlattr ** tb)908 static int wlan_hdd_vendor_scan_random_attr(struct wiphy *wiphy,
909 struct cfg80211_scan_request *request,
910 struct hdd_adapter *adapter,
911 struct nlattr **tb)
912 {
913 return 0;
914 }
915 #endif
916
917 const
918 struct nla_policy scan_policy[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1] = {
919 [QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS] = {.type = NLA_U32},
920 [QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE] = {.type = NLA_FLAG},
921 [QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE] = {.type = NLA_U64},
922 [QCA_WLAN_VENDOR_ATTR_SCAN_IE] = {.type = NLA_BINARY,
923 .len = MAX_DEFAULT_SCAN_IE_LEN},
924 [QCA_WLAN_VENDOR_ATTR_SCAN_MAC] = VENDOR_NLA_POLICY_MAC_ADDR,
925 [QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK] = VENDOR_NLA_POLICY_MAC_ADDR,
926 [QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES] = {.type = NLA_NESTED},
927 [QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS] = {.type = NLA_NESTED},
928 [QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES] = {.type = NLA_NESTED},
929 [QCA_WLAN_VENDOR_ATTR_SCAN_BSSID] = {.type = NLA_BINARY},
930 };
931
932 /**
933 * __wlan_hdd_cfg80211_vendor_scan() - API to process venor scan request
934 * @wiphy: Pointer to wiphy
935 * @wdev: Pointer to net device
936 * @data : Pointer to the data
937 * @data_len : length of the data
938 *
939 * API to process venor scan request.
940 *
941 * Return: return 0 on success and negative error code on failure
942 */
__wlan_hdd_cfg80211_vendor_scan(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)943 static int __wlan_hdd_cfg80211_vendor_scan(struct wiphy *wiphy,
944 struct wireless_dev *wdev, const void *data,
945 int data_len)
946 {
947 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
948 struct cfg80211_scan_request *request = NULL;
949 struct nlattr *attr;
950 enum nl80211_band band;
951 uint32_t n_channels = 0, n_ssid = 0;
952 uint32_t count, j;
953 int tmp;
954 size_t len, ie_len = 0;
955 struct ieee80211_channel *chan;
956 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
957 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
958 int ret;
959
960 hdd_enter_dev(wdev->netdev);
961
962 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
963 hdd_err("Command not allowed in FTM mode");
964 return -EPERM;
965 }
966
967 ret = wlan_hdd_validate_context(hdd_ctx);
968 if (ret) {
969 /*
970 * During SSR, if -EBUSY is returned then OBSS vendor scan is
971 * not issued immediately.
972 */
973 if (ret == -EAGAIN)
974 return -EBUSY;
975
976 return ret;
977 }
978
979 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
980 data, data_len, scan_policy)) {
981 hdd_err("Invalid ATTR");
982 return -EINVAL;
983 }
984
985 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) {
986 nla_for_each_nested(attr,
987 tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES], tmp)
988 n_channels++;
989 } else {
990 for (band = 0; band < HDD_NUM_NL80211_BANDS; band++)
991 if (wiphy->bands[band])
992 n_channels += wiphy->bands[band]->n_channels;
993 }
994
995 if (n_channels > NUM_CHANNELS) {
996 hdd_err("Exceed max number of channels: %d", n_channels);
997 return -EINVAL;
998 }
999 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS])
1000 nla_for_each_nested(attr,
1001 tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS], tmp)
1002 n_ssid++;
1003
1004 if (MAX_SCAN_SSID < n_ssid) {
1005 hdd_err("Exceed max number of SSID: %d", n_ssid);
1006 return -EINVAL;
1007 }
1008
1009 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE])
1010 ie_len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE]);
1011
1012 len = sizeof(*request) + (sizeof(*request->ssids) * n_ssid) +
1013 (sizeof(*request->channels) * n_channels) + ie_len;
1014
1015 request = qdf_mem_malloc(len);
1016 if (!request)
1017 goto error;
1018 if (n_ssid)
1019 request->ssids = (void *)&request->channels[n_channels];
1020 request->n_ssids = n_ssid;
1021 if (ie_len) {
1022 if (request->ssids)
1023 request->ie = (void *)(request->ssids + n_ssid);
1024 else
1025 request->ie = (void *)(request->channels + n_channels);
1026 }
1027
1028 request->ie_len = ie_len;
1029 count = 0;
1030 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) {
1031 nla_for_each_nested(attr,
1032 tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES],
1033 tmp) {
1034 if (nla_len(attr) != sizeof(uint32_t)) {
1035 hdd_err("len is not correct for frequency %d",
1036 count);
1037 goto error;
1038 }
1039 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
1040 if (!chan)
1041 goto error;
1042 if (chan->flags & IEEE80211_CHAN_DISABLED)
1043 continue;
1044 request->channels[count] = chan;
1045 count++;
1046 }
1047 } else {
1048 for (band = 0; band < HDD_NUM_NL80211_BANDS; band++) {
1049 if (!wiphy->bands[band])
1050 continue;
1051 for (j = 0; j < wiphy->bands[band]->n_channels;
1052 j++) {
1053 chan = &wiphy->bands[band]->channels[j];
1054 if (chan->flags & IEEE80211_CHAN_DISABLED)
1055 continue;
1056 request->channels[count] = chan;
1057 count++;
1058 }
1059 }
1060 }
1061
1062 if (!count)
1063 goto error;
1064
1065 request->n_channels = count;
1066 count = 0;
1067 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) {
1068 int ssid_length;
1069
1070 nla_for_each_nested(attr, tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS],
1071 tmp) {
1072 ssid_length = nla_len(attr);
1073 if ((ssid_length > WLAN_SSID_MAX_LEN) ||
1074 (ssid_length < 0)) {
1075 hdd_err("SSID Len %d is not correct for network %d",
1076 ssid_length, count);
1077 goto error;
1078 }
1079
1080 request->ssids[count].ssid_len = ssid_length;
1081 memcpy(request->ssids[count].ssid, nla_data(attr),
1082 ssid_length);
1083 count++;
1084 }
1085 }
1086
1087 if (ie_len)
1088 nla_memcpy((void *)request->ie,
1089 tb[QCA_WLAN_VENDOR_ATTR_SCAN_IE], ie_len);
1090
1091 for (count = 0; count < HDD_NUM_NL80211_BANDS; count++)
1092 if (wiphy->bands[count])
1093 request->rates[count] =
1094 (1 << wiphy->bands[count]->n_bitrates) - 1;
1095
1096 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES]) {
1097 nla_for_each_nested(attr,
1098 tb[QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES],
1099 tmp) {
1100 band = nla_type(attr);
1101 if (band >= HDD_NUM_NL80211_BANDS)
1102 continue;
1103 if (!wiphy->bands[band])
1104 continue;
1105 request->rates[band] =
1106 wlan_hdd_get_rates(wiphy,
1107 band, nla_data(attr),
1108 nla_len(attr));
1109 }
1110 }
1111
1112 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS]) {
1113 request->flags =
1114 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS]);
1115 if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
1116 !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
1117 hdd_err("LOW PRIORITY SCAN not supported");
1118 goto error;
1119 }
1120
1121 if (wlan_hdd_vendor_scan_random_attr(wiphy, request,
1122 adapter, tb))
1123 goto error;
1124 }
1125
1126 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_BSSID]) {
1127 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_SCAN_BSSID]) <
1128 QDF_MAC_ADDR_SIZE) {
1129 hdd_err("invalid bssid length");
1130 goto error;
1131 }
1132 wlan_hdd_copy_bssid(request,
1133 nla_data(tb[QCA_WLAN_VENDOR_ATTR_SCAN_BSSID]));
1134 }
1135
1136 /* Check if external acs was requested on this adapter */
1137 hdd_process_vendor_acs_response(adapter);
1138
1139 if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE])
1140 request->no_cck =
1141 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE]);
1142 request->wdev = wdev;
1143 request->wiphy = wiphy;
1144 request->scan_start = jiffies;
1145
1146 ret = __wlan_hdd_cfg80211_scan(wiphy, request, VENDOR_SCAN);
1147 if (0 != ret) {
1148 hdd_err("Scan Failed. Ret = %d", ret);
1149 qdf_mem_free(request);
1150 return ret;
1151 }
1152 ret = wlan_hdd_send_scan_start_event(wiphy, wdev, (uintptr_t)request);
1153
1154 return ret;
1155 error:
1156 hdd_err("Scan Request Failed");
1157 qdf_mem_free(request);
1158 return -EINVAL;
1159 }
1160
1161 /**
1162 * wlan_hdd_cfg80211_vendor_scan() -API to process venor scan request
1163 * @wiphy: Pointer to wiphy
1164 * @wdev: Pointer to wireless device
1165 * @data: Pointer to the data
1166 * @data_len: length of the data
1167 *
1168 * This is called from userspace to request scan.
1169 *
1170 * Return: Return the Success or Failure code.
1171 */
wlan_hdd_cfg80211_vendor_scan(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1172 int wlan_hdd_cfg80211_vendor_scan(struct wiphy *wiphy,
1173 struct wireless_dev *wdev, const void *data,
1174 int data_len)
1175 {
1176 int errno;
1177 struct osif_vdev_sync *vdev_sync;
1178
1179 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1180 if (errno)
1181 return errno;
1182
1183 errno = __wlan_hdd_cfg80211_vendor_scan(wiphy, wdev, data, data_len);
1184
1185 osif_vdev_sync_op_stop(vdev_sync);
1186
1187 return errno;
1188 }
1189
1190 /**
1191 * __wlan_hdd_vendor_abort_scan() - API to process vendor command for
1192 * abort scan
1193 * @wiphy: Pointer to wiphy
1194 * @data: Pointer to the data
1195 * @data_len: length of the data
1196 *
1197 * API to process vendor abort scan
1198 *
1199 * Return: zero for success and non zero for failure
1200 */
__wlan_hdd_vendor_abort_scan(struct wiphy * wiphy,const void * data,int data_len)1201 static int __wlan_hdd_vendor_abort_scan(
1202 struct wiphy *wiphy, const void *data,
1203 int data_len)
1204 {
1205 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1206 int ret;
1207
1208 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1209 hdd_err("Command not allowed in FTM mode");
1210 return -EINVAL;
1211 }
1212
1213 ret = wlan_hdd_validate_context(hdd_ctx);
1214 if (0 != ret)
1215 return ret;
1216
1217 wlan_vendor_abort_scan(hdd_ctx->pdev, data, data_len);
1218
1219 return ret;
1220 }
1221
1222 /**
1223 * wlan_hdd_vendor_abort_scan() - API to process vendor command for
1224 * abort scan
1225 * @wiphy: Pointer to wiphy
1226 * @wdev: Pointer to net device
1227 * @data : Pointer to the data
1228 * @data_len : length of the data
1229 *
1230 * This is called from supplicant to abort scan
1231 *
1232 * Return: zero for success and non zero for failure
1233 */
wlan_hdd_vendor_abort_scan(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1234 int wlan_hdd_vendor_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
1235 const void *data, int data_len)
1236 {
1237 struct osif_vdev_sync *vdev_sync;
1238 int errno;
1239
1240 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1241 if (errno)
1242 return errno;
1243
1244 errno = __wlan_hdd_vendor_abort_scan(wiphy, data, data_len);
1245
1246 osif_vdev_sync_op_stop(vdev_sync);
1247
1248 return errno;
1249 }
1250
wlan_hdd_scan_abort(struct wlan_hdd_link_info * link_info)1251 int wlan_hdd_scan_abort(struct wlan_hdd_link_info *link_info)
1252 {
1253 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
1254
1255 wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
1256 link_info->vdev_id, INVALID_SCAN_ID, true);
1257
1258 return 0;
1259 }
1260
1261 #ifdef FEATURE_WLAN_SCAN_PNO
1262 /**
1263 * __wlan_hdd_cfg80211_sched_scan_start() - cfg80211 scheduled scan(pno) start
1264 * @wiphy: Pointer to wiphy
1265 * @dev: Pointer network device
1266 * @request: Pointer to cfg80211 scheduled scan start request
1267 *
1268 * Return: 0 for success, non zero for failure
1269 */
__wlan_hdd_cfg80211_sched_scan_start(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_sched_scan_request * request)1270 static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
1271 struct net_device *dev,
1272 struct
1273 cfg80211_sched_scan_request
1274 *request)
1275 {
1276 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1277 struct hdd_context *hdd_ctx;
1278 struct wlan_objmgr_vdev *vdev;
1279 int ret;
1280 bool pno_offload_enabled;
1281 uint8_t scan_backoff_multiplier;
1282 bool enable_connected_scan;
1283 enum QDF_GLOBAL_MODE curr_mode;
1284
1285 curr_mode = hdd_get_conparam();
1286
1287 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
1288 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
1289 hdd_err_rl("Command not allowed in FTM/Monitor mode");
1290 return -EINVAL;
1291 }
1292
1293 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
1294 return -EINVAL;
1295
1296 if (adapter->device_mode != QDF_STA_MODE) {
1297 hdd_info("Sched scans only supported on STA ifaces");
1298 return -EINVAL;
1299 }
1300
1301 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1302 ret = wlan_hdd_validate_context(hdd_ctx);
1303 if (ret)
1304 return ret;
1305
1306 pno_offload_enabled = ucfg_scan_is_pno_offload_enabled(hdd_ctx->psoc);
1307 if (!pno_offload_enabled) {
1308 hdd_debug("Pno Offload is not enabled");
1309 return -EINVAL;
1310 }
1311
1312 enable_connected_scan = ucfg_scan_is_connected_scan_enabled(
1313 hdd_ctx->psoc);
1314 if (!enable_connected_scan &&
1315 hdd_cm_is_vdev_associated(adapter->deflink)) {
1316 hdd_info("enable_connected_scan is false, Aborting scan");
1317 return -EBUSY;
1318 }
1319
1320 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_SCAN_ID);
1321 if (!vdev)
1322 return -EINVAL;
1323
1324 scan_backoff_multiplier =
1325 ucfg_get_scan_backoff_multiplier(hdd_ctx->psoc);
1326 ret = wlan_cfg80211_sched_scan_start(vdev, request,
1327 scan_backoff_multiplier);
1328 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SCAN_ID);
1329
1330 return ret;
1331 }
1332
1333 /**
1334 * wlan_hdd_cfg80211_sched_scan_start() - cfg80211 scheduled scan(pno) start
1335 * @wiphy: Pointer to wiphy
1336 * @dev: Pointer network device
1337 * @request: Pointer to cfg80211 scheduled scan start request
1338 *
1339 * Return: 0 for success, non zero for failure
1340 */
wlan_hdd_cfg80211_sched_scan_start(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_sched_scan_request * request)1341 int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
1342 struct net_device *dev,
1343 struct cfg80211_sched_scan_request
1344 *request)
1345 {
1346 int errno;
1347 struct osif_vdev_sync *vdev_sync;
1348
1349 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
1350 if (errno)
1351 return errno;
1352
1353 errno = __wlan_hdd_cfg80211_sched_scan_start(wiphy, dev, request);
1354
1355 osif_vdev_sync_op_stop(vdev_sync);
1356
1357 return errno;
1358 }
1359
wlan_hdd_sched_scan_stop(struct net_device * dev)1360 int wlan_hdd_sched_scan_stop(struct net_device *dev)
1361 {
1362 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1363 struct hdd_context *hdd_ctx;
1364 struct wlan_objmgr_vdev *vdev;
1365 int ret;
1366 bool pno_offload_enabled;
1367
1368 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1369 hdd_err("Command not allowed in FTM mode");
1370 return -EINVAL;
1371 }
1372
1373 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
1374 return -EINVAL;
1375
1376 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1377 if (!hdd_ctx) {
1378 hdd_err("HDD context is Null");
1379 return -EINVAL;
1380 }
1381
1382 pno_offload_enabled = ucfg_scan_is_pno_offload_enabled(hdd_ctx->psoc);
1383 if (!pno_offload_enabled) {
1384 hdd_debug("PnoOffload is not enabled!!!");
1385 return -EINVAL;
1386 }
1387
1388 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_SCAN_ID);
1389 if (!vdev)
1390 return -EINVAL;
1391 ret = wlan_cfg80211_sched_scan_stop(vdev);
1392 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SCAN_ID);
1393
1394 return ret;
1395 }
1396
1397 /**
1398 * __wlan_hdd_cfg80211_sched_scan_stop() - stop cfg80211 scheduled scan(pno)
1399 * @dev: Pointer network device
1400 *
1401 * This is a wrapper around wlan_hdd_sched_scan_stop() that returns success
1402 * in the event that the driver is currently recovering or unloading. This
1403 * prevents a race condition where we get a scan stop from kernel during
1404 * a driver unload from PLD.
1405 *
1406 * Return: 0 for success, non zero for failure
1407 */
__wlan_hdd_cfg80211_sched_scan_stop(struct net_device * dev)1408 static int __wlan_hdd_cfg80211_sched_scan_stop(struct net_device *dev)
1409 {
1410 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1411 int errno;
1412 enum QDF_GLOBAL_MODE curr_mode;
1413
1414 curr_mode = hdd_get_conparam();
1415
1416 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
1417 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
1418 hdd_err_rl("Command not allowed in FTM/Monitor mode");
1419 return -EINVAL;
1420 }
1421
1422 /* The return 0 is intentional when Recovery and Load/Unload in
1423 * progress. We did observe a crash due to a return of
1424 * failure in sched_scan_stop , especially for a case where the unload
1425 * of the happens at the same time. The function
1426 * __cfg80211_stop_sched_scan was clearing rdev->sched_scan_req only
1427 * when the sched_scan_stop returns success. If it returns a failure ,
1428 * then its next invocation due to the clean up of the second interface
1429 * will have the dev pointer corresponding to the first one leading to
1430 * a crash.
1431 */
1432 if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
1433 hdd_info("Recovery in Progress. State: 0x%x Ignore!!!",
1434 cds_get_driver_state());
1435 return 0;
1436 }
1437
1438 if (cds_is_load_or_unload_in_progress()) {
1439 hdd_info("Unload/Load in Progress, state: 0x%x. Ignore!!!",
1440 cds_get_driver_state());
1441 return 0;
1442 }
1443
1444 errno = hdd_validate_adapter(adapter);
1445 if (errno)
1446 return errno;
1447
1448 if (adapter->device_mode != QDF_STA_MODE) {
1449 hdd_info("Sched scans only supported on STA ifaces");
1450 return -EINVAL;
1451 }
1452
1453 errno = wlan_hdd_validate_context(WLAN_HDD_GET_CTX(adapter));
1454 if (errno)
1455 return errno;
1456
1457 errno = wlan_hdd_sched_scan_stop(dev);
1458
1459 return errno;
1460 }
1461
1462 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
wlan_hdd_cfg80211_sched_scan_stop(struct wiphy * wiphy,struct net_device * dev)1463 int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
1464 struct net_device *dev)
1465 {
1466 int errno;
1467 struct osif_vdev_sync *vdev_sync;
1468
1469 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
1470 if (errno)
1471 return errno;
1472
1473 errno = __wlan_hdd_cfg80211_sched_scan_stop(dev);
1474
1475 osif_vdev_sync_op_stop(vdev_sync);
1476
1477 /* The return 0 is intentional. We observed a crash due to a return of
1478 * failure in sched_scan_stop , especially for a case where the unload
1479 * of the happens at the same time. The function
1480 * __cfg80211_stop_sched_scan was clearing rdev->sched_scan_req only
1481 * when the sched_scan_stop returns success. If it returns a failure ,
1482 * then its next invocation due to the clean up of the second interface
1483 * will have the dev pointer corresponding to the first one leading to
1484 * a crash.
1485 */
1486 return 0;
1487 }
1488 #else
wlan_hdd_cfg80211_sched_scan_stop(struct wiphy * wiphy,struct net_device * dev,uint64_t reqid)1489 int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy,
1490 struct net_device *dev,
1491 uint64_t reqid)
1492 {
1493 int errno;
1494 struct osif_vdev_sync *vdev_sync;
1495
1496 errno = osif_vdev_sync_op_start(dev, &vdev_sync);
1497 if (errno)
1498 return errno;
1499
1500 errno = __wlan_hdd_cfg80211_sched_scan_stop(dev);
1501
1502 osif_vdev_sync_op_stop(vdev_sync);
1503
1504 /* The return 0 is intentional. We observed a crash due to a return of
1505 * failure in sched_scan_stop , especially for a case where the unload
1506 * of the happens at the same time. The function
1507 * __cfg80211_stop_sched_scan was clearing rdev->sched_scan_req only
1508 * when the sched_scan_stop returns success. If it returns a failure ,
1509 * then its next invocation due to the clean up of the second interface
1510 * will have the dev pointer corresponding to the first one leading to
1511 * a crash.
1512 */
1513 return 0;
1514 }
1515 #endif /* KERNEL_VERSION(4, 12, 0) */
1516 #endif /*FEATURE_WLAN_SCAN_PNO */
1517
1518 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
1519 defined(CFG80211_ABORT_SCAN)
1520 /**
1521 * __wlan_hdd_cfg80211_abort_scan() - cfg80211 abort scan api
1522 * @wiphy: Pointer to wiphy
1523 * @wdev: Pointer to wireless device structure
1524 *
1525 * This function is used to abort an ongoing scan
1526 *
1527 * Return: None
1528 */
__wlan_hdd_cfg80211_abort_scan(struct wiphy * wiphy,struct wireless_dev * wdev)1529 static void __wlan_hdd_cfg80211_abort_scan(struct wiphy *wiphy,
1530 struct wireless_dev *wdev)
1531 {
1532 struct net_device *dev = wdev->netdev;
1533 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1534 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1535 int ret;
1536
1537 hdd_enter_dev(dev);
1538
1539 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1540 hdd_err("Command not allowed in FTM mode");
1541 return;
1542 }
1543
1544 if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
1545 return;
1546
1547 ret = wlan_hdd_validate_context(hdd_ctx);
1548 if (ret)
1549 return;
1550
1551 wlan_cfg80211_abort_scan(hdd_ctx->pdev);
1552
1553 hdd_exit();
1554 }
1555
1556 /**
1557 * wlan_hdd_cfg80211_abort_scan - cfg80211 abort scan api
1558 * @wiphy: Pointer to wiphy
1559 * @wdev: Pointer to wireless device structure
1560 *
1561 * Wrapper to __wlan_hdd_cfg80211_abort_scan() -
1562 * function is used to abort an ongoing scan
1563 *
1564 * Return: None
1565 */
wlan_hdd_cfg80211_abort_scan(struct wiphy * wiphy,struct wireless_dev * wdev)1566 void wlan_hdd_cfg80211_abort_scan(struct wiphy *wiphy,
1567 struct wireless_dev *wdev)
1568 {
1569 struct osif_psoc_sync *psoc_sync;
1570 int errno;
1571
1572 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
1573 if (errno)
1574 return;
1575
1576 __wlan_hdd_cfg80211_abort_scan(wiphy, wdev);
1577
1578 osif_psoc_sync_op_stop(psoc_sync);
1579 }
1580 #endif
1581
1582 /**
1583 * hdd_scan_context_destroy() - Destroy scan context
1584 * @hdd_ctx: HDD context.
1585 *
1586 * Destroy scan context.
1587 *
1588 * Return: None.
1589 */
hdd_scan_context_destroy(struct hdd_context * hdd_ctx)1590 void hdd_scan_context_destroy(struct hdd_context *hdd_ctx)
1591 {
1592 }
1593
1594 /**
1595 * hdd_scan_context_init() - Initialize scan context
1596 * @hdd_ctx: HDD context.
1597 *
1598 * Initialize scan related resources like spin lock and lists.
1599 *
1600 * Return: 0 on success and errno on failure.
1601 */
hdd_scan_context_init(struct hdd_context * hdd_ctx)1602 int hdd_scan_context_init(struct hdd_context *hdd_ctx)
1603 {
1604 return 0;
1605 }
1606