diff options
| author | bings <bings@codeaurora.org> | 2017-09-01 09:33:54 +0800 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-12-18 16:42:00 -0800 |
| commit | aa9b8f1e49d690f46de9658d2761ef616bfe2cae (patch) | |
| tree | 9ec9791db22c2e126189338431e7f788a8409d52 | |
| parent | 0a15a9fae719c13ba230a17246cc633bc2767a04 (diff) | |
qcacld-3.0: Changes related to false radar detection
Various WIFI devices leak/send out calibration signal that is
same as radar signal. We have added a second level of check to
filter them. Chirping and frequency hopping radar are excluded
from secondary check.
>We check for jitter in frequency (sidx)to be within certain limit
>We have a fractional PRI check
>We add a check to look for chirp in ETSI type 4 radar
CRs-Fixed: 2103710
Change-Id: I3ff14b9beed4382e2144c434ffa16b989b97a93f
| -rw-r--r-- | Kbuild | 4 | ||||
| -rw-r--r-- | core/sap/dfs/inc/ath_dfs_structs.h | 18 | ||||
| -rw-r--r-- | core/sap/dfs/inc/dfs.h | 60 | ||||
| -rw-r--r-- | core/sap/dfs/inc/radar_filters.h | 93 | ||||
| -rw-r--r-- | core/sap/dfs/src/dfs_bindetects.c | 43 | ||||
| -rw-r--r-- | core/sap/dfs/src/dfs_init.c | 2 | ||||
| -rw-r--r-- | core/sap/dfs/src/dfs_phyerr_tlv.c | 2 | ||||
| -rw-r--r-- | core/sap/dfs/src/dfs_process_phyerr.c | 2 | ||||
| -rw-r--r-- | core/sap/dfs/src/dfs_process_radarevent.c | 226 | ||||
| -rw-r--r-- | core/wma/src/wma_features.c | 7 |
10 files changed, 401 insertions, 56 deletions
@@ -1570,6 +1570,10 @@ ifeq ($(CONFIG_ARCH_SDX20), y) CDEFINES += -DSYNC_IPA_READY endif +ifeq ($(CONFIG_ARCH_SDX20), y) +CDEFINES += -DWLAN_DFS_FALSE_DETECT +endif + ifeq ($(CONFIG_ARCH_MSM8996), y) CDEFINES += -DCHANNEL_HOPPING_ALL_BANDS endif diff --git a/core/sap/dfs/inc/ath_dfs_structs.h b/core/sap/dfs/inc/ath_dfs_structs.h index 83c0655262ca..1a046b28819b 100644 --- a/core/sap/dfs/inc/ath_dfs_structs.h +++ b/core/sap/dfs/inc/ath_dfs_structs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -119,7 +119,21 @@ struct dfs_pulse { * diff. */ uint32_t rp_ignore_pri_window; - uint32_t rp_pulseid; /* Unique ID for identifying filter */ + /** + * 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 matchedsequence excluding FCC Bin 5. + */ + uint16_t rp_sidx_spread; + /** + * 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. It is disabled by default currently. + * Is delta_peak check required for this filter. + */ + int8_t rp_check_delta_peak; + uint16_t rp_pulseid; /* Unique ID for identifying filter */ }; struct dfs_staggered_pulse { diff --git a/core/sap/dfs/inc/dfs.h b/core/sap/dfs/inc/dfs.h index 0fea16d7fc4e..6353c7e8e769 100644 --- a/core/sap/dfs/inc/dfs.h +++ b/core/sap/dfs/inc/dfs.h @@ -237,6 +237,8 @@ enum { #define DFS_ETSI_TYPE3_WAR_PRI_UPPER_LIMIT 435 #define DFS_ETSI_WAR_VALID_PULSE_DURATION 15 +#define DFS_BIG_SIDX 10000 + typedef qdf_spinlock_t dfsq_lock_t; #ifdef WIN32 @@ -244,8 +246,12 @@ typedef qdf_spinlock_t dfsq_lock_t; #endif struct dfs_pulseparams { uint64_t p_time; /* time for start of pulse in usecs */ - uint8_t p_dur; /* Duration of pulse in usecs */ - uint8_t p_rssi; /* Duration of pulse in usecs */ + uint8_t p_dur; /* Duration of pulse in usecs */ + uint8_t p_rssi; /* Duration of pulse in usecs */ + uint8_t p_seg_id; + int16_t p_sidx; + int8_t p_delta_peak; + uint32_t p_seq_num; } qdf_packed; #ifdef WIN32 #pragma pack(pop, dfs_pulseparams) @@ -329,7 +335,7 @@ struct dfs_event { uint32_t re_freq; uint32_t re_freq_lo; uint32_t re_freq_hi; - int sidx; + uint16_t sidx; int radar_80p80_segid; uint8_t delta_peak; uint8_t delta_diff; @@ -387,6 +393,10 @@ struct dfs_delayelem { uint8_t de_rssi; /* time stamp for this delay element */ uint64_t de_ts; + uint8_t de_seg_id; /* HT80_80/HT160 use */ + int16_t de_sidx; + int8_t de_delta_peak; + uint32_t de_seq_num; } qdf_packed; #ifdef WIN32 #pragma pack(pop, dfs_delayelem) @@ -408,6 +418,35 @@ struct dfs_delayline { uint32_t dl_lastelem; /* Number of elements in the delay line */ uint32_t dl_numelems; + /** + * The following is to handle fractional PRI pulses that can cause false + * detection + * sequence number of first pulse that was part of threshold match + */ + uint32_t dl_seq_num_start; + /* sequence number of last pulse that was part of threshold match */ + uint32_t dl_seq_num_stop; + /** + * The following is required because the first pulse may or may not be + * in the delay line but we will find it in the pulse line using + * dl_seq_num_second's diff_ts value + * sequence number of sesecond pulse that was part of threshold match + */ + uint32_t dl_seq_num_second; + /* we need final search PRI to identify possible fractional PRI issue */ + uint32_t dl_search_pri; + /** + * minimum sidx value of pulses used to match thershold. used for sidx + * spread check + */ + int16_t dl_min_sidx; + /** + * maximum sidx value of pulses used to match thershold. used for sidx + * spread check + */ + int8_t dl_max_sidx; + /* number of pulse in the delay line that had valid delta peak value */ + uint8_t dl_delta_peak_match_count; } qdf_packed; #ifdef WIN32 #pragma pack(pop, dfs_delayline) @@ -442,6 +481,18 @@ struct dfs_filter { uint32_t rf_ignore_pri_window; /* Unique ID corresponding to the original filter ID */ uint32_t rf_pulseid; + /** + * 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. + * Maximum SIDX value spread in a matched sequence excluding FCC Bin 5 + */ + uint16_t rf_sidx_spread; + /** + * Minimum allowed delta_peak value for a pulse to be considetred for + * this filter's match + */ + int8_t rf_check_delta_peak; } qdf_packed; #ifdef WIN32 #pragma pack(pop, dfs_filter) @@ -702,6 +753,7 @@ struct ath_dfs { int8_t disable_dfs_ch_switch; uint32_t test_ts; /* to capture timestamps on primary segment */ uint32_t test_ts_ext_seg; /* to capture timestamps on ext segment */ + u_int32_t dfs_seq_num; }; /* This should match the table from if_ath.c */ @@ -819,6 +871,8 @@ struct dfs_phy_err { int peak_mag; /* Radar summary report version */ int rsu_version; + uint8_t pulse_delta_diff; + int8_t pulse_delta_peak; }; /* Attach, detach, handle ioctl prototypes */ diff --git a/core/sap/dfs/inc/radar_filters.h b/core/sap/dfs/inc/radar_filters.h index 0d1b6563ea50..e2b014aa4629 100644 --- a/core/sap/dfs/inc/radar_filters.h +++ b/core/sap/dfs/inc/radar_filters.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -42,39 +42,39 @@ struct dfs_pulse dfs_fcc_radars[] = { /* FCC NEW TYPE 0 */ /* {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 */ - {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, 6, 5, 0, 1, 18, 0, 3, 1, 5, 0, 0}, + {18, 1, 350, 350, 0, 6, 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}, // 333 +/- 7 us */ - {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, 8, 0, 7, 22, 0, 3, 0, 2}, + {23, 5, 4347, 6666, 0, 18, 8, 0, 7, 22, 0, 3, 0, 5, 0, 2}, /* FCC TYPE 3 */ - {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 22, 0, 3, 0, 5}, + {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 22, 0, 3, 0, 5, 0, 5}, /* FCC TYPE 4 */ - {16, 15, 2000, 5000, 0, 25, 5, 11, 23, 22, 0, 3, 0, 11}, + {16, 15, 2000, 5000, 0, 25, 5, 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, 6, 20, 0, 1, 22, 0, 3, 0, 5, 0, 21}, /* * FCC NEW TYPE 1 * 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, 5, 0, 22}, /* * FCC NEW TYPE 1 * 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, 5, 0, 23}, }; struct dfs_pulse dfs_mkk4_radars[] = { @@ -82,33 +82,36 @@ struct dfs_pulse dfs_mkk4_radars[] = { /* {18, 1, 720, 720, 1, 6, 6, 0, 1, 18, 0, 3, 17}, // 1389 +/- 6 us */ /* {18, 4, 250, 250, 1, 10, 5, 1, 6, 18, 0, 3, 18}, // 4000 +/- 6 us */ /* {18, 5, 260, 260, 1, 10, 6, 1, 6, 18, 0, 3, 19}, // 3846 +/- 7 us */ - {18, 1, 720, 720, 0, 6, 6, 0, 1, 18, 0, 3, 0, 17}, /* 1389 +/- 6 us */ - {18, 4, 250, 250, 0, 10, 5, 1, 6, 18, 0, 3, 0, 18}, /* 4000 +/- 6 us */ - {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 19}, /* 3846 +/- 7 us */ + /* 1389 +/- 6 us */ + {18, 1, 720, 720, 0, 6, 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, 5, 0, 18}, + /* 3846 +/- 7 us */ + {18, 5, 260, 260, 0, 10, 6, 1, 6, 18, 0, 3, 1, 5, 0, 19}, /* following filters are common to both FCC and JAPAN */ /* FCC TYPE 1 */ /* {18, 1, 325, 1930, 0, 6, 7, 0, 1, 18, 0, 3, 0}, // 518 to 3066 */ - {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, 6, 5, 0, 1, 18, 0, 3, 1, 5, 0, 0}, + {18, 1, 350, 350, 0, 6, 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}, // 333 +/- 7 us */ - {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, 8, 0, 7, 22, 0, 3, 0, 2}, + {23, 5, 4347, 6666, 0, 18, 8, 0, 7, 22, 0, 3, 0, 5, 0, 2}, /* FCC TYPE 3 */ - {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 22, 0, 3, 0, 5}, + {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 22, 0, 3, 0, 5, 0, 5}, /* FCC TYPE 4 */ - {16, 15, 2000, 5000, 0, 25, 5, 11, 23, 22, 0, 3, 0, 11}, + {16, 15, 2000, 5000, 0, 25, 5, 11, 23, 22, 0, 3, 0, 5, 0, 11}, }; struct dfs_bin5pulse dfs_fcc_bin5pulses[] = { - {4, 28, 105, 12, 17, 5}, + {5, 28, 105, 12, 17, 5}, }; struct dfs_bin5pulse dfs_jpn_bin5pulses[] = { @@ -119,77 +122,81 @@ struct dfs_pulse dfs_etsi_radars[] = { /* TYPE staggered pulse */ /* 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}, /* Type 5 */ + /* Type 5 */ + {30, 2, 300, 400, 2, 30, 3, 0, 5, 15, 0, 0, 1, 5, 0, 31}, /* Type 5 */ /* 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}, /* Type 6 */ + {30, 2, 400, 1200, 2, 30, 7, 0, 5, 15, 0, 0, 0, 5, 0, 32}, /* Type 6 */ /* constant PRF based */ /* 0.8-5us, 200 300 PRF, 10 pulses */ - {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, /* Type 1 */ - {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 37}, /* Type 1 */ - {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 38}, /* Type 1 */ - {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 39}, /* Type 1 */ + {10, 5, 200, 400, 0, 24, 5, 0, 8, 15, 0, 0, 2, 5, 0, 33}, /* Type 1 */ + {10, 5, 400, 600, 0, 24, 5, 0, 8, 15, 0, 0, 2, 5, 0, 37}, /* Type 1 */ + {10, 5, 600, 800, 0, 24, 5, 0, 8, 15, 0, 0, 2, 5, 0, 38}, /* Type 1 */ + {10, 5, 800, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 5, 0, 39}, /* Type 1 */ /* {10, 5, 200, 1000, 0, 24, 5, 0, 8, 15, 0, 0, 2, 33}, */ /* 0.8-15us, 200-1600 PRF, 15 pulses */ - {15, 15, 200, 1600, 0, 24, 8, 0, 18, 22, 0, 0, 0, 34}, /* Type 2 */ + /* Type 2 */ + {15, 15, 200, 1600, 0, 24, 8, 0, 18, 22, 0, 0, 0, 5, 0, 34}, /* 0.8-15us, 2300-4000 PRF, 25 pulses */ - {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 22, 0, 0, 0, 35}, /* Type 3 */ + /* Type 3 */ + {25, 15, 2300, 4000, 0, 24, 10, 0, 18, 22, 0, 0, 0, 5, 0, 35}, /* 20-30us, 2000-4000 PRF, 20 pulses */ - {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 36}, /* Type 4 */ + /* Type 4 */ + {20, 30, 2000, 4000, 0, 24, 6, 19, 33, 24, 0, 0, 0, 24, 0, 36}, }; 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, 6, 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, 6, 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, 6, 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}, }; struct dfs_pulse dfs_china_radars[] = { /* FCC NEW TYPE 0 */ - {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, 6, 5, 0, 1, 18, 0, 3, 1, 5, 0, 0}, + {18, 1, 350, 350, 0, 6, 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, 8, 0, 7, 22, 0, 3, 0, 2}, + {23, 5, 4347, 6666, 0, 18, 8, 0, 7, 22, 0, 3, 0, 5, 0, 2}, /* FCC TYPE 3 */ - {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 22, 0, 3, 0, 5}, + {18, 10, 2000, 5000, 0, 23, 6, 6, 13, 22, 0, 3, 0, 5, 0, 5}, /* FCC TYPE 4 */ - {16, 15, 2000, 5000, 0, 25, 5, 11, 23, 22, 0, 3, 0, 11}, + {16, 15, 2000, 5000, 0, 25, 5, 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, 6, 20, 0, 1, 22, 0, 3, 0, 5, 0, 21}, /* * FCC NEW TYPE 1 * 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, 5, 0, 22}, /* * FCC NEW TYPE 1 * 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, 5, 0, 23}, /* CN TYPE 1 */ - {20, 1, 1000, 1000, 0, 6, 5, 0, 1, 18, 0, 3, 1, 24}, + {20, 1, 1000, 1000, 0, 6, 5, 0, 1, 18, 0, 3, 1, 1000, 0, 24}, }; diff --git a/core/sap/dfs/src/dfs_bindetects.c b/core/sap/dfs/src/dfs_bindetects.c index b5c45a4aea7a..f88c1e864728 100644 --- a/core/sap/dfs/src/dfs_bindetects.c +++ b/core/sap/dfs/src/dfs_bindetects.c @@ -178,6 +178,10 @@ dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, 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->radar_80p80_segid; + dl->dl_elems[index].de_sidx = re->sidx; + dl->dl_elems[index].de_delta_peak = re->delta_peak; + dl->dl_elems[index].de_seq_num = dfs->dfs_seq_num; DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: adding: filter id %d, dur=%d, rssi=%d, ts=%llu\n", @@ -368,6 +372,12 @@ dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, score, highscoreindex = 0; int numpulses = 1; /* first pulse in the burst is most likely being filtered out based on maxfilterlen */ int priscorechk = 1, numpulsetochk = 2, primatch = 0; + int32_t sidx_min = DFS_BIG_SIDX; + int32_t sidx_max = -DFS_BIG_SIDX; + uint8_t delta_peak_match_num = 1; + int8_t de_delta_peak = 0; + int16_t de_sidx = 0; + uint32_t de_seq_num = 0; /* Use the adjusted PRI margin to reduce false alarms */ /* For non fixed pattern types, rf->rf_patterntype=0 */ @@ -436,6 +446,9 @@ dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, } searchdur = dl->dl_elems[delayindex].de_dur; searchrssi = dl->dl_elems[delayindex].de_rssi; + de_sidx = dl->dl_elems[delayindex].de_sidx; + de_delta_peak = dl->dl_elems[delayindex].de_delta_peak; + de_seq_num = dl->dl_elems[delayindex].de_seq_num; deltadur = DFS_DIFF(searchdur, refdur); deltapri = DFS_DIFF(searchpri, refpri); @@ -460,6 +473,18 @@ dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, if (primatch && (deltadur < durmargin)) { if (numpulses == 1) { numpulses++; + dl->dl_seq_num_second = de_seq_num; + /** + * update sidx min/max for false detection + * check later + */ + if (sidx_min > de_sidx) + sidx_min = de_sidx; + if (sidx_max < de_sidx) + sidx_max = de_sidx; + if ((rf->rf_check_delta_peak) && + (de_delta_peak != 0)) + delta_peak_match_num++; } else { delta_time_stamps = dl->dl_elems[delayindex].de_ts - @@ -483,6 +508,19 @@ dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, if (delta_ts_variance < (2 * (j + 1) * primargin)) { numpulses++; + dl->dl_seq_num_stop = + de_seq_num; + /** + * update sidx min/max for + * false detection check + */ + if (sidx_min > de_sidx) + sidx_min = de_sidx; + if (sidx_max < de_sidx) + sidx_max = de_sidx; + if ((rf->rf_check_delta_peak) && + (de_delta_peak != 0)) + delta_peak_match_num++; if (rf->rf_ignore_pri_window > 0) { break; @@ -491,7 +529,10 @@ dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, } } 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_num; DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "rf->minpri=%d rf->maxpri=%d searchpri = %d index = %d numpulses = %d deltapri=%d j=%d\n", rf->rf_minpri, rf->rf_maxpri, searchpri, i, diff --git a/core/sap/dfs/src/dfs_init.c b/core/sap/dfs/src/dfs_init.c index 12cb49b9caa3..70fd9202a7bc 100644 --- a/core/sap/dfs/src/dfs_init.c +++ b/core/sap/dfs/src/dfs_init.c @@ -344,6 +344,8 @@ int dfs_init_radar_filters(struct ieee80211com *ic, 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; diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.c b/core/sap/dfs/src/dfs_phyerr_tlv.c index 4316ddbbac52..32438fe41be2 100644 --- a/core/sap/dfs/src/dfs_phyerr_tlv.c +++ b/core/sap/dfs/src/dfs_phyerr_tlv.c @@ -870,6 +870,8 @@ dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, uint16_t datalen, e->is_ext = 0; e->is_dc = 0; e->is_early = 0; + e->pulse_delta_peak = rs.delta_peak; + e->pulse_delta_diff = rs.delta_diff; /* * Copy the segment ID from the radar summary report diff --git a/core/sap/dfs/src/dfs_process_phyerr.c b/core/sap/dfs/src/dfs_process_phyerr.c index 079c4d0acbc0..5ee708b8f1a2 100644 --- a/core/sap/dfs/src/dfs_process_phyerr.c +++ b/core/sap/dfs/src/dfs_process_phyerr.c @@ -850,6 +850,8 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, event->re_ts = (e.rs_tstamp) & DFS_TSMASK; event->re_rssi = e.rssi; event->sidx = e.sidx; + event->delta_diff = e.pulse_delta_diff; + event->delta_peak = e.pulse_delta_peak; if (e.rsu_version == DFS_RADAR_SUMMARY_REPORT_VERSION_3) { event->delta_peak = e.delta_peak; diff --git a/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c index 143a7e1d3815..9321720f27ef 100644 --- a/core/sap/dfs/src/dfs_process_radarevent.c +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -62,6 +62,10 @@ #define DFS_MAX_FREQ_SPREAD 1375 * 1 +#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; @@ -102,6 +106,168 @@ static inline uint8_t dfs_process_pulse_dur(struct ath_dfs *dfs, uint8_t re_dur) return (uint8_t) dfs_round((int32_t) ((dfs->dur_multiplier) * re_dur)); } +#ifdef WLAN_DFS_FALSE_DETECT +/** + * dfs_confirm_radar() - more rigid check for radar detection + * check for jitter in frequency (sidx) to be within certain limit + * introduce a fractional PRI check + * add a check to look for chirp in ETSI type 4 radar + * @dfs: pointer to dfs structure + * + * Return: max dur difference in sidx1_sidx2 pulse line + */ +static int dfs_confirm_radar(struct ath_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; + u_int64_t target_ts = 0; + struct dfs_pulseline *pl; + int start_index = 0, current_index, next_index; + unsigned char scores[FRAC_PRI_SCORE_ARRAY_SIZE]; + u_int32_t pri_margin; + u_int64_t this_diff_ts; + u_int32_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 & ATH_DEBUG_DFS2) { + dfs_print_delayline(dfs, &rf->rf_dl); + + /* print pulse line */ + DFS_DPRINTK(dfs, ATH_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_DPRINTK(dfs, ATH_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; + /* save for future use */ + start_index = index; + } + } + + DFS_DPRINTK(dfs, ATH_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) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, + "%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); + DFS_PRINTK("%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) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, + "%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); + DFS_PRINTK("%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)) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, + "%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); + + DFS_PRINTK("%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; +} +#else +static int dfs_confirm_radar(struct ath_dfs *dfs, struct dfs_filter *rf, + int ext_chan_flag) +{ + return 1; +} +#endif + /* * Process a radar event. * @@ -131,6 +297,7 @@ int dfs_process_radarevent(struct ath_dfs *dfs, int i; int seg_id = DFS_80P80_SEG0; struct dfs_delayline *dl; + int false_radar_found = 0; if (dfs == NULL) { QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, @@ -203,7 +370,8 @@ int dfs_process_radarevent(struct ath_dfs *dfs, empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); ATH_DFSQ_UNLOCK(dfs); - while ((!empty) && (!retval) && (events_processed < MAX_EVENTS)) { + while ((!empty) && (!retval) && (events_processed < MAX_EVENTS) && + (!false_radar_found)) { ATH_DFSQ_LOCK(dfs); event = STAILQ_FIRST(&(dfs->dfs_radarq)); if (event != NULL) @@ -381,6 +549,8 @@ int dfs_process_radarevent(struct ath_dfs *dfs, 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.sidx; + pl->pl_elems[index].p_delta_peak = re.delta_peak; if (seg_id == 0) { diff_ts = (uint32_t) this_ts - dfs->test_ts; dfs->test_ts = (uint32_t) this_ts; @@ -425,6 +595,8 @@ int dfs_process_radarevent(struct ath_dfs *dfs, re.re_rssi, diff_ts, (unsigned long long)pl->pl_elems[index].p_time); } + dfs->dfs_seq_num++; + pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num; /* If diff_ts is very small, we might be getting false pulse detects * due to heavy interference. We might be getting spectral splatter @@ -432,9 +604,25 @@ int dfs_process_radarevent(struct ath_dfs *dfs, * clear the delay-lines. This might impact positive detections under * harsh environments, but helps with false detects. */ - if (diff_ts < 100) { + if (diff_ts < DFS_INVALID_PRI_LIMIT) { + dfs->dfs_seq_num = 0; dfs_reset_alldelaylines(dfs, seg_id); 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.sidx; + pl->pl_elems[index].p_delta_peak = re.delta_peak; + dfs->dfs_seq_num++; + pl->pl_elems[index].p_seq_num = dfs->dfs_seq_num; } found = 0; @@ -599,7 +787,7 @@ int dfs_process_radarevent(struct ath_dfs *dfs, while ((tabledepth < DFS_MAX_RADAR_OVERLAP) && ((dfs->dfs_radartable[re.re_dur])[tabledepth] != -1) && - (!retval)) { + (!retval) && (!false_radar_found)) { ft = dfs-> dfs_radarf[((dfs-> dfs_radartable[re. @@ -649,7 +837,8 @@ int dfs_process_radarevent(struct ath_dfs *dfs, continue; } for (p = 0, found = 0; - (p < ft->ft_numfilters) && (!found); p++) { + (p < ft->ft_numfilters) && (!found) && + (!false_radar_found); p++) { rf = ft->ft_filters[p]; dl = (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg; @@ -766,12 +955,29 @@ int dfs_process_radarevent(struct ath_dfs *dfs, (uint32_t)deltaT, re.re_dur, seg_id); } else { - found = - dfs_bin_check(dfs, rf, + found = dfs_bin_check(dfs, rf, (uint32_t)deltaT, re.re_dur, ext_chan_event_flag, seg_id); + /** + * do additioal check to + * conirm radar except + * for the following + * staggered, chirp FCC + * Bin 5, frequency + * hopping indicated by + * rf_patterntype == 1 + */ + if ((rf->rf_patterntype != 1) && + found) { + found = + dfs_confirm_radar( + dfs, rf, + ext_chan_event_flag); + false_radar_found = + (found == 1) ? 0 : 1; + } } if (dfs-> dfs_debug_mask & ATH_DEBUG_DFS2) { @@ -879,6 +1085,14 @@ dfsfound: dfs->dfs_phyerr_w53_counter = 0; } /* QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_DEBUG, "IN FUNC %s[%d]: retval = %d ",__func__,__LINE__,retval); */ + if (false_radar_found) { + dfs->dfs_seq_num = 0; + dfs_reset_radarq(dfs); + dfs_reset_alldelaylines(dfs, seg_id); + dfs->dfs_phyerr_freq_min = 0x7fffffff; + dfs->dfs_phyerr_freq_max = 0; + dfs->dfs_phyerr_w53_counter = 0; + } return retval; /* #endif */ /* return 1; */ diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 50e511e39468..cdb34a0ab51a 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -2258,8 +2258,13 @@ static QDF_STATUS dfs_phyerr_offload_event_handler(void *handle, /* * Index of peak magnitude + * To do: + * Need change interface of WMI_DFS_RADAR_EVENTID to get delta_diff and + * delta_peak when DFS Phyerr filtering offload is enabled. */ - event->sidx = radar_event->peak_sidx; + event->sidx = radar_event->peak_sidx & 0x0000ffff; + event->delta_diff = 0; + event->delta_peak = 0; event->re_flags = 0; /* |
