xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c (revision 91abaccb452c5ef80225d45a998644d4cdd55543)
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 <wlan_reg_services_api.h>
30 #include <wlan_utility.h>
31 #include "../../core/src/wlan_scan_main.h"
32 #include "../../core/src/wlan_scan_manager.h"
33 #include "../../core/src/wlan_scan_cache_db.h"
34 #ifdef WLAN_PMO_ENABLE
35 #include <wlan_pmo_obj_mgmt_api.h>
36 #endif
37 #ifdef WLAN_POLICY_MGR_ENABLE
38 #include <wlan_policy_mgr_api.h>
39 #endif
40 
41 QDF_STATUS ucfg_scan_register_bcn_cb(struct wlan_objmgr_psoc *psoc,
42 	update_beacon_cb cb, enum scan_cb_type type)
43 {
44 	return scm_scan_register_bcn_cb(psoc, cb, type);
45 }
46 
47 qdf_list_t *ucfg_scan_get_result(struct wlan_objmgr_pdev *pdev,
48 	struct scan_filter *filter)
49 {
50 	return scm_get_scan_result(pdev, filter);
51 }
52 
53 QDF_STATUS ucfg_scan_db_iterate(struct wlan_objmgr_pdev *pdev,
54 	scan_iterator_func func, void *arg)
55 {
56 	return scm_iterate_scan_db(pdev, func, arg);
57 }
58 
59 QDF_STATUS ucfg_scan_purge_results(qdf_list_t *scan_list)
60 {
61 	return scm_purge_scan_results(scan_list);
62 }
63 
64 QDF_STATUS ucfg_scan_flush_results(struct wlan_objmgr_pdev *pdev,
65 	struct scan_filter *filter)
66 {
67 	return scm_flush_results(pdev, filter);
68 }
69 
70 void ucfg_scan_filter_valid_channel(struct wlan_objmgr_pdev *pdev,
71 	uint8_t *chan_list, uint32_t num_chan)
72 {
73 	scm_filter_valid_channel(pdev, chan_list, num_chan);
74 }
75 
76 QDF_STATUS ucfg_scan_init(void)
77 {
78 	QDF_STATUS status;
79 
80 	status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_SCAN,
81 		wlan_scan_psoc_created_notification, NULL);
82 	if (QDF_IS_STATUS_ERROR(status)) {
83 		scm_err("Failed to register psoc create handler");
84 		goto fail_create_psoc;
85 	}
86 
87 	status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN,
88 		wlan_scan_psoc_destroyed_notification, NULL);
89 	if (QDF_IS_STATUS_ERROR(status)) {
90 		scm_err("Failed to create psoc delete handler");
91 		goto fail_psoc_destroy;
92 	}
93 	scm_info("scan psoc create and delete handler registered with objmgr");
94 
95 	status = wlan_objmgr_register_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
96 		wlan_scan_vdev_created_notification, NULL);
97 	if (QDF_IS_STATUS_ERROR(status)) {
98 		scm_err("Failed to register vdev create handler");
99 		goto fail_pdev_create;
100 	}
101 
102 	status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_SCAN,
103 		wlan_scan_vdev_destroyed_notification, NULL);
104 	if (QDF_IS_STATUS_SUCCESS(status)) {
105 		scm_info("scan vdev create and delete handler registered with objmgr");
106 		return QDF_STATUS_SUCCESS;
107 	}
108 
109 	scm_err("Failed to destroy vdev delete handler");
110 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
111 				wlan_scan_vdev_created_notification, NULL);
112 fail_pdev_create:
113 	wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN,
114 				wlan_scan_psoc_destroyed_notification, NULL);
115 fail_psoc_destroy:
116 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN,
117 			wlan_scan_psoc_created_notification, NULL);
118 fail_create_psoc:
119 	return status;
120 }
121 
122 QDF_STATUS ucfg_scan_deinit(void)
123 {
124 	QDF_STATUS status;
125 
126 	status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN,
127 		wlan_scan_psoc_created_notification, NULL);
128 	if (status != QDF_STATUS_SUCCESS)
129 		scm_err("Failed to unregister psoc create handler");
130 
131 	status = wlan_objmgr_unregister_psoc_destroy_handler(
132 				WLAN_UMAC_COMP_SCAN,
133 				wlan_scan_psoc_destroyed_notification, NULL);
134 	if (status != QDF_STATUS_SUCCESS)
135 		scm_err("Failed to unregister psoc delete handler");
136 
137 	status = wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
138 		wlan_scan_vdev_created_notification, NULL);
139 	if (status != QDF_STATUS_SUCCESS)
140 		scm_err("Failed to unregister vdev create handler");
141 
142 	status = wlan_objmgr_unregister_vdev_destroy_handler(
143 			WLAN_UMAC_COMP_SCAN,
144 			wlan_scan_vdev_destroyed_notification, NULL);
145 	if (status != QDF_STATUS_SUCCESS)
146 		scm_err("Failed to unregister vdev delete handler");
147 
148 	return status;
149 }
150 
151 #ifdef FEATURE_WLAN_SCAN_PNO
152 
153 QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev,
154 	struct pno_scan_req_params *req)
155 {
156 	struct scan_vdev_obj *scan_vdev_obj;
157 	QDF_STATUS status;
158 
159 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
160 	if (!scan_vdev_obj) {
161 		scm_err("null scan_vdev_obj");
162 		return QDF_STATUS_E_INVAL;
163 	}
164 	if (scan_vdev_obj->pno_in_progress) {
165 		scm_err("pno already in progress");
166 		return QDF_STATUS_E_ALREADY;
167 	}
168 
169 	status = tgt_scan_pno_start(vdev, req);
170 	if (QDF_IS_STATUS_ERROR(status))
171 		scm_err("pno start failed");
172 	else
173 		scan_vdev_obj->pno_in_progress = true;
174 
175 	return status;
176 }
177 
178 QDF_STATUS ucfg_scan_pno_stop(struct wlan_objmgr_vdev *vdev)
179 {
180 	struct scan_vdev_obj *scan_vdev_obj;
181 	QDF_STATUS status;
182 
183 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
184 	if (!scan_vdev_obj) {
185 		scm_err("null scan_vdev_obj");
186 		return QDF_STATUS_E_INVAL;
187 	}
188 	if (!scan_vdev_obj->pno_in_progress) {
189 		scm_err("pno already stopped");
190 		return QDF_STATUS_E_ALREADY;
191 	}
192 
193 	status = tgt_scan_pno_stop(vdev, wlan_vdev_get_id(vdev));
194 	if (QDF_IS_STATUS_ERROR(status))
195 		scm_err("pno start failed");
196 	else
197 		scan_vdev_obj->pno_in_progress = false;
198 
199 	return status;
200 }
201 
202 bool ucfg_scan_get_pno_in_progress(struct wlan_objmgr_vdev *vdev)
203 {
204 	struct scan_vdev_obj *scan_vdev_obj;
205 
206 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
207 	if (!scan_vdev_obj) {
208 		scm_err("null scan_vdev_obj");
209 		return false;
210 	}
211 
212 	return scan_vdev_obj->pno_in_progress;
213 }
214 
215 bool ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev)
216 {
217 	struct scan_vdev_obj *scan_vdev_obj;
218 
219 	scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
220 	if (!scan_vdev_obj) {
221 		scm_err("null scan_vdev_obj");
222 		return false;
223 	}
224 
225 	return scan_vdev_obj->pno_match_evt_received;
226 }
227 
228 static QDF_STATUS
229 wlan_pno_global_init(struct pno_def_config *pno_def)
230 {
231 	struct nlo_mawc_params *mawc_cfg;
232 
233 	qdf_wake_lock_create(&pno_def->pno_wake_lock, "wlan_pno_wl");
234 	mawc_cfg = &pno_def->mawc_params;
235 	pno_def->channel_prediction = SCAN_PNO_CHANNEL_PREDICTION;
236 	pno_def->top_k_num_of_channels = SCAN_TOP_K_NUM_OF_CHANNELS;
237 	pno_def->stationary_thresh = SCAN_STATIONARY_THRESHOLD;
238 	pno_def->channel_prediction_full_scan =
239 			SCAN_CHANNEL_PREDICTION_FULL_SCAN_MS;
240 	pno_def->adaptive_dwell_mode = SCAN_ADAPTIVE_PNOSCAN_DWELL_MODE;
241 	mawc_cfg->enable = SCAN_MAWC_NLO_ENABLED;
242 	mawc_cfg->exp_backoff_ratio = SCAN_MAWC_NLO_EXP_BACKOFF_RATIO;
243 	mawc_cfg->init_scan_interval = SCAN_MAWC_NLO_INIT_SCAN_INTERVAL;
244 	mawc_cfg->max_scan_interval = SCAN_MAWC_NLO_MAX_SCAN_INTERVAL;
245 
246 	return QDF_STATUS_SUCCESS;
247 }
248 
249 static QDF_STATUS
250 wlan_pno_global_deinit(struct pno_def_config *pno_def)
251 {
252 	qdf_wake_lock_destroy(&pno_def->pno_wake_lock);
253 
254 	return QDF_STATUS_SUCCESS;
255 }
256 
257 QDF_STATUS
258 ucfg_scan_get_pno_def_params(struct wlan_objmgr_vdev *vdev,
259 	struct pno_scan_req_params *req)
260 {
261 	struct scan_default_params *scan_def;
262 	struct wlan_scan_obj *scan = wlan_vdev_get_scan_obj(vdev);
263 	struct pno_def_config *pno_def;
264 
265 	if (!vdev | !req | !scan) {
266 		scm_err("vdev: 0x%pK, req: 0x%pK scan_obj: 0x%pK",
267 			vdev, req, scan);
268 		return QDF_STATUS_E_INVAL;
269 	}
270 
271 	scan_def = wlan_vdev_get_def_scan_params(vdev);
272 	pno_def = &scan->pno_cfg;
273 
274 	req->active_dwell_time = scan_def->active_dwell;
275 	req->passive_dwell_time = scan_def->passive_dwell;
276 
277 	req->adaptive_dwell_mode = pno_def->adaptive_dwell_mode;
278 
279 	req->pno_channel_prediction = pno_def->adaptive_dwell_mode;
280 	req->top_k_num_of_channels = pno_def->top_k_num_of_channels;
281 	req->stationary_thresh = pno_def->stationary_thresh;
282 	req->channel_prediction_full_scan =
283 			pno_def->channel_prediction_full_scan;
284 	req->mawc_params.vdev_id = wlan_vdev_get_id(vdev);
285 	qdf_mem_copy(&req->mawc_params, &pno_def->mawc_params,
286 			sizeof(req->mawc_params));
287 
288 	return QDF_STATUS_SUCCESS;
289 }
290 
291 static QDF_STATUS ucfg_scan_update_pno_config(struct pno_def_config *pno,
292 	struct pno_user_cfg *pno_cfg)
293 {
294 	pno->channel_prediction = pno_cfg->channel_prediction;
295 	pno->top_k_num_of_channels = pno_cfg->top_k_num_of_channels;
296 	pno->stationary_thresh = pno_cfg->stationary_thresh;
297 	pno->adaptive_dwell_mode = pno_cfg->adaptive_dwell_mode;
298 	pno->channel_prediction_full_scan =
299 		pno_cfg->channel_prediction_full_scan;
300 	qdf_mem_copy(&pno->mawc_params, &pno_cfg->mawc_params,
301 			sizeof(pno->mawc_params));
302 
303 	return QDF_STATUS_SUCCESS;
304 }
305 
306 QDF_STATUS
307 ucfg_scan_register_pno_cb(struct wlan_objmgr_psoc *psoc,
308 	scan_event_handler event_cb, void *arg)
309 {
310 	struct wlan_scan_obj *scan;
311 
312 	if (!psoc) {
313 		scm_err("null psoc");
314 		return QDF_STATUS_E_INVAL;
315 	}
316 	scan = wlan_psoc_get_scan_obj(psoc);
317 	qdf_spin_lock_bh(&scan->lock);
318 	scan->pno_cfg.pno_cb.func = event_cb;
319 	scan->pno_cfg.pno_cb.arg = arg;
320 	qdf_spin_unlock_bh(&scan->lock);
321 	scm_info("event_cb: 0x%pK, arg: 0x%pK", event_cb, arg);
322 
323 	return QDF_STATUS_SUCCESS;
324 }
325 
326 #else
327 
328 static inline QDF_STATUS
329 wlan_pno_global_init(struct pno_def_config *pno_def)
330 {
331 	return QDF_STATUS_SUCCESS;
332 }
333 static inline QDF_STATUS
334 wlan_pno_global_deinit(struct pno_def_config *pno_def)
335 {
336 	return QDF_STATUS_SUCCESS;
337 }
338 
339 static inline QDF_STATUS
340 ucfg_scan_update_pno_config(struct pno_def_config *pno,
341 	struct pno_user_cfg *pno_cfg)
342 {
343 	return QDF_STATUS_SUCCESS;
344 }
345 
346 #endif
347 
348 #ifdef WLAN_POLICY_MGR_ENABLE
349 /**
350  * ucfg_scan_update_dbs_scan_ctrl_ext_flag() - update dbs scan ctrl flags
351  * @req: pointer to scan request
352  *
353  * This function updates the dbs scan ctrl flags.
354  * Non-DBS scan is requested if any of the below case is met:
355  * 1. HW is DBS incapable
356  * 2. Directed scan
357  * 3. Channel list has only few channels
358  * 4. Channel list has single band channels
359  * For remaining cases, dbs scan is requested.
360  *
361  * Return: None
362  */
363 static void
364 ucfg_scan_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req)
365 {
366 	uint32_t num_chan;
367 	struct wlan_objmgr_psoc *psoc;
368 	uint32_t scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS;
369 	uint32_t conn_cnt;
370 
371 	psoc = wlan_vdev_get_psoc(req->vdev);
372 
373 	if (DISABLE_DBS_CXN_AND_SCAN ==
374 			wlan_objmgr_psoc_get_dual_mac_disable(psoc))
375 		goto end;
376 
377 	conn_cnt = policy_mgr_get_connection_count(psoc);
378 	if (conn_cnt > 0) {
379 		scm_debug("%d active connections, go for DBS scan",
380 				conn_cnt);
381 		scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT;
382 		goto end;
383 	}
384 
385 	if (req->scan_req.num_ssids) {
386 		scm_debug("directed SSID");
387 		goto end;
388 	}
389 
390 	if (req->scan_req.num_bssid) {
391 		scm_debug("directed BSSID");
392 		goto end;
393 	}
394 
395 	num_chan = req->scan_req.chan_list.num_chan;
396 
397 	/* num_chan=0 means all channels */
398 	if (!num_chan)
399 		scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT;
400 
401 	if (num_chan < SCAN_MIN_CHAN_DBS_SCAN_THRESHOLD)
402 		goto end;
403 
404 	while (num_chan > 1) {
405 		if (!WLAN_REG_IS_SAME_BAND_CHANNELS(
406 			req->scan_req.chan_list.chan[0].freq,
407 			req->scan_req.chan_list.chan[num_chan-1].freq)) {
408 			scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT;
409 			break;
410 		}
411 		num_chan--;
412 	}
413 
414 end:
415 	req->scan_req.scan_ctrl_flags_ext |=
416 		((scan_dbs_policy << SCAN_FLAG_EXT_DBS_SCAN_POLICY_BIT)
417 		 & SCAN_FLAG_EXT_DBS_SCAN_POLICY_MASK);
418 	scm_debug("scan_ctrl_flags_ext: 0x%x",
419 			req->scan_req.scan_ctrl_flags_ext);
420 }
421 #else
422 static void
423 ucfg_scan_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req)
424 {
425 }
426 #endif
427 
428 QDF_STATUS
429 ucfg_scan_start(struct scan_start_request *req)
430 {
431 	struct scheduler_msg msg = {0};
432 	QDF_STATUS status;
433 	struct wlan_scan_obj *scan_obj;
434 	struct wlan_objmgr_pdev *pdev;
435 
436 	if (!req || !req->vdev) {
437 		scm_err("vdev: %pK, req: %pK", req->vdev, req);
438 		if (req)
439 			scm_scan_free_scan_request_mem(req);
440 		return QDF_STATUS_E_NULL_VALUE;
441 	}
442 
443 	pdev = wlan_vdev_get_pdev(req->vdev);
444 	if (!pdev) {
445 		scm_err("Failed to get pdev object");
446 		scm_scan_free_scan_request_mem(req);
447 		return QDF_STATUS_E_NULL_VALUE;
448 	}
449 
450 	scan_obj = wlan_pdev_get_scan_obj(pdev);
451 	if (!scan_obj) {
452 		scm_err("Failed to get scan object");
453 		scm_scan_free_scan_request_mem(req);
454 		return QDF_STATUS_E_NULL_VALUE;
455 	}
456 
457 	if (!scan_obj->enable_scan) {
458 		scm_err("scan disabled, rejecting the scan req");
459 		scm_scan_free_scan_request_mem(req);
460 		return QDF_STATUS_E_AGAIN;
461 	}
462 
463 	scm_debug("reqid: %d, scanid: %d, vdevid: %d",
464 		req->scan_req.scan_req_id, req->scan_req.scan_id,
465 		req->scan_req.vdev_id);
466 
467 	/* Overwrite scan parameters as required */
468 	if (!ucfg_scan_get_wide_band_scan(pdev)) {
469 		scm_debug("wide_band_scan not supported, Scan 20 MHz");
470 		req->scan_req.scan_f_wide_band = false;
471 	}
472 
473 	if (scan_obj->scan_def.usr_cfg_probe_rpt_time) {
474 		req->scan_req.repeat_probe_time =
475 			scan_obj->scan_def.usr_cfg_probe_rpt_time;
476 		scm_debug("usr_cfg_probe_rpt_time %d",
477 				req->scan_req.repeat_probe_time);
478 	}
479 
480 	if (scan_obj->scan_def.usr_cfg_num_probes) {
481 		req->scan_req.n_probes = scan_obj->scan_def.usr_cfg_num_probes;
482 		scm_debug("usr_cfg_num_probes %d", req->scan_req.n_probes);
483 	}
484 	ucfg_scan_update_dbs_scan_ctrl_ext_flag(req);
485 	if (req->scan_req.scan_f_passive)
486 		req->scan_req.scan_ctrl_flags_ext |=
487 			SCAN_FLAG_EXT_FILTER_PUBLIC_ACTION_FRAME;
488 
489 	/* Try to get vdev reference. Return if reference could
490 	 * not be taken. Reference will be released once scan
491 	 * request handling completes along with free of @req.
492 	 */
493 	status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID);
494 	if (QDF_IS_STATUS_ERROR(status)) {
495 		scm_info("unable to get reference");
496 		scm_scan_free_scan_request_mem(req);
497 		return status;
498 	}
499 
500 	msg.bodyptr = req;
501 	msg.callback = scm_scan_start_req;
502 	msg.flush_callback = scm_scan_start_flush_callback;
503 
504 	status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
505 	if (QDF_IS_STATUS_ERROR(status)) {
506 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
507 		scm_err("failed to post to QDF_MODULE_ID_OS_IF");
508 		scm_scan_free_scan_request_mem(req);
509 	}
510 
511 	return status;
512 }
513 
514 QDF_STATUS ucfg_scan_set_enable(struct wlan_objmgr_psoc *psoc, bool enable)
515 {
516 	struct wlan_scan_obj *scan_obj;
517 
518 	scan_obj = wlan_psoc_get_scan_obj(psoc);
519 	if (!scan_obj) {
520 		scm_err("Failed to get scan object");
521 		return QDF_STATUS_E_NULL_VALUE;
522 	}
523 	scan_obj->enable_scan = enable;
524 	scm_debug("set enable_scan to %d", scan_obj->enable_scan);
525 
526 	return QDF_STATUS_SUCCESS;
527 }
528 
529 bool ucfg_scan_get_enable(struct wlan_objmgr_psoc *psoc)
530 {
531 	struct wlan_scan_obj *scan_obj;
532 
533 	scan_obj = wlan_psoc_get_scan_obj(psoc);
534 	if (!scan_obj) {
535 		scm_err("Failed to get scan object");
536 		return false;
537 	}
538 	return scan_obj->enable_scan;
539 }
540 
541 QDF_STATUS
542 ucfg_scan_set_wide_band_scan(struct wlan_objmgr_pdev *pdev, bool enable)
543 {
544 	uint8_t pdev_id;
545 	struct wlan_scan_obj *scan_obj;
546 
547 	if (!pdev) {
548 		scm_warn("null vdev");
549 		return QDF_STATUS_E_NULL_VALUE;
550 	}
551 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
552 	scan_obj = wlan_pdev_get_scan_obj(pdev);
553 
554 	scm_debug("set wide_band_scan to %d", enable);
555 	scan_obj->pdev_info[pdev_id].wide_band_scan = enable;
556 
557 	return QDF_STATUS_SUCCESS;
558 }
559 
560 bool ucfg_scan_get_wide_band_scan(struct wlan_objmgr_pdev *pdev)
561 {
562 	uint8_t pdev_id;
563 	struct wlan_scan_obj *scan_obj;
564 
565 	if (!pdev) {
566 		scm_warn("null vdev");
567 		return QDF_STATUS_E_NULL_VALUE;
568 	}
569 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
570 	scan_obj = wlan_pdev_get_scan_obj(pdev);
571 
572 	return scan_obj->pdev_info[pdev_id].wide_band_scan;
573 }
574 
575 QDF_STATUS
576 ucfg_scan_cancel(struct scan_cancel_request *req)
577 {
578 	struct scheduler_msg msg = {0};
579 	QDF_STATUS status;
580 
581 	if (!req || !req->vdev) {
582 		scm_err("vdev: %pK, req: %pK", req->vdev, req);
583 		if (req)
584 			qdf_mem_free(req);
585 		return QDF_STATUS_E_NULL_VALUE;
586 	}
587 	scm_info("reqid: %d, scanid: %d, vdevid: %d, type: %d",
588 		req->cancel_req.requester, req->cancel_req.scan_id,
589 		req->cancel_req.vdev_id, req->cancel_req.req_type);
590 
591 	status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID);
592 	if (QDF_IS_STATUS_ERROR(status)) {
593 		scm_info("Failed to get vdev ref; status:%d", status);
594 		goto req_free;
595 	}
596 
597 	msg.bodyptr = req;
598 	msg.callback = scm_scan_cancel_req;
599 	msg.flush_callback = scm_scan_cancel_flush_callback;
600 
601 	status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg);
602 	if (QDF_IS_STATUS_ERROR(status)) {
603 		scm_err("failed to post to QDF_MODULE_ID_OS_IF");
604 		goto vdev_put;
605 	}
606 
607 	return QDF_STATUS_SUCCESS;
608 
609 vdev_put:
610 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
611 
612 req_free:
613 	qdf_mem_free(req);
614 
615 	return status;
616 }
617 
618 QDF_STATUS
619 ucfg_scan_cancel_sync(struct scan_cancel_request *req)
620 {
621 	QDF_STATUS status;
622 	bool cancel_vdev = false, cancel_pdev = false;
623 	struct wlan_objmgr_vdev *vdev;
624 	struct wlan_objmgr_pdev *pdev;
625 	uint32_t max_wait_iterations = SCM_CANCEL_SCAN_WAIT_ITERATION;
626 	qdf_event_t cancel_scan_event;
627 
628 	if (!req || !req->vdev) {
629 		scm_err("vdev: %pK, req: %pK", req->vdev, req);
630 		if (req)
631 			qdf_mem_free(req);
632 		return QDF_STATUS_E_NULL_VALUE;
633 	}
634 
635 	if (req->cancel_req.req_type ==
636 	   WLAN_SCAN_CANCEL_PDEV_ALL)
637 		cancel_pdev = true;
638 	else if (req->cancel_req.req_type ==
639 	   WLAN_SCAN_CANCEL_VDEV_ALL)
640 		cancel_vdev = true;
641 
642 	vdev = req->vdev;
643 	status = ucfg_scan_cancel(req);
644 	if (QDF_IS_STATUS_ERROR(status)) {
645 		scm_err("failed to post to QDF_MODULE_ID_OS_IF");
646 		return status;
647 	}
648 
649 	/*
650 	 * If cancel req is to cancel all scan of pdev or vdev
651 	 * wait untill all scan of pdev or vdev get cancelled
652 	 */
653 	qdf_event_create(&cancel_scan_event);
654 	qdf_event_reset(&cancel_scan_event);
655 
656 	if (cancel_pdev) {
657 		pdev = wlan_vdev_get_pdev(vdev);
658 		while ((ucfg_scan_get_pdev_status(pdev) !=
659 		     SCAN_NOT_IN_PROGRESS) && max_wait_iterations) {
660 			scm_debug("wait for all pdev scan to get complete");
661 				qdf_wait_single_event(&cancel_scan_event,
662 					qdf_system_msecs_to_ticks(
663 					SCM_CANCEL_SCAN_WAIT_TIME));
664 			max_wait_iterations--;
665 		}
666 	} else if (cancel_vdev) {
667 		while ((ucfg_scan_get_vdev_status(vdev) !=
668 		     SCAN_NOT_IN_PROGRESS) && max_wait_iterations) {
669 			scm_debug("wait for all vdev scan to get complete");
670 				qdf_wait_single_event(&cancel_scan_event,
671 					qdf_system_msecs_to_ticks(
672 					SCM_CANCEL_SCAN_WAIT_TIME));
673 			max_wait_iterations--;
674 		}
675 	}
676 
677 	qdf_event_destroy(&cancel_scan_event);
678 
679 	if (!max_wait_iterations) {
680 		scm_err("Failed to wait for scans to get complete");
681 		return QDF_STATUS_E_TIMEOUT;
682 	}
683 
684 	return status;
685 }
686 
687 wlan_scan_requester
688 ucfg_scan_register_requester(struct wlan_objmgr_psoc *psoc,
689 	uint8_t *name, scan_event_handler event_cb, void *arg)
690 {
691 	int i, j;
692 	struct wlan_scan_obj *scan;
693 	struct scan_requester_info *requesters;
694 	wlan_scan_requester requester = {0};
695 
696 	if (!psoc) {
697 		scm_err("null psoc");
698 		return 0;
699 	}
700 	scan = wlan_psoc_get_scan_obj(psoc);
701 	requesters = scan->requesters;
702 	qdf_spin_lock_bh(&scan->lock);
703 	for (i = 0; i < WLAN_MAX_REQUESTORS; ++i) {
704 		if (requesters[i].requester == 0) {
705 			requesters[i].requester =
706 				WLAN_SCAN_REQUESTER_ID_PREFIX | i;
707 			j = 0;
708 			while (name[j] && (j < (WLAN_MAX_MODULE_NAME - 1))) {
709 				requesters[i].module[j] = name[j];
710 				++j;
711 			}
712 			requesters[i].module[j] = 0;
713 			requesters[i].ev_handler.func = event_cb;
714 			requesters[i].ev_handler.arg = arg;
715 			requester = requesters[i].requester;
716 			break;
717 		}
718 	}
719 	qdf_spin_unlock_bh(&scan->lock);
720 	scm_info("module: %s, event_cb: 0x%pK, arg: 0x%pK, reqid: %d",
721 		name, event_cb, arg, requester);
722 
723 	return requester;
724 }
725 
726 void
727 ucfg_scan_unregister_requester(struct wlan_objmgr_psoc *psoc,
728 	wlan_scan_requester requester)
729 {
730 	int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX;
731 	struct wlan_scan_obj *scan;
732 	struct scan_requester_info *requesters;
733 
734 	if (!psoc) {
735 		scm_err("null psoc");
736 		return;
737 	}
738 	scan = wlan_psoc_get_scan_obj(psoc);
739 	requesters = scan->requesters;
740 	scm_info("reqid: %d", requester);
741 
742 	qdf_spin_lock_bh(&scan->lock);
743 	requesters[idx].requester = 0;
744 	requesters[idx].module[0] = 0;
745 	requesters[idx].ev_handler.func = NULL;
746 	requesters[idx].ev_handler.arg = NULL;
747 	qdf_spin_unlock_bh(&scan->lock);
748 }
749 
750 uint8_t*
751 ucfg_get_scan_requester_name(struct wlan_objmgr_psoc *psoc,
752 	wlan_scan_requester requester)
753 {
754 	int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX;
755 	struct wlan_scan_obj *scan;
756 	struct scan_requester_info *requesters;
757 
758 	if (!psoc) {
759 		scm_err("null psoc");
760 		return "null";
761 	}
762 	scan = wlan_psoc_get_scan_obj(psoc);
763 	requesters = scan->requesters;
764 
765 	if ((idx < WLAN_MAX_REQUESTORS) &&
766 		(requesters[idx].requester == requester)) {
767 		return requesters[idx].module;
768 	}
769 
770 	return (uint8_t *)"unknown";
771 }
772 
773 wlan_scan_id
774 ucfg_scan_get_scan_id(struct wlan_objmgr_psoc *psoc)
775 {
776 	wlan_scan_id id;
777 	struct wlan_scan_obj *scan;
778 
779 	if (!psoc) {
780 		QDF_ASSERT(0);
781 		scm_err("null psoc");
782 		return 0;
783 	}
784 	scan = wlan_psoc_get_scan_obj(psoc);
785 
786 	id = qdf_atomic_inc_return(&scan->scan_ids);
787 	id =  id & WLAN_SCAN_ID_MASK;
788 	/* Mark this scan request as triggered by host
789 	 * by setting WLAN_HOST_SCAN_REQ_ID_PREFIX flag.
790 	 */
791 	id =  id | WLAN_HOST_SCAN_REQ_ID_PREFIX;
792 	scm_info("scan_id: 0x%x", id);
793 
794 	return id;
795 }
796 
797 static QDF_STATUS
798 scm_add_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler,
799 	scan_event_handler event_cb, void *arg)
800 {
801 	struct cb_handler *cb_handler;
802 	uint32_t handler_cnt = pdev_ev_handler->handler_cnt;
803 
804 	/* Assign next available slot to this registration request */
805 	cb_handler = &(pdev_ev_handler->cb_handlers[handler_cnt]);
806 	cb_handler->func = event_cb;
807 	cb_handler->arg = arg;
808 	pdev_ev_handler->handler_cnt++;
809 
810 	return QDF_STATUS_SUCCESS;
811 }
812 
813 QDF_STATUS
814 ucfg_scan_register_event_handler(struct wlan_objmgr_pdev *pdev,
815 	scan_event_handler event_cb, void *arg)
816 {
817 	uint32_t idx;
818 	struct wlan_scan_obj *scan;
819 	struct pdev_scan_ev_handler *pdev_ev_handler;
820 	struct cb_handler *cb_handler;
821 
822 	/* scan event handler call back can't be NULL */
823 	if (!pdev || !event_cb) {
824 		scm_err("pdev: %pK, event_cb: %pK", pdev, event_cb);
825 		return QDF_STATUS_E_NULL_VALUE;
826 	}
827 
828 	scm_info("pdev: %pK, event_cb: %pK, arg: %pK\n", pdev, event_cb, arg);
829 
830 	scan = wlan_pdev_get_scan_obj(pdev);
831 	pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev);
832 	cb_handler = &(pdev_ev_handler->cb_handlers[0]);
833 
834 	qdf_spin_lock_bh(&scan->lock);
835 	/* Ensure its not a duplicate registration request */
836 	for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV;
837 		idx++, cb_handler++) {
838 		if ((cb_handler->func == event_cb) &&
839 			(cb_handler->arg == arg)) {
840 			qdf_spin_unlock_bh(&scan->lock);
841 			scm_warn("func: %pK, arg: %pK already exists",
842 				event_cb, arg);
843 			return QDF_STATUS_SUCCESS;
844 		}
845 	}
846 
847 	QDF_ASSERT(pdev_ev_handler->handler_cnt <
848 			MAX_SCAN_EVENT_HANDLERS_PER_PDEV);
849 
850 	if (pdev_ev_handler->handler_cnt >= MAX_SCAN_EVENT_HANDLERS_PER_PDEV) {
851 		qdf_spin_unlock_bh(&scan->lock);
852 		scm_warn("No more registrations possible");
853 		return QDF_STATUS_E_NOMEM;
854 	}
855 
856 	scm_add_scan_event_handler(pdev_ev_handler, event_cb, arg);
857 	qdf_spin_unlock_bh(&scan->lock);
858 
859 	scm_info("event_cb: 0x%pK, arg: 0x%pK", event_cb, arg);
860 
861 	return QDF_STATUS_SUCCESS;
862 }
863 
864 static QDF_STATUS
865 wlan_scan_global_init(struct wlan_scan_obj *scan_obj)
866 {
867 	scan_obj->enable_scan = true;
868 	scan_obj->scan_def.active_dwell = SCAN_ACTIVE_DWELL_TIME;
869 	scan_obj->scan_def.passive_dwell = SCAN_PASSIVE_DWELL_TIME;
870 	scan_obj->scan_def.max_rest_time = SCAN_MAX_REST_TIME;
871 	scan_obj->scan_def.min_rest_time = SCAN_MIN_REST_TIME;
872 	scan_obj->scan_def.conc_active_dwell = SCAN_CONC_ACTIVE_DWELL_TIME;
873 	scan_obj->scan_def.conc_passive_dwell = SCAN_CONC_PASSIVE_DWELL_TIME;
874 	scan_obj->scan_def.conc_max_rest_time = SCAN_CONC_MAX_REST_TIME;
875 	scan_obj->scan_def.conc_min_rest_time = SCAN_CONC_MIN_REST_TIME;
876 	scan_obj->scan_def.conc_idle_time = SCAN_CONC_IDLE_TIME;
877 	scan_obj->scan_def.repeat_probe_time = SCAN_REPEAT_PROBE_TIME;
878 	scan_obj->scan_def.probe_spacing_time = SCAN_PROBE_SPACING_TIME;
879 	scan_obj->scan_def.probe_delay = SCAN_PROBE_DELAY;
880 	scan_obj->scan_def.burst_duration = SCAN_BURST_DURATION;
881 	scan_obj->scan_def.max_scan_time = SCAN_MAX_SCAN_TIME;
882 	scan_obj->scan_def.num_probes = SCAN_NUM_PROBES;
883 	scan_obj->scan_def.scan_cache_aging_time = SCAN_CACHE_AGING_TIME;
884 	scan_obj->scan_def.max_bss_per_pdev = SCAN_MAX_BSS_PDEV;
885 	scan_obj->scan_def.scan_priority = SCAN_PRIORITY;
886 	scan_obj->scan_def.idle_time = SCAN_NETWORK_IDLE_TIMEOUT;
887 	scan_obj->scan_def.adaptive_dwell_time_mode = SCAN_DWELL_MODE_DEFAULT;
888 	/* scan contrl flags */
889 	scan_obj->scan_def.scan_f_passive = true;
890 	scan_obj->scan_def.scan_f_ofdm_rates = true;
891 	scan_obj->scan_def.scan_f_2ghz = true;
892 	scan_obj->scan_def.scan_f_5ghz = true;
893 	scan_obj->scan_def.scan_f_chan_stat_evnt = SCAN_CHAN_STATS_EVENT_ENAB;
894 	/* scan event flags */
895 	scan_obj->scan_def.scan_ev_started = true;
896 	scan_obj->scan_def.scan_ev_completed = true;
897 	scan_obj->scan_def.scan_ev_bss_chan = true;
898 	scan_obj->scan_def.scan_ev_foreign_chan = true;
899 	scan_obj->scan_def.scan_ev_foreign_chn_exit = true;
900 	scan_obj->scan_def.scan_ev_dequeued = true;
901 	scan_obj->scan_def.scan_ev_preempted = true;
902 	scan_obj->scan_def.scan_ev_start_failed = true;
903 	scan_obj->scan_def.scan_ev_restarted = true;
904 	/* init scan id seed */
905 	qdf_atomic_init(&scan_obj->scan_ids);
906 
907 	return wlan_pno_global_init(&scan_obj->pno_cfg);
908 }
909 
910 static QDF_STATUS
911 scm_remove_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler,
912 	struct cb_handler *entry)
913 {
914 	struct cb_handler *last_entry;
915 	uint32_t handler_cnt = pdev_ev_handler->handler_cnt;
916 
917 	/* Replace event handler being deleted
918 	 * with the last one in the list.
919 	 */
920 	last_entry = &(pdev_ev_handler->cb_handlers[handler_cnt - 1]);
921 	entry->func = last_entry->func;
922 	entry->arg = last_entry->arg;
923 
924 	/* Clear our last entry */
925 	last_entry->func = NULL;
926 	last_entry->arg = NULL;
927 	pdev_ev_handler->handler_cnt--;
928 
929 	return QDF_STATUS_SUCCESS;
930 }
931 
932 void
933 ucfg_scan_unregister_event_handler(struct wlan_objmgr_pdev *pdev,
934 	scan_event_handler event_cb, void *arg)
935 {
936 	uint8_t found = false;
937 	uint32_t idx;
938 	uint32_t handler_cnt;
939 	struct wlan_scan_obj *scan;
940 	struct cb_handler *cb_handler;
941 	struct pdev_scan_ev_handler *pdev_ev_handler;
942 
943 	scm_info("pdev: %pK, event_cb: 0x%pK, arg: 0x%pK", pdev, event_cb, arg);
944 	if (!pdev) {
945 		scm_err("null pdev");
946 		return;
947 	}
948 	scan = wlan_pdev_get_scan_obj(pdev);
949 	pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev);
950 	cb_handler = &(pdev_ev_handler->cb_handlers[0]);
951 
952 	qdf_spin_lock_bh(&scan->lock);
953 	handler_cnt = pdev_ev_handler->handler_cnt;
954 	if (!handler_cnt) {
955 		qdf_spin_unlock_bh(&scan->lock);
956 		scm_info("No event handlers registered");
957 		return;
958 	}
959 
960 	for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV;
961 		idx++, cb_handler++) {
962 		if ((cb_handler->func == event_cb) &&
963 			(cb_handler->arg == arg)) {
964 			/* Event handler found, remove it
965 			 * from event handler list.
966 			 */
967 			found = true;
968 			scm_remove_scan_event_handler(pdev_ev_handler,
969 				cb_handler);
970 			handler_cnt--;
971 			break;
972 		}
973 	}
974 	qdf_spin_unlock_bh(&scan->lock);
975 
976 	scm_info("event handler %s, remaining handlers: %d",
977 		(found ? "removed" : "not found"), handler_cnt);
978 }
979 
980 #ifdef WLAN_POLICY_MGR_ENABLE
981 /**
982  * ucfg_scan_req_update_params() - update scan req params depending
983  * on active modes
984  * @vdev: vdev object pointer
985  * @req: scan request
986  *
987  * Return: void
988  */
989 static void ucfg_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
990 	struct scan_start_request *req)
991 {
992 	bool ap_or_go_present;
993 	struct wlan_objmgr_psoc *psoc;
994 
995 	psoc = wlan_vdev_get_psoc(vdev);
996 
997 	if (!psoc)
998 		return;
999 
1000 	ap_or_go_present = policy_mgr_mode_specific_connection_count(
1001 				psoc, QDF_SAP_MODE, NULL) ||
1002 				policy_mgr_mode_specific_connection_count(
1003 				psoc, QDF_P2P_GO_MODE, NULL);
1004 
1005 	/*
1006 	 * If AP is active set min rest time same as max rest time, so that
1007 	 * firmware spends more time on home channel which will increase the
1008 	 * probability of sending beacon at TBTT
1009 	 */
1010 	if (ap_or_go_present)
1011 		req->scan_req.min_rest_time = req->scan_req.max_rest_time;
1012 }
1013 #else
1014 static inline void ucfg_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
1015 	struct scan_start_request *req){}
1016 #endif
1017 
1018 
1019 QDF_STATUS
1020 ucfg_scan_init_default_params(struct wlan_objmgr_vdev *vdev,
1021 	struct scan_start_request *req)
1022 {
1023 	struct scan_default_params *def;
1024 
1025 	if (!vdev | !req) {
1026 		scm_err("vdev: 0x%pK, req: 0x%pK", vdev, req);
1027 		return QDF_STATUS_E_INVAL;
1028 	}
1029 	def = wlan_vdev_get_def_scan_params(vdev);
1030 
1031 	/* Zero out everything and explicitly set fields as required */
1032 	qdf_mem_zero(req, sizeof(*req));
1033 
1034 	req->vdev = vdev;
1035 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
1036 	req->scan_req.scan_priority = def->scan_priority;
1037 	req->scan_req.dwell_time_active = def->active_dwell;
1038 	req->scan_req.dwell_time_passive = def->passive_dwell;
1039 	req->scan_req.min_rest_time = def->min_rest_time;
1040 	req->scan_req.max_rest_time = def->max_rest_time;
1041 	req->scan_req.repeat_probe_time = def->repeat_probe_time;
1042 	req->scan_req.probe_spacing_time = def->probe_spacing_time;
1043 	req->scan_req.idle_time = def->idle_time;
1044 	req->scan_req.max_scan_time = def->max_scan_time;
1045 	req->scan_req.probe_delay = def->probe_delay;
1046 	req->scan_req.burst_duration = def->burst_duration;
1047 	req->scan_req.n_probes = def->num_probes;
1048 	req->scan_req.adaptive_dwell_time_mode =
1049 		def->adaptive_dwell_time_mode;
1050 	req->scan_req.scan_flags = def->scan_flags;
1051 	req->scan_req.scan_events = def->scan_events;
1052 	req->scan_req.scan_random.randomize = def->enable_mac_spoofing;
1053 	ucfg_scan_req_update_params(vdev, req);
1054 
1055 	return QDF_STATUS_SUCCESS;
1056 }
1057 
1058 QDF_STATUS
1059 ucfg_scan_init_ssid_params(struct scan_start_request *req,
1060 		uint32_t num_ssid, struct wlan_ssid *ssid_list)
1061 {
1062 	uint32_t max_ssid = sizeof(req->scan_req.ssid) /
1063 				sizeof(req->scan_req.ssid[0]);
1064 
1065 	if (!req) {
1066 		scm_err("null request");
1067 		return QDF_STATUS_E_NULL_VALUE;
1068 	}
1069 	if (!num_ssid) {
1070 		/* empty channel list provided */
1071 		req->scan_req.num_ssids = 0;
1072 		qdf_mem_zero(&req->scan_req.ssid[0],
1073 			sizeof(req->scan_req.ssid));
1074 		return QDF_STATUS_SUCCESS;
1075 	}
1076 	if (!ssid_list) {
1077 		scm_err("null ssid_list while num_ssid: %d", num_ssid);
1078 		return QDF_STATUS_E_NULL_VALUE;
1079 	}
1080 	if (num_ssid > max_ssid) {
1081 		/* got a big list. alert and continue */
1082 		scm_warn("overflow: received %d, max supported : %d",
1083 			num_ssid, max_ssid);
1084 		return QDF_STATUS_E_E2BIG;
1085 	}
1086 
1087 	if (max_ssid > num_ssid)
1088 		max_ssid = num_ssid;
1089 
1090 	req->scan_req.num_ssids = max_ssid;
1091 	qdf_mem_copy(&req->scan_req.ssid[0], ssid_list,
1092 		(req->scan_req.num_ssids * sizeof(req->scan_req.ssid[0])));
1093 
1094 	return QDF_STATUS_SUCCESS;
1095 }
1096 
1097 QDF_STATUS
1098 ucfg_scan_init_bssid_params(struct scan_start_request *req,
1099 		uint32_t num_bssid, struct qdf_mac_addr *bssid_list)
1100 {
1101 	uint32_t max_bssid = sizeof(req->scan_req.bssid_list) /
1102 				sizeof(req->scan_req.bssid_list[0]);
1103 
1104 	if (!req) {
1105 		scm_err("null request");
1106 		return QDF_STATUS_E_NULL_VALUE;
1107 	}
1108 	if (!num_bssid) {
1109 		/* empty channel list provided */
1110 		req->scan_req.num_bssid = 0;
1111 		qdf_mem_zero(&req->scan_req.bssid_list[0],
1112 			sizeof(req->scan_req.bssid_list));
1113 		return QDF_STATUS_SUCCESS;
1114 	}
1115 	if (!bssid_list) {
1116 		scm_err("null bssid_list while num_bssid: %d", num_bssid);
1117 		return QDF_STATUS_E_NULL_VALUE;
1118 	}
1119 	if (num_bssid > max_bssid) {
1120 		/* got a big list. alert and continue */
1121 		scm_warn("overflow: received %d, max supported : %d",
1122 			num_bssid, max_bssid);
1123 		return QDF_STATUS_E_E2BIG;
1124 	}
1125 
1126 	if (max_bssid > num_bssid)
1127 		max_bssid = num_bssid;
1128 
1129 	req->scan_req.num_bssid = max_bssid;
1130 	qdf_mem_copy(&req->scan_req.bssid_list[0], bssid_list,
1131 		req->scan_req.num_bssid * sizeof(req->scan_req.bssid_list[0]));
1132 
1133 	return QDF_STATUS_SUCCESS;
1134 }
1135 
1136 QDF_STATUS
1137 ucfg_scan_init_chanlist_params(struct scan_start_request *req,
1138 		uint32_t num_chans, uint32_t *chan_list, uint32_t *phymode)
1139 {
1140 	uint32_t idx;
1141 	uint32_t max_chans = sizeof(req->scan_req.chan_list.chan) /
1142 				sizeof(req->scan_req.chan_list.chan[0]);
1143 	if (!req) {
1144 		scm_err("null request");
1145 		return QDF_STATUS_E_NULL_VALUE;
1146 	}
1147 	if (!num_chans) {
1148 		/* empty channel list provided */
1149 		qdf_mem_zero(&req->scan_req.chan_list,
1150 			sizeof(req->scan_req.chan_list));
1151 		req->scan_req.chan_list.num_chan = 0;
1152 		return QDF_STATUS_SUCCESS;
1153 	}
1154 	if (!chan_list) {
1155 		scm_err("null chan_list while num_chans: %d", num_chans);
1156 		return QDF_STATUS_E_NULL_VALUE;
1157 	}
1158 
1159 	if (num_chans > max_chans) {
1160 		/* got a big list. alert and continue */
1161 		scm_warn("overflow: received %d, max supported : %d",
1162 			num_chans, max_chans);
1163 		return QDF_STATUS_E_E2BIG;
1164 	}
1165 
1166 	if (max_chans > num_chans)
1167 		max_chans = num_chans;
1168 
1169 	req->scan_req.chan_list.num_chan = max_chans;
1170 	for (idx = 0; idx < max_chans; idx++) {
1171 		req->scan_req.chan_list.chan[idx].freq =
1172 			(chan_list[idx] > WLAN_24_GHZ_BASE_FREQ) ?
1173 			chan_list[idx] : wlan_chan_to_freq(chan_list[idx]);
1174 		req->scan_req.chan_list.chan[idx].phymode =
1175 			(phymode ? phymode[idx] : 0);
1176 	}
1177 
1178 	/* Enable wide band scan by default if phymode list is provided.
1179 	 * This flag will be cleared in @ucfg_scan_start() if underlying
1180 	 * phy doesn't support wide band scan.
1181 	 */
1182 	if (phymode)
1183 		req->scan_req.scan_f_wide_band = true;
1184 
1185 	return QDF_STATUS_SUCCESS;
1186 }
1187 
1188 static inline enum scm_scan_status
1189 get_scan_status_from_serialization_status(
1190 	enum wlan_serialization_cmd_status status)
1191 {
1192 	enum scm_scan_status scan_status;
1193 
1194 	switch (status) {
1195 	case WLAN_SER_CMD_IN_PENDING_LIST:
1196 		scan_status = SCAN_IS_PENDING;
1197 		break;
1198 	case WLAN_SER_CMD_IN_ACTIVE_LIST:
1199 		scan_status = SCAN_IS_ACTIVE;
1200 		break;
1201 	case WLAN_SER_CMDS_IN_ALL_LISTS:
1202 		scan_status = SCAN_IS_ACTIVE_AND_PENDING;
1203 		break;
1204 	case WLAN_SER_CMD_NOT_FOUND:
1205 		scan_status = SCAN_NOT_IN_PROGRESS;
1206 		break;
1207 	default:
1208 		scm_warn("invalid serialization status %d", status);
1209 		QDF_ASSERT(0);
1210 		scan_status = SCAN_NOT_IN_PROGRESS;
1211 		break;
1212 	}
1213 
1214 	return scan_status;
1215 }
1216 
1217 enum scm_scan_status
1218 ucfg_scan_get_vdev_status(struct wlan_objmgr_vdev *vdev)
1219 {
1220 	enum wlan_serialization_cmd_status status;
1221 
1222 	if (!vdev) {
1223 		scm_err("null vdev");
1224 		return QDF_STATUS_E_NULL_VALUE;
1225 	}
1226 	status = wlan_serialization_vdev_scan_status(vdev);
1227 
1228 	return get_scan_status_from_serialization_status(status);
1229 }
1230 
1231 enum scm_scan_status
1232 ucfg_scan_get_pdev_status(struct wlan_objmgr_pdev *pdev)
1233 {
1234 	enum wlan_serialization_cmd_status status;
1235 
1236 	if (!pdev) {
1237 		scm_err("null pdev");
1238 		return SCAN_NOT_IN_PROGRESS;
1239 	}
1240 	status = wlan_serialization_pdev_scan_status(pdev);
1241 
1242 	return get_scan_status_from_serialization_status(status);
1243 }
1244 
1245 static void
1246 ucfg_scan_register_unregister_bcn_cb(struct wlan_objmgr_psoc *psoc,
1247 	bool enable)
1248 {
1249 	QDF_STATUS status;
1250 	struct mgmt_txrx_mgmt_frame_cb_info cb_info[2];
1251 
1252 	cb_info[0].frm_type = MGMT_PROBE_RESP;
1253 	cb_info[0].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback;
1254 	cb_info[1].frm_type = MGMT_BEACON;
1255 	cb_info[1].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback;
1256 
1257 	if (enable)
1258 		status = wlan_mgmt_txrx_register_rx_cb(psoc,
1259 					 WLAN_UMAC_COMP_SCAN, cb_info, 2);
1260 	else
1261 		status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
1262 					 WLAN_UMAC_COMP_SCAN, cb_info, 2);
1263 	if (status != QDF_STATUS_SUCCESS)
1264 		scm_err("%s the Handle with MGMT TXRX layer has failed",
1265 			enable ? "Registering" : "Deregistering");
1266 }
1267 
1268 static void ucfg_scan_assign_rssi_category(struct scan_default_params *params,
1269 	int32_t best_ap_rssi, uint32_t cat_offset)
1270 {
1271 	int i;
1272 
1273 	scm_info("best AP RSSI:%d, cat offset: %d", best_ap_rssi, cat_offset);
1274 	if (cat_offset)
1275 		for (i = 0; i < SCM_NUM_RSSI_CAT; i++) {
1276 			params->rssi_cat[SCM_NUM_RSSI_CAT - i - 1] =
1277 				(best_ap_rssi -
1278 				params->select_5ghz_margin -
1279 				(int)(i * cat_offset));
1280 		params->bss_prefer_val[i] = i;
1281 	}
1282 }
1283 
1284 QDF_STATUS ucfg_scan_update_user_config(struct wlan_objmgr_psoc *psoc,
1285 	struct scan_user_cfg *scan_cfg)
1286 {
1287 	struct wlan_scan_obj *scan_obj;
1288 	struct scan_default_params *scan_def;
1289 
1290 	if (!psoc) {
1291 		scm_err("null psoc");
1292 		return QDF_STATUS_E_FAILURE;
1293 	}
1294 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1295 	if (scan_obj == NULL) {
1296 		scm_err("Failed to get scan object");
1297 		return QDF_STATUS_E_FAILURE;
1298 	}
1299 
1300 	scan_def = &scan_obj->scan_def;
1301 	scan_def->active_dwell = scan_cfg->active_dwell;
1302 	scan_def->passive_dwell = scan_cfg->passive_dwell;
1303 	scan_def->conc_active_dwell = scan_cfg->conc_active_dwell;
1304 	scan_def->conc_passive_dwell = scan_cfg->conc_passive_dwell;
1305 	scan_def->conc_max_rest_time = scan_cfg->conc_max_rest_time;
1306 	scan_def->conc_min_rest_time = scan_cfg->conc_min_rest_time;
1307 	scan_def->conc_idle_time = scan_cfg->conc_idle_time;
1308 	scan_def->scan_cache_aging_time = scan_cfg->scan_cache_aging_time;
1309 	scan_def->prefer_5ghz = scan_cfg->prefer_5ghz;
1310 	scan_def->select_5ghz_margin = scan_cfg->select_5ghz_margin;
1311 	scan_def->adaptive_dwell_time_mode = scan_cfg->scan_dwell_time_mode;
1312 	scan_def->scan_f_chan_stat_evnt = scan_cfg->is_snr_monitoring_enabled;
1313 	scan_obj->ie_whitelist = scan_cfg->ie_whitelist;
1314 	scan_def->usr_cfg_probe_rpt_time = scan_cfg->usr_cfg_probe_rpt_time;
1315 	scan_def->usr_cfg_num_probes = scan_cfg->usr_cfg_num_probes;
1316 	scan_def->is_bssid_hint_priority = scan_cfg->is_bssid_hint_priority;
1317 	scan_def->enable_mac_spoofing = scan_cfg->enable_mac_spoofing;
1318 
1319 	ucfg_scan_assign_rssi_category(scan_def,
1320 			scan_cfg->scan_bucket_threshold,
1321 			scan_cfg->rssi_cat_gap);
1322 
1323 	ucfg_scan_update_pno_config(&scan_obj->pno_cfg,
1324 		&scan_cfg->pno_cfg);
1325 
1326 	qdf_mem_copy(&scan_def->score_config, &scan_cfg->score_config,
1327 		sizeof(struct scoring_config));
1328 	scm_validate_scoring_config(&scan_def->score_config);
1329 
1330 	return QDF_STATUS_SUCCESS;
1331 }
1332 
1333 QDF_STATUS ucfg_scan_update_roam_params(struct wlan_objmgr_psoc *psoc,
1334 	struct roam_filter_params *roam_params)
1335 {
1336 	struct scan_default_params *scan_def;
1337 
1338 	if (!psoc) {
1339 		scm_err("null psoc");
1340 		return QDF_STATUS_E_FAILURE;
1341 	}
1342 	scan_def = wlan_scan_psoc_get_def_params(psoc);
1343 	if (!scan_def) {
1344 		scm_err("Failed to get scan object");
1345 		return QDF_STATUS_E_FAILURE;
1346 	}
1347 
1348 	qdf_mem_copy(&scan_def->roam_params, roam_params,
1349 		sizeof(struct roam_filter_params));
1350 
1351 	return QDF_STATUS_SUCCESS;
1352 }
1353 
1354 static QDF_STATUS
1355 ucfg_scan_cancel_pdev_scan(struct wlan_objmgr_pdev *pdev)
1356 {
1357 	struct scan_cancel_request *req;
1358 	QDF_STATUS status;
1359 	struct wlan_objmgr_vdev *vdev;
1360 
1361 	req = qdf_mem_malloc(sizeof(*req));
1362 	if (!req) {
1363 		scm_err("Failed to allocate memory");
1364 		return QDF_STATUS_E_NOMEM;
1365 	}
1366 
1367 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_OSIF_ID);
1368 	if (!vdev) {
1369 		scm_err("Failed to get vdev");
1370 		return QDF_STATUS_E_INVAL;
1371 	}
1372 	req->vdev = vdev;
1373 	req->cancel_req.scan_id = INVAL_SCAN_ID;
1374 	req->cancel_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1375 	req->cancel_req.vdev_id = INVAL_VDEV_ID;
1376 	req->cancel_req.req_type = WLAN_SCAN_CANCEL_PDEV_ALL;
1377 	status = ucfg_scan_cancel_sync(req);
1378 	if (QDF_IS_STATUS_ERROR(status))
1379 		scm_err("Cancel scan request failed");
1380 	wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
1381 
1382 	return status;
1383 }
1384 
1385 #ifdef WLAN_PMO_ENABLE
1386 
1387 static QDF_STATUS
1388 ucfg_scan_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg)
1389 {
1390 	struct wlan_objmgr_pdev *pdev = NULL;
1391 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1392 	int i;
1393 
1394 	/* Check all pdev */
1395 	for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
1396 		pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_SCAN_ID);
1397 		if (!pdev)
1398 			continue;
1399 		if (ucfg_scan_get_pdev_status(pdev) !=
1400 		    SCAN_NOT_IN_PROGRESS)
1401 			status = ucfg_scan_cancel_pdev_scan(pdev);
1402 		wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID);
1403 		if (QDF_IS_STATUS_ERROR(status)) {
1404 			scm_err("failed to cancel scan for pdev_id %d", i);
1405 			return status;
1406 		}
1407 	}
1408 
1409 	return QDF_STATUS_SUCCESS;
1410 }
1411 
1412 static QDF_STATUS
1413 ucfg_scan_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg)
1414 {
1415 	return QDF_STATUS_SUCCESS;
1416 }
1417 
1418 static inline void
1419 ucfg_scan_register_pmo_handler(void)
1420 {
1421 	pmo_register_suspend_handler(WLAN_UMAC_COMP_SCAN,
1422 		ucfg_scan_suspend_handler, NULL);
1423 	pmo_register_resume_handler(WLAN_UMAC_COMP_SCAN,
1424 		ucfg_scan_resume_handler, NULL);
1425 }
1426 
1427 static inline void
1428 ucfg_scan_unregister_pmo_handler(void)
1429 {
1430 	pmo_unregister_suspend_handler(WLAN_UMAC_COMP_SCAN,
1431 		ucfg_scan_suspend_handler);
1432 	pmo_unregister_resume_handler(WLAN_UMAC_COMP_SCAN,
1433 		ucfg_scan_resume_handler);
1434 }
1435 
1436 #else
1437 static inline void
1438 ucfg_scan_register_pmo_handler(void)
1439 {
1440 }
1441 
1442 static inline void
1443 ucfg_scan_unregister_pmo_handler(void)
1444 {
1445 }
1446 #endif
1447 
1448 QDF_STATUS
1449 ucfg_scan_psoc_open(struct wlan_objmgr_psoc *psoc)
1450 {
1451 	struct wlan_scan_obj *scan_obj;
1452 
1453 	scm_info("psoc open: 0x%pK", psoc);
1454 	if (!psoc) {
1455 		scm_err("null psoc");
1456 		return QDF_STATUS_E_FAILURE;
1457 	}
1458 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1459 	if (scan_obj == NULL) {
1460 		scm_err("Failed to get scan object");
1461 		return QDF_STATUS_E_FAILURE;
1462 	}
1463 	/* Initialize the scan Globals */
1464 	wlan_scan_global_init(scan_obj);
1465 	qdf_spinlock_create(&scan_obj->lock);
1466 	ucfg_scan_register_pmo_handler();
1467 
1468 	return QDF_STATUS_SUCCESS;
1469 }
1470 
1471 QDF_STATUS
1472 ucfg_scan_psoc_close(struct wlan_objmgr_psoc *psoc)
1473 {
1474 	struct wlan_scan_obj *scan_obj;
1475 
1476 	scm_info("psoc close: 0x%pK", psoc);
1477 	if (!psoc) {
1478 		scm_err("null psoc");
1479 		return QDF_STATUS_E_FAILURE;
1480 	}
1481 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1482 	if (scan_obj == NULL) {
1483 		scm_err("Failed to get scan object");
1484 		return QDF_STATUS_E_FAILURE;
1485 	}
1486 	ucfg_scan_unregister_pmo_handler();
1487 	qdf_spinlock_destroy(&scan_obj->lock);
1488 	wlan_pno_global_deinit(&scan_obj->pno_cfg);
1489 
1490 	return QDF_STATUS_SUCCESS;
1491 }
1492 
1493 static bool scm_serialization_scan_rules_cb(
1494 		union wlan_serialization_rules_info *comp_info,
1495 		uint8_t comp_id)
1496 {
1497 	switch (comp_id) {
1498 	case WLAN_UMAC_COMP_TDLS:
1499 		if (comp_info->scan_info.is_tdls_in_progress) {
1500 			scm_info("Cancel scan. Tdls in progress");
1501 			return false;
1502 		}
1503 		break;
1504 	case WLAN_UMAC_COMP_DFS:
1505 		if (comp_info->scan_info.is_cac_in_progress) {
1506 			scm_info("Cancel scan. CAC in progress");
1507 			return false;
1508 		}
1509 		break;
1510 	default:
1511 		scm_info("not handled comp_id %d", comp_id);
1512 		break;
1513 	}
1514 
1515 	return true;
1516 }
1517 
1518 QDF_STATUS
1519 ucfg_scan_psoc_enable(struct wlan_objmgr_psoc *psoc)
1520 {
1521 	QDF_STATUS status;
1522 
1523 	scm_info("psoc enable: 0x%pK", psoc);
1524 	if (!psoc) {
1525 		scm_err("null psoc");
1526 		return QDF_STATUS_E_FAILURE;
1527 	}
1528 	/* Subscribe for scan events from lmac layesr */
1529 	status = tgt_scan_register_ev_handler(psoc);
1530 	QDF_ASSERT(status == QDF_STATUS_SUCCESS);
1531 	scm_db_init(psoc);
1532 	ucfg_scan_register_unregister_bcn_cb(psoc, true);
1533 	status = wlan_serialization_register_apply_rules_cb(psoc,
1534 				WLAN_SER_CMD_SCAN,
1535 				scm_serialization_scan_rules_cb);
1536 	QDF_ASSERT(status == QDF_STATUS_SUCCESS);
1537 	return status;
1538 }
1539 
1540 QDF_STATUS
1541 ucfg_scan_psoc_disable(struct wlan_objmgr_psoc *psoc)
1542 {
1543 	QDF_STATUS status;
1544 
1545 	scm_info("psoc disable: 0x%pK", psoc);
1546 	if (!psoc) {
1547 		scm_err("null psoc");
1548 		return QDF_STATUS_E_FAILURE;
1549 	}
1550 	/* Unsubscribe for scan events from lmac layesr */
1551 	status = tgt_scan_unregister_ev_handler(psoc);
1552 	QDF_ASSERT(status == QDF_STATUS_SUCCESS);
1553 	ucfg_scan_register_unregister_bcn_cb(psoc, false);
1554 	scm_db_deinit(psoc);
1555 
1556 	return status;
1557 }
1558 
1559 uint32_t
1560 ucfg_scan_get_max_active_scans(struct wlan_objmgr_psoc *psoc)
1561 {
1562 	struct scan_default_params *scan_params = NULL;
1563 
1564 	if (!psoc) {
1565 		scm_err("null psoc");
1566 		return 0;
1567 	}
1568 	scan_params = wlan_scan_psoc_get_def_params(psoc);
1569 
1570 	return scan_params->max_active_scans_allowed;
1571 }
1572 
1573 bool ucfg_copy_ie_whitelist_attrs(struct wlan_objmgr_psoc *psoc,
1574 				  struct probe_req_whitelist_attr *ie_whitelist)
1575 {
1576 	struct wlan_scan_obj *scan_obj = NULL;
1577 
1578 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1579 	if (!scan_obj)
1580 		return false;
1581 
1582 	qdf_mem_copy(ie_whitelist, &scan_obj->ie_whitelist,
1583 		     sizeof(*ie_whitelist));
1584 
1585 	return true;
1586 }
1587 
1588 bool ucfg_ie_whitelist_enabled(struct wlan_objmgr_psoc *psoc,
1589 			       struct wlan_objmgr_vdev *vdev)
1590 {
1591 	struct wlan_scan_obj *scan_obj = NULL;
1592 
1593 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1594 	if (!scan_obj)
1595 		return false;
1596 
1597 	if ((wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) ||
1598 	    wlan_vdev_is_connected(vdev))
1599 		return false;
1600 
1601 	if (!scan_obj->ie_whitelist.white_list)
1602 		return false;
1603 
1604 	return true;
1605 }
1606