xref: /wlan-dirver/qca-wifi-host-cmn/target_if/scan/src/target_if_scan.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
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_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(GET_WMI_HDL_FROM_PSOC(psoc),
197 			wmi_nlo_match_event_id,
198 			target_if_nlo_match_event_handler);
199 	if (status) {
200 		target_if_err("Failed to register nlo match event cb");
201 		return QDF_STATUS_E_FAILURE;
202 	}
203 
204 	status = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
205 			wmi_nlo_scan_complete_event_id,
206 			target_if_nlo_complete_handler);
207 	if (status) {
208 		target_if_err("Failed to register nlo scan comp event cb");
209 		return QDF_STATUS_E_FAILURE;
210 	}
211 
212 	return QDF_STATUS_SUCCESS;
213 }
214 
215 static QDF_STATUS
216 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc,
217 		void *arg)
218 {
219 	QDF_STATUS status;
220 
221 	status = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
222 			wmi_nlo_match_event_id);
223 	if (status) {
224 		target_if_err("Failed to unregister nlo match event cb");
225 		return QDF_STATUS_E_FAILURE;
226 	}
227 
228 	status = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
229 			wmi_nlo_scan_complete_event_id);
230 	if (status) {
231 		target_if_err("Failed to unregister nlo scan comp event cb");
232 		return QDF_STATUS_E_FAILURE;
233 	}
234 
235 	return QDF_STATUS_SUCCESS;
236 }
237 
238 static QDF_STATUS
239 target_if_pno_start(struct wlan_objmgr_psoc *psoc,
240 	struct pno_scan_req_params *req)
241 {
242 	QDF_STATUS status;
243 
244 	status = wmi_unified_pno_start_cmd(GET_WMI_HDL_FROM_PSOC(psoc), req);
245 	if (status == QDF_STATUS_SUCCESS) {
246 		if (req->mawc_params.enable)
247 			status = wmi_unified_nlo_mawc_cmd(
248 					GET_WMI_HDL_FROM_PSOC(psoc),
249 					&req->mawc_params);
250 	}
251 
252 	return status;
253 }
254 
255 static QDF_STATUS
256 target_if_pno_stop(struct wlan_objmgr_psoc *psoc,
257 	uint8_t vdev_id)
258 {
259 	return wmi_unified_pno_stop_cmd(GET_WMI_HDL_FROM_PSOC(psoc), vdev_id);
260 }
261 
262 #else
263 
264 static inline QDF_STATUS
265 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc,
266 	void *arg)
267 {
268 	return QDF_STATUS_SUCCESS;
269 }
270 
271 static inline QDF_STATUS
272 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc,
273 	void *arg)
274 {
275 	return QDF_STATUS_SUCCESS;
276 }
277 
278 static inline QDF_STATUS
279 target_if_pno_start(struct wlan_objmgr_psoc *psoc,
280 	struct pno_scan_req_params *req)
281 {
282 	return QDF_STATUS_SUCCESS;
283 }
284 
285 static inline QDF_STATUS
286 target_if_pno_stop(struct wlan_objmgr_psoc *psoc,
287 	uint8_t vdev_id)
288 {
289 	return QDF_STATUS_SUCCESS;
290 }
291 #endif
292 
293 
294 QDF_STATUS
295 target_if_scan_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg)
296 {
297 	QDF_STATUS status;
298 
299 	status = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
300 		wmi_scan_event_id, target_if_scan_event_handler);
301 	if (status) {
302 		target_if_err("Failed to register Scan match event cb");
303 		return QDF_STATUS_E_FAILURE;
304 	}
305 
306 	status = target_if_scan_register_pno_event_handler(psoc, arg);
307 
308 	return status;
309 }
310 
311 QDF_STATUS
312 target_if_scan_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
313 		void *arg)
314 {
315 	QDF_STATUS status;
316 
317 	status = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
318 		wmi_scan_event_id);
319 	if (status) {
320 		target_if_err("Failed to unregister Scan match event cb");
321 		return QDF_STATUS_E_FAILURE;
322 	}
323 
324 	status = target_if_scan_unregister_pno_event_handler(psoc, arg);
325 
326 	return status;
327 }
328 
329 QDF_STATUS
330 target_if_scan_start(struct wlan_objmgr_pdev *pdev,
331 		struct scan_start_request *req)
332 {
333 	void *pdev_wmi_handle;
334 
335 	pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
336 	if (!pdev_wmi_handle) {
337 		target_if_err("Invalid PDEV WMI handle");
338 		return QDF_STATUS_E_FAILURE;
339 	}
340 	return wmi_unified_scan_start_cmd_send(pdev_wmi_handle, &req->scan_req);
341 }
342 
343 QDF_STATUS
344 target_if_scan_cancel(struct wlan_objmgr_pdev *pdev,
345 		struct scan_cancel_param *req)
346 {
347 	void *pdev_wmi_handle;
348 
349 	pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
350 	if (!pdev_wmi_handle) {
351 		target_if_err("Invalid PDEV WMI handle");
352 		return QDF_STATUS_E_NULL_VALUE;
353 	}
354 	return wmi_unified_scan_stop_cmd_send(pdev_wmi_handle, req);
355 }
356 
357 QDF_STATUS
358 target_if_scan_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops)
359 {
360 	struct wlan_lmac_if_scan_tx_ops *scan;
361 
362 	scan = &tx_ops->scan;
363 	if (!scan) {
364 		target_if_err("Scan txops NULL");
365 		return QDF_STATUS_E_FAILURE;
366 	}
367 
368 	scan->scan_start = target_if_scan_start;
369 	scan->scan_cancel = target_if_scan_cancel;
370 	scan->pno_start = target_if_pno_start;
371 	scan->pno_stop = target_if_pno_stop;
372 	scan->scan_reg_ev_handler = target_if_scan_register_event_handler;
373 	scan->scan_unreg_ev_handler = target_if_scan_unregister_event_handler;
374 
375 	return QDF_STATUS_SUCCESS;
376 }
377 
378 QDF_STATUS
379 target_if_scan_set_max_active_scans(struct wlan_objmgr_psoc *psoc,
380 		uint32_t max_active_scans)
381 {
382 	struct wlan_lmac_if_scan_rx_ops *scan_rx_ops;
383 	QDF_STATUS status;
384 
385 	scan_rx_ops = target_if_scan_get_rx_ops(psoc);
386 	if (scan_rx_ops->scan_set_max_active_scans) {
387 		status = scan_rx_ops->scan_set_max_active_scans(psoc,
388 				max_active_scans);
389 	} else {
390 		target_if_err("scan_set_max_active_scans uninitialized");
391 		status = QDF_STATUS_E_FAULT;
392 	}
393 
394 	return status;
395 }
396