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