xref: /wlan-dirver/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_radar.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
1 /*
2  * Copyright (c) 2016-2018 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 "wlan_dfs_mlme_api.h"
21 #include "wlan_dfs_lmac_api.h"
22 #include "../dfs_partial_offload_radar.h"
23 #include "../dfs_direct_attach_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 struct dfs_state *dfs_getchanstate(struct wlan_dfs *dfs, uint8_t *index,
65 		int ext_chan_flag)
66 {
67 	struct dfs_state *rs = NULL;
68 	struct dfs_channel *cmp_ch, cmp_ch1;
69 	int i;
70 	QDF_STATUS err;
71 
72 	if (!dfs) {
73 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
74 		return NULL;
75 	}
76 	cmp_ch = &cmp_ch1;
77 	if (ext_chan_flag) {
78 		err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj,
79 				&(cmp_ch->dfs_ch_freq),
80 				&(cmp_ch->dfs_ch_flags),
81 				&(cmp_ch->dfs_ch_flagext),
82 				&(cmp_ch->dfs_ch_ieee),
83 				&(cmp_ch->dfs_ch_vhtop_ch_freq_seg1),
84 				&(cmp_ch->dfs_ch_vhtop_ch_freq_seg2));
85 
86 		if (err == QDF_STATUS_SUCCESS) {
87 			dfs_debug(dfs, WLAN_DEBUG_DFS2,
88 					"Extension channel freq = %u flags=0x%x",
89 					cmp_ch->dfs_ch_freq,
90 					cmp_ch->dfs_ch_flagext);
91 		} else
92 			return NULL;
93 	} else {
94 		cmp_ch = dfs->dfs_curchan;
95 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
96 				"Primary channel freq = %u flags=0x%x",
97 				cmp_ch->dfs_ch_freq, cmp_ch->dfs_ch_flagext);
98 	}
99 
100 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
101 		if ((dfs->dfs_radar[i].rs_chan.dfs_ch_freq ==
102 					cmp_ch->dfs_ch_freq) &&
103 				(dfs->dfs_radar[i].rs_chan.dfs_ch_flags ==
104 				 cmp_ch->dfs_ch_flags)
105 		   ) {
106 			if (index != NULL)
107 				*index = (uint8_t)i;
108 			return &(dfs->dfs_radar[i]);
109 		}
110 	}
111 	/* No existing channel found, look for first free channel state entry.*/
112 	for (i = 0; i < DFS_NUM_RADAR_STATES; i++) {
113 		if (dfs->dfs_radar[i].rs_chan.dfs_ch_freq == 0) {
114 			rs = &(dfs->dfs_radar[i]);
115 			/* Found one, set channel info and default thresholds.*/
116 			rs->rs_chan = *cmp_ch;
117 
118 			/* Copy the parameters from the default set. */
119 			dfs_phyerr_param_copy(&rs->rs_param,
120 					&dfs->dfs_defaultparams);
121 
122 			if (index != NULL)
123 				*index = (uint8_t)i;
124 
125 			return rs;
126 		}
127 	}
128 	dfs_debug(dfs, WLAN_DEBUG_DFS2, "No more radar states left.");
129 
130 	return NULL;
131 }
132 
133 void dfs_radar_enable(struct wlan_dfs *dfs, int no_cac, uint32_t opmode)
134 {
135 	int is_ext_ch;
136 	int is_fastclk = 0;
137 	struct dfs_channel *ext_ch, extchan;
138 	QDF_STATUS err = QDF_STATUS_E_FAILURE;
139 
140 	if (!dfs) {
141 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
142 		return;
143 	}
144 
145 	is_ext_ch = WLAN_IS_CHAN_11N_HT40(dfs->dfs_curchan);
146 	lmac_dfs_disable(dfs->dfs_pdev_obj, no_cac);
147 	/*
148 	 * In all modes, if the primary is DFS then we have to
149 	 * enable radar detection. In HT80_80, we can have
150 	 * primary non-DFS 80MHz with extension 80MHz DFS.
151 	 */
152 	if ((WLAN_IS_CHAN_DFS(dfs->dfs_curchan) ||
153 				((WLAN_IS_CHAN_11AC_VHT160(dfs->dfs_curchan) ||
154 				  WLAN_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan))
155 				 &&
156 				 WLAN_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) ||
157 		(dfs_is_precac_timer_running(dfs))) {
158 		struct dfs_state *rs_pri = NULL, *rs_ext = NULL;
159 		uint8_t index_pri, index_ext;
160 
161 		dfs->dfs_proc_phyerr |= DFS_AR_EN;
162 		dfs->dfs_proc_phyerr |= DFS_RADAR_EN;
163 		dfs->dfs_proc_phyerr |= DFS_SECOND_SEGMENT_RADAR_EN;
164 
165 		ext_ch = &extchan;
166 		if (is_ext_ch)
167 			err = dfs_mlme_get_extchan(dfs->dfs_pdev_obj,
168 					&(ext_ch->dfs_ch_freq),
169 					&(ext_ch->dfs_ch_flags),
170 					&(ext_ch->dfs_ch_flagext),
171 					&(ext_ch->dfs_ch_ieee),
172 					&(ext_ch->dfs_ch_vhtop_ch_freq_seg1),
173 					&(ext_ch->dfs_ch_vhtop_ch_freq_seg2));
174 
175 
176 		dfs_reset_alldelaylines(dfs);
177 
178 		rs_pri = dfs_getchanstate(dfs, &index_pri, 0);
179 		if (err == QDF_STATUS_SUCCESS)
180 			rs_ext = dfs_getchanstate(dfs, &index_ext, 1);
181 
182 		if (rs_pri != NULL && ((err == QDF_STATUS_E_FAILURE) ||
183 					(rs_ext != NULL))) {
184 			struct wlan_dfs_phyerr_param pe;
185 
186 			qdf_mem_set(&pe, sizeof(pe), '\0');
187 
188 			if (index_pri != dfs->dfs_curchan_radindex)
189 				dfs_reset_alldelaylines(dfs);
190 
191 			dfs->dfs_curchan_radindex = (int16_t)index_pri;
192 
193 			if (rs_ext)
194 				dfs->dfs_extchan_radindex = (int16_t)index_ext;
195 
196 			dfs_phyerr_param_copy(&pe, &rs_pri->rs_param);
197 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
198 					"firpwr=%d, rssi=%d, height=%d, prssi=%d, inband=%d, relpwr=%d, relstep=%d, maxlen=%d",
199 					pe.pe_firpwr,
200 					pe.pe_rrssi, pe.pe_height,
201 					pe.pe_prssi, pe.pe_inband,
202 					pe.pe_relpwr, pe.pe_relstep,
203 					pe.pe_maxlen);
204 
205 			lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
206 					&pe, dfs->dfsdomain);
207 			dfs_debug(dfs, WLAN_DEBUG_DFS,
208 					"Enabled radar detection on channel %d",
209 					dfs->dfs_curchan->dfs_ch_freq);
210 
211 			dfs->dur_multiplier = is_fastclk ?
212 				DFS_FAST_CLOCK_MULTIPLIER :
213 				DFS_NO_FAST_CLOCK_MULTIPLIER;
214 
215 			dfs_debug(dfs, WLAN_DEBUG_DFS3,
216 					"duration multiplier is %d",
217 					dfs->dur_multiplier);
218 		} else
219 			dfs_debug(dfs, WLAN_DEBUG_DFS,
220 					"No more radar states left");
221 	}
222 }
223 
224 int dfs_set_thresholds(struct wlan_dfs *dfs, const uint32_t threshtype,
225 		const uint32_t value)
226 {
227 	int16_t chanindex;
228 	struct dfs_state *rs;
229 	struct wlan_dfs_phyerr_param pe;
230 	int is_fastclk = 0;
231 
232 	if (!dfs) {
233 		dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS,  "dfs is NULL");
234 		return 0;
235 	}
236 
237 	chanindex = dfs->dfs_curchan_radindex;
238 	if ((chanindex < 0) || (chanindex >= DFS_NUM_RADAR_STATES)) {
239 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
240 				"%s: chanindex = %d, DFS_NUM_RADAR_STATES=%d\n",
241 				__func__,
242 				chanindex,
243 				DFS_NUM_RADAR_STATES);
244 		return 0;
245 	}
246 
247 	dfs_debug(dfs, WLAN_DEBUG_DFS,
248 			"threshtype=%d, value=%d", threshtype, value);
249 
250 	wlan_dfs_phyerr_init_noval(&pe);
251 
252 	rs = &(dfs->dfs_radar[chanindex]);
253 	switch (threshtype) {
254 	case DFS_PARAM_FIRPWR:
255 		rs->rs_param.pe_firpwr = (int32_t) value;
256 		pe.pe_firpwr = value;
257 		break;
258 	case DFS_PARAM_RRSSI:
259 		rs->rs_param.pe_rrssi = value;
260 		pe.pe_rrssi = value;
261 		break;
262 	case DFS_PARAM_HEIGHT:
263 		rs->rs_param.pe_height = value;
264 		pe.pe_height = value;
265 		break;
266 	case DFS_PARAM_PRSSI:
267 		rs->rs_param.pe_prssi = value;
268 		pe.pe_prssi = value;
269 		break;
270 	case DFS_PARAM_INBAND:
271 		rs->rs_param.pe_inband = value;
272 		pe.pe_inband = value;
273 		break;
274 		/* 5413 specific */
275 	case DFS_PARAM_RELPWR:
276 		rs->rs_param.pe_relpwr = value;
277 		pe.pe_relpwr = value;
278 		break;
279 	case DFS_PARAM_RELSTEP:
280 		rs->rs_param.pe_relstep = value;
281 		pe.pe_relstep = value;
282 		break;
283 	case DFS_PARAM_MAXLEN:
284 		rs->rs_param.pe_maxlen = value;
285 		pe.pe_maxlen = value;
286 		break;
287 	default:
288 		dfs_debug(dfs, WLAN_DEBUG_DFS1,
289 				"unknown threshtype (%d)", threshtype);
290 		break;
291 	}
292 
293 
294 	/*
295 	 * The driver layer dfs_enable routine is tasked with translating
296 	 * values from the global format to the per-device (HAL, offload)
297 	 * format.
298 	 */
299 	lmac_dfs_enable(dfs->dfs_pdev_obj, &is_fastclk,
300 			&pe, dfs->dfsdomain);
301 
302 	return 1;
303 }
304 
305 int dfs_get_thresholds(struct wlan_dfs *dfs,
306 		struct wlan_dfs_phyerr_param *param)
307 {
308 	qdf_mem_zero(param, sizeof(*param));
309 	lmac_dfs_get_thresholds(dfs->dfs_pdev_obj, param);
310 
311 	return 1;
312 }
313 
314 uint16_t dfs_chan2freq(struct dfs_channel *chan)
315 {
316 	if (!chan)
317 		return 0;
318 
319 	return chan == WLAN_CHAN_ANYC ? WLAN_CHAN_ANY : chan->dfs_ch_freq;
320 }
321