xref: /wlan-driver/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager.c (revision 5113495b16420b49004c444715d2daae2066e7dc) !
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