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