summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbings <bings@codeaurora.org>2017-09-01 09:33:54 +0800
committersnandini <snandini@codeaurora.org>2017-12-18 16:42:00 -0800
commitaa9b8f1e49d690f46de9658d2761ef616bfe2cae (patch)
tree9ec9791db22c2e126189338431e7f788a8409d52
parent0a15a9fae719c13ba230a17246cc633bc2767a04 (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--Kbuild4
-rw-r--r--core/sap/dfs/inc/ath_dfs_structs.h18
-rw-r--r--core/sap/dfs/inc/dfs.h60
-rw-r--r--core/sap/dfs/inc/radar_filters.h93
-rw-r--r--core/sap/dfs/src/dfs_bindetects.c43
-rw-r--r--core/sap/dfs/src/dfs_init.c2
-rw-r--r--core/sap/dfs/src/dfs_phyerr_tlv.c2
-rw-r--r--core/sap/dfs/src/dfs_process_phyerr.c2
-rw-r--r--core/sap/dfs/src/dfs_process_radarevent.c226
-rw-r--r--core/wma/src/wma_features.c7
10 files changed, 401 insertions, 56 deletions
diff --git a/Kbuild b/Kbuild
index 0d5fae3e9e2b..5021efab2f9f 100644
--- a/Kbuild
+++ b/Kbuild
@@ -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;
/*