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