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