blob: 71c04b573b0a3eeb0fa8a4a1d5dc366931671ec0 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*===========================================================================
29
30 dfs_staggered.c
31
32 OVERVIEW:
33
34 Source code borrowed from QCA_MAIN DFS module
35
36 DEPENDENCIES:
37
38 Are listed for each API below.
39
40 ===========================================================================*/
41
42/*===========================================================================
43
44 EDIT HISTORY FOR FILE
45
46 This section contains comments describing changes made to the module.
47 Notice that changes are listed in reverse chronological order.
48
49 when who what, where, why
50 ---------- --- --------------------------------------------------------
51
52 ===========================================================================*/
53
54#include "dfs.h"
55/* TO DO DFS
56 #include <ieee80211_var.h>
57 */
58#ifdef ATH_SUPPORT_DFS
59
60static int is_pri_multiple(uint32_t sample_pri, uint32_t refpri)
61{
62#define MAX_ALLOWED_MISSED 3
63 int i;
64
65 if (sample_pri < refpri || (!refpri))
66 return 0;
67
68 for (i = 1; i <= MAX_ALLOWED_MISSED; i++) {
69 if ((sample_pri % (i * refpri) <= 5)) {
70 /* printk("sample_pri=%d is a multiple of refpri=%d\n", sample_pri, refpri); */
71 return 1;
72 }
73 }
74 return 0;
75#undef MAX_ALLOWED_MISSED
76}
77
78static int is_unique_pri(uint32_t highestpri, uint32_t midpri,
79 uint32_t lowestpri, uint32_t refpri)
80{
81#define DFS_STAGGERED_PRI_MARGIN_MIN 20
82#define DFS_STAGGERED_PRI_MARGIN_MAX 400
83 if ((DFS_DIFF(lowestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
84 (DFS_DIFF(midpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN) &&
85 (DFS_DIFF(highestpri, refpri) >= DFS_STAGGERED_PRI_MARGIN_MIN)) {
86 return 1;
87 } else {
88 if ((is_pri_multiple(refpri, highestpri))
89 || (is_pri_multiple(refpri, lowestpri))
90 || (is_pri_multiple(refpri, midpri)))
91 return 0;
92 }
93 return 0;
94#undef DFS_STAGGERED_PRI_MARGIN_MIN
95#undef DFS_STAGGERED_PRI_MARGIN_MAX
96}
97
98int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf,
99 uint32_t deltaT, uint32_t width)
100{
101 uint32_t refpri, refdur, searchpri = 0, deltapri; /* , averagerefpri; */
102 uint32_t n, i, primargin, durmargin;
103 int score[DFS_MAX_DL_SIZE], delayindex, dindex, found = 0;
104 struct dfs_delayline *dl;
105 uint32_t scoreindex, lowpriindex = 0, lowpri = 0xffff;
106#if 0
107 int numpulses = 0;
108#endif
109 int higherthan, lowerthan, numscores;
110 int numpulseshigh = 0, numpulsesmid = 0, numpulsestemp = 0;
111 uint32_t lowestscore = 0, lowestscoreindex = 0, lowestpri = 0;
112 uint32_t midscore = 0, midscoreindex = 0, midpri = 0;
113 uint32_t highestscore = 0, highestscoreindex = 0, highestpri = 0;
114
115 dl = &rf->rf_dl;
116 if (dl->dl_numelems < (rf->rf_threshold - 1)) {
117 DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
118 "numelems %d < threshold for filter %d\n",
119 dl->dl_numelems, rf->rf_pulseid);
120 return 0;
121 }
122 if (deltaT > rf->rf_filterlen) {
123 DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
124 "numelems %d < threshold for filter %d\n",
125 dl->dl_numelems, rf->rf_pulseid);
126 return 0;
127 }
128 primargin = 6;
129 if (rf->rf_maxdur < 10) {
130 durmargin = 4;
131 } else {
132 durmargin = 6;
133 }
134
135 OS_MEMZERO(score, sizeof(int) * DFS_MAX_DL_SIZE);
136 /* find out the lowest pri */
137 for (n = 0; n < dl->dl_numelems; n++) {
138 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
139 refpri = dl->dl_elems[delayindex].de_time;
140 if (refpri == 0)
141 continue;
142 else if (refpri < lowpri) {
143 lowpri = dl->dl_elems[delayindex].de_time;
144 lowpriindex = n;
145 }
146 }
147 /* find out the each delay element's pri score */
148 for (n = 0; n < dl->dl_numelems; n++) {
149 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
150 refpri = dl->dl_elems[delayindex].de_time;
151 if (refpri == 0) {
152 continue;
153 }
154
155 if ((refpri > rf->rf_maxpri) || (refpri < rf->rf_minpri)) {
156 score[n] = 0;
157 continue;
158 }
159
160 for (i = 0; i < dl->dl_numelems; i++) {
161 dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
162 searchpri = dl->dl_elems[dindex].de_time;
163 deltapri = DFS_DIFF(searchpri, refpri);
164 if (deltapri < primargin)
165 score[n]++;
166 }
167 }
168 for (n = 0; n < dl->dl_numelems; n++) {
169 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
170 refdur = dl->dl_elems[delayindex].de_time;
171 DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "score[%d]=%d pri=%d\n", n,
172 score[n], refdur);
173 }
174
175 /* find out the 2 or 3 highest scorers */
176 scoreindex = 0;
177 highestscore = 0;
178 highestscoreindex = 0;
179 highestpri = 0;
180 numscores = 0;
181 lowestscore = 0;
182
183 for (n = 0; n < dl->dl_numelems; n++) {
184 higherthan = 0;
185 lowerthan = 0;
186 delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK;
187 refpri = dl->dl_elems[delayindex].de_time;
188
189 if ((score[n] >= highestscore) &&
190 (is_unique_pri(highestpri, midpri, lowestpri, refpri))) {
191 lowestscore = midscore;
192 lowestpri = midpri;
193 lowestscoreindex = midscoreindex;
194 midscore = highestscore;
195 midpri = highestpri;
196 midscoreindex = highestscoreindex;
197 highestscore = score[n];
198 highestpri = refpri;
199 highestscoreindex = n;
200 } else {
201 if ((score[n] >= midscore) &&
202 (is_unique_pri
203 (highestpri, midpri, lowestpri, refpri))) {
204 lowestscore = midscore;
205 lowestpri = midpri;
206 lowestscoreindex = midscoreindex;
207 midscore = score[n];
208 midpri = refpri;
209 midscoreindex = n;
210 } else if ((score[n] >= lowestscore) &&
211 (is_unique_pri
212 (highestpri, midpri, lowestpri, refpri))) {
213 lowestscore = score[n];
214 lowestpri = refpri;
215 lowestscoreindex = n;
216 }
217 }
218
219 }
220
221 if (midscore == 0) {
222 /* This means we have only 1 pulse type. It can not be staggered! */
223 return 0;
224 }
225
226 DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
227 "FINAL highestscore=%d highestscoreindex=%d highestpri=%d\n",
228 highestscore, highestscoreindex, highestpri);
229 DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
230 "FINAL lowestscore=%d lowestscoreindex=%d lowpri=%d\n",
231 lowestscore, lowestscoreindex, lowestpri);
232 DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
233 "FINAL midscore=%d midscoreindex=%d midpri=%d\n",
234 midscore, midscoreindex, midpri);
235
236 delayindex = (dl->dl_firstelem + highestscoreindex) & DFS_MAX_DL_MASK;
237 refdur = dl->dl_elems[delayindex].de_dur;
238 refpri = dl->dl_elems[delayindex].de_time;
239 DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
240 "highscoreindex=%d refdur=%d refpri=%d\n",
241 highestscoreindex, refdur, refpri);
242
243 numpulsestemp =
244 dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur, 0,
245 highestpri);
246 numpulseshigh = numpulsestemp;
247 numpulsestemp =
248 dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur, 0,
249 highestpri + midpri);
250 if (numpulsestemp > numpulseshigh) {
251 numpulseshigh = numpulsestemp;
252 }
253 numpulsestemp =
254 dfs_bin_pri_check(dfs, rf, dl, highestscore, refpri, refdur, 0,
255 highestpri + midpri + lowestpri);
256 if (numpulsestemp > numpulseshigh) {
257 numpulseshigh = numpulsestemp;
258 }
259
260 delayindex = (dl->dl_firstelem + midscoreindex) & DFS_MAX_DL_MASK;
261 refdur = dl->dl_elems[delayindex].de_dur;
262 refpri = dl->dl_elems[delayindex].de_time;
263 DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
264 "midscoreindex=%d refdur=%d refpri=%d\n",
265 midscoreindex, refdur, refpri);
266
267 /* numpulsesmid = dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur,0, 1); */
268 numpulsestemp =
269 dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur, 0, midpri);
270 numpulsesmid = numpulsestemp;
271 numpulsestemp =
272 dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur, 0,
273 highestpri + midpri);
274 if (numpulsestemp > numpulsesmid) {
275 numpulsesmid = numpulsestemp;
276 }
277 numpulsestemp =
278 dfs_bin_pri_check(dfs, rf, dl, midscore, refpri, refdur, 0,
279 highestpri + midpri + lowestpri);
280 if (numpulsestemp > numpulsesmid) {
281 numpulsesmid = numpulsestemp;
282 }
283
284 /*delayindex = (dl->dl_firstelem + lowestscoreindex) & DFS_MAX_DL_MASK;
285 refdur = dl->dl_elems[delayindex].de_dur;
286 refpri = dl->dl_elems[delayindex].de_time;
287 DFS_DPRINTK(ic, ATH_DEBUG_DFS1, "lowestscoreindex=%d refdur=%d refpri=%d\n", lowestscoreindex, refdur, refpri);
288
289 numpulseslow = dfs_bin_pri_check(dfs, rf, dl, lowestscore, refpri, refdur,0, 1);
290 */
291 DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
292 "numpulseshigh=%d, numpulsesmid=%d\n",
293 numpulseshigh, numpulsesmid);
294/* printf("numpulseshigh=%d, numpulsesmid=%d, numpulseslow %d\n",numpulseshigh, numpulsesmid, numpulseslow); */
295
296 if ((numpulseshigh >= rf->rf_threshold)
297 && (numpulsesmid >= rf->rf_threshold)) {
298 /*if (numpulses >= rf->rf_threshold) { */
299 found = 1;
300 DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
301 "MATCH filter=%u numpulseshigh=%u numpulsesmid= %u thresh=%u\n",
302 rf->rf_pulseid, numpulseshigh, numpulsesmid,
303 rf->rf_threshold);
304 }
305 return found;
306}
307
308#endif /* ATH_SUPPORT_DFS */