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