xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
1 /*
2  * Copyright (c) 2016-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: This file has the DFS dispatcher API implementation which is exposed
22  * to outside of DFS component.
23  */
24 #include <wlan_objmgr_pdev_obj.h>
25 #include "wlan_dfs_tgt_api.h"
26 #include "wlan_lmac_if_def.h"
27 #include "wlan_lmac_if_api.h"
28 #include "wlan_dfs_mlme_api.h"
29 #include "../../core/src/dfs.h"
30 #include "../../core/src/dfs_zero_cac.h"
31 #include "../../core/src/dfs_process_radar_found_ind.h"
32 
33 struct wlan_lmac_if_dfs_tx_ops *
34 wlan_psoc_get_dfs_txops(struct wlan_objmgr_psoc *psoc)
35 {
36 	return &((psoc->soc_cb.tx_ops.dfs_tx_ops));
37 }
38 
39 QDF_STATUS tgt_dfs_set_current_channel(struct wlan_objmgr_pdev *pdev,
40 				       uint16_t dfs_ch_freq,
41 				       uint64_t dfs_ch_flags,
42 				       uint16_t dfs_ch_flagext,
43 				       uint8_t dfs_ch_ieee,
44 				       uint8_t dfs_ch_vhtop_ch_freq_seg1,
45 				       uint8_t dfs_ch_vhtop_ch_freq_seg2)
46 {
47 	struct wlan_dfs *dfs;
48 
49 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
50 	if (!dfs) {
51 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
52 		return  QDF_STATUS_E_FAILURE;
53 	}
54 
55 	dfs_set_current_channel(dfs,
56 				dfs_ch_freq,
57 				dfs_ch_flags,
58 				dfs_ch_flagext,
59 				dfs_ch_ieee,
60 				dfs_ch_vhtop_ch_freq_seg1,
61 				dfs_ch_vhtop_ch_freq_seg2);
62 
63 	return QDF_STATUS_SUCCESS;
64 }
65 EXPORT_SYMBOL(tgt_dfs_set_current_channel);
66 
67 QDF_STATUS tgt_dfs_radar_enable(struct wlan_objmgr_pdev *pdev,
68 				int no_cac, uint32_t opmode)
69 {
70 	struct wlan_dfs *dfs;
71 	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
72 	struct wlan_objmgr_psoc *psoc;
73 	QDF_STATUS status;
74 
75 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
76 	if (!dfs) {
77 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
78 		return  QDF_STATUS_E_FAILURE;
79 	}
80 
81 	if (!dfs->dfs_is_offload_enabled) {
82 		dfs_radar_enable(dfs, no_cac, opmode);
83 		return QDF_STATUS_SUCCESS;
84 	}
85 
86 	psoc = wlan_pdev_get_psoc(pdev);
87 	if (!psoc) {
88 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "psoc is null");
89 		return  QDF_STATUS_E_FAILURE;
90 	}
91 
92 	dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
93 	if (!dfs_tx_ops) {
94 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_tx_ops is null");
95 		return  QDF_STATUS_E_FAILURE;
96 	}
97 
98 	status = dfs_tx_ops->dfs_send_offload_enable_cmd(pdev, true);
99 	if (QDF_IS_STATUS_ERROR(status))
100 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,
101 			"Failed to enable dfs offload, pdev_id: %d",
102 			wlan_objmgr_pdev_get_pdev_id(pdev));
103 
104 	return status;
105 }
106 EXPORT_SYMBOL(tgt_dfs_radar_enable);
107 
108 QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev,
109 				  void *buf,
110 				  uint16_t datalen,
111 				  uint8_t r_rssi,
112 				  uint8_t r_ext_rssi,
113 				  uint32_t r_rs_tstamp,
114 				  uint64_t r_fulltsf)
115 {
116 	struct wlan_dfs *dfs;
117 
118 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
119 	if (!dfs) {
120 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
121 		return  QDF_STATUS_E_FAILURE;
122 	}
123 
124 	if (!dfs->dfs_is_offload_enabled)
125 		dfs_process_phyerr(dfs, buf, datalen, r_rssi,
126 				   r_ext_rssi, r_rs_tstamp, r_fulltsf);
127 	else
128 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
129 			 "Unexpect phyerror as DFS is offloaded, pdev_id: %d",
130 			 wlan_objmgr_pdev_get_pdev_id(pdev));
131 
132 	return QDF_STATUS_SUCCESS;
133 }
134 EXPORT_SYMBOL(tgt_dfs_process_phyerr);
135 
136 #ifdef QCA_MCL_DFS_SUPPORT
137 QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev,
138 						 struct radar_event_info
139 						 *wlan_radar_event)
140 {
141 	struct wlan_dfs *dfs;
142 
143 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
144 	if (!dfs) {
145 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
146 		return  QDF_STATUS_E_FAILURE;
147 	}
148 	if (!dfs->dfs_is_offload_enabled)
149 		dfs_process_phyerr_filter_offload(dfs, wlan_radar_event);
150 	else
151 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
152 			 "Unexpect phyerror as DFS is offloaded, pdev_id: %d",
153 			 wlan_objmgr_pdev_get_pdev_id(pdev));
154 
155 	return QDF_STATUS_SUCCESS;
156 }
157 EXPORT_SYMBOL(tgt_dfs_process_phyerr_filter_offload);
158 
159 QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_psoc *psoc,
160 					    bool *is_phyerr_filter_offload)
161 {
162 	struct dfs_soc_priv_obj *soc_obj;
163 
164 	if (!psoc) {
165 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "psoc is null");
166 		return QDF_STATUS_E_FAILURE;
167 	}
168 
169 	soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
170 							WLAN_UMAC_COMP_DFS);
171 	if (!soc_obj) {
172 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
173 			"Failed to get dfs psoc component");
174 		return QDF_STATUS_E_FAILURE;
175 	}
176 
177 	*is_phyerr_filter_offload = soc_obj->dfs_is_phyerr_filter_offload;
178 
179 	return QDF_STATUS_SUCCESS;
180 }
181 EXPORT_SYMBOL(tgt_dfs_is_phyerr_filter_offload);
182 #else
183 QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev,
184 						 struct radar_event_info
185 						 *wlan_radar_event)
186 {
187 	return QDF_STATUS_SUCCESS;
188 }
189 
190 QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_psoc *psoc,
191 					    bool *is_phyerr_filter_offload)
192 {
193 	return QDF_STATUS_SUCCESS;
194 }
195 #endif
196 
197 QDF_STATUS tgt_dfs_is_precac_timer_running(struct wlan_objmgr_pdev *pdev,
198 					   bool *is_precac_timer_running)
199 {
200 	struct wlan_dfs *dfs;
201 
202 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
203 	if (!dfs) {
204 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
205 		return  QDF_STATUS_E_FAILURE;
206 	}
207 
208 	*is_precac_timer_running = dfs_is_precac_timer_running(dfs);
209 
210 	return QDF_STATUS_SUCCESS;
211 }
212 EXPORT_SYMBOL(tgt_dfs_is_precac_timer_running);
213 
214 QDF_STATUS tgt_dfs_get_radars(struct wlan_objmgr_pdev *pdev)
215 {
216 	struct wlan_dfs *dfs;
217 
218 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
219 	if (!dfs) {
220 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
221 		return  QDF_STATUS_E_FAILURE;
222 	}
223 
224 	if (!dfs->dfs_is_offload_enabled)
225 		dfs_get_radars(dfs);
226 
227 	return QDF_STATUS_SUCCESS;
228 }
229 EXPORT_SYMBOL(tgt_dfs_get_radars);
230 
231 QDF_STATUS tgt_dfs_destroy_object(struct wlan_objmgr_pdev *pdev)
232 {
233 	struct wlan_dfs *dfs;
234 
235 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
236 	if (!dfs) {
237 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
238 		return  QDF_STATUS_E_FAILURE;
239 	}
240 
241 	dfs_destroy_object(dfs);
242 
243 	return QDF_STATUS_SUCCESS;
244 }
245 EXPORT_SYMBOL(tgt_dfs_destroy_object);
246 
247 #ifdef QCA_MCL_DFS_SUPPORT
248 QDF_STATUS tgt_dfs_set_tx_leakage_threshold(struct wlan_objmgr_pdev *pdev,
249 		uint16_t tx_leakage_threshold)
250 {
251 	struct wlan_dfs *dfs;
252 
253 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
254 	if (!dfs) {
255 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
256 		return  QDF_STATUS_E_FAILURE;
257 	}
258 
259 	dfs->tx_leakage_threshold = tx_leakage_threshold;
260 
261 	return QDF_STATUS_SUCCESS;
262 }
263 EXPORT_SYMBOL(tgt_dfs_set_tx_leakage_threshold);
264 #endif
265 
266 QDF_STATUS tgt_dfs_control(struct wlan_objmgr_pdev *pdev,
267 			   u_int id,
268 			   void *indata,
269 			   uint32_t insize,
270 			   void *outdata,
271 			   uint32_t *outsize,
272 			   int *error)
273 {
274 	struct wlan_dfs *dfs;
275 
276 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
277 	if (!dfs) {
278 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
279 		return  QDF_STATUS_E_FAILURE;
280 	}
281 
282 	*error = dfs_control(dfs, id, indata, insize, outdata, outsize);
283 
284 	return  QDF_STATUS_SUCCESS;
285 }
286 EXPORT_SYMBOL(tgt_dfs_control);
287 
288 QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev,
289 					      uint32_t chan_mode,
290 					      uint8_t ch_freq_seg1,
291 					      uint32_t *cfreq1,
292 					      uint32_t *cfreq2,
293 					      uint32_t *phy_mode,
294 					      bool *dfs_set_cfreq2,
295 					      bool *set_agile)
296 {
297 	struct wlan_dfs *dfs;
298 
299 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
300 	if (!dfs) {
301 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
302 		return  QDF_STATUS_E_FAILURE;
303 	}
304 
305 	dfs_find_vht80_chan_for_precac(dfs,
306 				       chan_mode,
307 				       ch_freq_seg1,
308 				       cfreq1,
309 				       cfreq2,
310 				       phy_mode,
311 				       dfs_set_cfreq2,
312 				       set_agile);
313 
314 	return  QDF_STATUS_SUCCESS;
315 }
316 EXPORT_SYMBOL(tgt_dfs_find_vht80_chan_for_precac);
317 
318 QDF_STATUS tgt_dfs_process_radar_ind(struct wlan_objmgr_pdev *pdev,
319 				     struct radar_found_info *radar_found)
320 {
321 	struct wlan_dfs *dfs;
322 
323 	if (!pdev) {
324 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null pdev");
325 		return QDF_STATUS_E_FAILURE;
326 	}
327 
328 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
329 	if (!dfs) {
330 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is null");
331 		return QDF_STATUS_E_FAILURE;
332 	}
333 
334 	return dfs_process_radar_ind(dfs, radar_found);
335 }
336 EXPORT_SYMBOL(tgt_dfs_process_radar_ind);
337 
338 #ifndef QCA_MCL_DFS_SUPPORT
339 QDF_STATUS tgt_dfs_cac_complete(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id)
340 {
341 	return QDF_STATUS_SUCCESS;
342 }
343 #else
344 QDF_STATUS tgt_dfs_cac_complete(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id)
345 {
346 	dfs_mlme_proc_cac(pdev, vdev_id);
347 
348 	return QDF_STATUS_SUCCESS;
349 }
350 #endif
351 EXPORT_SYMBOL(tgt_dfs_cac_complete);
352 
353 QDF_STATUS tgt_dfs_reg_ev_handler(struct wlan_objmgr_psoc *psoc,
354 				  bool dfs_offload)
355 {
356 	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
357 
358 	if (!psoc) {
359 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null psoc");
360 		return QDF_STATUS_E_FAILURE;
361 	}
362 
363 	dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
364 	if (!dfs_tx_ops) {
365 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null dfs_tx_ops");
366 		return QDF_STATUS_E_FAILURE;
367 	}
368 
369 	if (dfs_tx_ops->dfs_reg_ev_handler)
370 		return dfs_tx_ops->dfs_reg_ev_handler(psoc, dfs_offload);
371 
372 	return QDF_STATUS_E_FAILURE;
373 }
374 EXPORT_SYMBOL(tgt_dfs_reg_ev_handler);
375 
376 QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev)
377 {
378 	struct wlan_dfs *dfs;
379 
380 	dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev);
381 	if (!dfs) {
382 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL");
383 		return  QDF_STATUS_E_FAILURE;
384 	}
385 
386 	dfs_stop(dfs);
387 
388 	return QDF_STATUS_SUCCESS;
389 }
390 EXPORT_SYMBOL(tgt_dfs_stop);
391 
392 QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev,
393 		struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test)
394 {
395 	struct wlan_objmgr_psoc *psoc;
396 	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
397 
398 	psoc = wlan_pdev_get_psoc(pdev);
399 	if (!psoc) {
400 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null");
401 		return QDF_STATUS_E_FAILURE;
402 	}
403 
404 	dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
405 	if (dfs_tx_ops && dfs_tx_ops->dfs_process_emulate_bang_radar_cmd)
406 		return dfs_tx_ops->dfs_process_emulate_bang_radar_cmd(pdev,
407 				dfs_unit_test);
408 	else
409 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
410 			"dfs_tx_ops=%pK", dfs_tx_ops);
411 
412 	return QDF_STATUS_E_FAILURE;
413 }
414 EXPORT_SYMBOL(tgt_dfs_process_emulate_bang_radar_cmd);
415 
416 #ifdef QCA_MCL_DFS_SUPPORT
417 QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev)
418 {
419 	struct wlan_objmgr_psoc *psoc;
420 	struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
421 	struct dfs_soc_priv_obj *soc_obj;
422 
423 	psoc = wlan_pdev_get_psoc(pdev);
424 	if (!psoc) {
425 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null");
426 		return QDF_STATUS_E_FAILURE;
427 	}
428 
429 	soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
430 							WLAN_UMAC_COMP_DFS);
431 	if (!soc_obj) {
432 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
433 			"Failed to get dfs psoc component");
434 		return QDF_STATUS_E_FAILURE;
435 	}
436 	dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
437 	if (dfs_tx_ops && dfs_tx_ops->dfs_set_phyerr_filter_offload)
438 		return dfs_tx_ops->dfs_set_phyerr_filter_offload(pdev,
439 				soc_obj->dfs_is_phyerr_filter_offload);
440 	else
441 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
442 			"dfs_tx_ops=%pK", dfs_tx_ops);
443 
444 	return QDF_STATUS_E_FAILURE;
445 }
446 EXPORT_SYMBOL(tgt_dfs_set_phyerr_filter_offload);
447 #endif
448