xref: /wlan-driver/qca-wifi-host-cmn/umac/dfs/core/src/misc/dfs.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2002-2006, Atheros Communications Inc.
4*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
5*5113495bSYour Name  *
6*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for any
7*5113495bSYour Name  * purpose with or without fee is hereby granted, provided that the above
8*5113495bSYour Name  * copyright notice and this permission notice appear in all copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*5113495bSYour Name  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*5113495bSYour Name  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*5113495bSYour Name  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*5113495bSYour Name  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*5113495bSYour Name  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*5113495bSYour Name  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name  */
18*5113495bSYour Name 
19*5113495bSYour Name /**
20*5113495bSYour Name  * DOC: This file contains the dfs_attach() and dfs_detach() functions as well
21*5113495bSYour Name  * as the dfs_control() function which is used to process ioctls related to DFS.
22*5113495bSYour Name  * For Linux/Mac,  "radartool" is the command line tool that can be used to call
23*5113495bSYour Name  * various ioctls to set and get radar detection thresholds.
24*5113495bSYour Name  */
25*5113495bSYour Name 
26*5113495bSYour Name #include "../dfs_zero_cac.h"
27*5113495bSYour Name #include "wlan_dfs_lmac_api.h"
28*5113495bSYour Name #include "wlan_dfs_mlme_api.h"
29*5113495bSYour Name #include "wlan_dfs_tgt_api.h"
30*5113495bSYour Name #include "../dfs_internal.h"
31*5113495bSYour Name #include "../dfs_filter_init.h"
32*5113495bSYour Name #include <wlan_objmgr_vdev_obj.h>
33*5113495bSYour Name #include "wlan_dfs_utils_api.h"
34*5113495bSYour Name #include "../dfs_process_radar_found_ind.h"
35*5113495bSYour Name #include "../dfs_partial_offload_radar.h"
36*5113495bSYour Name 
37*5113495bSYour Name /* Disable NOL in FW. */
38*5113495bSYour Name #define DISABLE_NOL_FW 0
39*5113495bSYour Name 
40*5113495bSYour Name #ifndef WLAN_DFS_STATIC_MEM_ALLOC
41*5113495bSYour Name /**
42*5113495bSYour Name  * dfs_alloc_wlan_dfs() - allocate wlan_dfs buffer
43*5113495bSYour Name  *
44*5113495bSYour Name  * Return: buffer, null on failure.
45*5113495bSYour Name  */
dfs_alloc_wlan_dfs(void)46*5113495bSYour Name static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void)
47*5113495bSYour Name {
48*5113495bSYour Name 	return qdf_mem_malloc(sizeof(struct wlan_dfs));
49*5113495bSYour Name }
50*5113495bSYour Name 
51*5113495bSYour Name /**
52*5113495bSYour Name  * dfs_free_wlan_dfs() - Free wlan_dfs buffer
53*5113495bSYour Name  * @dfs: wlan_dfs buffer pointer
54*5113495bSYour Name  *
55*5113495bSYour Name  * Return: None
56*5113495bSYour Name  */
dfs_free_wlan_dfs(struct wlan_dfs * dfs)57*5113495bSYour Name static inline void dfs_free_wlan_dfs(struct wlan_dfs *dfs)
58*5113495bSYour Name {
59*5113495bSYour Name 	qdf_mem_free(dfs);
60*5113495bSYour Name }
61*5113495bSYour Name 
62*5113495bSYour Name /**
63*5113495bSYour Name  * dfs_alloc_dfs_curchan() - allocate dfs_channel buffer
64*5113495bSYour Name  *
65*5113495bSYour Name  * Return: buffer, null on failure.
66*5113495bSYour Name  */
dfs_alloc_dfs_curchan(void)67*5113495bSYour Name static inline struct dfs_channel *dfs_alloc_dfs_curchan(void)
68*5113495bSYour Name {
69*5113495bSYour Name 	return qdf_mem_malloc(sizeof(struct dfs_channel));
70*5113495bSYour Name }
71*5113495bSYour Name 
dfs_alloc_dfs_prevchan(void)72*5113495bSYour Name static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void)
73*5113495bSYour Name {
74*5113495bSYour Name 	return qdf_mem_malloc(sizeof(struct dfs_channel));
75*5113495bSYour Name }
76*5113495bSYour Name 
77*5113495bSYour Name /**
78*5113495bSYour Name  * dfs_free_dfs_chan() - Free dfs_channel buffer
79*5113495bSYour Name  * @dfs_chan: dfs_channel buffer pointer
80*5113495bSYour Name  *
81*5113495bSYour Name  * Return: None
82*5113495bSYour Name  */
dfs_free_dfs_chan(struct dfs_channel * dfs_chan)83*5113495bSYour Name static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan)
84*5113495bSYour Name {
85*5113495bSYour Name 	qdf_mem_free(dfs_chan);
86*5113495bSYour Name }
87*5113495bSYour Name 
88*5113495bSYour Name #else
89*5113495bSYour Name 
90*5113495bSYour Name /* Static buffers for DFS objects */
91*5113495bSYour Name static struct wlan_dfs global_dfs;
92*5113495bSYour Name static struct dfs_channel global_dfs_curchan;
93*5113495bSYour Name static struct dfs_channel global_dfs_prevchan;
94*5113495bSYour Name 
dfs_alloc_wlan_dfs(void)95*5113495bSYour Name static inline struct wlan_dfs *dfs_alloc_wlan_dfs(void)
96*5113495bSYour Name {
97*5113495bSYour Name 	return &global_dfs;
98*5113495bSYour Name }
99*5113495bSYour Name 
dfs_free_wlan_dfs(struct wlan_dfs * dfs)100*5113495bSYour Name static inline void dfs_free_wlan_dfs(struct wlan_dfs *dfs)
101*5113495bSYour Name {
102*5113495bSYour Name }
103*5113495bSYour Name 
dfs_alloc_dfs_curchan(void)104*5113495bSYour Name static inline struct dfs_channel *dfs_alloc_dfs_curchan(void)
105*5113495bSYour Name {
106*5113495bSYour Name 	return &global_dfs_curchan;
107*5113495bSYour Name }
108*5113495bSYour Name 
dfs_alloc_dfs_prevchan(void)109*5113495bSYour Name static inline struct dfs_channel *dfs_alloc_dfs_prevchan(void)
110*5113495bSYour Name {
111*5113495bSYour Name 	return &global_dfs_prevchan;
112*5113495bSYour Name }
113*5113495bSYour Name 
dfs_free_dfs_chan(struct dfs_channel * dfs_chan)114*5113495bSYour Name static inline void dfs_free_dfs_chan(struct dfs_channel *dfs_chan)
115*5113495bSYour Name {
116*5113495bSYour Name }
117*5113495bSYour Name #endif
118*5113495bSYour Name 
119*5113495bSYour Name /*
120*5113495bSYour Name  * dfs_testtimer_task() - Sends CSA in the current channel.
121*5113495bSYour Name  *
122*5113495bSYour Name  * When the user sets usenol to 0 and inject the RADAR, AP does not mark the
123*5113495bSYour Name  * channel as RADAR and does not add the channel to NOL. It sends the CSA in
124*5113495bSYour Name  * the current channel.
125*5113495bSYour Name  *
126*5113495bSYour Name  * NB: not using kernel-doc format since the kernel-doc script doesn't
127*5113495bSYour Name  *     handle the os_timer_func() macro
128*5113495bSYour Name  */
129*5113495bSYour Name #ifdef CONFIG_CHAN_FREQ_API
os_timer_func(dfs_testtimer_task)130*5113495bSYour Name static os_timer_func(dfs_testtimer_task)
131*5113495bSYour Name {
132*5113495bSYour Name 	struct wlan_dfs *dfs = NULL;
133*5113495bSYour Name 
134*5113495bSYour Name 	OS_GET_TIMER_ARG(dfs, struct wlan_dfs *);
135*5113495bSYour Name 	dfs->wlan_dfstest = 0;
136*5113495bSYour Name 
137*5113495bSYour Name 	/*
138*5113495bSYour Name 	 * Flip the channel back to the original channel.
139*5113495bSYour Name 	 * Make sure this is done properly with a CSA.
140*5113495bSYour Name 	 */
141*5113495bSYour Name 	dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "go back to channel %d",
142*5113495bSYour Name 		  dfs->wlan_dfstest_ieeechan);
143*5113495bSYour Name 	dfs_mlme_start_csa_for_freq(dfs->dfs_pdev_obj,
144*5113495bSYour Name 				    dfs->wlan_dfstest_ieeechan,
145*5113495bSYour Name 				    dfs->dfs_curchan->dfs_ch_freq,
146*5113495bSYour Name 				    dfs->dfs_curchan->dfs_ch_mhz_freq_seg2,
147*5113495bSYour Name 				    dfs->dfs_curchan->dfs_ch_flags);
148*5113495bSYour Name }
149*5113495bSYour Name #endif
150*5113495bSYour Name 
dfs_get_debug_info(struct wlan_dfs * dfs,void * data)151*5113495bSYour Name int dfs_get_debug_info(struct wlan_dfs *dfs, void *data)
152*5113495bSYour Name {
153*5113495bSYour Name 	if (data)
154*5113495bSYour Name 		*(uint32_t *)data = dfs->dfs_proc_phyerr;
155*5113495bSYour Name 
156*5113495bSYour Name 	return (int)dfs->dfs_proc_phyerr;
157*5113495bSYour Name }
158*5113495bSYour Name 
dfs_main_task_testtimer_init(struct wlan_dfs * dfs)159*5113495bSYour Name void dfs_main_task_testtimer_init(struct wlan_dfs *dfs)
160*5113495bSYour Name {
161*5113495bSYour Name 	qdf_timer_init(NULL,
162*5113495bSYour Name 		&(dfs->wlan_dfstesttimer),
163*5113495bSYour Name 		dfs_testtimer_task, (void *)dfs,
164*5113495bSYour Name 		QDF_TIMER_TYPE_WAKE_APPS);
165*5113495bSYour Name }
166*5113495bSYour Name 
dfs_create_object(struct wlan_dfs ** dfs)167*5113495bSYour Name int dfs_create_object(struct wlan_dfs **dfs)
168*5113495bSYour Name {
169*5113495bSYour Name 	*dfs = dfs_alloc_wlan_dfs();
170*5113495bSYour Name 	if (!(*dfs))
171*5113495bSYour Name 		return 1;
172*5113495bSYour Name 
173*5113495bSYour Name 	qdf_mem_zero(*dfs, sizeof(**dfs));
174*5113495bSYour Name 
175*5113495bSYour Name 	(*dfs)->dfs_curchan = dfs_alloc_dfs_curchan();
176*5113495bSYour Name 	if (!((*dfs)->dfs_curchan)) {
177*5113495bSYour Name 		dfs_free_wlan_dfs(*dfs);
178*5113495bSYour Name 		return 1;
179*5113495bSYour Name 	}
180*5113495bSYour Name 
181*5113495bSYour Name 	(*dfs)->dfs_prevchan = dfs_alloc_dfs_prevchan();
182*5113495bSYour Name 	if (!((*dfs)->dfs_prevchan)) {
183*5113495bSYour Name 		dfs_free_wlan_dfs(*dfs);
184*5113495bSYour Name 		return 1;
185*5113495bSYour Name 	}
186*5113495bSYour Name 	qdf_mem_zero((*dfs)->dfs_prevchan, sizeof(struct dfs_channel));
187*5113495bSYour Name 	return 0;
188*5113495bSYour Name }
189*5113495bSYour Name 
190*5113495bSYour Name #if defined(QCA_DFS_BW_PUNCTURE)
191*5113495bSYour Name #if defined(CONFIG_REG_CLIENT)
dfs_puncture_init(struct wlan_dfs * dfs)192*5113495bSYour Name static void dfs_puncture_init(struct wlan_dfs *dfs)
193*5113495bSYour Name {
194*5113495bSYour Name 	/*
195*5113495bSYour Name 	 * Enable sub chan DFS type if QCA_DFS_BW_PUNCTURE defined, or all
196*5113495bSYour Name 	 * bonded operation freq will be affected and disabled for nol,
197*5113495bSYour Name 	 * puncture can't work, always need to switch freq.
198*5113495bSYour Name 	 */
199*5113495bSYour Name 	dfs_set_nol_subchannel_marking(dfs, true);
200*5113495bSYour Name 	dfs->dfs_use_puncture = true;
201*5113495bSYour Name }
202*5113495bSYour Name #else
dfs_puncture_init(struct wlan_dfs * dfs)203*5113495bSYour Name static void dfs_puncture_init(struct wlan_dfs *dfs)
204*5113495bSYour Name {
205*5113495bSYour Name 	uint8_t i;
206*5113495bSYour Name 	struct dfs_punc_obj *dfs_punc_obj;
207*5113495bSYour Name 
208*5113495bSYour Name 	for (i = 0 ; i < N_MAX_PUNC_SM; i++) {
209*5113495bSYour Name 		dfs_punc_obj = &dfs->dfs_punc_lst.dfs_punc_arr[i];
210*5113495bSYour Name 		dfs_punc_cac_timer_attach(dfs, dfs_punc_obj);
211*5113495bSYour Name 	}
212*5113495bSYour Name }
213*5113495bSYour Name #endif
214*5113495bSYour Name #else
dfs_puncture_init(struct wlan_dfs * dfs)215*5113495bSYour Name static inline void dfs_puncture_init(struct wlan_dfs *dfs)
216*5113495bSYour Name {
217*5113495bSYour Name }
218*5113495bSYour Name #endif
219*5113495bSYour Name 
dfs_attach(struct wlan_dfs * dfs)220*5113495bSYour Name int dfs_attach(struct wlan_dfs *dfs)
221*5113495bSYour Name {
222*5113495bSYour Name 	int ret;
223*5113495bSYour Name 
224*5113495bSYour Name 	if (!dfs->dfs_is_offload_enabled) {
225*5113495bSYour Name 		ret = dfs_main_attach(dfs);
226*5113495bSYour Name 
227*5113495bSYour Name 		/*
228*5113495bSYour Name 		 * For full offload we have a wmi handler registered to process
229*5113495bSYour Name 		 * a radar event from firmware in the event of a radar detect.
230*5113495bSYour Name 		 * So, init of timer, dfs_task is not required for
231*5113495bSYour Name 		 * full-offload. dfs_task timer is called in
232*5113495bSYour Name 		 * dfs_main_timer_init within dfs_main_attach for
233*5113495bSYour Name 		 * partial-offload in the event of radar detect.
234*5113495bSYour Name 		 */
235*5113495bSYour Name 		if (ret) {
236*5113495bSYour Name 			dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs_main_attach failed");
237*5113495bSYour Name 			return ret;
238*5113495bSYour Name 		}
239*5113495bSYour Name 	}
240*5113495bSYour Name 	dfs_cac_timer_attach(dfs);
241*5113495bSYour Name 	dfs_zero_cac_attach(dfs);
242*5113495bSYour Name 	dfs_nol_attach(dfs);
243*5113495bSYour Name 	dfs_postnol_attach(dfs);
244*5113495bSYour Name 
245*5113495bSYour Name 	/*
246*5113495bSYour Name 	 * Init of timer ,dfs_testtimer_task is required by both partial
247*5113495bSYour Name 	 * and full offload, indicating test mode timer initialization for both.
248*5113495bSYour Name 	 */
249*5113495bSYour Name 	dfs_main_task_testtimer_init(dfs);
250*5113495bSYour Name 
251*5113495bSYour Name 	dfs_puncture_init(dfs);
252*5113495bSYour Name 
253*5113495bSYour Name 	return 0;
254*5113495bSYour Name }
255*5113495bSYour Name 
dfs_stop(struct wlan_dfs * dfs)256*5113495bSYour Name void dfs_stop(struct wlan_dfs *dfs)
257*5113495bSYour Name {
258*5113495bSYour Name 	dfs_nol_timer_cleanup(dfs);
259*5113495bSYour Name 	dfs_nol_workqueue_cleanup(dfs);
260*5113495bSYour Name 	dfs_clear_nolhistory(dfs);
261*5113495bSYour Name }
262*5113495bSYour Name 
dfs_task_testtimer_reset(struct wlan_dfs * dfs)263*5113495bSYour Name void dfs_task_testtimer_reset(struct wlan_dfs *dfs)
264*5113495bSYour Name {
265*5113495bSYour Name 	if (dfs->wlan_dfstest) {
266*5113495bSYour Name 		qdf_timer_sync_cancel(&dfs->wlan_dfstesttimer);
267*5113495bSYour Name 		dfs->wlan_dfstest = 0;
268*5113495bSYour Name 	}
269*5113495bSYour Name }
270*5113495bSYour Name 
dfs_task_testtimer_detach(struct wlan_dfs * dfs)271*5113495bSYour Name void dfs_task_testtimer_detach(struct wlan_dfs *dfs)
272*5113495bSYour Name {
273*5113495bSYour Name 	qdf_timer_free(&dfs->wlan_dfstesttimer);
274*5113495bSYour Name 	dfs->wlan_dfstest = 0;
275*5113495bSYour Name }
276*5113495bSYour Name 
dfs_reset(struct wlan_dfs * dfs)277*5113495bSYour Name void dfs_reset(struct wlan_dfs *dfs)
278*5113495bSYour Name {
279*5113495bSYour Name 	if (!dfs) {
280*5113495bSYour Name 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
281*5113495bSYour Name 		return;
282*5113495bSYour Name 	}
283*5113495bSYour Name 
284*5113495bSYour Name 	dfs_cac_timer_reset(dfs);
285*5113495bSYour Name 	dfs_zero_cac_reset(dfs);
286*5113495bSYour Name 	if (!dfs->dfs_is_offload_enabled) {
287*5113495bSYour Name 		dfs_main_timer_reset(dfs);
288*5113495bSYour Name 		dfs_host_wait_timer_reset(dfs);
289*5113495bSYour Name 		dfs_false_radarfound_reset_vars(dfs);
290*5113495bSYour Name 	}
291*5113495bSYour Name 	dfs_task_testtimer_reset(dfs);
292*5113495bSYour Name }
293*5113495bSYour Name 
dfs_timer_detach(struct wlan_dfs * dfs)294*5113495bSYour Name void dfs_timer_detach(struct wlan_dfs *dfs)
295*5113495bSYour Name {
296*5113495bSYour Name 	dfs_cac_timer_detach(dfs);
297*5113495bSYour Name 	dfs_puncture_cac_timer_detach(dfs);
298*5113495bSYour Name 	dfs_zero_cac_timer_detach(dfs->dfs_soc_obj);
299*5113495bSYour Name 
300*5113495bSYour Name 	if (!dfs->dfs_is_offload_enabled) {
301*5113495bSYour Name 		dfs_main_timer_detach(dfs);
302*5113495bSYour Name 		dfs_host_wait_timer_detach(dfs);
303*5113495bSYour Name 	}
304*5113495bSYour Name 
305*5113495bSYour Name 	dfs_task_testtimer_detach(dfs);
306*5113495bSYour Name }
307*5113495bSYour Name 
dfs_detach(struct wlan_dfs * dfs)308*5113495bSYour Name void dfs_detach(struct wlan_dfs *dfs)
309*5113495bSYour Name {
310*5113495bSYour Name 	dfs_timer_detach(dfs);
311*5113495bSYour Name 	if (!dfs->dfs_is_offload_enabled)
312*5113495bSYour Name 		dfs_main_detach(dfs);
313*5113495bSYour Name 	dfs_zero_cac_detach(dfs);
314*5113495bSYour Name 	dfs_nol_detach(dfs);
315*5113495bSYour Name }
316*5113495bSYour Name 
317*5113495bSYour Name #ifndef WLAN_DFS_STATIC_MEM_ALLOC
dfs_destroy_object(struct wlan_dfs * dfs)318*5113495bSYour Name void dfs_destroy_object(struct wlan_dfs *dfs)
319*5113495bSYour Name {
320*5113495bSYour Name 	dfs_free_dfs_chan(dfs->dfs_prevchan);
321*5113495bSYour Name 	dfs_free_dfs_chan(dfs->dfs_curchan);
322*5113495bSYour Name 	dfs_free_wlan_dfs(dfs);
323*5113495bSYour Name }
324*5113495bSYour Name #else
dfs_destroy_object(struct wlan_dfs * dfs)325*5113495bSYour Name void dfs_destroy_object(struct wlan_dfs *dfs)
326*5113495bSYour Name {
327*5113495bSYour Name }
328*5113495bSYour Name #endif
329*5113495bSYour Name 
330*5113495bSYour Name /* dfs_set_disable_radar_marking()- Set the flag to mark/unmark a radar flag
331*5113495bSYour Name  * on NOL channel.
332*5113495bSYour Name  * @dfs: Pointer to wlan_dfs structure.
333*5113495bSYour Name  * @disable_radar_marking: Flag to enable/disable marking channel as radar.
334*5113495bSYour Name  */
335*5113495bSYour Name #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD)
dfs_set_disable_radar_marking(struct wlan_dfs * dfs,bool disable_radar_marking)336*5113495bSYour Name static void dfs_set_disable_radar_marking(struct wlan_dfs *dfs,
337*5113495bSYour Name 					  bool disable_radar_marking)
338*5113495bSYour Name {
339*5113495bSYour Name 	dfs->dfs_disable_radar_marking = disable_radar_marking;
340*5113495bSYour Name }
341*5113495bSYour Name #else
dfs_set_disable_radar_marking(struct wlan_dfs * dfs,bool disable_radar_marking)342*5113495bSYour Name static inline void dfs_set_disable_radar_marking(struct wlan_dfs *dfs,
343*5113495bSYour Name 						 bool disable_radar_marking)
344*5113495bSYour Name {
345*5113495bSYour Name }
346*5113495bSYour Name #endif
347*5113495bSYour Name 
348*5113495bSYour Name #if defined(WLAN_DFS_FULL_OFFLOAD) && defined(QCA_DFS_NOL_OFFLOAD)
dfs_get_disable_radar_marking(struct wlan_dfs * dfs)349*5113495bSYour Name bool dfs_get_disable_radar_marking(struct wlan_dfs *dfs)
350*5113495bSYour Name {
351*5113495bSYour Name 	return dfs->dfs_disable_radar_marking;
352*5113495bSYour Name }
353*5113495bSYour Name #endif
354*5113495bSYour Name 
dfs_control(struct wlan_dfs * dfs,u_int id,void * indata,uint32_t insize,void * outdata,uint32_t * outsize)355*5113495bSYour Name int dfs_control(struct wlan_dfs *dfs,
356*5113495bSYour Name 		u_int id,
357*5113495bSYour Name 		void *indata,
358*5113495bSYour Name 		uint32_t insize,
359*5113495bSYour Name 		void *outdata,
360*5113495bSYour Name 		uint32_t *outsize)
361*5113495bSYour Name {
362*5113495bSYour Name 	struct wlan_dfs_phyerr_param peout;
363*5113495bSYour Name 	struct dfs_ioctl_params *dfsparams;
364*5113495bSYour Name 	int error = 0;
365*5113495bSYour Name 	uint32_t val = 0;
366*5113495bSYour Name 	struct dfsreq_nolinfo *nol;
367*5113495bSYour Name 	uint32_t *data = NULL;
368*5113495bSYour Name 	int i;
369*5113495bSYour Name 	int usenol_pdev_param;
370*5113495bSYour Name 
371*5113495bSYour Name 	if (!dfs) {
372*5113495bSYour Name 		dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
373*5113495bSYour Name 		goto bad;
374*5113495bSYour Name 	}
375*5113495bSYour Name 
376*5113495bSYour Name 	switch (id) {
377*5113495bSYour Name 	case DFS_SET_THRESH:
378*5113495bSYour Name 		if (insize < sizeof(struct dfs_ioctl_params) || !indata) {
379*5113495bSYour Name 			dfs_debug(dfs, WLAN_DEBUG_DFS1,
380*5113495bSYour Name 					"insize = %d, expected = %zu bytes, indata = %pK",
381*5113495bSYour Name 					insize,
382*5113495bSYour Name 					sizeof(struct dfs_ioctl_params),
383*5113495bSYour Name 					indata);
384*5113495bSYour Name 			error = -EINVAL;
385*5113495bSYour Name 			break;
386*5113495bSYour Name 		}
387*5113495bSYour Name 		dfsparams = (struct dfs_ioctl_params *)indata;
388*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_FIRPWR,
389*5113495bSYour Name 					dfsparams->dfs_firpwr))
390*5113495bSYour Name 			error = -EINVAL;
391*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RRSSI,
392*5113495bSYour Name 					dfsparams->dfs_rrssi))
393*5113495bSYour Name 			error = -EINVAL;
394*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_HEIGHT,
395*5113495bSYour Name 					dfsparams->dfs_height))
396*5113495bSYour Name 			error = -EINVAL;
397*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_PRSSI,
398*5113495bSYour Name 					dfsparams->dfs_prssi))
399*5113495bSYour Name 			error = -EINVAL;
400*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_INBAND,
401*5113495bSYour Name 					dfsparams->dfs_inband))
402*5113495bSYour Name 			error = -EINVAL;
403*5113495bSYour Name 
404*5113495bSYour Name 		/* 5413 speicfic. */
405*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELPWR,
406*5113495bSYour Name 					dfsparams->dfs_relpwr))
407*5113495bSYour Name 			error = -EINVAL;
408*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_RELSTEP,
409*5113495bSYour Name 					dfsparams->dfs_relstep))
410*5113495bSYour Name 			error = -EINVAL;
411*5113495bSYour Name 		if (!dfs_set_thresholds(dfs, DFS_PARAM_MAXLEN,
412*5113495bSYour Name 					dfsparams->dfs_maxlen))
413*5113495bSYour Name 			error = -EINVAL;
414*5113495bSYour Name 		break;
415*5113495bSYour Name 	case DFS_BANGRADAR:
416*5113495bSYour Name 		error = dfs_bang_radar(dfs, indata, insize);
417*5113495bSYour Name 		break;
418*5113495bSYour Name 	case DFS_GET_THRESH:
419*5113495bSYour Name 		if (!outdata || !outsize ||
420*5113495bSYour Name 				*outsize < sizeof(struct dfs_ioctl_params)) {
421*5113495bSYour Name 			error = -EINVAL;
422*5113495bSYour Name 			break;
423*5113495bSYour Name 		}
424*5113495bSYour Name 		*outsize = sizeof(struct dfs_ioctl_params);
425*5113495bSYour Name 		dfsparams = (struct dfs_ioctl_params *) outdata;
426*5113495bSYour Name 
427*5113495bSYour Name 		qdf_mem_zero(&peout, sizeof(struct wlan_dfs_phyerr_param));
428*5113495bSYour Name 
429*5113495bSYour Name 		/* Fetch the DFS thresholds using the internal representation */
430*5113495bSYour Name 		(void) dfs_get_thresholds(dfs, &peout);
431*5113495bSYour Name 
432*5113495bSYour Name 		/* Convert them to the dfs IOCTL representation. */
433*5113495bSYour Name 		wlan_dfs_dfsparam_to_ioctlparam(&peout, dfsparams);
434*5113495bSYour Name 		break;
435*5113495bSYour Name 	case DFS_RADARDETECTS:
436*5113495bSYour Name 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
437*5113495bSYour Name 			error = -EINVAL;
438*5113495bSYour Name 			break;
439*5113495bSYour Name 		}
440*5113495bSYour Name 		*outsize = sizeof(uint32_t);
441*5113495bSYour Name 		*((uint32_t *)outdata) = dfs->wlan_dfs_stats.num_radar_detects;
442*5113495bSYour Name 		break;
443*5113495bSYour Name 	case DFS_DISABLE_DETECT:
444*5113495bSYour Name 		dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
445*5113495bSYour Name 		dfs->dfs_proc_phyerr &= ~DFS_SECOND_SEGMENT_RADAR_EN;
446*5113495bSYour Name 		dfs->dfs_ignore_dfs = 1;
447*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
448*5113495bSYour Name 			  "enable detects, ignore_dfs %d",
449*5113495bSYour Name 			  dfs->dfs_ignore_dfs ? 1 : 0);
450*5113495bSYour Name 		break;
451*5113495bSYour Name 	case DFS_ENABLE_DETECT:
452*5113495bSYour Name 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
453*5113495bSYour Name 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
454*5113495bSYour Name 		dfs->dfs_ignore_dfs = 0;
455*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
456*5113495bSYour Name 			  "enable detects, ignore_dfs %d",
457*5113495bSYour Name 			  dfs->dfs_ignore_dfs ? 1 : 0);
458*5113495bSYour Name 		break;
459*5113495bSYour Name 	case DFS_DISABLE_FFT:
460*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
461*5113495bSYour Name 			  "TODO disable FFT val=0x%x", val);
462*5113495bSYour Name 		break;
463*5113495bSYour Name 	case DFS_ENABLE_FFT:
464*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
465*5113495bSYour Name 			  "TODO enable FFT val=0x%x", val);
466*5113495bSYour Name 		break;
467*5113495bSYour Name 	case DFS_SET_DEBUG_LEVEL:
468*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
469*5113495bSYour Name 			error = -EINVAL;
470*5113495bSYour Name 			break;
471*5113495bSYour Name 		}
472*5113495bSYour Name 		dfs->dfs_debug_mask = *(uint32_t *)indata;
473*5113495bSYour Name 
474*5113495bSYour Name 		/* Do not allow user to set the ALWAYS/MAX bit.
475*5113495bSYour Name 		 * It will be used internally  by dfs print macro(s)
476*5113495bSYour Name 		 * to print messages when dfs is NULL.
477*5113495bSYour Name 		 */
478*5113495bSYour Name 		dfs->dfs_debug_mask &= ~(WLAN_DEBUG_DFS_ALWAYS);
479*5113495bSYour Name 
480*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
481*5113495bSYour Name 			  "debug level now = 0x%x", dfs->dfs_debug_mask);
482*5113495bSYour Name 		if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS3) {
483*5113495bSYour Name 			/* Enable debug Radar Event */
484*5113495bSYour Name 			dfs->dfs_event_log_on = 1;
485*5113495bSYour Name 		} else if ((utils_get_dfsdomain(dfs->dfs_pdev_obj) ==
486*5113495bSYour Name 		    DFS_FCC_DOMAIN) &&
487*5113495bSYour Name 		    lmac_is_host_dfs_check_support_enabled(dfs->dfs_pdev_obj)) {
488*5113495bSYour Name 			dfs->dfs_event_log_on = 1;
489*5113495bSYour Name 		} else {
490*5113495bSYour Name 			dfs->dfs_event_log_on = 0;
491*5113495bSYour Name 		}
492*5113495bSYour Name 		break;
493*5113495bSYour Name 	case DFS_SET_FALSE_RSSI_THRES:
494*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
495*5113495bSYour Name 			error = -EINVAL;
496*5113495bSYour Name 			break;
497*5113495bSYour Name 		}
498*5113495bSYour Name 		dfs->wlan_dfs_false_rssi_thres = *(uint32_t *)indata;
499*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
500*5113495bSYour Name 			  "false RSSI threshold now = 0x%x",
501*5113495bSYour Name 			  dfs->wlan_dfs_false_rssi_thres);
502*5113495bSYour Name 		break;
503*5113495bSYour Name 	case DFS_SET_PEAK_MAG:
504*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
505*5113495bSYour Name 			error = -EINVAL;
506*5113495bSYour Name 			break;
507*5113495bSYour Name 		}
508*5113495bSYour Name 		dfs->wlan_dfs_peak_mag = *(uint32_t *)indata;
509*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
510*5113495bSYour Name 			  "peak_mag now = 0x%x",
511*5113495bSYour Name 				dfs->wlan_dfs_peak_mag);
512*5113495bSYour Name 		break;
513*5113495bSYour Name 	case DFS_GET_CAC_VALID_TIME:
514*5113495bSYour Name 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
515*5113495bSYour Name 			error = -EINVAL;
516*5113495bSYour Name 			break;
517*5113495bSYour Name 		}
518*5113495bSYour Name 		*outsize = sizeof(uint32_t);
519*5113495bSYour Name 		*((uint32_t *)outdata) = dfs->dfs_cac_valid_time;
520*5113495bSYour Name 		break;
521*5113495bSYour Name 	case DFS_SET_CAC_VALID_TIME:
522*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
523*5113495bSYour Name 			error = -EINVAL;
524*5113495bSYour Name 			break;
525*5113495bSYour Name 		}
526*5113495bSYour Name 		dfs->dfs_cac_valid_time = *(uint32_t *)indata;
527*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
528*5113495bSYour Name 			  "dfs timeout = %d", dfs->dfs_cac_valid_time);
529*5113495bSYour Name 		break;
530*5113495bSYour Name 	case DFS_IGNORE_CAC:
531*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
532*5113495bSYour Name 			error = -EINVAL;
533*5113495bSYour Name 			break;
534*5113495bSYour Name 		}
535*5113495bSYour Name 
536*5113495bSYour Name 		if (*(uint32_t *)indata)
537*5113495bSYour Name 			dfs->dfs_ignore_cac = 1;
538*5113495bSYour Name 		else
539*5113495bSYour Name 			dfs->dfs_ignore_cac = 0;
540*5113495bSYour Name 
541*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
542*5113495bSYour Name 			  "ignore cac = 0x%x", dfs->dfs_ignore_cac);
543*5113495bSYour Name 		break;
544*5113495bSYour Name 	case DFS_SET_NOL_TIMEOUT:
545*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
546*5113495bSYour Name 			error = -EINVAL;
547*5113495bSYour Name 			break;
548*5113495bSYour Name 		}
549*5113495bSYour Name 		if (*(int *)indata)
550*5113495bSYour Name 			dfs->wlan_dfs_nol_timeout = *(int *)indata;
551*5113495bSYour Name 		else
552*5113495bSYour Name 			dfs->wlan_dfs_nol_timeout = DFS_NOL_TIMEOUT_S;
553*5113495bSYour Name 
554*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS, "nol timeout = %d sec",
555*5113495bSYour Name 			  dfs->wlan_dfs_nol_timeout);
556*5113495bSYour Name 		break;
557*5113495bSYour Name 	case DFS_MUTE_TIME:
558*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
559*5113495bSYour Name 			error = -EINVAL;
560*5113495bSYour Name 			break;
561*5113495bSYour Name 		}
562*5113495bSYour Name 		data = (uint32_t *) indata;
563*5113495bSYour Name 		dfs->wlan_dfstesttime = *data;
564*5113495bSYour Name 		dfs->wlan_dfstesttime *= (1000); /* convert sec into ms */
565*5113495bSYour Name 		break;
566*5113495bSYour Name 	case DFS_GET_USENOL:
567*5113495bSYour Name 		if (!outdata || !outsize || *outsize < sizeof(uint32_t)) {
568*5113495bSYour Name 			error = -EINVAL;
569*5113495bSYour Name 			break;
570*5113495bSYour Name 		}
571*5113495bSYour Name 		*outsize = sizeof(uint32_t);
572*5113495bSYour Name 		*((uint32_t *)outdata) = dfs->dfs_use_nol;
573*5113495bSYour Name 
574*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
575*5113495bSYour Name 			  "#Phyerr=%d, #false detect=%d, #queued=%d",
576*5113495bSYour Name 			  dfs->dfs_phyerr_count,
577*5113495bSYour Name 			  dfs->dfs_phyerr_reject_count,
578*5113495bSYour Name 			  dfs->dfs_phyerr_queued_count);
579*5113495bSYour Name 
580*5113495bSYour Name 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
581*5113495bSYour Name 			 "dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d",
582*5113495bSYour Name 			 dfs->dfs_phyerr_freq_min,
583*5113495bSYour Name 			 dfs->dfs_phyerr_freq_max);
584*5113495bSYour Name 
585*5113495bSYour Name 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
586*5113495bSYour Name 			 "Total radar events detected=%d, entries in the radar queue follows:",
587*5113495bSYour Name 			 dfs->dfs_event_log_count);
588*5113495bSYour Name 
589*5113495bSYour Name 		for (i = 0; (i < DFS_EVENT_LOG_SIZE) &&
590*5113495bSYour Name 				(i < dfs->dfs_event_log_count); i++) {
591*5113495bSYour Name #define FREQ_OFFSET1 ((int)dfs->radar_log[i].freq_offset_khz / 1000)
592*5113495bSYour Name #define FREQ_OFFSET2 ((int)abs(dfs->radar_log[i].freq_offset_khz) % 1000)
593*5113495bSYour Name 			dfs_debug(dfs, WLAN_DEBUG_DFS,
594*5113495bSYour Name 				  "ts=%llu diff_ts=%u rssi=%u dur=%u, is_chirp=%d, seg_id=%d, sidx=%d, freq_offset=%d.%dMHz, peak_mag=%d, total_gain=%d, mb_gain=%d, relpwr_db=%d, delta_diff=%d, delta_peak=%d, psidx_diff=%d\n",
595*5113495bSYour Name 				  dfs->radar_log[i].ts,
596*5113495bSYour Name 				  dfs->radar_log[i].diff_ts,
597*5113495bSYour Name 				  dfs->radar_log[i].rssi,
598*5113495bSYour Name 				  dfs->radar_log[i].dur,
599*5113495bSYour Name 				  dfs->radar_log[i].is_chirp,
600*5113495bSYour Name 				  dfs->radar_log[i].seg_id,
601*5113495bSYour Name 				  dfs->radar_log[i].sidx,
602*5113495bSYour Name 				  FREQ_OFFSET1,
603*5113495bSYour Name 				  FREQ_OFFSET2,
604*5113495bSYour Name 				  dfs->radar_log[i].peak_mag,
605*5113495bSYour Name 				  dfs->radar_log[i].total_gain,
606*5113495bSYour Name 				  dfs->radar_log[i].mb_gain,
607*5113495bSYour Name 				  dfs->radar_log[i].relpwr_db,
608*5113495bSYour Name 				  dfs->radar_log[i].delta_diff,
609*5113495bSYour Name 				  dfs->radar_log[i].delta_peak,
610*5113495bSYour Name 				  dfs->radar_log[i].psidx_diff);
611*5113495bSYour Name 		}
612*5113495bSYour Name 		dfs->dfs_event_log_count = 0;
613*5113495bSYour Name 		dfs->dfs_phyerr_count = 0;
614*5113495bSYour Name 		dfs->dfs_phyerr_reject_count = 0;
615*5113495bSYour Name 		dfs->dfs_phyerr_queued_count = 0;
616*5113495bSYour Name 		dfs->dfs_phyerr_freq_min = 0x7fffffff;
617*5113495bSYour Name 		dfs->dfs_phyerr_freq_max = 0;
618*5113495bSYour Name 		break;
619*5113495bSYour Name 	case DFS_SET_USENOL:
620*5113495bSYour Name 		if (insize < sizeof(uint32_t) || !indata) {
621*5113495bSYour Name 			error = -EINVAL;
622*5113495bSYour Name 			break;
623*5113495bSYour Name 		}
624*5113495bSYour Name 		dfs->dfs_use_nol = *(uint32_t *)indata;
625*5113495bSYour Name 		usenol_pdev_param = dfs->dfs_use_nol;
626*5113495bSYour Name 		if (dfs->dfs_is_offload_enabled) {
627*5113495bSYour Name 			if (dfs->dfs_use_nol ==
628*5113495bSYour Name 				USENOL_ENABLE_NOL_HOST_DISABLE_NOL_FW)
629*5113495bSYour Name 				usenol_pdev_param = DISABLE_NOL_FW;
630*5113495bSYour Name 			tgt_dfs_send_usenol_pdev_param(dfs->dfs_pdev_obj,
631*5113495bSYour Name 						       usenol_pdev_param);
632*5113495bSYour Name 		}
633*5113495bSYour Name 		break;
634*5113495bSYour Name 	case DFS_SET_DISABLE_RADAR_MARKING:
635*5113495bSYour Name 		if (dfs->dfs_is_offload_enabled &&
636*5113495bSYour Name 		    (utils_get_dfsdomain(dfs->dfs_pdev_obj) ==
637*5113495bSYour Name 			 DFS_FCC_DOMAIN)) {
638*5113495bSYour Name 			if (insize < sizeof(uint32_t) || !indata) {
639*5113495bSYour Name 				error = -EINVAL;
640*5113495bSYour Name 				break;
641*5113495bSYour Name 			}
642*5113495bSYour Name 			dfs_set_disable_radar_marking(dfs, *(uint8_t *)indata);
643*5113495bSYour Name 		}
644*5113495bSYour Name 		break;
645*5113495bSYour Name 	case DFS_GET_DISABLE_RADAR_MARKING:
646*5113495bSYour Name 		if (!outdata || !outsize || *outsize < sizeof(uint8_t)) {
647*5113495bSYour Name 			error = -EINVAL;
648*5113495bSYour Name 			break;
649*5113495bSYour Name 		}
650*5113495bSYour Name 		if (dfs->dfs_is_offload_enabled) {
651*5113495bSYour Name 			*outsize = sizeof(uint8_t);
652*5113495bSYour Name 			*((uint8_t *)outdata) =
653*5113495bSYour Name 				dfs_get_disable_radar_marking(dfs);
654*5113495bSYour Name 		}
655*5113495bSYour Name 		break;
656*5113495bSYour Name 	case DFS_GET_NOL:
657*5113495bSYour Name 		if (!outdata || !outsize ||
658*5113495bSYour Name 				*outsize < sizeof(struct dfsreq_nolinfo)) {
659*5113495bSYour Name 			error = -EINVAL;
660*5113495bSYour Name 			break;
661*5113495bSYour Name 		}
662*5113495bSYour Name 		*outsize = sizeof(struct dfsreq_nolinfo);
663*5113495bSYour Name 		nol = (struct dfsreq_nolinfo *)outdata;
664*5113495bSYour Name 		DFS_GET_NOL_LOCKED(dfs,
665*5113495bSYour Name 				(struct dfsreq_nolelem *)nol->dfs_nol,
666*5113495bSYour Name 				&nol->dfs_ch_nchans);
667*5113495bSYour Name 		DFS_PRINT_NOL_LOCKED(dfs);
668*5113495bSYour Name 		break;
669*5113495bSYour Name 	case DFS_SET_NOL:
670*5113495bSYour Name 		if (insize < sizeof(struct dfsreq_nolinfo) || !indata) {
671*5113495bSYour Name 			error = -EINVAL;
672*5113495bSYour Name 			break;
673*5113495bSYour Name 		}
674*5113495bSYour Name 		nol = (struct dfsreq_nolinfo *) indata;
675*5113495bSYour Name 		dfs_set_nol(dfs,
676*5113495bSYour Name 				(struct dfsreq_nolelem *)nol->dfs_nol,
677*5113495bSYour Name 				nol->dfs_ch_nchans);
678*5113495bSYour Name 		break;
679*5113495bSYour Name 	case DFS_SHOW_NOL:
680*5113495bSYour Name 		DFS_PRINT_NOL_LOCKED(dfs);
681*5113495bSYour Name 		break;
682*5113495bSYour Name 	case DFS_SHOW_NOLHISTORY:
683*5113495bSYour Name 		dfs_print_nolhistory(dfs);
684*5113495bSYour Name 		break;
685*5113495bSYour Name 	case DFS_SHOW_PRECAC_LISTS:
686*5113495bSYour Name 		dfs_print_precaclists(dfs);
687*5113495bSYour Name 		break;
688*5113495bSYour Name 	case DFS_RESET_PRECAC_LISTS:
689*5113495bSYour Name 		dfs_reset_precac_lists(dfs);
690*5113495bSYour Name 		break;
691*5113495bSYour Name 	case DFS_INJECT_SEQUENCE:
692*5113495bSYour Name 		error = dfs_inject_synthetic_pulse_sequence(dfs, indata);
693*5113495bSYour Name 		if (error)
694*5113495bSYour Name 			dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
695*5113495bSYour Name 				  "Not injected Synthetic pulse");
696*5113495bSYour Name 		break;
697*5113495bSYour Name 
698*5113495bSYour Name 	case DFS_ALLOW_HW_PULSES:
699*5113495bSYour Name 		if (insize < sizeof(u_int8_t) || !indata) {
700*5113495bSYour Name 			error = -EINVAL;
701*5113495bSYour Name 			break;
702*5113495bSYour Name 		}
703*5113495bSYour Name 		dfs_allow_hw_pulses(dfs, !!(*(u_int8_t *)indata));
704*5113495bSYour Name 		break;
705*5113495bSYour Name 	case DFS_SET_PRI_MULTIPILER:
706*5113495bSYour Name 		dfs->dfs_pri_multiplier = *(int *)indata;
707*5113495bSYour Name 		dfs_debug(dfs, WLAN_DEBUG_DFS_ALWAYS,
708*5113495bSYour Name 			  "Set dfs pri multiplier to %d, dfsdomain %d",
709*5113495bSYour Name 			  dfs->dfs_pri_multiplier, dfs->dfsdomain);
710*5113495bSYour Name 		break;
711*5113495bSYour Name 	default:
712*5113495bSYour Name 		error = -EINVAL;
713*5113495bSYour Name 	}
714*5113495bSYour Name 
715*5113495bSYour Name bad:
716*5113495bSYour Name 	return error;
717*5113495bSYour Name }
718*5113495bSYour Name 
719*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
720*5113495bSYour Name static inline bool
dfs_is_chan_punc_same_as_given_punc(struct dfs_channel * dfs_curchan,uint16_t dfs_chan_punc_pattern)721*5113495bSYour Name dfs_is_chan_punc_same_as_given_punc(struct dfs_channel *dfs_curchan,
722*5113495bSYour Name 				    uint16_t dfs_chan_punc_pattern)
723*5113495bSYour Name {
724*5113495bSYour Name 	return (dfs_curchan->dfs_ch_punc_pattern == dfs_chan_punc_pattern);
725*5113495bSYour Name }
726*5113495bSYour Name #else
727*5113495bSYour Name static inline bool
dfs_is_chan_punc_same_as_given_punc(struct dfs_channel * dfs_curchan,uint16_t dfs_chan_punc_pattern)728*5113495bSYour Name dfs_is_chan_punc_same_as_given_punc(struct dfs_channel *dfs_curchan,
729*5113495bSYour Name 				    uint16_t dfs_chan_punc_pattern)
730*5113495bSYour Name {
731*5113495bSYour Name 	return true;
732*5113495bSYour Name }
733*5113495bSYour Name #endif
734*5113495bSYour Name /**
735*5113495bSYour Name  * dfs_is_curchan_same_as_given_chan() - Find if dfs_curchan has the same
736*5113495bSYour Name  * channel parameters provided.
737*5113495bSYour Name  * @dfs_curchan: Pointer to DFS current channel structure.
738*5113495bSYour Name  * @dfs_ch_freq: New curchan's primary frequency.
739*5113495bSYour Name  * @dfs_ch_flags: New curchan's channel flags.
740*5113495bSYour Name  * @dfs_ch_flagext: New curchan's channel flags extension.
741*5113495bSYour Name  * @dfs_ch_vhtop_ch_freq_seg1: New curchan's primary centre IEEE.
742*5113495bSYour Name  * @dfs_ch_vhtop_ch_freq_seg2: New curchan's secondary centre IEEE.
743*5113495bSYour Name  * @dfs_chan_punc_pattern: Channel puncture pattern
744*5113495bSYour Name  *
745*5113495bSYour Name  * Return: True if curchan has the same channel parameters of the given channel,
746*5113495bSYour Name  * else false.
747*5113495bSYour Name  */
748*5113495bSYour Name static bool
dfs_is_curchan_same_as_given_chan(struct dfs_channel * dfs_curchan,uint16_t dfs_ch_freq,uint64_t dfs_ch_flags,uint16_t dfs_ch_flagext,uint8_t dfs_ch_vhtop_ch_freq_seg1,uint8_t dfs_ch_vhtop_ch_freq_seg2,uint16_t dfs_chan_punc_pattern)749*5113495bSYour Name dfs_is_curchan_same_as_given_chan(struct dfs_channel *dfs_curchan,
750*5113495bSYour Name 				  uint16_t dfs_ch_freq,
751*5113495bSYour Name 				  uint64_t dfs_ch_flags,
752*5113495bSYour Name 				  uint16_t dfs_ch_flagext,
753*5113495bSYour Name 				  uint8_t dfs_ch_vhtop_ch_freq_seg1,
754*5113495bSYour Name 				  uint8_t dfs_ch_vhtop_ch_freq_seg2,
755*5113495bSYour Name 				  uint16_t dfs_chan_punc_pattern)
756*5113495bSYour Name {
757*5113495bSYour Name 	if ((dfs_curchan->dfs_ch_freq == dfs_ch_freq) &&
758*5113495bSYour Name 	    (dfs_curchan->dfs_ch_flags == dfs_ch_flags) &&
759*5113495bSYour Name 	    (dfs_curchan->dfs_ch_flagext == dfs_ch_flagext) &&
760*5113495bSYour Name 	    (dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 ==
761*5113495bSYour Name 	     dfs_ch_vhtop_ch_freq_seg1) &&
762*5113495bSYour Name 	    (dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 ==
763*5113495bSYour Name 	     dfs_ch_vhtop_ch_freq_seg2) &&
764*5113495bSYour Name 	    (dfs_is_chan_punc_same_as_given_punc(dfs_curchan,
765*5113495bSYour Name 						 dfs_chan_punc_pattern)))
766*5113495bSYour Name 		return true;
767*5113495bSYour Name 
768*5113495bSYour Name 	return false;
769*5113495bSYour Name }
770*5113495bSYour Name 
771*5113495bSYour Name #ifdef WLAN_FEATURE_11BE
772*5113495bSYour Name static inline void
dfs_set_cur_chan_punc_pattern(struct wlan_dfs * dfs,uint16_t dfs_ch_punc_pattern)773*5113495bSYour Name dfs_set_cur_chan_punc_pattern(struct wlan_dfs *dfs,
774*5113495bSYour Name 			      uint16_t dfs_ch_punc_pattern)
775*5113495bSYour Name {
776*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_punc_pattern = dfs_ch_punc_pattern;
777*5113495bSYour Name }
778*5113495bSYour Name #else
779*5113495bSYour Name static inline void
dfs_set_cur_chan_punc_pattern(struct wlan_dfs * dfs,uint16_t dfs_ch_punc_pattern)780*5113495bSYour Name dfs_set_cur_chan_punc_pattern(struct wlan_dfs *dfs,
781*5113495bSYour Name 			      uint16_t dfs_ch_punc_pattern)
782*5113495bSYour Name {
783*5113495bSYour Name }
784*5113495bSYour Name #endif
785*5113495bSYour Name 
786*5113495bSYour Name #ifdef CONFIG_CHAN_FREQ_API
dfs_set_current_channel_for_freq(struct wlan_dfs * dfs,uint16_t dfs_chan_freq,uint64_t dfs_chan_flags,uint16_t dfs_chan_flagext,uint8_t dfs_chan_ieee,uint8_t dfs_chan_vhtop_freq_seg1,uint8_t dfs_chan_vhtop_freq_seg2,uint16_t dfs_chan_mhz_freq_seg1,uint16_t dfs_chan_mhz_freq_seg2,uint16_t dfs_ch_punc_pattern,bool * is_channel_updated)787*5113495bSYour Name void dfs_set_current_channel_for_freq(struct wlan_dfs *dfs,
788*5113495bSYour Name 				      uint16_t dfs_chan_freq,
789*5113495bSYour Name 				      uint64_t dfs_chan_flags,
790*5113495bSYour Name 				      uint16_t dfs_chan_flagext,
791*5113495bSYour Name 				      uint8_t dfs_chan_ieee,
792*5113495bSYour Name 				      uint8_t dfs_chan_vhtop_freq_seg1,
793*5113495bSYour Name 				      uint8_t dfs_chan_vhtop_freq_seg2,
794*5113495bSYour Name 				      uint16_t dfs_chan_mhz_freq_seg1,
795*5113495bSYour Name 				      uint16_t dfs_chan_mhz_freq_seg2,
796*5113495bSYour Name 				      uint16_t dfs_ch_punc_pattern,
797*5113495bSYour Name 				      bool *is_channel_updated)
798*5113495bSYour Name {
799*5113495bSYour Name 	if (is_channel_updated)
800*5113495bSYour Name 		*is_channel_updated = false;
801*5113495bSYour Name 
802*5113495bSYour Name 	if (!dfs) {
803*5113495bSYour Name 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
804*5113495bSYour Name 		return;
805*5113495bSYour Name 	}
806*5113495bSYour Name 
807*5113495bSYour Name 	/* Check if the input parameters are the same as that of dfs_curchan */
808*5113495bSYour Name 	if (dfs_is_curchan_same_as_given_chan(dfs->dfs_curchan,
809*5113495bSYour Name 					      dfs_chan_freq,
810*5113495bSYour Name 					      dfs_chan_flags,
811*5113495bSYour Name 					      dfs_chan_flagext,
812*5113495bSYour Name 					      dfs_chan_vhtop_freq_seg1,
813*5113495bSYour Name 					      dfs_chan_vhtop_freq_seg2,
814*5113495bSYour Name 					      dfs_ch_punc_pattern)) {
815*5113495bSYour Name 		dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
816*5113495bSYour Name 			 "dfs_curchan already updated");
817*5113495bSYour Name 		return;
818*5113495bSYour Name 	}
819*5113495bSYour Name 
820*5113495bSYour Name 	/* Update dfs previous channel with the old dfs_curchan, if it exists */
821*5113495bSYour Name 	if (dfs->dfs_curchan->dfs_ch_freq)
822*5113495bSYour Name 		qdf_mem_copy(dfs->dfs_prevchan,
823*5113495bSYour Name 			     dfs->dfs_curchan,
824*5113495bSYour Name 			     sizeof(struct dfs_channel));
825*5113495bSYour Name 
826*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_freq = dfs_chan_freq;
827*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_flags = dfs_chan_flags;
828*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_flagext = dfs_chan_flagext;
829*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_ieee = dfs_chan_ieee;
830*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg1 = dfs_chan_vhtop_freq_seg1;
831*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_vhtop_ch_freq_seg2 = dfs_chan_vhtop_freq_seg2;
832*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_mhz_freq_seg1 = dfs_chan_mhz_freq_seg1;
833*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_mhz_freq_seg2 = dfs_chan_mhz_freq_seg2;
834*5113495bSYour Name 	dfs_set_cur_chan_punc_pattern(dfs, dfs_ch_punc_pattern);
835*5113495bSYour Name 
836*5113495bSYour Name 	if (is_channel_updated)
837*5113495bSYour Name 		*is_channel_updated = true;
838*5113495bSYour Name 	if (dfs->dfs_use_puncture)
839*5113495bSYour Name 		dfs_handle_dfs_puncture_unpuncture(dfs);
840*5113495bSYour Name }
841*5113495bSYour Name #endif
842*5113495bSYour Name 
dfs_update_cur_chan_flags(struct wlan_dfs * dfs,uint64_t flags,uint16_t flagext)843*5113495bSYour Name void dfs_update_cur_chan_flags(struct wlan_dfs *dfs,
844*5113495bSYour Name 		uint64_t flags,
845*5113495bSYour Name 		uint16_t flagext)
846*5113495bSYour Name {
847*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_flags = flags;
848*5113495bSYour Name 	dfs->dfs_curchan->dfs_ch_flagext = flagext;
849*5113495bSYour Name }
850*5113495bSYour Name 
dfs_reinit_timers(struct wlan_dfs * dfs)851*5113495bSYour Name int dfs_reinit_timers(struct wlan_dfs *dfs)
852*5113495bSYour Name {
853*5113495bSYour Name 	dfs_cac_timer_attach(dfs);
854*5113495bSYour Name 	dfs_zero_cac_timer_init(dfs->dfs_soc_obj);
855*5113495bSYour Name 	dfs_main_task_testtimer_init(dfs);
856*5113495bSYour Name 	return 0;
857*5113495bSYour Name }
858*5113495bSYour Name 
dfs_reset_dfs_prevchan(struct wlan_dfs * dfs)859*5113495bSYour Name void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs)
860*5113495bSYour Name {
861*5113495bSYour Name 	qdf_mem_zero(dfs->dfs_prevchan, sizeof(struct dfs_channel));
862*5113495bSYour Name }
863*5113495bSYour Name 
864*5113495bSYour Name #ifdef WLAN_DFS_TRUE_160MHZ_SUPPORT
dfs_is_true_160mhz_supported(struct wlan_dfs * dfs)865*5113495bSYour Name bool dfs_is_true_160mhz_supported(struct wlan_dfs *dfs)
866*5113495bSYour Name {
867*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = dfs->dfs_soc_obj->psoc;
868*5113495bSYour Name 	struct wlan_lmac_if_target_tx_ops *tgt_tx_ops;
869*5113495bSYour Name 	struct wlan_lmac_if_tx_ops *tx_ops;
870*5113495bSYour Name 	uint32_t target_type;
871*5113495bSYour Name 
872*5113495bSYour Name 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
873*5113495bSYour Name 	if (!tx_ops) {
874*5113495bSYour Name 		 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "tx_ops is NULL");
875*5113495bSYour Name 		 return false;
876*5113495bSYour Name 	}
877*5113495bSYour Name 	target_type = lmac_get_target_type(dfs->dfs_pdev_obj);
878*5113495bSYour Name 	tgt_tx_ops = &tx_ops->target_tx_ops;
879*5113495bSYour Name 	if (tgt_tx_ops->tgt_is_tgt_type_qcn9000 &&
880*5113495bSYour Name 	    tgt_tx_ops->tgt_is_tgt_type_qcn9000(target_type))
881*5113495bSYour Name 		return true;
882*5113495bSYour Name 
883*5113495bSYour Name 	if (tgt_tx_ops->tgt_is_tgt_type_qcn6122 &&
884*5113495bSYour Name 	    tgt_tx_ops->tgt_is_tgt_type_qcn6122(target_type))
885*5113495bSYour Name 		return true;
886*5113495bSYour Name 
887*5113495bSYour Name 	if (tgt_tx_ops->tgt_is_tgt_type_qcn9160 &&
888*5113495bSYour Name 	    tgt_tx_ops->tgt_is_tgt_type_qcn9160(target_type))
889*5113495bSYour Name 		return true;
890*5113495bSYour Name 
891*5113495bSYour Name 	if (tgt_tx_ops->tgt_is_tgt_type_qcn6432 &&
892*5113495bSYour Name 	    tgt_tx_ops->tgt_is_tgt_type_qcn6432(target_type))
893*5113495bSYour Name 		return true;
894*5113495bSYour Name 
895*5113495bSYour Name 	return false;
896*5113495bSYour Name }
897*5113495bSYour Name 
dfs_is_restricted_80p80mhz_supported(struct wlan_dfs * dfs)898*5113495bSYour Name bool dfs_is_restricted_80p80mhz_supported(struct wlan_dfs *dfs)
899*5113495bSYour Name {
900*5113495bSYour Name 	return wlan_psoc_nif_fw_ext_cap_get(dfs->dfs_soc_obj->psoc,
901*5113495bSYour Name 					    WLAN_SOC_RESTRICTED_80P80_SUPPORT);
902*5113495bSYour Name }
903*5113495bSYour Name #endif
904*5113495bSYour Name 
905*5113495bSYour Name #ifdef QCA_SUPPORT_AGILE_DFS
dfs_get_agile_detector_id(struct wlan_dfs * dfs)906*5113495bSYour Name uint8_t dfs_get_agile_detector_id(struct wlan_dfs *dfs)
907*5113495bSYour Name {
908*5113495bSYour Name 	return dfs->dfs_agile_detector_id;
909*5113495bSYour Name }
910*5113495bSYour Name #endif
911*5113495bSYour Name 
912*5113495bSYour Name /**
913*5113495bSYour Name  * dfs_chan_to_ch_width() - Outputs the channel width in MHz of the given input
914*5113495bSYour Name  * dfs_channel.
915*5113495bSYour Name  * @chan: Pointer to the input dfs_channel structure.
916*5113495bSYour Name  *
917*5113495bSYour Name  * Return: Channel width in MHz. BW_INVALID(0MHz) on invalid channel.
918*5113495bSYour Name  */
dfs_chan_to_ch_width(struct dfs_channel * chan)919*5113495bSYour Name uint16_t dfs_chan_to_ch_width(struct dfs_channel *chan)
920*5113495bSYour Name {
921*5113495bSYour Name 	uint16_t ch_width;
922*5113495bSYour Name 
923*5113495bSYour Name 	if (!chan)
924*5113495bSYour Name 		return BW_INVALID;
925*5113495bSYour Name 
926*5113495bSYour Name 	if (WLAN_IS_CHAN_MODE_320(chan))
927*5113495bSYour Name 		ch_width = BW_320;
928*5113495bSYour Name 	else if (WLAN_IS_CHAN_MODE_160(chan))
929*5113495bSYour Name 		ch_width = BW_160;
930*5113495bSYour Name 	else if (WLAN_IS_CHAN_MODE_80(chan))
931*5113495bSYour Name 		ch_width = BW_80;
932*5113495bSYour Name 	else if (WLAN_IS_CHAN_MODE_40(chan))
933*5113495bSYour Name 		ch_width = BW_40;
934*5113495bSYour Name 	else if (WLAN_IS_CHAN_MODE_20(chan))
935*5113495bSYour Name 		ch_width = BW_20;
936*5113495bSYour Name 	else
937*5113495bSYour Name 		ch_width = BW_INVALID;
938*5113495bSYour Name 
939*5113495bSYour Name 	return ch_width;
940*5113495bSYour Name }
941