From 382c50fff7a52a8aab678f6f6c46833fab4a5b71 Mon Sep 17 00:00:00 2001 From: Abhijit Pradhan Date: Sun, 20 Aug 2017 11:49:35 +0530 Subject: [PATCH] qcacmn: refactor DFS code Part-I Reduced the max indentation level to five. Spilt functions to several smaller functions. Only a few functions were split in this commit. Rest need to be done in future commits. Change-Id: I1c9dcf3ae12edef6bcce37023f93d062705e0142 CRs-Fixed: 2098511 --- umac/dfs/core/src/dfs.h | 59 +- umac/dfs/core/src/filtering/dfs_bindetects.c | 771 ++++++++--- umac/dfs/core/src/filtering/dfs_debug.c | 44 +- umac/dfs/core/src/filtering/dfs_fcc_bin5.c | 106 +- umac/dfs/core/src/filtering/dfs_init.c | 214 +-- umac/dfs/core/src/filtering/dfs_misc.c | 61 +- umac/dfs/core/src/filtering/dfs_phyerr_tlv.c | 122 +- .../core/src/filtering/dfs_process_phyerr.c | 213 +-- .../src/filtering/dfs_process_radarevent.c | 1230 ++++++++++------- umac/dfs/core/src/filtering/dfs_radar.c | 45 +- umac/dfs/core/src/filtering/dfs_staggered.c | 39 +- umac/dfs/core/src/misc/dfs.c | 24 +- 12 files changed, 1832 insertions(+), 1096 deletions(-) diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 77edfe4949..0a30bec7f9 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -67,6 +67,8 @@ * XXX Peregrine reports pulses in microseconds, not hardware clocks! */ +#define MAX_DUR_FOR_LOW_RSSI 4 + /** * Cascade has issue with reported duration especially when there is a * crossover of chirp from one segment to another. It may report a value @@ -231,7 +233,7 @@ * struct dfs_pulseparams - DFS pulse param structure. * @p_time: Time for start of pulse in usecs. * @p_dur: Duration of pulse in usecs. - * @p_rssi: Duration of pulse in usecs. + * @p_rssi: RSSI of pulse. */ struct dfs_pulseparams { uint64_t p_time; @@ -497,7 +499,7 @@ struct dfs_nolelem { /** * struct dfs_info - DFS Info. * @rn_use_nol: Use the NOL when radar found (default: TRUE). - * @rn_numradars: Number of different types of radars. + * @rn_ftindex: Number of different types of radars. * @rn_lastfull_ts: Last 64 bit timstamp from recv interrupt. * @rn_last_ts: last 15 bit ts from recv descriptor. * @rn_last_unique_ts: last unique 32 bit ts from recv descriptor. @@ -513,7 +515,7 @@ struct dfs_nolelem { */ struct dfs_info { int rn_use_nol; - uint32_t rn_numradars; + uint32_t rn_ftindex; uint64_t rn_lastfull_ts; uint16_t rn_last_ts; uint32_t rn_last_unique_ts; @@ -663,7 +665,7 @@ struct dfs_event_log { * @dfs_radarf[]: dfs_radarf - One filter for each radar pulse type. * @dfs_rinfo: State vars for radar processing. * @dfs_b5radars: array of bin5 radar events. - * @dfs_radartable: map of radar durs to filter types. + * @dfs_ftindextable: map of radar durs to filter types. * @dfs_nol: Non occupancy list for radar. * @dfs_nol_count: How many items? * @dfs_defaultparams: Default phy params per radar state. @@ -752,7 +754,7 @@ struct wlan_dfs { struct dfs_filtertype *dfs_radarf[DFS_MAX_RADAR_TYPES]; struct dfs_info dfs_rinfo; struct dfs_bin5radars *dfs_b5radars; - int8_t **dfs_radartable; + int8_t **dfs_ftindextable; struct dfs_nolelem *dfs_nol; int dfs_nol_count; struct wlan_dfs_phyerr_param dfs_defaultparams; @@ -1012,7 +1014,8 @@ void dfs_radar_found_action(struct wlan_dfs *dfs); * and ext channels as being unavailable. This should be fixed for 802.11ac * or we'll quickly run out of valid channels to use. * - * Return: If a radar event is found, return 1. Otherwise, return 0. + * Return: If a radar event found on non-DFS channel return 0. + * Otherwise, return 1. */ int dfs_process_radarevent(struct wlan_dfs *dfs, struct dfs_ieee80211_channel *chan); @@ -1229,18 +1232,6 @@ void dfs_add_pulse(struct wlan_dfs *dfs, uint32_t deltaT, uint64_t this_ts); -/** - * dfs_bin_fixedpattern_check() - Checks the BIN pattern. - * @dfs: Pointer to wlan_dfs structure. - * @rf: Pointer to dfs_filter structure. - * @dur: Duration. - * ext_chan_flag : Ext channel flag. - */ -int dfs_bin_fixedpattern_check(struct wlan_dfs *dfs, - struct dfs_filter *rf, - uint32_t dur, - int ext_chan_flag); - /** * dfs_bin_check() - BIN check * @dfs: Pointer to wlan_dfs structure. @@ -1845,7 +1836,6 @@ int dfs_process_phyerr_merlin(struct wlan_dfs *dfs, * __dfs_process_radarevent() - Continuation of process a radar event function. * @dfs: Pointer to wlan_dfs structure. * @ft: Pointer to dfs_filtertype structure. - * @rf: Pointer to dfs_filter structure. * @re: Pointer to dfs_event structure. * @this_ts: Timestamp. * @@ -1858,7 +1848,6 @@ int dfs_process_phyerr_merlin(struct wlan_dfs *dfs, */ void __dfs_process_radarevent(struct wlan_dfs *dfs, struct dfs_filtertype *ft, - struct dfs_filter *rf, struct dfs_event *re, uint64_t this_ts, int *found); @@ -1879,34 +1868,8 @@ void bin5_rules_check_internal(struct wlan_dfs *dfs, uint32_t *numevents, uint32_t prev, uint32_t i, - uint32_t this); - -/** - * count_the_other_delay_elements() - Counts the ther delay elements. - * @dfs: Pointer to wlan_dfs structure. - * @rf: Pointer to dfs_filter structure. - * @dl: Pointer to dfs_delayline structure. - * @i: Index value. - * @refpri: Current "filter" time for start of pulse in usecs. - * @refdur: Duration value. - * @primargin: Primary margin. - * @durmargin: Duration margin. - * @numpulses: Number of pulses. - * @prev_good_timestamp: Previous good timestamp. - * @fundamentalpri: Highest PRI. - */ -void count_the_other_delay_elements(struct wlan_dfs *dfs, - struct dfs_filter *rf, - struct dfs_delayline *dl, - uint32_t i, - uint32_t refpri, - uint32_t refdur, - uint32_t primargin, - uint32_t durmargin, - int *numpulses, - uint32_t *prev_good_timestamp, - int fundamentalpri - ); + uint32_t this, + int *index); /** * dfs_main_timer_init() - Initialize dfs timers. diff --git a/umac/dfs/core/src/filtering/dfs_bindetects.c b/umac/dfs/core/src/filtering/dfs_bindetects.c index 1af6066d4e..0f295a1623 100644 --- a/umac/dfs/core/src/filtering/dfs_bindetects.c +++ b/umac/dfs/core/src/filtering/dfs_bindetects.c @@ -25,102 +25,249 @@ #include "../dfs.h" -int dfs_bin_fixedpattern_check(struct wlan_dfs *dfs, +/** + * dfs_find_first_index_within_window() - Find first index within window + * @pl: Pointer to dfs_pulseline structure. + * @index: Index to dfs pulse elements. + * @start_ts: Start timestamp. + * + * Return: Returns index. + */ +static inline uint32_t dfs_find_first_index_within_window( + struct dfs_pulseline *pl, + uint32_t index, + uint64_t start_ts) +{ + uint16_t i; + + /* Find the index of first element in our window of interest. */ + for (i = 0; i < pl->pl_numelems; i++) { + index = (index - 1) & DFS_MAX_PULSE_BUFFER_MASK; + if (pl->pl_elems[index].p_time >= start_ts) { + continue; + } else { + index = (index) & DFS_MAX_PULSE_BUFFER_MASK; + break; + } + } + + return index; +} + +/** + * dfs_ts_within_window() - Calculate pulses for timestamp within window + * @dfs: Pointer to wlan_dfs structure. + * @pl: Pointer to dfs_pulseline structure. + * @index: Index to dfs pulse elements. + * @dur: Pulse duration/width + * @numpulses: Number of pulses + * + * Return: Returns 1 if pulse count is incremented else returns 0. + */ +static inline bool dfs_ts_within_window( + struct wlan_dfs *dfs, + struct dfs_pulseline *pl, + uint32_t *index, + uint32_t dur, + int *numpulses) +{ + uint32_t deltadur; + + deltadur = DFS_DIFF(pl->pl_elems[*index].p_dur, dur); + if ((pl->pl_elems[*index].p_dur == 1) || + ((dur != 1) && (deltadur <= 2))) { + (*numpulses)++; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, "numpulses %u\n", *numpulses); + return 1; + } + + return 0; +} + +/** + * dfs_ts_eq_prevts() - Calculate pulses for timestamp equals to prev event + * @dfs: Pointer to wlan_dfs structure. + * @pl: Pointer to dfs_pulseline structure. + * @index: Index to dfs pulse elements. + * @dur: Pulse duration/width + * @numpulses: Number of pulses + * + * Return: Returns 1 if pulse count is incremented else returns 0. + */ +static inline bool dfs_ts_eq_prevts( + struct wlan_dfs *dfs, + struct dfs_pulseline *pl, + uint64_t next_event_ts, + uint64_t event_ts, + uint32_t refpri, + uint32_t *index, + uint32_t dur, + int *numpulses) + +{ + uint32_t deltadur; + + if (((next_event_ts - event_ts) > refpri) || + ((next_event_ts - event_ts) == 0)) { + deltadur = DFS_DIFF(pl->pl_elems[*index].p_dur, dur); + if ((pl->pl_elems[*index].p_dur == 1) || + ((pl->pl_elems[*index].p_dur != 1) && + (deltadur <= 2))) { + (*numpulses)++; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "zero PRI: numpulses %u\n", *numpulses); + return 1; + } + } + + return 0; +} + +/** + * dfs_pulses_within_window() - Calculate pulses within window + * @dfs: Pointer to wlan_dfs structure. + * @window_start: Start of the window. + * @window_end: End of the window. + * @index: Index to dfs pulse elements. + * @dur: Pulse duration/width. + * @refpri: reference PRI. + * + * Return: Returns 1 if pulse count is incremented else returns 0. + */ +static inline int dfs_pulses_within_window( + struct wlan_dfs *dfs, + uint64_t window_start, + uint64_t window_end, + uint32_t *index, + uint32_t dur, + uint32_t refpri) +{ + int numpulses = 0; + uint32_t i; + struct dfs_pulseline *pl = dfs->pulses; + uint64_t event_ts, prev_event_ts, next_event_ts; + uint32_t next_index; + + for (i = 0; i < pl->pl_numelems; i++) { + prev_event_ts = pl->pl_elems[*index].p_time; + *index = (*index+1) & DFS_MAX_PULSE_BUFFER_MASK; + event_ts = pl->pl_elems[*index].p_time; + next_index = (*index+1) & DFS_MAX_PULSE_BUFFER_MASK; + next_event_ts = pl->pl_elems[next_index].p_time; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, "ts %u\n", + (uint32_t)event_ts); + + if ((event_ts <= window_end) && (event_ts >= window_start)) { + if (dfs_ts_within_window(dfs, pl, index, dur, + &numpulses)) + break; + } else if (event_ts > window_end) { + *index = (*index-1) & DFS_MAX_PULSE_BUFFER_MASK; + break; + } else if (event_ts == prev_event_ts) { + if (dfs_ts_eq_prevts(dfs, pl, next_event_ts, event_ts, + refpri, index, dur, &numpulses)) + break; + } + } + + return numpulses; +} + +/** + * dfs_count_pulses() - Count pulses + * @dfs: Pointer to wlan_dfs structure. + * @rf: Pointer to dfs_filter structure. + * @dur: Pulse duration/width. + * @ext_chan_flag : Ext channel flag. + * @primargin: Primary margin. + * @index: Index to dfs pulse elements. + * @refpri: reference PRI. + * @start_ts: Start timestamp. + * + * Return: Returns number of pulses within window. + */ +static inline int dfs_count_pulses( + struct wlan_dfs *dfs, + struct dfs_filter *rf, + uint32_t dur, + int ext_chan_flag, + int primargin, + uint32_t index, + uint32_t refpri, + uint64_t start_ts) +{ + uint32_t n; + int numpulses = 0; + uint64_t window_start, window_end; + + for (n = 0; n <= rf->rf_numpulses; n++) { + window_start = (start_ts + (refpri*n))-(primargin+n); + window_end = window_start + 2*(primargin+n); + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "window_start %u window_end %u\n", + (uint32_t)window_start, (uint32_t)window_end); + numpulses += dfs_pulses_within_window(dfs, window_start, + window_end, &index, dur, refpri); + } + + return numpulses; +} + +/** + * dfs_bin_fixedpattern_check() - Fixed pattern check + * @dfs: Pointer to wlan_dfs structure. + * @rf: Pointer to dfs_filter structure. + * @dur: Pulse duration/width. + * @ext_chan_flag : Ext channel flag. + */ +static int dfs_bin_fixedpattern_check( + struct wlan_dfs *dfs, struct dfs_filter *rf, uint32_t dur, int ext_chan_flag) { struct dfs_pulseline *pl = dfs->pulses; - int i, n, refpri, primargin, numpulses = 0; - uint64_t start_ts, end_ts, event_ts, prev_event_ts; - uint64_t next_event_ts, window_start, window_end; - uint32_t index, next_index, deltadur; - - /* For fixed pattern types, rf->rf_patterntype=1. */ - primargin = dfs_get_pri_margin(dfs, ext_chan_flag, - (rf->rf_patterntype == 1)); + int primargin, numpulses, fil_thresh; + uint64_t start_ts, end_ts; + uint32_t last_index, first_index; + uint32_t refpri; refpri = (rf->rf_minpri + rf->rf_maxpri)/2; - index = pl->pl_lastelem; - end_ts = pl->pl_elems[index].p_time; + last_index = pl->pl_lastelem; + end_ts = pl->pl_elems[last_index].p_time; start_ts = end_ts - (refpri*rf->rf_numpulses); DFS_DPRINTK(dfs, WLAN_DEBUG_DFS3, "lastelem ts=%llu start_ts=%llu, end_ts=%llu\n", - (unsigned long long)pl->pl_elems[index].p_time, + (unsigned long long)pl->pl_elems[last_index].p_time, (unsigned long long)start_ts, (unsigned long long) end_ts); - /* Find the index of first element in our window of interest. */ - for (i = 0; i < pl->pl_numelems; i++) { - index = (index - 1) & DFS_MAX_PULSE_BUFFER_MASK; - if (pl->pl_elems[index].p_time >= start_ts) - continue; - else { - index = (index) & DFS_MAX_PULSE_BUFFER_MASK; - break; - } - } - for (n = 0; n <= rf->rf_numpulses; n++) { - window_start = (start_ts + (refpri*n))-(primargin+n); - window_end = window_start + 2*(primargin+n); - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "window_start %u window_end %u\n", - (uint32_t)window_start, (uint32_t)window_end); + first_index = dfs_find_first_index_within_window(pl, last_index, + start_ts); - for (i = 0; i < pl->pl_numelems; i++) { - prev_event_ts = pl->pl_elems[index].p_time; - index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; - event_ts = pl->pl_elems[index].p_time; - next_index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; - next_event_ts = pl->pl_elems[next_index].p_time; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, "ts %u\n", - (uint32_t)event_ts); + /* For fixed pattern types, rf->rf_patterntype=1. */ + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, + (rf->rf_patterntype == 1)); - if ((event_ts <= window_end) && - (event_ts >= window_start)) { - deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, - dur); - if ((pl->pl_elems[index].p_dur == 1) || - ((dur != 1) && (deltadur <= 2))) { - numpulses++; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "numpulses %u\n", numpulses); - break; - } - } else if (event_ts > window_end) { - index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK; - break; - } else if (event_ts == prev_event_ts) { - if (((next_event_ts - event_ts) > refpri) || - ((next_event_ts - event_ts) == 0)) { - deltadur = - DFS_DIFF(pl->pl_elems[index].p_dur, - dur); - if ((pl->pl_elems[index].p_dur == 1) || - ((pl->pl_elems[index].p_dur != - 1) && (deltadur <= 2))) { - numpulses++; - DFS_DPRINTK(dfs, - WLAN_DEBUG_DFS2, - "zero PRI: numpulses %u\n", - numpulses); - break; - } - } - } - } - } - if (numpulses >= dfs_get_filter_threshold(dfs, rf, ext_chan_flag)) { + numpulses = dfs_count_pulses(dfs, rf, dur, ext_chan_flag, primargin, + first_index, refpri, start_ts); + + fil_thresh = dfs_get_filter_threshold(dfs, rf, ext_chan_flag); + + if (numpulses >= fil_thresh) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, "%s FOUND filterID=%u numpulses=%d unadj thresh=%d\n", __func__, rf->rf_pulseid, numpulses, rf->rf_threshold); return 1; - } else + } else { return 0; + } } -void dfs_add_pulse(struct wlan_dfs *dfs, +void dfs_add_pulse( + struct wlan_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, uint32_t deltaT, @@ -165,85 +312,107 @@ void dfs_add_pulse(struct wlan_dfs *dfs, dl->dl_firstelem, dl->dl_lastelem); } -int dfs_bin_check(struct wlan_dfs *dfs, - struct dfs_filter *rf, - uint32_t deltaT, - uint32_t width, - int ext_chan_flag) +/** + * dfs_find_lowestpri() - Find lowest PRI + * @dl: Pointer to dfs delayline. + * @lowpriindex: Low PRI index. + * @lowpri: Low PRI + */ +static inline void dfs_find_lowestpri( + struct dfs_delayline *dl, + uint32_t *lowpriindex, + uint32_t *lowpri) { - struct dfs_delayline *dl; - uint32_t refpri, refdur, searchpri, deltapri, deltapri_2, deltapri_3; - uint32_t averagerefpri, n, i, primargin, durmargin, highscore; - uint32_t highscoreindex; - int score[DFS_MAX_DL_SIZE], delayindex, dindex, found = 0; - uint32_t scoreindex, lowpriindex = 0, lowpri = 0xffff; - int numpulses = 0; - int lowprichk = 3, pri_match = 0; + int delayindex; + uint32_t refpri; + uint32_t n; - dl = &rf->rf_dl; - if (dl->dl_numelems < (rf->rf_threshold-1)) - return 0; - - if (deltaT > rf->rf_filterlen) - return 0; - - primargin = dfs_get_pri_margin(dfs, ext_chan_flag, - (rf->rf_patterntype == 1)); - - if (rf->rf_maxdur < 10) - durmargin = 4; - else - durmargin = 6; - - if (rf->rf_patterntype == 1) { - found = dfs_bin_fixedpattern_check(dfs, rf, width, - ext_chan_flag); - if (found) - dl->dl_numelems = 0; - return found; - } - - qdf_mem_zero(score, sizeof(int)*DFS_MAX_DL_SIZE); /* Find out the lowest pri. */ for (n = 0; n < dl->dl_numelems; n++) { delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; refpri = dl->dl_elems[delayindex].de_time; if (refpri == 0) { continue; - } else if (refpri < lowpri) { - lowpri = dl->dl_elems[delayindex].de_time; - lowpriindex = n; + } else if (refpri < *lowpri) { + *lowpri = dl->dl_elems[delayindex].de_time; + *lowpriindex = n; } } - /* Find out the each delay element's pri score. */ +} + +/** + * dfs_calculate_score() - Calculate score for the score index + * if PRI match is found + * @dl: Pointer to dfs delayline. + * @rf: Pointer to dfs_filter structure. + * @score: score array. + * @refpri: reference PRI. + * @primargin: PRI margin. + * @score_index: Score index. + */ +static inline void dfs_calculate_score( + struct dfs_delayline *dl, + struct dfs_filter *rf, + int *score, + uint32_t refpri, + uint32_t primargin, + uint32_t score_index) +{ + int pri_match = 0; + int dindex; + uint32_t searchpri, deltapri, deltapri_2, deltapri_3; + uint32_t i; + + for (i = 0; i < dl->dl_numelems; i++) { + dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; + searchpri = dl->dl_elems[dindex].de_time; + deltapri = DFS_DIFF(searchpri, refpri); + deltapri_2 = DFS_DIFF(searchpri, 2*refpri); + deltapri_3 = DFS_DIFF(searchpri, 3*refpri); + if (rf->rf_ignore_pri_window == 2) + pri_match = ((deltapri < primargin) || + (deltapri_2 < primargin) || + (deltapri_3 < primargin)); + else + pri_match = (deltapri < primargin); + + if (pri_match) + score[score_index]++; + } +} + +/** + * dfs_find_priscores() - Find PRI score + * @dl: Pointer to dfs delayline. + * @rf: Pointer to dfs_filter structure. + * @score: score array. + * @primargin: PRI margin. + */ +static void dfs_find_priscores( + struct dfs_delayline *dl, + struct dfs_filter *rf, + int *score, + uint32_t primargin) +{ + int delayindex; + uint32_t refpri; + uint32_t n; + + qdf_mem_zero(score, sizeof(int)*DFS_MAX_DL_SIZE); + for (n = 0; n < dl->dl_numelems; n++) { - delayindex = (dl->dl_firstelem + n) & - DFS_MAX_DL_MASK; + delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; refpri = dl->dl_elems[delayindex].de_time; if (refpri == 0) continue; if (refpri < rf->rf_maxpri) { /* Use only valid PRI range for high score. */ - for (i = 0; i < dl->dl_numelems; i++) { - dindex = (dl->dl_firstelem + i) & - DFS_MAX_DL_MASK; - searchpri = dl->dl_elems[dindex].de_time; - deltapri = DFS_DIFF(searchpri, refpri); - deltapri_2 = DFS_DIFF(searchpri, 2*refpri); - deltapri_3 = DFS_DIFF(searchpri, 3*refpri); - if (rf->rf_ignore_pri_window == 2) { - pri_match = ((deltapri < primargin) || - (deltapri_2 < primargin) || - (deltapri_3 < primargin)); - } else { - pri_match = (deltapri < primargin); - } - if (pri_match) - score[n]++; - } + dfs_calculate_score(dl, rf, score, refpri, primargin, + n); } else { score[n] = 0; } + if (score[n] > rf->rf_threshold) { /* * We got the most possible candidate, @@ -252,67 +421,301 @@ int dfs_bin_check(struct wlan_dfs *dfs, break; } } +} + +/** + * dfs_find_highscore() - Find PRI high score + * @dl: Pointer to dfs delayline. + * @score: score array. + * @highscore: High score. + * @highscoreindex: High score index. + */ +static inline void dfs_find_highscore( + struct dfs_delayline *dl, + int *score, + uint32_t *highscore, + uint32_t *highscoreindex) +{ + int delayindex, dindex; + uint32_t n; + + *highscore = 0; + *highscoreindex = 0; - /* Find out the high scorer. */ - highscore = 0; - highscoreindex = 0; for (n = 0; n < dl->dl_numelems; n++) { - if (score[n] > highscore) { - highscore = score[n]; - highscoreindex = n; - } else if (score[n] == highscore) { + if (score[n] > *highscore) { + *highscore = score[n]; + *highscoreindex = n; + } else if (score[n] == *highscore) { /* * More than one pri has highscore take the least pri. */ - delayindex = (dl->dl_firstelem + highscoreindex) & + delayindex = (dl->dl_firstelem + *highscoreindex) & DFS_MAX_DL_MASK; dindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; if (dl->dl_elems[dindex].de_time <= dl->dl_elems[delayindex].de_time) { - highscoreindex = n; + *highscoreindex = n; } } } - /* - * Find the average pri of pulses around the pri of highscore - * or the pulses around the lowest pri. - */ + return; +} + +/** + * dfs_get_durmargin() - Find duration margin + * @rf: Pointer to dfs_filter structure. + * @durmargin: Duration margin + */ +static inline void dfs_get_durmargin( + struct dfs_filter *rf, + uint32_t *durmargin) +{ +#define DUR_THRESH 10 +#define LOW_MARGIN 4 +#define HIGH_MARGIN 6 + + if (rf->rf_maxdur < DUR_THRESH) + *durmargin = LOW_MARGIN; + else + *durmargin = HIGH_MARGIN; + +#undef DUR_THRESH +#undef LOW_MARGIN +#undef HIGH_MARGIN +} + +/** + * dfs_handle_fixedpattern() - Handle Fixed pattern radar + * @dfs: Pointer to wlan_dfs structure. + * @dl: Pointer to dfs delayline. + * @rf: Pointer to dfs_filter structure. + * @dur: Pulse duration/width + * @ext_chan_flag : Ext channel flag. + */ +static inline int dfs_handle_fixedpattern( + struct wlan_dfs *dfs, + struct dfs_delayline *dl, + struct dfs_filter *rf, + uint32_t dur, + int ext_chan_flag) +{ + int found = 0; + + found = dfs_bin_fixedpattern_check(dfs, rf, dur, ext_chan_flag); + if (found) + dl->dl_numelems = 0; + + return found; +} + +/** + * dfs_bin_basic_sanity() - Sanity check + * @dl: Pointer to dfs delayline. + * @rf: Pointer to dfs_filter structure. + * @deltaT: Delta time. + */ +static inline int dfs_bin_basic_sanity( + struct dfs_delayline *dl, + struct dfs_filter *rf, + uint32_t *deltaT) +{ + if (dl->dl_numelems < (rf->rf_threshold-1)) + return 0; + + if (*deltaT > rf->rf_filterlen) + return 0; + + return 1; +} + +/** + * dfs_find_scoreindex() - Find score index + * @rf: Pointer to dfs_filter structure. + * @highscore: High score. + * @lowpriindex: Low PRI index. + * @highscoreindex: High score index. + * @scoreindex: score index. + */ +static inline void dfs_find_scoreindex( + struct dfs_filter *rf, + uint32_t highscore, + uint32_t lowpriindex, + uint32_t highscoreindex, + uint32_t *scoreindex) +{ + int lowprichk = 3; + if (rf->rf_ignore_pri_window > 0) lowprichk = (rf->rf_threshold >> 1)+1; else lowprichk = 3; if (highscore < lowprichk) - scoreindex = lowpriindex; + *scoreindex = lowpriindex; else - scoreindex = highscoreindex; + *scoreindex = highscoreindex; +} + +/** + * dfs_find_refs() - Find reference values. + * @dl: Pointer to dfs delayline. + * @rf: Pointer to dfs_filter structure. + * @scoreindex: score index. + * @refdur: Duration value. + * @refpri: Current "filter" time for start of pulse in usecs. + */ +static inline void dfs_find_refs( + struct dfs_delayline *dl, + struct dfs_filter *rf, + uint32_t scoreindex, + uint32_t *refdur, + uint32_t *refpri) +{ + int delayindex; - /* We got the possible pri, save its parameters as reference. */ delayindex = (dl->dl_firstelem + scoreindex) & DFS_MAX_DL_MASK; - refdur = dl->dl_elems[delayindex].de_dur; - refpri = dl->dl_elems[delayindex].de_time; - averagerefpri = 0; + *refdur = dl->dl_elems[delayindex].de_dur; + *refpri = dl->dl_elems[delayindex].de_time; if (rf->rf_fixed_pri_radar_pulse) - refpri = (rf->rf_minpri + rf->rf_maxpri)/2; + *refpri = (rf->rf_minpri + rf->rf_maxpri)/2; +} - numpulses = dfs_bin_pri_check(dfs, rf, dl, score[scoreindex], refpri, - refdur, ext_chan_flag, refpri); - if (numpulses >= dfs_get_filter_threshold(dfs, rf, ext_chan_flag)) { - found = 1; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, +/** + * dfs_bin_success_print() - Debug print + * @dfs: Pointer to wlan_dfs structure. + * @rf: Pointer to dfs_filter structure. + * @ext_chan_flag: Extension channel flag. + * @numpulses: Number of pulses. + * @refpri: Current "filter" time for start of pulse in usecs. + * @refdur: Duration value. + * @primargin: PRI margin. + */ +static inline void dfs_bin_success_print( + struct wlan_dfs *dfs, + struct dfs_filter *rf, + int ext_chan_flag, + int numpulses, + uint32_t refpri, + uint32_t refdur, + uint32_t primargin) +{ + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, "ext_flag=%d MATCH filter=%u numpulses=%u thresh=%u refdur=%d refpri=%d primargin=%d\n", ext_chan_flag, rf->rf_pulseid, numpulses, rf->rf_threshold, refdur, refpri, primargin); - dfs_print_delayline(dfs, &rf->rf_dl); - dfs_print_filter(dfs, rf); + dfs_print_delayline(dfs, &rf->rf_dl); + dfs_print_filter(dfs, rf); +} + +int dfs_bin_check( + struct wlan_dfs *dfs, + struct dfs_filter *rf, + uint32_t deltaT, + uint32_t width, + int ext_chan_flag) +{ + struct dfs_delayline *dl; + uint32_t refpri, refdur; + uint32_t highscoreindex; + uint32_t primargin, highscore; + int score[DFS_MAX_DL_SIZE], found = 0; + uint32_t scoreindex, lowpriindex = 0, lowpri = 0xffff; + int numpulses = 0; + int fil_thresh; + + dl = &rf->rf_dl; + if (!dfs_bin_basic_sanity(dl, rf, &deltaT)) + return 0; + + primargin = dfs_get_pri_margin(dfs, ext_chan_flag, + (rf->rf_patterntype == 1)); + + + if (rf->rf_patterntype == 1) + return dfs_handle_fixedpattern(dfs, dl, rf, width, + ext_chan_flag); + + dfs_find_lowestpri(dl, &lowpriindex, &lowpri); + + /* Find out the each delay element's pri score. */ + dfs_find_priscores(dl, rf, score, primargin); + + /* Find out the high scorer. */ + dfs_find_highscore(dl, score, &highscore, &highscoreindex); + + /* + * Find the average pri of pulses around the pri of highscore + * or the pulses around the lowest pri. + */ + dfs_find_scoreindex(rf, highscore, lowpriindex, highscoreindex, + &scoreindex); + + /* We got the possible pri, save its parameters as reference. */ + dfs_find_refs(dl, rf, scoreindex, &refdur, &refpri); + + numpulses = dfs_bin_pri_check(dfs, rf, dl, score[scoreindex], refpri, + refdur, ext_chan_flag, refpri); + + fil_thresh = dfs_get_filter_threshold(dfs, rf, ext_chan_flag); + + if (numpulses >= fil_thresh) { + found = 1; + dfs_bin_success_print(dfs, rf, ext_chan_flag, numpulses, + refpri, refdur, primargin); } return found; } -void count_the_other_delay_elements(struct wlan_dfs *dfs, +/** + * dfs_check_pulses_for_delta_variance() - Check pulses for delta variance. + * @rf: Pointer to dfs_filter structure. + * @numpulsetochk: Number of pulses to check. + * @delta_time_stamps: Delta time stamp. + * @fundamentalpri: Highest PRI. + * @primargin: Primary margin. + * @numpulses: Number of pulses. + */ +static inline void dfs_check_pulses_for_delta_variance( + struct dfs_filter *rf, + int numpulsetochk, + uint32_t delta_time_stamps, + int fundamentalpri, + uint32_t primargin, + int *numpulses) +{ + uint32_t delta_ts_variance, j; + + for (j = 0; j < numpulsetochk; j++) { + delta_ts_variance = DFS_DIFF(delta_time_stamps, + ((j + 1) * fundamentalpri)); + if (delta_ts_variance < (2 * (j + 1) * primargin)) { + (*numpulses)++; + if (rf->rf_ignore_pri_window > 0) + break; + } + } +} + +/** + * dfs_count_the_other_delay_elements() - Counts the ther delay elements. + * @dfs: Pointer to wlan_dfs structure. + * @rf: Pointer to dfs_filter structure. + * @dl: Pointer to dfs_delayline structure. + * @i: Index value. + * @refpri: Current "filter" time for start of pulse in usecs. + * @refdur: Duration value. + * @primargin: Primary margin. + * @durmargin: Duration margin. + * @numpulses: Number of pulses. + * @prev_good_timestamp: Previous good timestamp. + * @fundamentalpri: Highest PRI. + */ +static void dfs_count_the_other_delay_elements( + struct wlan_dfs *dfs, struct dfs_filter *rf, struct dfs_delayline *dl, uint32_t i, @@ -322,12 +725,11 @@ void count_the_other_delay_elements(struct wlan_dfs *dfs, uint32_t durmargin, int *numpulses, uint32_t *prev_good_timestamp, - int fundamentalpri - ) + int fundamentalpri) { int delayindex; uint32_t searchpri, searchdur, deltadur, deltapri1, deltapri2; - uint32_t j = 0, delta_time_stamps, delta_ts_variance, deltapri; + uint32_t j = 0, delta_time_stamps, deltapri; int dindex, primatch, numpulsetochk = 2; delayindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; @@ -348,21 +750,16 @@ void count_the_other_delay_elements(struct wlan_dfs *dfs, deltapri2 = DFS_DIFF(searchpri, 2 * refpri); primatch = 0; - if ((rf->rf_ignore_pri_window > 0) && - (rf->rf_patterntype != 2)) { + if ((rf->rf_ignore_pri_window > 0) && (rf->rf_patterntype != 2)) { for (j = 0; j < rf->rf_numpulses; j++) { - deltapri1 = DFS_DIFF(searchpri, - (j + 1) * refpri); + deltapri1 = DFS_DIFF(searchpri, (j + 1) * refpri); if (deltapri1 < (2 * primargin)) { primatch = 1; break; } } - } else { - if ((deltapri1 < primargin) || - (deltapri2 < primargin)) { - primatch = 1; - } + } else if ((deltapri1 < primargin) || (deltapri2 < primargin)) { + primatch = 1; } if (primatch && (deltadur < durmargin)) { @@ -380,16 +777,10 @@ void count_the_other_delay_elements(struct wlan_dfs *dfs, } else { numpulsetochk = 4; } - for (j = 0; j < numpulsetochk; j++) { - delta_ts_variance = DFS_DIFF(delta_time_stamps, - ((j + 1) * fundamentalpri)); - if (delta_ts_variance < - (2 * (j + 1) * primargin)) { - (*numpulses)++; - if (rf->rf_ignore_pri_window > 0) - break; - } - } + + dfs_check_pulses_for_delta_variance(rf, numpulsetochk, + delta_time_stamps, fundamentalpri, + primargin, numpulses); } *prev_good_timestamp = dl->dl_elems[delayindex].de_ts; @@ -400,7 +791,8 @@ void count_the_other_delay_elements(struct wlan_dfs *dfs, } } -int dfs_bin_pri_check(struct wlan_dfs *dfs, +int dfs_bin_pri_check( + struct wlan_dfs *dfs, struct dfs_filter *rf, struct dfs_delayline *dl, uint32_t score, @@ -433,10 +825,7 @@ int dfs_bin_pri_check(struct wlan_dfs *dfs, return numpulses; } - if (rf->rf_maxdur < 10) - durmargin = 4; - else - durmargin = 6; + dfs_get_durmargin(rf, &durmargin); if ((!rf->rf_fixed_pri_radar_pulse)) { if (rf->rf_ignore_pri_window == 1) @@ -481,9 +870,9 @@ int dfs_bin_pri_check(struct wlan_dfs *dfs, * in the acceptable range from the reference one. */ for (i = 0; i < dl->dl_numelems; i++) - count_the_other_delay_elements(dfs, rf, dl, i, refpri, refdur, - primargin, durmargin, &numpulses, &prev_good_timestamp, - fundamentalpri); + dfs_count_the_other_delay_elements(dfs, rf, dl, i, refpri, + refdur, primargin, durmargin, &numpulses, + &prev_good_timestamp, fundamentalpri); return numpulses; } diff --git a/umac/dfs/core/src/filtering/dfs_debug.c b/umac/dfs/core/src/filtering/dfs_debug.c index 32318ce04c..651195770a 100644 --- a/umac/dfs/core/src/filtering/dfs_debug.c +++ b/umac/dfs/core/src/filtering/dfs_debug.c @@ -44,11 +44,33 @@ void dfs_print_filter(struct wlan_dfs *dfs, struct dfs_filter *rf) rf->rf_maxdur); } +/** + * dfs_print_filtertype() - Print the filtertype + * @dfs: Pointer to wlan_dfs structure. + * @ft: Pointer to dfs_filtertype structure. + */ +static void dfs_print_filtertype( + struct wlan_dfs *dfs, + struct dfs_filtertype *ft) +{ + uint32_t j; + struct dfs_filter *rf; + + for (j = 0; j < ft->ft_numfilters; j++) { + rf = &(ft->ft_filters[j]); + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n", + j, rf->rf_pulseid, rf->rf_numpulses, + rf->rf_minpri, rf->rf_maxpri, + rf->rf_threshold, rf->rf_filterlen, + rf->rf_mindur, rf->rf_maxdur); + } +} + void dfs_print_filters(struct wlan_dfs *dfs) { struct dfs_filtertype *ft = NULL; - struct dfs_filter *rf; - int i, j; + uint8_t i; if (dfs == NULL) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, @@ -64,21 +86,9 @@ void dfs_print_filters(struct wlan_dfs *dfs) continue; } DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "===========ft->ft_numfilters = %u===========\n", - ft->ft_numfilters); - for (j = 0; j < ft->ft_numfilters; j++) { - rf = &(ft->ft_filters[j]); - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n", - j, rf->rf_pulseid, - rf->rf_numpulses, - rf->rf_minpri, - rf->rf_maxpri, - rf->rf_threshold, - rf->rf_filterlen, - rf->rf_mindur, - rf->rf_maxdur); - } + "===========ft->ft_numfilters = %u===========\n", + ft->ft_numfilters); + dfs_print_filtertype(dfs, ft); } } } diff --git a/umac/dfs/core/src/filtering/dfs_fcc_bin5.c b/umac/dfs/core/src/filtering/dfs_fcc_bin5.c index e233afc25f..27844fe04b 100644 --- a/umac/dfs/core/src/filtering/dfs_fcc_bin5.c +++ b/umac/dfs/core/src/filtering/dfs_fcc_bin5.c @@ -127,17 +127,70 @@ int dfs_bin5_addpulse(struct wlan_dfs *dfs, return 1; } +/** + * dfs_calculate_bursts_for_same_rssi() - Calculate bursts for same rssi. + * @dfs: Pointer to wlan_dfs structure. + * @br: Pointer to dfs_bin5radars structure. + * @bursts: Bursts. + * @numevents: Number of events. + * @prev: prev index. + * @this: index to br_elems[]. + * @index: index array. + */ +static inline void dfs_calculate_bursts_for_same_rssi( + struct wlan_dfs *dfs, + struct dfs_bin5radars *br, + uint32_t *bursts, + uint32_t *numevents, + uint32_t prev, + uint32_t this, + int *index) +{ + uint32_t rssi_diff; + + if (br->br_elems[this].be_rssi >= br->br_elems[prev].be_rssi) + rssi_diff = (br->br_elems[this].be_rssi - + br->br_elems[prev].be_rssi); + else + rssi_diff = (br->br_elems[prev].be_rssi - + br->br_elems[this].be_rssi); + + if (rssi_diff <= DFS_BIN5_RSSI_MARGIN) { + (*bursts)++; + /* + * Save the indexes of this pair for later + * width variance check. + */ + if ((*numevents) >= 2) { + /* + * Make sure the event is not duplicated, possible in + * a 3 pulse burst. + */ + if (index[(*numevents)-1] != prev) + index[(*numevents)++] = prev; + } else { + index[(*numevents)++] = prev; + } + + index[(*numevents)++] = this; + } else { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_BIN5, + "%s %d Bin5 rssi_diff=%d\n", + __func__, __LINE__, rssi_diff); + } +} + void bin5_rules_check_internal(struct wlan_dfs *dfs, struct dfs_bin5radars *br, uint32_t *bursts, uint32_t *numevents, uint32_t prev, uint32_t i, - uint32_t this) + uint32_t this, + int *index) { uint64_t pri = 0; - uint32_t width_diff = 0, rssi_diff = 0; - int index[DFS_MAX_B5_SIZE]; + uint32_t width_diff = 0; /* Rule 1: 1000 <= PRI <= 2000 + some margin. */ if (br->br_elems[this].be_ts >= br->br_elems[prev].be_ts) { @@ -168,42 +221,15 @@ void bin5_rules_check_internal(struct wlan_dfs *dfs, width_diff = (br->br_elems[prev].be_dur - br->br_elems[this].be_dur); } - if (width_diff <= DFS_BIN5_WIDTH_MARGIN) { + + if (width_diff <= DFS_BIN5_WIDTH_MARGIN) /* * Rule 3: RSSI of the pulses in the * burst should be same (+/- margin) */ - if (br->br_elems[this].be_rssi >= - br->br_elems[prev].be_rssi) { - rssi_diff = (br->br_elems[this].be_rssi - - br->br_elems[prev].be_rssi); - } else { - rssi_diff = (br->br_elems[prev].be_rssi - - br->br_elems[this].be_rssi); - } - if (rssi_diff <= DFS_BIN5_RSSI_MARGIN) { - (*bursts)++; - /* - * Save the indexes of this pair for later - * width variance check. - */ - if ((*numevents) >= 2) { - /* - * Make sure the event is not - * duplicated, possible in a 3 pulse - * burst. - */ - if (index[(*numevents)-1] != prev) - index[(*numevents)++] = prev; - } else - index[(*numevents)++] = prev; - - index[(*numevents)++] = this; - } else - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_BIN5, - "%s %d Bin5 rssi_diff=%d\n", - __func__, __LINE__, rssi_diff); - } else + dfs_calculate_bursts_for_same_rssi(dfs, br, bursts, + numevents, prev, this, index); + else DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_BIN5, "%s %d Bin5 width_diff=%d\n", __func__, __LINE__, width_diff); @@ -224,6 +250,7 @@ int dfs_bin5_check(struct wlan_dfs *dfs) uint32_t n = 0, i = 0, i1 = 0, this = 0, prev = 0; uint32_t bursts = 0, total_diff = 0, average_diff = 0; uint32_t total_width = 0, average_width = 0, numevents = 0; + int index[DFS_MAX_B5_SIZE]; if (dfs == NULL) { DFS_PRINTK("%s: dfs is NULL\n", __func__); @@ -258,7 +285,7 @@ int dfs_bin5_check(struct wlan_dfs *dfs) continue; } bin5_rules_check_internal(dfs, br, &bursts, &numevents, - prev, i, this); + prev, i, this, index); prev = this; } @@ -272,12 +299,9 @@ int dfs_bin5_check(struct wlan_dfs *dfs) DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_BIN5, "bursts=%u numevents=%u total_width=%d average_width=%d total_diff=%d average_diff=%d\n", - bursts, numevents, - total_width, average_width, + bursts, numevents, total_width, average_width, total_diff, average_diff); - DFS_PRINTK( - "bin 5 radar detected, bursts=%d\n", - bursts); + DFS_PRINTK("bin 5 radar detected, bursts=%d\n", bursts); return 1; } } diff --git a/umac/dfs/core/src/filtering/dfs_init.c b/umac/dfs/core/src/filtering/dfs_init.c index 193dbc04cc..0ba51b064f 100644 --- a/umac/dfs/core/src/filtering/dfs_init.c +++ b/umac/dfs/core/src/filtering/dfs_init.c @@ -23,13 +23,32 @@ #include "../dfs.h" #include "wlan_dfs_lmac_api.h" +/** + * dfs_reset_filtertype() - Reset filtertype. + * @ft: Pointer to dfs_filtertype structure. + */ +static inline void dfs_reset_filtertype( + struct dfs_filtertype *ft) +{ + int j; + struct dfs_filter *rf; + struct dfs_delayline *dl; + + for (j = 0; j < ft->ft_numfilters; j++) { + rf = &(ft->ft_filters[j]); + dl = &(rf->rf_dl); + if (dl != NULL) { + qdf_mem_zero(dl, sizeof(*dl)); + dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK; + } + } +} + void dfs_reset_alldelaylines(struct wlan_dfs *dfs) { struct dfs_filtertype *ft = NULL; - struct dfs_filter *rf; - struct dfs_delayline *dl; struct dfs_pulseline *pl; - int i, j; + int i; if (dfs == NULL) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, @@ -57,16 +76,7 @@ void dfs_reset_alldelaylines(struct wlan_dfs *dfs) for (i = 0; i < DFS_MAX_RADAR_TYPES; i++) { if (dfs->dfs_radarf[i] != NULL) { ft = dfs->dfs_radarf[i]; - for (j = 0; j < ft->ft_numfilters; j++) { - rf = &(ft->ft_filters[j]); - dl = &(rf->rf_dl); - if (dl != NULL) { - qdf_mem_zero(dl, - sizeof(struct dfs_delayline)); - dl->dl_lastelem = - (0xFFFFFFFF) & DFS_MAX_DL_MASK; - } - } + dfs_reset_filtertype(ft); } } @@ -119,6 +129,93 @@ void dfs_reset_radarq(struct wlan_dfs *dfs) WLAN_DFSQ_UNLOCK(dfs); } +/** + * dfs_fill_ft_index_table() - DFS fill ft index table. + * @dfs: Pointer to wlan_dfs structure. + * @i: Duration used as an index. + * + * Return: 1 if too many overlapping radar filters else 0. + */ +static inline bool dfs_fill_ft_index_table( + struct wlan_dfs *dfs, + int i) +{ + uint32_t stop = 0, tableindex = 0; + + while ((tableindex < DFS_MAX_RADAR_OVERLAP) && (!stop)) { + if ((dfs->dfs_ftindextable[i])[tableindex] == -1) + stop = 1; + else + tableindex++; + } + + if (stop) { + (dfs->dfs_ftindextable[i])[tableindex] = + (int8_t)(dfs->dfs_rinfo.rn_ftindex); + } else { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, + "%s: Too many overlapping radar filters\n", + __func__); + return 1; + } + + return 0; +} + +/** + * dfs_fill_filter_type() - DFS fill filter type. + * @dfs: Pointer to wlan_dfs structure. + * @ft: Double pointer to dfs_filtertype structure. + * @dfs_radars: Pointer to dfs_pulse structure. + * @min_rssithresh: Minimum RSSI threshold. + * @max_pulsedur: Maximum RSSI threshold. + * @p: Index to dfs_pulse structure. + * + * Return: 1 if too many overlapping radar filters else 0. + */ +static inline bool dfs_fill_filter_type( + struct wlan_dfs *dfs, + struct dfs_filtertype **ft, + struct dfs_pulse *dfs_radars, + int32_t *min_rssithresh, + uint32_t *max_pulsedur, + int p) +{ + int i; + + /* No filter of the appropriate dur was found. */ + if ((dfs->dfs_rinfo.rn_ftindex + 1) > DFS_MAX_RADAR_TYPES) { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, + "%s: Too many filter types\n", __func__); + return 1; + } + (*ft) = dfs->dfs_radarf[dfs->dfs_rinfo.rn_ftindex]; + (*ft)->ft_numfilters = 0; + (*ft)->ft_numpulses = dfs_radars[p].rp_numpulses; + (*ft)->ft_patterntype = dfs_radars[p].rp_patterntype; + (*ft)->ft_mindur = dfs_radars[p].rp_mindur; + (*ft)->ft_maxdur = dfs_radars[p].rp_maxdur; + (*ft)->ft_filterdur = dfs_radars[p].rp_pulsedur; + (*ft)->ft_rssithresh = dfs_radars[p].rp_rssithresh; + (*ft)->ft_rssimargin = dfs_radars[p].rp_rssimargin; + (*ft)->ft_minpri = 1000000; + + if ((*ft)->ft_rssithresh < *min_rssithresh) + *min_rssithresh = (*ft)->ft_rssithresh; + + if ((*ft)->ft_maxdur > *max_pulsedur) + *max_pulsedur = (*ft)->ft_maxdur; + + for (i = (*ft)->ft_mindur; i <= (*ft)->ft_maxdur; i++) { + if (dfs_fill_ft_index_table(dfs, i)) + return 1; + } + + dfs->dfs_rinfo.rn_ftindex++; + + return 0; +} + int dfs_init_radar_filters(struct wlan_dfs *dfs, struct wlan_dfs_radar_tab_info *radar_info) { @@ -131,6 +228,7 @@ int dfs_init_radar_filters(struct wlan_dfs *dfs, uint32_t max_pulsedur = 0; int numpulses, p, n, i; int numradars = 0, numb5radars = 0; + int retval; if (dfs == NULL) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "dfs is NULL %s", __func__); @@ -167,17 +265,17 @@ int dfs_init_radar_filters(struct wlan_dfs *dfs, dfs->dfs_defaultparams = radar_info->dfs_defaultparams; dfs->wlan_dfs_isdfsregdomain = 1; - dfs->dfs_rinfo.rn_numradars = 0; + dfs->dfs_rinfo.rn_ftindex = 0; /* Clear filter type table. */ for (n = 0; n < 256; n++) { for (i = 0; i < DFS_MAX_RADAR_OVERLAP; i++) - (dfs->dfs_radartable[n])[i] = -1; + (dfs->dfs_ftindextable[n])[i] = -1; } /* Now, initialize the radar filters. */ for (p = 0; p < numradars; p++) { ft = NULL; - for (n = 0; n < dfs->dfs_rinfo.rn_numradars; n++) { + for (n = 0; n < dfs->dfs_rinfo.rn_ftindex; n++) { if ((dfs_radars[p].rp_pulsedur == dfs->dfs_radarf[n]->ft_filterdur) && (dfs_radars[p].rp_numpulses == @@ -190,57 +288,14 @@ int dfs_init_radar_filters(struct wlan_dfs *dfs, break; } } + if (ft == NULL) { - /* No filter of the appropriate dur was found. */ - if ((dfs->dfs_rinfo.rn_numradars + 1) > - DFS_MAX_RADAR_TYPES) { - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, - "%s: Too many filter types\n", - __func__); + retval = dfs_fill_filter_type(dfs, &ft, dfs_radars, + &min_rssithresh, &max_pulsedur, p); + if (retval == 1) goto bad4; - } - ft = dfs->dfs_radarf[dfs->dfs_rinfo.rn_numradars]; - ft->ft_numfilters = 0; - ft->ft_numpulses = dfs_radars[p].rp_numpulses; - ft->ft_patterntype = dfs_radars[p].rp_patterntype; - ft->ft_mindur = dfs_radars[p].rp_mindur; - ft->ft_maxdur = dfs_radars[p].rp_maxdur; - ft->ft_filterdur = dfs_radars[p].rp_pulsedur; - ft->ft_rssithresh = dfs_radars[p].rp_rssithresh; - ft->ft_rssimargin = dfs_radars[p].rp_rssimargin; - ft->ft_minpri = 1000000; - - if (ft->ft_rssithresh < min_rssithresh) - min_rssithresh = ft->ft_rssithresh; - - if (ft->ft_maxdur > max_pulsedur) - max_pulsedur = ft->ft_maxdur; - - for (i = ft->ft_mindur; i <= ft->ft_maxdur; i++) { - uint32_t stop = 0, tableindex = 0; - - while ((tableindex < DFS_MAX_RADAR_OVERLAP) && - (!stop)) { - if ((dfs->dfs_radartable[i])[tableindex] - == -1) - stop = 1; - else - tableindex++; - } - - if (stop) { - (dfs->dfs_radartable[i])[tableindex] = - (int8_t) - (dfs->dfs_rinfo.rn_numradars); - } else { - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, - "%s: Too many overlapping radar filters\n", - __func__); - goto bad4; - } - } - dfs->dfs_rinfo.rn_numradars++; } + rf = &(ft->ft_filters[ft->ft_numfilters++]); dfs_reset_delayline(&rf->rf_dl); numpulses = dfs_radars[p].rp_numpulses; @@ -254,21 +309,19 @@ int dfs_init_radar_filters(struct wlan_dfs *dfs, rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window; T = (100000000 / dfs_radars[p].rp_max_pulsefreq) - 100 * (dfs_radars[p].rp_meanoffset); - rf->rf_minpri = - dfs_round((int32_t)T - - (100 * (dfs_radars[p].rp_pulsevar))); + rf->rf_minpri = dfs_round((int32_t)T - + (100 * (dfs_radars[p].rp_pulsevar))); Tmax = (100000000 / dfs_radars[p].rp_pulsefreq) - 100 * (dfs_radars[p].rp_meanoffset); - rf->rf_maxpri = - dfs_round((int32_t)Tmax + - (100 * (dfs_radars[p].rp_pulsevar))); + rf->rf_maxpri = dfs_round((int32_t)Tmax + + (100 * (dfs_radars[p].rp_pulsevar))); if (rf->rf_minpri < ft->ft_minpri) ft->ft_minpri = rf->rf_minpri; - rf->rf_fixed_pri_radar_pulse = - (dfs_radars[p].rp_max_pulsefreq == - dfs_radars[p].rp_pulsefreq) ? 1 : 0; + rf->rf_fixed_pri_radar_pulse = ( + dfs_radars[p].rp_max_pulsefreq == + dfs_radars[p].rp_pulsefreq) ? 1 : 0; rf->rf_threshold = dfs_radars[p].rp_threshold; rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses; @@ -307,10 +360,8 @@ int dfs_init_radar_filters(struct wlan_dfs *dfs, min_rssithresh = dfs->dfs_b5radars[n].br_pulse.b5_rssithresh; - if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur - > max_pulsedur) - max_pulsedur = - dfs->dfs_b5radars[n].br_pulse.b5_maxdur; + if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur) + max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur; } dfs_reset_alldelaylines(dfs); dfs_reset_radarq(dfs); @@ -325,15 +376,12 @@ int dfs_init_radar_filters(struct wlan_dfs *dfs, * Relax the max pulse duration a little bit due to inaccuracy * caused by chirping. */ - dfs->dfs_rinfo.rn_maxpulsedur = - dfs->dfs_rinfo.rn_maxpulsedur + 20; + dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur + 20; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, - "DFS min filter rssiThresh = %d\n", + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "DFS min filter rssiThresh = %d\n", min_rssithresh); - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, - "DFS max pulse dur = %d ticks\n", + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "DFS max pulse dur = %d ticks\n", dfs->dfs_rinfo.rn_maxpulsedur); return 0; diff --git a/umac/dfs/core/src/filtering/dfs_misc.c b/umac/dfs/core/src/filtering/dfs_misc.c index e71053f4e6..a48d384bfc 100644 --- a/umac/dfs/core/src/filtering/dfs_misc.c +++ b/umac/dfs/core/src/filtering/dfs_misc.c @@ -71,6 +71,30 @@ static int dfs_adjust_thresh_per_chan_busy(int ext_chan_busy, int thresh) return adjust_thresh; } +/** + * dfs_get_cached_ext_chan_busy() - Get cached ext chan busy. + * @dfs: Pointer to wlan_dfs structure. + * @ext_chan_busy: Extension channel PRI. + */ +static inline void dfs_get_cached_ext_chan_busy( + struct wlan_dfs *dfs, + int *ext_chan_busy) +{ + *ext_chan_busy = 0; + /* Check to see if the cached value of ext_chan_busy can be used. */ + + if (dfs->dfs_rinfo.dfs_ext_chan_busy && + (dfs->dfs_rinfo.rn_lastfull_ts < + dfs->dfs_rinfo.ext_chan_busy_ts)) { + *ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "Use cached copy of ext_chan_busy extchanbusy=%d rn_lastfull_ts=%llu ext_chan_busy_ts=%llu\n", + *ext_chan_busy, + (uint64_t)dfs->dfs_rinfo.rn_lastfull_ts, + (uint64_t)dfs->dfs_rinfo.ext_chan_busy_ts); + } +} + int dfs_get_pri_margin(struct wlan_dfs *dfs, int is_extchan_detect, int is_fixed_pattern) @@ -90,21 +114,7 @@ int dfs_get_pri_margin(struct wlan_dfs *dfs, lmac_get_tsf64(dfs->dfs_pdev_obj); dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; } else { - /* - * Check to see if the cached value of ext_chan_busy - * can be used. - */ - ext_chan_busy = 0; - if (dfs->dfs_rinfo.dfs_ext_chan_busy) { - if (dfs->dfs_rinfo.rn_lastfull_ts < - dfs->dfs_rinfo.ext_chan_busy_ts) { - ext_chan_busy = - dfs->dfs_rinfo.dfs_ext_chan_busy; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "PRI Use cached copy of ext_chan_busy extchanbusy=%d\n", - ext_chan_busy); - } - } + dfs_get_cached_ext_chan_busy(dfs, &ext_chan_busy); } adjust_pri = dfs_adjust_pri_per_chan_busy(ext_chan_busy, pri_margin); @@ -130,26 +140,7 @@ int dfs_get_filter_threshold(struct wlan_dfs *dfs, lmac_get_tsf64(dfs->dfs_pdev_obj); dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; } else { - /* - * Check to see if the cached value of ext_chan_busy - * can be used. - */ - ext_chan_busy = 0; - if (dfs->dfs_rinfo.dfs_ext_chan_busy) { - if (dfs->dfs_rinfo.rn_lastfull_ts < - dfs->dfs_rinfo.ext_chan_busy_ts) { - ext_chan_busy = - dfs->dfs_rinfo.dfs_ext_chan_busy; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "THRESH Use cached copy of ext_chan_busy extchanbusy=%d rn_lastfull_ts=%llu ext_chan_busy_ts=%llu\n", - ext_chan_busy, - (uint64_t) - dfs->dfs_rinfo.rn_lastfull_ts, - (uint64_t) - dfs->dfs_rinfo.ext_chan_busy_ts - ); - } - } + dfs_get_cached_ext_chan_busy(dfs, &ext_chan_busy); } adjust_thresh = diff --git a/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c b/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c index 94b3c12310..2b78aaeb9b 100644 --- a/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c +++ b/umac/dfs/core/src/filtering/dfs_phyerr_tlv.c @@ -255,6 +255,52 @@ static void dfs_radar_fft_search_report_parse(struct wlan_dfs *dfs, } } +/** + * dfs_check_for_false_detection() - Check for possible false detection on + * beeliner this may also work for Cascade but parameters + * (e.g. AGC_MB_GAIN_THRESH1) may be different for Cascade. + * @dfs: pointer to wlan_dfs structure. + * @rs: pointer to rx_radar_status structure. + * @false_detect: Pointer to save false detect value. + * @rssi: RSSI. + */ +static inline void dfs_check_for_false_detection( + struct wlan_dfs *dfs, + struct rx_radar_status *rs, + bool *false_detect, + uint8_t rssi) +{ + bool is_ht160 = false; + bool is_false_detect = false; + + is_ht160 = dfs->dfs_caps.wlan_chip_is_ht160; + is_false_detect = dfs->dfs_caps.wlan_chip_is_false_detect; + + if ((dfs->dfs_caps.wlan_chip_is_over_sampled == 0) && + (is_ht160 == 0 && is_false_detect)) { + if ((rs->agc_mb_gain > AGC_MB_GAIN_THRESH1) && + ((rs->agc_total_gain - rs->agc_mb_gain) < + AGC_OTHER_GAIN_THRESH1)) { + *false_detect = true; + } + + if ((rs->agc_mb_gain > AGC_MB_GAIN_THRESH2) && + ((rs->agc_total_gain - rs->agc_mb_gain) > + AGC_OTHER_GAIN_THRESH2) && + (rssi > AGC_GAIN_RSSI_THRESH)) { + *false_detect = true; + } + } + + if (*false_detect) + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, + "%s: setting false_detect to TRUE because of mb/total_gain/rssi, agc_mb_gain=%d, agc_total_gain=%d, rssi=%d\n", + __func__, + rs->agc_mb_gain, + rs->agc_total_gain, + rssi); +} + /** * dfs_tlv_parse_frame () - Parse a Peregrine BB TLV frame. * @dfs: pointer to wlan_dfs structure. @@ -282,8 +328,6 @@ static int dfs_tlv_parse_frame(struct wlan_dfs *dfs, uint32_t tlv_hdr[1]; bool first_tlv = true; bool false_detect = false; - bool is_ht160 = false; - bool is_false_detect = false; DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, "%s: total length = %zu bytes\n", @@ -335,47 +379,8 @@ static int dfs_tlv_parse_frame(struct wlan_dfs *dfs, dfs_radar_summary_parse(dfs, buf + i, MS(tlv_hdr[TLV_REG], TLV_LEN), rs); - /* - * Check for possible false detection on - * beeliner this may also work for Cascade but - * parameters (e.g. AGC_MB_GAIN_THRESH1) may - * be different for Cascade. - */ - is_ht160 = dfs->dfs_caps.wlan_chip_is_ht160; - is_false_detect = - dfs->dfs_caps.wlan_chip_is_false_detect; - - if ((dfs->dfs_caps.wlan_chip_is_over_sampled == 0) && - (is_ht160 == 0 && is_false_detect) - ) { - if ((rs->agc_mb_gain > AGC_MB_GAIN_THRESH1) && - ((rs->agc_total_gain - rs->agc_mb_gain) - < AGC_OTHER_GAIN_THRESH1)) { - false_detect = true; - DFS_DPRINTK(dfs, - WLAN_DEBUG_DFS_PHYERR, - "%s: setting false_detect to TRUE because of mb/total_gain, agc_mb_gain=%d, agc_total_gain=%d, rssi=%d\n", - __func__, - rs->agc_mb_gain, - rs->agc_total_gain, - rssi); - } - - if ((rs->agc_mb_gain > AGC_MB_GAIN_THRESH2) && - ((rs->agc_total_gain - rs->agc_mb_gain) - > AGC_OTHER_GAIN_THRESH2) && - (rssi > AGC_GAIN_RSSI_THRESH) - ) { - false_detect = true; - DFS_DPRINTK(dfs, - WLAN_DEBUG_DFS_PHYERR, - "%s: setting false_detect to TRUE because of mb/total_gain/rssi, agc_mb_gain=%d, agc_total_gain=%d, rssi=%d\n", - __func__, - rs->agc_mb_gain, - rs->agc_total_gain, - rssi); - } - } + dfs_check_for_false_detection(dfs, rs, &false_detect, + rssi); break; case TAG_ID_SEARCH_FFT_REPORT: dfs_radar_fft_search_report_parse(dfs, buf + i, @@ -722,33 +727,20 @@ int dfs_process_phyerr_bb_tlv(struct wlan_dfs *dfs, DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR_SUM, "%s: fbin=%d, freq=%d.%d MHz, raw tsf=%u, offset=%d, cooked tsf=%u, rssi=%d, dur=%d, is_chirp=%d, fulltsf=%llu, freq=%d.%d MHz, freq_lo=%d.%dMHz, freq_hi=%d.%d MHz\n", - __func__, rs.sidx, - (int) (rs.freq_offset / 1000), - (int) abs(rs.freq_offset % 1000), - rs.raw_tsf, rs.tsf_offset, - e->rs_tstamp, rs.rssi, - rs.pulse_duration, - (int)rs.is_chirp, - (unsigned long long) fulltsf, - (int)e->freq / 1000, - (int) abs(e->freq) % 1000, - (int)e->freq_lo / 1000, - (int) abs(e->freq_lo) % 1000, - (int)e->freq_hi / 1000, + __func__, rs.sidx, (int) (rs.freq_offset / 1000), + (int) abs(rs.freq_offset % 1000), rs.raw_tsf, rs.tsf_offset, + e->rs_tstamp, rs.rssi, rs.pulse_duration, (int)rs.is_chirp, + (unsigned long long) fulltsf, (int)e->freq / 1000, + (int) abs(e->freq) % 1000, (int)e->freq_lo / 1000, + (int) abs(e->freq_lo) % 1000, (int)e->freq_hi / 1000, (int) abs(e->freq_hi) % 1000); DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_FALSE_DET, "ts=%u, dur=%d, rssi=%d, freq_offset=%d.%dMHz, is_chirp=%d, seg_id=%d, peak_mag=%d, total_gain=%d, mb_gain=%d, relpwr_db=%d\n", - e->rs_tstamp, - rs.pulse_duration, - rs.rssi, + e->rs_tstamp, rs.pulse_duration, rs.rssi, (int)e->freq_offset_khz / 1000, - (int)abs(e->freq_offset_khz) % 1000, - (int)rs.is_chirp, - rsfr.seg_id, - rsfr.peak_mag, - rs.agc_total_gain, - rs.agc_mb_gain, + (int)abs(e->freq_offset_khz) % 1000, (int)rs.is_chirp, + rsfr.seg_id, rsfr.peak_mag, rs.agc_total_gain, rs.agc_mb_gain, rsfr.relpwr_db); return 1; diff --git a/umac/dfs/core/src/filtering/dfs_process_phyerr.c b/umac/dfs/core/src/filtering/dfs_process_phyerr.c index feb2d2876f..793fa8a936 100644 --- a/umac/dfs/core/src/filtering/dfs_process_phyerr.c +++ b/umac/dfs/core/src/filtering/dfs_process_phyerr.c @@ -162,11 +162,7 @@ int dfs_process_phyerr_owl(struct wlan_dfs *dfs, DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR_SUM, "%s: rssi=%u dur=%u, freq=%d MHz, freq_lo=%d MHz, freq_hi=%d MHz\n", - __func__, - rssi, - dur, - e->freq/1000, - e->freq_lo/1000, + __func__, rssi, dur, e->freq/1000, e->freq_lo/1000, e->freq_hi / 1000); return 1; @@ -266,8 +262,7 @@ int dfs_process_phyerr_sowl(struct wlan_dfs *dfs, if (!pulse_bw_info) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, "ERROR channel dur=%u rssi=%u pulse_bw_info=0x%x datalen MOD 4 = %d\n", - dur, rssi, pulse_bw_info, - (datalen & 0x3)); + dur, rssi, pulse_bw_info, (datalen & 0x3)); /* * Bogus bandwidth info received in descriptor, so * ignore this PHY error. @@ -305,15 +300,8 @@ int dfs_process_phyerr_sowl(struct wlan_dfs *dfs, DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR_SUM, "%s: pulse_bw_info=0x%x pulse_length_ext=%u pulse_length_pri=%u rssi=%u ext_rssi=%u, freq=%d MHz, freq_lo=%d MHz, freq_hi=%d MHz\n", - __func__, - pulse_bw_info, - pulse_length_ext, - pulse_length_pri, - rssi, - ext_rssi, - e->freq/1000, - e->freq_lo/1000, - e->freq_hi/1000); + __func__, pulse_bw_info, pulse_length_ext, pulse_length_pri, + rssi, ext_rssi, e->freq/1000, e->freq_lo/1000, e->freq_hi/1000); #undef EXT_CH_RADAR_FOUND #undef PRI_CH_RADAR_FOUND #undef EXT_CH_RADAR_EARLY_FOUND @@ -354,8 +342,7 @@ int dfs_process_phyerr_merlin(struct wlan_dfs *dfs, case 0x01: /* Radar in ctrl channel */ DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, - "RAW RSSI: rssi=%u ext_rssi=%u\n", - rssi, ext_rssi); + "RAW RSSI: rssi=%u ext_rssi=%u\n", rssi, ext_rssi); if (ext_rssi >= (rssi + 3)) { /* * Cannot use ctrl channel RSSI if extension channel is @@ -367,8 +354,7 @@ int dfs_process_phyerr_merlin(struct wlan_dfs *dfs, case 0x02: /* Radar in extension channel */ DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, - "RAW RSSI: rssi=%u ext_rssi=%u\n", - rssi, ext_rssi); + "RAW RSSI: rssi=%u ext_rssi=%u\n", rssi, ext_rssi); if (rssi >= (ext_rssi + 12)) { /* * Cannot use extension channel RSSI if control channel @@ -435,6 +421,111 @@ static void dfs_dump_phyerr_contents(const char *d, int len) DFS_PRINTK("%s: %s\n", __func__, buf); } +/** + * dfs_bump_up_bin5_pulse_dur() - Bump up to a random BIN 5 pulse duration. + * @dfs: Pointer to wlan_dfs structure. + * @e: Pointer to dfs_phy_err structure. + * @slope: Slope value. + */ +static inline void dfs_bump_up_bin5_pulse_dur( + struct wlan_dfs *dfs, + struct dfs_phy_err *e, + int slope) +{ + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, "old dur %d slope =%d\n", + e->dur, slope); + + e->is_sw_chirp = 1; + /* bump up to a random bin5 pulse duration */ + if (e->dur < MIN_BIN5_DUR) + e->dur = dfs_get_random_bin5_dur(dfs, e->fulltsf); + + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, "new dur %d\n", e->dur); +} + +/** + * dfs_filter_short_pulses() - Filter short pulses. + * @dfs: Pointer to wlan_dfs structure. + * @e: Pointer to dfs_phy_err structure. + * @retval: Return value + * + * Rssi is not accurate for short pulses, so donot filter based on that for + * short duration pulses. + */ +static inline void dfs_filter_short_pulses( + struct wlan_dfs *dfs, + struct dfs_phy_err *e, + int *retval) +{ + if (dfs->dfs_caps.wlan_dfs_ext_chan_ok) { + if ((e->rssi < dfs->dfs_rinfo.rn_minrssithresh && + (e->dur > MAX_DUR_FOR_LOW_RSSI)) || + e->dur > (dfs->dfs_rinfo.rn_maxpulsedur)) { + dfs->wlan_dfs_stats.rssi_discards++; + *retval = 1; + } + } else if (e->rssi < dfs->dfs_rinfo.rn_minrssithresh || + e->dur > dfs->dfs_rinfo.rn_maxpulsedur) { + dfs->wlan_dfs_stats.rssi_discards++; + *retval = 1; + } + + if (*retval) { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, + "%s pulse is discarded: dur=%d, maxpulsedur=%d, rssi=%d, minrssi=%d\n", + (dfs->dfs_caps.wlan_dfs_ext_chan_ok) ? + "Extension channel" : "", + e->dur, dfs->dfs_rinfo.rn_maxpulsedur, + e->rssi, dfs->dfs_rinfo.rn_minrssithresh); + } +} + +/** + * dfs_is_second_seg_radar_disabled() - Check for second segment radar disabled. + * @dfs: Pointer to wlan_dfs structure. + * @seg_id: Segment id. + * + * Return: true if the second segment RADAR is enabled else false. + */ +static inline bool dfs_is_second_seg_radar_disabled( + struct wlan_dfs *dfs, + int seg_id) +{ + if ((seg_id == SEG_ID_SECONDARY) && + !(dfs->dfs_proc_phyerr & + DFS_SECOND_SEGMENT_RADAR_EN)) { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS3, + "%s: Do not process PHY error data from Second segment, DFS_SECOND_SEGMENT_RADAR_EN is not enabled\n", + __func__); + return true; + } + + return false; +} + +/** + * dfs_set_chan_index() - Set channel index. + * @dfs: Pointer to wlan_dfs structure. + * @e: Pointer to dfs_phy_err structure. + * @event: Pointer to dfs_event structure. + */ +static inline void dfs_set_chan_index( + struct wlan_dfs *dfs, + struct dfs_phy_err *e, + struct dfs_event *event) +{ + if (e->is_pri) { + event->re_chanindex = dfs->dfs_curchan_radindex; + } else { + event->re_chanindex = dfs->dfs_extchan_radindex; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, + "%s %s New extension channel event is added to queue\n", + __func__, + (event->re_chanindex == -1) ? + "- phyerr on ext channel\n" : ""); + } +} + void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, uint8_t r_rssi, uint8_t r_ext_rssi, uint32_t r_rs_tstamp, uint64_t r_fulltsf) @@ -595,16 +686,7 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, (e.is_pri ? 1 : 0), (e.is_ext ? 1 : 0), &slope, &dc_found); if (add_dur) { - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, - "old dur %d slope =%d\n", e.dur, slope); - e.is_sw_chirp = 1; - /* bump up to a random bin5 pulse duration */ - if (e.dur < MIN_BIN5_DUR) { - e.dur = dfs_get_random_bin5_dur(dfs, - e.fulltsf); - } - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, - "new dur %d\n", e.dur); + dfs_bump_up_bin5_pulse_dur(dfs, &e, slope); } else { /* Set the duration so that it is rejected. */ e.is_sw_chirp = 0; @@ -616,7 +698,7 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, } else { /* * We have a pulse that is either bigger than - * MAX_BIN5_DUR or * less than MAYBE_BIN5_DUR + * MAX_BIN5_DUR or less than MAYBE_BIN5_DUR */ if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { @@ -654,8 +736,7 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, if ((dfs->dfs_curchan->dfs_ch_flags & CHANNEL_108G) == CHANNEL_108G) { if (!(dfs->dfs_proc_phyerr & DFS_AR_EN)) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "%s: DFS_AR_EN not enabled\n", - __func__); + "%s: DFS_AR_EN not enabled\n", __func__); return; } WLAN_DFSEVENTQ_LOCK(dfs); @@ -663,8 +744,7 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, if (event == NULL) { WLAN_DFSEVENTQ_UNLOCK(dfs); DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, - "%s: no more events space left\n", - __func__); + "%s: no more events space left\n", __func__); return; } STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); @@ -694,54 +774,22 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, IEEE80211_IS_CHAN_11AC_VHT80_80(dfs->dfs_curchan)) && IEEE80211_IS_CHAN_DFS_CFREQ2(dfs->dfs_curchan))) || (dfs_is_precac_timer_running(dfs))) { + + int retval = 0; + if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS3, "%s: DFS_RADAR_EN not enabled\n", __func__); return; } - /* - * Rssi is not accurate for short pulses, so donot - * filter based on that for short duration pulses. - */ - if (dfs->dfs_caps.wlan_dfs_ext_chan_ok) { - if ((e.rssi < dfs->dfs_rinfo.rn_minrssithresh && - (e.dur > 4)) || e.dur > - (dfs->dfs_rinfo.rn_maxpulsedur)) { - dfs->wlan_dfs_stats.rssi_discards++; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "Extension channel pulse is discarded: dur=%d, maxpulsedur=%d, rssi=%d, minrssi=%d\n", - e.dur, - dfs->dfs_rinfo.rn_maxpulsedur, - e.rssi, - dfs->dfs_rinfo.rn_minrssithresh - ); - return; - } - } else { - if (e.rssi < dfs->dfs_rinfo.rn_minrssithresh || - e.dur > - dfs->dfs_rinfo.rn_maxpulsedur) { - dfs->wlan_dfs_stats.rssi_discards++; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "Pulse is discarded: dur=%d, maxpulsedur=%d, rssi=%d, minrssi=%d\n", - e.dur, - dfs->dfs_rinfo.rn_maxpulsedur, - e.rssi, - dfs->dfs_rinfo.rn_minrssithresh - ); - return; - } - } - if ((e.seg_id == SEG_ID_SECONDARY) && - !(dfs->dfs_proc_phyerr & - DFS_SECOND_SEGMENT_RADAR_EN)){ - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS3, - "%s: Do not process PHY error data from Second segment, DFS_SECOND_SEGMENT_RADAR_EN is not enabled\n", - __func__); + dfs_filter_short_pulses(dfs, &e, &retval); + if (retval) + return; + + if (dfs_is_second_seg_radar_disabled(dfs, e.seg_id)) return; - } /* Add the event to the list, if there's space. */ WLAN_DFSEVENTQ_LOCK(dfs); @@ -781,19 +829,8 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, } /* Correctly set which channel is being reported on */ - if (e.is_pri) { - event->re_chanindex = dfs->dfs_curchan_radindex; - } else { - if (dfs->dfs_extchan_radindex == -1) { - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, - "%s - phyerr on ext channel\n", - __func__); - } - event->re_chanindex = dfs->dfs_extchan_radindex; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_PHYERR, - "%s New extension channel event is added to queue\n", - __func__); - } + dfs_set_chan_index(dfs, &e, event); + WLAN_DFSQ_LOCK(dfs); STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list); WLAN_DFSQ_UNLOCK(dfs); diff --git a/umac/dfs/core/src/filtering/dfs_process_radarevent.c b/umac/dfs/core/src/filtering/dfs_process_radarevent.c index 4f7c74cd80..4737c0d200 100644 --- a/umac/dfs/core/src/filtering/dfs_process_radarevent.c +++ b/umac/dfs/core/src/filtering/dfs_process_radarevent.c @@ -47,6 +47,13 @@ static int debug_dup_cnt; * Peregrine reports the pulse duration in microseconds regardless of the * operating mode. (XXX TODO: verify this, obviously.) * + * The hardware returns the duration in a variety of formats, + * so it's converted from the hardware format to TSF (usec) + * values here. + * XXX TODO: this should really be done when the PHY error + * is processed, rather than way out here.. + * + * * Return: Returns the duration. */ static inline uint8_t dfs_process_pulse_dur(struct wlan_dfs *dfs, @@ -84,31 +91,23 @@ static void dfs_print_radar_events(struct wlan_dfs *dfs) int i; DFS_PRINTK("%s:#Phyerr=%d, #false detect=%d, #queued=%d\n", - __func__, - dfs->dfs_phyerr_count, - dfs->dfs_phyerr_reject_count, + __func__, dfs->dfs_phyerr_count, dfs->dfs_phyerr_reject_count, dfs->dfs_phyerr_queued_count); DFS_PRINTK("%s:dfs_phyerr_freq_min=%d, dfs_phyerr_freq_max=%d\n", - __func__, - dfs->dfs_phyerr_freq_min, - dfs->dfs_phyerr_freq_max); + __func__, dfs->dfs_phyerr_freq_min, dfs->dfs_phyerr_freq_max); DFS_PRINTK( "%s:Total radar events detected=%d, entries in the radar queue follows:\n", - __func__, - dfs->dfs_event_log_count); + __func__, dfs->dfs_event_log_count); for (i = 0; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count); i++) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "ts=%llu diff_ts=%u rssi=%u dur=%u, is_chirp=%d, seg_id=%d, sidx=%d, freq_offset=%d.%dMHz, peak_mag=%d, total_gain=%d, mb_gain=%d, relpwr_db=%d\n", - dfs->radar_log[i].ts, - dfs->radar_log[i].diff_ts, - dfs->radar_log[i].rssi, - dfs->radar_log[i].dur, - dfs->radar_log[i].is_chirp, - dfs->radar_log[i].seg_id, + dfs->radar_log[i].ts, dfs->radar_log[i].diff_ts, + dfs->radar_log[i].rssi, dfs->radar_log[i].dur, + dfs->radar_log[i].is_chirp, dfs->radar_log[i].seg_id, dfs->radar_log[i].sidx, (int)dfs->radar_log[i].freq_offset_khz/1000, (int)abs(dfs->radar_log[i].freq_offset_khz)%1000, @@ -125,9 +124,66 @@ static void dfs_print_radar_events(struct wlan_dfs *dfs) dfs->dfs_phyerr_freq_max = 0; } +/* + * dfs_reject_on_pri() - Rejecting on individual filter based on min PRI . + * @dfs: Pointer to wlan_dfs structure. + * @rf: Pointer to dfs_filter structure. + * @deltaT: deltaT value. + * @this_ts: Timestamp. + */ +static inline bool dfs_reject_on_pri( + struct wlan_dfs *dfs, + struct dfs_filter *rf, + uint64_t deltaT, + uint64_t this_ts) +{ + if ((deltaT < rf->rf_minpri) && (deltaT != 0)) { + /* Second line of PRI filtering. */ + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u\n", + rf->rf_pulseid, (uint64_t)deltaT, + rf->rf_minpri); + return 1; + } + + if (rf->rf_ignore_pri_window > 0) { + if (deltaT < rf->rf_minpri) { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n", + rf->rf_pulseid, (uint64_t)deltaT, + rf->rf_minpri); + /* But update the last time stamp. */ + rf->rf_dl.dl_last_ts = this_ts; + return 1; + } + } else { + /* + * The HW may miss some pulses especially with + * high channel loading. This is true for Japan + * W53 where channel loaoding is 50%. Also for + * ETSI where channel loading is 30% this can + * be an issue too. To take care of missing + * pulses, we introduce pri_margin multiplie. + * This is normally 2 but can be higher for W53. + */ + + if ((deltaT > (dfs->dfs_pri_multiplier * rf->rf_maxpri)) || + (deltaT < rf->rf_minpri)) { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n", + rf->rf_pulseid, (uint64_t) deltaT, + rf->rf_minpri); + /* But update the last time stamp. */ + rf->rf_dl.dl_last_ts = this_ts; + return 1; + } + } + + return 0; +} + void __dfs_process_radarevent(struct wlan_dfs *dfs, struct dfs_filtertype *ft, - struct dfs_filter *rf, struct dfs_event *re, uint64_t this_ts, int *found) @@ -135,6 +191,7 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs, int p; uint64_t deltaT = 0; int ext_chan_event_flag = 0; + struct dfs_filter *rf = NULL; for (p = 0, *found = 0; (p < ft->ft_numfilters) && (!(*found)); p++) { @@ -147,56 +204,9 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs, this_ts + 1) : this_ts - rf->rf_dl.dl_last_ts; - if ((deltaT < rf->rf_minpri) && (deltaT != 0)) { - /* Second line of PRI filtering. */ - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "filterID %d : Rejecting on individual filter min PRI deltaT=%lld rf->rf_minpri=%u\n", - rf->rf_pulseid, - (uint64_t)deltaT, - rf->rf_minpri); + if (dfs_reject_on_pri(dfs, rf, deltaT, this_ts)) continue; - } - if (rf->rf_ignore_pri_window > 0) { - if (deltaT < rf->rf_minpri) { - DFS_DPRINTK(dfs, - WLAN_DEBUG_DFS2, - "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n", - rf->rf_pulseid, - (uint64_t) - deltaT, - rf->rf_minpri); - /* But update the last time stamp. */ - rf->rf_dl.dl_last_ts = this_ts; - continue; - } - } else { - /* - * The HW may miss some pulses especially with - * high channel loading. This is true for Japan - * W53 where channel loaoding is 50%. Also for - * ETSI where channel loading is 30% this can - * be an issue too. To take care of missing - * pulses, we introduce pri_margin multiplie. - * This is normally 2 but can be higher for W53. - */ - - if ((deltaT > (dfs->dfs_pri_multiplier * - rf->rf_maxpri)) || - (deltaT < rf->rf_minpri) - ) { - DFS_DPRINTK(dfs, - WLAN_DEBUG_DFS2, - "filterID %d : Rejecting on individual filter max PRI deltaT=%lld rf->rf_minpri=%u\n", - rf->rf_pulseid, - (uint64_t) - deltaT, - rf->rf_minpri); - /* But update the last time stamp. */ - rf->rf_dl.dl_last_ts = this_ts; - continue; - } - } dfs_add_pulse(dfs, rf, re, deltaT, this_ts); /* @@ -220,28 +230,90 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs, rf->rf_dl.dl_last_ts = this_ts; } } + + if (*found) { + DFS_PRINTK("Found on channel minDur = %d, filterId = %d\n", + ft->ft_mindur, + rf != NULL ? rf->rf_pulseid : -1); + } + + return; } -int dfs_process_radarevent(struct wlan_dfs *dfs, +/** + * dfs_radarfound_reset_vars() - Reset dfs variables after radar found + * @dfs: Pointer to wlan_dfs structure. + * @rs: Pointer to dfs_state. + * @chan: Current channel. + */ +static inline void dfs_radarfound_reset_vars( + struct wlan_dfs *dfs, + struct dfs_state *rs, + struct dfs_ieee80211_channel *chan, + uint8_t seg_id) +{ + struct dfs_ieee80211_channel *thischan; + + /* + * TODO: Instead of discarding the radar, create a workqueue + * if the channel change is happenning through userspace and + * process the radar event once the channel change is completed. + */ + + /* Collect stats */ + dfs->wlan_dfs_stats.num_radar_detects++; + thischan = &rs->rs_chan; + if ((seg_id == SEG_ID_SECONDARY) && + (dfs_is_precac_timer_running(dfs))) { + dfs->is_radar_during_precac = 1; + DFS_PRINTK("Radar found on second segment VHT80 freq=%d MHz\n", + dfs->dfs_precac_secondary_freq); + } else { + DFS_PRINTK("Radar found on channel %d (%d MHz)\n", + thischan->dfs_ch_ieee, thischan->dfs_ch_freq); + } + + /* + * If event log is on then dump the radar event queue on + * filter match. This can be used to collect information + * on false radar detection. + */ + if (dfs->dfs_event_log_on) + dfs_print_radar_events(dfs); + + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs); + + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, + "Primary channel freq = %u flags=0x%x\n", + chan->dfs_ch_freq, chan->dfs_ch_flagext); + + if (chan->dfs_ch_freq != thischan->dfs_ch_freq) + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, + "Ext channel freq = %u flags=0x%x\n", + thischan->dfs_ch_freq, + thischan->dfs_ch_flagext); + + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + dfs->dfs_phyerr_w53_counter = 0; + if (seg_id == SEG_ID_SECONDARY) { + dfs->wlan_dfs_stats.num_seg_two_radar_detects++; + dfs->is_radar_found_on_secondary_seg = 1; + } +} + +/** + * dfs_radarevent_basic_sanity - Check basic sanity of the radar event + * @dfs: Pointer to wlan_dfs structure. + * @chan: Current channel. + * Return: If a radar event found on NON-DFS channel return 0. Otherwise, + * return 1. + */ +static inline int dfs_radarevent_basic_sanity( + struct wlan_dfs *dfs, struct dfs_ieee80211_channel *chan) { - struct dfs_event re, *event; - struct dfs_state *rs = NULL; - struct dfs_filtertype *ft; - struct dfs_filter *rf; - int found, retval = 0, p, empty; - int events_processed = 0; - uint32_t tabledepth, index; - uint64_t deltafull_ts = 0, this_ts, deltaT; - struct dfs_ieee80211_channel *thischan; - struct dfs_pulseline *pl; - static uint32_t test_ts; - static uint32_t diff_ts; - int i; - uint8_t seg_id = 0; - - pl = dfs->pulses; - if (!(dfs->dfs_second_segment_bangradar || dfs_is_precac_timer_running(dfs))) if (!(IEEE80211_IS_CHAN_DFS(chan) || @@ -249,28 +321,41 @@ int dfs_process_radarevent(struct wlan_dfs *dfs, IEEE80211_IS_CHAN_11AC_VHT80_80(chan)) && IEEE80211_IS_CHAN_DFS_CFREQ2(chan)))) { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "%s: radar event on non-DFS chan\n", - __func__); + "%s: radar event on non-DFS chan\n", __func__); dfs_reset_radarq(dfs); dfs_reset_alldelaylines(dfs); dfs->dfs_bangradar = 0; return 0; } - /* - * TEST : Simulate radar bang, make sure we add the channel to NOL - * (bug 29968) - */ + return 1; +} + +/** + * dfs_handle_bangradar - Handle the case of bangradar + * @dfs: Pointer to wlan_dfs structure. + * @chan: Current channel. + * @rs: Pointer to dfs_state. + * Return: if bangradar then return 0. Otherwise, return 1. + */ +static inline int dfs_handle_bangradar( + struct wlan_dfs *dfs, + struct dfs_ieee80211_channel *chan, + struct dfs_state **rs, + uint8_t *seg_id, + int *retval) +{ + if (dfs->dfs_bangradar) { /* * Bangradar will always simulate radar found on the primary * channel. */ - rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; + *rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; dfs->dfs_bangradar = 0; /* Reset */ DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: bangradar\n", __func__); - retval = 1; - goto dfsfound; + *retval = 1; + return 1; } if (dfs->dfs_second_segment_bangradar) { @@ -278,80 +363,569 @@ int dfs_process_radarevent(struct wlan_dfs *dfs, IEEE80211_IS_CHAN_11AC_VHT160(chan) || IEEE80211_IS_CHAN_11AC_VHT80_80(chan)) { dfs->is_radar_found_on_secondary_seg = 1; - rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; + *rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: second segment bangradar on cfreq = %u\n", __func__, dfs->dfs_precac_secondary_freq); - retval = 1; - seg_id = SEG_ID_SECONDARY; + *retval = 1; + *seg_id = SEG_ID_SECONDARY; } else { DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, "%s: Do not process the second segment bangradar\n", __func__); } dfs->dfs_second_segment_bangradar = 0; /* Reset */ - goto dfsfound; + return 1; } - /* - * The HW may miss some pulses especially with high channel loading. - * This is true for Japan W53 where channel loaoding is 50%. Also - * for ETSI where channel loading is 30% this can be an issue too. - * To take care of missing pulses, we introduce pri_margin multiplie. - * This is normally 2 but can be higher for W53. - */ + return 0; +} +/** + * dfs_process_w53_pulses() - Prrocess w53 pulses + * @dfs: Pointer to wlan_dfs structure. + * + * For chips that support frequency information, we can relax PRI + * restriction if the frequency spread is narrow. + */ +static inline void dfs_process_w53_pulses( + struct wlan_dfs *dfs) +{ + if ((dfs->dfs_phyerr_freq_max - dfs->dfs_phyerr_freq_min) < + DFS_MAX_FREQ_SPREAD) + dfs->dfs_pri_multiplier = DFS_LARGE_PRI_MULTIPLIER; + + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, + "%s: w53_counter=%d, freq_max=%d, freq_min=%d, pri_multiplier=%d\n", + __func__, dfs->dfs_phyerr_w53_counter, + dfs->dfs_phyerr_freq_max, dfs->dfs_phyerr_freq_min, + dfs->dfs_pri_multiplier); + + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; +} + +/** + * dfs_handle_missing_pulses - Handle the case of missing pulses + * @dfs: Pointer to wlan_dfs structure. + * @chan: Current channel. + * + * The HW may miss some pulses especially with high channel loading. + * This is true for Japan W53 where channel loaoding is 50%. Also + * for ETSI where channel loading is 30% this can be an issue too. + * To take care of missing pulses, we introduce pri_margin multiplie. + * This is normally 2 but can be higher for W53. + * Return: If not enough pulses return 0. Otherwise, return 1. + */ +static inline int dfs_handle_missing_pulses( + struct wlan_dfs *dfs, + struct dfs_ieee80211_channel *chan) +{ if ((dfs->dfsdomain == DFS_MKK4_DOMAIN) && - (dfs->dfs_caps.wlan_chip_is_bb_tlv) && - (chan->dfs_ch_freq < FREQ_5500_MHZ)) { - + (dfs->dfs_caps.wlan_chip_is_bb_tlv) && + (chan->dfs_ch_freq < FREQ_5500_MHZ)) { dfs->dfs_pri_multiplier = DFS_W53_DEFAULT_PRI_MULTIPLIER; /* * Do not process W53 pulses unless we have a minimum number * of them. */ - if (dfs->dfs_phyerr_w53_counter >= 5) { - /* - * For chips that support frequency information, we - * can relax PRI restriction if the frequency spread - * is narrow. - */ - if ((dfs->dfs_phyerr_freq_max - - dfs->dfs_phyerr_freq_min) < - DFS_MAX_FREQ_SPREAD) { - dfs->dfs_pri_multiplier = - DFS_LARGE_PRI_MULTIPLIER; - } - - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "%s: w53_counter=%d, freq_max=%d, freq_min=%d, pri_multiplier=%d\n", - __func__, - dfs->dfs_phyerr_w53_counter, - dfs->dfs_phyerr_freq_max, - dfs->dfs_phyerr_freq_min, - dfs->dfs_pri_multiplier); - dfs->dfs_phyerr_freq_min = 0x7fffffff; - dfs->dfs_phyerr_freq_max = 0; - } else { + if (dfs->dfs_phyerr_w53_counter >= 5) + dfs_process_w53_pulses(dfs); + else return 0; - } } - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "%s: pri_multiplier=%d\n", + + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, "%s: pri_multiplier=%d\n", __func__, dfs->dfs_pri_multiplier); + return 1; +} + +/** + * dfs_is_radarq_empty - check if radarq is empty + * @dfs: Pointer to wlan_dfs structure. + * @empty: Pointer to empty + */ +static inline void dfs_is_radarq_empty( + struct wlan_dfs *dfs, + int *empty) +{ WLAN_DFSQ_LOCK(dfs); - empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); + *empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); WLAN_DFSQ_UNLOCK(dfs); +} - while ((!empty) && (!retval) && (events_processed < MAX_EVENTS)) { - WLAN_DFSQ_LOCK(dfs); - event = STAILQ_FIRST(&(dfs->dfs_radarq)); - if (event != NULL) - STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); - WLAN_DFSQ_UNLOCK(dfs); +/** + * dfs_remove_event_from_radarq - remove event from radarq + * @dfs: Pointer to wlan_dfs structure. + * @event: Double pointer to the event structure + */ +static inline void dfs_remove_event_from_radarq( + struct wlan_dfs *dfs, + struct dfs_event **event) +{ + WLAN_DFSQ_LOCK(dfs); + *event = STAILQ_FIRST(&(dfs->dfs_radarq)); + if (*event != NULL) + STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); + WLAN_DFSQ_UNLOCK(dfs); +} +/** + * dfs_return_event_to_eventq - return event to eventq + * @dfs: Pointer to wlan_dfs structure. + * @event: Pointer to the event structure + */ +static inline void dfs_return_event_to_eventq( + struct wlan_dfs *dfs, + struct dfs_event *event) +{ + qdf_mem_zero(event, sizeof(struct dfs_event)); + WLAN_DFSEVENTQ_LOCK(dfs); + STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); + WLAN_DFSEVENTQ_UNLOCK(dfs); +} + +/** + * dfs_log_event - log dfs event + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to dfs_event re + * @this_ts: Current time stamp 64bit + * @diff_ts: Difference between 2 timestamps 32bit + */ +static inline void dfs_log_event( + struct wlan_dfs *dfs, + struct dfs_event *re, + uint64_t this_ts, + uint32_t diff_ts) +{ + uint8_t i; + + if (dfs->dfs_event_log_on) { + i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE; + dfs->radar_log[i].ts = this_ts; + dfs->radar_log[i].diff_ts = diff_ts; + dfs->radar_log[i].rssi = (*re).re_rssi; + dfs->radar_log[i].dur = (*re).re_dur; + dfs->radar_log[i].seg_id = (*re).re_seg_id; + dfs->radar_log[i].sidx = (*re).re_sidx; + dfs->radar_log[i].freq_offset_khz = + (*re).re_freq_offset_khz; + dfs->radar_log[i].peak_mag = (*re).re_peak_mag; + dfs->radar_log[i].total_gain = (*re).re_total_gain; + dfs->radar_log[i].mb_gain = (*re).re_mb_gain; + dfs->radar_log[i].relpwr_db = (*re).re_relpwr_db; + dfs->radar_log[i].is_chirp = DFS_EVENT_NOTCHIRP(re) ? + 0 : 1; + dfs->dfs_event_log_count++; + } +} + +/** + * dfs_check_if_nonbin5 - Check if radar, other than bin5, is found + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re (radar event) + * @rs: Double Pointer to rs (radar state) + * @this_ts: Current time stamp 64bit + * @diff_ts: Difference between 2 timestamps 32bit + * @found: Pointer to found. If radar found or not. + * @retval: Pointer to retval(return value). + */ +static inline void dfs_check_if_nonbin5( + struct wlan_dfs *dfs, + struct dfs_event *re, + struct dfs_state **rs, + uint64_t this_ts, + uint32_t diff_ts, + int *found, + int *retval) +{ + + uint32_t tabledepth = 0; + struct dfs_filtertype *ft; + uint64_t deltaT; + + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, + " *** chan freq (%d): ts %llu dur %u rssi %u\n", + (*rs)->rs_chan.dfs_ch_freq, (uint64_t)this_ts, + (*re).re_dur, (*re).re_rssi); + + while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && + ((dfs->dfs_ftindextable[(*re).re_dur])[tabledepth] != + -1) && (!*retval)) { + ft = dfs->dfs_radarf[((dfs->dfs_ftindextable[(*re).re_dur]) + [tabledepth])]; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + " ** RD (%d): ts %x dur %u rssi %u\n", + (*rs)->rs_chan.dfs_ch_freq, (*re).re_ts, + (*re).re_dur, (*re).re_rssi); + + if ((*re).re_rssi < ft->ft_rssithresh && + (*re).re_dur > MAX_DUR_FOR_LOW_RSSI) { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "%s : Rejecting on rssi rssi=%u thresh=%u\n", + __func__, (*re).re_rssi, + ft->ft_rssithresh); + tabledepth++; + continue; + } + deltaT = this_ts - ft->ft_last_ts; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)\n", + (uint64_t)deltaT, (uint64_t)this_ts, + (uint64_t)ft->ft_last_ts); + + if ((deltaT < ft->ft_minpri) && (deltaT != 0)) { + /* + * This check is for the whole filter type. + * Individual filters will check this again. + * This is first line of filtering. + */ + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, + "%s: Rejecting on pri pri=%lld minpri=%u\n", + __func__, (uint64_t)deltaT, + ft->ft_minpri); + tabledepth++; + continue; + } + + __dfs_process_radarevent(dfs, ft, re, this_ts, found); + + ft->ft_last_ts = this_ts; + *retval |= *found; + tabledepth++; + } +} + +/** + * dfs_check_each_b5radar() - Check each bin5 radar + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re(radar event). + * @br: Pointer to dfs_bin5radars structure. + * @this_ts: Current time stamp 64bit. + * @diff_ts: Difference between 2 timestamps 32bit. + * @found: Pointer to found. If radar found or not. + */ +static inline void dfs_check_each_b5radar( + struct wlan_dfs *dfs, + struct dfs_event *re, + struct dfs_bin5radars *br, + uint64_t this_ts, + uint32_t diff_ts, + int *found) +{ + if (dfs_bin5_check_pulse(dfs, re, br)) { + /* + * This is a valid Bin5 pulse, check if it belongs to a + * burst. + */ + (*re).re_dur = dfs_retain_bin5_burst_pattern(dfs, diff_ts, + (*re).re_dur); + /* + * Remember our computed duration for the next pulse in the + * burst (if needed). + */ + dfs->dfs_rinfo.dfs_bin5_chirp_ts = this_ts; + dfs->dfs_rinfo.dfs_last_bin5_dur = (*re).re_dur; + + if (dfs_bin5_addpulse(dfs, br, re, this_ts)) + *found |= dfs_bin5_check(dfs); + } else { + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS_BIN5_PULSE, + "%s not a BIN5 pulse (dur=%d)\n", + __func__, (*re).re_dur); + } +} + +/** + * dfs_check_if_bin5() - Check if bin5 radar is found + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re(radar event). + * @this_ts: Current time stamp 64bit. + * @diff_ts: Difference between 2 timestamps 32bit. + * @found: Pointer to found. If radar found or not. + */ +static inline void dfs_check_if_bin5( + struct wlan_dfs *dfs, + struct dfs_event *re, + uint64_t this_ts, + uint32_t diff_ts, + int *found) +{ + int p; + + /* BIN5 pulses are FCC and Japan specific. */ + if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || + (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { + for (p = 0; (p < dfs->dfs_rinfo.rn_numbin5radars) && (!*found); + p++) { + struct dfs_bin5radars *br; + + br = &(dfs->dfs_b5radars[p]); + dfs_check_each_b5radar(dfs, re, br, this_ts, diff_ts, + found); + } + } + + if (*found) + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, + "%s: Found bin5 radar\n", __func__); +} + +/** + * dfs_skip_the_event() - Skip the Radar event + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re(radar event). + * @rs: Pointer to dfs_state. + */ +static inline bool dfs_skip_the_event( + struct wlan_dfs *dfs, + struct dfs_event *re, + struct dfs_state **rs) +{ + if ((*re).re_chanindex < DFS_NUM_RADAR_STATES) + (*rs) = &dfs->dfs_radar[(*re).re_chanindex]; + else + return 1; + + if ((*rs)->rs_chan.dfs_ch_flagext & CHANNEL_INTERFERENCE) + return 1; + + return 0; +} + +/** + * dfs_check_ts_wrap() - dfs check for timestamp wrap. + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re(radar event). + * @deltafull_ts: Deltafull ts. + * + * Return: Deltafull ts. + */ +static inline uint64_t dfs_check_ts_wrap( + struct wlan_dfs *dfs, + struct dfs_event *re, + uint64_t deltafull_ts) +{ + if (deltafull_ts > + ((uint64_t)((DFS_TSMASK - + dfs->dfs_rinfo.rn_last_ts) + + 1 + (*re).re_ts))) + deltafull_ts -= + (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + + 1 + (*re).re_ts; + + return deltafull_ts; +} + +/** + * dfs_calculate_ts_prefix() - Calculate deltafull ts value. + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re(radar event). + */ +static inline void dfs_calculate_ts_prefix( + struct wlan_dfs *dfs, + struct dfs_event *re) +{ + uint64_t deltafull_ts; + + if ((*re).re_ts <= dfs->dfs_rinfo.rn_last_ts) { + dfs->dfs_rinfo.rn_ts_prefix += (((uint64_t) 1) << DFS_TSSHIFT); + /* Now, see if it's been more than 1 wrap */ + deltafull_ts = (*re).re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; + deltafull_ts = dfs_check_ts_wrap(dfs, re, deltafull_ts); + deltafull_ts >>= DFS_TSSHIFT; + + if (deltafull_ts > 1) + dfs->dfs_rinfo.rn_ts_prefix += + ((deltafull_ts - 1) << DFS_TSSHIFT); + } else { + deltafull_ts = (*re).re_full_ts - + dfs->dfs_rinfo.rn_lastfull_ts; + if (deltafull_ts > (uint64_t) DFS_TSMASK) { + deltafull_ts >>= DFS_TSSHIFT; + dfs->dfs_rinfo.rn_ts_prefix += + ((deltafull_ts - 1) << DFS_TSSHIFT); + } + } +} + +/** + * dfs_calculate_timestamps() - Calculate various timestamps + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re(radar event) + * @this_ts : Pointer to this_ts (this timestamp) + */ + +static inline void dfs_calculate_timestamps( + struct wlan_dfs *dfs, + struct dfs_event *re, + uint64_t *this_ts) +{ + if (dfs->dfs_rinfo.rn_lastfull_ts == 0) { + /* + * Either not started, or 64-bit rollover exactly to + * zero Just prepend zeros to the 15-bit ts. + */ + dfs->dfs_rinfo.rn_ts_prefix = 0; + } else { + /* WAR 23031- patch duplicate ts on very short pulses. + * This pacth has two problems in linux environment. + * 1)The time stamp created and hence PRI depends + * entirely on the latency. If the latency is high, it + * possibly can split two consecutive pulses in the + * same burst so far away (the same amount of latency) + * that make them look like they are from differenct + * bursts. It is observed to happen too often. It sure + * makes the detection fail. + * 2)Even if the latency is not that bad, it simply + * shifts the duplicate timestamps to a new duplicate + * timestamp based on how they are processed. + * This is not worse but not good either. + * Take this pulse as a good one and create a probable + * PRI later. + */ + if ((*re).re_dur == 0 && (*re).re_ts == + dfs->dfs_rinfo.rn_last_unique_ts) { + debug_dup[debug_dup_cnt++] = '1'; + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, + "\n %s deltaT is 0\n", __func__); + } else { + dfs->dfs_rinfo.rn_last_unique_ts = (*re).re_ts; + debug_dup[debug_dup_cnt++] = '0'; + } + + if (debug_dup_cnt >= 32) + debug_dup_cnt = 0; + + dfs_calculate_ts_prefix(dfs, re); + } + + /* + * At this stage rn_ts_prefix has either been blanked or + * calculated, so it's safe to use. + */ + *this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((uint64_t) (*re).re_ts); + dfs->dfs_rinfo.rn_lastfull_ts = (*re).re_full_ts; + dfs->dfs_rinfo.rn_last_ts = (*re).re_ts; +} + +/** + * dfs_add_to_pulseline - Extract necessary items from dfs_event and + * add it as pulse in the pulseline + * @dfs: Pointer to wlan_dfs structure. + * @re: Pointer to re(radar event) + * @this_ts : Pointer to this_ts (this timestamp) + */ +static inline void dfs_add_to_pulseline( + struct wlan_dfs *dfs, + struct dfs_event *re, + uint64_t *this_ts, + uint32_t *test_ts, + uint32_t *diff_ts) +{ + uint32_t index; + struct dfs_pulseline *pl; + + /* + * Calculate the start of the radar pulse. + * + * The TSF is stamped by the MAC upon reception of the event, + * which is (typically?) at the end of the event. But the + * pattern matching code expects the event timestamps to be at + * the start of the event. So to fake it, we subtract the pulse + * duration from the given TSF. This is done after the 64-bit + * timestamp has been calculated so long pulses correctly + * under-wrap the counter. Ie, if this was done on the 32 + * (or 15!) bit TSF when the TSF value is closed to 0, it will + * underflow to 0xfffffXX, which would mess up the logical "OR" + * operation done above. + * This isn't valid for Peregrine as the hardware gives us the + * actual TSF offset of the radar event, not just the MAC TSF + * of the completed receive. + * + * XXX TODO: ensure that the TLV PHY error processing code will + * correctly calculate the TSF to be the start of the radar + * pulse. + * + * XXX TODO TODO: modify the TLV parsing code to subtract the + * duration from the TSF, based on the current fast clock value. + */ + if ((!dfs->dfs_caps.wlan_chip_is_bb_tlv) && (*re).re_dur != 1) + *this_ts -= (*re).re_dur; + + pl = dfs->pulses; + /* Save the pulse parameters in the pulse buffer(pulse line). */ + index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; + + if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) + pl->pl_firstelem = (pl->pl_firstelem+1) & + DFS_MAX_PULSE_BUFFER_MASK; + else + pl->pl_numelems++; + + pl->pl_lastelem = index; + pl->pl_elems[index].p_time = *this_ts; + pl->pl_elems[index].p_dur = (*re).re_dur; + pl->pl_elems[index].p_rssi = (*re).re_rssi; + *diff_ts = (uint32_t)*this_ts - *test_ts; + *test_ts = (uint32_t)*this_ts; + + DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, + "ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu\n", + (uint32_t)*this_ts, (*re).re_dur, + (*re).re_rssi, *diff_ts, + (uint64_t)pl->pl_elems[index].p_time); +} + +/** + * dfs_conditional_clear_delaylines - Clear delay lines to remove the + * false pulses. + * @dfs: Pointer to wlan_dfs structure. + * @diff_ts: diff between timerstamps + */ +static inline void dfs_conditional_clear_delaylines( + struct wlan_dfs *dfs, + uint32_t diff_ts) +{ + /* If diff_ts is very small, we might be getting false pulse + * detects due to heavy interference. We might be getting + * spectral splatter from adjacent channel. In order to prevent + * false alarms we clear the delay-lines. This might impact + * positive detections under harsh environments, but helps with + * false detects. + */ + + if (diff_ts < 100) { + dfs_reset_alldelaylines(dfs); + dfs_reset_radarq(dfs); + } +} +/** + * dfs_process_each_radarevent - remove each event from the dfs radar queue + * and process it. + * @dfs: Pointer to wlan_dfs structure. + * Return: If radar found then return 1 else return 0. + */ +static inline int dfs_process_each_radarevent( + struct wlan_dfs *dfs, + struct dfs_ieee80211_channel *chan, + struct dfs_state **rs, + uint8_t *seg_id, + int *retval) +{ + struct dfs_event re, *event; + int found, empty; + int events_processed = 0; + uint64_t this_ts; + static uint32_t test_ts; + static uint32_t diff_ts; + + dfs_is_radarq_empty(dfs, &empty); + + while ((!empty) && (!*retval) && (events_processed < MAX_EVENTS)) { + dfs_remove_event_from_radarq(dfs, &event); if (event == NULL) { empty = 1; break; @@ -359,364 +933,66 @@ int dfs_process_radarevent(struct wlan_dfs *dfs, events_processed++; re = *event; - qdf_mem_zero(event, sizeof(struct dfs_event)); - WLAN_DFSEVENTQ_LOCK(dfs); - STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); - WLAN_DFSEVENTQ_UNLOCK(dfs); + dfs_return_event_to_eventq(dfs, event); - seg_id = re.re_seg_id; + *seg_id = re.re_seg_id; found = 0; - if (re.re_chanindex < DFS_NUM_RADAR_STATES) - rs = &dfs->dfs_radar[re.re_chanindex]; - else { - WLAN_DFSQ_LOCK(dfs); - empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); - WLAN_DFSQ_UNLOCK(dfs); - continue; - } - if (rs->rs_chan.dfs_ch_flagext & CHANNEL_INTERFERENCE) { - WLAN_DFSQ_LOCK(dfs); - empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); - WLAN_DFSQ_UNLOCK(dfs); + if (dfs_skip_the_event(dfs, &re, rs)) { + dfs_is_radarq_empty(dfs, &empty); continue; } - if (dfs->dfs_rinfo.rn_lastfull_ts == 0) { - /* - * Either not started, or 64-bit rollover exactly to - * zero Just prepend zeros to the 15-bit ts. - */ - dfs->dfs_rinfo.rn_ts_prefix = 0; - } else { - /* WAR 23031- patch duplicate ts on very short pulses. - * This pacth has two problems in linux environment. - * 1)The time stamp created and hence PRI depends - * entirely on the latency. If the latency is high, it - * possibly can split two consecutive pulses in the - * same burst so far away (the same amount of latency) - * that make them look like they are from differenct - * bursts. It is observed to happen too often. It sure - * makes the detection fail. - * 2)Even if the latency is not that bad, it simply - * shifts the duplicate timestamps to a new duplicate - * timestamp based on how they are processed. - * This is not worse but not good either. - * Take this pulse as a good one and create a probable - * PRI later. - */ - if (re.re_dur == 0 && re.re_ts == - dfs->dfs_rinfo.rn_last_unique_ts) { - debug_dup[debug_dup_cnt++] = '1'; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "\n %s deltaT is 0\n", __func__); - } else { - dfs->dfs_rinfo.rn_last_unique_ts = re.re_ts; - debug_dup[debug_dup_cnt++] = '0'; - } + dfs_calculate_timestamps(dfs, &re, &this_ts); - if (debug_dup_cnt >= 32) - debug_dup_cnt = 0; - - if (re.re_ts <= dfs->dfs_rinfo.rn_last_ts) { - dfs->dfs_rinfo.rn_ts_prefix += - (((uint64_t) 1) << DFS_TSSHIFT); - /* Now, see if it's been more than 1 wrap */ - deltafull_ts = re.re_full_ts - - dfs->dfs_rinfo.rn_lastfull_ts; - if (deltafull_ts > - ((uint64_t)((DFS_TSMASK - - dfs->dfs_rinfo.rn_last_ts) - + 1 + re.re_ts))) - deltafull_ts -= (DFS_TSMASK - - dfs->dfs_rinfo.rn_last_ts) + 1 + - re.re_ts; - deltafull_ts = deltafull_ts >> DFS_TSSHIFT; - - if (deltafull_ts > 1) { - dfs->dfs_rinfo.rn_ts_prefix += - ((deltafull_ts - 1) << - DFS_TSSHIFT); - } - } else { - deltafull_ts = re.re_full_ts - - dfs->dfs_rinfo.rn_lastfull_ts; - if (deltafull_ts > (uint64_t) DFS_TSMASK) { - deltafull_ts = - deltafull_ts >> DFS_TSSHIFT; - dfs->dfs_rinfo.rn_ts_prefix += - ((deltafull_ts - 1) << DFS_TSSHIFT); - } - } - } - - /* - * At this stage rn_ts_prefix has either been blanked or - * calculated, so it's safe to use. - */ - this_ts = dfs->dfs_rinfo.rn_ts_prefix | ((uint64_t) re.re_ts); - dfs->dfs_rinfo.rn_lastfull_ts = re.re_full_ts; - dfs->dfs_rinfo.rn_last_ts = re.re_ts; - - /* - * The hardware returns the duration in a variety of formats, - * so it's converted from the hardware format to TSF (usec) - * values here. - * XXX TODO: this should really be done when the PHY error - * is processed, rather than way out here.. - */ re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur); - /* - * Calculate the start of the radar pulse. - * - * The TSF is stamped by the MAC upon reception of the event, - * which is (typically?) at the end of the event. But the - * pattern matching code expects the event timestamps to be at - * the start of the event. So to fake it, we subtract the pulse - * duration from the given TSF. This is done after the 64-bit - * timestamp has been calculated so long pulses correctly - * under-wrap the counter. Ie, if this was done on the 32 - * (or 15!) bit TSF when the TSF value is closed to 0, it will - * underflow to 0xfffffXX, which would mess up the logical "OR" - * operation done above. - * This isn't valid for Peregrine as the hardware gives us the - * actual TSF offset of the radar event, not just the MAC TSF - * of the completed receive. - * - * XXX TODO: ensure that the TLV PHY error processing code will - * correctly calculate the TSF to be the start of the radar - * pulse. - * - * XXX TODO TODO: modify the TLV parsing code to subtract the - * duration from the TSF, based on the current fast clock value. - */ - if ((!dfs->dfs_caps.wlan_chip_is_bb_tlv) && re.re_dur != 1) - this_ts -= re.re_dur; + dfs_add_to_pulseline(dfs, &re, &this_ts, &test_ts, &diff_ts); - /* Save the pulse parameters in the pulse buffer(pulse line). */ - index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK; + dfs_log_event(dfs, &re, this_ts, diff_ts); - if (pl->pl_numelems == DFS_MAX_PULSE_BUFFER_SIZE) - pl->pl_firstelem = (pl->pl_firstelem+1) & - DFS_MAX_PULSE_BUFFER_MASK; - else - pl->pl_numelems++; + dfs_conditional_clear_delaylines(dfs, diff_ts); - pl->pl_lastelem = index; - pl->pl_elems[index].p_time = this_ts; - pl->pl_elems[index].p_dur = re.re_dur; - pl->pl_elems[index].p_rssi = re.re_rssi; - diff_ts = (uint32_t)this_ts - test_ts; - test_ts = (uint32_t)this_ts; - - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu\n", - (uint32_t)this_ts, re.re_dur, - re.re_rssi, diff_ts, - (uint64_t)pl->pl_elems[index].p_time); - - if (dfs->dfs_event_log_on) { - i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE; - dfs->radar_log[i].ts = this_ts; - dfs->radar_log[i].diff_ts = diff_ts; - dfs->radar_log[i].rssi = re.re_rssi; - dfs->radar_log[i].dur = re.re_dur; - dfs->radar_log[i].seg_id = re.re_seg_id; - dfs->radar_log[i].sidx = re.re_sidx; - dfs->radar_log[i].freq_offset_khz = - re.re_freq_offset_khz; - dfs->radar_log[i].peak_mag = re.re_peak_mag; - dfs->radar_log[i].total_gain = re.re_total_gain; - dfs->radar_log[i].mb_gain = re.re_mb_gain; - dfs->radar_log[i].relpwr_db = re.re_relpwr_db; - dfs->radar_log[i].is_chirp = DFS_EVENT_NOTCHIRP(&re) ? - 0 : 1; - dfs->dfs_event_log_count++; - } - - /* If diff_ts is very small, we might be getting false pulse - * detects due to heavy interference. We might be getting - * spectral splatter from adjacent channel. In order to prevent - * false alarms we clear the delay-lines. This might impact - * positive detections under harsh environments, but helps with - * false detects. - */ - - if (diff_ts < 100) { - dfs_reset_alldelaylines(dfs); - dfs_reset_radarq(dfs); - } found = 0; - - /* BIN5 pulses are FCC and Japan specific. */ - if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || - (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { - for (p = 0; (p < dfs->dfs_rinfo.rn_numbin5radars) && - (!found); p++) { - struct dfs_bin5radars *br; - - br = &(dfs->dfs_b5radars[p]); - if (dfs_bin5_check_pulse(dfs, &re, br)) { - /* - * This is a valid Bin5 pulse, check if - * it belongs to a burst. - */ - re.re_dur = - dfs_retain_bin5_burst_pattern(dfs, - diff_ts, re.re_dur); - /* - * Remember our computed duration for - * the next pulse in the burst - * (if needed). - */ - dfs->dfs_rinfo.dfs_bin5_chirp_ts = - this_ts; - dfs->dfs_rinfo.dfs_last_bin5_dur = - re.re_dur; - - if (dfs_bin5_addpulse(dfs, br, &re, - this_ts)) { - found |= dfs_bin5_check(dfs); - } - } else - DFS_DPRINTK(dfs, - WLAN_DEBUG_DFS_BIN5_PULSE, - "%s not a BIN5 pulse (dur=%d)\n", - __func__, re.re_dur); - } - } - + dfs_check_if_bin5(dfs, &re, this_ts, diff_ts, &found); if (found) { - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS, - "%s: Found bin5 radar\n", __func__); - retval |= found; - goto dfsfound; + *retval |= found; + return 1; } - tabledepth = 0; - rf = NULL; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - " *** chan freq (%d): ts %llu dur %u rssi %u\n", - rs->rs_chan.dfs_ch_freq, - (uint64_t)this_ts, - re.re_dur, - re.re_rssi); + dfs_check_if_nonbin5(dfs, &re, rs, this_ts, diff_ts, &found, + retval); - while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && - ((dfs->dfs_radartable[re.re_dur])[tabledepth] != - -1) && (!retval)) { - ft = dfs->dfs_radarf[((dfs->dfs_radartable[re.re_dur]) - [tabledepth])]; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - " ** RD (%d): ts %x dur %u rssi %u\n", - rs->rs_chan.dfs_ch_freq, - re.re_ts, - re.re_dur, - re.re_rssi); - - if (re.re_rssi < ft->ft_rssithresh && re.re_dur > 4) { - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "%s : Rejecting on rssi rssi=%u thresh=%u\n", - __func__, - re.re_rssi, - ft->ft_rssithresh); - tabledepth++; - WLAN_DFSQ_LOCK(dfs); - empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); - WLAN_DFSQ_UNLOCK(dfs); - continue; - } - deltaT = this_ts - ft->ft_last_ts; - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "deltaT = %lld (ts: 0x%llx) (last ts: 0x%llx)\n", - (uint64_t)deltaT, - (uint64_t)this_ts, - (uint64_t)ft->ft_last_ts); - - if ((deltaT < ft->ft_minpri) && (deltaT != 0)) { - /* - * This check is for the whole filter type. - * Individual filters will check this again. - * This is first line of filtering. - */ - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS2, - "%s: Rejecting on pri pri=%lld minpri=%u\n", - __func__, - (uint64_t)deltaT, - ft->ft_minpri); - tabledepth++; - continue; - } - - __dfs_process_radarevent(dfs, ft, rf, &re, this_ts, - &found); - ft->ft_last_ts = this_ts; - retval |= found; - if (found) { - DFS_PRINTK( - "Found on channel minDur = %d, filterId = %d\n", - ft->ft_mindur, - rf != NULL ? rf->rf_pulseid : -1); - } - tabledepth++; - } - WLAN_DFSQ_LOCK(dfs); - empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); - WLAN_DFSQ_UNLOCK(dfs); + dfs_is_radarq_empty(dfs, &empty); } + + return 0; +} + +int dfs_process_radarevent( + struct wlan_dfs *dfs, + struct dfs_ieee80211_channel *chan) +{ + struct dfs_state *rs = NULL; + uint8_t seg_id = 0; + int retval = 0; + + if (!dfs_radarevent_basic_sanity(dfs, chan)) + return 0; + /* + * TEST : Simulate radar bang, make sure we add the channel to NOL + * (bug 29968) + */ + if (dfs_handle_bangradar(dfs, chan, &rs, &seg_id, &retval)) + goto dfsfound; + + if (!dfs_handle_missing_pulses(dfs, chan)) + return 0; + + dfs_process_each_radarevent(dfs, chan, &rs, &seg_id, &retval); + dfsfound: - if (retval) { - - /* - * TODO: Instead of discarding the radar, create a workqueue - * if the channel change is happenning through userspace and - * process the radar event once the channel change is completed. - */ - - /* Collect stats */ - dfs->wlan_dfs_stats.num_radar_detects++; - thischan = &rs->rs_chan; - if ((seg_id == SEG_ID_SECONDARY) && - (dfs_is_precac_timer_running(dfs))) { - dfs->is_radar_during_precac = 1; - DFS_PRINTK( - "Radar found on second segment VHT80 freq=%d MHz\n", - dfs->dfs_precac_secondary_freq); - } else { - DFS_PRINTK( - "Radar found on channel %d (%d MHz)\n", - thischan->dfs_ch_ieee, thischan->dfs_ch_freq); - } - - /* - * If event log is on then dump the radar event queue on - * filter match. This can be used to collect information - * on false radar detection. - */ - if (dfs->dfs_event_log_on) - dfs_print_radar_events(dfs); - - dfs_reset_radarq(dfs); - dfs_reset_alldelaylines(dfs); - - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "Primary channel freq = %u flags=0x%x\n", - chan->dfs_ch_freq, chan->dfs_ch_flagext); - - if (chan->dfs_ch_freq != thischan->dfs_ch_freq) - DFS_DPRINTK(dfs, WLAN_DEBUG_DFS1, - "Ext channel freq = %u flags=0x%x\n", - thischan->dfs_ch_freq, - thischan->dfs_ch_flagext); - - dfs->dfs_phyerr_freq_min = 0x7fffffff; - dfs->dfs_phyerr_freq_max = 0; - dfs->dfs_phyerr_w53_counter = 0; - if (seg_id == SEG_ID_SECONDARY) { - dfs->wlan_dfs_stats.num_seg_two_radar_detects++; - dfs->is_radar_found_on_secondary_seg = 1; - } - } + if (retval) + dfs_radarfound_reset_vars(dfs, rs, chan, seg_id); return retval; } diff --git a/umac/dfs/core/src/filtering/dfs_radar.c b/umac/dfs/core/src/filtering/dfs_radar.c index 08132852de..2416cbd835 100644 --- a/umac/dfs/core/src/filtering/dfs_radar.c +++ b/umac/dfs/core/src/filtering/dfs_radar.c @@ -247,6 +247,32 @@ struct dfs_pulse dfs_korea_radars[] = { #define TARGET_TYPE_QCA9888 12 #define RSSI_THERSH_AR900B 15 +/** + * dfs_assign_fcc_pulse_table() - Assign FCC pulse table + * @rinfo: Pointer to wlan_dfs_radar_tab_info structure. + * @target_type: Target type. + */ +static inline void dfs_assign_fcc_pulse_table( + struct wlan_dfs_radar_tab_info *rinfo, + uint32_t target_type) +{ + rinfo->dfs_radars = dfs_fcc_radars; + rinfo->numradars = QDF_ARRAY_SIZE(dfs_fcc_radars); + + if (target_type == TARGET_TYPE_AR900B || + target_type == TARGET_TYPE_IPQ4019) { + rinfo->b5pulses = dfs_fcc_bin5pulses_ar900b; + rinfo->numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses_ar900b); + } else if (target_type == TARGET_TYPE_QCA9984 || + target_type == TARGET_TYPE_QCA9888) { + rinfo->b5pulses = dfs_fcc_bin5pulses_qca9984; + rinfo->numb5radars = + QDF_ARRAY_SIZE(dfs_fcc_bin5pulses_qca9984); + } else { + rinfo->b5pulses = dfs_fcc_bin5pulses; + rinfo->numb5radars = QDF_ARRAY_SIZE(dfs_fcc_bin5pulses); + } +} void ol_if_dfs_configure(struct wlan_dfs *dfs) { struct wlan_dfs_radar_tab_info rinfo; @@ -284,24 +310,7 @@ void ol_if_dfs_configure(struct wlan_dfs *dfs) rinfo.b5pulses = NULL; rinfo.numb5radars = 0; } else { - rinfo.dfs_radars = dfs_fcc_radars; - rinfo.numradars = QDF_ARRAY_SIZE(dfs_fcc_radars); - - if (target_type == TARGET_TYPE_AR900B || - target_type == TARGET_TYPE_IPQ4019) { - rinfo.b5pulses = dfs_fcc_bin5pulses_ar900b; - rinfo.numb5radars = QDF_ARRAY_SIZE( - dfs_fcc_bin5pulses_ar900b); - } else if (target_type == TARGET_TYPE_QCA9984 || - target_type == TARGET_TYPE_QCA9888) { - rinfo.b5pulses = dfs_fcc_bin5pulses_qca9984; - rinfo.numb5radars = QDF_ARRAY_SIZE( - dfs_fcc_bin5pulses_qca9984); - } else { - rinfo.b5pulses = dfs_fcc_bin5pulses; - rinfo.numb5radars = - QDF_ARRAY_SIZE(dfs_fcc_bin5pulses); - } + dfs_assign_fcc_pulse_table(&rinfo, target_type); } break; diff --git a/umac/dfs/core/src/filtering/dfs_staggered.c b/umac/dfs/core/src/filtering/dfs_staggered.c index 507923cb32..663e3e7fe0 100644 --- a/umac/dfs/core/src/filtering/dfs_staggered.c +++ b/umac/dfs/core/src/filtering/dfs_staggered.c @@ -164,8 +164,13 @@ int dfs_staggered_check(struct wlan_dfs *dfs, struct dfs_filter *rf, delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; refpri = dl->dl_elems[delayindex].de_time; - if ((score[n] >= highestscore) && (dfs_is_unique_pri(highestpri, - midpri, lowestpri, refpri))) { + if (!dfs_is_unique_pri(highestpri, + midpri, + lowestpri, + refpri)) + continue; + + if (score[n] >= highestscore) { lowestscore = midscore; lowestpri = midpri; lowestscoreindex = midscoreindex; @@ -175,25 +180,17 @@ int dfs_staggered_check(struct wlan_dfs *dfs, struct dfs_filter *rf, highestscore = score[n]; highestpri = refpri; highestscoreindex = n; - } else { - if ((score[n] >= midscore) && - (dfs_is_unique_pri(highestpri, midpri, - lowestpri, refpri)) - ) { - lowestscore = midscore; - lowestpri = midpri; - lowestscoreindex = midscoreindex; - midscore = score[n]; - midpri = refpri; - midscoreindex = n; - } else if ((score[n] >= lowestscore) && - (dfs_is_unique_pri(highestpri, midpri, - lowestpri, refpri)) - ) { - lowestscore = score[n]; - lowestpri = refpri; - lowestscoreindex = n; - } + } else if (score[n] >= midscore) { + lowestscore = midscore; + lowestpri = midpri; + lowestscoreindex = midscoreindex; + midscore = score[n]; + midpri = refpri; + midscoreindex = n; + } else if (score[n] >= lowestscore) { + lowestscore = score[n]; + lowestpri = refpri; + lowestscoreindex = n; } } diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index 2ed33b85bd..9b2d3d4674 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/umac/dfs/core/src/misc/dfs.c @@ -233,17 +233,17 @@ int dfs_main_attach(struct wlan_dfs *dfs) } /* Allocate memory for radar table. */ - dfs->dfs_radartable = (int8_t **)qdf_mem_malloc(256*sizeof(int8_t *)); - if (dfs->dfs_radartable == NULL) { + dfs->dfs_ftindextable = (int8_t **)qdf_mem_malloc(256*sizeof(int8_t *)); + if (dfs->dfs_ftindextable == NULL) { DFS_PRINTK( "%s: Cannot allocate memory for radar table\n", __func__); goto bad1; } for (n = 0; n < 256; n++) { - dfs->dfs_radartable[n] = qdf_mem_malloc( + dfs->dfs_ftindextable[n] = qdf_mem_malloc( DFS_MAX_RADAR_OVERLAP*sizeof(int8_t)); - if (dfs->dfs_radartable[n] == NULL) { + if (dfs->dfs_ftindextable[n] == NULL) { DFS_PRINTK( "%s: cannot allocate memory for radar table entry\n", __func__); @@ -290,8 +290,8 @@ int dfs_main_attach(struct wlan_dfs *dfs) return 0; bad2: - qdf_mem_free(dfs->dfs_radartable); - dfs->dfs_radartable = NULL; + qdf_mem_free(dfs->dfs_ftindextable); + dfs->dfs_ftindextable = NULL; bad1: for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { if (dfs->dfs_radarf[n] != NULL) { @@ -391,15 +391,15 @@ void dfs_main_detach(struct wlan_dfs *dfs) } } - if (dfs->dfs_radartable != NULL) { + if (dfs->dfs_ftindextable != NULL) { for (n = 0; n < 256; n++) { - if (dfs->dfs_radartable[n] != NULL) { - qdf_mem_free(dfs->dfs_radartable[n]); - dfs->dfs_radartable[n] = NULL; + if (dfs->dfs_ftindextable[n] != NULL) { + qdf_mem_free(dfs->dfs_ftindextable[n]); + dfs->dfs_ftindextable[n] = NULL; } } - qdf_mem_free(dfs->dfs_radartable); - dfs->dfs_radartable = NULL; + qdf_mem_free(dfs->dfs_ftindextable); + dfs->dfs_ftindextable = NULL; dfs->wlan_dfs_isdfsregdomain = 0; }