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