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