xref: /wlan-dirver/qca-wifi-host-cmn/target_if/dfs/src/target_if_dfs_full_offload.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
1 /*
2  * Copyright (c) 2017-2018 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_ucfg.h>
29 #include <wlan_module_ids.h>
30 #include <target_if_dfs_full_offload.h>
31 
32 /**
33  * target_if_dfs_cac_complete_event_handler() - CAC complete indication.
34  * @scn: scn handle.
35  * @data: Pointer to data buffer.
36  * @datalen: data length.
37  *
38  * Return: 0 on successful indication.
39  */
40 static int target_if_dfs_cac_complete_event_handler(
41 		ol_scn_t scn, uint8_t *data, uint32_t datalen)
42 {
43 	struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops;
44 	struct wlan_objmgr_psoc *psoc;
45 	struct wlan_objmgr_vdev *vdev;
46 	struct wlan_objmgr_pdev *pdev;
47 	int ret = 0;
48 	uint32_t vdev_id = 0;
49 
50 	if (!scn || !data) {
51 		target_if_err("scn: %pK, data: %pK", scn, data);
52 		return -EINVAL;
53 	}
54 
55 	psoc = target_if_get_psoc_from_scn_hdl(scn);
56 	if (!psoc) {
57 		target_if_err("null psoc");
58 		return -EINVAL;
59 	}
60 
61 	dfs_rx_ops = target_if_dfs_get_rx_ops(psoc);
62 	if (!dfs_rx_ops || !dfs_rx_ops->dfs_dfs_cac_complete_ind) {
63 		target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops);
64 		return -EINVAL;
65 	}
66 
67 	if (wmi_extract_dfs_cac_complete_event(GET_WMI_HDL_FROM_PSOC(psoc),
68 			data, &vdev_id, datalen) != QDF_STATUS_SUCCESS) {
69 		target_if_err("failed to extract cac complete event");
70 		return -EFAULT;
71 	}
72 
73 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_DFS_ID);
74 	if (!vdev) {
75 		target_if_err("null vdev");
76 		return -EINVAL;
77 	}
78 
79 	pdev = wlan_vdev_get_pdev(vdev);
80 	if (!pdev) {
81 		target_if_err("null pdev");
82 		ret = -EINVAL;
83 	}
84 
85 	if (!ret && (QDF_STATUS_SUCCESS !=
86 	    dfs_rx_ops->dfs_dfs_cac_complete_ind(pdev, vdev_id))) {
87 		target_if_err("dfs_dfs_cac_complete_ind failed");
88 		ret = -EINVAL;
89 	}
90 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID);
91 
92 	return ret;
93 }
94 
95 /**
96  * target_if_dfs_radar_detection_event_handler() - Indicate RADAR detection and
97  * process RADAR detection.
98  * @scn: scn handle.
99  * @data: pointer to data buffer.
100  * @datalen: data length.
101  *
102  * Return: 0 on successful indication.
103  */
104 static int target_if_dfs_radar_detection_event_handler(
105 		ol_scn_t scn, uint8_t *data, uint32_t datalen)
106 {
107 	struct radar_found_info radar;
108 	struct wlan_objmgr_psoc *psoc = NULL;
109 	struct wlan_objmgr_pdev *pdev = NULL;
110 	struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops;
111 	int ret = 0;
112 
113 	if (!scn || !data) {
114 		target_if_err("scn: %pK, data: %pK", scn, data);
115 		return -EINVAL;
116 	}
117 
118 	psoc = target_if_get_psoc_from_scn_hdl(scn);
119 	if (!psoc) {
120 		target_if_err("null psoc");
121 		return -EINVAL;
122 	}
123 
124 	dfs_rx_ops = target_if_dfs_get_rx_ops(psoc);
125 	if (!dfs_rx_ops || !dfs_rx_ops->dfs_process_radar_ind) {
126 		target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops);
127 		return -EINVAL;
128 	}
129 
130 	if (wmi_extract_dfs_radar_detection_event(GET_WMI_HDL_FROM_PSOC(psoc),
131 			data, &radar, datalen) != QDF_STATUS_SUCCESS) {
132 		target_if_err("failed to extract cac complete event");
133 		return -EFAULT;
134 	}
135 
136 	pdev = wlan_objmgr_get_pdev_by_id(psoc, radar.pdev_id, WLAN_DFS_ID);
137 	if (!pdev) {
138 		target_if_err("null pdev");
139 		return -EINVAL;
140 	}
141 
142 	if (dfs_rx_ops->dfs_process_radar_ind(pdev,
143 				&radar) != QDF_STATUS_SUCCESS) {
144 		target_if_err("dfs_process_radar_ind failed pdev_id=%d",
145 			      radar.pdev_id);
146 		ret = -EINVAL;
147 	}
148 
149 	wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID);
150 
151 	return ret;
152 }
153 
154 QDF_STATUS target_if_dfs_reg_offload_events(
155 		struct wlan_objmgr_psoc *psoc)
156 {
157 	int ret1, ret2;
158 
159 	ret1 = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
160 			wmi_dfs_radar_detection_event_id,
161 			target_if_dfs_radar_detection_event_handler);
162 	target_if_debug("wmi_dfs_radar_detection_event_id ret=%d", ret1);
163 
164 	ret2 = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
165 			wmi_dfs_cac_complete_id,
166 			target_if_dfs_cac_complete_event_handler);
167 	target_if_debug("wmi_dfs_cac_complete_id ret=%d", ret2);
168 
169 	if (ret1 || ret2)
170 		return QDF_STATUS_E_FAILURE;
171 	else
172 		return QDF_STATUS_SUCCESS;
173 }
174 
175 #if (defined(CONFIG_MCL) || (QCA_WIFI_QCA8074))
176 QDF_STATUS target_process_bang_radar_cmd(
177 		struct wlan_objmgr_pdev *pdev,
178 		struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test)
179 {
180 	QDF_STATUS status;
181 	struct wmi_unit_test_cmd wmi_utest;
182 	int i;
183 	wmi_unified_t wmi_handle;
184 
185 	if (!pdev) {
186 		target_if_err("null pdev");
187 		return QDF_STATUS_E_FAILURE;
188 	}
189 
190 	wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
191 	if (!wmi_handle) {
192 		target_if_err("null wmi_handle");
193 		return QDF_STATUS_E_FAILURE;
194 	}
195 
196 	wmi_utest.vdev_id = dfs_unit_test->vdev_id;
197 	wmi_utest.module_id = WLAN_MODULE_PHYERR_DFS;
198 	wmi_utest.num_args = dfs_unit_test->num_args;
199 
200 	for (i = 0; i < dfs_unit_test->num_args; i++)
201 		wmi_utest.args[i] = dfs_unit_test->args[i];
202 	/*
203 	 * Host to Target  conversion for pdev id required
204 	 * before we send a wmi unit test command
205 	 */
206 	wmi_utest.args[IDX_PDEV_ID] = wmi_handle->ops->
207 		convert_pdev_id_host_to_target(pdev->pdev_objmgr.wlan_pdev_id);
208 
209 	status = wmi_unified_unit_test_cmd(wmi_handle, &wmi_utest);
210 	if (QDF_IS_STATUS_ERROR(status))
211 		target_if_err("dfs: unit_test_cmd send failed %d", status);
212 	return status;
213 }
214 #else
215 static QDF_STATUS target_process_bang_radar_cmd(
216 		struct wlan_objmgr_pdev *pdev,
217 		struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test)
218 {
219 	    return QDF_STATUS_SUCCESS;
220 }
221 #endif
222