xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_radar.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2011, Atheros Communications Inc.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "../dfs.h"
19 #include "../dfs_zero_cac.h"
20 #include "../dfs_filter_init.h"
21 #include "wlan_dfs_mlme_api.h"
22 #include "wlan_dfs_lmac_api.h"
23 #include "../dfs_partial_offload_radar.h"
24 #include "../dfs_internal.h"
25 
26 void dfs_get_radars(struct wlan_dfs *dfs)
27 {
28 	struct wlan_objmgr_psoc *psoc;
29 
30 	if (!dfs) {
31 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
32 		return;
33 	}
34 
35 	psoc = wlan_pdev_get_psoc(dfs->dfs_pdev_obj);
36 	if (!psoc) {
37 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "psoc is NULL");
38 		return;
39 	}
40 
41 	if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_OL) {
42 		/* For Partial offload */
43 		dfs_get_po_radars(dfs);
44 	}
45 }
46 
47 int dfs_radar_disable(struct wlan_dfs *dfs)
48 {
49 	dfs->dfs_proc_phyerr &= ~DFS_AR_EN;
50 	dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN;
51 
52 	return 0;
53 }
54 
55 void dfs_phyerr_param_copy(struct wlan_dfs_phyerr_param *dst,
56 		struct wlan_dfs_phyerr_param *src)
57 {
58 	qdf_mem_copy(dst, src, sizeof(*dst));
59 }
60 
61 #ifdef CONFIG_CHAN_FREQ_API
62 struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index,
63 				   int ext_chan_flag)
64 {
65 	struct dfs_state *rs = NULL;
66 	struct dfs_channel *ch, cmp_ch1;
67 	int i;
68 	QDF_STATUS err;
69 
70 	if (!dfs) {
71 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
72 		return NULL;
73 	}
74 	ch = &cmp_ch1;
75 	if (ext_chan_flag) {
76 		err = dfs_mlme_get_extchan_for_freq(
77 					dfs->dfs_pdev_obj,
78 					&ch->dfs_ch_freq,
79 					&ch->dfs_ch_flags,
80 					&ch->dfs_ch_flagext,
81 					&ch->dfs_ch_ieee,
82 					&ch->dfs_ch_vhtop_ch_freq_seg1,
83 					&ch->dfs_ch_vhtop_ch_freq_seg2,
84 					&ch->dfs_ch_mhz_freq_seg1,
85 					&ch->dfs_ch_mhz_freq_seg2);
86 
87 		if (err == QDF_STATUS_SUCCESS) {
88 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
89 				  "Extension channel freq = %u flags=0x%x",
90 				  ch->dfs_ch_freq,
91 				  ch->dfs_ch_flagext);
92 		} else {
93 			return NULL;
94 		}
95 	} else {
96 		ch = dfs->dfs_curchan;
97 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
98 			  "Primary channel freq = %u flags=0x%x",
99 			  ch->dfs_ch_freq, ch->dfs_ch_flagext);
100 	}
101 
102 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
103 		if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq ==
104 			 ch->dfs_ch_freq) &&
105 			(dfs->dfs_radar[i].rs_chan.dfs_ch_flags ==
106 			 ch->dfs_ch_flags)) {
107 			if (index)
108 				*index = (uint8_t)i;
109 			return &dfs->dfs_radar[i];
110 		}
111 	}
112 	/* No existing channel found, look for first free channel state entry.*/
113 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
114 		if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) {
115 			rs = &dfs->dfs_radar[i];
116 			/* Found one, set channel info and default thresholds.*/
117 			rs->rs_chan = *ch;
118 
119 			/* Copy the parameters from the default set. */
120 			dfs_phyerr_param_copy(&rs->rs_param,
121 					      &dfs->dfs_defaultparams);
122 
123 			if (index)
124 				*index = (uint8_t)i;
125 
126 			return rs;
127 		}
128 	}
129 	dfs_debug(dfs, WLAN_DEBUG_DFS2, "No more radar states left.");
130 
131 	return NULL;
132 }
133 #endif
134 
135 #ifdef CONFIG_CHAN_FREQ_API
136 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode)
137 {
138 	int is_ext_ch;
139 	int is_fastclk = 0;
140 	struct dfs_channel *exch, extchan;
141 	QDF_STATUS err = QDF_STATUS_E_FAILURE;
142 
143 	if (!dfs) {
144 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
145 		return;
146 	}
147 
148 	is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan);
149 	lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac);
150 	/*
151 	 * In all modes, if the primary is DFS then we have to
152 	 * enable radar detection. In HT80_80, we can have
153 	 * primary non-DFS 80MHz with extension 80MHz DFS.
154 	 */
155 	if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) ||
156 	     ((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) ||
157 	       WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) &&
158 	      WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) ||
159 	    (dfs_is_precac_timer_running(dfs))) {
160 		struct dfs_state *rs_pri = NULL, *rs_ext = NULL;
161 		uint8_t index_pri, index_ext;
162 
163 		dfs->dfs_proc_phyerr |= DFS_AR_EN;
164 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
165 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
166 
167 		exch = &extchan;
168 		if (is_ext_ch) {
169 			err = dfs_mlme_get_extchan_for_freq
170 				(
171 				 dfs->dfs_pdev_obj,
172 				 &exch->dfs_ch_freq,
173 				 &exch->dfs_ch_flags,
174 				 &exch->dfs_ch_flagext,
175 				 &exch->dfs_ch_ieee,
176 				 &exch->dfs_ch_vhtop_ch_freq_seg1,
177 				 &exch->dfs_ch_vhtop_ch_freq_seg2,
178 				 &exch->dfs_ch_mhz_freq_seg1,
179 				 &exch->dfs_ch_mhz_freq_seg2);
180 		}
181 		dfs_reset_alldelaylines(dfs);
182 
183 		rs_pri = dfs_getchanstate(dfs, &index_pri, 0);
184 		if (err == QDF_STATUS_SUCCESS)
185 			rs_ext = dfs_getchanstate(dfs, &index_ext, 1);
186 
187 		if (rs_pri && ((err == QDF_STATUS_E_FAILURE) || (rs_ext))) {
188 			struct wlan_dfs_phyerr_param pe;
189 
190 			qdf_mem_set(&pe, sizeof(pe), '\0');
191 
192 			if (index_pri != dfs->dfs_curchan_radindex)
193 				dfs_reset_alldelaylines(dfs);
194 
195 			dfs->dfs_curchan_radindex = (int16_t)index_pri;
196 
197 			if (rs_ext)
198 				dfs->dfs_extchan_radindex = (int16_t)index_ext;
199 
200 			dfs_phyerr_param_copy(&pe, &rs_pri->rs_param);
201 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
202 				  "firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d",
203 				  pe.pe_firpwr,
204 				  pe.pe_rrssi, pe.pe_height,
205 				  pe.pe_prssi, pe.pe_inband,
206 				  pe.pe_relpwr, pe.pe_relstep,
207 				  pe.pe_maxlen);
208 
209 			lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
210 					&pe, dfs->dfsdomain);
211 			dfs_debug(dfs, WLAN_DEBUG_DFS,
212 				  "Enabled radar detection on channel %d",
213 				  dfs->dfs_curchan->dfs_ch_freq);
214 
215 			dfs->dur_multiplier = is_fastclk ?
216 				DFS_FAST_CLOCK_MULTIPLIER :
217 				DFS_NO_FAST_CLOCK_MULTIPLIER;
218 
219 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
220 				  "duration multiplier is %d",
221 				  dfs->dur_multiplier);
222 		} else
223 			dfs_debug(dfs, WLAN_DEBUG_DFS,
224 				  "No more radar states left");
225 	}
226 }
227 #endif
228 
229 int dfs_set_thresholds(struct wlan_dfs *dfs, const uint32_t threshtype,
230 		const uint32_t value)
231 {
232 	int16_t chanindex;
233 	struct dfs_state *rs;
234 	struct wlan_dfs_phyerr_param pe;
235 	int is_fastclk = 0;
236 
237 	if (!dfs) {
238 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
239 		return 0;
240 	}
241 
242 	chanindex = dfs->dfs_curchan_radindex;
243 	if ((chanindex < 0) || (chanindex >= DFS_NUM_RADAR_STATES)) {
244 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
245 			  "chanindex = %d, DFS_NUM_RADAR_STATES=%d",
246 			  chanindex,
247 			  DFS_NUM_RADAR_STATES);
248 		return 0;
249 	}
250 
251 	dfs_debug(dfs, WLAN_DEBUG_DFS,
252 			"threshtype=%d, value=%d", threshtype, value);
253 
254 	wlan_dfs_phyerr_init_noval(&pe);
255 
256 	rs = &(dfs->dfs_radar[chanindex]);
257 	switch (threshtype) {
258 	case DFS_PARAM_FIRPWR:
259 		rs->rs_param.pe_firpwr = (int32_t) value;
260 		pe.pe_firpwr = value;
261 		break;
262 	case DFS_PARAM_RRSSI:
263 		rs->rs_param.pe_rrssi = value;
264 		pe.pe_rrssi = value;
265 		break;
266 	case DFS_PARAM_HEIGHT:
267 		rs->rs_param.pe_height = value;
268 		pe.pe_height = value;
269 		break;
270 	case DFS_PARAM_PRSSI:
271 		rs->rs_param.pe_prssi = value;
272 		pe.pe_prssi = value;
273 		break;
274 	case DFS_PARAM_INBAND:
275 		rs->rs_param.pe_inband = value;
276 		pe.pe_inband = value;
277 		break;
278 		/* 5413 specific */
279 	case DFS_PARAM_RELPWR:
280 		rs->rs_param.pe_relpwr = value;
281 		pe.pe_relpwr = value;
282 		break;
283 	case DFS_PARAM_RELSTEP:
284 		rs->rs_param.pe_relstep = value;
285 		pe.pe_relstep = value;
286 		break;
287 	case DFS_PARAM_MAXLEN:
288 		rs->rs_param.pe_maxlen = value;
289 		pe.pe_maxlen = value;
290 		break;
291 	default:
292 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
293 				"unknown threshtype (%d)", threshtype);
294 		break;
295 	}
296 
297 
298 	/*
299 	 * The driver layer dfs_enable routine is tasked with translating
300 	 * values from the global format to the per-device (HAL, offload)
301 	 * format.
302 	 */
303 	lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
304 			&pe, dfs->dfsdomain);
305 
306 	return 1;
307 }
308 
309 int dfs_get_thresholds(struct wlan_dfs *dfs,
310 		struct wlan_dfs_phyerr_param *param)
311 {
312 	lmac_dfs_get_thresholds(dfs->dfs_pdev_obj, param);
313 
314 	return 1;
315 }
316 
317 uint16_t dfs_chan2freq(struct dfs_channel *chan)
318 {
319 	if (!chan)
320 		return 0;
321 
322 	return chan == WLAN_CHAN_ANYC ? WLAN_CHAN_ANY : chan->dfs_ch_freq;
323 }
324