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