xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c (revision d2cd9eab9b38f8dceb85c744ffada78cad4f5940)
1 /*
2  * Copyright (c) 2017 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 north bound interface definitions
21  */
22 
23 #include <scheduler_api.h>
24 #include <wlan_scan_ucfg_api.h>
25 #include <wlan_objmgr_global_obj.h>
26 #include <wlan_objmgr_cmn.h>
27 #include <wlan_serialization_api.h>
28 #include <wlan_scan_tgt_api.h>
29 #include "../../core/src/wlan_scan_main.h"
30 #include "../../core/src/wlan_scan_manager.h"
31 #include "../../core/src/wlan_scan_cache_db.h"
32 #ifdef WLAN_PMO_ENABLE
33 #include <wlan_pmo_obj_mgmt_api.h>
34 #endif
35 
36 QDF_STATUS ucfg_scan_register_bcn_cb(struct wlan_objmgr_psoc *psoc,
37 	update_beacon_cb cb, enum scan_cb_type type)
38 {
39 	return scm_scan_register_bcn_cb(psoc, cb, type);
40 }
41 
42 qdf_list_t *ucfg_scan_get_result(struct wlan_objmgr_pdev *pdev,
43 	struct scan_filter *filter)
44 {
45 	return scm_get_scan_result(pdev, filter);
46 }
47 
48 QDF_STATUS ucfg_scan_db_iterate(struct wlan_objmgr_pdev *pdev,
49 	scan_iterator_func func, void *arg)
50 {
51 	return scm_iterate_scan_db(pdev, func, arg);
52 }
53 
54 QDF_STATUS ucfg_scan_purge_results(qdf_list_t *scan_list)
55 {
56 	return scm_purge_scan_results(scan_list);
57 }
58 
59 QDF_STATUS ucfg_scan_flush_results(struct wlan_objmgr_pdev *pdev,
60 	struct scan_filter *filter)
61 {
62 	return scm_flush_results(pdev, filter);
63 }
64 
65 void ucfg_scan_filter_valid_channel(struct wlan_objmgr_pdev *pdev,
66 	uint8_t *chan_list, uint32_t num_chan)
67 {
68 	scm_filter_valid_channel(pdev, chan_list, num_chan);
69 }
70 
71 QDF_STATUS ucfg_scan_init(void)
72 {
73 	QDF_STATUS status;
74 
75 	status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_SCAN,
76 		wlan_scan_psoc_created_notification, NULL);
77 	if (QDF_IS_STATUS_ERROR(status)) {
78 		scm_err("Failed to register psoc create handler");
79 		goto fail_create_psoc;
80 	}
81 
82 	status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN,
83 		wlan_scan_psoc_destroyed_notification, NULL);
84 	if (QDF_IS_STATUS_ERROR(status)) {
85 		scm_err("Failed to create psoc delete handler");
86 		goto fail_psoc_destroy;
87 	}
88 	scm_info("scan psoc create and delete handler registered with objmgr");
89 
90 	status = wlan_objmgr_register_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
91 		wlan_scan_vdev_created_notification, NULL);
92 	if (QDF_IS_STATUS_ERROR(status)) {
93 		scm_err("Failed to register vdev create handler");
94 		goto fail_pdev_create;
95 	}
96 
97 	status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_SCAN,
98 		wlan_scan_vdev_destroyed_notification, NULL);
99 	if (QDF_IS_STATUS_SUCCESS(status)) {
100 		scm_info("scan vdev create and delete handler registered with objmgr");
101 		return QDF_STATUS_SUCCESS;
102 	}
103 
104 	scm_err("Failed to destroy vdev delete handler");
105 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
106 				wlan_scan_vdev_created_notification, NULL);
107 fail_pdev_create:
108 	wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN,
109 				wlan_scan_psoc_destroyed_notification, NULL);
110 fail_psoc_destroy:
111 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN,
112 			wlan_scan_psoc_created_notification, NULL);
113 fail_create_psoc:
114 	return status;
115 }
116 
117 QDF_STATUS ucfg_scan_deinit(void)
118 {
119 	QDF_STATUS status;
120 
121 	status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN,
122 		wlan_scan_psoc_created_notification, NULL);
123 	if (status != QDF_STATUS_SUCCESS)
124 		scm_err("Failed to unregister psoc create handler");
125 
126 	status = wlan_objmgr_unregister_psoc_destroy_handler(
127 				WLAN_UMAC_COMP_SCAN,
128 				wlan_scan_psoc_destroyed_notification, NULL);
129 	if (status != QDF_STATUS_SUCCESS)
130 		scm_err("Failed to unregister psoc delete handler");
131 
132 	status = wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
133 		wlan_scan_vdev_created_notification, NULL);
134 	if (status != QDF_STATUS_SUCCESS)
135 		scm_err("Failed to unregister vdev create handler");
136 
137 	status = wlan_objmgr_unregister_vdev_destroy_handler(
138 			WLAN_UMAC_COMP_SCAN,
139 			wlan_scan_vdev_destroyed_notification, NULL);
140 	if (status != QDF_STATUS_SUCCESS)
141 		scm_err("Failed to unregister vdev delete handler");
142 
143 	return status;
144 }
145 
146 #ifdef FEATURE_WLAN_SCAN_PNO
147 
148 QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev,
149 	struct pno_scan_req_params *req)
150 {
151 	struct scan_vdev_obj *scan_vdev_obj;
152 	QDF_STATUS status;
153 
154 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
155 	if (!scan_vdev_obj) {
156 		scm_err("null scan_vdev_obj");
157 		return QDF_STATUS_E_INVAL;
158 	}
159 	if (scan_vdev_obj->pno_in_progress) {
160 		scm_err("pno already in progress");
161 		return QDF_STATUS_E_ALREADY;
162 	}
163 
164 	status = tgt_scan_pno_start(vdev, req);
165 	if (QDF_IS_STATUS_ERROR(status))
166 		scm_err("pno start failed");
167 	else
168 		scan_vdev_obj->pno_in_progress = true;
169 
170 	return status;
171 }
172 
173 QDF_STATUS ucfg_scan_pno_stop(struct wlan_objmgr_vdev *vdev)
174 {
175 	struct scan_vdev_obj *scan_vdev_obj;
176 	QDF_STATUS status;
177 
178 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
179 	if (!scan_vdev_obj) {
180 		scm_err("null scan_vdev_obj");
181 		return QDF_STATUS_E_INVAL;
182 	}
183 	if (!scan_vdev_obj->pno_in_progress) {
184 		scm_err("pno already stopped");
185 		return QDF_STATUS_E_ALREADY;
186 	}
187 
188 	status = tgt_scan_pno_stop(vdev, wlan_vdev_get_id(vdev));
189 	if (QDF_IS_STATUS_ERROR(status))
190 		scm_err("pno start failed");
191 	else
192 		scan_vdev_obj->pno_in_progress = false;
193 
194 	return status;
195 }
196 
197 bool ucfg_scan_get_pno_in_progress(struct wlan_objmgr_vdev *vdev)
198 {
199 	struct scan_vdev_obj *scan_vdev_obj;
200 
201 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
202 	if (!scan_vdev_obj) {
203 		scm_err("null scan_vdev_obj");
204 		return false;
205 	}
206 
207 	return scan_vdev_obj->pno_in_progress;
208 }
209 
210 bool ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev)
211 {
212 	struct scan_vdev_obj *scan_vdev_obj;
213 
214 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
215 	if (!scan_vdev_obj) {
216 		scm_err("null scan_vdev_obj");
217 		return false;
218 	}
219 
220 	return scan_vdev_obj->pno_match_evt_received;
221 }
222 
223 static QDF_STATUS
224 wlan_pno_global_init(struct pno_def_config *pno_def)
225 {
226 	qdf_wake_lock_create(&pno_def->pno_wake_lock, "wlan_pno_wl");
227 	pno_def->channel_prediction = SCAN_PNO_CHANNEL_PREDICTION;
228 	pno_def->top_k_num_of_channels = SCAN_TOP_K_NUM_OF_CHANNELS;
229 	pno_def->stationary_thresh = SCAN_STATIONARY_THRESHOLD;
230 	pno_def->channel_prediction_full_scan =
231 			SCAN_CHANNEL_PREDICTION_FULL_SCAN_MS;
232 	pno_def->adaptive_dwell_mode = SCAN_ADAPTIVE_PNOSCAN_DWELL_MODE;
233 
234 	return QDF_STATUS_SUCCESS;
235 }
236 
237 static QDF_STATUS
238 wlan_pno_global_deinit(struct pno_def_config *pno_def)
239 {
240 	qdf_wake_lock_destroy(&pno_def->pno_wake_lock);
241 
242 	return QDF_STATUS_SUCCESS;
243 }
244 
245 QDF_STATUS
246 ucfg_scan_get_pno_def_params(struct wlan_objmgr_vdev *vdev,
247 	struct pno_scan_req_params *req)
248 {
249 	struct scan_default_params *scan_def;
250 	struct wlan_scan_obj *scan = wlan_vdev_get_scan_obj(vdev);
251 	struct pno_def_config *pno_def;
252 
253 	if (!vdev | !req | !scan) {
254 		scm_err("vdev: 0x%p, req: 0x%p scan_obj: 0x%p",
255 			vdev, req, scan);
256 		return QDF_STATUS_E_INVAL;
257 	}
258 
259 	scan_def = wlan_vdev_get_def_scan_params(vdev);
260 	pno_def = &scan->pno_cfg;
261 
262 	req->active_dwell_time = scan_def->active_dwell;
263 	req->passive_dwell_time = scan_def->passive_dwell;
264 
265 	req->adaptive_dwell_mode = pno_def->adaptive_dwell_mode;
266 
267 	req->pno_channel_prediction = pno_def->adaptive_dwell_mode;
268 	req->top_k_num_of_channels = pno_def->top_k_num_of_channels;
269 	req->stationary_thresh = pno_def->stationary_thresh;
270 	req->channel_prediction_full_scan =
271 			pno_def->channel_prediction_full_scan;
272 
273 	return QDF_STATUS_SUCCESS;
274 }
275 
276 static QDF_STATUS ucfg_scan_update_pno_config(struct pno_def_config *pno,
277 	struct pno_user_cfg *pno_cfg)
278 {
279 	pno->channel_prediction = pno_cfg->channel_prediction;
280 	pno->top_k_num_of_channels = pno_cfg->top_k_num_of_channels;
281 	pno->stationary_thresh = pno_cfg->stationary_thresh;
282 	pno->adaptive_dwell_mode = pno_cfg->adaptive_dwell_mode;
283 	pno->channel_prediction_full_scan =
284 		pno_cfg->channel_prediction_full_scan;
285 
286 	return QDF_STATUS_SUCCESS;
287 }
288 
289 QDF_STATUS
290 ucfg_scan_register_pno_cb(struct wlan_objmgr_psoc *psoc,
291 	scan_event_handler event_cb, void *arg)
292 {
293 	struct wlan_scan_obj *scan;
294 
295 	if (!psoc) {
296 		scm_err("null psoc");
297 		return QDF_STATUS_E_INVAL;
298 	}
299 	scan = wlan_psoc_get_scan_obj(psoc);
300 	qdf_spin_lock_bh(&scan->lock);
301 	scan->pno_cfg.pno_cb.func = event_cb;
302 	scan->pno_cfg.pno_cb.arg = arg;
303 	qdf_spin_unlock_bh(&scan->lock);
304 	scm_info("event_cb: 0x%p, arg: 0x%p", event_cb, arg);
305 
306 	return QDF_STATUS_SUCCESS;
307 }
308 
309 #else
310 
311 static inline QDF_STATUS
312 wlan_pno_global_init(struct pno_def_config *pno_def)
313 {
314 	return QDF_STATUS_SUCCESS;
315 }
316 static inline QDF_STATUS
317 wlan_pno_global_deinit(struct pno_def_config *pno_def)
318 {
319 	return QDF_STATUS_SUCCESS;
320 }
321 
322 static inline QDF_STATUS
323 ucfg_scan_update_pno_config(struct pno_def_config *pno,
324 	struct pno_user_cfg *pno_cfg)
325 {
326 	return QDF_STATUS_SUCCESS;
327 }
328 
329 #endif
330 
331 
332 QDF_STATUS
333 ucfg_scan_start(struct scan_start_request *req)
334 {
335 	struct scheduler_msg msg = {0};
336 	QDF_STATUS status;
337 
338 	if (!req || !req->vdev) {
339 		scm_err("vdev: %p, req: %p", req->vdev, req);
340 		if (req)
341 			scm_scan_free_scan_request_mem(req);
342 		return QDF_STATUS_E_NULL_VALUE;
343 	}
344 	scm_info("reqid: %d, scanid: %d, vdevid: %d",
345 		req->scan_req.scan_req_id, req->scan_req.scan_id,
346 		req->scan_req.vdev_id);
347 
348 	/* Try to get vdev reference. Return if reference could
349 	 * not be taken. Reference will be released once scan
350 	 * request handling completes along with free of @req.
351 	 */
352 	status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID);
353 	if (QDF_IS_STATUS_ERROR(status)) {
354 		scm_info("unable to get reference");
355 		scm_scan_free_scan_request_mem(req);
356 		return status;
357 	}
358 
359 	msg.bodyptr = req;
360 	msg.callback = scm_scan_start_req;
361 
362 	status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
363 	if (QDF_IS_STATUS_ERROR(status)) {
364 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
365 		scm_err("failed to post to QDF_MODULE_ID_OS_IF");
366 		scm_scan_free_scan_request_mem(req);
367 	}
368 
369 	return status;
370 }
371 
372 QDF_STATUS
373 ucfg_scan_cancel(struct scan_cancel_request *req)
374 {
375 	struct scheduler_msg msg = {0};
376 	QDF_STATUS status;
377 
378 	if (!req || !req->vdev) {
379 		scm_err("vdev: %p, req: %p", req->vdev, req);
380 		if (req)
381 			qdf_mem_free(req);
382 		return QDF_STATUS_E_NULL_VALUE;
383 	}
384 	scm_info("reqid: %d, scanid: %d, vdevid: %d, type: %d",
385 		req->cancel_req.requester, req->cancel_req.scan_id,
386 		req->cancel_req.vdev_id, req->cancel_req.req_type);
387 
388 	/* Get vdev reference unconditionally.
389 	 * Reference will be released once scan cancel is
390 	 * posted to FW.
391 	 */
392 	wlan_objmgr_vdev_get_ref(req->vdev, WLAN_SCAN_ID);
393 
394 	msg.bodyptr = req;
395 	msg.callback = scm_scan_cancel_req;
396 
397 	status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
398 	if (QDF_IS_STATUS_ERROR(status)) {
399 		scm_err("failed to post to QDF_MODULE_ID_OS_IF");
400 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
401 		qdf_mem_free(req);
402 	}
403 
404 	return status;
405 }
406 
407 QDF_STATUS
408 ucfg_scan_cancel_sync(struct scan_cancel_request *req)
409 {
410 	QDF_STATUS status;
411 	bool cancel_vdev = false, cancel_pdev = false;
412 	struct wlan_objmgr_vdev *vdev;
413 	struct wlan_objmgr_pdev *pdev;
414 	uint32_t max_wait_iterations = SCM_CANCEL_SCAN_WAIT_ITERATION;
415 	qdf_event_t cancel_scan_event;
416 
417 	if (!req || !req->vdev) {
418 		scm_err("vdev: %p, req: %p", req->vdev, req);
419 		if (req)
420 			qdf_mem_free(req);
421 		return QDF_STATUS_E_NULL_VALUE;
422 	}
423 
424 	if (req->cancel_req.req_type ==
425 	   WLAN_SCAN_CANCEL_PDEV_ALL)
426 		cancel_pdev = true;
427 	else if (req->cancel_req.req_type ==
428 	   WLAN_SCAN_CANCEL_VDEV_ALL)
429 		cancel_vdev = true;
430 
431 	vdev = req->vdev;
432 	status = ucfg_scan_cancel(req);
433 	if (QDF_IS_STATUS_ERROR(status)) {
434 		scm_err("failed to post to QDF_MODULE_ID_OS_IF");
435 		return status;
436 	}
437 
438 	/*
439 	 * If cancel req is to cancel all scan of pdev or vdev
440 	 * wait untill all scan of pdev or vdev get cancelled
441 	 */
442 	qdf_event_create(&cancel_scan_event);
443 	qdf_event_reset(&cancel_scan_event);
444 
445 	if (cancel_pdev) {
446 		wlan_vdev_obj_lock(vdev);
447 		pdev = wlan_vdev_get_pdev(vdev);
448 		wlan_vdev_obj_unlock(vdev);
449 		while ((ucfg_scan_get_pdev_status(pdev) !=
450 		     SCAN_NOT_IN_PROGRESS) && max_wait_iterations) {
451 			scm_debug("wait for all pdev scan to get complete");
452 				qdf_wait_single_event(&cancel_scan_event,
453 					qdf_system_msecs_to_ticks(
454 					SCM_CANCEL_SCAN_WAIT_TIME));
455 			max_wait_iterations--;
456 		}
457 	} else if (cancel_vdev) {
458 		while ((ucfg_scan_get_vdev_status(vdev) !=
459 		     SCAN_NOT_IN_PROGRESS) && max_wait_iterations) {
460 			scm_debug("wait for all vdev scan to get complete");
461 				qdf_wait_single_event(&cancel_scan_event,
462 					qdf_system_msecs_to_ticks(
463 					SCM_CANCEL_SCAN_WAIT_TIME));
464 			max_wait_iterations--;
465 		}
466 	}
467 
468 	qdf_event_destroy(&cancel_scan_event);
469 
470 	if (!max_wait_iterations) {
471 		scm_err("Failed to wait for scans to get complete");
472 		return QDF_STATUS_E_TIMEOUT;
473 	}
474 
475 	return status;
476 }
477 
478 wlan_scan_requester
479 ucfg_scan_register_requester(struct wlan_objmgr_psoc *psoc,
480 	uint8_t *name, scan_event_handler event_cb, void *arg)
481 {
482 	int i, j;
483 	struct wlan_scan_obj *scan;
484 	struct scan_requester_info *requesters;
485 	wlan_scan_requester requester = {0};
486 
487 	if (!psoc) {
488 		scm_err("null psoc");
489 		return 0;
490 	}
491 	scan = wlan_psoc_get_scan_obj(psoc);
492 	requesters = scan->requesters;
493 	qdf_spin_lock_bh(&scan->lock);
494 	for (i = 0; i < WLAN_MAX_REQUESTORS; ++i) {
495 		if (requesters[i].requester == 0) {
496 			requesters[i].requester =
497 				WLAN_SCAN_REQUESTER_ID_PREFIX | i;
498 			j = 0;
499 			while (name[j] && (j < (WLAN_MAX_MODULE_NAME - 1))) {
500 				requesters[i].module[j] = name[j];
501 				++j;
502 			}
503 			requesters[i].module[j] = 0;
504 			requesters[i].ev_handler.func = event_cb;
505 			requesters[i].ev_handler.arg = arg;
506 			requester = requesters[i].requester;
507 			break;
508 		}
509 	}
510 	qdf_spin_unlock_bh(&scan->lock);
511 	scm_info("module: %s, event_cb: 0x%p, arg: 0x%p, reqid: %d",
512 		name, event_cb, arg, requester);
513 
514 	return requester;
515 }
516 
517 void
518 ucfg_scan_unregister_requester(struct wlan_objmgr_psoc *psoc,
519 	wlan_scan_requester requester)
520 {
521 	int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX;
522 	struct wlan_scan_obj *scan;
523 	struct scan_requester_info *requesters;
524 
525 	if (!psoc) {
526 		scm_err("null psoc");
527 		return;
528 	}
529 	scan = wlan_psoc_get_scan_obj(psoc);
530 	requesters = scan->requesters;
531 	scm_info("reqid: %d", requester);
532 
533 	qdf_spin_lock_bh(&scan->lock);
534 	requesters[idx].requester = 0;
535 	requesters[idx].module[0] = 0;
536 	requesters[idx].ev_handler.func = NULL;
537 	requesters[idx].ev_handler.arg = NULL;
538 	qdf_spin_unlock_bh(&scan->lock);
539 }
540 
541 uint8_t*
542 ucfg_get_scan_requester_name(struct wlan_objmgr_psoc *psoc,
543 	wlan_scan_requester requester)
544 {
545 	int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX;
546 	struct wlan_scan_obj *scan;
547 	struct scan_requester_info *requesters;
548 
549 	if (!psoc) {
550 		scm_err("null psoc");
551 		return "null";
552 	}
553 	scan = wlan_psoc_get_scan_obj(psoc);
554 	requesters = scan->requesters;
555 
556 	if ((idx < WLAN_MAX_REQUESTORS) &&
557 		(requesters[idx].requester == requester)) {
558 		return requesters[idx].module;
559 	}
560 
561 	return (uint8_t *)"unknown";
562 }
563 
564 wlan_scan_id
565 ucfg_scan_get_scan_id(struct wlan_objmgr_psoc *psoc)
566 {
567 	wlan_scan_id id;
568 	struct wlan_scan_obj *scan;
569 
570 	if (!psoc) {
571 		QDF_ASSERT(0);
572 		scm_err("null psoc");
573 		return 0;
574 	}
575 	scan = wlan_psoc_get_scan_obj(psoc);
576 
577 	id = qdf_atomic_inc_return(&scan->scan_ids);
578 	id =  id & WLAN_SCAN_ID_MASK;
579 	/* Mark this scan request as triggered by host
580 	 * by setting WLAN_HOST_SCAN_REQ_ID_PREFIX flag.
581 	 */
582 	id =  id | WLAN_HOST_SCAN_REQ_ID_PREFIX;
583 	scm_info("scan_id: 0x%x", id);
584 
585 	return id;
586 }
587 
588 static QDF_STATUS
589 scm_add_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler,
590 	scan_event_handler event_cb, void *arg)
591 {
592 	struct cb_handler *cb_handler;
593 	uint32_t handler_cnt = pdev_ev_handler->handler_cnt;
594 
595 	/* Assign next available slot to this registration request */
596 	cb_handler = &(pdev_ev_handler->cb_handlers[handler_cnt]);
597 	cb_handler->func = event_cb;
598 	cb_handler->arg = arg;
599 	pdev_ev_handler->handler_cnt++;
600 
601 	return QDF_STATUS_SUCCESS;
602 }
603 
604 QDF_STATUS
605 ucfg_scan_register_event_handler(struct wlan_objmgr_pdev *pdev,
606 	scan_event_handler event_cb, void *arg)
607 {
608 	uint32_t idx;
609 	struct wlan_scan_obj *scan;
610 	struct pdev_scan_ev_handler *pdev_ev_handler;
611 	struct cb_handler *cb_handler;
612 
613 	/* scan event handler call back can't be NULL */
614 	if (!pdev || !event_cb) {
615 		scm_err("pdev: %p, event_cb: %p", pdev, event_cb);
616 		return QDF_STATUS_E_NULL_VALUE;
617 	}
618 
619 	scm_info("pdev: %p, event_cb: %p, arg: %p\n", pdev, event_cb, arg);
620 
621 	scan = wlan_pdev_get_scan_obj(pdev);
622 	pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev);
623 	cb_handler = &(pdev_ev_handler->cb_handlers[0]);
624 
625 	qdf_spin_lock_bh(&scan->lock);
626 	/* Ensure its not a duplicate registration request */
627 	for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV;
628 		idx++, cb_handler++) {
629 		if ((cb_handler->func == event_cb) &&
630 			(cb_handler->arg == arg)) {
631 			qdf_spin_unlock_bh(&scan->lock);
632 			scm_warn("func: %p, arg: %p already exists",
633 				event_cb, arg);
634 			return QDF_STATUS_SUCCESS;
635 		}
636 	}
637 
638 	QDF_ASSERT(pdev_ev_handler->handler_cnt <
639 			MAX_SCAN_EVENT_HANDLERS_PER_PDEV);
640 
641 	if (pdev_ev_handler->handler_cnt >= MAX_SCAN_EVENT_HANDLERS_PER_PDEV) {
642 		qdf_spin_unlock_bh(&scan->lock);
643 		scm_warn("No more registrations possible");
644 		return QDF_STATUS_E_NOMEM;
645 	}
646 
647 	scm_add_scan_event_handler(pdev_ev_handler, event_cb, arg);
648 	qdf_spin_unlock_bh(&scan->lock);
649 
650 	scm_info("event_cb: 0x%p, arg: 0x%p", event_cb, arg);
651 
652 	return QDF_STATUS_SUCCESS;
653 }
654 
655 static QDF_STATUS
656 wlan_scan_global_init(struct wlan_scan_obj *scan_obj)
657 {
658 	scan_obj->scan_def.active_dwell = SCAN_ACTIVE_DWELL_TIME;
659 	scan_obj->scan_def.passive_dwell = SCAN_PASSIVE_DWELL_TIME;
660 	scan_obj->scan_def.max_rest_time = SCAN_MAX_REST_TIME;
661 	scan_obj->scan_def.min_rest_time = SCAN_MIN_REST_TIME;
662 	scan_obj->scan_def.conc_active_dwell = SCAN_CONC_ACTIVE_DWELL_TIME;
663 	scan_obj->scan_def.conc_passive_dwell = SCAN_CONC_PASSIVE_DWELL_TIME;
664 	scan_obj->scan_def.conc_max_rest_time = SCAN_CONC_MAX_REST_TIME;
665 	scan_obj->scan_def.conc_min_rest_time = SCAN_CONC_MIN_REST_TIME;
666 	scan_obj->scan_def.conc_idle_time = SCAN_CONC_IDLE_TIME;
667 	scan_obj->scan_def.repeat_probe_time = SCAN_REPEAT_PROBE_TIME;
668 	scan_obj->scan_def.probe_spacing_time = SCAN_PROBE_SPACING_TIME;
669 	scan_obj->scan_def.probe_delay = SCAN_PROBE_DELAY;
670 	scan_obj->scan_def.burst_duration = SCAN_BURST_DURATION;
671 	scan_obj->scan_def.max_scan_time = SCAN_MAX_SCAN_TIME;
672 	scan_obj->scan_def.num_probes = SCAN_NUM_PROBES;
673 	scan_obj->scan_def.scan_cache_aging_time = SCAN_CACHE_AGING_TIME;
674 	scan_obj->scan_def.max_bss_per_pdev = SCAN_MAX_BSS_PDEV;
675 	scan_obj->scan_def.scan_priority = SCAN_PRIORITY;
676 	scan_obj->scan_def.idle_time = SCAN_NETWORK_IDLE_TIMEOUT;
677 	scan_obj->scan_def.adaptive_dwell_time_mode = SCAN_DWELL_MODE_DEFAULT;
678 	/* scan contrl flags */
679 	scan_obj->scan_def.scan_f_passive = true;
680 	scan_obj->scan_def.scan_f_ofdm_rates = true;
681 	scan_obj->scan_def.scan_f_2ghz = true;
682 	scan_obj->scan_def.scan_f_5ghz = true;
683 	/* scan event flags */
684 	scan_obj->scan_def.scan_ev_started = true;
685 	scan_obj->scan_def.scan_ev_completed = true;
686 	scan_obj->scan_def.scan_ev_bss_chan = true;
687 	scan_obj->scan_def.scan_ev_foreign_chan = true;
688 	scan_obj->scan_def.scan_ev_dequeued = true;
689 	scan_obj->scan_def.scan_ev_preempted = true;
690 	scan_obj->scan_def.scan_ev_start_failed = true;
691 	scan_obj->scan_def.scan_ev_restarted = true;
692 	/* init scan id seed */
693 	qdf_atomic_init(&scan_obj->scan_ids);
694 
695 	return wlan_pno_global_init(&scan_obj->pno_cfg);
696 }
697 
698 static QDF_STATUS
699 scm_remove_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler,
700 	struct cb_handler *entry)
701 {
702 	struct cb_handler *last_entry;
703 	uint32_t handler_cnt = pdev_ev_handler->handler_cnt;
704 
705 	/* Replace event handler being deleted
706 	 * with the last one in the list.
707 	 */
708 	last_entry = &(pdev_ev_handler->cb_handlers[handler_cnt - 1]);
709 	entry->func = last_entry->func;
710 	entry->arg = last_entry->arg;
711 
712 	/* Clear our last entry */
713 	last_entry->func = NULL;
714 	last_entry->arg = NULL;
715 	pdev_ev_handler->handler_cnt--;
716 
717 	return QDF_STATUS_SUCCESS;
718 }
719 
720 void
721 ucfg_scan_unregister_event_handler(struct wlan_objmgr_pdev *pdev,
722 	scan_event_handler event_cb, void *arg)
723 {
724 	uint8_t found = false;
725 	uint32_t idx;
726 	uint32_t handler_cnt;
727 	struct wlan_scan_obj *scan;
728 	struct cb_handler *cb_handler;
729 	struct pdev_scan_ev_handler *pdev_ev_handler;
730 
731 	scm_info("pdev: %p, event_cb: 0x%p, arg: 0x%p", pdev, event_cb, arg);
732 	if (!pdev) {
733 		scm_err("null pdev");
734 		return;
735 	}
736 	scan = wlan_pdev_get_scan_obj(pdev);
737 	pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev);
738 	cb_handler = &(pdev_ev_handler->cb_handlers[0]);
739 
740 	qdf_spin_lock_bh(&scan->lock);
741 	handler_cnt = pdev_ev_handler->handler_cnt;
742 	if (!handler_cnt) {
743 		qdf_spin_unlock_bh(&scan->lock);
744 		scm_info("No event handlers registered");
745 		return;
746 	}
747 
748 	for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV;
749 		idx++, cb_handler++) {
750 		if ((cb_handler->func == event_cb) &&
751 			(cb_handler->arg == arg)) {
752 			/* Event handler found, remove it
753 			 * from event handler list.
754 			 */
755 			found = true;
756 			scm_remove_scan_event_handler(pdev_ev_handler,
757 				cb_handler);
758 			handler_cnt--;
759 			break;
760 		}
761 	}
762 	qdf_spin_unlock_bh(&scan->lock);
763 
764 	scm_info("event handler %s, remaining handlers: %d",
765 		(found ? "removed" : "not found"), handler_cnt);
766 }
767 
768 QDF_STATUS
769 ucfg_scan_init_default_params(struct wlan_objmgr_vdev *vdev,
770 	struct scan_start_request *req)
771 {
772 	struct scan_default_params *def;
773 
774 	if (!vdev | !req) {
775 		scm_err("vdev: 0x%p, req: 0x%p", vdev, req);
776 		return QDF_STATUS_E_INVAL;
777 	}
778 	def = wlan_vdev_get_def_scan_params(vdev);
779 
780 	/* Zero out everything and explicitly set fields as required */
781 	qdf_mem_zero(req, sizeof(*req));
782 
783 	req->vdev = vdev;
784 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
785 	req->scan_req.scan_priority = def->scan_priority;
786 	req->scan_req.dwell_time_active = def->active_dwell;
787 	req->scan_req.dwell_time_passive = def->passive_dwell;
788 	req->scan_req.min_rest_time = def->min_rest_time;
789 	req->scan_req.max_rest_time = def->max_rest_time;
790 	req->scan_req.repeat_probe_time = def->repeat_probe_time;
791 	req->scan_req.probe_spacing_time = def->probe_spacing_time;
792 	req->scan_req.idle_time = def->idle_time;
793 	req->scan_req.max_scan_time = def->max_scan_time;
794 	req->scan_req.probe_delay = def->probe_delay;
795 	req->scan_req.burst_duration = def->burst_duration;
796 	req->scan_req.n_probes = def->num_probes;
797 	req->scan_req.adaptive_dwell_time_mode =
798 		def->adaptive_dwell_time_mode;
799 	req->scan_req.scan_flags = def->scan_flags;
800 	req->scan_req.scan_events = def->scan_events;
801 
802 	return QDF_STATUS_SUCCESS;
803 }
804 
805 QDF_STATUS
806 ucfg_scan_init_ssid_params(struct scan_start_request *req,
807 		uint32_t num_ssid, struct wlan_ssid *ssid_list)
808 {
809 	uint32_t max_ssid = sizeof(req->scan_req.ssid) /
810 				sizeof(req->scan_req.ssid[0]);
811 
812 	if (!req) {
813 		scm_err("null request");
814 		return QDF_STATUS_E_NULL_VALUE;
815 	}
816 	if (!num_ssid) {
817 		/* empty channel list provided */
818 		req->scan_req.num_ssids = 0;
819 		qdf_mem_zero(&req->scan_req.ssid[0],
820 			sizeof(req->scan_req.ssid));
821 		return QDF_STATUS_SUCCESS;
822 	}
823 	if (!ssid_list) {
824 		scm_err("null ssid_list while num_ssid: %d", num_ssid);
825 		return QDF_STATUS_E_NULL_VALUE;
826 	}
827 	if (num_ssid > max_ssid) {
828 		/* got a big list. alert and continue */
829 		scm_warn("overflow: received %d, max supported : %d",
830 			num_ssid, max_ssid);
831 		return QDF_STATUS_E_E2BIG;
832 	}
833 
834 	if (max_ssid > num_ssid)
835 		max_ssid = num_ssid;
836 
837 	req->scan_req.num_ssids = max_ssid;
838 	qdf_mem_copy(&req->scan_req.ssid[0], ssid_list,
839 		(req->scan_req.num_ssids * sizeof(req->scan_req.ssid[0])));
840 
841 	return QDF_STATUS_SUCCESS;
842 }
843 
844 QDF_STATUS
845 ucfg_scan_init_bssid_params(struct scan_start_request *req,
846 		uint32_t num_bssid, struct qdf_mac_addr *bssid_list)
847 {
848 	uint32_t max_bssid = sizeof(req->scan_req.bssid_list) /
849 				sizeof(req->scan_req.bssid_list[0]);
850 
851 	if (!req) {
852 		scm_err("null request");
853 		return QDF_STATUS_E_NULL_VALUE;
854 	}
855 	if (!num_bssid) {
856 		/* empty channel list provided */
857 		req->scan_req.num_bssid = 0;
858 		qdf_mem_zero(&req->scan_req.bssid_list[0],
859 			sizeof(req->scan_req.bssid_list));
860 		return QDF_STATUS_SUCCESS;
861 	}
862 	if (!bssid_list) {
863 		scm_err("null bssid_list while num_bssid: %d", num_bssid);
864 		return QDF_STATUS_E_NULL_VALUE;
865 	}
866 	if (num_bssid > max_bssid) {
867 		/* got a big list. alert and continue */
868 		scm_warn("overflow: received %d, max supported : %d",
869 			num_bssid, max_bssid);
870 		return QDF_STATUS_E_E2BIG;
871 	}
872 
873 	if (max_bssid > num_bssid)
874 		max_bssid = num_bssid;
875 
876 	req->scan_req.num_bssid = max_bssid;
877 	qdf_mem_copy(&req->scan_req.bssid_list[0], bssid_list,
878 		req->scan_req.num_bssid * sizeof(req->scan_req.bssid_list[0]));
879 
880 	return QDF_STATUS_SUCCESS;
881 }
882 
883 QDF_STATUS
884 ucfg_scan_init_chanlist_params(struct scan_start_request *req,
885 		uint32_t num_chans, uint32_t *chan_list)
886 {
887 
888 	uint32_t max_chans = sizeof(req->scan_req.chan_list) /
889 				sizeof(req->scan_req.chan_list[0]);
890 	if (!req) {
891 		scm_err("null request");
892 		return QDF_STATUS_E_NULL_VALUE;
893 	}
894 	if (!num_chans) {
895 		/* empty channel list provided */
896 		req->scan_req.num_chan = 0;
897 		qdf_mem_zero(&req->scan_req.chan_list[0],
898 			sizeof(req->scan_req.chan_list));
899 		return QDF_STATUS_SUCCESS;
900 	}
901 	if (!chan_list) {
902 		scm_err("null chan_list while num_chans: %d", num_chans);
903 		return QDF_STATUS_E_NULL_VALUE;
904 	}
905 
906 	if (num_chans > max_chans) {
907 		/* got a big list. alert and continue */
908 		scm_warn("overflow: received %d, max supported : %d",
909 			num_chans, max_chans);
910 		return QDF_STATUS_E_E2BIG;
911 	}
912 
913 	if (max_chans > num_chans)
914 		max_chans = num_chans;
915 
916 	req->scan_req.num_chan = max_chans;
917 	qdf_mem_copy(&req->scan_req.chan_list[0], chan_list,
918 		req->scan_req.num_chan * sizeof(req->scan_req.chan_list[0]));
919 
920 	return QDF_STATUS_SUCCESS;
921 }
922 
923 static inline enum scm_scan_status
924 get_scan_status_from_serialization_status(
925 	enum wlan_serialization_cmd_status status)
926 {
927 	enum scm_scan_status scan_status;
928 
929 	switch (status) {
930 	case WLAN_SER_CMD_IN_PENDING_LIST:
931 		scan_status = SCAN_IS_PENDING;
932 		break;
933 	case WLAN_SER_CMD_IN_ACTIVE_LIST:
934 		scan_status = SCAN_IS_ACTIVE;
935 		break;
936 	case WLAN_SER_CMDS_IN_ALL_LISTS:
937 		scan_status = SCAN_IS_ACTIVE_AND_PENDING;
938 		break;
939 	case WLAN_SER_CMD_NOT_FOUND:
940 		scan_status = SCAN_NOT_IN_PROGRESS;
941 		break;
942 	default:
943 		scm_warn("invalid serialization status %d", status);
944 		QDF_ASSERT(0);
945 		scan_status = SCAN_NOT_IN_PROGRESS;
946 		break;
947 	}
948 
949 	return scan_status;
950 }
951 
952 enum scm_scan_status
953 ucfg_scan_get_vdev_status(struct wlan_objmgr_vdev *vdev)
954 {
955 	enum wlan_serialization_cmd_status status;
956 
957 	if (!vdev) {
958 		scm_err("null vdev");
959 		return QDF_STATUS_E_NULL_VALUE;
960 	}
961 	status = wlan_serialization_vdev_scan_status(vdev);
962 
963 	return get_scan_status_from_serialization_status(status);
964 }
965 
966 enum scm_scan_status
967 ucfg_scan_get_pdev_status(struct wlan_objmgr_pdev *pdev)
968 {
969 	enum wlan_serialization_cmd_status status;
970 
971 	if (!pdev) {
972 		scm_err("null pdev");
973 		return SCAN_NOT_IN_PROGRESS;
974 	}
975 	status = wlan_serialization_pdev_scan_status(pdev);
976 
977 	return get_scan_status_from_serialization_status(status);
978 }
979 
980 static void
981 ucfg_scan_register_unregister_bcn_cb(struct wlan_objmgr_psoc *psoc,
982 	bool enable)
983 {
984 	QDF_STATUS status;
985 	struct mgmt_txrx_mgmt_frame_cb_info cb_info[2];
986 
987 	cb_info[0].frm_type = MGMT_PROBE_RESP;
988 	cb_info[0].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback;
989 	cb_info[1].frm_type = MGMT_BEACON;
990 	cb_info[1].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback;
991 
992 	if (enable)
993 		status = wlan_mgmt_txrx_register_rx_cb(psoc,
994 					 WLAN_UMAC_COMP_SCAN, cb_info, 2);
995 	else
996 		status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
997 					 WLAN_UMAC_COMP_SCAN, cb_info, 2);
998 	if (status != QDF_STATUS_SUCCESS)
999 		scm_err("%s the Handle with MGMT TXRX layer has failed",
1000 			enable ? "Registering" : "Deregistering");
1001 }
1002 
1003 static void ucfg_scan_assign_rssi_category(struct scan_default_params *params,
1004 	int32_t best_ap_rssi, uint32_t cat_offset)
1005 {
1006 	int i;
1007 
1008 	scm_info("best AP RSSI:%d, cat offset: %d", best_ap_rssi, cat_offset);
1009 	if (cat_offset)
1010 		for (i = 0; i < SCM_NUM_RSSI_CAT; i++) {
1011 			params->rssi_cat[SCM_NUM_RSSI_CAT - i - 1] =
1012 				(best_ap_rssi -
1013 				params->select_5ghz_margin -
1014 				(int)(i * cat_offset));
1015 		params->bss_prefer_val[i] = i;
1016 	}
1017 }
1018 
1019 QDF_STATUS ucfg_scan_update_user_config(struct wlan_objmgr_psoc *psoc,
1020 	struct scan_user_cfg *scan_cfg)
1021 {
1022 	struct wlan_scan_obj *scan_obj;
1023 	struct scan_default_params *scan_def;
1024 
1025 	if (!psoc) {
1026 		scm_err("null psoc");
1027 		return QDF_STATUS_E_FAILURE;
1028 	}
1029 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1030 	if (scan_obj == NULL) {
1031 		scm_err("Failed to get scan object");
1032 		return QDF_STATUS_E_FAILURE;
1033 	}
1034 
1035 	scan_def = &scan_obj->scan_def;
1036 	scan_def->active_dwell = scan_cfg->active_dwell;
1037 	scan_def->passive_dwell = scan_cfg->passive_dwell;
1038 	scan_def->conc_active_dwell = scan_cfg->conc_active_dwell;
1039 	scan_def->conc_passive_dwell = scan_cfg->conc_passive_dwell;
1040 	scan_def->conc_max_rest_time = scan_cfg->conc_max_rest_time;
1041 	scan_def->conc_min_rest_time = scan_cfg->conc_min_rest_time;
1042 	scan_def->conc_idle_time = scan_cfg->conc_idle_time;
1043 	scan_def->scan_cache_aging_time = scan_cfg->scan_cache_aging_time;
1044 	scan_def->prefer_5ghz = scan_cfg->prefer_5ghz;
1045 	scan_def->select_5ghz_margin = scan_cfg->select_5ghz_margin;
1046 	scan_def->adaptive_dwell_time_mode = scan_cfg->scan_dwell_time_mode;
1047 	scan_def->scan_f_chan_stat_evnt = scan_cfg->is_snr_monitoring_enabled;
1048 
1049 	ucfg_scan_assign_rssi_category(scan_def,
1050 			scan_cfg->scan_bucket_threshold,
1051 			scan_cfg->rssi_cat_gap);
1052 
1053 	return ucfg_scan_update_pno_config(&scan_obj->pno_cfg,
1054 		&scan_cfg->pno_cfg);
1055 }
1056 
1057 QDF_STATUS ucfg_scan_update_roam_params(struct wlan_objmgr_psoc *psoc,
1058 	struct roam_filter_params *roam_params)
1059 {
1060 	struct scan_default_params *scan_def;
1061 
1062 	if (!psoc) {
1063 		scm_err("null psoc");
1064 		return QDF_STATUS_E_FAILURE;
1065 	}
1066 	scan_def = wlan_scan_psoc_get_def_params(psoc);
1067 	if (!scan_def) {
1068 		scm_err("Failed to get scan object");
1069 		return QDF_STATUS_E_FAILURE;
1070 	}
1071 
1072 	qdf_mem_copy(&scan_def->roam_params, roam_params,
1073 		sizeof(struct roam_filter_params));
1074 
1075 	return QDF_STATUS_SUCCESS;
1076 }
1077 
1078 static QDF_STATUS
1079 ucfg_scan_cancel_pdev_scan(struct wlan_objmgr_pdev *pdev)
1080 {
1081 	struct scan_cancel_request *req;
1082 	QDF_STATUS status;
1083 	struct wlan_objmgr_vdev *vdev;
1084 
1085 	req = qdf_mem_malloc(sizeof(*req));
1086 	if (!req) {
1087 		scm_err("Failed to allocate memory");
1088 		return QDF_STATUS_E_NOMEM;
1089 	}
1090 
1091 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_OSIF_ID);
1092 	if (!vdev) {
1093 		scm_err("Failed to get vdev");
1094 		return QDF_STATUS_E_INVAL;
1095 	}
1096 	req->vdev = vdev;
1097 	req->cancel_req.scan_id = INVAL_SCAN_ID;
1098 	wlan_pdev_obj_lock(pdev);
1099 	req->cancel_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1100 	wlan_pdev_obj_unlock(pdev);
1101 	req->cancel_req.vdev_id = INVAL_VDEV_ID;
1102 	req->cancel_req.req_type = WLAN_SCAN_CANCEL_PDEV_ALL;
1103 	status = ucfg_scan_cancel_sync(req);
1104 	if (QDF_IS_STATUS_ERROR(status))
1105 		scm_err("Cancel scan request failed");
1106 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
1107 
1108 	return status;
1109 }
1110 
1111 #ifdef WLAN_PMO_ENABLE
1112 
1113 static QDF_STATUS
1114 ucfg_scan_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg)
1115 {
1116 	struct wlan_objmgr_pdev *pdev = NULL;
1117 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1118 	int i;
1119 
1120 	/* Check all pdev */
1121 	for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
1122 		pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_SCAN_ID);
1123 		if (!pdev)
1124 			continue;
1125 		if (ucfg_scan_get_pdev_status(pdev) !=
1126 		    SCAN_NOT_IN_PROGRESS)
1127 			status = ucfg_scan_cancel_pdev_scan(pdev);
1128 		wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID);
1129 		if (QDF_IS_STATUS_ERROR(status)) {
1130 			scm_err("failed to cancel scan for pdev_id %d", i);
1131 			return status;
1132 		}
1133 	}
1134 
1135 	return QDF_STATUS_SUCCESS;
1136 }
1137 
1138 static QDF_STATUS
1139 ucfg_scan_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg)
1140 {
1141 	return QDF_STATUS_SUCCESS;
1142 }
1143 
1144 static inline void
1145 ucfg_scan_register_pmo_handler(void)
1146 {
1147 	pmo_register_suspend_handler(WLAN_UMAC_COMP_SCAN,
1148 		ucfg_scan_suspend_handler, NULL);
1149 	pmo_register_resume_handler(WLAN_UMAC_COMP_SCAN,
1150 		ucfg_scan_resume_handler, NULL);
1151 }
1152 
1153 static inline void
1154 ucfg_scan_unregister_pmo_handler(void)
1155 {
1156 	pmo_unregister_suspend_handler(WLAN_UMAC_COMP_SCAN,
1157 		ucfg_scan_suspend_handler);
1158 	pmo_unregister_resume_handler(WLAN_UMAC_COMP_SCAN,
1159 		ucfg_scan_resume_handler);
1160 }
1161 
1162 #else
1163 static inline void
1164 ucfg_scan_register_pmo_handler(void)
1165 {
1166 }
1167 
1168 static inline void
1169 ucfg_scan_unregister_pmo_handler(void)
1170 {
1171 }
1172 #endif
1173 
1174 QDF_STATUS
1175 ucfg_scan_psoc_open(struct wlan_objmgr_psoc *psoc)
1176 {
1177 	struct wlan_scan_obj *scan_obj;
1178 
1179 	scm_info("psoc open: 0x%p", psoc);
1180 	if (!psoc) {
1181 		scm_err("null psoc");
1182 		return QDF_STATUS_E_FAILURE;
1183 	}
1184 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1185 	if (scan_obj == NULL) {
1186 		scm_err("Failed to get scan object");
1187 		return QDF_STATUS_E_FAILURE;
1188 	}
1189 	/* Initialize the scan Globals */
1190 	wlan_scan_global_init(scan_obj);
1191 	qdf_spinlock_create(&scan_obj->lock);
1192 	ucfg_scan_register_pmo_handler();
1193 
1194 	return QDF_STATUS_SUCCESS;
1195 }
1196 
1197 QDF_STATUS
1198 ucfg_scan_psoc_close(struct wlan_objmgr_psoc *psoc)
1199 {
1200 	struct wlan_scan_obj *scan_obj;
1201 
1202 	scm_info("psoc close: 0x%p", psoc);
1203 	if (!psoc) {
1204 		scm_err("null psoc");
1205 		return QDF_STATUS_E_FAILURE;
1206 	}
1207 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1208 	if (scan_obj == NULL) {
1209 		scm_err("Failed to get scan object");
1210 		return QDF_STATUS_E_FAILURE;
1211 	}
1212 	ucfg_scan_unregister_pmo_handler();
1213 	qdf_spinlock_destroy(&scan_obj->lock);
1214 	wlan_pno_global_deinit(&scan_obj->pno_cfg);
1215 
1216 	return QDF_STATUS_SUCCESS;
1217 }
1218 
1219 static bool scm_serialization_scan_rules_cb(
1220 		union wlan_serialization_rules_info *comp_info,
1221 		uint8_t comp_id)
1222 {
1223 	switch (comp_id) {
1224 	case QDF_MODULE_ID_TDLS:
1225 		if (comp_info->scan_info.is_tdls_in_progress) {
1226 			scm_info("Cancel scan. Tdls in progress");
1227 			return false;
1228 		}
1229 		break;
1230 	case QDF_MODULE_ID_DFS:
1231 		if (comp_info->scan_info.is_cac_in_progress) {
1232 			scm_info("Cancel scan. CAC in progress");
1233 			return false;
1234 		}
1235 		break;
1236 	default:
1237 		scm_info("not handled comp_id %d", comp_id);
1238 		break;
1239 	}
1240 
1241 	return true;
1242 }
1243 
1244 QDF_STATUS
1245 ucfg_scan_psoc_enable(struct wlan_objmgr_psoc *psoc)
1246 {
1247 	QDF_STATUS status;
1248 
1249 	scm_info("psoc enable: 0x%p", psoc);
1250 	if (!psoc) {
1251 		scm_err("null psoc");
1252 		return QDF_STATUS_E_FAILURE;
1253 	}
1254 	/* Subscribe for scan events from lmac layesr */
1255 	status = tgt_scan_register_ev_handler(psoc);
1256 	QDF_ASSERT(status == QDF_STATUS_SUCCESS);
1257 	scm_db_init(psoc);
1258 	ucfg_scan_register_unregister_bcn_cb(psoc, true);
1259 	status = wlan_serialization_register_apply_rules_cb(psoc,
1260 				WLAN_SER_CMD_SCAN,
1261 				scm_serialization_scan_rules_cb);
1262 	QDF_ASSERT(status == QDF_STATUS_SUCCESS);
1263 	return status;
1264 }
1265 
1266 QDF_STATUS
1267 ucfg_scan_psoc_disable(struct wlan_objmgr_psoc *psoc)
1268 {
1269 	QDF_STATUS status;
1270 
1271 	scm_info("psoc disable: 0x%p", psoc);
1272 	if (!psoc) {
1273 		scm_err("null psoc");
1274 		return QDF_STATUS_E_FAILURE;
1275 	}
1276 	/* Unsubscribe for scan events from lmac layesr */
1277 	status = tgt_scan_unregister_ev_handler(psoc);
1278 	QDF_ASSERT(status == QDF_STATUS_SUCCESS);
1279 	ucfg_scan_register_unregister_bcn_cb(psoc, false);
1280 	scm_db_deinit(psoc);
1281 
1282 	return status;
1283 }
1284 
1285 uint32_t
1286 ucfg_scan_get_max_active_scans(struct wlan_objmgr_psoc *psoc)
1287 {
1288 	struct scan_default_params *scan_params = NULL;
1289 
1290 	if (!psoc) {
1291 		scm_err("null psoc");
1292 		return 0;
1293 	}
1294 	scan_params = wlan_scan_psoc_get_def_params(psoc);
1295 
1296 	return scan_params->max_active_scans_allowed;
1297 }
1298