1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * DOC: This file contains all SCAN component's APIs
22  */
23 
24 #include "cfg_ucfg_api.h"
25 #include "wlan_scan_api.h"
26 #include "../../core/src/wlan_scan_manager.h"
27 #ifdef WLAN_POLICY_MGR_ENABLE
28 #include <wlan_policy_mgr_api.h>
29 #include "wlan_policy_mgr_public_struct.h"
30 #endif
31 
wlan_scan_cfg_get_passive_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t * dwell_time)32 void wlan_scan_cfg_get_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
33 					 uint32_t *dwell_time)
34 {
35 	struct wlan_scan_obj *scan_obj;
36 
37 	scan_obj = wlan_psoc_get_scan_obj(psoc);
38 	if (!scan_obj)
39 		return;
40 	*dwell_time = scan_obj->scan_def.passive_dwell;
41 }
42 
wlan_scan_cfg_set_passive_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t dwell_time)43 void wlan_scan_cfg_set_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
44 					 uint32_t dwell_time)
45 {
46 	struct wlan_scan_obj *scan_obj;
47 
48 	scan_obj = wlan_psoc_get_scan_obj(psoc);
49 	if (!scan_obj)
50 		return;
51 	scan_obj->scan_def.passive_dwell = dwell_time;
52 }
53 
wlan_scan_cfg_get_active_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t * dwell_time)54 void wlan_scan_cfg_get_active_dwelltime(struct wlan_objmgr_psoc *psoc,
55 					uint32_t *dwell_time)
56 {
57 	struct wlan_scan_obj *scan_obj;
58 
59 	scan_obj = wlan_psoc_get_scan_obj(psoc);
60 	if (!scan_obj)
61 		return;
62 	*dwell_time = scan_obj->scan_def.active_dwell;
63 }
64 
wlan_scan_cfg_set_active_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t dwell_time)65 void wlan_scan_cfg_set_active_dwelltime(struct wlan_objmgr_psoc *psoc,
66 					uint32_t dwell_time)
67 {
68 	struct wlan_scan_obj *scan_obj;
69 
70 	scan_obj = wlan_psoc_get_scan_obj(psoc);
71 	if (!scan_obj)
72 		return;
73 	scan_obj->scan_def.active_dwell = dwell_time;
74 }
75 
wlan_scan_cfg_get_active_2g_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t * dwell_time)76 void wlan_scan_cfg_get_active_2g_dwelltime(struct wlan_objmgr_psoc *psoc,
77 					   uint32_t *dwell_time)
78 {
79 	struct wlan_scan_obj *scan_obj;
80 
81 	scan_obj = wlan_psoc_get_scan_obj(psoc);
82 	if (!scan_obj)
83 		return;
84 
85 	*dwell_time = scan_obj->scan_def.active_dwell_2g;
86 }
87 
wlan_scan_cfg_set_active_2g_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t dwell_time)88 void wlan_scan_cfg_set_active_2g_dwelltime(struct wlan_objmgr_psoc *psoc,
89 					   uint32_t dwell_time)
90 {
91 	struct wlan_scan_obj *scan_obj;
92 
93 	scan_obj = wlan_psoc_get_scan_obj(psoc);
94 	if (!scan_obj)
95 		return;
96 	scan_obj->scan_def.active_dwell_2g = dwell_time;
97 }
98 
99 #ifdef CONFIG_BAND_6GHZ
wlan_scan_cfg_get_active_6g_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t * dwell_time)100 QDF_STATUS wlan_scan_cfg_get_active_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
101 						 uint32_t *dwell_time)
102 {
103 	struct wlan_scan_obj *scan_obj;
104 
105 	scan_obj = wlan_psoc_get_scan_obj(psoc);
106 	if (!scan_obj)
107 		return QDF_STATUS_E_INVAL;
108 
109 	*dwell_time = scan_obj->scan_def.active_dwell_6g;
110 
111 	return QDF_STATUS_SUCCESS;
112 }
113 
wlan_scan_cfg_set_active_6g_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t dwell_time)114 QDF_STATUS wlan_scan_cfg_set_active_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
115 						 uint32_t dwell_time)
116 {
117 	struct wlan_scan_obj *scan_obj;
118 
119 	scan_obj = wlan_psoc_get_scan_obj(psoc);
120 	if (!scan_obj)
121 		return QDF_STATUS_E_INVAL;
122 
123 	scan_obj->scan_def.active_dwell_6g = dwell_time;
124 
125 	return QDF_STATUS_SUCCESS;
126 }
127 
wlan_scan_cfg_get_passive_6g_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t * dwell_time)128 QDF_STATUS wlan_scan_cfg_get_passive_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
129 						  uint32_t *dwell_time)
130 {
131 	struct wlan_scan_obj *scan_obj;
132 
133 	scan_obj = wlan_psoc_get_scan_obj(psoc);
134 	if (!scan_obj)
135 		return QDF_STATUS_E_INVAL;
136 
137 	*dwell_time = scan_obj->scan_def.passive_dwell_6g;
138 
139 	return QDF_STATUS_SUCCESS;
140 }
141 
wlan_scan_cfg_set_passive_6g_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t dwell_time)142 QDF_STATUS wlan_scan_cfg_set_passive_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
143 						  uint32_t dwell_time)
144 {
145 	struct wlan_scan_obj *scan_obj;
146 
147 	scan_obj = wlan_psoc_get_scan_obj(psoc);
148 	if (!scan_obj)
149 		return QDF_STATUS_E_INVAL;
150 
151 	scan_obj->scan_def.passive_dwell_6g = dwell_time;
152 
153 	return QDF_STATUS_SUCCESS;
154 }
155 
wlan_scan_cfg_get_min_dwelltime_6g(struct wlan_objmgr_psoc * psoc,uint32_t * min_dwell_time_6ghz)156 void wlan_scan_cfg_get_min_dwelltime_6g(struct wlan_objmgr_psoc *psoc,
157 					uint32_t *min_dwell_time_6ghz)
158 {
159 	struct wlan_scan_obj *scan_obj;
160 
161 	scan_obj = wlan_psoc_get_scan_obj(psoc);
162 	if (!scan_obj)
163 		return;
164 	*min_dwell_time_6ghz = scan_obj->scan_def.min_dwell_time_6g;
165 }
166 
wlan_scan_cfg_set_scan_mode_6g(struct wlan_objmgr_psoc * psoc,enum scan_mode_6ghz scan_mode_6g)167 QDF_STATUS wlan_scan_cfg_set_scan_mode_6g(struct wlan_objmgr_psoc *psoc,
168 					  enum scan_mode_6ghz scan_mode_6g)
169 {
170 	struct wlan_scan_obj *scan_obj;
171 
172 	scan_obj = wlan_psoc_get_scan_obj(psoc);
173 	if (!scan_obj)
174 		return QDF_STATUS_E_INVAL;
175 
176 	scan_obj->scan_def.scan_mode_6g = scan_mode_6g;
177 
178 	return QDF_STATUS_SUCCESS;
179 }
180 #endif
181 
182 #ifdef WLAN_POLICY_MGR_ENABLE
wlan_scan_update_pno_dwell_time(struct wlan_objmgr_vdev * vdev,struct pno_scan_req_params * req,struct scan_default_params * scan_def)183 void wlan_scan_update_pno_dwell_time(struct wlan_objmgr_vdev *vdev,
184 				     struct pno_scan_req_params *req,
185 				     struct scan_default_params *scan_def)
186 {
187 	bool sap_or_p2p_present;
188 	struct wlan_objmgr_psoc *psoc;
189 
190 	psoc = wlan_vdev_get_psoc(vdev);
191 
192 	if (!psoc)
193 		return;
194 
195 	sap_or_p2p_present = policy_mgr_get_beaconing_mode_count(psoc, NULL) ||
196 				policy_mgr_mode_specific_connection_count
197 			       (psoc,
198 				PM_P2P_CLIENT_MODE, NULL);
199 
200 	if (sap_or_p2p_present) {
201 		req->active_dwell_time = scan_def->conc_active_dwell;
202 		req->passive_dwell_time = scan_def->conc_passive_dwell;
203 	}
204 }
205 #endif
206 
wlan_scan_cfg_get_conc_active_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t * dwell_time)207 void wlan_scan_cfg_get_conc_active_dwelltime(struct wlan_objmgr_psoc *psoc,
208 					     uint32_t *dwell_time)
209 {
210 	struct wlan_scan_obj *scan_obj;
211 
212 	scan_obj = wlan_psoc_get_scan_obj(psoc);
213 	if (!scan_obj)
214 		return;
215 
216 	*dwell_time = scan_obj->scan_def.conc_active_dwell;
217 }
218 
wlan_scan_cfg_set_conc_active_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t dwell_time)219 void wlan_scan_cfg_set_conc_active_dwelltime(struct wlan_objmgr_psoc *psoc,
220 					     uint32_t dwell_time)
221 {
222 	struct wlan_scan_obj *scan_obj;
223 
224 	scan_obj = wlan_psoc_get_scan_obj(psoc);
225 	if (!scan_obj)
226 		return;
227 
228 	scan_obj->scan_def.conc_active_dwell = dwell_time;
229 }
230 
wlan_scan_cfg_get_conc_passive_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t * dwell_time)231 void wlan_scan_cfg_get_conc_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
232 					      uint32_t *dwell_time)
233 {
234 	struct wlan_scan_obj *scan_obj;
235 
236 	scan_obj = wlan_psoc_get_scan_obj(psoc);
237 	if (!scan_obj)
238 		return;
239 
240 	*dwell_time = scan_obj->scan_def.conc_passive_dwell;
241 }
242 
wlan_scan_cfg_set_conc_passive_dwelltime(struct wlan_objmgr_psoc * psoc,uint32_t dwell_time)243 void wlan_scan_cfg_set_conc_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
244 					      uint32_t dwell_time)
245 {
246 	struct wlan_scan_obj *scan_obj;
247 
248 	scan_obj = wlan_psoc_get_scan_obj(psoc);
249 	if (!scan_obj)
250 		return;
251 
252 	scan_obj->scan_def.conc_passive_dwell = dwell_time;
253 }
254 
255 void
wlan_scan_cfg_get_dfs_chan_scan_allowed(struct wlan_objmgr_psoc * psoc,bool * enable_dfs_scan)256 wlan_scan_cfg_get_dfs_chan_scan_allowed(struct wlan_objmgr_psoc *psoc,
257 					bool *enable_dfs_scan)
258 {
259 	struct wlan_scan_obj *scan_obj;
260 
261 	scan_obj = wlan_psoc_get_scan_obj(psoc);
262 	if (!scan_obj)
263 		return;
264 
265 	*enable_dfs_scan = scan_obj->scan_def.allow_dfs_chan_in_scan;
266 }
267 
268 void
wlan_scan_cfg_set_dfs_chan_scan_allowed(struct wlan_objmgr_psoc * psoc,bool enable_dfs_scan)269 wlan_scan_cfg_set_dfs_chan_scan_allowed(struct wlan_objmgr_psoc *psoc,
270 					bool enable_dfs_scan)
271 {
272 	struct wlan_scan_obj *scan_obj;
273 
274 	scan_obj = wlan_psoc_get_scan_obj(psoc);
275 	if (!scan_obj)
276 		return;
277 
278 	scan_obj->scan_def.allow_dfs_chan_in_scan = enable_dfs_scan;
279 }
280 
wlan_scan_cfg_honour_nl_scan_policy_flags(struct wlan_objmgr_psoc * psoc)281 bool wlan_scan_cfg_honour_nl_scan_policy_flags(struct wlan_objmgr_psoc *psoc)
282 {
283 	struct wlan_scan_obj *scan_obj;
284 
285 	scan_obj = wlan_psoc_get_scan_obj(psoc);
286 	if (!scan_obj)
287 		return false;
288 
289 	return scan_obj->scan_def.honour_nl_scan_policy_flags;
290 }
291 
wlan_scan_cfg_get_conc_max_resttime(struct wlan_objmgr_psoc * psoc,uint32_t * rest_time)292 void wlan_scan_cfg_get_conc_max_resttime(struct wlan_objmgr_psoc *psoc,
293 					 uint32_t *rest_time)
294 {
295 	struct wlan_scan_obj *scan_obj;
296 
297 	scan_obj = wlan_psoc_get_scan_obj(psoc);
298 	if (!scan_obj)
299 		return;
300 
301 	*rest_time = scan_obj->scan_def.conc_max_rest_time;
302 }
303 
wlan_scan_cfg_get_conc_min_resttime(struct wlan_objmgr_psoc * psoc,uint32_t * rest_time)304 void wlan_scan_cfg_get_conc_min_resttime(struct wlan_objmgr_psoc *psoc,
305 					 uint32_t *rest_time)
306 {
307 	struct wlan_scan_obj *scan_obj;
308 
309 	scan_obj = wlan_psoc_get_scan_obj(psoc);
310 	if (!scan_obj)
311 		return;
312 
313 	*rest_time = scan_obj->scan_def.conc_min_rest_time;
314 }
315 
wlan_scan_is_snr_monitor_enabled(struct wlan_objmgr_psoc * psoc)316 bool wlan_scan_is_snr_monitor_enabled(struct wlan_objmgr_psoc *psoc)
317 {
318 	struct wlan_scan_obj *scan_obj;
319 
320 	scan_obj = wlan_psoc_get_scan_obj(psoc);
321 	if (!scan_obj)
322 		return cfg_default(CFG_ENABLE_SNR_MONITORING);
323 
324 	return scan_obj->scan_def.scan_f_chan_stat_evnt;
325 }
326 
327 QDF_STATUS
wlan_scan_process_bcn_probe_rx_sync(struct wlan_objmgr_psoc * psoc,qdf_nbuf_t buf,struct mgmt_rx_event_params * rx_param,enum mgmt_frame_type frm_type)328 wlan_scan_process_bcn_probe_rx_sync(struct wlan_objmgr_psoc *psoc,
329 				    qdf_nbuf_t buf,
330 				    struct mgmt_rx_event_params *rx_param,
331 				    enum mgmt_frame_type frm_type)
332 {
333 	struct scan_bcn_probe_event *bcn = NULL;
334 	QDF_STATUS status;
335 
336 	if ((frm_type != MGMT_PROBE_RESP) &&
337 	    (frm_type != MGMT_BEACON)) {
338 		scm_err("frame is not beacon or probe resp");
339 		status = QDF_STATUS_E_INVAL;
340 		goto free;
341 	}
342 
343 	bcn = qdf_mem_malloc_atomic(sizeof(*bcn));
344 	if (!bcn) {
345 		status = QDF_STATUS_E_NOMEM;
346 		goto free;
347 	}
348 	bcn->rx_data =
349 		qdf_mem_malloc_atomic(sizeof(*rx_param));
350 	if (!bcn->rx_data) {
351 		status = QDF_STATUS_E_NOMEM;
352 		goto free;
353 	}
354 
355 	if (frm_type == MGMT_PROBE_RESP)
356 		bcn->frm_type = MGMT_SUBTYPE_PROBE_RESP;
357 	else
358 		bcn->frm_type = MGMT_SUBTYPE_BEACON;
359 
360 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_SCAN_ID);
361 	if (QDF_IS_STATUS_ERROR(status)) {
362 		scm_info("unable to get reference");
363 		goto free;
364 	}
365 
366 	bcn->psoc = psoc;
367 	bcn->buf = buf;
368 
369 	/*
370 	 * Save the rnr entries from the frame into rnr db.
371 	 * The RNR entry would have the partner links as well.
372 	 * If the partner link is a non-tx profile, and if there
373 	 * is no MBSSID info for that partner link, then look up
374 	 * into the rnr db will help to identify if that partner
375 	 * is a non-tx profile.
376 	 */
377 	bcn->save_rnr_info = true;
378 	qdf_mem_copy(bcn->rx_data, rx_param, sizeof(*rx_param));
379 
380 	return __scm_handle_bcn_probe(bcn);
381 free:
382 	if (bcn && bcn->rx_data)
383 		qdf_mem_free(bcn->rx_data);
384 	if (bcn)
385 		qdf_mem_free(bcn);
386 	if (buf)
387 		qdf_nbuf_free(buf);
388 
389 	return status;
390 }
391 
wlan_scan_get_aging_time(struct wlan_objmgr_psoc * psoc)392 qdf_time_t wlan_scan_get_aging_time(struct wlan_objmgr_psoc *psoc)
393 {
394 	struct wlan_scan_obj *scan_obj;
395 
396 	scan_obj = wlan_psoc_get_scan_obj(psoc);
397 	if (!scan_obj)
398 		return cfg_default(CFG_SCAN_AGING_TIME) * 1000;
399 
400 	return scan_obj->scan_def.scan_cache_aging_time;
401 }
402 
wlan_scan_set_aging_time(struct wlan_objmgr_psoc * psoc,qdf_time_t time)403 QDF_STATUS wlan_scan_set_aging_time(struct wlan_objmgr_psoc *psoc,
404 				    qdf_time_t time)
405 {
406 	struct wlan_scan_obj *scan_obj;
407 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
408 
409 	scan_obj = wlan_psoc_get_scan_obj(psoc);
410 	if (!scan_obj)
411 		return status;
412 
413 	if (!cfg_in_range(CFG_SCAN_AGING_TIME, time / 1000)) {
414 		status = QDF_STATUS_E_RANGE;
415 		return status;
416 	}
417 
418 	scan_obj->scan_def.scan_cache_aging_time = time;
419 	status = QDF_STATUS_SUCCESS;
420 	return status;
421 }
422 
wlan_scan_start(struct scan_start_request * req)423 QDF_STATUS wlan_scan_start(struct scan_start_request *req)
424 {
425 	struct scheduler_msg msg = {0};
426 	QDF_STATUS status;
427 
428 	if (!req || !req->vdev) {
429 		scm_err("req or vdev within req is NULL");
430 		scm_scan_free_scan_request_mem(req);
431 		return QDF_STATUS_E_NULL_VALUE;
432 	}
433 
434 	if (!scm_is_scan_allowed(req->vdev)) {
435 		scm_err_rl("scan disabled, rejecting the scan req");
436 		scm_scan_free_scan_request_mem(req);
437 		return QDF_STATUS_E_AGAIN;
438 	}
439 
440 	/*
441 	 * Try to get vdev reference. Return if reference could
442 	 * not be taken. Reference will be released once scan
443 	 * request handling completes along with free of @req.
444 	 */
445 	status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID);
446 	if (QDF_IS_STATUS_ERROR(status)) {
447 		scm_info("unable to get reference");
448 		scm_scan_free_scan_request_mem(req);
449 		return status;
450 	}
451 
452 	msg.bodyptr = req;
453 	msg.callback = scm_scan_start_req;
454 	msg.flush_callback = scm_scan_start_flush_callback;
455 
456 	status = scheduler_post_message(QDF_MODULE_ID_OS_IF,
457 					QDF_MODULE_ID_SCAN,
458 					QDF_MODULE_ID_OS_IF, &msg);
459 	if (QDF_IS_STATUS_ERROR(status)) {
460 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
461 		scm_scan_free_scan_request_mem(req);
462 	}
463 
464 	return status;
465 }
466 
wlan_scan_cancel(struct scan_cancel_request * req)467 QDF_STATUS wlan_scan_cancel(struct scan_cancel_request *req)
468 {
469 	struct scheduler_msg msg = {0};
470 	QDF_STATUS status;
471 
472 	if (!req || !req->vdev) {
473 		scm_err("req or vdev within req is NULL");
474 		if (req)
475 			qdf_mem_free(req);
476 		return QDF_STATUS_E_NULL_VALUE;
477 	}
478 
479 	status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID);
480 	if (QDF_IS_STATUS_ERROR(status)) {
481 		scm_info("Failed to get vdev ref; status:%d", status);
482 		goto req_free;
483 	}
484 
485 	msg.bodyptr = req;
486 	msg.callback = scm_scan_cancel_req;
487 	msg.flush_callback = scm_scan_cancel_flush_callback;
488 
489 	status = scheduler_post_message(QDF_MODULE_ID_OS_IF,
490 					QDF_MODULE_ID_SCAN,
491 					QDF_MODULE_ID_OS_IF, &msg);
492 	if (QDF_IS_STATUS_ERROR(status))
493 		goto vdev_put;
494 
495 	return QDF_STATUS_SUCCESS;
496 
497 vdev_put:
498 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
499 
500 req_free:
501 	qdf_mem_free(req);
502 
503 	return status;
504 }
505 
506 wlan_scan_id
wlan_scan_get_scan_id(struct wlan_objmgr_psoc * psoc)507 wlan_scan_get_scan_id(struct wlan_objmgr_psoc *psoc)
508 {
509 	wlan_scan_id id;
510 	struct wlan_scan_obj *scan;
511 
512 	if (!psoc) {
513 		QDF_ASSERT(0);
514 		scm_err("null psoc");
515 		return 0;
516 	}
517 
518 	scan = wlan_psoc_get_scan_obj(psoc);
519 	if (!scan) {
520 		scm_err("scan object null");
521 		return 0;
522 	}
523 
524 	id = qdf_atomic_inc_return(&scan->scan_ids);
525 	id =  id & WLAN_SCAN_ID_MASK;
526 	/* Mark this scan request as triggered by host
527 	 * by setting WLAN_HOST_SCAN_REQ_ID_PREFIX flag.
528 	 */
529 	id =  id | WLAN_HOST_SCAN_REQ_ID_PREFIX;
530 	scm_debug("scan_id: 0x%x", id);
531 
532 	return id;
533 }
534 
535 QDF_STATUS
wlan_scan_init_default_params(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)536 wlan_scan_init_default_params(struct wlan_objmgr_vdev *vdev,
537 			      struct scan_start_request *req)
538 {
539 	struct scan_default_params *def;
540 
541 	if (!vdev | !req) {
542 		scm_err("vdev: 0x%pK, req: 0x%pK", vdev, req);
543 		return QDF_STATUS_E_INVAL;
544 	}
545 	def = wlan_vdev_get_def_scan_params(vdev);
546 	if (!def) {
547 		scm_err("wlan_vdev_get_def_scan_params returned NULL");
548 		return QDF_STATUS_E_NULL_VALUE;
549 	}
550 
551 	/* Zero out everything and explicitly set fields as required */
552 	qdf_mem_zero(req, sizeof(*req));
553 
554 	req->vdev = vdev;
555 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
556 	req->scan_req.scan_type = SCAN_TYPE_DEFAULT;
557 	req->scan_req.scan_priority = def->scan_priority;
558 	req->scan_req.dwell_time_active = def->active_dwell;
559 	req->scan_req.dwell_time_active_2g = def->active_dwell_2g;
560 	req->scan_req.min_dwell_time_6g = def->min_dwell_time_6g;
561 	req->scan_req.dwell_time_active_6g = def->active_dwell_6g;
562 	req->scan_req.dwell_time_passive_6g = def->passive_dwell_6g;
563 	req->scan_req.dwell_time_passive = def->passive_dwell;
564 	req->scan_req.min_rest_time = def->min_rest_time;
565 	req->scan_req.max_rest_time = def->max_rest_time;
566 	req->scan_req.repeat_probe_time = def->repeat_probe_time;
567 	req->scan_req.probe_spacing_time = def->probe_spacing_time;
568 	req->scan_req.idle_time = def->idle_time;
569 	req->scan_req.max_scan_time = def->max_scan_time;
570 	req->scan_req.probe_delay = def->probe_delay;
571 	req->scan_req.burst_duration = def->burst_duration;
572 	req->scan_req.n_probes = def->num_probes;
573 	req->scan_req.adaptive_dwell_time_mode =
574 		def->adaptive_dwell_time_mode;
575 	req->scan_req.scan_flags = def->scan_flags;
576 	req->scan_req.scan_events = def->scan_events;
577 	req->scan_req.scan_random.randomize = def->enable_mac_spoofing;
578 
579 	return QDF_STATUS_SUCCESS;
580 }
581 
582 wlan_scan_requester
wlan_scan_register_requester(struct wlan_objmgr_psoc * psoc,uint8_t * name,scan_event_handler event_cb,void * arg)583 wlan_scan_register_requester(struct wlan_objmgr_psoc *psoc,
584 			     uint8_t *name,
585 			     scan_event_handler event_cb,
586 			     void *arg)
587 {
588 	int i, j;
589 	struct wlan_scan_obj *scan;
590 	struct scan_requester_info *requesters;
591 	wlan_scan_requester requester = {0};
592 
593 	if (!psoc) {
594 		scm_err("null psoc");
595 		return 0;
596 	}
597 	scan = wlan_psoc_get_scan_obj(psoc);
598 	if (!scan)
599 		return 0;
600 
601 	requesters = scan->requesters;
602 	qdf_spin_lock_bh(&scan->lock);
603 	for (i = 0; i < WLAN_MAX_REQUESTORS; ++i) {
604 		if (requesters[i].requester == 0) {
605 			requesters[i].requester =
606 				WLAN_SCAN_REQUESTER_ID_PREFIX | i;
607 			j = 0;
608 			while (name[j] && (j < (WLAN_MAX_MODULE_NAME - 1))) {
609 				requesters[i].module[j] = name[j];
610 				++j;
611 			}
612 			requesters[i].module[j] = 0;
613 			requesters[i].ev_handler.func = event_cb;
614 			requesters[i].ev_handler.arg = arg;
615 			requester = requesters[i].requester;
616 			break;
617 		}
618 	}
619 	qdf_spin_unlock_bh(&scan->lock);
620 	scm_debug("module: %s, event_cb: 0x%pK, arg: 0x%pK, reqid: %d",
621 		  name, event_cb, arg, requester);
622 
623 	return requester;
624 }
625 
626 void
wlan_scan_unregister_requester(struct wlan_objmgr_psoc * psoc,wlan_scan_requester requester)627 wlan_scan_unregister_requester(struct wlan_objmgr_psoc *psoc,
628 			       wlan_scan_requester requester)
629 {
630 	int idx;
631 	struct wlan_scan_obj *scan;
632 	struct scan_requester_info *requesters;
633 
634 	idx = requester & WLAN_SCAN_REQUESTER_ID_PREFIX;
635 	if (idx != WLAN_SCAN_REQUESTER_ID_PREFIX) {
636 		scm_err("prefix didn't match for requester id %d", requester);
637 		return;
638 	}
639 
640 	idx = requester & WLAN_SCAN_REQUESTER_ID_MASK;
641 	if (idx >= WLAN_MAX_REQUESTORS) {
642 		scm_err("requester id %d greater than max value", requester);
643 		return;
644 	}
645 
646 	if (!psoc) {
647 		scm_err("null psoc");
648 		return;
649 	}
650 	scan = wlan_psoc_get_scan_obj(psoc);
651 	if (!scan)
652 		return;
653 	requesters = scan->requesters;
654 	scm_debug("reqid: %d", requester);
655 
656 	qdf_spin_lock_bh(&scan->lock);
657 	requesters[idx].requester = 0;
658 	requesters[idx].module[0] = 0;
659 	requesters[idx].ev_handler.func = NULL;
660 	requesters[idx].ev_handler.arg = NULL;
661 	qdf_spin_unlock_bh(&scan->lock);
662 }
663 
wlan_scan_cfg_skip_6g_and_indoor_freq(struct wlan_objmgr_psoc * psoc)664 bool wlan_scan_cfg_skip_6g_and_indoor_freq(struct wlan_objmgr_psoc *psoc)
665 {
666 	struct wlan_scan_obj *scan_obj;
667 
668 	scan_obj = wlan_psoc_get_scan_obj(psoc);
669 	if (!scan_obj)
670 		return false;
671 
672 	return scan_obj->scan_def.skip_6g_and_indoor_freq;
673 }
674 
wlan_scan_get_last_scan_ageout_time(struct wlan_objmgr_psoc * psoc,uint32_t * last_scan_ageout_time)675 void wlan_scan_get_last_scan_ageout_time(struct wlan_objmgr_psoc *psoc,
676 					 uint32_t *last_scan_ageout_time)
677 {
678 	struct wlan_scan_obj *scan_obj;
679 
680 	scan_obj = wlan_psoc_get_scan_obj(psoc);
681 	if (!scan_obj) {
682 		*last_scan_ageout_time = 0;
683 		return;
684 	}
685 	*last_scan_ageout_time =
686 	scan_obj->scan_def.last_scan_ageout_time;
687 }
688 
689 #ifdef FEATURE_SET
690 /**
691  * wlan_scan_get_pno_scan_support() - Check if pno scan support is enabled
692  * @psoc: pointer to psoc object
693  *
694  * Return: pno scan_support_enabled flag
695  */
wlan_scan_get_pno_scan_support(struct wlan_objmgr_psoc * psoc)696 static bool wlan_scan_get_pno_scan_support(struct wlan_objmgr_psoc *psoc)
697 {
698 	struct wlan_scan_obj *scan_obj;
699 
700 	scan_obj = wlan_psoc_get_scan_obj(psoc);
701 	if (!scan_obj) {
702 		scm_err("NULL scan obj");
703 		return cfg_default(CFG_PNO_SCAN_SUPPORT);
704 	}
705 
706 	return scan_obj->pno_cfg.scan_support_enabled;
707 }
708 
709 /**
710  * wlan_scan_is_connected_scan_enabled() - API to get scan enabled after connect
711  * @psoc: pointer to psoc object
712  *
713  * Return: value.
714  */
wlan_scan_is_connected_scan_enabled(struct wlan_objmgr_psoc * psoc)715 static bool wlan_scan_is_connected_scan_enabled(struct wlan_objmgr_psoc *psoc)
716 {
717 	struct wlan_scan_obj *scan_obj;
718 
719 	scan_obj = wlan_psoc_get_scan_obj(psoc);
720 	if (!scan_obj) {
721 		scm_err("Failed to get scan object");
722 		return cfg_default(CFG_ENABLE_CONNECTED_SCAN);
723 	}
724 
725 	return scan_obj->scan_def.enable_connected_scan;
726 }
727 
wlan_scan_get_feature_info(struct wlan_objmgr_psoc * psoc,struct wlan_scan_features * scan_feature_set)728 void wlan_scan_get_feature_info(struct wlan_objmgr_psoc *psoc,
729 				struct wlan_scan_features *scan_feature_set)
730 {
731 	scan_feature_set->pno_in_unassoc_state =
732 					wlan_scan_get_pno_scan_support(psoc);
733 	if (scan_feature_set->pno_in_unassoc_state)
734 		scan_feature_set->pno_in_assoc_state =
735 				wlan_scan_is_connected_scan_enabled(psoc);
736 }
737 #endif
738 
739 #ifdef WLAN_POLICY_MGR_ENABLE
740 /**
741  * wlan_scan_update_hint_bssid() - Update rnr hint bssid info
742  * @psoc: objmgr psoc
743  * @req: Scan request
744  * @ll_sap_freq: ll sap freq
745  *
746  * Use to update hint_bssid if low latency Sap is UP
747  *
748  * Return: void
749  */
750 static void
wlan_scan_update_hint_bssid(struct wlan_objmgr_psoc * psoc,struct scan_start_request * req,qdf_freq_t ll_sap_freq)751 wlan_scan_update_hint_bssid(struct wlan_objmgr_psoc *psoc,
752 			    struct scan_start_request *req,
753 			    qdf_freq_t ll_sap_freq)
754 {
755 	struct hint_bssid hint_bssid[WLAN_SCAN_MAX_HINT_BSSID] = {0};
756 	uint32_t i;
757 	uint32_t count = 0;
758 	qdf_freq_t freq;
759 
760 	if (!req->scan_req.num_hint_bssid)
761 		return;
762 
763 	for (i = 0; i < req->scan_req.num_hint_bssid; i++) {
764 		freq = req->scan_req.hint_bssid[i].freq_flags >> 16;
765 		if (!freq)
766 			continue;
767 		if (!policy_mgr_2_freq_always_on_same_mac(psoc,
768 							  ll_sap_freq,
769 							  freq)) {
770 			qdf_mem_copy(
771 				&hint_bssid[count].bssid,
772 				&req->scan_req.hint_bssid[i].bssid,
773 				sizeof(hint_bssid[i].bssid));
774 			hint_bssid[count].freq_flags =
775 				req->scan_req.hint_bssid[i].freq_flags;
776 			count++;
777 		}
778 	}
779 	qdf_mem_zero(req->scan_req.hint_bssid,
780 		     sizeof(req->scan_req.hint_bssid));
781 	if (count)
782 		qdf_mem_copy(req->scan_req.hint_bssid, hint_bssid,
783 			     sizeof(hint_bssid));
784 	req->scan_req.num_hint_bssid = count;
785 }
786 
787 /**
788  * wlan_scan_update_hint_s_ssid() - Update rnr hint short ssid info
789  * @psoc: objmgr psoc
790  * @req: Scan request
791  * @ll_sap_freq: ll sap freq
792  *
793  * Use to update hint_s_ssid if low latency Sap is UP
794  *
795  * Return: void
796  */
797 static
wlan_scan_update_hint_s_ssid(struct wlan_objmgr_psoc * psoc,struct scan_start_request * req,qdf_freq_t ll_sap_freq)798 void wlan_scan_update_hint_s_ssid(struct wlan_objmgr_psoc *psoc,
799 				  struct scan_start_request *req,
800 				  qdf_freq_t ll_sap_freq)
801 {
802 	struct hint_short_ssid hint_s_ssid[WLAN_SCAN_MAX_HINT_BSSID] = {0};
803 	uint32_t i;
804 	uint32_t count = 0;
805 	qdf_freq_t freq;
806 
807 	if (!req->scan_req.num_hint_s_ssid)
808 		return;
809 
810 	for (i = 0; i < req->scan_req.num_hint_s_ssid; i++) {
811 		freq = req->scan_req.hint_s_ssid[i].freq_flags >> 16;
812 		if (!freq)
813 			continue;
814 		if (!policy_mgr_2_freq_always_on_same_mac(psoc,
815 							  ll_sap_freq,
816 							  freq)) {
817 			qdf_mem_copy(
818 				&hint_s_ssid[count].short_ssid,
819 				&req->scan_req.hint_s_ssid[i].short_ssid,
820 				sizeof(hint_s_ssid[i].short_ssid));
821 			hint_s_ssid[count].freq_flags =
822 				req->scan_req.hint_s_ssid[i].freq_flags;
823 			count++;
824 		}
825 	}
826 	qdf_mem_zero(req->scan_req.hint_s_ssid,
827 		     sizeof(req->scan_req.hint_s_ssid));
828 	if (count)
829 		qdf_mem_copy(req->scan_req.hint_s_ssid, hint_s_ssid,
830 			     sizeof(hint_s_ssid));
831 	req->scan_req.num_hint_s_ssid = count;
832 }
833 
wlan_scan_update_low_latency_profile_chnlist(struct wlan_objmgr_vdev * vdev,struct scan_start_request * req)834 void wlan_scan_update_low_latency_profile_chnlist(
835 				struct wlan_objmgr_vdev *vdev,
836 				struct scan_start_request *req)
837 {
838 	uint32_t num_scan_channels = 0, i;
839 	struct wlan_objmgr_psoc *psoc;
840 	qdf_freq_t freq, ll_sap_freq;
841 
842 	psoc = wlan_vdev_get_psoc(vdev);
843 	if (!psoc) {
844 		scm_err("psoc is null");
845 		return;
846 	}
847 
848 /*
849  * Get ll_sap freq api will be cleaned up once macro is enabled
850  */
851 #ifndef WLAN_FEATURE_LL_LT_SAP
852 	ll_sap_freq = policy_mgr_get_ll_sap_freq(psoc);
853 #else
854 	ll_sap_freq = policy_mgr_get_ll_ht_sap_freq(psoc);
855 #endif
856 
857 	if (!ll_sap_freq)
858 		return;
859 
860 	wlan_scan_update_hint_bssid(psoc, req, ll_sap_freq);
861 	wlan_scan_update_hint_s_ssid(psoc, req, ll_sap_freq);
862 	/*
863 	 * Scenario: LL SAP is present and scan is requested.
864 	 * Allow scan on freq on mutually exclusive mac.
865 	 */
866 	for (i = 0; i < req->scan_req.chan_list.num_chan; i++) {
867 		freq = req->scan_req.chan_list.chan[i].freq;
868 		if (policy_mgr_2_freq_always_on_same_mac(psoc,
869 							 ll_sap_freq,
870 							 freq))
871 			continue;
872 
873 		req->scan_req.chan_list.chan[num_scan_channels++] =
874 					req->scan_req.chan_list.chan[i];
875 	}
876 	if (num_scan_channels < req->scan_req.chan_list.num_chan)
877 		scm_debug("For DBS: only 2.4Ghz chan and for SBS: mutually exclusive ll-sap 5GHz chan allowed, total-chan %d, remaining-chan %d, ll-sap chan %d",
878 			  req->scan_req.chan_list.num_chan,
879 			  num_scan_channels,
880 			  ll_sap_freq);
881 	req->scan_req.chan_list.num_chan = num_scan_channels;
882 }
883 #endif
884 
885 QDF_STATUS
wlan_scan_get_entry_by_mac_addr(struct wlan_objmgr_pdev * pdev,struct qdf_mac_addr * bssid,struct element_info * frame)886 wlan_scan_get_entry_by_mac_addr(struct wlan_objmgr_pdev *pdev,
887 				struct qdf_mac_addr *bssid,
888 				struct element_info *frame)
889 {
890 	return scm_scan_get_entry_by_mac_addr(pdev, bssid, frame);
891 }
892 
wlan_scan_register_mbssid_cb(struct wlan_objmgr_psoc * psoc,update_mbssid_bcn_prb_rsp cb)893 QDF_STATUS wlan_scan_register_mbssid_cb(struct wlan_objmgr_psoc *psoc,
894 					update_mbssid_bcn_prb_rsp cb)
895 {
896 	return scm_scan_register_mbssid_cb(psoc, cb);
897 }
898 
899 struct scan_cache_entry *
wlan_scan_get_entry_by_bssid(struct wlan_objmgr_pdev * pdev,struct qdf_mac_addr * bssid)900 wlan_scan_get_entry_by_bssid(struct wlan_objmgr_pdev *pdev,
901 			     struct qdf_mac_addr *bssid)
902 {
903 	return scm_scan_get_entry_by_bssid(pdev, bssid);
904 }
905 
906 QDF_STATUS
wlan_scan_get_mld_addr_by_link_addr(struct wlan_objmgr_pdev * pdev,struct qdf_mac_addr * link_addr,struct qdf_mac_addr * mld_mac_addr)907 wlan_scan_get_mld_addr_by_link_addr(struct wlan_objmgr_pdev *pdev,
908 				    struct qdf_mac_addr *link_addr,
909 				    struct qdf_mac_addr *mld_mac_addr)
910 {
911 	return scm_get_mld_addr_by_link_addr(pdev, link_addr, mld_mac_addr);
912 }
913 
914 struct scan_cache_entry *
wlan_scan_get_scan_entry_by_mac_freq(struct wlan_objmgr_pdev * pdev,struct qdf_mac_addr * bssid,uint16_t freq)915 wlan_scan_get_scan_entry_by_mac_freq(struct wlan_objmgr_pdev *pdev,
916 				     struct qdf_mac_addr *bssid,
917 				     uint16_t freq)
918 {
919 	return scm_scan_get_scan_entry_by_mac_freq(pdev, bssid, freq);
920 }
921 
wlan_scan_get_aux_support(struct wlan_objmgr_psoc * psoc)922 bool wlan_scan_get_aux_support(struct wlan_objmgr_psoc *psoc)
923 
924 {
925 	struct wlan_scan_obj *scan_obj;
926 
927 	scan_obj = wlan_psoc_get_scan_obj(psoc);
928 	if (!scan_obj)
929 		return false;
930 
931 	if (scan_obj->aux_mac_support)
932 		scm_debug("aux mac support: %d", scan_obj->aux_mac_support);
933 	else
934 		scm_debug("aux mac not supported");
935 
936 	return scan_obj->aux_mac_support;
937 }
938 
939