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