xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_radar.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2016-2020 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 #else
134 #ifdef CONFIG_CHAN_NUM_API
135 struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index,
136 		int ext_chan_flag)
137 {
138 	struct dfs_state *rs = NULL;
139 	struct dfs_channel *cmp_ch, cmp_ch1;
140 	int i;
141 	QDF_STATUS err;
142 
143 	if (!dfs) {
144 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
145 		return NULL;
146 	}
147 	cmp_ch = &cmp_ch1;
148 	if (ext_chan_flag) {
149 		err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj,
150 				&(cmp_ch->dfs_ch_freq),
151 				&(cmp_ch->dfs_ch_flags),
152 				&(cmp_ch->dfs_ch_flagext),
153 				&(cmp_ch->dfs_ch_ieee),
154 				&(cmp_ch->dfs_ch_vhtop_ch_freq_seg1),
155 				&(cmp_ch->dfs_ch_vhtop_ch_freq_seg2));
156 
157 		if (err == QDF_STATUS_SUCCESS) {
158 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
159 					"Extension channel freq = %u flags=0x%x",
160 					cmp_ch->dfs_ch_freq,
161 					cmp_ch->dfs_ch_flagext);
162 		} else
163 			return NULL;
164 	} else {
165 		cmp_ch = dfs->dfs_curchan;
166 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
167 				"Primary channel freq = %u flags=0x%x",
168 				cmp_ch->dfs_ch_freq, cmp_ch->dfs_ch_flagext);
169 	}
170 
171 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
172 		if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq ==
173 					cmp_ch->dfs_ch_freq) &&
174 				(dfs->dfs_radar[i].rs_chan.dfs_ch_flags ==
175 				 cmp_ch->dfs_ch_flags)
176 		   ) {
177 			if (index)
178 				*index = (uint8_t)i;
179 			return &(dfs->dfs_radar[i]);
180 		}
181 	}
182 	/* No existing channel found, look for first free channel state entry.*/
183 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
184 		if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) {
185 			rs = &(dfs->dfs_radar[i]);
186 			/* Found one, set channel info and default thresholds.*/
187 			rs->rs_chan = *cmp_ch;
188 
189 			/* Copy the parameters from the default set. */
190 			dfs_phyerr_param_copy(&rs->rs_param,
191 					&dfs->dfs_defaultparams);
192 
193 			if (index)
194 				*index = (uint8_t)i;
195 
196 			return rs;
197 		}
198 	}
199 	dfs_debug(dfs, WLAN_DEBUG_DFS2, "No more radar states left.");
200 
201 	return NULL;
202 }
203 #endif
204 #endif
205 
206 #ifdef CONFIG_CHAN_FREQ_API
207 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode)
208 {
209 	int is_ext_ch;
210 	int is_fastclk = 0;
211 	struct dfs_channel *exch, extchan;
212 	QDF_STATUS err = QDF_STATUS_E_FAILURE;
213 
214 	if (!dfs) {
215 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
216 		return;
217 	}
218 
219 	is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan);
220 	lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac);
221 	/*
222 	 * In all modes, if the primary is DFS then we have to
223 	 * enable radar detection. In HT80_80, we can have
224 	 * primary non-DFS 80MHz with extension 80MHz DFS.
225 	 */
226 	if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) ||
227 	     ((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) ||
228 	       WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) &&
229 	      WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) ||
230 	    (dfs_is_precac_timer_running(dfs))) {
231 		struct dfs_state *rs_pri = NULL, *rs_ext = NULL;
232 		uint8_t index_pri, index_ext;
233 
234 		dfs->dfs_proc_phyerr |= DFS_AR_EN;
235 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
236 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
237 
238 		exch = &extchan;
239 		if (is_ext_ch) {
240 			err = dfs_mlme_get_extchan_for_freq
241 				(
242 				 dfs->dfs_pdev_obj,
243 				 &exch->dfs_ch_freq,
244 				 &exch->dfs_ch_flags,
245 				 &exch->dfs_ch_flagext,
246 				 &exch->dfs_ch_ieee,
247 				 &exch->dfs_ch_vhtop_ch_freq_seg1,
248 				 &exch->dfs_ch_vhtop_ch_freq_seg2,
249 				 &exch->dfs_ch_mhz_freq_seg1,
250 				 &exch->dfs_ch_mhz_freq_seg2);
251 		}
252 		dfs_reset_alldelaylines(dfs);
253 
254 		rs_pri = dfs_getchanstate(dfs, &index_pri, 0);
255 		if (err == QDF_STATUS_SUCCESS)
256 			rs_ext = dfs_getchanstate(dfs, &index_ext, 1);
257 
258 		if (rs_pri && ((err == QDF_STATUS_E_FAILURE) || (rs_ext))) {
259 			struct wlan_dfs_phyerr_param pe;
260 
261 			qdf_mem_set(&pe, sizeof(pe), '\0');
262 
263 			if (index_pri != dfs->dfs_curchan_radindex)
264 				dfs_reset_alldelaylines(dfs);
265 
266 			dfs->dfs_curchan_radindex = (int16_t)index_pri;
267 
268 			if (rs_ext)
269 				dfs->dfs_extchan_radindex = (int16_t)index_ext;
270 
271 			dfs_phyerr_param_copy(&pe, &rs_pri->rs_param);
272 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
273 				  "firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d",
274 				  pe.pe_firpwr,
275 				  pe.pe_rrssi, pe.pe_height,
276 				  pe.pe_prssi, pe.pe_inband,
277 				  pe.pe_relpwr, pe.pe_relstep,
278 				  pe.pe_maxlen);
279 
280 			lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
281 					&pe, dfs->dfsdomain);
282 			dfs_debug(dfs, WLAN_DEBUG_DFS,
283 				  "Enabled radar detection on channel %d",
284 				  dfs->dfs_curchan->dfs_ch_freq);
285 
286 			dfs->dur_multiplier = is_fastclk ?
287 				DFS_FAST_CLOCK_MULTIPLIER :
288 				DFS_NO_FAST_CLOCK_MULTIPLIER;
289 
290 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
291 				  "duration multiplier is %d",
292 				  dfs->dur_multiplier);
293 		} else
294 			dfs_debug(dfs, WLAN_DEBUG_DFS,
295 				  "No more radar states left");
296 	}
297 }
298 #else
299 #ifdef CONFIG_CHAN_NUM_API
300 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode)
301 {
302 	int is_ext_ch;
303 	int is_fastclk = 0;
304 	struct dfs_channel *ext_ch, extchan;
305 	QDF_STATUS err = QDF_STATUS_E_FAILURE;
306 
307 	if (!dfs) {
308 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
309 		return;
310 	}
311 
312 	is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan);
313 	lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac);
314 	/*
315 	 * In all modes, if the primary is DFS then we have to
316 	 * enable radar detection. In HT80_80, we can have
317 	 * primary non-DFS 80MHz with extension 80MHz DFS.
318 	 */
319 	if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) ||
320 				((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) ||
321 				  WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan))
322 				 &&
323 				 WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) ||
324 		(dfs_is_precac_timer_running(dfs))) {
325 		struct dfs_state *rs_pri = NULL, *rs_ext = NULL;
326 		uint8_t index_pri, index_ext;
327 
328 		dfs->dfs_proc_phyerr |= DFS_AR_EN;
329 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
330 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
331 
332 		ext_ch = &extchan;
333 		if (is_ext_ch)
334 			err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj,
335 					&(ext_ch->dfs_ch_freq),
336 					&(ext_ch->dfs_ch_flags),
337 					&(ext_ch->dfs_ch_flagext),
338 					&(ext_ch->dfs_ch_ieee),
339 					&(ext_ch->dfs_ch_vhtop_ch_freq_seg1),
340 					&(ext_ch->dfs_ch_vhtop_ch_freq_seg2));
341 
342 
343 		dfs_reset_alldelaylines(dfs);
344 
345 		rs_pri = dfs_getchanstate(dfs, &index_pri, 0);
346 		if (err == QDF_STATUS_SUCCESS)
347 			rs_ext = dfs_getchanstate(dfs, &index_ext, 1);
348 
349 		if (rs_pri && ((err == QDF_STATUS_E_FAILURE) ||
350 					(rs_ext))) {
351 			struct wlan_dfs_phyerr_param pe;
352 
353 			qdf_mem_set(&pe, sizeof(pe), '\0');
354 
355 			if (index_pri != dfs->dfs_curchan_radindex)
356 				dfs_reset_alldelaylines(dfs);
357 
358 			dfs->dfs_curchan_radindex = (int16_t)index_pri;
359 
360 			if (rs_ext)
361 				dfs->dfs_extchan_radindex = (int16_t)index_ext;
362 
363 			dfs_phyerr_param_copy(&pe, &rs_pri->rs_param);
364 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
365 					"firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d",
366 					pe.pe_firpwr,
367 					pe.pe_rrssi, pe.pe_height,
368 					pe.pe_prssi, pe.pe_inband,
369 					pe.pe_relpwr, pe.pe_relstep,
370 					pe.pe_maxlen);
371 
372 			lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
373 					&pe, dfs->dfsdomain);
374 			dfs_debug(dfs, WLAN_DEBUG_DFS,
375 					"Enabled radar detection on channel %d",
376 					dfs->dfs_curchan->dfs_ch_freq);
377 
378 			dfs->dur_multiplier = is_fastclk ?
379 				DFS_FAST_CLOCK_MULTIPLIER :
380 				DFS_NO_FAST_CLOCK_MULTIPLIER;
381 
382 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
383 					"duration multiplier is %d",
384 					dfs->dur_multiplier);
385 		} else
386 			dfs_debug(dfs, WLAN_DEBUG_DFS,
387 					"No more radar states left");
388 	}
389 }
390 #endif
391 #endif
392 
393 int dfs_set_thresholds(struct wlan_dfs *dfs, const uint32_t threshtype,
394 		const uint32_t value)
395 {
396 	int16_t chanindex;
397 	struct dfs_state *rs;
398 	struct wlan_dfs_phyerr_param pe;
399 	int is_fastclk = 0;
400 
401 	if (!dfs) {
402 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
403 		return 0;
404 	}
405 
406 	chanindex = dfs->dfs_curchan_radindex;
407 	if ((chanindex < 0) || (chanindex >= DFS_NUM_RADAR_STATES)) {
408 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
409 			  "chanindex = %d, DFS_NUM_RADAR_STATES=%d",
410 			  chanindex,
411 			  DFS_NUM_RADAR_STATES);
412 		return 0;
413 	}
414 
415 	dfs_debug(dfs, WLAN_DEBUG_DFS,
416 			"threshtype=%d, value=%d", threshtype, value);
417 
418 	wlan_dfs_phyerr_init_noval(&pe);
419 
420 	rs = &(dfs->dfs_radar[chanindex]);
421 	switch (threshtype) {
422 	case DFS_PARAM_FIRPWR:
423 		rs->rs_param.pe_firpwr = (int32_t) value;
424 		pe.pe_firpwr = value;
425 		break;
426 	case DFS_PARAM_RRSSI:
427 		rs->rs_param.pe_rrssi = value;
428 		pe.pe_rrssi = value;
429 		break;
430 	case DFS_PARAM_HEIGHT:
431 		rs->rs_param.pe_height = value;
432 		pe.pe_height = value;
433 		break;
434 	case DFS_PARAM_PRSSI:
435 		rs->rs_param.pe_prssi = value;
436 		pe.pe_prssi = value;
437 		break;
438 	case DFS_PARAM_INBAND:
439 		rs->rs_param.pe_inband = value;
440 		pe.pe_inband = value;
441 		break;
442 		/* 5413 specific */
443 	case DFS_PARAM_RELPWR:
444 		rs->rs_param.pe_relpwr = value;
445 		pe.pe_relpwr = value;
446 		break;
447 	case DFS_PARAM_RELSTEP:
448 		rs->rs_param.pe_relstep = value;
449 		pe.pe_relstep = value;
450 		break;
451 	case DFS_PARAM_MAXLEN:
452 		rs->rs_param.pe_maxlen = value;
453 		pe.pe_maxlen = value;
454 		break;
455 	default:
456 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
457 				"unknown threshtype (%d)", threshtype);
458 		break;
459 	}
460 
461 
462 	/*
463 	 * The driver layer dfs_enable routine is tasked with translating
464 	 * values from the global format to the per-device (HAL, offload)
465 	 * format.
466 	 */
467 	lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
468 			&pe, dfs->dfsdomain);
469 
470 	return 1;
471 }
472 
473 int dfs_get_thresholds(struct wlan_dfs *dfs,
474 		struct wlan_dfs_phyerr_param *param)
475 {
476 	lmac_dfs_get_thresholds(dfs->dfs_pdev_obj, param);
477 
478 	return 1;
479 }
480 
481 uint16_t dfs_chan2freq(struct dfs_channel *chan)
482 {
483 	if (!chan)
484 		return 0;
485 
486 	return chan == WLAN_CHAN_ANYC ? WLAN_CHAN_ANY : chan->dfs_ch_freq;
487 }
488