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