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