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