xref: /wlan-dirver/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs_full_offload.c (revision a86b23ee68a2491aede2e03991f3fb37046f4e41)
1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  *
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: target_if_dfs_full_offload.c
22  * This file contains dfs target interface for full offload
23  */
24 
25 #include <target_if.h>
26 #include <target_if_dfs.h>
27 #include <wmi_unified_dfs_api.h>
28 #include <init_deinit_lmac.h>
29 #include <wlan_module_ids.h>
30 #include <target_if_dfs_full_offload.h>
31 #include <wlan_dfs_tgt_api.h>
32 #include <wlan_objmgr_pdev_obj.h>
33 
34 #if defined(QCA_SUPPORT_AGILE_DFS)
35 #include <wlan_mlme_dispatcher.h>
36 #endif
37 /**
38  * target_if_dfs_cac_complete_event_handler() - CAC complete indication.
39  * @scn: scn handle.
40  * @data: Pointer to data buffer.
41  * @datalen: data length.
42  *
43  * Return: 0 on successful indication.
44  */
45 static int target_if_dfs_cac_complete_event_handler(
46 		ol_scn_t scn, uint8_t *data, uint32_t datalen)
47 {
48 	struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops;
49 	struct wlan_objmgr_psoc *psoc;
50 	struct wlan_objmgr_vdev *vdev;
51 	struct wlan_objmgr_pdev *pdev;
52 	int ret = 0;
53 	uint32_t vdev_id = 0;
54 	struct wmi_unified *wmi_handle;
55 
56 	if (!scn || !data) {
57 		target_if_err("scn: %pK, data: %pK", scn, data);
58 		return -EINVAL;
59 	}
60 
61 	psoc = target_if_get_psoc_from_scn_hdl(scn);
62 	if (!psoc) {
63 		target_if_err("null psoc");
64 		return -EINVAL;
65 	}
66 
67 	dfs_rx_ops = target_if_dfs_get_rx_ops(psoc);
68 	if (!dfs_rx_ops || !dfs_rx_ops->dfs_dfs_cac_complete_ind) {
69 		target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops);
70 		return -EINVAL;
71 	}
72 
73 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
74 	if (!wmi_handle) {
75 		target_if_err("Invalid WMI handle");
76 		return -EINVAL;
77 	}
78 
79 	if (wmi_extract_dfs_cac_complete_event(wmi_handle, data, &vdev_id,
80 					       datalen) != QDF_STATUS_SUCCESS) {
81 		target_if_err("failed to extract cac complete event");
82 		return -EFAULT;
83 	}
84 
85 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_DFS_ID);
86 	if (!vdev) {
87 		target_if_err("null vdev");
88 		return -EINVAL;
89 	}
90 
91 	pdev = wlan_vdev_get_pdev(vdev);
92 	if (!pdev) {
93 		target_if_err("null pdev");
94 		ret = -EINVAL;
95 	}
96 
97 	if (!ret && (QDF_STATUS_SUCCESS !=
98 	    dfs_rx_ops->dfs_dfs_cac_complete_ind(pdev, vdev_id))) {
99 		target_if_err("dfs_dfs_cac_complete_ind failed");
100 		ret = -EINVAL;
101 	}
102 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
103 
104 	return ret;
105 }
106 
107 #if defined(QCA_SUPPORT_AGILE_DFS)
108 /**
109  * target_if_dfs_ocac_complete_event_handler() - Off Channel CAC complete
110  *						 indication.
111  * @scn: scn handle.
112  * @data: Pointer to data buffer.
113  * @datalen: data length.
114  *
115  * Return: 0 on successful indication.
116  */
117 static int target_if_dfs_ocac_complete_event_handler(
118 		ol_scn_t scn, uint8_t *data, uint32_t datalen)
119 {
120 	struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops;
121 	struct wlan_objmgr_psoc *psoc;
122 	struct wlan_objmgr_vdev *vdev;
123 	struct wlan_objmgr_pdev *pdev;
124 	struct vdev_adfs_complete_status ocac_status;
125 	int ret = 0;
126 	struct wmi_unified *wmi_handle;
127 
128 	if (!scn || !data) {
129 		target_if_err("scn: %pK, data: %pK", scn, data);
130 		return -EINVAL;
131 	}
132 
133 	psoc = target_if_get_psoc_from_scn_hdl(scn);
134 	if (!psoc) {
135 		target_if_err("null psoc");
136 		return -EINVAL;
137 	}
138 
139 	dfs_rx_ops = target_if_dfs_get_rx_ops(psoc);
140 	if (!dfs_rx_ops || !dfs_rx_ops->dfs_dfs_ocac_complete_ind) {
141 		target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops);
142 		return -EINVAL;
143 	}
144 
145 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
146 	if (!wmi_handle) {
147 		target_if_err("Invalid WMI handle");
148 		return -EINVAL;
149 	}
150 
151 	if (wmi_extract_dfs_ocac_complete_event(wmi_handle,
152 						data,
153 						&ocac_status)
154 						!= QDF_STATUS_SUCCESS) {
155 		target_if_err("failed to extract off channel cac complete event");
156 		return -EFAULT;
157 	}
158 
159 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
160 						    ocac_status.vdev_id,
161 						    WLAN_DFS_ID);
162 	if (!vdev) {
163 		target_if_err("null vdev");
164 		return -EINVAL;
165 	}
166 
167 	pdev = wlan_vdev_get_pdev(vdev);
168 	if (!pdev) {
169 		target_if_err("null pdev");
170 		ret = -EINVAL;
171 		goto free_vdevref;
172 	}
173 
174 	if (!ret && (QDF_STATUS_SUCCESS !=
175 	    dfs_rx_ops->dfs_dfs_ocac_complete_ind(pdev, &ocac_status))) {
176 		target_if_err("dfs_dfs_ocac_complete_ind failed");
177 		ret = -EINVAL;
178 	}
179 
180 free_vdevref:
181 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
182 
183 	return ret;
184 }
185 #endif
186 
187 /**
188  * target_if_dfs_radar_detection_event_handler() - Indicate RADAR detection and
189  * process RADAR detection.
190  * @scn: scn handle.
191  * @data: pointer to data buffer.
192  * @datalen: data length.
193  *
194  * Return: 0 on successful indication.
195  */
196 static int target_if_dfs_radar_detection_event_handler(
197 		ol_scn_t scn, uint8_t *data, uint32_t datalen)
198 {
199 	struct radar_found_info radar;
200 	struct wlan_objmgr_psoc *psoc = NULL;
201 	struct wlan_objmgr_pdev *pdev = NULL;
202 	struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops;
203 	int ret = 0;
204 	struct wmi_unified *wmi_handle;
205 
206 	if (!scn || !data) {
207 		target_if_err("scn: %pK, data: %pK", scn, data);
208 		return -EINVAL;
209 	}
210 
211 	psoc = target_if_get_psoc_from_scn_hdl(scn);
212 	if (!psoc) {
213 		target_if_err("null psoc");
214 		return -EINVAL;
215 	}
216 
217 	dfs_rx_ops = target_if_dfs_get_rx_ops(psoc);
218 	if (!dfs_rx_ops || !dfs_rx_ops->dfs_process_radar_ind) {
219 		target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops);
220 		return -EINVAL;
221 	}
222 
223 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
224 	if (!wmi_handle) {
225 		target_if_err("Invalid WMI handle");
226 		return -EINVAL;
227 	}
228 
229 	if (wmi_extract_dfs_radar_detection_event(wmi_handle, data, &radar,
230 						  datalen)
231 	    != QDF_STATUS_SUCCESS) {
232 		target_if_err("failed to extract cac complete event");
233 		return -EFAULT;
234 	}
235 
236 	pdev = wlan_objmgr_get_pdev_by_id(psoc, radar.pdev_id, WLAN_DFS_ID);
237 	if (!pdev) {
238 		target_if_err("null pdev");
239 		return -EINVAL;
240 	}
241 
242 	if (dfs_rx_ops->dfs_process_radar_ind(pdev,
243 				&radar) != QDF_STATUS_SUCCESS) {
244 		target_if_err("dfs_process_radar_ind failed pdev_id=%d",
245 			      radar.pdev_id);
246 		ret = -EINVAL;
247 	}
248 
249 	wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
250 
251 	return ret;
252 }
253 
254 /**
255  * target_if_dfs_reg_ocac_event() - registers dfs off channel event
256  * for full offload.
257  * @psoc: Pointer to psoc object.
258  *
259  * Return: 0 on successful registration.
260  */
261 #if defined(QCA_SUPPORT_AGILE_DFS)
262 static int target_if_dfs_reg_ocac_event(struct wlan_objmgr_psoc *psoc)
263 {
264 	return wmi_unified_register_event(
265 			get_wmi_unified_hdl_from_psoc(psoc),
266 			wmi_vdev_ocac_complete_event_id,
267 			target_if_dfs_ocac_complete_event_handler);
268 }
269 #else
270 static int target_if_dfs_reg_ocac_event(struct wlan_objmgr_psoc *psoc)
271 {
272 	return 0;
273 }
274 #endif
275 
276 #if defined(WLAN_DFS_FULL_OFFLOAD)
277 QDF_STATUS target_if_dfs_reg_offload_events(
278 		struct wlan_objmgr_psoc *psoc)
279 {
280 	int ret1, ret2, ret3;
281 
282 	ret1 = wmi_unified_register_event(
283 			get_wmi_unified_hdl_from_psoc(psoc),
284 			wmi_dfs_radar_detection_event_id,
285 			target_if_dfs_radar_detection_event_handler);
286 	target_if_debug("wmi_dfs_radar_detection_event_id ret=%d", ret1);
287 
288 	ret2 = wmi_unified_register_event(
289 			get_wmi_unified_hdl_from_psoc(psoc),
290 			wmi_dfs_cac_complete_id,
291 			target_if_dfs_cac_complete_event_handler);
292 	target_if_debug("wmi_dfs_cac_complete_id ret=%d", ret2);
293 
294 	ret3 = target_if_dfs_reg_ocac_event(psoc);
295 	target_if_debug("wmi_vdev_ocac_complete_event_id ret=%d", ret3);
296 
297 	if (ret1 || ret2 || ret3)
298 		return QDF_STATUS_E_FAILURE;
299 	else
300 		return QDF_STATUS_SUCCESS;
301 }
302 #endif
303 
304 #if defined(QCA_SUPPORT_AGILE_DFS)
305 QDF_STATUS target_send_ocac_abort_cmd(struct wlan_objmgr_pdev *pdev)
306 {
307 	wmi_unified_t wmi_handle;
308 	struct vdev_adfs_abort_params param;
309 	struct wlan_objmgr_vdev *vdev;
310 	QDF_STATUS status;
311 
312 	if (!pdev) {
313 		target_if_err("null pdev");
314 		return QDF_STATUS_E_FAILURE;
315 	}
316 
317 	vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_DFS_ID);
318 
319 	if (!vdev) {
320 		target_if_err("null vdev");
321 		return QDF_STATUS_E_FAILURE;
322 	}
323 
324 	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
325 	if (!wmi_handle) {
326 		target_if_err("null wmi_handle");
327 		status = QDF_STATUS_E_FAILURE;
328 		goto free_vdevref;
329 	}
330 
331 	qdf_mem_set(&param, sizeof(param), 0);
332 	param.vdev_id = wlan_vdev_get_id(vdev);
333 	utils_dfs_cancel_precac_timer(pdev);
334 
335 	status = wmi_unified_send_vdev_adfs_ocac_abort_cmd(wmi_handle, &param);
336 	if (QDF_IS_STATUS_ERROR(status))
337 		target_if_err("dfs: unit_test_cmd send failed %d", status);
338 
339 free_vdevref:
340 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
341 
342 	return status;
343 }
344 
345 QDF_STATUS target_send_agile_ch_cfg_cmd(struct wlan_objmgr_pdev *pdev,
346 					struct dfs_agile_cac_params *adfs_param)
347 {
348 	wmi_unified_t wmi_handle;
349 	struct vdev_adfs_ch_cfg_params param;
350 	struct wlan_objmgr_vdev *vdev;
351 	QDF_STATUS status;
352 
353 	if (!pdev) {
354 		target_if_err("null pdev");
355 		return QDF_STATUS_E_FAILURE;
356 	}
357 
358 	vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_DFS_ID);
359 
360 	if (!vdev) {
361 		target_if_err("null vdev");
362 		return QDF_STATUS_E_FAILURE;
363 	}
364 
365 	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
366 	if (!wmi_handle) {
367 		target_if_err("null wmi_handle");
368 		status = QDF_STATUS_E_FAILURE;
369 		goto free_vdevref;
370 	}
371 
372 	qdf_mem_set(&param, sizeof(param), 0);
373 	param.vdev_id = wlan_vdev_get_id(vdev);
374 	param.ocac_mode = adfs_param->ocac_mode;
375 	param.min_duration_ms = adfs_param->min_precac_timeout;
376 	param.max_duration_ms = adfs_param->max_precac_timeout;
377 	param.chan_freq = adfs_param->precac_center_freq_1;
378 	param.chan_width = adfs_param->precac_chwidth;
379 	param.center_freq1 = adfs_param->precac_center_freq_1;
380 	param.center_freq2 = adfs_param->precac_center_freq_2;
381 
382 	status = wmi_unified_send_vdev_adfs_ch_cfg_cmd(wmi_handle, &param);
383 	if (QDF_IS_STATUS_ERROR(status))
384 		target_if_err("dfs: unit_test_cmd send failed %d", status);
385 
386 free_vdevref:
387 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
388 
389 	return status;
390 }
391 #endif
392 
393 #if (defined(WLAN_DFS_FULL_OFFLOAD) || defined(QCA_WIFI_QCA8074) || \
394 	defined(QCA_WIFI_QCA6018) || defined(QCA_WIFI_QCA5018))
395 QDF_STATUS target_process_bang_radar_cmd(
396 		struct wlan_objmgr_pdev *pdev,
397 		struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test)
398 {
399 	QDF_STATUS status;
400 	struct wmi_unit_test_cmd wmi_utest;
401 	int i;
402 	wmi_unified_t wmi_handle;
403 	uint32_t target_pdev_id = 0;
404 
405 	if (!pdev) {
406 		target_if_err("null pdev");
407 		return QDF_STATUS_E_FAILURE;
408 	}
409 
410 	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
411 	if (!wmi_handle) {
412 		target_if_err("null wmi_handle");
413 		return QDF_STATUS_E_FAILURE;
414 	}
415 
416 	wmi_utest.vdev_id = dfs_unit_test->vdev_id;
417 	wmi_utest.module_id = WLAN_MODULE_PHYERR_DFS;
418 	wmi_utest.num_args = dfs_unit_test->num_args;
419 
420 	for (i = 0; i < dfs_unit_test->num_args; i++)
421 		wmi_utest.args[i] = dfs_unit_test->args[i];
422 	/*
423 	 * Host to Target  conversion for pdev id required
424 	 * before we send a wmi unit test command
425 	 */
426 	if (wmi_convert_pdev_id_host_to_target(
427 				wmi_handle, pdev->pdev_objmgr.wlan_pdev_id,
428 				&target_pdev_id) != QDF_STATUS_SUCCESS) {
429 		target_if_err("failed to convert host pdev id to target");
430 		return QDF_STATUS_E_FAILURE;
431 	}
432 
433 	wmi_utest.args[IDX_PDEV_ID] = target_pdev_id;
434 
435 	status = wmi_unified_unit_test_cmd(wmi_handle, &wmi_utest);
436 	if (QDF_IS_STATUS_ERROR(status))
437 		target_if_err("dfs: unit_test_cmd send failed %d", status);
438 	return status;
439 }
440 #endif
441 
442 #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD)
443 QDF_STATUS target_send_usenol_pdev_param(struct wlan_objmgr_pdev *pdev,
444 					 bool usenol)
445 {
446 	QDF_STATUS status;
447 	wmi_unified_t wmi_handle;
448 
449 	if (!pdev) {
450 		target_if_err("null pdev");
451 		return QDF_STATUS_E_FAILURE;
452 	}
453 
454 	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
455 	if (!wmi_handle) {
456 		target_if_err("null wmi_handle");
457 		return QDF_STATUS_E_FAILURE;
458 	}
459 	status = wmi_send_usenol_pdev_param(wmi_handle, usenol, pdev);
460 
461 	if (QDF_IS_STATUS_ERROR(status))
462 		target_if_err("dfs: usenol_pdev_param send failed %d", status);
463 	return status;
464 }
465 
466 QDF_STATUS
467 target_send_subchan_marking_pdev_param(struct wlan_objmgr_pdev *pdev,
468 				       bool subchanmark)
469 {
470 	QDF_STATUS status;
471 	wmi_unified_t wmi_handle;
472 
473 	if (!pdev) {
474 		target_if_err("null pdev");
475 		return QDF_STATUS_E_FAILURE;
476 	}
477 
478 	wmi_handle = get_wmi_unified_hdl_from_pdev(pdev);
479 	if (!wmi_handle) {
480 		target_if_err("null wmi_handle");
481 		return QDF_STATUS_E_FAILURE;
482 	}
483 	status = wmi_send_subchan_marking_pdev_param(wmi_handle,
484 						     subchanmark, pdev);
485 
486 	if (QDF_IS_STATUS_ERROR(status))
487 		target_if_err("dfs: subchan_marking_pdev_param send failed %d",
488 			      status);
489 
490 	return status;
491 }
492 #endif
493