qcacmn: Fix false radar detect

Changes related to false radar detection, various WIFI devices leak/send
out calibration signal that is same as radar signal. Added a
second level of check to filter them. Chirping and frequency hopping
radar are excluded from secondary check.
* Added a check for jitter in frequency (sidx) to be within certain limit.
* Added a fractional PRI check.
* Added a check to look for chirp in ETSI type 4  radar.

Change-Id: Iec6e264b0db7fafe4d01f5ded481b22993b2b2ed
CRs-Fixed: 2106960
This commit is contained in:
Shashikala Prabhu 2017-11-01 17:50:15 +05:30 • committed by snandini
commit 4ef75c1c97
12 changed files with 576 additions and 143 deletions

View file

@ -235,6 +235,7 @@
#define DFS_FAST_CLOCK_MULTIPLIER (800/11)
#define DFS_NO_FAST_CLOCK_MULTIPLIER (80)
#define DFS_BIG_SIDX 10000
/**
* Software use: channel interference used for as AR as well as RADAR
@ -284,11 +285,19 @@
* @p_time: Time for start of pulse in usecs.
* @p_dur: Duration of pulse in usecs.
* @p_rssi: RSSI of pulse.
* @p_seg_id: Segment id.
* @p_sidx: Sidx value.
* @p_delta_peak: Delta peak value.
* @p_seq_num: Sequence number.
*/
struct dfs_pulseparams {
uint64_t p_time;
uint8_t p_dur;
uint8_t p_rssi;
uint8_t p_dur;
uint8_t p_rssi;
uint8_t p_seg_id;
int16_t p_sidx;
int8_t p_delta_peak;
uint32_t p_seq_num;
} qdf_packed;
/**
@ -340,6 +349,8 @@ struct dfs_pulseline {
* @re_total_gain: Total gain.
* @re_mb_gain: Mb gain.
* @re_relpwr_db: Relpower in db.
* @re_delta_diff: Delta diff.
* @re_delta_peak: Delta peak.
* @re_list: List of radar events.
*/
struct dfs_event {
@ -352,13 +363,15 @@ struct dfs_event {
uint32_t re_freq;
uint32_t re_freq_lo;
uint32_t re_freq_hi;
u_int re_seg_id;
uint8_t re_seg_id;
int re_sidx;
u_int re_freq_offset_khz;
int re_peak_mag;
int re_total_gain;
int re_mb_gain;
int re_relpwr_db;
uint8_t re_delta_diff;
int8_t re_delta_peak;
STAILQ_ENTRY(dfs_event) re_list;
} qdf_packed;
@ -377,6 +390,9 @@ struct dfs_event {
/* Number of different radar types */
#define DFS_MAX_RADAR_TYPES 32
/* RADAR filter pattern type 1*/
#define WLAN_DFS_RF_PATTERN_TYPE_1 1
/**
* struct dfs_ar_state - DFS AR state structure.
* @ar_prevwidth: Previous width.
@ -401,16 +417,24 @@ struct dfs_ar_state {
/**
* struct dfs_delayelem - Delay Element.
* @de_time: Current "filter" time for start of pulse in usecs.
* @de_dur: Duration of pulse in usecs.
* @de_rssi: Rssi of pulse in dB.
* @de_ts: Time stamp for this delay element.
* @de_time: Current "filter" time for start of pulse in usecs.
* @de_dur: Duration of pulse in usecs.
* @de_rssi: Rssi of pulse in dB.
* @de_ts: Time stamp for this delay element.
* @de_seg_id: Segment id for HT80_80/HT160 use.
* @de_sidx: Sidx value.
* @de_delta_peak: Delta peak.
* @de_seq_num: Sequence number.
*/
struct dfs_delayelem {
uint32_t de_time;
uint8_t de_dur;
uint8_t de_rssi;
uint64_t de_ts;
uint8_t de_seg_id;
int16_t de_sidx;
int8_t de_delta_peak;
uint32_t de_seq_num;
} qdf_packed;
/**
@ -420,6 +444,25 @@ struct dfs_delayelem {
* @dl_firstelem: Index of the first element.
* @dl_lastelem: Index of the last element.
* @dl_numelems: Number of elements in the delay line.
* The following is to handle fractional PRI pulses that can cause false
* detection.
* @dl_seq_num_start: Sequence number of first pulse that was part of
* threshold match.
* @dl_seq_num_stop: Sequence number of last pulse that was part of threshold
* match.
* The following is required because the first pulse may or may not be in the
* delay line but we will find it iin the pulse line using dl_seq_num_second's
* diff_ts value.
* @dl_seq_num_second: Sequence number of second pulse that was part of
* threshold match.
* @dl_search_pri: We need final search PRI to identify possible fractional
* PRI issue.
* @dl_min_sidx: Minimum sidx value of pulses used to match thershold.
* Used for sidx spread check.
* @dl_max_sidx: Maximum sidx value of pulses used to match thershold.
* Used for sidx spread check.
* @dl_delta_peak_match_count: Number of pulse in the delay line that had valid
* delta peak value.
*/
struct dfs_delayline {
struct dfs_delayelem dl_elems[DFS_MAX_DL_SIZE];
@ -427,6 +470,13 @@ struct dfs_delayline {
uint32_t dl_firstelem;
uint32_t dl_lastelem;
uint32_t dl_numelems;
uint32_t dl_seq_num_start;
uint32_t dl_seq_num_stop;
uint32_t dl_seq_num_second;
uint32_t dl_search_pri;
int16_t dl_min_sidx;
int8_t dl_max_sidx;
uint8_t dl_delta_peak_match_count;
} qdf_packed;
/**
@ -443,6 +493,12 @@ struct dfs_delayline {
* @rf_maxdur: Max duration for this radar filter.
* @rf_ignore_pri_window: Ignore pri window.
* @rf_pulseid: Unique ID corresponding to the original filter ID.
* To reduce false detection, look at frequency spread. For now we will use
* sidx spread. But for HT160 frequency spread will be a better measure.
* @rf_sidx_spread: Maximum SIDX value spread in a matched sequence
* excluding FCC Bin 5.
* @rf_check_delta_peak: Minimum allowed delta_peak value for a pulse to be
* considetred for this filter's match.
*/
struct dfs_filter {
struct dfs_delayline rf_dl;
@ -457,6 +513,8 @@ struct dfs_filter {
uint32_t rf_maxdur;
uint32_t rf_ignore_pri_window;
uint32_t rf_pulseid;
uint16_t rf_sidx_spread;
int8_t rf_check_delta_peak;
} qdf_packed;
/**
@ -652,6 +710,8 @@ struct dfs_stats {
* @total_gain: Total gain.
* @mb_gain: Mb gain.
* @relpwr_db: Relpower in db.
* @delta_diff: Delta diff.
* @delta_peak: Delta peak.
*/
struct dfs_event_log {
@ -660,13 +720,15 @@ struct dfs_event_log {
uint8_t rssi;
uint8_t dur;
int is_chirp;
u_int seg_id;
uint8_t seg_id;
int sidx;
u_int freq_offset_khz;
int peak_mag;
int total_gain;
int mb_gain;
int relpwr_db;
uint8_t delta_diff;
int8_t delta_peak;
};
#define WLAN_DFS_RESET_TIME_S 7
@ -761,6 +823,7 @@ struct dfs_event_log {
* the radar type.
* @wlan_dfs_nol_timeout: NOL timeout.
* @update_nol: Update NOL.
* @dfs_seq_num: Sequence number.
* @dfs_nol_event[]: NOL event.
* @dfs_nol_timer: NOL list processing.
* @dfs_cac_timer: CAC timer.
@ -849,6 +912,7 @@ struct wlan_dfs {
int dfs_pri_multiplier;
int wlan_dfs_nol_timeout;
bool update_nol;
uint32_t dfs_seq_num;
int dfs_nol_event[IEEE80211_CHAN_MAX];
os_timer_t dfs_nol_timer;
os_timer_t dfs_cac_timer;
@ -887,6 +951,8 @@ struct wlan_dfs {
* @WLAN_DEBUG_DFS_BIN5_FFT: BIN5 FFT check.
* @WLAN_DEBUG_DFS_BIN5_PULSE: BIN5 pulse check.
* @WLAN_DEBUG_DFS_FALSE_DET: False detection debug related prints.
* @WLAN_DEBUG_DFS_FALSE_DET2: Second level check to confirm poisitive
* detection.
* @WLAN_DEBUG_DFS_RANDOM_CHAN: Random channel selection.
*/
enum {
@ -902,7 +968,8 @@ enum {
WLAN_DEBUG_DFS_BIN5_FFT = 0x00020000,
WLAN_DEBUG_DFS_BIN5_PULSE = 0x00040000,
WLAN_DEBUG_DFS_FALSE_DET = 0x00080000,
WLAN_DEBUG_DFS_RANDOM_CHAN = 0x00100000,
WLAN_DEBUG_DFS_FALSE_DET2 = 0x00100000,
WLAN_DEBUG_DFS_RANDOM_CHAN = 0x00200000,
WLAN_DEBUG_DFS_MAX = 0x80000000,
WLAN_DEBUG_DFS_ALWAYS = WLAN_DEBUG_DFS_MAX
};
@ -930,6 +997,8 @@ enum {
* @total_gain: Total gain.
* @mb_gain: Mb gain.
* @relpwr_db: Relpower in DB.
* @pulse_delta_diff: Pulse delta diff.
* @pulse_delta_peak: Pulse delta peak.
*
* Chirp notes!
*
@ -990,13 +1059,15 @@ struct dfs_phy_err {
uint32_t freq_hi;
uint8_t rssi;
uint8_t dur;
u_int seg_id;
uint8_t seg_id;
int sidx;
u_int freq_offset_khz;
int peak_mag;
int total_gain;
int mb_gain;
int relpwr_db;
uint8_t pulse_delta_diff;
int8_t pulse_delta_peak;
};
/**
@ -1886,7 +1957,8 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs,
struct dfs_filtertype *ft,
struct dfs_event *re,
uint64_t this_ts,
int *found);
int *found,
int *false_radar_found);
/**
* bin5_rules_check_internal() - This is a extension of dfs_bin5_check().

View file

@ -93,6 +93,16 @@ struct wlan_dfs_caps {
* rssi 3dBm. lower than in non TURBO mode. This
* will be used to offset that diff.
* @rp_ignore_pri_window: Ignore PRI window.
* @rp_sidx_spread: To reduce false detection use sidx spread. For HT160,
* for consistency, push all pulses at center of the
* channel to 80MHz ext when both segments are DFS.
* Maximum SIDX value spread in a matched sequence
* excluding FCC Bin 5.
* @rp_check_delta_peak: This is mainly used for ETSI Type 4 5MHz chirp pulses
* which HW cnanot identify.
* Reliably as chirping but can correctly characterize
* these with delta_peak non-zero.
* Is delta_peak check required for this filter.
* @rp_pulseid: Unique ID for identifying filter.
*/
struct dfs_pulse {
@ -109,7 +119,9 @@ struct dfs_pulse {
uint32_t rp_meanoffset;
int32_t rp_rssimargin;
uint32_t rp_ignore_pri_window;
uint32_t rp_pulseid;
uint16_t rp_sidx_spread;
int8_t rp_check_delta_peak;
uint16_t rp_pulseid;
};
/**

View file

@ -45,25 +45,25 @@
struct dfs_pulse ar5416_etsi_radars[] = {
/* TYPE staggered pulse */
/* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */
{20, 2, 300, 400, 2, 30, 4, 0, 2, 15, 0, 0, 0, 31},
{20, 2, 300, 400, 2, 30, 4, 0, 2, 15, 0, 0, 0, 0, 0, 31},
/* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */
{30, 2, 400, 1200, 2, 30, 7, 0, 2, 15, 0, 0, 0, 32},
{30, 2, 400, 1200, 2, 30, 7, 0, 2, 15, 0, 0, 0, 0, 0, 32},
/* constant PRF based */
/* 0.8-5us, 200 300 PRF, 10 pulses */
{10, 5, 200, 400, 0, 24, 5, 0, 8, 18, 0, 0, 0, 33},
{10, 5, 400, 600, 0, 24, 5, 0, 8, 18, 0, 0, 0, 37},
{10, 5, 600, 800, 0, 24, 5, 0, 8, 18, 0, 0, 0, 38},
{10, 5, 800, 1000, 0, 24, 5, 0, 8, 18, 0, 0, 0, 39},
{10, 5, 200, 400, 0, 24, 5, 0, 8, 18, 0, 0, 0, 0, 0, 33},
{10, 5, 400, 600, 0, 24, 5, 0, 8, 18, 0, 0, 0, 0, 0, 37},
{10, 5, 600, 800, 0, 24, 5, 0, 8, 18, 0, 0, 0, 0, 0, 38},
{10, 5, 800, 1000, 0, 24, 5, 0, 8, 18, 0, 0, 0, 0, 0, 39},
/* 0.8-15us, 200-1600 PRF, 15 pulses */
{15, 15, 200, 1600, 0, 24, 6, 0, 18, 15, 0, 0, 0, 34},
{15, 15, 200, 1600, 0, 24, 6, 0, 18, 15, 0, 0, 0, 0, 0, 34},
/* 0.8-15us, 2300-4000 PRF, 25 pulses*/
{25, 15, 2300, 4000, 0, 24, 8, 0, 18, 15, 0, 0, 0, 35},
{25, 15, 2300, 4000, 0, 24, 8, 0, 18, 15, 0, 0, 0, 0, 0, 35},
/* 20-30us, 2000-4000 PRF, 20 pulses*/
{20, 30, 2000, 4000, 0, 24, 8, 19, 33, 15, 0, 0, 0, 36},
{20, 30, 2000, 4000, 0, 24, 8, 19, 33, 15, 0, 0, 0, 0, 0, 36},
};
/**
@ -73,28 +73,28 @@ struct dfs_pulse ar5416_etsi_radars[] = {
struct dfs_pulse ar5416_fcc_radars[] = {
/* following two filters are specific to Japan/MKK4 */
/* 1389 +/- 6 us */
{18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17},
{18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 0, 0, 17},
/* 4000 +/- 6 us */
{18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18},
{18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 0, 0, 18},
/* 3846 +/- 7 us */
{18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 0, 19},
{18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 0, 0, 0, 19},
/* following filters are common to both FCC and JAPAN */
/* FCC TYPE 1 */
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0},
{18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0},
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0, 0, 0},
{18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0, 0, 0},
/* FCC TYPE 6 */
{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 0, 1},
{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 0, 0, 0, 1},
/* FCC TYPE 2 */
{23, 5, 4347, 6666, 0, 18, 11, 0, 7, 20, 0, 3, 0, 2},
{23, 5, 4347, 6666, 0, 18, 11, 0, 7, 20, 0, 3, 0, 0, 0, 2},
/* FCC TYPE 3 */
{18, 10, 2000, 5000, 0, 23, 8, 6, 13, 20, 0, 3, 0, 5},
{18, 10, 2000, 5000, 0, 23, 8, 6, 13, 20, 0, 3, 0, 0, 0, 5},
/* FCC TYPE 4 */
{16, 15, 2000, 5000, 0, 25, 7, 11, 23, 20, 0, 3, 0, 11},
{16, 15, 2000, 5000, 0, 25, 7, 11, 23, 20, 0, 3, 0, 0, 0, 11},
};
/**

View file

@ -60,30 +60,30 @@ struct dfs_pulse ar9300_etsi_radars[] = {
/* TYPE staggered pulse */
/* Type 5*/
/* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */
{30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31},
{30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 0, 0, 31},
/* Type 6 */
/* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */
{30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32},
{30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 0, 0, 32},
/* constant PRF based */
/* Type 1 */
/* 0.8-5us, 200 300 PRF, 10 pulses */
{10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33},
{10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37},
{10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38},
{10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39},
{10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 33},
{10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 37},
{10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 38},
{10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 0, 0, 39},
/* Type 2 */
/* 0.8-15us, 200-1600 PRF, 15 pulses */
{15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 34},
{15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 0, 0, 34},
/* Type 3 */
/* 0.8-15us, 2300-4000 PRF, 25 pulses*/
{25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 35},
{25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 0, 0, 35},
/* Type 4 */
/* 20-30us, 2000-4000 PRF, 20 pulses*/
{20, 30, 2000, 4000, 0, 24, 8, 19, 33, 24, 0, 0, 0, 36},
{20, 30, 2000, 4000, 0, 24, 8, 19, 33, 24, 0, 0, 0, 0, 0, 36},
};
/**
@ -99,42 +99,42 @@ struct dfs_pulse ar9300_fcc_radars[] = {
/* following two filters are specific to Japan/MKK4 */
/* 1389 +/- 6 us */
{18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17},
{18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 0, 0, 17},
/* 4000 +/- 6 us */
{18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18},
{18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 0, 0, 18},
/* 3846 +/- 7 us */
{18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19},
{18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 0, 0, 19},
/* 3846 +/- 7 us */
{18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 20},
{18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 1, 0, 0, 20},
/* following filters are common to both FCC and JAPAN */
/* FCC TYPE 1 */
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 8},
{18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0},
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0, 0, 8},
{18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0, 0, 0},
/* FCC TYPE 6 */
{9, 1, 3003, 3003, 0, 7, 5, 0, 1, 18, 0, 0, 1, 1},
{9, 1, 3003, 3003, 0, 7, 5, 0, 1, 18, 0, 0, 1, 0, 0, 1},
/* FCC TYPE 2 */
{23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2},
{23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 0, 0, 2},
/* FCC TYPE 3 */
{18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5},
{18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 0, 0, 5},
/* FCC TYPE 4 */
{16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11},
{16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 0, 0, 11},
/* FCC NEW TYPE 1 */
/* Search duration is numpulses*maxpri.
* The last theshold can be increased if false detects happen
*/
/* 518us to 938us pulses (min 56 pulses) */
{57, 1, 1066, 1930, 0, 6, 20, 0, 1, 22, 0, 3, 0, 21},
{57, 1, 1066, 1930, 0, 6, 20, 0, 1, 22, 0, 3, 0, 0, 0, 21},
/* 938us to 2000 pulses (min 26 pulses) */
{27, 1, 500, 1066, 0, 6, 13, 0, 1, 22, 0, 3, 0, 22},
{27, 1, 500, 1066, 0, 6, 13, 0, 1, 22, 0, 3, 0, 0, 0, 22},
/* 2000 to 3067us pulses (min 17 pulses)*/
{18, 1, 325, 500, 0, 6, 9, 0, 1, 22, 0, 3, 0, 23},
{18, 1, 325, 500, 0, 6, 9, 0, 1, 22, 0, 3, 0, 0, 0, 23},
};
@ -150,13 +150,13 @@ struct dfs_bin5pulse ar9300_bin5pulses[] = {
*/
struct dfs_pulse ar9300_korea_radars[] = {
/* Korea Type 1 */
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 40},
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0, 0, 40},
/* Korea Type 2 */
{10, 1, 1800, 1800, 0, 6, 4, 0, 1, 18, 0, 3, 1, 41},
{10, 1, 1800, 1800, 0, 6, 4, 0, 1, 18, 0, 3, 1, 0, 0, 41},
/* Korea Type 3 */
{70, 1, 330, 330, 0, 6, 20, 0, 2, 18, 0, 3, 1, 42},
{70, 1, 330, 330, 0, 6, 20, 0, 2, 18, 0, 3, 1, 0, 0, 42},
/* Korea Type 4 */
{3, 1, 3003, 3003, 1, 7, 2, 0, 1, 18, 0, 0, 1, 43},
{3, 1, 3003, 3003, 1, 7, 2, 0, 1, 18, 0, 0, 1, 0, 0, 43},
};
void dfs_get_radars_for_ar9300(struct wlan_dfs *dfs)

View file

@ -289,6 +289,10 @@ void dfs_add_pulse(
window = deltaT;
dl->dl_elems[index].de_dur = re->re_dur;
dl->dl_elems[index].de_rssi = re->re_rssi;
dl->dl_elems[index].de_seg_id = re->re_seg_id;
dl->dl_elems[index].de_sidx = re->re_sidx;
dl->dl_elems[index].de_delta_peak = re->re_delta_peak;
dl->dl_elems[index].de_seq_num = dfs->dfs_seq_num;
dfs_debug(dfs, WLAN_DEBUG_DFS2,
"adding: filter id %d, dur=%d, rssi=%d, ts=%llu",
@ -670,6 +674,35 @@ int dfs_bin_check(
return found;
}
/**
* dfs_update_min_and_max_sidx() - Calculate min and max sidx.
* @dl: Pointer to dfs_delayline structure.
* @delayindex: Delay index.
* @sidx_min: Sidx min.
* @sidx_max: Sidx max.
* @delta_peak_match_count: Delta peak match count.
* @rf: Pointer to dfs_filter structure.
*/
static inline void dfs_update_min_and_max_sidx(
struct dfs_delayline *dl,
int delayindex,
int32_t *sidx_min,
int32_t *sidx_max,
uint8_t *delta_peak_match_count,
struct dfs_filter *rf)
{
/* update sidx min/max for false detection check later */
if (*sidx_min > dl->dl_elems[delayindex].de_sidx)
*sidx_min = dl->dl_elems[delayindex].de_sidx;
if (*sidx_max < dl->dl_elems[delayindex].de_sidx)
*sidx_max = dl->dl_elems[delayindex].de_sidx;
if ((rf->rf_check_delta_peak) &&
(dl->dl_elems[delayindex].de_delta_peak != 0))
(*delta_peak_match_count)++;
}
/**
* dfs_check_pulses_for_delta_variance() - Check pulses for delta variance.
* @rf: Pointer to dfs_filter structure.
@ -678,6 +711,11 @@ int dfs_bin_check(
* @fundamentalpri: Highest PRI.
* @primargin: Primary margin.
* @numpulses: Number of pulses.
* @delayindex: Delay index.
* @sidx_min: Sidx min.
* @sidx_max: Sidx max.
* @delta_peak_match_count: Delta peak match count.
* @dl: Pointer to dfs_delayline structure.
*/
static inline void dfs_check_pulses_for_delta_variance(
struct dfs_filter *rf,
@ -685,7 +723,12 @@ static inline void dfs_check_pulses_for_delta_variance(
uint32_t delta_time_stamps,
int fundamentalpri,
uint32_t primargin,
int *numpulses)
int *numpulses,
int delayindex,
int32_t *sidx_min,
int32_t *sidx_max,
uint8_t *delta_peak_match_count,
struct dfs_delayline *dl)
{
uint32_t delta_ts_variance, j;
@ -693,6 +736,12 @@ static inline void dfs_check_pulses_for_delta_variance(
delta_ts_variance = DFS_DIFF(delta_time_stamps,
((j + 1) * fundamentalpri));
if (delta_ts_variance < (2 * (j + 1) * primargin)) {
dl->dl_seq_num_stop =
dl->dl_elems[delayindex].de_seq_num;
dfs_update_min_and_max_sidx(dl, delayindex,
sidx_min, sidx_max,
delta_peak_match_count,
rf);
(*numpulses)++;
if (rf->rf_ignore_pri_window > 0)
break;
@ -731,6 +780,9 @@ static void dfs_count_the_other_delay_elements(
uint32_t searchpri, searchdur, deltadur, deltapri1, deltapri2;
uint32_t j = 0, delta_time_stamps, deltapri;
int dindex, primatch, numpulsetochk = 2;
int32_t sidx_min = DFS_BIG_SIDX;
int32_t sidx_max = -DFS_BIG_SIDX;
uint8_t delta_peak_match_count = 1;
delayindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
searchpri = dl->dl_elems[delayindex].de_time;
@ -764,6 +816,12 @@ static void dfs_count_the_other_delay_elements(
if (primatch && (deltadur < durmargin)) {
if ((*numpulses == 1)) {
dl->dl_seq_num_second =
dl->dl_elems[delayindex].de_seq_num;
dfs_update_min_and_max_sidx(dl, delayindex,
&sidx_min, &sidx_max,
&delta_peak_match_count,
rf);
(*numpulses)++;
} else {
delta_time_stamps = (dl->dl_elems[delayindex].de_ts -
@ -780,9 +838,16 @@ static void dfs_count_the_other_delay_elements(
dfs_check_pulses_for_delta_variance(rf, numpulsetochk,
delta_time_stamps, fundamentalpri,
primargin, numpulses);
primargin, numpulses, delayindex,
&sidx_min, &sidx_max,
&delta_peak_match_count,
dl);
}
*prev_good_timestamp = dl->dl_elems[delayindex].de_ts;
dl->dl_search_pri = searchpri;
dl->dl_min_sidx = sidx_min;
dl->dl_max_sidx = sidx_max;
dl->dl_delta_peak_match_count = delta_peak_match_count;
dfs_debug(dfs, WLAN_DEBUG_DFS2,
"rf->minpri=%d rf->maxpri=%d searchpri = %d index = %d numpulses = %d deltapri=%d j=%d",

View file

@ -25,13 +25,16 @@ void dfs_print_delayline(struct wlan_dfs *dfs, struct dfs_delayline *dl)
int i = 0, index;
struct dfs_delayelem *de;
index = dl->dl_lastelem;
index = dl->dl_firstelem;
for (i = 0; i < dl->dl_numelems; i++) {
de = &dl->dl_elems[index];
dfs_debug(dfs, WLAN_DEBUG_DFS2,
"Elem %d: ts = %u (0x%x) dur=%u",
i, de->de_time, de->de_time, de->de_dur);
index = (index - 1) & DFS_MAX_DL_MASK;
"Elem %u: ts=%llu diff_ts=%u (0x%x) dur=%u, seg_id=%d sidx=%d delta_peak=%d seq_num=%d",
i, de->de_ts, de->de_time, de->de_time,
de->de_dur, de->de_seg_id, de->de_sidx,
de->de_delta_peak, de->de_seq_num);
index = (index + 1) & DFS_MAX_DL_MASK;
}
}

View file

@ -296,6 +296,8 @@ int dfs_init_radar_filters(struct wlan_dfs *dfs,
rf->rf_numpulses = numpulses;
rf->rf_patterntype = dfs_radars[p].rp_patterntype;
rf->rf_sidx_spread = dfs_radars[p].rp_sidx_spread;
rf->rf_check_delta_peak = dfs_radars[p].rp_check_delta_peak;
rf->rf_pulseid = dfs_radars[p].rp_pulseid;
rf->rf_mindur = dfs_radars[p].rp_mindur;
rf->rf_maxdur = dfs_radars[p].rp_maxdur;

View file

@ -702,6 +702,8 @@ int dfs_process_phyerr_bb_tlv(struct wlan_dfs *dfs,
e->total_gain = rs.agc_total_gain;
e->mb_gain = rs.agc_mb_gain;
e->relpwr_db = rsfr.relpwr_db;
e->pulse_delta_peak = rs.delta_peak;
e->pulse_delta_diff = rs.delta_diff;
dfs_debug(dfs, WLAN_DEBUG_DFS_PHYERR_SUM,
"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",
@ -714,12 +716,14 @@ int dfs_process_phyerr_bb_tlv(struct wlan_dfs *dfs,
(int) abs(e->freq_hi) % 1000);
dfs_debug(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",
"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, delta_peak=%d, delta_diff=%d",
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,
rsfr.relpwr_db);
rsfr.relpwr_db,
rs.delta_peak,
rs.delta_diff);
return 1;
}

View file

@ -809,6 +809,8 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen,
event->re_total_gain = e.total_gain;
event->re_mb_gain = e.mb_gain;
event->re_relpwr_db = e.relpwr_db;
event->re_delta_diff = e.pulse_delta_diff;
event->re_delta_peak = e.pulse_delta_peak;
/* Handle chirp flags. */
if (e.do_check_chirp) {
event->re_flags |= DFS_EVENT_CHECKCHIRP;

View file

@ -31,6 +31,10 @@
#define DFS_MAX_FREQ_SPREAD (1375 * 1)
#define DFS_LARGE_PRI_MULTIPLIER 4
#define DFS_W53_DEFAULT_PRI_MULTIPLIER 2
#define DFS_INVALID_PRI_LIMIT 100 /* should we use 135? */
#define DFS_BIG_SIDX 10000
#define FRAC_PRI_SCORE_ARRAY_SIZE 40
static char debug_dup[33];
static int debug_dup_cnt;
@ -104,7 +108,7 @@ static void dfs_print_radar_events(struct wlan_dfs *dfs)
for (i = 0; (i < DFS_EVENT_LOG_SIZE) && (i < dfs->dfs_event_log_count);
i++) {
dfs_debug(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",
"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, delta_diff=%d, delta_peak=%d",
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,
@ -114,7 +118,9 @@ static void dfs_print_radar_events(struct wlan_dfs *dfs)
dfs->radar_log[i].peak_mag,
dfs->radar_log[i].total_gain,
dfs->radar_log[i].mb_gain,
dfs->radar_log[i].relpwr_db);
dfs->radar_log[i].relpwr_db,
dfs->radar_log[i].delta_diff,
dfs->radar_log[i].delta_peak);
}
dfs->dfs_event_log_count = 0;
dfs->dfs_phyerr_count = 0;
@ -124,6 +130,163 @@ static void dfs_print_radar_events(struct wlan_dfs *dfs)
dfs->dfs_phyerr_freq_max = 0;
}
/**
* dfs_confirm_radar() - This function checks for fractional PRI and jitter in
* sidx index to determine if the radar is real or not.
* @dfs: Pointer to dfs structure.
* @rf: Pointer to dfs_filter structure.
* @ext_chan_flag: ext chan flags.
*/
static int dfs_confirm_radar(struct wlan_dfs *dfs,
struct dfs_filter *rf,
int ext_chan_flag)
{
int i = 0;
int index;
struct dfs_delayline *dl = &rf->rf_dl;
struct dfs_delayelem *de;
uint64_t target_ts = 0;
struct dfs_pulseline *pl;
int start_index = 0, current_index, next_index;
unsigned char scores[FRAC_PRI_SCORE_ARRAY_SIZE];
uint32_t pri_margin;
uint64_t this_diff_ts;
uint32_t search_bin;
unsigned char max_score = 0;
int max_score_index = 0;
pl = dfs->pulses;
OS_MEMZERO(scores, sizeof(scores));
scores[0] = rf->rf_threshold;
pri_margin = dfs_get_pri_margin(dfs, ext_chan_flag,
(rf->rf_patterntype == 1));
/*
* Look for the entry that matches dl_seq_num_second.
* we need the time stamp and diff_ts from there.
*/
for (i = 0; i < dl->dl_numelems; i++) {
index = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK;
de = &dl->dl_elems[index];
if (dl->dl_seq_num_second == de->de_seq_num)
target_ts = de->de_ts - de->de_time;
}
if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS2) {
dfs_print_delayline(dfs, &rf->rf_dl);
/* print pulse line */
dfs_debug(dfs, WLAN_DEBUG_DFS2,
"%s: Pulse Line\n", __func__);
for (i = 0; i < pl->pl_numelems; i++) {
index = (pl->pl_firstelem + i) &
DFS_MAX_PULSE_BUFFER_MASK;
dfs_debug(dfs, WLAN_DEBUG_DFS2,
"Elem %u: ts=%llu dur=%u, seq_num=%d, delta_peak=%d\n",
i, pl->pl_elems[index].p_time,
pl->pl_elems[index].p_dur,
pl->pl_elems[index].p_seq_num,
pl->pl_elems[index].p_delta_peak);
}
}
/*
* Walk through the pulse line and find pulse with target_ts.
* Then continue until we find entry with seq_number dl_seq_num_stop.
*/
for (i = 0; i < pl->pl_numelems; i++) {
index = (pl->pl_firstelem + i) & DFS_MAX_PULSE_BUFFER_MASK;
if (pl->pl_elems[index].p_time == target_ts) {
dl->dl_seq_num_start = pl->pl_elems[index].p_seq_num;
start_index = index; /* save for future use */
}
}
dfs_debug(dfs, WLAN_DEBUG_DFS2,
"%s: target_ts=%llu, dl_seq_num_start=%d, dl_seq_num_second=%d, dl_seq_num_stop=%d\n",
__func__, target_ts, dl->dl_seq_num_start,
dl->dl_seq_num_second, dl->dl_seq_num_stop);
current_index = start_index;
while (pl->pl_elems[current_index].p_seq_num < dl->dl_seq_num_stop) {
next_index = (current_index + 1) & DFS_MAX_PULSE_BUFFER_MASK;
this_diff_ts = pl->pl_elems[next_index].p_time -
pl->pl_elems[current_index].p_time;
/* Now update the score for this diff_ts */
for (i = 1; i < FRAC_PRI_SCORE_ARRAY_SIZE; i++) {
search_bin = dl->dl_search_pri / (i + 1);
/*
* We do not give score to PRI that is lower then the
* limit.
*/
if (search_bin < DFS_INVALID_PRI_LIMIT)
break;
/*
* Increment the score if this_diff_ts belongs to this
* search_bin +/- margin.
*/
if ((this_diff_ts >= (search_bin - pri_margin)) &&
(this_diff_ts <=
(search_bin + pri_margin))) {
/*increment score */
scores[i]++;
}
}
current_index = next_index;
}
for (i = 0; i < FRAC_PRI_SCORE_ARRAY_SIZE; i++)
if (scores[i] > max_score) {
max_score = scores[i];
max_score_index = i;
}
if (max_score_index != 0) {
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
"%s: Rejecting Radar since Fractional PRI detected: searchpri=%d, threshold=%d, fractional PRI=%d, Fractional PRI score=%d\n",
__func__, dl->dl_search_pri, scores[0],
dl->dl_search_pri/(max_score_index + 1),
max_score);
return 0;
}
/* Check for frequency spread */
if (dl->dl_min_sidx > pl->pl_elems[start_index].p_sidx)
dl->dl_min_sidx = pl->pl_elems[start_index].p_sidx;
if (dl->dl_max_sidx < pl->pl_elems[start_index].p_sidx)
dl->dl_max_sidx = pl->pl_elems[start_index].p_sidx;
if ((dl->dl_max_sidx - dl->dl_min_sidx) > rf->rf_sidx_spread) {
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
"%s: Rejecting Radar since frequency spread is too large : min_sidx=%d, max_sidx=%d, rf_sidx_spread=%d\n",
__func__, dl->dl_min_sidx, dl->dl_max_sidx,
rf->rf_sidx_spread);
return 0;
}
if ((rf->rf_check_delta_peak) &&
((dl->dl_delta_peak_match_count) <
rf->rf_threshold)) {
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
"%s: Rejecting Radar since delta peak values are invalid : dl_delta_peak_match_count=%d, rf_threshold=%d\n",
__func__, dl->dl_delta_peak_match_count,
rf->rf_threshold);
return 0;
}
return 1;
}
/*
* dfs_reject_on_pri() - Rejecting on individual filter based on min PRI .
* @dfs: Pointer to wlan_dfs structure.
@ -182,11 +345,36 @@ static inline bool dfs_reject_on_pri(
return 0;
}
/**
* dfs_confirm_radar_check() - Do additioal check to conirm radar except for
* the staggered, chirp FCC Bin 5, frequency hopping indicated by
* rf_patterntype == 1.
* @dfs: Pointer to wlan_dfs structure.
* @rf: Pointer to dfs_filter structure.
* @ext_chan_event_flag: Extension channel event flag
* @found: Pointer to radar found flag (return value).
* @false_radar_found: Pointer to false radar found (return value).
*/
static inline void dfs_confirm_radar_check(
struct wlan_dfs *dfs,
struct dfs_filter *rf,
int ext_chan_event_flag,
int *found,
int *false_radar_found)
{
if (rf->rf_patterntype != 1) {
*found = dfs_confirm_radar(dfs, rf, ext_chan_event_flag);
*false_radar_found = (*found == 1) ? 0 : 1;
}
}
void __dfs_process_radarevent(struct wlan_dfs *dfs,
struct dfs_filtertype *ft,
struct dfs_event *re,
uint64_t this_ts,
int *found)
int *found,
int *false_radar_found)
{
int p;
uint64_t deltaT = 0;
@ -194,7 +382,7 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs,
struct dfs_filter *rf = NULL;
for (p = 0, *found = 0; (p < ft->ft_numfilters) &&
(!(*found)); p++) {
(!(*found)) && !(*false_radar_found); p++) {
rf = &(ft->ft_filters[p]);
if ((re->re_dur >= rf->rf_mindur) &&
(re->re_dur <= rf->rf_maxdur)) {
@ -223,9 +411,18 @@ void __dfs_process_radarevent(struct wlan_dfs *dfs,
*found = dfs_bin_check(dfs, rf,
(uint32_t) deltaT, re->re_dur,
ext_chan_event_flag);
if (*found)
dfs_confirm_radar_check(dfs,
rf, ext_chan_event_flag,
found,
false_radar_found);
}
if (dfs->dfs_debug_mask & WLAN_DEBUG_DFS2)
dfs_print_delayline(dfs, &rf->rf_dl);
if (rf->rf_patterntype !=
WLAN_DFS_RF_PATTERN_TYPE_1)
dfs_print_delayline(dfs, &rf->rf_dl);
rf->rf_dl.dl_last_ts = this_ts;
}
@ -300,6 +497,7 @@ static inline void dfs_radarfound_reset_vars(
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;
@ -494,14 +692,17 @@ static inline void dfs_return_event_to_eventq(
* @re: Pointer to dfs_event re
* @this_ts: Current time stamp 64bit
* @diff_ts: Difference between 2 timestamps 32bit
* @index: Index value.
*/
static inline void dfs_log_event(
struct wlan_dfs *dfs,
struct dfs_event *re,
uint64_t this_ts,
uint32_t diff_ts)
uint32_t diff_ts,
uint32_t index)
{
uint8_t i;
struct dfs_pulseline *pl = dfs->pulses;
if (dfs->dfs_event_log_on) {
i = dfs->dfs_event_log_count % DFS_EVENT_LOG_SIZE;
@ -517,10 +718,15 @@ static inline void dfs_log_event(
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].delta_diff = (*re).re_delta_diff;
dfs->radar_log[i].delta_peak = (*re).re_delta_peak;
dfs->radar_log[i].is_chirp = DFS_EVENT_NOTCHIRP(re) ?
0 : 1;
dfs->dfs_event_log_count++;
}
dfs->dfs_seq_num++;
pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num;
}
/**
@ -532,6 +738,7 @@ static inline void dfs_log_event(
* @diff_ts: Difference between 2 timestamps 32bit
* @found: Pointer to found. If radar found or not.
* @retval: Pointer to retval(return value).
* @false_radar_found: Pointer to false_radar_found(return value).
*/
static inline void dfs_check_if_nonbin5(
struct wlan_dfs *dfs,
@ -540,7 +747,8 @@ static inline void dfs_check_if_nonbin5(
uint64_t this_ts,
uint32_t diff_ts,
int *found,
int *retval)
int *retval,
int *false_radar_found)
{
uint32_t tabledepth = 0;
@ -554,7 +762,7 @@ static inline void dfs_check_if_nonbin5(
while ((tabledepth < DFS_MAX_RADAR_OVERLAP) &&
((dfs->dfs_ftindextable[(*re).re_dur])[tabledepth] !=
-1) && (!*retval)) {
-1) && (!*retval) && !(*false_radar_found)) {
ft = dfs->dfs_radarf[((dfs->dfs_ftindextable[(*re).re_dur])
[tabledepth])];
dfs_debug(dfs, WLAN_DEBUG_DFS2,
@ -590,7 +798,8 @@ static inline void dfs_check_if_nonbin5(
continue;
}
__dfs_process_radarevent(dfs, ft, re, this_ts, found);
__dfs_process_radarevent(dfs, ft, re, this_ts, found,
false_radar_found);
ft->ft_last_ts = this_ts;
*retval |= *found;
@ -813,16 +1022,18 @@ static inline void dfs_calculate_timestamps(
* 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)
* @this_ts: Pointer to this_ts (this timestamp)
* @diff_ts: Diff ts.
* @index: Pointer to get index value.
*/
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 *diff_ts,
uint32_t *index)
{
uint32_t index;
struct dfs_pulseline *pl;
/*
@ -854,7 +1065,7 @@ static inline void dfs_add_to_pulseline(
pl = dfs->pulses;
/* Save the pulse parameters in the pulse buffer(pulse line). */
index = (pl->pl_lastelem + 1) & DFS_MAX_PULSE_BUFFER_MASK;
*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) &
@ -862,10 +1073,12 @@ static inline void dfs_add_to_pulseline(
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;
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;
pl->pl_elems[*index].p_sidx = (*re).re_sidx;
pl->pl_elems[*index].p_delta_peak = (*re).re_delta_peak;
*diff_ts = (uint32_t)*this_ts - *test_ts;
*test_ts = (uint32_t)*this_ts;
@ -873,19 +1086,26 @@ static inline void dfs_add_to_pulseline(
"ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu",
(uint32_t)*this_ts, (*re).re_dur,
(*re).re_rssi, *diff_ts,
(uint64_t)pl->pl_elems[index].p_time);
(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
* @diff_ts: diff between timerstamps.
* @this_ts: this timestamp value.
* @re: Pointer to dfs_event structure.
*/
static inline void dfs_conditional_clear_delaylines(
struct wlan_dfs *dfs,
uint32_t diff_ts)
uint32_t diff_ts,
uint64_t this_ts,
struct dfs_event re)
{
struct dfs_pulseline *pl = dfs->pulses;
uint32_t index;
/* 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
@ -894,15 +1114,39 @@ static inline void dfs_conditional_clear_delaylines(
* false detects.
*/
if (diff_ts < 100) {
if (diff_ts < DFS_INVALID_PRI_LIMIT) {
dfs->dfs_seq_num = 0;
dfs_reset_alldelaylines(dfs);
dfs_reset_radarq(dfs);
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;
pl->pl_elems[index].p_sidx = re.re_sidx;
pl->pl_elems[index].p_delta_peak = re.re_delta_peak;
dfs->dfs_seq_num++;
pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num;
}
}
/**
* dfs_process_each_radarevent - remove each event from the dfs radar queue
* and process it.
* @dfs: Pointer to wlan_dfs structure.
* @chan: Pointer to DFS current channel.
* @rs: Pointer to dfs_state structure.
* @seg_id: segment id.
* @retval: pointer to retval.
* @false_radar_found: pointer to false radar found.
*
* Return: If radar found then return 1 else return 0.
*/
static inline int dfs_process_each_radarevent(
@ -910,18 +1154,21 @@ static inline int dfs_process_each_radarevent(
struct dfs_ieee80211_channel *chan,
struct dfs_state **rs,
uint8_t *seg_id,
int *retval)
int *retval,
int *false_radar_found)
{
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;
static uint32_t test_ts;
static uint32_t diff_ts;
uint32_t index;
dfs_is_radarq_empty(dfs, &empty);
while ((!empty) && (!*retval) && (events_processed < MAX_EVENTS)) {
while ((!empty) && (!*retval) && !(*false_radar_found) &&
(events_processed < MAX_EVENTS)) {
dfs_remove_event_from_radarq(dfs, &event);
if (!event) {
empty = 1;
@ -943,11 +1190,12 @@ static inline int dfs_process_each_radarevent(
re.re_dur = dfs_process_pulse_dur(dfs, re.re_dur);
dfs_add_to_pulseline(dfs, &re, &this_ts, &test_ts, &diff_ts);
dfs_add_to_pulseline(dfs, &re, &this_ts, &test_ts, &diff_ts,
&index);
dfs_log_event(dfs, &re, this_ts, diff_ts);
dfs_log_event(dfs, &re, this_ts, diff_ts, index);
dfs_conditional_clear_delaylines(dfs, diff_ts);
dfs_conditional_clear_delaylines(dfs, diff_ts, this_ts, re);
found = 0;
dfs_check_if_bin5(dfs, &re, this_ts, diff_ts, &found);
@ -957,7 +1205,7 @@ static inline int dfs_process_each_radarevent(
}
dfs_check_if_nonbin5(dfs, &re, rs, this_ts, diff_ts, &found,
retval);
retval, false_radar_found);
dfs_is_radarq_empty(dfs, &empty);
}
@ -965,6 +1213,22 @@ static inline int dfs_process_each_radarevent(
return 0;
}
/**
* dfs_false_radarfound_reset_vars () - Reset dfs variables after false radar
* found.
* @dfs: Pointer to wlan_dfs structure.
*/
static inline void dfs_false_radarfound_reset_vars(
struct wlan_dfs *dfs)
{
dfs->dfs_seq_num = 0;
dfs_reset_radarq(dfs);
dfs_reset_alldelaylines(dfs);
dfs->dfs_phyerr_freq_min = 0x7fffffff;
dfs->dfs_phyerr_freq_max = 0;
dfs->dfs_phyerr_w53_counter = 0;
}
int dfs_process_radarevent(
struct wlan_dfs *dfs,
struct dfs_ieee80211_channel *chan)
@ -972,6 +1236,7 @@ int dfs_process_radarevent(
struct dfs_state *rs = NULL;
uint8_t seg_id = 0;
int retval = 0;
int false_radar_found = 0;
if (!dfs_radarevent_basic_sanity(dfs, chan))
return 0;
@ -985,11 +1250,15 @@ int dfs_process_radarevent(
if (!dfs_handle_missing_pulses(dfs, chan))
return 0;
dfs_process_each_radarevent(dfs, chan, &rs, &seg_id, &retval);
dfs_process_each_radarevent(dfs, chan, &rs, &seg_id, &retval,
&false_radar_found);
dfsfound:
if (retval)
dfs_radarfound_reset_vars(dfs, rs, chan, seg_id);
if (false_radar_found)
dfs_false_radarfound_reset_vars(dfs);
return retval;
}

View file

@ -31,30 +31,30 @@
*/
struct dfs_pulse dfs_fcc_radars[] = {
/* FCC TYPE 1 */
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0},
{18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0},
{18, 1, 700, 700, 0, 4, 5, 0, 1, 18, 0, 3, 1, 5, 0, 0},
{18, 1, 350, 350, 0, 4, 5, 0, 1, 18, 0, 3, 0, 5, 0, 0},
/* FCC TYPE 6 */
{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1},
{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1000, 0, 1},
/* FCC TYPE 2 */
{23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2},
{23, 5, 4347, 6666, 0, 4, 11, 0, 7, 22, 0, 3, 0, 5, 0, 2},
/* FCC TYPE 3 */
{18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5},
{18, 10, 2000, 5000, 0, 4, 8, 6, 13, 22, 0, 3, 0, 5, 0, 5},
/* FCC TYPE 4 */
{16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11},
{16, 15, 2000, 5000, 0, 4, 7, 11, 23, 22, 0, 3, 0, 5, 0, 11},
/* FCC NEW TYPE 1 */
/* 518us to 938us pulses (min 56 pulses) */
{57, 1, 1066, 1930, 0, 6, 20, 0, 1, 22, 0, 3, 0, 21},
{57, 1, 1066, 1930, 0, 4, 20, 0, 1, 22, 0, 3, 0, 5, 0, 21},
/* 938us to 2000 pulses (min 26 pulses) */
{27, 1, 500, 1066, 0, 6, 13, 0, 1, 22, 0, 3, 0, 22},
{27, 1, 500, 1066, 0, 4, 13, 0, 1, 22, 0, 3, 0, 5, 0, 22},
/* 2000 to 3067us pulses (min 17 pulses) */
{18, 1, 325, 500, 0, 6, 9, 0, 1, 22, 0, 3, 0, 23},
{18, 1, 325, 500, 0, 4, 9, 0, 1, 22, 0, 3, 0, 5, 0, 23},
};
/**
@ -64,31 +64,31 @@ struct dfs_pulse dfs_mkk4_radars[] = {
/* following two filters are specific to Japan/MKK4 */
/* 1389 +/- 6 us */
{18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17},
{18, 1, 720, 720, 0, 4, 6, 0, 1, 18, 0, 3, 0, 5, 0, 17},
/* 4000 +/- 6 us */
{18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18},
{18, 4, 250, 250, 0, 4, 5, 1, 6, 18, 0, 3, 0, 5, 0, 18},
/* 3846 +/- 7 us */
{18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19},
{18, 5, 260, 260, 0, 4, 6, 1, 6, 18, 0, 3, 1, 5, 0, 19},
/* following filters are common to both FCC and JAPAN */
/* FCC TYPE 1 */
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 0},
{18, 1, 350, 350, 0, 6, 5, 0, 1, 18, 0, 3, 0, 0},
{18, 1, 700, 700, 0, 4, 5, 0, 1, 18, 0, 3, 1, 5, 0, 0},
{18, 1, 350, 350, 0, 4, 5, 0, 1, 18, 0, 3, 0, 5, 0, 0},
/* FCC TYPE 6 */
{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1},
{9, 1, 3003, 3003, 1, 7, 5, 0, 1, 18, 0, 0, 1, 1000, 0, 1},
/* FCC TYPE 2 */
{23, 5, 4347, 6666, 0, 18, 11, 0, 7, 22, 0, 3, 0, 2},
{23, 5, 4347, 6666, 0, 4, 11, 0, 7, 22, 0, 3, 0, 5, 0, 2},
/* FCC TYPE 3 */
{18, 10, 2000, 5000, 0, 23, 8, 6, 13, 22, 0, 3, 0, 5},
{18, 10, 2000, 5000, 0, 4, 8, 6, 13, 22, 0, 3, 0, 5, 0, 5},
/* FCC TYPE 4 */
{16, 15, 2000, 5000, 0, 25, 7, 11, 23, 22, 0, 3, 0, 11},
{16, 15, 2000, 5000, 0, 4, 7, 11, 23, 22, 0, 3, 0, 5, 0, 11},
};
/**
@ -96,7 +96,7 @@ struct dfs_pulse dfs_mkk4_radars[] = {
* chipsets.
*/
struct dfs_bin5pulse dfs_fcc_bin5pulses[] = {
{4, 28, 105, 12, 22, 5},
{5, 28, 105, 12, 22, 5},
};
/**
@ -119,7 +119,7 @@ struct dfs_bin5pulse dfs_jpn_bin5pulses[] = {
*/
struct dfs_bin5pulse dfs_fcc_bin5pulses_ar900b[] = {
{4, 28, 105, 12, 20, 5},
{5, 28, 105, 12, 20, 5},
};
/**
@ -141,7 +141,7 @@ struct dfs_bin5pulse dfs_jpn_bin5pulses_ar900b[] = {
* raise the threshold.
*/
struct dfs_bin5pulse dfs_fcc_bin5pulses_qca9984[] = {
{4, 20, 105, 12, 20, 0},
{5, 20, 105, 12, 20, 0},
};
/**
@ -160,30 +160,31 @@ struct dfs_pulse dfs_etsi_radars[] = {
/* TYPE staggered pulse */
/* Type 5*/
/* 0.8-2us, 2-3 bursts,300-400 PRF, 10 pulses each */
{30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 31},
{30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 5, 0, 31},
/* Type 6 */
/* 0.8-2us, 2-3 bursts, 400-1200 PRF, 15 pulses each */
{30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 32},
{30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 5, 0, 32},
/* constant PRF based */
/* Type 1 */
/* 0.8-5us, 200 300 PRF, 10 pulses */
{10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33},
{10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37},
{10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38},
{10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39},
{10, 5, 200, 400, 0, 4, 5, 0, 8, 15, 0, 0, 2, 5, 0, 33},
{10, 5, 400, 600, 0, 4, 5, 0, 8, 15, 0, 0, 2, 5, 0, 37},
{10, 5, 600, 800, 0, 4, 5, 0, 8, 15, 0, 0, 2, 5, 0, 38},
{10, 5, 800, 1000, 0, 4, 5, 0, 8, 15, 0, 0, 2, 5, 0, 39},
/* {10, 5, 200, 1000, 0, 6, 5, 0, 8, 15, 0, 0, 2, 5, 33}, */
/* Type 2 */
/* 0.8-15us, 200-1600 PRF, 15 pulses */
{15, 15, 200, 1600, 0, 24, 8, 0, 18, 24, 0, 0, 0, 34},
{15, 15, 200, 1600, 0, 4, 8, 0, 18, 24, 0, 0, 0, 5, 0, 34},
/* Type 3 */
/* 0.8-15us, 2300-4000 PRF, 25 pulses*/
{25, 15, 2300, 4000, 0, 24, 10, 0, 18, 24, 0, 0, 0, 35},
{25, 15, 2300, 4000, 0, 4, 10, 0, 18, 24, 0, 0, 0, 5, 0, 35},
/* Type 4 */
/* 20-30us, 2000-4000 PRF, 20 pulses*/
{20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 36},
{20, 30, 2000, 4000, 0, 4, 6, 19, 33, 24, 0, 0, 0, 24, 1, 36},
};
/**
@ -229,16 +230,16 @@ struct dfs_pulse dfs_china_radars[] = {
*/
struct dfs_pulse dfs_korea_radars[] = {
/* Korea Type 1 */
{18, 1, 700, 700, 0, 6, 5, 0, 1, 18, 0, 3, 1, 40},
{18, 1, 700, 700, 0, 4, 5, 0, 1, 18, 0, 3, 1, 5, 0, 40},
/* Korea Type 2 */
{10, 1, 1800, 1800, 0, 6, 4, 0, 1, 18, 0, 3, 1, 41},
{10, 1, 1800, 1800, 0, 4, 4, 0, 1, 18, 0, 3, 1, 5, 0, 41},
/* Korea Type 3 */
{70, 1, 330, 330, 0, 6, 20, 0, 2, 18, 0, 3, 1, 42},
{70, 1, 330, 330, 0, 4, 20, 0, 2, 18, 0, 3, 1, 5, 0, 42},
/* Korea Type 4 */
{3, 1, 3003, 3003, 1, 7, 2, 0, 1, 18, 0, 0, 1, 43},
{3, 1, 3003, 3003, 1, 7, 2, 0, 1, 18, 0, 0, 1, 1000, 0, 43},
};
#define RSSI_THERSH_AR900B 15

View file

@ -888,22 +888,25 @@ int dfs_control(struct wlan_dfs *dfs,
for (i = 0; (i < DFS_EVENT_LOG_SIZE) &&
(i < dfs->dfs_event_log_count); i++) {
#define FREQ_OFFSET1 ((int)dfs->radar_log[i].freq_offset_khz / 1000)
#define FREQ_OFFSET2 ((int)abs(dfs->radar_log[i].freq_offset_khz) % 1000)
dfs_debug(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",
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),
dfs->radar_log[i].peak_mag,
dfs->radar_log[i].total_gain,
dfs->radar_log[i].mb_gain,
dfs->radar_log[i].relpwr_db);
"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, delta_diff=%d, delta_peak=%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].sidx,
FREQ_OFFSET1,
FREQ_OFFSET2,
dfs->radar_log[i].peak_mag,
dfs->radar_log[i].total_gain,
dfs->radar_log[i].mb_gain,
dfs->radar_log[i].relpwr_db,
dfs->radar_log[i].delta_diff,
dfs->radar_log[i].delta_peak);
}
dfs->dfs_event_log_count = 0;
dfs->dfs_phyerr_count = 0;