xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_api.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * DOC: This file contains all SCAN component's APIs
21  */
22 
23 #include "cfg_ucfg_api.h"
24 #include "wlan_scan_api.h"
25 #include "../../core/src/wlan_scan_manager.h"
26 
27 void wlan_scan_cfg_get_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
28 					 uint32_t *dwell_time)
29 {
30 	struct wlan_scan_obj *scan_obj;
31 
32 	scan_obj = wlan_psoc_get_scan_obj(psoc);
33 	if (!scan_obj)
34 		return;
35 	*dwell_time = scan_obj->scan_def.passive_dwell;
36 }
37 
38 void wlan_scan_cfg_set_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
39 					 uint32_t dwell_time)
40 {
41 	struct wlan_scan_obj *scan_obj;
42 
43 	scan_obj = wlan_psoc_get_scan_obj(psoc);
44 	if (!scan_obj)
45 		return;
46 	scan_obj->scan_def.passive_dwell = dwell_time;
47 }
48 
49 void wlan_scan_cfg_get_active_dwelltime(struct wlan_objmgr_psoc *psoc,
50 					uint32_t *dwell_time)
51 {
52 	struct wlan_scan_obj *scan_obj;
53 
54 	scan_obj = wlan_psoc_get_scan_obj(psoc);
55 	if (!scan_obj)
56 		return;
57 	*dwell_time = scan_obj->scan_def.active_dwell;
58 }
59 
60 void wlan_scan_cfg_set_active_dwelltime(struct wlan_objmgr_psoc *psoc,
61 					uint32_t dwell_time)
62 {
63 	struct wlan_scan_obj *scan_obj;
64 
65 	scan_obj = wlan_psoc_get_scan_obj(psoc);
66 	if (!scan_obj)
67 		return;
68 	scan_obj->scan_def.active_dwell = dwell_time;
69 }
70 
71 void wlan_scan_cfg_get_active_2g_dwelltime(struct wlan_objmgr_psoc *psoc,
72 					   uint32_t *dwell_time)
73 {
74 	struct wlan_scan_obj *scan_obj;
75 
76 	scan_obj = wlan_psoc_get_scan_obj(psoc);
77 	if (!scan_obj)
78 		return;
79 
80 	*dwell_time = scan_obj->scan_def.active_dwell_2g;
81 }
82 
83 void wlan_scan_cfg_set_active_2g_dwelltime(struct wlan_objmgr_psoc *psoc,
84 					   uint32_t dwell_time)
85 {
86 	struct wlan_scan_obj *scan_obj;
87 
88 	scan_obj = wlan_psoc_get_scan_obj(psoc);
89 	if (!scan_obj)
90 		return;
91 	scan_obj->scan_def.active_dwell_2g = dwell_time;
92 }
93 
94 #ifdef CONFIG_BAND_6GHZ
95 QDF_STATUS wlan_scan_cfg_get_active_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
96 						 uint32_t *dwell_time)
97 {
98 	struct wlan_scan_obj *scan_obj;
99 
100 	scan_obj = wlan_psoc_get_scan_obj(psoc);
101 	if (!scan_obj)
102 		return QDF_STATUS_E_INVAL;
103 
104 	*dwell_time = scan_obj->scan_def.active_dwell_6g;
105 
106 	return QDF_STATUS_SUCCESS;
107 }
108 
109 QDF_STATUS wlan_scan_cfg_set_active_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
110 						 uint32_t dwell_time)
111 {
112 	struct wlan_scan_obj *scan_obj;
113 
114 	scan_obj = wlan_psoc_get_scan_obj(psoc);
115 	if (!scan_obj)
116 		return QDF_STATUS_E_INVAL;
117 
118 	scan_obj->scan_def.active_dwell_6g = dwell_time;
119 
120 	return QDF_STATUS_SUCCESS;
121 }
122 
123 QDF_STATUS wlan_scan_cfg_get_passive_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
124 						  uint32_t *dwell_time)
125 {
126 	struct wlan_scan_obj *scan_obj;
127 
128 	scan_obj = wlan_psoc_get_scan_obj(psoc);
129 	if (!scan_obj)
130 		return QDF_STATUS_E_INVAL;
131 
132 	*dwell_time = scan_obj->scan_def.passive_dwell_6g;
133 
134 	return QDF_STATUS_SUCCESS;
135 }
136 
137 QDF_STATUS wlan_scan_cfg_set_passive_6g_dwelltime(struct wlan_objmgr_psoc *psoc,
138 						  uint32_t dwell_time)
139 {
140 	struct wlan_scan_obj *scan_obj;
141 
142 	scan_obj = wlan_psoc_get_scan_obj(psoc);
143 	if (!scan_obj)
144 		return QDF_STATUS_E_INVAL;
145 
146 	scan_obj->scan_def.passive_dwell_6g = dwell_time;
147 
148 	return QDF_STATUS_SUCCESS;
149 }
150 #endif
151 
152 void wlan_scan_cfg_get_conc_active_dwelltime(struct wlan_objmgr_psoc *psoc,
153 					     uint32_t *dwell_time)
154 {
155 	struct wlan_scan_obj *scan_obj;
156 
157 	scan_obj = wlan_psoc_get_scan_obj(psoc);
158 	if (!scan_obj)
159 		return;
160 
161 	*dwell_time = scan_obj->scan_def.conc_active_dwell;
162 }
163 
164 void wlan_scan_cfg_set_conc_active_dwelltime(struct wlan_objmgr_psoc *psoc,
165 					     uint32_t dwell_time)
166 {
167 	struct wlan_scan_obj *scan_obj;
168 
169 	scan_obj = wlan_psoc_get_scan_obj(psoc);
170 	if (!scan_obj)
171 		return;
172 
173 	scan_obj->scan_def.conc_active_dwell = dwell_time;
174 }
175 
176 void wlan_scan_cfg_get_conc_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
177 					      uint32_t *dwell_time)
178 {
179 	struct wlan_scan_obj *scan_obj;
180 
181 	scan_obj = wlan_psoc_get_scan_obj(psoc);
182 	if (!scan_obj)
183 		return;
184 
185 	*dwell_time = scan_obj->scan_def.conc_passive_dwell;
186 }
187 
188 void wlan_scan_cfg_set_conc_passive_dwelltime(struct wlan_objmgr_psoc *psoc,
189 					      uint32_t dwell_time)
190 {
191 	struct wlan_scan_obj *scan_obj;
192 
193 	scan_obj = wlan_psoc_get_scan_obj(psoc);
194 	if (!scan_obj)
195 		return;
196 
197 	scan_obj->scan_def.conc_passive_dwell = dwell_time;
198 }
199 
200 void
201 wlan_scan_cfg_get_dfs_chan_scan_allowed(struct wlan_objmgr_psoc *psoc,
202 					bool *enable_dfs_scan)
203 {
204 	struct wlan_scan_obj *scan_obj;
205 
206 	scan_obj = wlan_psoc_get_scan_obj(psoc);
207 	if (!scan_obj)
208 		return;
209 
210 	*enable_dfs_scan = scan_obj->scan_def.allow_dfs_chan_in_scan;
211 }
212 
213 void
214 wlan_scan_cfg_set_dfs_chan_scan_allowed(struct wlan_objmgr_psoc *psoc,
215 					bool enable_dfs_scan)
216 {
217 	struct wlan_scan_obj *scan_obj;
218 
219 	scan_obj = wlan_psoc_get_scan_obj(psoc);
220 	if (!scan_obj)
221 		return;
222 
223 	scan_obj->scan_def.allow_dfs_chan_in_scan = enable_dfs_scan;
224 }
225 
226 bool wlan_scan_cfg_honour_nl_scan_policy_flags(struct wlan_objmgr_psoc *psoc)
227 {
228 	struct wlan_scan_obj *scan_obj;
229 
230 	scan_obj = wlan_psoc_get_scan_obj(psoc);
231 	if (!scan_obj)
232 		return false;
233 
234 	return scan_obj->scan_def.honour_nl_scan_policy_flags;
235 }
236 
237 void wlan_scan_cfg_get_conc_max_resttime(struct wlan_objmgr_psoc *psoc,
238 					 uint32_t *rest_time)
239 {
240 	struct wlan_scan_obj *scan_obj;
241 
242 	scan_obj = wlan_psoc_get_scan_obj(psoc);
243 	if (!scan_obj)
244 		return;
245 
246 	*rest_time = scan_obj->scan_def.conc_max_rest_time;
247 }
248 
249 void wlan_scan_cfg_get_conc_min_resttime(struct wlan_objmgr_psoc *psoc,
250 					 uint32_t *rest_time)
251 {
252 	struct wlan_scan_obj *scan_obj;
253 
254 	scan_obj = wlan_psoc_get_scan_obj(psoc);
255 	if (!scan_obj)
256 		return;
257 
258 	*rest_time = scan_obj->scan_def.conc_min_rest_time;
259 }
260 
261 bool wlan_scan_is_snr_monitor_enabled(struct wlan_objmgr_psoc *psoc)
262 {
263 	struct wlan_scan_obj *scan_obj;
264 
265 	scan_obj = wlan_psoc_get_scan_obj(psoc);
266 	if (!scan_obj)
267 		return cfg_default(CFG_ENABLE_SNR_MONITORING);
268 
269 	return scan_obj->scan_def.scan_f_chan_stat_evnt;
270 }
271 
272 QDF_STATUS
273 wlan_scan_process_bcn_probe_rx_sync(struct wlan_objmgr_psoc *psoc,
274 				    qdf_nbuf_t buf,
275 				    struct mgmt_rx_event_params *rx_param,
276 				    enum mgmt_frame_type frm_type)
277 {
278 	struct scan_bcn_probe_event *bcn = NULL;
279 	QDF_STATUS status;
280 
281 	if ((frm_type != MGMT_PROBE_RESP) &&
282 	    (frm_type != MGMT_BEACON)) {
283 		scm_err("frame is not beacon or probe resp");
284 		status = QDF_STATUS_E_INVAL;
285 		goto free;
286 	}
287 
288 	bcn = qdf_mem_malloc_atomic(sizeof(*bcn));
289 	if (!bcn) {
290 		status = QDF_STATUS_E_NOMEM;
291 		goto free;
292 	}
293 	bcn->rx_data =
294 		qdf_mem_malloc_atomic(sizeof(*rx_param));
295 	if (!bcn->rx_data) {
296 		status = QDF_STATUS_E_NOMEM;
297 		goto free;
298 	}
299 
300 	if (frm_type == MGMT_PROBE_RESP)
301 		bcn->frm_type = MGMT_SUBTYPE_PROBE_RESP;
302 	else
303 		bcn->frm_type = MGMT_SUBTYPE_BEACON;
304 
305 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_SCAN_ID);
306 	if (QDF_IS_STATUS_ERROR(status)) {
307 		scm_info("unable to get reference");
308 		goto free;
309 	}
310 
311 	bcn->psoc = psoc;
312 	bcn->buf = buf;
313 	qdf_mem_copy(bcn->rx_data, rx_param, sizeof(*rx_param));
314 
315 	return __scm_handle_bcn_probe(bcn);
316 free:
317 	if (bcn && bcn->rx_data)
318 		qdf_mem_free(bcn->rx_data);
319 	if (bcn)
320 		qdf_mem_free(bcn);
321 	if (buf)
322 		qdf_nbuf_free(buf);
323 
324 	return status;
325 }
326 
327 qdf_time_t wlan_scan_get_aging_time(struct wlan_objmgr_psoc *psoc)
328 {
329 	struct wlan_scan_obj *scan_obj;
330 
331 	scan_obj = wlan_psoc_get_scan_obj(psoc);
332 	if (!scan_obj)
333 		return cfg_default(CFG_SCAN_AGING_TIME) * 1000;
334 
335 	return scan_obj->scan_def.scan_cache_aging_time;
336 }
337 
338 QDF_STATUS wlan_scan_start(struct scan_start_request *req)
339 {
340 	struct scheduler_msg msg = {0};
341 	QDF_STATUS status;
342 
343 	if (!req || !req->vdev) {
344 		scm_err("req or vdev within req is NULL");
345 		if (req)
346 			scm_scan_free_scan_request_mem(req);
347 		return QDF_STATUS_E_NULL_VALUE;
348 	}
349 
350 	if (!scm_is_scan_allowed(req->vdev)) {
351 		scm_err_rl("scan disabled, rejecting the scan req");
352 		scm_scan_free_scan_request_mem(req);
353 		return QDF_STATUS_E_AGAIN;
354 	}
355 
356 	/*
357 	 * Try to get vdev reference. Return if reference could
358 	 * not be taken. Reference will be released once scan
359 	 * request handling completes along with free of @req.
360 	 */
361 	status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID);
362 	if (QDF_IS_STATUS_ERROR(status)) {
363 		scm_info("unable to get reference");
364 		scm_scan_free_scan_request_mem(req);
365 		return status;
366 	}
367 
368 	msg.bodyptr = req;
369 	msg.callback = scm_scan_start_req;
370 	msg.flush_callback = scm_scan_start_flush_callback;
371 
372 	status = scheduler_post_message(QDF_MODULE_ID_OS_IF,
373 					QDF_MODULE_ID_SCAN,
374 					QDF_MODULE_ID_OS_IF, &msg);
375 	if (QDF_IS_STATUS_ERROR(status)) {
376 		wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
377 		scm_scan_free_scan_request_mem(req);
378 	}
379 
380 	return status;
381 }
382 
383 QDF_STATUS wlan_scan_cancel(struct scan_cancel_request *req)
384 {
385 	struct scheduler_msg msg = {0};
386 	QDF_STATUS status;
387 
388 	if (!req || !req->vdev) {
389 		scm_err("req or vdev within req is NULL");
390 		if (req)
391 			qdf_mem_free(req);
392 		return QDF_STATUS_E_NULL_VALUE;
393 	}
394 
395 	status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID);
396 	if (QDF_IS_STATUS_ERROR(status)) {
397 		scm_info("Failed to get vdev ref; status:%d", status);
398 		goto req_free;
399 	}
400 
401 	msg.bodyptr = req;
402 	msg.callback = scm_scan_cancel_req;
403 	msg.flush_callback = scm_scan_cancel_flush_callback;
404 
405 	status = scheduler_post_message(QDF_MODULE_ID_OS_IF,
406 					QDF_MODULE_ID_SCAN,
407 					QDF_MODULE_ID_OS_IF, &msg);
408 	if (QDF_IS_STATUS_ERROR(status))
409 		goto vdev_put;
410 
411 	return QDF_STATUS_SUCCESS;
412 
413 vdev_put:
414 	wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID);
415 
416 req_free:
417 	qdf_mem_free(req);
418 
419 	return status;
420 }
421 
422 wlan_scan_id
423 wlan_scan_get_scan_id(struct wlan_objmgr_psoc *psoc)
424 {
425 	wlan_scan_id id;
426 	struct wlan_scan_obj *scan;
427 
428 	if (!psoc) {
429 		QDF_ASSERT(0);
430 		scm_err("null psoc");
431 		return 0;
432 	}
433 
434 	scan = wlan_psoc_get_scan_obj(psoc);
435 	if (!scan) {
436 		scm_err("scan object null");
437 		return 0;
438 	}
439 
440 	id = qdf_atomic_inc_return(&scan->scan_ids);
441 	id =  id & WLAN_SCAN_ID_MASK;
442 	/* Mark this scan request as triggered by host
443 	 * by setting WLAN_HOST_SCAN_REQ_ID_PREFIX flag.
444 	 */
445 	id =  id | WLAN_HOST_SCAN_REQ_ID_PREFIX;
446 	scm_debug("scan_id: 0x%x", id);
447 
448 	return id;
449 }
450 
451 QDF_STATUS
452 wlan_scan_init_default_params(struct wlan_objmgr_vdev *vdev,
453 			      struct scan_start_request *req)
454 {
455 	struct scan_default_params *def;
456 
457 	if (!vdev | !req) {
458 		scm_err("vdev: 0x%pK, req: 0x%pK", vdev, req);
459 		return QDF_STATUS_E_INVAL;
460 	}
461 	def = wlan_vdev_get_def_scan_params(vdev);
462 	if (!def) {
463 		scm_err("wlan_vdev_get_def_scan_params returned NULL");
464 		return QDF_STATUS_E_NULL_VALUE;
465 	}
466 
467 	/* Zero out everything and explicitly set fields as required */
468 	qdf_mem_zero(req, sizeof(*req));
469 
470 	req->vdev = vdev;
471 	req->scan_req.vdev_id = wlan_vdev_get_id(vdev);
472 	req->scan_req.scan_type = SCAN_TYPE_DEFAULT;
473 	req->scan_req.scan_priority = def->scan_priority;
474 	req->scan_req.dwell_time_active = def->active_dwell;
475 	req->scan_req.dwell_time_active_2g = def->active_dwell_2g;
476 	req->scan_req.dwell_time_active_6g = def->active_dwell_6g;
477 	req->scan_req.dwell_time_passive_6g = def->passive_dwell_6g;
478 	req->scan_req.dwell_time_passive = def->passive_dwell;
479 	req->scan_req.min_rest_time = def->min_rest_time;
480 	req->scan_req.max_rest_time = def->max_rest_time;
481 	req->scan_req.repeat_probe_time = def->repeat_probe_time;
482 	req->scan_req.probe_spacing_time = def->probe_spacing_time;
483 	req->scan_req.idle_time = def->idle_time;
484 	req->scan_req.max_scan_time = def->max_scan_time;
485 	req->scan_req.probe_delay = def->probe_delay;
486 	req->scan_req.burst_duration = def->burst_duration;
487 	req->scan_req.n_probes = def->num_probes;
488 	req->scan_req.adaptive_dwell_time_mode =
489 		def->adaptive_dwell_time_mode;
490 	req->scan_req.scan_flags = def->scan_flags;
491 	req->scan_req.scan_events = def->scan_events;
492 	req->scan_req.scan_random.randomize = def->enable_mac_spoofing;
493 
494 	return QDF_STATUS_SUCCESS;
495 }
496 
497 wlan_scan_requester
498 wlan_scan_register_requester(struct wlan_objmgr_psoc *psoc,
499 			     uint8_t *name,
500 			     scan_event_handler event_cb,
501 			     void *arg)
502 {
503 	int i, j;
504 	struct wlan_scan_obj *scan;
505 	struct scan_requester_info *requesters;
506 	wlan_scan_requester requester = {0};
507 
508 	if (!psoc) {
509 		scm_err("null psoc");
510 		return 0;
511 	}
512 	scan = wlan_psoc_get_scan_obj(psoc);
513 	if (!scan)
514 		return 0;
515 
516 	requesters = scan->requesters;
517 	qdf_spin_lock_bh(&scan->lock);
518 	for (i = 0; i < WLAN_MAX_REQUESTORS; ++i) {
519 		if (requesters[i].requester == 0) {
520 			requesters[i].requester =
521 				WLAN_SCAN_REQUESTER_ID_PREFIX | i;
522 			j = 0;
523 			while (name[j] && (j < (WLAN_MAX_MODULE_NAME - 1))) {
524 				requesters[i].module[j] = name[j];
525 				++j;
526 			}
527 			requesters[i].module[j] = 0;
528 			requesters[i].ev_handler.func = event_cb;
529 			requesters[i].ev_handler.arg = arg;
530 			requester = requesters[i].requester;
531 			break;
532 		}
533 	}
534 	qdf_spin_unlock_bh(&scan->lock);
535 	scm_debug("module: %s, event_cb: 0x%pK, arg: 0x%pK, reqid: %d",
536 		  name, event_cb, arg, requester);
537 
538 	return requester;
539 }
540 
541 void
542 wlan_scan_unregister_requester(struct wlan_objmgr_psoc *psoc,
543 			       wlan_scan_requester requester)
544 {
545 	int idx;
546 	struct wlan_scan_obj *scan;
547 	struct scan_requester_info *requesters;
548 
549 	idx = requester & WLAN_SCAN_REQUESTER_ID_PREFIX;
550 	if (idx != WLAN_SCAN_REQUESTER_ID_PREFIX) {
551 		scm_err("prefix didn't match for requester id %d", requester);
552 		return;
553 	}
554 
555 	idx = requester & WLAN_SCAN_REQUESTER_ID_MASK;
556 	if (idx >= WLAN_MAX_REQUESTORS) {
557 		scm_err("requester id %d greater than max value", requester);
558 		return;
559 	}
560 
561 	if (!psoc) {
562 		scm_err("null psoc");
563 		return;
564 	}
565 	scan = wlan_psoc_get_scan_obj(psoc);
566 	if (!scan)
567 		return;
568 	requesters = scan->requesters;
569 	scm_debug("reqid: %d", requester);
570 
571 	qdf_spin_lock_bh(&scan->lock);
572 	requesters[idx].requester = 0;
573 	requesters[idx].module[0] = 0;
574 	requesters[idx].ev_handler.func = NULL;
575 	requesters[idx].ev_handler.arg = NULL;
576 	qdf_spin_unlock_bh(&scan->lock);
577 }
578 
579