xref: /wlan-driver/qca-wifi-host-cmn/umac/dfs/core/src/filtering/dfs_staggered.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2002-2010, 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 /**
19  * DOC: ETSI 1.5.1 introduced new waveforms which use staggered PRIs within
20  * the same waveform. This file contains the detection implementation for
21  * these specific types of radars. This logic is different from the other
22  * detection because it must detect waveforms that may have 2 or more
23  * different PRIs (pulse repetition intervals).
24  */
25 
26 #include "../dfs.h"
27 #include "../dfs_process_radar_found_ind.h"
28 
29 /**
30  * dfs_is_pri_multiple() - Is PRI is multiple.
31  * @sample_pri: Sample PRI.
32  * @refpri: Reference PRI.
33  */
dfs_is_pri_multiple(uint32_t sample_pri,uint32_t refpri)34 static int dfs_is_pri_multiple(uint32_t sample_pri, uint32_t refpri)
35 {
36 #define MAX_ALLOWED_MISSED 3
37 	int i;
38 
39 	if (sample_pri < refpri || (!refpri))
40 		return 0;
41 
42 	for (i = 1; i <= MAX_ALLOWED_MISSED; i++) {
43 		if ((sample_pri%(i*refpri) <= 5))
44 			return 1;
45 	}
46 
47 	return 0;
48 #undef MAX_ALLOWED_MISSED
49 }
50 
51 /**
52  * dfs_is_unique_pri() - Check for the unique PRI.
53  * @highestpri: Highest PRI.
54  * @midpri: MID PRI.
55  * @lowestpri: Lowest PRI.
56  * @refpri: Reference PRI.
57  */
dfs_is_unique_pri(uint32_t highestpri,uint32_t midpri,uint32_t lowestpri,uint32_t refpri)58 static int dfs_is_unique_pri(uint32_t highestpri, uint32_t midpri,
59 		uint32_t lowestpri, uint32_t refpri)
60 {
61 #define DFS_STAGGERED_PRI_MARGIN_MIN  20
62 #define DFS_STAGGERED_PRI_MARGIN_MAX  400
63 	if ((DFS_DIFF(lowestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
64 		(DFS_DIFF(midpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
65 		(DFS_DIFF(highestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN)
66 	   )
67 		return 1;
68 
69 	if ((dfs_is_pri_multiple(refpri, highestpri)) ||
70 			(dfs_is_pri_multiple(refpri, lowestpri)) ||
71 			(dfs_is_pri_multiple(refpri, midpri)))
72 		return 0;
73 #undef DFS_STAGGERED_PRI_MARGIN_MIN
74 #undef DFS_STAGGERED_PRI_MARGIN_MAX
75 
76 	return 0;
77 }
78 
dfs_staggered_check(struct wlan_dfs * dfs,struct dfs_filter * rf,uint32_t deltaT,uint32_t width)79 int dfs_staggered_check(struct wlan_dfs *dfs, struct dfs_filter *rf,
80 		uint32_t deltaT, uint32_t width)
81 {
82 	uint32_t refpri, refdur, searchpri = 0, deltapri;
83 	uint32_t n, i, primargin, durmargin;
84 	int score[DFS_MAX_DL_SIZE], delayindex, dindex, found = 0;
85 	struct dfs_delayline *dl;
86 	uint32_t scoreindex, lowpriindex = 0, lowpri = 0xffff;
87 	int  higherthan, lowerthan, numscores;
88 	int numpulseshigh = 0, numpulsesmid = 0, numpulsestemp = 0;
89 	uint32_t lowestscore = 0, lowestscoreindex = 0, lowestpri = 0;
90 	uint32_t midscore = 0, midscoreindex = 0, midpri = 0;
91 	uint32_t highestscore = 0, highestscoreindex = 0, highestpri = 0;
92 
93 	dl = &rf->rf_dl;
94 	if (dl->dl_numelems < (rf->rf_threshold-1)) {
95 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
96 				"numelems %d < threshold for filter %d",
97 				dl->dl_numelems,
98 				rf->rf_pulseid);
99 		return 0;
100 	}
101 	if (deltaT > rf->rf_filterlen) {
102 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
103 				"numelems %d < threshold for filter %d",
104 				dl->dl_numelems,
105 				rf->rf_pulseid);
106 		return 0;
107 	}
108 	primargin = 6;
109 	if (rf->rf_maxdur < 10)
110 		durmargin = 4;
111 	else
112 		durmargin = 6;
113 
114 	qdf_mem_zero(score, sizeof(int)*DFS_MAX_DL_SIZE);
115 	/* Find out the lowest pri */
116 	for (n = 0; n < dl->dl_numelems; n++) {
117 		delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
118 		refpri = dl->dl_elems[delayindex].de_time;
119 		if (refpri == 0) {
120 			continue;
121 		} else if (refpri < lowpri) {
122 			lowpri = dl->dl_elems[delayindex].de_time;
123 			lowpriindex = n;
124 		}
125 	}
126 
127 	/* Find out the each delay element's pri score */
128 	for (n = 0; n < dl->dl_numelems; n++) {
129 		delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
130 		refpri = dl->dl_elems[delayindex].de_time;
131 		if (refpri == 0)
132 			continue;
133 
134 		if ((refpri > rf->rf_maxpri) || (refpri < rf->rf_minpri)) {
135 			score[n] = 0;
136 			continue;
137 		}
138 
139 		for (i = 0; i < dl->dl_numelems; i++) {
140 			dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
141 			searchpri = dl->dl_elems[dindex].de_time;
142 			deltapri = DFS_DIFF(searchpri, refpri);
143 			if (deltapri < primargin)
144 				score[n]++;
145 		}
146 	}
147 
148 	dfs->dfs_freq_offset = DFS_SIDX_TO_FREQ_OFFSET(
149 				       (dl->dl_min_sidx + dl->dl_max_sidx) / 2);
150 
151 	for (n = 0; n < dl->dl_numelems; n++) {
152 		delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
153 		refdur = dl->dl_elems[delayindex].de_time;
154 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
155 				"score[%d]=%d pri=%d",
156 				n, score[n], refdur);
157 	}
158 
159 	/* Find out the 2 or 3 highest scorers */
160 	scoreindex = 0;
161 	highestscore = 0;
162 	highestscoreindex = 0;
163 	highestpri = 0; numscores = 0; lowestscore = 0;
164 
165 	for (n = 0; n < dl->dl_numelems; n++) {
166 		higherthan = 0;
167 		lowerthan = 0;
168 		delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
169 		refpri = dl->dl_elems[delayindex].de_time;
170 
171 		if (!dfs_is_unique_pri(highestpri,
172 					midpri,
173 					lowestpri,
174 					refpri))
175 			continue;
176 
177 		if (score[n] >= highestscore) {
178 			lowestscore = midscore;
179 			lowestpri = midpri;
180 			lowestscoreindex = midscoreindex;
181 			midscore = highestscore;
182 			midpri = highestpri;
183 			midscoreindex = highestscoreindex;
184 			highestscore = score[n];
185 			highestpri = refpri;
186 			highestscoreindex = n;
187 		} else if (score[n] >= midscore) {
188 			lowestscore = midscore;
189 			lowestpri = midpri;
190 			lowestscoreindex = midscoreindex;
191 			midscore = score[n];
192 			midpri = refpri;
193 			midscoreindex = n;
194 		} else if (score[n] >= lowestscore) {
195 			lowestscore = score[n];
196 			lowestpri = refpri;
197 			lowestscoreindex = n;
198 		}
199 	}
200 
201 	if (midscore == 0)
202 		return 0;
203 
204 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
205 			"FINAL highestscore=%d highestscoreindex = %d highestpri = %d",
206 			highestscore, highestscoreindex, highestpri);
207 
208 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
209 			"FINAL lowestscore=%d lowestscoreindex=%d lowpri=%d",
210 			lowestscore, lowestscoreindex, lowestpri);
211 
212 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
213 			"FINAL midscore=%d midscoreindex=%d midpri=%d",
214 			midscore, midscoreindex, midpri);
215 
216 	delayindex = (dl->dl_firstelem + highestscoreindex) & DFS_MAX_DL_MASK;
217 	refdur = dl->dl_elems[delayindex].de_dur;
218 	refpri = dl->dl_elems[delayindex].de_time;
219 
220 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
221 			"highscoreindex=%d refdur=%d refpri=%d",
222 			highestscoreindex, refdur, refpri);
223 
224 	numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri,
225 			refdur, 0, highestpri);
226 	numpulseshigh = numpulsestemp;
227 	numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri,
228 			refdur, 0, highestpri + midpri);
229 	if (numpulsestemp > numpulseshigh)
230 		numpulseshigh = numpulsestemp;
231 
232 	numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri,
233 			refdur, 0, highestpri + midpri + lowestpri);
234 	if (numpulsestemp > numpulseshigh)
235 		numpulseshigh = numpulsestemp;
236 
237 	delayindex = (dl->dl_firstelem + midscoreindex) & DFS_MAX_DL_MASK;
238 	refdur = dl->dl_elems[delayindex].de_dur;
239 	refpri = dl->dl_elems[delayindex].de_time;
240 	dfs_debug(dfs, WLAN_DEBUG_DFS1,
241 			"midscoreindex=%d refdur=%d refpri=%d",
242 			midscoreindex, refdur, refpri);
243 
244 	numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,
245 			0, midpri);
246 	numpulsesmid = numpulsestemp;
247 	numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,
248 			0, highestpri + midpri);
249 	if (numpulsestemp > numpulsesmid)
250 		numpulsesmid = numpulsestemp;
251 	numpulsestemp = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,
252 			0, highestpri + midpri + lowestpri);
253 	if (numpulsestemp > numpulsesmid)
254 		numpulsesmid = numpulsestemp;
255 
256 	dfs_debug(dfs, WLAN_DEBUG_DFS2,
257 			"numpulseshigh=%d, numpulsesmid=%d",
258 			numpulseshigh, numpulsesmid);
259 
260 	if ((numpulseshigh >= rf->rf_threshold) &&
261 			(numpulsesmid >= rf->rf_threshold)) {
262 		found = 1;
263 		dfs_debug(dfs, WLAN_DEBUG_DFS2,
264 				"MATCH filter=%u numpulseshigh=%u numpulsesmid= %u thresh=%u",
265 				rf->rf_pulseid, numpulseshigh,
266 				numpulsesmid, rf->rf_threshold);
267 	}
268 
269 	return found;
270 }
271