xref: /wlan-dirver/qca-wifi-host-cmn/target_if/scan/src/target_if_scan.c (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 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: offload lmac interface APIs definitions for scan
22  */
23 
24 #include <qdf_mem.h>
25 #include <qdf_status.h>
26 #include <target_if_scan.h>
27 #include <wmi_unified_priv.h>
28 #include <wmi_unified_param.h>
29 #include <wlan_objmgr_psoc_obj.h>
30 #include <wlan_scan_tgt_api.h>
31 #include <target_if.h>
32 
33 static inline struct wlan_lmac_if_scan_rx_ops *
34 target_if_scan_get_rx_ops(struct wlan_objmgr_psoc *psoc)
35 {
36 	struct wlan_lmac_if_rx_ops *rx_ops;
37 
38 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
39 	if (!rx_ops) {
40 		target_if_err("rx_ops is NULL");
41 		return NULL;
42 	}
43 
44 	return &rx_ops->scan;
45 }
46 
47 static int
48 target_if_scan_event_handler(ol_scn_t scn, uint8_t *data, uint32_t datalen)
49 {
50 	struct scan_event_info *event_info;
51 	struct wlan_objmgr_psoc *psoc;
52 	struct wmi_unified *wmi_handle;
53 	struct wlan_lmac_if_scan_rx_ops *scan_rx_ops;
54 	QDF_STATUS status;
55 
56 	if (!scn || !data) {
57 		target_if_err("scn: 0x%pK, data: 0x%pK\n", scn, data);
58 		return -EINVAL;
59 	}
60 	psoc = target_if_get_psoc_from_scn_hdl(scn);
61 	if (!psoc) {
62 		target_if_err("null psoc\n");
63 		return -EINVAL;
64 	}
65 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
66 
67 	if (!wmi_handle) {
68 		target_if_err("wmi_handle is NULL");
69 		return -EINVAL;
70 	}
71 
72 	event_info = qdf_mem_malloc(sizeof(*event_info));
73 
74 	if (!event_info)
75 		return -ENOMEM;
76 
77 	if (wmi_extract_vdev_scan_ev_param(wmi_handle, data,
78 	   &(event_info->event))) {
79 		target_if_err("Failed to extract wmi scan event");
80 		qdf_mem_free(event_info);
81 		return -EINVAL;
82 	}
83 
84 	scan_rx_ops = target_if_scan_get_rx_ops(psoc);
85 	if (!scan_rx_ops) {
86 		target_if_err("scan_rx_ops is NULL");
87 		return -EINVAL;
88 	}
89 
90 	if (scan_rx_ops->scan_ev_handler) {
91 		status = scan_rx_ops->scan_ev_handler(psoc, event_info);
92 		if (status != QDF_STATUS_SUCCESS) {
93 			qdf_mem_free(event_info);
94 			return -EINVAL;
95 		}
96 	} else {
97 		qdf_mem_free(event_info);
98 		return -EINVAL;
99 	}
100 
101 	return 0;
102 }
103 
104 #ifdef FEATURE_WLAN_SCAN_PNO
105 
106 int target_if_nlo_complete_handler(ol_scn_t scn, uint8_t *data,
107 	uint32_t len)
108 {
109 	struct scan_event_info *event_info;
110 	struct wlan_objmgr_psoc *psoc;
111 	struct wmi_unified *wmi_handle;
112 	struct wlan_lmac_if_scan_rx_ops *scan_rx_ops;
113 	QDF_STATUS status;
114 
115 	if (!scn || !data) {
116 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
117 		return -EINVAL;
118 	}
119 
120 	psoc = target_if_get_psoc_from_scn_hdl(scn);
121 	if (!psoc) {
122 		target_if_err("null psoc");
123 		return -EINVAL;
124 	}
125 
126 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
127 	if (!wmi_handle) {
128 		target_if_err("wmi_handle is NULL");
129 		return -EINVAL;
130 	}
131 
132 	event_info = qdf_mem_malloc(sizeof(*event_info));
133 	if (!event_info)
134 		return -ENOMEM;
135 
136 	if (wmi_extract_nlo_complete_ev_param(wmi_handle, data,
137 					      &event_info->event)) {
138 		target_if_err("Failed to extract WMI PNO complete event");
139 		qdf_mem_free(event_info);
140 		return -EINVAL;
141 	}
142 
143 	target_if_debug("PNO complete event received for vdev %d",
144 			event_info->event.vdev_id);
145 
146 	scan_rx_ops = target_if_scan_get_rx_ops(psoc);
147 	if (!scan_rx_ops) {
148 		target_if_err("scan_rx_ops is NULL");
149 		return -EINVAL;
150 	}
151 
152 	if (scan_rx_ops->scan_ev_handler) {
153 		status = scan_rx_ops->scan_ev_handler(psoc, event_info);
154 		if (status != QDF_STATUS_SUCCESS) {
155 			qdf_mem_free(event_info);
156 			return -EINVAL;
157 		}
158 	} else {
159 		qdf_mem_free(event_info);
160 		return -EINVAL;
161 	}
162 
163 	return 0;
164 }
165 
166 int target_if_nlo_match_event_handler(ol_scn_t scn, uint8_t *data,
167 	uint32_t len)
168 {
169 	struct scan_event_info *event_info;
170 	struct wlan_objmgr_psoc *psoc;
171 	struct wmi_unified *wmi_handle;
172 	struct wlan_lmac_if_scan_rx_ops *scan_rx_ops;
173 	QDF_STATUS status;
174 
175 	if (!scn || !data) {
176 		target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
177 		return -EINVAL;
178 	}
179 
180 	psoc = target_if_get_psoc_from_scn_hdl(scn);
181 	if (!psoc) {
182 		target_if_err("null psoc");
183 		return -EINVAL;
184 	}
185 
186 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
187 	if (!wmi_handle) {
188 		target_if_err("wmi_handle is NULL");
189 		return -EINVAL;
190 	}
191 
192 	event_info = qdf_mem_malloc(sizeof(*event_info));
193 	if (!event_info)
194 		return -ENOMEM;
195 
196 	if (wmi_extract_nlo_match_ev_param(wmi_handle, data,
197 					   &event_info->event)) {
198 		target_if_err("Failed to extract WMI PNO match event");
199 		qdf_mem_free(event_info);
200 		return -EINVAL;
201 	}
202 
203 	target_if_debug("PNO match event received for vdev %d",
204 			event_info->event.vdev_id);
205 
206 	scan_rx_ops = target_if_scan_get_rx_ops(psoc);
207 	if (!scan_rx_ops) {
208 		target_if_err("scan_rx_ops is NULL");
209 		return -EINVAL;
210 	}
211 
212 	if (scan_rx_ops->scan_ev_handler) {
213 		status = scan_rx_ops->scan_ev_handler(psoc, event_info);
214 		if (status != QDF_STATUS_SUCCESS) {
215 			qdf_mem_free(event_info);
216 			return -EINVAL;
217 		}
218 	} else {
219 		qdf_mem_free(event_info);
220 		return -EINVAL;
221 	}
222 
223 	return 0;
224 }
225 
226 static QDF_STATUS
227 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc,
228 	void *arg)
229 {
230 	QDF_STATUS status;
231 	struct wmi_unified *wmi_handle;
232 
233 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
234 	if (!wmi_handle) {
235 		target_if_err("Invalid WMI handle");
236 		return QDF_STATUS_E_FAILURE;
237 	}
238 
239 	status = wmi_unified_register_event(
240 			wmi_handle,
241 			wmi_nlo_match_event_id,
242 			target_if_nlo_match_event_handler);
243 	if (status) {
244 		target_if_err("Failed to register nlo match event cb");
245 		return QDF_STATUS_E_FAILURE;
246 	}
247 
248 	status = wmi_unified_register_event(
249 			wmi_handle,
250 			wmi_nlo_scan_complete_event_id,
251 			target_if_nlo_complete_handler);
252 	if (status) {
253 		target_if_err("Failed to register nlo scan comp event cb");
254 		return QDF_STATUS_E_FAILURE;
255 	}
256 
257 	return QDF_STATUS_SUCCESS;
258 }
259 
260 static QDF_STATUS
261 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc,
262 		void *arg)
263 {
264 	QDF_STATUS status;
265 	struct wmi_unified *wmi_handle;
266 
267 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
268 	if (!wmi_handle) {
269 		target_if_err("Invalid WMI handle");
270 		return QDF_STATUS_E_FAILURE;
271 	}
272 
273 	status = wmi_unified_unregister_event(
274 			wmi_handle,
275 			wmi_nlo_match_event_id);
276 	if (status) {
277 		target_if_err("Failed to unregister nlo match event cb");
278 		return QDF_STATUS_E_FAILURE;
279 	}
280 
281 	status = wmi_unified_unregister_event(
282 			wmi_handle,
283 			wmi_nlo_scan_complete_event_id);
284 	if (status) {
285 		target_if_err("Failed to unregister nlo scan comp event cb");
286 		return QDF_STATUS_E_FAILURE;
287 	}
288 
289 	return QDF_STATUS_SUCCESS;
290 }
291 
292 static QDF_STATUS
293 target_if_pno_start(struct wlan_objmgr_psoc *psoc,
294 	struct pno_scan_req_params *req)
295 {
296 	QDF_STATUS status;
297 	struct wmi_unified *wmi_handle;
298 
299 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
300 	if (!wmi_handle) {
301 		target_if_err("Invalid WMI handle");
302 		return QDF_STATUS_E_FAILURE;
303 	}
304 
305 	status = wmi_unified_pno_start_cmd(wmi_handle, req);
306 	if (status == QDF_STATUS_SUCCESS) {
307 		if (req->mawc_params.enable)
308 			status = wmi_unified_nlo_mawc_cmd(wmi_handle,
309 							  &req->mawc_params);
310 	}
311 
312 	return status;
313 }
314 
315 static QDF_STATUS
316 target_if_pno_stop(struct wlan_objmgr_psoc *psoc,
317 	uint8_t vdev_id)
318 {
319 	struct wmi_unified *wmi_handle;
320 
321 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
322 	if (!wmi_handle) {
323 		target_if_err("Invalid WMI handle");
324 		return QDF_STATUS_E_FAILURE;
325 	}
326 
327 	return wmi_unified_pno_stop_cmd(wmi_handle, vdev_id);
328 }
329 
330 #else
331 
332 static inline QDF_STATUS
333 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc,
334 	void *arg)
335 {
336 	return QDF_STATUS_SUCCESS;
337 }
338 
339 static inline QDF_STATUS
340 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc,
341 	void *arg)
342 {
343 	return QDF_STATUS_SUCCESS;
344 }
345 
346 static inline QDF_STATUS
347 target_if_pno_start(struct wlan_objmgr_psoc *psoc,
348 	struct pno_scan_req_params *req)
349 {
350 	return QDF_STATUS_SUCCESS;
351 }
352 
353 static inline QDF_STATUS
354 target_if_pno_stop(struct wlan_objmgr_psoc *psoc,
355 	uint8_t vdev_id)
356 {
357 	return QDF_STATUS_SUCCESS;
358 }
359 #endif
360 
361 static QDF_STATUS
362 target_if_obss_scan_disable(struct wlan_objmgr_psoc *psoc,
363 			    uint8_t vdev_id)
364 {
365 	struct wmi_unified *wmi_handle;
366 
367 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
368 	if (!wmi_handle) {
369 		target_if_err("Invalid WMI handle");
370 		return QDF_STATUS_E_FAILURE;
371 	}
372 
373 	return wmi_unified_obss_disable_cmd(wmi_handle, vdev_id);
374 }
375 
376 QDF_STATUS
377 target_if_scan_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg)
378 {
379 	QDF_STATUS status;
380 	struct wmi_unified *wmi_handle;
381 
382 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
383 	if (!wmi_handle) {
384 		target_if_err("Invalid WMI handle");
385 		return QDF_STATUS_E_FAILURE;
386 	}
387 
388 	status = wmi_unified_register_event(
389 			wmi_handle,
390 			wmi_scan_event_id,
391 			target_if_scan_event_handler);
392 	if (status) {
393 		target_if_err("Failed to register Scan match event cb");
394 		return QDF_STATUS_E_FAILURE;
395 	}
396 
397 	status = target_if_scan_register_pno_event_handler(psoc, arg);
398 
399 	return status;
400 }
401 
402 QDF_STATUS
403 target_if_scan_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
404 		void *arg)
405 {
406 	QDF_STATUS status;
407 	struct wmi_unified *wmi_handle;
408 
409 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
410 	if (!wmi_handle) {
411 		target_if_err("Invalid WMI handle");
412 		return QDF_STATUS_E_FAILURE;
413 	}
414 
415 	status = wmi_unified_unregister_event(
416 			wmi_handle,
417 			wmi_scan_event_id);
418 	if (status) {
419 		target_if_err("Failed to unregister Scan match event cb");
420 		return QDF_STATUS_E_FAILURE;
421 	}
422 
423 	status = target_if_scan_unregister_pno_event_handler(psoc, arg);
424 
425 	return status;
426 }
427 
428 QDF_STATUS
429 target_if_scan_start(struct wlan_objmgr_pdev *pdev,
430 		struct scan_start_request *req)
431 {
432 	wmi_unified_t pdev_wmi_handle;
433 
434 	pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
435 	if (!pdev_wmi_handle) {
436 		target_if_err("Invalid PDEV WMI handle");
437 		return QDF_STATUS_E_FAILURE;
438 	}
439 	return wmi_unified_scan_start_cmd_send(pdev_wmi_handle, &req->scan_req);
440 }
441 
442 QDF_STATUS
443 target_if_scan_cancel(struct wlan_objmgr_pdev *pdev,
444 		struct scan_cancel_param *req)
445 {
446 	wmi_unified_t pdev_wmi_handle;
447 
448 	pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
449 	if (!pdev_wmi_handle) {
450 		target_if_err("Invalid PDEV WMI handle");
451 		return QDF_STATUS_E_NULL_VALUE;
452 	}
453 	return wmi_unified_scan_stop_cmd_send(pdev_wmi_handle, req);
454 }
455 
456 #if defined(WLAN_FEATURE_11BE) && defined(WLAN_FEATURE_11BE_MLO_MBSSID)
457 bool target_if_is_platform_eht_capable(struct wlan_objmgr_psoc *psoc,
458 				       uint8_t pdev_id)
459 {
460 	struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr, *mac_phy_cap;
461 
462 	if (psoc->tgt_if_handle) {
463 		mac_phy_cap_arr =
464 			target_psoc_get_mac_phy_cap(psoc->tgt_if_handle);
465 		if (!mac_phy_cap_arr)
466 			return false;
467 
468 		mac_phy_cap = &mac_phy_cap_arr[pdev_id];
469 		if (mac_phy_cap && mac_phy_cap->supports_11be)
470 			return true;
471 	}
472 
473 	return false;
474 }
475 #else
476 bool target_if_is_platform_eht_capable(struct wlan_objmgr_psoc *psoc,
477 				       uint8_t pdev_id)
478 {
479 	return false;
480 }
481 #endif
482 
483 QDF_STATUS
484 target_if_scan_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
485 {
486 	struct wlan_lmac_if_scan_tx_ops *scan;
487 
488 	scan = &tx_ops->scan;
489 	if (!scan) {
490 		target_if_err("Scan txops NULL");
491 		return QDF_STATUS_E_FAILURE;
492 	}
493 
494 	scan->scan_start = target_if_scan_start;
495 	scan->scan_cancel = target_if_scan_cancel;
496 	scan->pno_start = target_if_pno_start;
497 	scan->pno_stop = target_if_pno_stop;
498 	scan->obss_disable = target_if_obss_scan_disable;
499 	scan->scan_reg_ev_handler = target_if_scan_register_event_handler;
500 	scan->scan_unreg_ev_handler = target_if_scan_unregister_event_handler;
501 	scan->is_platform_eht_capable = target_if_is_platform_eht_capable;
502 
503 	return QDF_STATUS_SUCCESS;
504 }
505 
506 QDF_STATUS
507 target_if_scan_set_max_active_scans(struct wlan_objmgr_psoc *psoc,
508 		uint32_t max_active_scans)
509 {
510 	struct wlan_lmac_if_scan_rx_ops *scan_rx_ops;
511 	QDF_STATUS status;
512 
513 	scan_rx_ops = target_if_scan_get_rx_ops(psoc);
514 	if (!scan_rx_ops) {
515 		target_if_err("scan_rx_ops is NULL");
516 		return QDF_STATUS_E_FAILURE;
517 	}
518 
519 	if (scan_rx_ops->scan_set_max_active_scans) {
520 		status = scan_rx_ops->scan_set_max_active_scans(psoc,
521 				max_active_scans);
522 	} else {
523 		target_if_err("scan_set_max_active_scans uninitialized");
524 		status = QDF_STATUS_E_FAULT;
525 	}
526 
527 	return status;
528 }
529