1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-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: contains scan manager functionality
22 */
23
24 #include <wlan_serialization_api.h>
25 #include <wlan_scan_ucfg_api.h>
26 #include <wlan_scan_tgt_api.h>
27 #include "wlan_scan_main.h"
28 #include "wlan_scan_manager.h"
29 #include "wlan_utility.h"
30 #include <wlan_reg_services_api.h>
31 #ifdef FEATURE_WLAN_SCAN_PNO
32 #include <host_diag_core_event.h>
33 #endif
34 #ifdef WLAN_POLICY_MGR_ENABLE
35 #include <wlan_policy_mgr_api.h>
36 #endif
37 #include <wlan_dfs_utils_api.h>
38 #include <cfg_scan.h>
39
40 QDF_STATUS
scm_scan_free_scan_request_mem(struct scan_start_request * req)41 scm_scan_free_scan_request_mem(struct scan_start_request *req)
42 {
43 void *ie;
44
45 if (!req) {
46 scm_err("null request");
47 QDF_ASSERT(0);
48 return QDF_STATUS_E_FAILURE;
49 }
50 /* Free vendor(extra) ie */
51 ie = req->scan_req.extraie.ptr;
52 if (ie) {
53 req->scan_req.extraie.ptr = NULL;
54 req->scan_req.extraie.len = 0;
55 qdf_mem_free(ie);
56 }
57
58 /* Free htcap ie */
59 ie = req->scan_req.htcap.ptr;
60 if (ie) {
61 req->scan_req.htcap.len = 0;
62 req->scan_req.htcap.ptr = NULL;
63 qdf_mem_free(ie);
64 }
65
66 /* Free vhtcap ie */
67 ie = req->scan_req.vhtcap.ptr;
68 if (ie) {
69 req->scan_req.vhtcap.len = 0;
70 req->scan_req.vhtcap.ptr = NULL;
71 qdf_mem_free(ie);
72 }
73 /* free scan_start_request memory */
74 qdf_mem_free(req);
75
76 return QDF_STATUS_SUCCESS;
77 }
78
79 static QDF_STATUS
scm_scan_get_pdev_global_event_handlers(struct scan_event_listeners * listeners,struct pdev_scan_ev_handler * pdev_ev_handler)80 scm_scan_get_pdev_global_event_handlers(struct scan_event_listeners *listeners,
81 struct pdev_scan_ev_handler *pdev_ev_handler)
82 {
83 uint32_t i;
84 struct cb_handler *cb_handlers = &(pdev_ev_handler->cb_handlers[0]);
85
86 for (i = 0; i < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; i++, cb_handlers++) {
87 if ((cb_handlers->func) &&
88 (listeners->count < MAX_SCAN_EVENT_LISTENERS)) {
89 listeners->cb[listeners->count].func =
90 cb_handlers->func;
91 listeners->cb[listeners->count].arg =
92 cb_handlers->arg;
93 listeners->count++;
94 }
95 }
96
97 return QDF_STATUS_SUCCESS;
98 }
99
100 static QDF_STATUS
scm_scan_get_requester_event_handler(struct scan_event_listeners * listeners,struct scan_requester_info * requesters,wlan_scan_requester requester_id)101 scm_scan_get_requester_event_handler(struct scan_event_listeners *listeners,
102 struct scan_requester_info *requesters,
103 wlan_scan_requester requester_id)
104 {
105 uint32_t idx;
106 struct cb_handler *ev_handler;
107
108 idx = requester_id & WLAN_SCAN_REQUESTER_ID_PREFIX;
109 if (idx != WLAN_SCAN_REQUESTER_ID_PREFIX)
110 return QDF_STATUS_SUCCESS;
111
112 idx = requester_id & WLAN_SCAN_REQUESTER_ID_MASK;
113 if (idx < WLAN_MAX_REQUESTORS) {
114 ev_handler = &(requesters[idx].ev_handler);
115 if (ev_handler->func) {
116 if (listeners->count < MAX_SCAN_EVENT_LISTENERS) {
117 listeners->cb[listeners->count].func =
118 ev_handler->func;
119 listeners->cb[listeners->count].arg =
120 ev_handler->arg;
121 listeners->count++;
122 }
123 }
124 return QDF_STATUS_SUCCESS;
125 } else {
126 scm_err("invalid requester id");
127 return QDF_STATUS_E_INVAL;
128 }
129
130 }
131
scm_scan_post_event(struct wlan_objmgr_vdev * vdev,struct scan_event * event)132 static void scm_scan_post_event(struct wlan_objmgr_vdev *vdev,
133 struct scan_event *event)
134 {
135 uint32_t i = 0;
136 struct wlan_scan_obj *scan;
137 struct pdev_scan_ev_handler *pdev_ev_handler;
138 struct cb_handler *cb_handlers;
139 struct scan_requester_info *requesters;
140 struct scan_event_listeners *listeners;
141
142 if (!vdev || !event) {
143 scm_err("vdev: 0x%pK, event: 0x%pK", vdev, event);
144 return;
145 }
146 if (!event->requester) {
147 scm_err("invalid requester id");
148 QDF_ASSERT(0);
149 }
150 scan = wlan_vdev_get_scan_obj(vdev);
151 pdev_ev_handler = wlan_vdev_get_pdev_scan_ev_handlers(vdev);
152 if (!pdev_ev_handler)
153 return;
154 cb_handlers = &(pdev_ev_handler->cb_handlers[0]);
155 requesters = scan->requesters;
156
157 listeners = qdf_mem_malloc_atomic(sizeof(*listeners));
158 if (!listeners) {
159 scm_warn("couldn't allocate listeners list");
160 return;
161 }
162
163 /* initialize number of listeners */
164 listeners->count = 0;
165
166 /*
167 * Initiator of scan request decides which all scan events
168 * he is interested in and FW will send only those scan events
169 * to host driver.
170 * All the events received by scan module will be notified
171 * to all registered handlers.
172 */
173
174 qdf_spin_lock_bh(&scan->lock);
175 /* find all global scan event handlers on this pdev */
176 scm_scan_get_pdev_global_event_handlers(listeners, pdev_ev_handler);
177 /* find owner who triggered this scan request */
178 scm_scan_get_requester_event_handler(listeners, requesters,
179 event->requester);
180 qdf_spin_unlock_bh(&scan->lock);
181
182 scm_listener_duration_init(scan);
183
184 /* notify all interested handlers */
185 for (i = 0; i < listeners->count; i++) {
186 scm_listener_cb_exe_dur_start(scan, i);
187 listeners->cb[i].func(vdev, event, listeners->cb[i].arg);
188 scm_listener_cb_exe_dur_end(scan, i);
189 }
190 qdf_mem_free(listeners);
191 }
192
193 static QDF_STATUS
scm_release_serialization_command(struct wlan_objmgr_vdev * vdev,uint32_t scan_id)194 scm_release_serialization_command(struct wlan_objmgr_vdev *vdev,
195 uint32_t scan_id)
196 {
197 struct wlan_serialization_queued_cmd_info cmd = {0};
198
199 cmd.requestor = WLAN_UMAC_COMP_SCAN;
200 cmd.cmd_type = WLAN_SER_CMD_SCAN;
201 cmd.cmd_id = scan_id;
202 cmd.req_type = WLAN_SER_CANCEL_SINGLE_SCAN;
203 cmd.vdev = vdev;
204 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
205
206 /* Inform serialization for command completion */
207 wlan_serialization_remove_cmd(&cmd);
208
209 return QDF_STATUS_SUCCESS;
210 }
211
212 static QDF_STATUS
scm_post_internal_scan_complete_event(struct scan_start_request * req,enum scan_completion_reason reason)213 scm_post_internal_scan_complete_event(struct scan_start_request *req,
214 enum scan_completion_reason reason)
215 {
216 struct scan_event event = {0, };
217
218 /* prepare internal scan complete event */
219 event.type = SCAN_EVENT_TYPE_COMPLETED;
220 event.reason = reason;
221 event.chan_freq = 0; /* Invalid frequency */
222 event.vdev_id = req->scan_req.vdev_id;
223 event.requester = req->scan_req.scan_req_id;
224 event.scan_id = req->scan_req.scan_id;
225 /* Fill scan_start_request used to trigger this scan */
226 event.scan_start_req = req;
227 /* post scan event to registered handlers */
228 scm_scan_post_event(req->vdev, &event);
229
230 return QDF_STATUS_SUCCESS;
231 }
232
233 static inline struct pdev_scan_info *
scm_scan_get_pdev_priv_info(uint8_t pdev_id,struct wlan_scan_obj * scan_obj)234 scm_scan_get_pdev_priv_info(uint8_t pdev_id, struct wlan_scan_obj *scan_obj)
235 {
236 return &scan_obj->pdev_info[pdev_id];
237 }
238
239 static QDF_STATUS
scm_update_last_scan_time(struct scan_start_request * req)240 scm_update_last_scan_time(struct scan_start_request *req)
241 {
242 uint8_t pdev_id;
243 struct wlan_scan_obj *scan_obj;
244 struct pdev_scan_info *pdev_scan_info;
245
246 scan_obj = wlan_vdev_get_scan_obj(req->vdev);
247 pdev_id = wlan_scan_vdev_get_pdev_id(req->vdev);
248 pdev_scan_info = scm_scan_get_pdev_priv_info(pdev_id, scan_obj);
249 /* update last scan start time */
250 pdev_scan_info->last_scan_time = qdf_system_ticks();
251
252 return QDF_STATUS_SUCCESS;
253 }
254
255 static QDF_STATUS
scm_activate_scan_request(struct scan_start_request * req)256 scm_activate_scan_request(struct scan_start_request *req)
257 {
258 QDF_STATUS status;
259
260 status = tgt_scan_start(req);
261 if (status != QDF_STATUS_SUCCESS) {
262 scm_err("tgt_scan_start failed, status: %d", status);
263 /* scan could not be started and hence
264 * we will not receive any completions.
265 * post scan cancelled
266 */
267 scm_post_internal_scan_complete_event(req,
268 SCAN_REASON_CANCELLED);
269 return status;
270 }
271 /* save last scan start time */
272 status = scm_update_last_scan_time(req);
273
274 return status;
275 }
276
277 static QDF_STATUS
scm_cancel_scan_request(struct scan_start_request * req)278 scm_cancel_scan_request(struct scan_start_request *req)
279 {
280 struct scan_cancel_request cancel_req = {0, };
281 QDF_STATUS status;
282
283 cancel_req.vdev = req->vdev;
284 cancel_req.cancel_req.scan_id = req->scan_req.scan_id;
285 cancel_req.cancel_req.requester = req->scan_req.scan_req_id;
286 cancel_req.cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE;
287 cancel_req.cancel_req.vdev_id = req->scan_req.vdev_id;
288 /* send scan cancel to fw */
289 status = tgt_scan_cancel(&cancel_req);
290 if (status != QDF_STATUS_SUCCESS)
291 scm_err("tgt_scan_cancel failed: status: %d, scanid: %d",
292 status, req->scan_req.scan_id);
293 /* notify event handler about scan cancellation */
294 scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED);
295
296 return status;
297 }
298
299 static QDF_STATUS
scm_scan_serialize_callback(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)300 scm_scan_serialize_callback(struct wlan_serialization_command *cmd,
301 enum wlan_serialization_cb_reason reason)
302 {
303 struct scan_start_request *req;
304 QDF_STATUS status;
305
306 if (!cmd) {
307 scm_err("cmd is NULL, reason: %d", reason);
308 QDF_ASSERT(0);
309 return QDF_STATUS_E_NULL_VALUE;
310 }
311
312 if (!cmd->umac_cmd) {
313 scm_err("cmd->umac_cmd is NULL , reason: %d", reason);
314 QDF_ASSERT(0);
315 return QDF_STATUS_E_NULL_VALUE;
316 }
317
318 req = cmd->umac_cmd;
319 if (!req->vdev) {
320 scm_err("NULL vdev. req:0x%pK, reason:%d\n", req, reason);
321 QDF_ASSERT(0);
322 return QDF_STATUS_E_NULL_VALUE;
323 }
324
325 qdf_mtrace(QDF_MODULE_ID_SERIALIZATION, QDF_MODULE_ID_SCAN, reason,
326 req->scan_req.vdev_id, req->scan_req.scan_id);
327
328 switch (reason) {
329 case WLAN_SER_CB_ACTIVATE_CMD:
330 /* command moved to active list
331 * modify the params if required for concurrency case.
332 */
333 status = scm_activate_scan_request(req);
334 break;
335
336 case WLAN_SER_CB_CANCEL_CMD:
337 /* command removed from pending list.
338 * notify registered scan event handlers with
339 * status completed and reason cancelled.
340 */
341 status = scm_post_internal_scan_complete_event(req,
342 SCAN_REASON_CANCELLED);
343 break;
344
345 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
346 /* active command timed out.
347 * prepare internal scan cancel request
348 */
349 status = scm_cancel_scan_request(req);
350 break;
351
352 case WLAN_SER_CB_RELEASE_MEM_CMD:
353 /* command successfully completed.
354 * Release vdev reference and free scan_start_request memory
355 */
356 cmd->umac_cmd = NULL;
357 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
358 status = scm_scan_free_scan_request_mem(req);
359 break;
360
361 default:
362 /* Do nothing but logging */
363 QDF_ASSERT(0);
364 status = QDF_STATUS_E_INVAL;
365 break;
366 }
367
368 return status;
369 }
370
scm_is_scan_allowed(struct wlan_objmgr_vdev * vdev)371 bool scm_is_scan_allowed(struct wlan_objmgr_vdev *vdev)
372 {
373 struct wlan_scan_obj *scan_psoc_obj;
374 struct scan_vdev_obj *scan_vdev_obj;
375
376 if (!vdev) {
377 scm_err("vdev is NULL");
378 return false;
379 }
380
381 scan_psoc_obj = wlan_vdev_get_scan_obj(vdev);
382 if (!scan_psoc_obj) {
383 scm_err("Couldn't find scan psoc object");
384 return false;
385 }
386
387 if (scan_psoc_obj->scan_disabled) {
388 scm_err_rl("scan disabled %x, for psoc",
389 scan_psoc_obj->scan_disabled);
390 return false;
391 }
392
393 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
394 if (!scan_vdev_obj) {
395 scm_err("Couldn't find scan vdev object");
396 return false;
397 }
398
399 if (scan_vdev_obj->scan_disabled) {
400 scm_err_rl("scan disabled %x on vdev_id:%d",
401 scan_vdev_obj->scan_disabled,
402 wlan_vdev_get_id(vdev));
403 return false;
404 }
405
406 return true;
407 }
408
409 #ifdef WLAN_POLICY_MGR_ENABLE
410 /**
411 * scm_update_dbs_scan_ctrl_ext_flag() - update dbs scan ctrl flags
412 * @req: pointer to scan request
413 *
414 * This function sets scan_ctrl_flags_ext value depending on the type of
415 * scan and the channel lists.
416 *
417 * Non-DBS scan is requested if any of the below case is met:
418 * 1. HW is DBS incapable
419 * 2. A high accuracy scan request is sent by kernel.
420 *
421 * DBS scan is enabled for these conditions:
422 * 1. A low power or low span scan request is sent by kernel.
423 * For remaining cases DBS is enabled by default.
424 * Return: void
425 */
426 static void
scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request * req)427 scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req)
428 {
429 struct wlan_objmgr_psoc *psoc;
430 uint32_t scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT;
431 bool ndi_present;
432
433 psoc = wlan_vdev_get_psoc(req->vdev);
434
435 if (!policy_mgr_is_dbs_scan_allowed(psoc)) {
436 scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS;
437 goto end;
438 }
439
440 if (!wlan_scan_cfg_honour_nl_scan_policy_flags(psoc)) {
441 scm_debug_rl("nl scan policy flags not honoured, goto end");
442 goto end;
443 }
444
445 ndi_present = policy_mgr_mode_specific_connection_count(psoc,
446 PM_NDI_MODE,
447 NULL);
448
449 if (ndi_present || policy_mgr_is_hw_dbs_2x2_capable(psoc)) {
450 scm_debug("NDP present or HW 2x2 capable, go for DBS scan");
451 goto end;
452 }
453
454 if (req->scan_req.scan_policy_high_accuracy) {
455 scm_debug("high accuracy scan received, going for non-dbs scan");
456 scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS;
457 goto end;
458 }
459
460 if ((req->scan_req.scan_policy_low_power) ||
461 (req->scan_req.scan_policy_low_span)) {
462 scm_debug("low power/span scan received, going for dbs scan");
463 scan_dbs_policy = SCAN_DBS_POLICY_IGNORE_DUTY;
464 goto end;
465 }
466
467 end:
468 req->scan_req.scan_ctrl_flags_ext |=
469 ((scan_dbs_policy << SCAN_FLAG_EXT_DBS_SCAN_POLICY_BIT)
470 & SCAN_FLAG_EXT_DBS_SCAN_POLICY_MASK);
471 }
472
473
474 /**
475 * scm_update_passive_dwell_time() - update dwell passive time
476 * @vdev: vdev object
477 * @req: scan request
478 *
479 * Return: None
480 */
481 static void
scm_update_passive_dwell_time(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)482 scm_update_passive_dwell_time(struct wlan_objmgr_vdev *vdev,
483 struct scan_start_request *req)
484 {
485 struct wlan_objmgr_psoc *psoc;
486
487 psoc = wlan_vdev_get_psoc(vdev);
488 if (!psoc)
489 return;
490
491 if (policy_mgr_is_sta_connected_2g(psoc) &&
492 !policy_mgr_is_hw_dbs_capable(psoc) &&
493 ucfg_scan_get_bt_activity(psoc))
494 req->scan_req.dwell_time_passive =
495 PASSIVE_DWELL_TIME_BT_A2DP_ENABLED;
496 }
497
498 static const struct probe_time_dwell_time
499 scan_probe_time_dwell_time_map[SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE] = {
500 {28, 11}, /* 0 SSID */
501 {28, 20}, /* 1 SSID */
502 {28, 20}, /* 2 SSID */
503 {28, 20}, /* 3 SSID */
504 {28, 20}, /* 4 SSID */
505 {28, 20}, /* 5 SSID */
506 {28, 20}, /* 6 SSID */
507 {28, 11}, /* 7 SSID */
508 {28, 11}, /* 8 SSID */
509 {28, 11}, /* 9 SSID */
510 {28, 8} /* 10 SSID */
511 };
512
513 /**
514 * scm_scan_get_burst_duration() - get burst duration depending on max chan
515 * and miracast.
516 * @max_ch_time: max channel time
517 * @miracast_enabled: if miracast is enabled
518 *
519 * Return: burst_duration
520 */
521 static inline
scm_scan_get_burst_duration(int max_ch_time,bool miracast_enabled)522 int scm_scan_get_burst_duration(int max_ch_time, bool miracast_enabled)
523 {
524 int burst_duration = 0;
525
526 if (miracast_enabled) {
527 /*
528 * When miracast is running, burst
529 * duration needs to be minimum to avoid
530 * any stutter or glitch in miracast
531 * during station scan
532 */
533 if (max_ch_time <= SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION)
534 burst_duration = max_ch_time;
535 else
536 burst_duration = SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION;
537 } else {
538 /*
539 * If miracast is not running, accommodate max
540 * stations to make the scans faster
541 */
542 burst_duration = SCAN_GO_BURST_SCAN_MAX_NUM_OFFCHANNELS *
543 max_ch_time;
544
545 if (burst_duration > SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION) {
546 uint8_t channels = SCAN_P2P_SCAN_MAX_BURST_DURATION /
547 max_ch_time;
548
549 if (channels)
550 burst_duration = channels * max_ch_time;
551 else
552 burst_duration =
553 SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION;
554 }
555 }
556 return burst_duration;
557 }
558
559 #define SCM_ACTIVE_DWELL_TIME_NAN 60
560 #define SCM_ACTIVE_DWELL_TIME_SAP 40
561
562 /**
563 * scm_req_update_concurrency_params() - update scan req params depending on
564 * concurrent mode present.
565 * @vdev: vdev object pointer
566 * @req: scan request
567 * @scan_obj: scan object
568 *
569 * Return: void
570 */
scm_req_update_concurrency_params(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req,struct wlan_scan_obj * scan_obj)571 static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev,
572 struct scan_start_request *req,
573 struct wlan_scan_obj *scan_obj)
574 {
575 bool ap_present, go_present, sta_active, p2p_cli_present, ndi_present;
576 struct wlan_objmgr_psoc *psoc;
577 uint16_t sap_peer_count = 0;
578 uint16_t go_peer_count = 0;
579 struct wlan_objmgr_pdev *pdev;
580
581 psoc = wlan_vdev_get_psoc(vdev);
582 pdev = wlan_vdev_get_pdev(vdev);
583
584 if (!psoc || !pdev)
585 return;
586
587 ap_present = policy_mgr_mode_specific_connection_count(
588 psoc, PM_SAP_MODE, NULL);
589 go_present = policy_mgr_mode_specific_connection_count(
590 psoc, PM_P2P_GO_MODE, NULL);
591 p2p_cli_present = policy_mgr_mode_specific_connection_count(
592 psoc, PM_P2P_CLIENT_MODE, NULL);
593 sta_active = policy_mgr_mode_specific_connection_count(
594 psoc, PM_STA_MODE, NULL);
595 ndi_present = policy_mgr_mode_specific_connection_count(
596 psoc, PM_NDI_MODE, NULL);
597 if (ap_present)
598 sap_peer_count =
599 wlan_util_get_peer_count_for_mode(pdev, QDF_SAP_MODE);
600 if (go_present)
601 go_peer_count =
602 wlan_util_get_peer_count_for_mode(pdev, QDF_P2P_GO_MODE);
603
604 if (!req->scan_req.scan_f_passive)
605 scm_update_passive_dwell_time(vdev, req);
606
607 if (policy_mgr_get_connection_count(psoc)) {
608 if (!req->scan_req.scan_f_passive)
609 req->scan_req.dwell_time_active =
610 scan_obj->scan_def.conc_active_dwell;
611 /*
612 * Irrespective of any concurrency, if a scan request is
613 * triggered to get channel utilization for the current
614 * connected channel, passive scan dwell time should be
615 * MLME_GET_CHAN_STATS_PASSIVE_SCAN_TIME
616 */
617 if (!req->scan_req.scan_f_pause_home_channel)
618 req->scan_req.dwell_time_passive =
619 scan_obj->scan_def.conc_passive_dwell;
620 req->scan_req.max_rest_time =
621 scan_obj->scan_def.conc_max_rest_time;
622 req->scan_req.min_rest_time =
623 scan_obj->scan_def.conc_min_rest_time;
624 req->scan_req.idle_time = scan_obj->scan_def.conc_idle_time;
625 }
626
627 if (wlan_vdev_is_up(req->vdev) != QDF_STATUS_SUCCESS)
628 req->scan_req.adaptive_dwell_time_mode =
629 scan_obj->scan_def.adaptive_dwell_time_mode_nc;
630 /*
631 * If AP/GO is active and has connected clients :
632 * 1.set min rest time same as max rest time, so that
633 * firmware spends more time on home channel which will
634 * increase the probability of sending beacon at TBTT
635 * 2.if DBS is supported and SAP is not on 2g,
636 * do not reset active dwell time for 2g.
637 */
638
639 /*
640 * For SAP, the dwell time cannot exceed 32 ms as it can't go
641 * offchannel more than 32 ms. For Go, since we
642 * advertise NOA, GO can have regular dwell time which is 40 ms.
643 */
644 if ((ap_present && sap_peer_count) ||
645 (go_present && go_peer_count)) {
646 if ((policy_mgr_is_hw_dbs_capable(psoc) &&
647 policy_mgr_is_sap_go_on_2g(psoc)) ||
648 !policy_mgr_is_hw_dbs_capable(psoc)) {
649 if (ap_present)
650 req->scan_req.dwell_time_active_2g =
651 QDF_MIN(req->scan_req.dwell_time_active,
652 (SCAN_CTS_DURATION_MS_MAX -
653 SCAN_ROAM_SCAN_CHANNEL_SWITCH_TIME));
654 else
655 req->scan_req.dwell_time_active_2g = 0;
656 }
657 req->scan_req.min_rest_time = req->scan_req.max_rest_time;
658 }
659
660 if (policy_mgr_current_concurrency_is_mcc(psoc))
661 req->scan_req.min_rest_time =
662 scan_obj->scan_def.conc_max_rest_time;
663
664 /*
665 * If scan req for SAP (ACS Sacn) use dwell_time_active_def as dwell
666 * time for 2g channels instead of dwell_time_active_2g
667 */
668 if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE)
669 req->scan_req.dwell_time_active_2g = SCM_ACTIVE_DWELL_TIME_SAP;
670
671 if (req->scan_req.scan_type == SCAN_TYPE_DEFAULT) {
672 /*
673 * Decide burst_duration and dwell_time_active based on
674 * what type of devices are active.
675 */
676 do {
677 if (ap_present && go_present && sta_active) {
678 if (req->scan_req.dwell_time_active <=
679 SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION)
680 req->scan_req.burst_duration =
681 req->scan_req.dwell_time_active;
682 else
683 req->scan_req.burst_duration =
684 SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION;
685
686 break;
687 }
688
689 if (scan_obj->miracast_enabled &&
690 policy_mgr_is_mcc_in_24G(psoc))
691 req->scan_req.max_rest_time =
692 scan_obj->scan_def.sta_miracast_mcc_rest_time;
693
694 if (go_present) {
695 /*
696 * Background scan while GO is sending beacons.
697 * Every off-channel transition has overhead of
698 * 2 beacon intervals for NOA. Maximize number
699 * of channels in every transition by using
700 * burst scan.
701 */
702 if (scan_obj->scan_def.go_scan_burst_duration)
703 req->scan_req.burst_duration =
704 scan_obj->
705 scan_def.go_scan_burst_duration;
706 else
707 req->scan_req.burst_duration =
708 scm_scan_get_burst_duration(
709 req->scan_req.
710 dwell_time_active,
711 scan_obj->
712 miracast_enabled);
713 break;
714 }
715 if ((sta_active || p2p_cli_present)) {
716 if (scan_obj->scan_def.sta_scan_burst_duration)
717 req->scan_req.burst_duration =
718 scan_obj->scan_def.
719 sta_scan_burst_duration;
720 break;
721 }
722
723 if (go_present && sta_active) {
724 req->scan_req.burst_duration =
725 req->scan_req.dwell_time_active;
726 break;
727 }
728
729 if (ndi_present || (p2p_cli_present && sta_active)) {
730 req->scan_req.burst_duration = 0;
731 break;
732 }
733 } while (0);
734
735 if (ap_present) {
736 uint8_t ssid_num;
737
738 ssid_num = req->scan_req.num_ssids *
739 req->scan_req.num_bssid;
740 req->scan_req.repeat_probe_time =
741 scan_probe_time_dwell_time_map[
742 QDF_MIN(ssid_num,
743 SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE
744 - 1)].probe_time;
745 req->scan_req.n_probes =
746 (req->scan_req.repeat_probe_time > 0) ?
747 req->scan_req.dwell_time_active /
748 req->scan_req.repeat_probe_time : 0;
749 }
750 }
751
752 if (ap_present) {
753 uint16_t ap_chan_freq;
754 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
755
756 ap_chan_freq = policy_mgr_get_channel(psoc, PM_SAP_MODE, NULL);
757 /*
758 * P2P/STA scan while SoftAP is sending beacons.
759 * Max duration of CTS2self is 32 ms, which limits the
760 * dwell time.
761 * If DBS is supported and:
762 * 1.if SAP is on 2G channel then keep passive
763 * dwell time default.
764 * 2.if SAP is on 5G/6G channel then update dwell time active.
765 */
766 if (sap_peer_count) {
767 if (policy_mgr_is_hw_dbs_capable(psoc) &&
768 (WLAN_REG_IS_5GHZ_CH_FREQ(ap_chan_freq) ||
769 WLAN_REG_IS_6GHZ_CHAN_FREQ(ap_chan_freq))) {
770 req->scan_req.dwell_time_active =
771 QDF_MIN(req->scan_req.dwell_time_active,
772 (SCAN_CTS_DURATION_MS_MAX -
773 SCAN_ROAM_SCAN_CHANNEL_SWITCH_TIME));
774 }
775 if (!policy_mgr_is_hw_dbs_capable(psoc) ||
776 (policy_mgr_is_hw_dbs_capable(psoc) &&
777 WLAN_REG_IS_5GHZ_CH_FREQ(ap_chan_freq))) {
778 req->scan_req.dwell_time_passive =
779 req->scan_req.dwell_time_active;
780 }
781 }
782
783 if (scan_obj->scan_def.ap_scan_burst_duration) {
784 req->scan_req.burst_duration =
785 scan_obj->scan_def.ap_scan_burst_duration;
786 } else {
787 req->scan_req.burst_duration = 0;
788 if (wlan_reg_is_dfs_for_freq(pdev, ap_chan_freq))
789 req->scan_req.burst_duration =
790 SCAN_BURST_SCAN_MAX_NUM_OFFCHANNELS *
791 req->scan_req.dwell_time_active;
792 }
793 }
794
795 if (ndi_present) {
796 req->scan_req.dwell_time_active =
797 SCM_ACTIVE_DWELL_TIME_NAN;
798 req->scan_req.dwell_time_active_2g =
799 QDF_MIN(req->scan_req.dwell_time_active_2g,
800 SCM_ACTIVE_DWELL_TIME_NAN);
801 scm_debug("NDP active modify dwell time 2ghz %d",
802 req->scan_req.dwell_time_active_2g);
803 }
804
805 if (sta_active) {
806 req->scan_req.dwell_time_active_6g =
807 scan_obj->scan_def.active_dwell_time_6g_conc;
808 /*
809 * Irrespective of any concurrency, if a scan request is
810 * triggered to get channel utilization for the current
811 * connected channel, 6g passive scan dwell time should be
812 * MLME_GET_CHAN_STATS_WIDE_BAND_PASSIVE_SCAN_TIME
813 */
814 if (!req->scan_req.scan_f_pause_home_channel)
815 req->scan_req.dwell_time_passive_6g =
816 scan_obj->scan_def.passive_dwell_time_6g_conc;
817 }
818 }
819
scm_update_5ghz_6ghz_chlist(struct scan_start_request * req,qdf_freq_t intf_freq)820 static inline void scm_update_5ghz_6ghz_chlist(struct scan_start_request *req,
821 qdf_freq_t intf_freq)
822 {
823 struct wlan_objmgr_psoc *psoc;
824 struct wlan_objmgr_pdev *pdev;
825 uint32_t i;
826 uint32_t num_scan_channels;
827
828 pdev = wlan_vdev_get_pdev(req->vdev);
829 if (!pdev)
830 return;
831
832 psoc = wlan_pdev_get_psoc(pdev);
833 if (!psoc)
834 return;
835
836 num_scan_channels = 0;
837 for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
838 if (!WLAN_REG_IS_24GHZ_CH_FREQ(
839 req->scan_req.chan_list.chan[i].freq)) {
840 /*
841 * If no intf_freq, skip all 5 + 6 GHz freq
842 * else, skip only freq on same mac as intf_freq
843 */
844 if (!intf_freq ||
845 policy_mgr_2_freq_always_on_same_mac(
846 psoc, intf_freq,
847 req->scan_req.chan_list.chan[i].freq))
848 continue;
849 }
850
851 req->scan_req.chan_list.chan[num_scan_channels++] =
852 req->scan_req.chan_list.chan[i];
853 }
854 if (num_scan_channels < req->scan_req.chan_list.num_chan)
855 scm_debug("5g chan skipped (%d, %d)",
856 req->scan_req.chan_list.num_chan, num_scan_channels);
857 req->scan_req.chan_list.num_chan = num_scan_channels;
858 }
859
scm_update_24g_chlist(struct scan_start_request * req)860 static inline void scm_update_24g_chlist(struct scan_start_request *req)
861 {
862 uint32_t i;
863 uint32_t num_scan_channels;
864
865 num_scan_channels = 0;
866 for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
867 if (WLAN_REG_IS_24GHZ_CH_FREQ(
868 req->scan_req.chan_list.chan[i].freq))
869 continue;
870
871 req->scan_req.chan_list.chan[num_scan_channels++] =
872 req->scan_req.chan_list.chan[i];
873 }
874 if (num_scan_channels < req->scan_req.chan_list.num_chan)
875 scm_debug("2g chan skipped (%d, %d)",
876 req->scan_req.chan_list.num_chan, num_scan_channels);
877 req->scan_req.chan_list.num_chan = num_scan_channels;
878 }
879
880 /**
881 * scm_filter_6g_and_indoor_freq() - Modify channel list to skip 6Ghz and 5Ghz
882 * indoor channel if hw mode is non dbs and SAP is present
883 * @pdev: pointer to pdev
884 * @req: scan request
885 *
886 * Return: None
887 */
scm_filter_6g_and_indoor_freq(struct wlan_objmgr_pdev * pdev,struct scan_start_request * req)888 static void scm_filter_6g_and_indoor_freq(struct wlan_objmgr_pdev *pdev,
889 struct scan_start_request *req)
890 {
891 uint32_t i;
892 uint32_t num_scan_channels;
893 qdf_freq_t freq;
894
895 num_scan_channels = 0;
896 for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
897 freq = req->scan_req.chan_list.chan[i].freq;
898 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
899 continue;
900
901 if (wlan_reg_is_freq_indoor(pdev, freq))
902 continue;
903
904 req->scan_req.chan_list.chan[num_scan_channels++] =
905 req->scan_req.chan_list.chan[i];
906 }
907 if (num_scan_channels < req->scan_req.chan_list.num_chan)
908 scm_debug("6g and indoor channel chan skipped (%d, %d)",
909 req->scan_req.chan_list.num_chan, num_scan_channels);
910 req->scan_req.chan_list.num_chan = num_scan_channels;
911 }
912
913 /**
914 * scm_scan_chlist_concurrency_modify() - modify chan list to skip 5G if
915 * required
916 * @vdev: vdev object
917 * @req: scan request
918 *
919 * Check and skip 5G chan list based on DFS AP present and current hw mode.
920 *
921 * Return: void
922 */
scm_scan_chlist_concurrency_modify(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)923 static inline void scm_scan_chlist_concurrency_modify(
924 struct wlan_objmgr_vdev *vdev, struct scan_start_request *req)
925 {
926 struct wlan_objmgr_psoc *psoc;
927 struct wlan_objmgr_pdev *pdev;
928 struct wlan_scan_obj *scan_obj;
929 uint16_t trim;
930 qdf_freq_t dfs_ap_freq;
931
932 pdev = wlan_vdev_get_pdev(vdev);
933 if (!pdev)
934 return;
935
936 psoc = wlan_pdev_get_psoc(pdev);
937 if (!psoc)
938 return;
939
940 scan_obj = wlan_vdev_get_scan_obj(req->vdev);
941 if (!scan_obj)
942 return;
943
944 /* do this only for STA and P2P-CLI mode */
945 if (!(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_STA_MODE) &&
946 !(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_P2P_CLIENT_MODE))
947 return;
948
949 if (policy_mgr_scan_trim_5g_chnls_for_dfs_ap(psoc, &dfs_ap_freq))
950 scm_update_5ghz_6ghz_chlist(req, dfs_ap_freq);
951
952 if (scan_obj->scan_def.conc_chlist_trim) {
953 trim = policy_mgr_scan_trim_chnls_for_connected_ap(pdev);
954 if (trim & TRIM_CHANNEL_LIST_5G)
955 scm_update_5ghz_6ghz_chlist(req, 0);
956 if (trim & TRIM_CHANNEL_LIST_24G)
957 scm_update_24g_chlist(req);
958 }
959
960 /*
961 * Do not allow STA to scan on 6Ghz or indoor channel for non dbs
962 * hardware if SAP and skip_6g_and_indoor_freq_scan ini are present
963 */
964 if (scan_obj->scan_def.skip_6g_and_indoor_freq &&
965 !policy_mgr_is_hw_dbs_capable(psoc) &&
966 (wlan_vdev_mlme_get_opmode(req->vdev) == QDF_STA_MODE) &&
967 policy_mgr_mode_specific_connection_count(psoc, PM_SAP_MODE, NULL))
968 scm_filter_6g_and_indoor_freq(pdev, req);
969
970 }
971 #else
972 static inline
scm_req_update_concurrency_params(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req,struct wlan_scan_obj * scan_obj)973 void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev,
974 struct scan_start_request *req,
975 struct wlan_scan_obj *scan_obj)
976 {
977 }
978
979 static inline void
scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request * req)980 scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req)
981 {
982 }
983
scm_scan_chlist_concurrency_modify(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)984 static inline void scm_scan_chlist_concurrency_modify(
985 struct wlan_objmgr_vdev *vdev, struct scan_start_request *req)
986 {
987 }
988 #endif
989
990 /**
991 * scm_update_channel_list() - update scan req params depending on dfs inis
992 * and initial scan request.
993 * @req: scan request
994 * @scan_obj: scan object
995 *
996 * Return: void
997 */
998 static void
scm_update_channel_list(struct scan_start_request * req,struct wlan_scan_obj * scan_obj)999 scm_update_channel_list(struct scan_start_request *req,
1000 struct wlan_scan_obj *scan_obj)
1001 {
1002 uint8_t i;
1003 uint8_t num_scan_channels = 0;
1004 struct scan_vdev_obj *scan_vdev_obj;
1005 struct wlan_objmgr_pdev *pdev;
1006 bool first_scan_done = true;
1007 bool p2p_search = false;
1008 bool skip_dfs_ch = true;
1009 uint32_t first_freq;
1010
1011 pdev = wlan_vdev_get_pdev(req->vdev);
1012
1013 scan_vdev_obj = wlan_get_vdev_scan_obj(req->vdev);
1014 if (!scan_vdev_obj) {
1015 scm_err("null scan_vdev_obj");
1016 return;
1017 }
1018
1019 if (!scan_vdev_obj->first_scan_done) {
1020 first_scan_done = false;
1021 scan_vdev_obj->first_scan_done = true;
1022 }
1023
1024 if (req->scan_req.scan_type == SCAN_TYPE_P2P_SEARCH)
1025 p2p_search = true;
1026 /*
1027 * No need to update channels if req is single channel* ie ROC,
1028 * Preauth or a single channel scan etc.
1029 * If the single chan in the scan channel list is an NOL channel,it is
1030 * removed and it would reduce the number of scan channels to 0.
1031 */
1032 first_freq = req->scan_req.chan_list.chan[0].freq;
1033 if ((req->scan_req.chan_list.num_chan == 1) &&
1034 (!utils_dfs_is_freq_in_nol(pdev, first_freq)))
1035 return;
1036
1037 /* do this only for STA and P2P-CLI mode */
1038 if ((!(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_STA_MODE) &&
1039 !(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_P2P_CLIENT_MODE)) &&
1040 !p2p_search)
1041 skip_dfs_ch = false;
1042
1043 if ((scan_obj->scan_def.allow_dfs_chan_in_scan &&
1044 (scan_obj->scan_def.allow_dfs_chan_in_first_scan ||
1045 first_scan_done)) &&
1046 !(scan_obj->scan_def.skip_dfs_chan_in_p2p_search && p2p_search) &&
1047 !scan_obj->miracast_enabled)
1048 skip_dfs_ch = false;
1049
1050 for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
1051 uint32_t freq;
1052
1053 freq = req->scan_req.chan_list.chan[i].freq;
1054 if ((wlan_reg_is_6ghz_chan_freq(freq) &&
1055 !wlan_reg_is_6ghz_band_set(pdev))) {
1056 scm_nofl_debug("Skip 6 GHz freq = %d", freq);
1057 continue;
1058 }
1059 if (skip_dfs_ch &&
1060 wlan_reg_chan_has_dfs_attribute_for_freq(pdev, freq)) {
1061 scm_nofl_debug("Skip DFS freq %d", freq);
1062 continue;
1063 }
1064 if (utils_dfs_is_freq_in_nol(pdev, freq)) {
1065 scm_nofl_debug("Skip NOL freq %d", freq);
1066 continue;
1067 }
1068
1069 req->scan_req.chan_list.chan[num_scan_channels++] =
1070 req->scan_req.chan_list.chan[i];
1071 }
1072
1073 req->scan_req.chan_list.num_chan = num_scan_channels;
1074
1075 scm_update_6ghz_channel_list(req, scan_obj);
1076 scm_scan_chlist_concurrency_modify(req->vdev, req);
1077 }
1078
1079 /**
1080 * scm_req_update_dwell_time_as_per_scan_mode() - update scan req params
1081 * dwell time as per scan mode.
1082 * @vdev: vdev to update
1083 * @req: scan request
1084 *
1085 * Return: void
1086 */
1087 static void
scm_req_update_dwell_time_as_per_scan_mode(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)1088 scm_req_update_dwell_time_as_per_scan_mode(
1089 struct wlan_objmgr_vdev *vdev,
1090 struct scan_start_request *req)
1091 {
1092 struct wlan_objmgr_psoc *psoc;
1093
1094 psoc = wlan_vdev_get_psoc(vdev);
1095
1096 if (req->scan_req.scan_policy_low_span &&
1097 wlan_scan_cfg_honour_nl_scan_policy_flags(psoc)) {
1098 req->scan_req.adaptive_dwell_time_mode =
1099 SCAN_DWELL_MODE_STATIC;
1100 req->scan_req.dwell_time_active =
1101 QDF_MIN(req->scan_req.dwell_time_active,
1102 LOW_SPAN_ACTIVE_DWELL_TIME);
1103 req->scan_req.dwell_time_active_2g =
1104 QDF_MIN(req->scan_req.dwell_time_active_2g,
1105 LOW_SPAN_ACTIVE_DWELL_TIME);
1106 req->scan_req.dwell_time_passive =
1107 QDF_MIN(req->scan_req.dwell_time_passive,
1108 LOW_SPAN_PASSIVE_DWELL_TIME);
1109 }
1110 }
1111
1112 /**
1113 * scm_update_aux_scan_ctrl_ext_flag() - update aux scan policy
1114 * @req: pointer to scan request
1115 *
1116 * Set aux scan bits in scan_ctrl_ext_flag value depending on scan type.
1117 *
1118 * Return: None
1119 */
1120
1121 static void
scm_update_aux_scan_ctrl_ext_flag(struct scan_start_request * req)1122 scm_update_aux_scan_ctrl_ext_flag(struct scan_start_request *req)
1123 {
1124 if (req->scan_req.scan_policy_low_span)
1125 req->scan_req.scan_ctrl_flags_ext |= SCAN_FLAG_EXT_AUX_FAST_SCAN;
1126 else if (req->scan_req.scan_policy_low_power)
1127 req->scan_req.scan_ctrl_flags_ext |= SCAN_FLAG_EXT_AUX_FAST_SCAN;
1128 else if (req->scan_req.scan_policy_high_accuracy)
1129 req->scan_req.scan_ctrl_flags_ext |=
1130 SCAN_FLAG_EXT_AUX_RELIABLE_SCAN;
1131 }
1132
1133 /**
1134 * scm_scan_req_update_params() - update scan req params depending on modes
1135 * and scan type.
1136 * @vdev: vdev object pointer
1137 * @req: scan request
1138 * @scan_obj: scan object
1139 *
1140 * Return: void
1141 */
1142 static void
scm_scan_req_update_params(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req,struct wlan_scan_obj * scan_obj)1143 scm_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
1144 struct scan_start_request *req,
1145 struct wlan_scan_obj *scan_obj)
1146 {
1147 struct chan_list *custom_chan_list;
1148 struct wlan_objmgr_pdev *pdev;
1149 uint8_t pdev_id;
1150 struct wlan_objmgr_psoc *psoc;
1151
1152 /* Ensure correct number of probes are sent on active channel */
1153 if (!req->scan_req.repeat_probe_time)
1154 req->scan_req.repeat_probe_time =
1155 req->scan_req.dwell_time_active / SCAN_NPROBES_DEFAULT;
1156
1157 if (req->scan_req.scan_f_passive)
1158 req->scan_req.scan_ctrl_flags_ext |=
1159 SCAN_FLAG_EXT_FILTER_PUBLIC_ACTION_FRAME;
1160
1161 if (!req->scan_req.n_probes)
1162 req->scan_req.n_probes = (req->scan_req.repeat_probe_time > 0) ?
1163 req->scan_req.dwell_time_active /
1164 req->scan_req.repeat_probe_time : 0;
1165
1166 if (req->scan_req.scan_type == SCAN_TYPE_P2P_SEARCH ||
1167 req->scan_req.scan_type == SCAN_TYPE_P2P_LISTEN) {
1168 req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC;
1169 req->scan_req.dwell_time_active_2g = 0;
1170 if (req->scan_req.scan_type == SCAN_TYPE_P2P_LISTEN) {
1171 req->scan_req.repeat_probe_time = 0;
1172 } else {
1173 req->scan_req.scan_f_filter_prb_req = true;
1174 if (!req->scan_req.num_ssids)
1175 req->scan_req.scan_f_bcast_probe = true;
1176
1177 req->scan_req.dwell_time_active +=
1178 P2P_SEARCH_DWELL_TIME_INC;
1179 /*
1180 * 3 channels with default max dwell time 40 ms.
1181 * Cap limit will be set by
1182 * P2P_SCAN_MAX_BURST_DURATION. Burst duration
1183 * should be such that no channel is scanned less
1184 * than the dwell time in normal scenarios.
1185 */
1186 if (req->scan_req.chan_list.num_chan ==
1187 WLAN_P2P_SOCIAL_CHANNELS &&
1188 !scan_obj->miracast_enabled)
1189 req->scan_req.repeat_probe_time =
1190 req->scan_req.dwell_time_active / 5;
1191 else
1192 req->scan_req.repeat_probe_time =
1193 req->scan_req.dwell_time_active / 3;
1194 if (scan_obj->scan_def.p2p_scan_burst_duration) {
1195 req->scan_req.burst_duration =
1196 scan_obj->scan_def.
1197 p2p_scan_burst_duration;
1198 } else {
1199 req->scan_req.burst_duration =
1200 BURST_SCAN_MAX_NUM_OFFCHANNELS *
1201 req->scan_req.dwell_time_active;
1202 if (req->scan_req.burst_duration >
1203 P2P_SCAN_MAX_BURST_DURATION) {
1204 uint8_t channels =
1205 P2P_SCAN_MAX_BURST_DURATION /
1206 req->scan_req.dwell_time_active;
1207 if (channels)
1208 req->scan_req.burst_duration =
1209 channels *
1210 req->scan_req.dwell_time_active;
1211 else
1212 req->scan_req.burst_duration =
1213 P2P_SCAN_MAX_BURST_DURATION;
1214 }
1215 }
1216 req->scan_req.scan_ev_bss_chan = false;
1217 }
1218 } else {
1219 req->scan_req.scan_f_cck_rates = true;
1220 if (!req->scan_req.num_ssids)
1221 req->scan_req.scan_f_bcast_probe = true;
1222 req->scan_req.scan_f_add_ds_ie_in_probe = true;
1223 req->scan_req.scan_f_filter_prb_req = true;
1224 req->scan_req.scan_f_add_tpc_ie_in_probe = true;
1225 }
1226
1227 scm_update_dbs_scan_ctrl_ext_flag(req);
1228
1229 psoc = wlan_vdev_get_psoc(vdev);
1230 if (wlan_scan_get_aux_support(psoc))
1231 scm_update_aux_scan_ctrl_ext_flag(req);
1232
1233 /*
1234 * No need to update conncurrency parmas if req is passive scan on
1235 * single channel ie ROC, Preauth etc
1236 */
1237 if (!(req->scan_req.scan_f_passive &&
1238 req->scan_req.chan_list.num_chan == 1) &&
1239 req->scan_req.scan_type != SCAN_TYPE_RRM)
1240 scm_req_update_concurrency_params(vdev, req, scan_obj);
1241
1242 if (req->scan_req.scan_type == SCAN_TYPE_RRM)
1243 req->scan_req.scan_ctrl_flags_ext |= SCAN_FLAG_EXT_RRM_SCAN_IND;
1244
1245 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_DEVICE_MODE ||
1246 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) &&
1247 !qdf_is_macaddr_zero(&req->scan_req.bssid_list[0]) &&
1248 !qdf_is_macaddr_broadcast(&req->scan_req.bssid_list[0]))
1249 req->scan_req.scan_ctrl_flags_ext |=
1250 SCAN_FLAG_EXT_STOP_IF_BSSID_FOUND;
1251
1252 scm_req_update_dwell_time_as_per_scan_mode(vdev, req);
1253
1254 scm_debug("scan_ctrl_flags_ext %0x", req->scan_req.scan_ctrl_flags_ext);
1255 /*
1256 * Set wide band flag if enabled. This will cause
1257 * phymode TLV being sent to FW.
1258 */
1259 pdev = wlan_vdev_get_pdev(vdev);
1260 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1261 /*
1262 * Trigger wide band scan also if
1263 * scan_f_report_cca_busy_for_each_20mhz flag is set
1264 */
1265 if (ucfg_scan_get_wide_band_scan(pdev) ||
1266 req->scan_req.scan_f_report_cca_busy_for_each_20mhz)
1267 req->scan_req.scan_f_wide_band = true;
1268 else
1269 req->scan_req.scan_f_wide_band = false;
1270
1271 /*
1272 * Overwrite scan channels with custom scan channel
1273 * list if configured.
1274 */
1275 custom_chan_list = &scan_obj->pdev_info[pdev_id].custom_chan_list;
1276 if (custom_chan_list->num_chan)
1277 qdf_mem_copy(&req->scan_req.chan_list, custom_chan_list,
1278 sizeof(struct chan_list));
1279 else if (!req->scan_req.chan_list.num_chan)
1280 ucfg_scan_init_chanlist_params(req, 0, NULL, NULL);
1281
1282 scm_update_channel_list(req, scan_obj);
1283
1284 wlan_scan_update_low_latency_profile_chnlist(vdev, req);
1285 }
1286
scm_print_scan_req_info(struct scan_req_params * req)1287 static inline void scm_print_scan_req_info(struct scan_req_params *req)
1288 {
1289 uint32_t buff_len;
1290 char *chan_buff;
1291 uint32_t len = 0;
1292 uint8_t buff_size, idx, count = 0;
1293 struct chan_list *chan_lst;
1294 #define MAX_SCAN_FREQ_TO_PRINT 25
1295
1296 scm_nofl_debug("Scan start: scan id %d vdev %d Dwell time: act %d pass %d act_2G %d act_6G %d pass_6G %d, probe time %d n_probes %d flags %x ext_flag %x events %x policy %d is_wb: %d pri %d",
1297 req->scan_id, req->vdev_id, req->dwell_time_active,
1298 req->dwell_time_passive, req->dwell_time_active_2g,
1299 req->dwell_time_active_6g, req->dwell_time_passive_6g,
1300 req->repeat_probe_time, req->n_probes, req->scan_flags,
1301 req->scan_ctrl_flags_ext, req->scan_events,
1302 req->scan_policy_type, req->scan_f_wide_band,
1303 req->scan_priority);
1304 scm_nofl_debug("Scan Type %d rest time: min %d max %d probe spacing %d idle %d probe delay %d scan offset %d burst duration %d adaptive dwell mode %d",
1305 req->scan_type, req->min_rest_time, req->max_rest_time,
1306 req->probe_spacing_time, req->idle_time,
1307 req->probe_delay, req->scan_offset_time,
1308 req->burst_duration, req->adaptive_dwell_time_mode);
1309
1310 for (idx = 0; idx < req->num_ssids; idx++)
1311 scm_nofl_debug("SSID[%d]: " QDF_SSID_FMT, idx,
1312 QDF_SSID_REF(req->ssid[idx].length,
1313 req->ssid[idx].ssid));
1314
1315 chan_lst = &req->chan_list;
1316
1317 if (!chan_lst->num_chan)
1318 return;
1319
1320 /*
1321 * Buffer of (num channel * buff_size) + 1 to consider the 4 char freq,
1322 * 6 char flags and 1 space after it for each channel and 1 to end the
1323 * string with NULL.
1324 * In case of wide band scan extra 4 char for phymode.
1325 */
1326 if (req->scan_f_wide_band)
1327 buff_size = 15;
1328 else
1329 buff_size = 11;
1330
1331 buff_len = (QDF_MIN(MAX_SCAN_FREQ_TO_PRINT,
1332 chan_lst->num_chan) * buff_size) + 1;
1333
1334 chan_buff = qdf_mem_malloc(buff_len);
1335 if (!chan_buff)
1336 return;
1337
1338 scm_nofl_debug("Total freq %d", chan_lst->num_chan);
1339 for (idx = 0; idx < chan_lst->num_chan; idx++) {
1340 if (req->scan_f_wide_band)
1341 len += qdf_scnprintf(chan_buff + len, buff_len - len,
1342 "%d(0x%02x)[%d] ",
1343 chan_lst->chan[idx].freq,
1344 chan_lst->chan[idx].flags,
1345 chan_lst->chan[idx].phymode);
1346 else
1347 len += qdf_scnprintf(chan_buff + len, buff_len - len,
1348 "%d(0x%02x) ",
1349 chan_lst->chan[idx].freq,
1350 chan_lst->chan[idx].flags);
1351
1352 count++;
1353 if (count >= MAX_SCAN_FREQ_TO_PRINT) {
1354 /* Print the MAX_SCAN_FREQ_TO_PRINT channels */
1355 scm_nofl_debug("Freq list: %s", chan_buff);
1356 len = 0;
1357 count = 0;
1358 }
1359 }
1360 if (len)
1361 scm_nofl_debug("Freq list: %s", chan_buff);
1362
1363 qdf_mem_free(chan_buff);
1364 }
1365 QDF_STATUS
scm_scan_start_req(struct scheduler_msg * msg)1366 scm_scan_start_req(struct scheduler_msg *msg)
1367 {
1368 struct wlan_serialization_command cmd = {0, };
1369 enum wlan_serialization_status ser_cmd_status;
1370 struct scan_start_request *req = NULL;
1371 struct wlan_scan_obj *scan_obj;
1372 QDF_STATUS status = QDF_STATUS_SUCCESS;
1373
1374
1375 if (!msg) {
1376 scm_err("msg received is NULL");
1377 QDF_ASSERT(0);
1378 return QDF_STATUS_E_NULL_VALUE;
1379 }
1380 if (!msg->bodyptr) {
1381 scm_err("bodyptr is NULL");
1382 QDF_ASSERT(0);
1383 return QDF_STATUS_E_NULL_VALUE;
1384 }
1385
1386 req = msg->bodyptr;
1387
1388 if (!scm_is_scan_allowed(req->vdev)) {
1389 scm_err("scan disabled, rejecting the scan req");
1390 status = QDF_STATUS_E_NULL_VALUE;
1391 goto err;
1392 }
1393
1394 scan_obj = wlan_vdev_get_scan_obj(req->vdev);
1395 if (!scan_obj) {
1396 scm_debug("Couldn't find scan object");
1397 status = QDF_STATUS_E_NULL_VALUE;
1398 goto err;
1399 }
1400
1401 scm_scan_req_update_params(req->vdev, req, scan_obj);
1402 scm_print_scan_req_info(&req->scan_req);
1403
1404 if (!req->scan_req.chan_list.num_chan) {
1405 scm_info("Reject 0 channel Scan");
1406 status = QDF_STATUS_E_NULL_VALUE;
1407 goto err;
1408 }
1409
1410 cmd.cmd_type = WLAN_SER_CMD_SCAN;
1411 cmd.cmd_id = req->scan_req.scan_id;
1412 cmd.cmd_cb = scm_scan_serialize_callback;
1413 cmd.umac_cmd = req;
1414 cmd.source = WLAN_UMAC_COMP_SCAN;
1415 cmd.is_high_priority = false;
1416 cmd.cmd_timeout_duration = req->scan_req.max_scan_time +
1417 SCAN_TIMEOUT_GRACE_PERIOD;
1418 cmd.vdev = req->vdev;
1419
1420 if (scan_obj->disable_timeout)
1421 cmd.cmd_timeout_duration = 0;
1422
1423 qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SERIALIZATION,
1424 WLAN_SER_CMD_SCAN, req->vdev->vdev_objmgr.vdev_id,
1425 req->scan_req.scan_id);
1426
1427 ser_cmd_status = wlan_serialization_request(&cmd);
1428 switch (ser_cmd_status) {
1429 case WLAN_SER_CMD_PENDING:
1430 /* command moved to pending list.Do nothing */
1431 break;
1432 case WLAN_SER_CMD_ACTIVE:
1433 /* command moved to active list. Do nothing */
1434 break;
1435 default:
1436 scm_debug("ser cmd status %d", ser_cmd_status);
1437 goto err;
1438 }
1439
1440 return status;
1441 err:
1442 /*
1443 * notify registered scan event handlers
1444 * about internal error
1445 */
1446 scm_post_internal_scan_complete_event(req,
1447 SCAN_REASON_INTERNAL_FAILURE);
1448 /*
1449 * cmd can't be serviced.
1450 * release vdev reference and free scan_start_request memory
1451 */
1452 if (req) {
1453 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
1454 scm_scan_free_scan_request_mem(req);
1455 }
1456
1457 return status;
1458 }
1459
1460 static inline enum wlan_serialization_cancel_type
get_serialization_cancel_type(enum scan_cancel_req_type type)1461 get_serialization_cancel_type(enum scan_cancel_req_type type)
1462 {
1463 enum wlan_serialization_cancel_type serialization_type;
1464
1465 switch (type) {
1466 case WLAN_SCAN_CANCEL_SINGLE:
1467 serialization_type = WLAN_SER_CANCEL_SINGLE_SCAN;
1468 break;
1469 case WLAN_SCAN_CANCEL_VDEV_ALL:
1470 serialization_type = WLAN_SER_CANCEL_VDEV_SCANS;
1471 break;
1472 case WLAN_SCAN_CANCEL_PDEV_ALL:
1473 serialization_type = WLAN_SER_CANCEL_PDEV_SCANS;
1474 break;
1475 case WLAN_SCAN_CANCEL_HOST_VDEV_ALL:
1476 serialization_type = WLAN_SER_CANCEL_VDEV_HOST_SCANS;
1477 break;
1478 default:
1479 QDF_ASSERT(0);
1480 scm_warn("invalid scan_cancel_req_type: %d", type);
1481 serialization_type = WLAN_SER_CANCEL_PDEV_SCANS;
1482 break;
1483 }
1484
1485 return serialization_type;
1486 }
1487
1488 QDF_STATUS
scm_scan_cancel_req(struct scheduler_msg * msg)1489 scm_scan_cancel_req(struct scheduler_msg *msg)
1490 {
1491 struct wlan_serialization_queued_cmd_info cmd = {0,};
1492 struct wlan_serialization_command ser_cmd = {0,};
1493 enum wlan_serialization_cmd_status ser_cmd_status;
1494 struct scan_cancel_request *req;
1495 QDF_STATUS status = QDF_STATUS_SUCCESS;
1496
1497 if (!msg) {
1498 scm_err("msg received is NULL");
1499 QDF_ASSERT(0);
1500 return QDF_STATUS_E_NULL_VALUE;
1501 }
1502 if (!msg->bodyptr) {
1503 scm_err("Bodyptr is NULL");
1504 QDF_ASSERT(0);
1505 return QDF_STATUS_E_NULL_VALUE;
1506 }
1507
1508 req = msg->bodyptr;
1509 /*
1510 * If requester wants to wait for target scan cancel event
1511 * instead of internally generated cancel event, just check
1512 * which queue this scan request belongs to and send scan
1513 * cancel request to FW accordingly.
1514 * Else generate internal scan cancel event and notify
1515 * handlers and free scan request resources.
1516 */
1517 if (req->wait_tgt_cancel &&
1518 (req->cancel_req.req_type == WLAN_SCAN_CANCEL_SINGLE)) {
1519 ser_cmd.cmd_type = WLAN_SER_CMD_SCAN;
1520 ser_cmd.cmd_id = req->cancel_req.scan_id;
1521 ser_cmd.cmd_cb = NULL;
1522 ser_cmd.umac_cmd = NULL;
1523 ser_cmd.source = WLAN_UMAC_COMP_SCAN;
1524 ser_cmd.is_high_priority = false;
1525 ser_cmd.vdev = req->vdev;
1526 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, &ser_cmd))
1527 ser_cmd_status = WLAN_SER_CMD_IN_ACTIVE_LIST;
1528 else if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, &ser_cmd))
1529 ser_cmd_status = WLAN_SER_CMD_IN_PENDING_LIST;
1530 else
1531 ser_cmd_status = WLAN_SER_CMD_NOT_FOUND;
1532 } else {
1533 cmd.requestor = 0;
1534 cmd.cmd_type = WLAN_SER_CMD_SCAN;
1535 cmd.cmd_id = req->cancel_req.scan_id;
1536 cmd.vdev = req->vdev;
1537 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE |
1538 WLAN_SERIALIZATION_PENDING_QUEUE;
1539 cmd.req_type = get_serialization_cancel_type(req->cancel_req.req_type);
1540
1541 ser_cmd_status = wlan_serialization_cancel_request(&cmd);
1542 }
1543
1544 scm_debug("status: %d, reqid: %d, scanid: %d, vdevid: %d, type: %d",
1545 ser_cmd_status, req->cancel_req.requester,
1546 req->cancel_req.scan_id, req->cancel_req.vdev_id,
1547 req->cancel_req.req_type);
1548
1549 switch (ser_cmd_status) {
1550 case WLAN_SER_CMD_IN_PENDING_LIST:
1551 /* do nothing */
1552 break;
1553 case WLAN_SER_CMD_IN_ACTIVE_LIST:
1554 case WLAN_SER_CMDS_IN_ALL_LISTS:
1555 /* send wmi scan cancel to fw */
1556 status = tgt_scan_cancel(req);
1557 break;
1558 case WLAN_SER_CMD_NOT_FOUND:
1559 /* do nothing */
1560 break;
1561 default:
1562 QDF_ASSERT(0);
1563 status = QDF_STATUS_E_INVAL;
1564 break;
1565 }
1566
1567 /* Release vdev reference and scan cancel request
1568 * processing is complete
1569 */
1570 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
1571 /* Free cancel request memory */
1572 qdf_mem_free(req);
1573
1574 return status;
1575 }
1576
1577 #ifdef FEATURE_WLAN_SCAN_PNO
1578 static QDF_STATUS
scm_pno_event_handler(struct wlan_objmgr_vdev * vdev,struct scan_event * event)1579 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
1580 struct scan_event *event)
1581 {
1582 struct scan_vdev_obj *scan_vdev_obj;
1583 struct wlan_scan_obj *scan_psoc_obj;
1584 scan_event_handler pno_cb;
1585 void *cb_arg;
1586
1587 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
1588 scan_psoc_obj = wlan_vdev_get_scan_obj(vdev);
1589 if (!scan_vdev_obj || !scan_psoc_obj) {
1590 scm_err("null scan_vdev_obj %pK scan_obj %pK",
1591 scan_vdev_obj, scan_psoc_obj);
1592 return QDF_STATUS_E_INVAL;
1593 }
1594
1595 switch (event->type) {
1596 case SCAN_EVENT_TYPE_NLO_COMPLETE:
1597 if (!scan_vdev_obj->pno_match_evt_received)
1598 return QDF_STATUS_SUCCESS;
1599 qdf_wake_lock_release(&scan_psoc_obj->pno_cfg.pno_wake_lock,
1600 WIFI_POWER_EVENT_WAKELOCK_PNO);
1601 qdf_wake_lock_timeout_acquire(
1602 &scan_psoc_obj->pno_cfg.pno_wake_lock,
1603 SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT);
1604 qdf_runtime_pm_allow_suspend(
1605 &scan_psoc_obj->pno_cfg.pno_runtime_pm_lock);
1606 scan_vdev_obj->pno_match_evt_received = false;
1607 break;
1608 case SCAN_EVENT_TYPE_NLO_MATCH:
1609 scan_vdev_obj->pno_match_evt_received = true;
1610 qdf_wake_lock_timeout_acquire(
1611 &scan_psoc_obj->pno_cfg.pno_wake_lock,
1612 SCAN_PNO_MATCH_WAKE_LOCK_TIMEOUT);
1613 qdf_runtime_pm_prevent_suspend(
1614 &scan_psoc_obj->pno_cfg.pno_runtime_pm_lock);
1615 return QDF_STATUS_SUCCESS;
1616 default:
1617 return QDF_STATUS_E_INVAL;
1618 }
1619 qdf_spin_lock_bh(&scan_psoc_obj->lock);
1620 pno_cb = scan_psoc_obj->pno_cfg.pno_cb.func;
1621 cb_arg = scan_psoc_obj->pno_cfg.pno_cb.arg;
1622 qdf_spin_unlock_bh(&scan_psoc_obj->lock);
1623
1624 if (pno_cb)
1625 pno_cb(vdev, event, cb_arg);
1626
1627 return QDF_STATUS_SUCCESS;
1628 }
1629 #else
1630
1631 static QDF_STATUS
scm_pno_event_handler(struct wlan_objmgr_vdev * vdev,struct scan_event * event)1632 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
1633 struct scan_event *event)
1634 {
1635 return QDF_STATUS_SUCCESS;
1636 }
1637 #endif
1638
1639 /**
1640 * scm_scan_update_scan_event() - update scan event
1641 * @scan: scan object
1642 * @event: scan event
1643 * @scan_start_req: scan_start_req used for triggering scan
1644 *
1645 * update scan params in scan event
1646 *
1647 * Return: QDF_STATUS
1648 */
1649 static QDF_STATUS
scm_scan_update_scan_event(struct wlan_scan_obj * scan,struct scan_event * event,struct scan_start_request * scan_start_req)1650 scm_scan_update_scan_event(struct wlan_scan_obj *scan,
1651 struct scan_event *event,
1652 struct scan_start_request *scan_start_req)
1653 {
1654 if (!event)
1655 return QDF_STATUS_E_NULL_VALUE;
1656
1657 if (!scan || !scan_start_req) {
1658 event->scan_start_req = NULL;
1659 return QDF_STATUS_E_NULL_VALUE;
1660 }
1661 /* copy scan start request to pass back buffer */
1662 qdf_mem_copy(&scan->scan_start_request_buff, scan_start_req,
1663 sizeof(struct scan_start_request));
1664 /* reset all pointers */
1665 scan->scan_start_request_buff.scan_req.extraie.ptr = NULL;
1666 scan->scan_start_request_buff.scan_req.extraie.len = 0;
1667 scan->scan_start_request_buff.scan_req.htcap.ptr = NULL;
1668 scan->scan_start_request_buff.scan_req.htcap.len = 0;
1669 scan->scan_start_request_buff.scan_req.vhtcap.ptr = NULL;
1670 scan->scan_start_request_buff.scan_req.vhtcap.len = 0;
1671
1672 event->scan_start_req = &scan->scan_start_request_buff;
1673
1674 return QDF_STATUS_SUCCESS;
1675 }
1676
1677 static
scm_update_last_scan_time_per_channel(struct wlan_objmgr_vdev * vdev,uint32_t chan_freq,uint32_t time)1678 void scm_update_last_scan_time_per_channel(struct wlan_objmgr_vdev *vdev,
1679 uint32_t chan_freq, uint32_t time)
1680 {
1681 struct wlan_scan_obj *scan_obj;
1682 struct chan_list_scan_info *chan_info;
1683 bool chan_found = false;
1684 uint8_t pdev_id;
1685 int i;
1686
1687 scan_obj = wlan_vdev_get_scan_obj(vdev);
1688 if (!scan_obj)
1689 return;
1690
1691 pdev_id = wlan_scan_vdev_get_pdev_id(vdev);
1692 chan_info = &scan_obj->pdev_info[pdev_id].chan_scan_info;
1693
1694 for (i = 0; i < chan_info->num_chan ; i++) {
1695 if (chan_info->ch_scan_info[i].freq == chan_freq) {
1696 chan_info->ch_scan_info[i].last_scan_time = time;
1697 chan_found = true;
1698 break;
1699 }
1700 }
1701
1702 if (!chan_found) {
1703 chan_info->ch_scan_info[chan_info->num_chan].freq = chan_freq;
1704 chan_info->ch_scan_info[chan_info->num_chan].last_scan_time =
1705 time;
1706 chan_info->num_chan++;
1707 }
1708 }
1709
1710 QDF_STATUS
scm_scan_event_handler(struct scheduler_msg * msg)1711 scm_scan_event_handler(struct scheduler_msg *msg)
1712 {
1713 struct wlan_objmgr_vdev *vdev;
1714 struct scan_event *event;
1715 struct scan_event_info *event_info;
1716 struct wlan_serialization_command cmd = {0,};
1717 struct wlan_serialization_command *queued_cmd;
1718 struct scan_start_request *scan_start_req;
1719 struct wlan_scan_obj *scan;
1720
1721 if (!msg) {
1722 scm_err("NULL msg received ");
1723 QDF_ASSERT(0);
1724 return QDF_STATUS_E_NULL_VALUE;
1725 }
1726 if (!msg->bodyptr) {
1727 scm_err("NULL scan event received");
1728 QDF_ASSERT(0);
1729 return QDF_STATUS_E_NULL_VALUE;
1730 }
1731
1732 event_info = msg->bodyptr;
1733 vdev = event_info->vdev;
1734 event = &(event_info->event);
1735
1736 scan = wlan_vdev_get_scan_obj(vdev);
1737
1738 scm_duration_init(scan);
1739
1740 scm_event_duration_start(scan);
1741
1742 scm_debug("vdevid:%d, type:%d, reason:%d, freq:%d, reqstr:%d,"
1743 "scanid:%d (0x%x), timestamp:%u", event->vdev_id,
1744 event->type, event->reason, event->chan_freq,
1745 event->requester, event->scan_id, event->scan_id,
1746 event->timestamp);
1747
1748 if (event->type == SCAN_EVENT_TYPE_FOREIGN_CHANNEL)
1749 scm_update_last_scan_time_per_channel(
1750 vdev, event->chan_freq, qdf_get_time_of_the_day_ms());
1751
1752 /*
1753 * NLO requests are never queued, so post NLO events
1754 * without checking for their presence in active queue.
1755 */
1756 switch (event->type) {
1757 case SCAN_EVENT_TYPE_NLO_COMPLETE:
1758 case SCAN_EVENT_TYPE_NLO_MATCH:
1759 scm_pno_event_handler(vdev, event);
1760 goto exit;
1761 default:
1762 break;
1763 }
1764
1765 cmd.cmd_type = WLAN_SER_CMD_SCAN;
1766 cmd.cmd_id = event->scan_id;
1767 cmd.cmd_cb = NULL;
1768 cmd.umac_cmd = NULL;
1769 cmd.source = WLAN_UMAC_COMP_SCAN;
1770 cmd.is_high_priority = false;
1771 cmd.vdev = vdev;
1772 if (!wlan_serialization_is_cmd_present_in_active_queue(NULL, &cmd)) {
1773 /*
1774 * We received scan event for an already completed/cancelled
1775 * scan request. Drop this event.
1776 */
1777 scm_debug("Received scan event while request not in active queue");
1778 goto exit;
1779 }
1780
1781 /* Fill scan_start_request used to trigger this scan */
1782 queued_cmd = wlan_serialization_get_scan_cmd_using_scan_id(
1783 wlan_vdev_get_psoc(vdev), wlan_vdev_get_id(vdev),
1784 event->scan_id, true);
1785
1786 if (!queued_cmd) {
1787 scm_err("NULL queued_cmd");
1788 goto exit;
1789 }
1790 if (!queued_cmd->umac_cmd) {
1791 scm_err("NULL umac_cmd");
1792 goto exit;
1793 }
1794 scan_start_req = queued_cmd->umac_cmd;
1795
1796 if (scan_start_req->scan_req.scan_req_id != event->requester) {
1797 scm_err("req ID mismatch, scan_req_id:%d, event_req_id:%d",
1798 scan_start_req->scan_req.scan_req_id, event->requester);
1799 goto exit;
1800 }
1801
1802 if (scan)
1803 scm_scan_update_scan_event(scan, event, scan_start_req);
1804
1805 switch (event->type) {
1806 case SCAN_EVENT_TYPE_COMPLETED:
1807 if (event->reason == SCAN_REASON_COMPLETED)
1808 scm_11d_decide_country_code(vdev);
1809 /* release the command */
1810 fallthrough;
1811 case SCAN_EVENT_TYPE_START_FAILED:
1812 case SCAN_EVENT_TYPE_DEQUEUED:
1813 scm_release_serialization_command(vdev, event->scan_id);
1814 break;
1815 default:
1816 break;
1817 }
1818
1819 scm_to_post_scan_duration_set(scan);
1820 /* Notify all interested parties */
1821 scm_scan_post_event(vdev, event);
1822
1823 exit:
1824 /* free event info memory */
1825 qdf_mem_free(event_info);
1826
1827 scm_event_duration_end(scan);
1828
1829 wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID);
1830
1831 return QDF_STATUS_SUCCESS;
1832 }
1833
scm_scan_event_flush_callback(struct scheduler_msg * msg)1834 QDF_STATUS scm_scan_event_flush_callback(struct scheduler_msg *msg)
1835 {
1836 struct wlan_objmgr_vdev *vdev;
1837 struct scan_event_info *event_info;
1838 struct scan_event *event;
1839
1840 if (!msg || !msg->bodyptr) {
1841 scm_err("msg or msg->bodyptr is NULL");
1842 return QDF_STATUS_E_NULL_VALUE;
1843 }
1844
1845 event_info = msg->bodyptr;
1846 vdev = event_info->vdev;
1847 event = &event_info->event;
1848
1849 scm_debug("Flush scan event vdev %d type %d reason %d freq: %d req %d scanid %d",
1850 event->vdev_id, event->type, event->reason, event->chan_freq,
1851 event->requester, event->scan_id);
1852
1853 /* free event info memory */
1854 qdf_mem_free(event_info);
1855 wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID);
1856
1857 return QDF_STATUS_SUCCESS;
1858 }
1859
scm_bcn_probe_flush_callback(struct scheduler_msg * msg)1860 QDF_STATUS scm_bcn_probe_flush_callback(struct scheduler_msg *msg)
1861 {
1862 struct scan_bcn_probe_event *bcn;
1863
1864 bcn = msg->bodyptr;
1865
1866 if (!bcn) {
1867 scm_err("bcn is NULL");
1868 return QDF_STATUS_E_NULL_VALUE;
1869 }
1870 if (bcn->psoc)
1871 wlan_objmgr_psoc_release_ref(bcn->psoc, WLAN_SCAN_ID);
1872 if (bcn->rx_data)
1873 qdf_mem_free(bcn->rx_data);
1874 if (bcn->buf)
1875 qdf_nbuf_free(bcn->buf);
1876 qdf_mem_free(bcn);
1877
1878 return QDF_STATUS_SUCCESS;
1879 }
1880
scm_scan_start_flush_callback(struct scheduler_msg * msg)1881 QDF_STATUS scm_scan_start_flush_callback(struct scheduler_msg *msg)
1882 {
1883 struct scan_start_request *req;
1884
1885 if (!msg || !msg->bodyptr) {
1886 scm_err("msg or msg->bodyptr is NULL");
1887 return QDF_STATUS_E_NULL_VALUE;
1888 }
1889
1890 req = msg->bodyptr;
1891 scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED);
1892 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
1893 scm_scan_free_scan_request_mem(req);
1894
1895 return QDF_STATUS_SUCCESS;
1896 }
1897
scm_scan_cancel_flush_callback(struct scheduler_msg * msg)1898 QDF_STATUS scm_scan_cancel_flush_callback(struct scheduler_msg *msg)
1899 {
1900 struct scan_cancel_request *req;
1901
1902 if (!msg || !msg->bodyptr) {
1903 scm_err("msg or msg->bodyptr is NULL");
1904 return QDF_STATUS_E_NULL_VALUE;
1905 }
1906
1907 req = msg->bodyptr;
1908 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
1909 /* Free cancel request memory */
1910 qdf_mem_free(req);
1911
1912 return QDF_STATUS_SUCCESS;
1913 }
1914
scm_disable_obss_pdev_scan(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev)1915 void scm_disable_obss_pdev_scan(struct wlan_objmgr_psoc *psoc,
1916 struct wlan_objmgr_pdev *pdev)
1917 {
1918 struct wlan_objmgr_vdev *vdev;
1919 struct wlan_scan_obj *scan_obj;
1920 struct scan_vdev_obj *scan_vdev_obj;
1921 QDF_STATUS status;
1922 struct wlan_objmgr_pdev_objmgr *pdev_objmgr;
1923 qdf_list_t *vdev_list;
1924 uint16_t index = 0;
1925
1926 scan_obj = wlan_psoc_get_scan_obj(psoc);
1927 if (!scan_obj) {
1928 scm_err("scan object null");
1929 return;
1930 }
1931
1932 if (scan_obj->obss_scan_offload) {
1933 pdev_objmgr = &pdev->pdev_objmgr;
1934
1935 wlan_pdev_obj_lock(pdev);
1936 vdev_list = &pdev_objmgr->wlan_vdev_list;
1937 /* Get first vdev */
1938 vdev = wlan_pdev_vdev_list_peek_head(vdev_list);
1939
1940 while (vdev) {
1941 scm_debug("wlan_vdev_list[%d]: %pK", index, vdev);
1942
1943 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
1944 if (!scan_vdev_obj) {
1945 scm_err("null scan_vdev_obj");
1946 goto next;
1947 }
1948
1949 status = tgt_scan_obss_disable(vdev);
1950 if (QDF_IS_STATUS_ERROR(status))
1951 scm_err("disable obss scan failed");
1952 next:
1953 index++;
1954 /* get next vdev */
1955 vdev = wlan_vdev_get_next_vdev_of_pdev(vdev_list,
1956 vdev);
1957 }
1958 wlan_pdev_obj_unlock(pdev);
1959 }
1960 }
1961