diff --git a/core/sap/dfs/inc/dfs.h b/core/sap/dfs/inc/dfs.h index 64bc046fa04f..f3bdff8e7efb 100644 --- a/core/sap/dfs/inc/dfs.h +++ b/core/sap/dfs/inc/dfs.h @@ -98,6 +98,9 @@ #define DFS_STATUS_SUCCESS 0 #define DFS_STATUS_FAIL 1 +#define DFS_80P80_SEG0 0 +#define DFS_80P80_SEG1 1 + /* * Constants to use for chirping detection. * @@ -115,6 +118,8 @@ #define MAX_BIN5_DUR 145 #define MAX_BIN5_DUR_MICROSEC 105 +#define DFS_BIN5_TIME_WINDOW_UNITS_MULTIPLIER 1000000 + #define DFS_MARGIN_EQUAL(a, b, margin) ((DFS_DIFF(a, b)) <= margin) #define DFS_MAX_STAGGERED_BURSTS 3 @@ -280,6 +285,7 @@ struct dfs_event { uint32_t re_freq_lo; /* Lower bounds of frequency, KHz */ uint32_t re_freq_hi; /* Upper bounds of frequency, KHz */ int sidx; /* Pulse Index as in radar summary report */ + int radar_80p80_segid; /* 80p80 segment ID as in radar sum report */ STAILQ_ENTRY(dfs_event) re_list; /* List of radar events */ } cdf_packed; #ifdef WIN32 @@ -355,6 +361,8 @@ struct dfs_delayline { struct dfs_filter { /* Delay line of pulses for this filter */ struct dfs_delayline rf_dl; + /* Delay line of pulses for this filter in 80p80 */ + struct dfs_delayline rf_dl_ext_seg; /* Number of pulses in the filter */ uint32_t rf_numpulses; /* min pri to be considered for this filter */ @@ -475,6 +483,7 @@ struct dfs_info { uint64_t dfs_bin5_chirp_ts; uint8_t dfs_last_bin5_dur; + uint8_t dfs_last_bin5_dur_ext_seg; } cdf_packed; #ifdef WIN32 #pragma pack(pop, dfs_info) @@ -574,6 +583,8 @@ struct ath_dfs { struct dfs_info dfs_rinfo; /* State vars for radar processing */ struct dfs_bin5radars *dfs_b5radars; /* array of bin5 radar events */ + /* array of bin5 radar events on extension segment in 80p80 */ + struct dfs_bin5radars *dfs_b5radars_ext_seg; int8_t **dfs_radartable; /* map of radar durs to filter types */ #ifndef ATH_DFS_RADAR_DETECTION_ONLY struct dfs_nolelem *dfs_nol; /* Non occupancy list for radar */ @@ -583,6 +594,7 @@ struct ath_dfs { struct ath_dfs_phyerr_param dfs_defaultparams; struct dfs_stats ath_dfs_stats; /* DFS related stats */ struct dfs_pulseline *pulses; /* pulse history */ + struct dfs_pulseline *pulses_ext_seg; /* pulse history ext 80p80 seg */ struct dfs_event *events; /* Events structure */ uint32_t ath_radar_tasksched:1, /* radar task is scheduled */ @@ -630,6 +642,8 @@ struct ath_dfs { * channel switch is disabled. */ 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 */ }; /* This should match the table from if_ath.c */ @@ -718,6 +732,11 @@ struct dfs_phy_err { uint8_t rssi; /* pulse RSSI */ uint8_t dur; /* pulse duration, raw (not uS) */ int sidx; /* Pulse Index as in radar summary report */ + /* + * Indicates segment ID on which the phyerror is received + * when SAP is operating in 80p80 channel width. + */ + int radar_80p80_segid; }; /* Attach, detach, handle ioctl prototypes */ @@ -746,14 +765,14 @@ int dfs_bin5_check_pulse(struct ath_dfs *dfs, struct dfs_event *re, struct dfs_bin5radars *br); int dfs_bin5_addpulse(struct ath_dfs *dfs, struct dfs_bin5radars *br, struct dfs_event *re, uint64_t thists); -int dfs_bin5_check(struct ath_dfs *dfs); +int dfs_bin5_check(struct ath_dfs *dfs, int seg_id); int dfs_check_chirping(struct ath_dfs *dfs, void *buf, uint16_t datalen, int is_ctl, int is_ext, int *slope, int *is_dc); uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, - uint8_t old_dur); + uint8_t old_dur, int seg_id); uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, - uint8_t old_dur); + uint8_t old_dur, int seg_id); int dfs_get_random_bin5_dur(struct ath_dfs *dfs, uint64_t tstamp); /* Debug prototypes */ @@ -773,26 +792,26 @@ struct dfs_state *dfs_getchanstate(struct ath_dfs *dfs, uint8_t *index, int dfs_init_radar_filters(struct ieee80211com *ic, struct ath_dfs_radar_tab_info *radar_info); -void dfs_reset_alldelaylines(struct ath_dfs *dfs); +void dfs_reset_alldelaylines(struct ath_dfs *dfs, int seg_id); void dfs_reset_delayline(struct dfs_delayline *dl); -void dfs_reset_filter_delaylines(struct dfs_filtertype *dft); void dfs_reset_radarq(struct ath_dfs *dfs); /* Detection algorithm prototypes */ void dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, - struct dfs_event *re, uint32_t deltaT, uint64_t this_ts); + struct dfs_event *re, uint32_t deltaT, uint64_t this_ts, + int seg_id); int dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t dur, int ext_chan_flag); + uint32_t dur, int ext_chan_flag, int seg_id); int dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t deltaT, uint32_t dur, int ext_chan_flag); + uint32_t deltaT, uint32_t dur, int ext_chan_flag, int seg_id); int dfs_bin_pri_check(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_delayline *dl, uint32_t score, uint32_t refpri, uint32_t refdur, int ext_chan_flag, int fundamentalpri); int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t deltaT, uint32_t width); + uint32_t deltaT, uint32_t width, int seg_id); /* False detection reduction */ int dfs_get_pri_margin(struct ath_dfs *dfs, int is_extchan_detect, int is_fixed_pattern); diff --git a/core/sap/dfs/src/dfs.c b/core/sap/dfs/src/dfs.c index 2d0a81a3c55d..22ba6f405b0a 100644 --- a/core/sap/dfs/src/dfs.c +++ b/core/sap/dfs/src/dfs.c @@ -300,6 +300,28 @@ int dfs_attach(struct ieee80211com *ic) return 1; } + /* + * If the chip supports DFS-3 then allocate + * memory for pulses for extension segment. + */ + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + dfs->pulses_ext_seg = (struct dfs_pulseline *) + os_malloc(NULL, + sizeof(struct dfs_pulseline), + GFP_ATOMIC); + if (dfs->pulses_ext_seg == NULL) { + OS_FREE(dfs->events); + dfs->events = NULL; + OS_FREE(dfs); + ic->ic_dfs = NULL; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s[%d]: pulse buffer allocation failed", + __func__, __LINE__); + return 1; + } + dfs->pulses_ext_seg->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; + } + dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; /* Allocate memory for radar filters */ @@ -351,6 +373,10 @@ int dfs_attach(struct ieee80211com *ic) dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; dfs->dfs_b5radars = NULL; + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + dfs->dfs_rinfo.dfs_last_bin5_dur_ext_seg = MAX_BIN5_DUR; + dfs->dfs_b5radars_ext_seg = NULL; + } /* * If dfs_init_radar_filters() fails, we can abort here and @@ -388,6 +414,11 @@ bad1: OS_FREE(dfs->pulses); dfs->pulses = NULL; } + if (dfs->pulses_ext_seg && + ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + OS_FREE(dfs->pulses_ext_seg); + dfs->pulses_ext_seg = NULL; + } if (dfs->events) { OS_FREE(dfs->events); dfs->events = NULL; @@ -446,9 +477,12 @@ void dfs_detach(struct ieee80211com *ic) } #endif #endif + /* Return radar events to free q */ dfs_reset_radarq(dfs); - dfs_reset_alldelaylines(dfs); + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); /* Free up pulse log */ if (dfs->pulses != NULL) { @@ -456,6 +490,12 @@ void dfs_detach(struct ieee80211com *ic) dfs->pulses = NULL; } + if (dfs->pulses_ext_seg != NULL && + ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + OS_FREE(dfs->pulses_ext_seg); + dfs->pulses_ext_seg = NULL; + } + for (n = 0; n < DFS_MAX_RADAR_TYPES; n++) { if (dfs->dfs_radarf[n] != NULL) { OS_FREE(dfs->dfs_radarf[n]); @@ -481,6 +521,11 @@ void dfs_detach(struct ieee80211com *ic) OS_FREE(dfs->dfs_b5radars); dfs->dfs_b5radars = NULL; } + if (dfs->dfs_b5radars_ext_seg != NULL && + ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + OS_FREE(dfs->dfs_b5radars_ext_seg); + dfs->dfs_b5radars_ext_seg = NULL; + } /* Commenting out since all the ar functions are obsolete and * the function definition has been removed as part of dfs_ar.c @@ -582,7 +627,14 @@ int dfs_radar_enable(struct ieee80211com *ic, if (is_ext_ch) { ext_ch = ieee80211_get_extchan(ic); } - dfs_reset_alldelaylines(dfs); + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + /* + * Extension segment delaylines will be + * enabled only when SAP operates in 80p80 + * and both the channels are DFS. + */ + if (chan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); rs_pri = dfs_getchanstate(dfs, &index_pri, 0); if (ext_ch) { @@ -594,9 +646,17 @@ int dfs_radar_enable(struct ieee80211com *ic, OS_MEMSET(&pe, '\0', sizeof(pe)); - if (index_pri != dfs->dfs_curchan_radindex) - dfs_reset_alldelaylines(dfs); - + if (index_pri != dfs->dfs_curchan_radindex) { + dfs_reset_alldelaylines(dfs, + DFS_80P80_SEG0); + /* + * Reset only when ext segment is + * present + */ + if (chan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, + DFS_80P80_SEG1); + } dfs->dfs_curchan_radindex = (int16_t) index_pri; dfs->dfs_pri_multiplier_ini = radar_info->dfs_pri_multiplier; diff --git a/core/sap/dfs/src/dfs_bindetects.c b/core/sap/dfs/src/dfs_bindetects.c index 7c48309942ca..dc3acf6dabd6 100644 --- a/core/sap/dfs/src/dfs_bindetects.c +++ b/core/sap/dfs/src/dfs_bindetects.c @@ -59,14 +59,19 @@ int dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t dur, int ext_chan_flag) + uint32_t dur, int ext_chan_flag, int seg_id) { - struct dfs_pulseline *pl = dfs->pulses; + struct dfs_pulseline *pl; int i, n, refpri, primargin, numpulses = 0; uint64_t start_ts, end_ts, event_ts, prev_event_ts, next_event_ts, window_start, window_end; uint32_t index, next_index, deltadur; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + pl = (seg_id == 0) ? dfs->pulses : dfs->pulses_ext_seg; + else + pl = dfs->pulses; + /* For fixed pattern types, rf->rf_patterntype=1 */ primargin = dfs_get_pri_margin(dfs, ext_chan_flag, (rf->rf_patterntype == 1)); @@ -151,12 +156,15 @@ dfs_bin_fixedpattern_check(struct ath_dfs *dfs, struct dfs_filter *rf, void dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, - uint32_t deltaT, uint64_t this_ts) + uint32_t deltaT, uint64_t this_ts, int seg_id) { uint32_t index, n, window; struct dfs_delayline *dl; - dl = &rf->rf_dl; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dl = (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg; + else + dl = &rf->rf_dl; /* Circular buffer of size 2^n */ index = (dl->dl_lastelem + 1) & DFS_MAX_DL_MASK; /* if ((dl->dl_numelems+1) == DFS_MAX_DL_SIZE) */ @@ -197,7 +205,7 @@ dfs_add_pulse(struct ath_dfs *dfs, struct dfs_filter *rf, struct dfs_event *re, int dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, - uint32_t width, int ext_chan_flag) + uint32_t width, int ext_chan_flag, int seg_id) { uint32_t refpri, refdur, searchpri, deltapri, deltapri_2, deltapri_3, averagerefpri; @@ -208,7 +216,11 @@ dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, int numpulses = 0; int lowprichk = 3, pri_match = 0; - dl = &rf->rf_dl; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dl = (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg; + else + dl = &rf->rf_dl; + if (dl->dl_numelems < (rf->rf_threshold - 1)) { return 0; } @@ -226,7 +238,8 @@ dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, if (rf->rf_patterntype == 1) { found = - dfs_bin_fixedpattern_check(dfs, rf, width, ext_chan_flag); + dfs_bin_fixedpattern_check(dfs, rf, width, + ext_chan_flag, seg_id); if (found) { dl->dl_numelems = 0; } @@ -330,7 +343,13 @@ dfs_bin_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t deltaT, "ext_flag=%d MATCH filter=%u numpulses=%u thresh=%u refdur=%d refpri=%d primargin=%d\n", ext_chan_flag, rf->rf_pulseid, numpulses, rf->rf_threshold, refdur, refpri, primargin); - dfs_print_delayline(dfs, &rf->rf_dl); + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_print_delayline(dfs, + (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg); + else + dfs_print_delayline(dfs, &rf->rf_dl); + dfs_print_filter(dfs, rf); } return found; diff --git a/core/sap/dfs/src/dfs_fcc_bin5.c b/core/sap/dfs/src/dfs_fcc_bin5.c index d6f62542c0ce..027e3211866e 100644 --- a/core/sap/dfs/src/dfs_fcc_bin5.c +++ b/core/sap/dfs/src/dfs_fcc_bin5.c @@ -176,7 +176,7 @@ int dfs_bin5_addpulse(struct ath_dfs *dfs, struct dfs_bin5radars *br, * properly, then signify that a bin5 radar was found */ -int dfs_bin5_check(struct ath_dfs *dfs) +int dfs_bin5_check(struct ath_dfs *dfs, int seg_id) { struct dfs_bin5radars *br; int index[DFS_MAX_B5_SIZE]; @@ -191,7 +191,11 @@ int dfs_bin5_check(struct ath_dfs *dfs) return 1; } for (n = 0; n < dfs->dfs_rinfo.rn_numbin5radars; n++) { - br = &(dfs->dfs_b5radars[n]); + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + br = (seg_id == 0) ? &(dfs->dfs_b5radars[n]) : + &(dfs->dfs_b5radars_ext_seg[n]); + else + br = &(dfs->dfs_b5radars[n]); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "Num elems = %d\n", br->br_numelems); @@ -806,9 +810,18 @@ dfs_check_chirping(struct ath_dfs *dfs, void *buf, uint8_t dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, - uint8_t old_dur) + uint8_t old_dur, int seg_id) { + u_int8_t dfs_last_bin5_dur; + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_last_bin5_dur = (seg_id == 0) ? + dfs->dfs_rinfo.dfs_last_bin5_dur : + dfs->dfs_rinfo.dfs_last_bin5_dur_ext_seg; + else + dfs_last_bin5_dur = dfs->dfs_rinfo.dfs_last_bin5_dur; + /* * Pulses may get split into 2 during chirping, this print is only * to show that it happened, we do not handle this condition if we @@ -821,7 +834,7 @@ dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "%s SPLIT pulse diffTs=%u dur=%d (old_dur=%d)\n", __func__, diff_ts, - dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur); + dfs_last_bin5_dur, old_dur); } /* * Check if this is the 2nd or 3rd pulse in the same burst, @@ -836,10 +849,9 @@ dfs_retain_bin5_burst_pattern(struct ath_dfs *dfs, uint32_t diff_ts, DFS_DPRINTK(dfs, ATH_DEBUG_DFS_BIN5, "%s this pulse belongs to the same burst as before, give " "it same dur=%d (old_dur=%d)\n", - __func__, dfs->dfs_rinfo.dfs_last_bin5_dur, - old_dur); + __func__, dfs_last_bin5_dur, old_dur); - return (dfs->dfs_rinfo.dfs_last_bin5_dur); + return dfs_last_bin5_dur; } /* * This pulse does not belong to this burst, return unchanged diff --git a/core/sap/dfs/src/dfs_init.c b/core/sap/dfs/src/dfs_init.c index ca259c4af8ea..7ab7df12a9cb 100644 --- a/core/sap/dfs/src/dfs_init.c +++ b/core/sap/dfs/src/dfs_init.c @@ -66,7 +66,7 @@ extern int domainoverride; * (eg on a non-DFS channel, with radar PHY errors still showing up.) * In that case, just drop out early. */ -void dfs_reset_alldelaylines(struct ath_dfs *dfs) +void dfs_reset_alldelaylines(struct ath_dfs *dfs, int seg_id) { struct dfs_filtertype *ft = NULL; struct dfs_filter *rf; @@ -79,7 +79,11 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) "%s[%d]: sc_dfs is NULL", __func__, __LINE__); return; } - pl = dfs->pulses; + + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + pl = (seg_id == 0) ? dfs->pulses : dfs->pulses_ext_seg; + else + pl = dfs->pulses; if (pl == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -87,13 +91,24 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) return; } - if (dfs->dfs_b5radars == NULL) { - CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s[%d]: pl==NULL, b5radars=%p", __func__, __LINE__, - dfs->dfs_b5radars); - return; + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + if (((seg_id == 0) ? + dfs->dfs_b5radars : dfs->dfs_b5radars_ext_seg) == NULL) { + DFS_DPRINTK(dfs, ATH_DEBUG_DFS, + "%s: pl==NULL, b5radars=%p\n", + __func__, + (seg_id == 0) ? dfs->dfs_b5radars : + dfs->dfs_b5radars_ext_seg); + return; + } + } else { + if (dfs->dfs_b5radars == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s[%d]: pl==NULL, b5radars=%p", __func__, __LINE__, + dfs->dfs_b5radars); + return; + } } - /* reset the pulse log */ pl->pl_firstelem = pl->pl_numelems = 0; pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; @@ -104,7 +119,13 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) if (NULL != ft) { for (j = 0; j < ft->ft_numfilters; j++) { rf = &(ft->ft_filters[j]); - dl = &(rf->rf_dl); + if (dfs->ic->dfs_hw_bd_id != + DFS_HWBD_QCA6174) + dl = (seg_id == 0) ? + &(rf->rf_dl) : + &(rf->rf_dl_ext_seg); + else + dl = &(rf->rf_dl); if (dl != NULL) { OS_MEMZERO(dl, sizeof(struct @@ -118,12 +139,34 @@ void dfs_reset_alldelaylines(struct ath_dfs *dfs) } } for (i = 0; i < dfs->dfs_rinfo.rn_numbin5radars; i++) { - OS_MEMZERO(&(dfs->dfs_b5radars[i].br_elems[0]), - sizeof(struct dfs_bin5elem) * DFS_MAX_B5_SIZE); - dfs->dfs_b5radars[i].br_firstelem = 0; - dfs->dfs_b5radars[i].br_numelems = 0; - dfs->dfs_b5radars[i].br_lastelem = - (0xFFFFFFFF) & DFS_MAX_B5_MASK; + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + if (seg_id == DFS_80P80_SEG0) { + OS_MEMZERO(&(dfs->dfs_b5radars[i].br_elems[0]), + sizeof(struct dfs_bin5elem) * + DFS_MAX_B5_SIZE); + dfs->dfs_b5radars[i].br_firstelem = 0; + dfs->dfs_b5radars[i].br_numelems = 0; + dfs->dfs_b5radars[i].br_lastelem = + (0xFFFFFFFF) & DFS_MAX_B5_MASK; + } else { + OS_MEMZERO( + &(dfs->dfs_b5radars_ext_seg[i].br_elems[0]), + sizeof(struct dfs_bin5elem)* + DFS_MAX_B5_SIZE); + dfs->dfs_b5radars_ext_seg[i].br_firstelem = 0; + dfs->dfs_b5radars_ext_seg[i].br_numelems = 0; + dfs->dfs_b5radars_ext_seg[i].br_lastelem = + (0xFFFFFFFF)&DFS_MAX_B5_MASK; + } + + } else { + OS_MEMZERO(&(dfs->dfs_b5radars[i].br_elems[0]), + sizeof(struct dfs_bin5elem) * DFS_MAX_B5_SIZE); + dfs->dfs_b5radars[i].br_firstelem = 0; + dfs->dfs_b5radars[i].br_numelems = 0; + dfs->dfs_b5radars[i].br_lastelem = + (0xFFFFFFFF) & DFS_MAX_B5_MASK; + } } } @@ -137,16 +180,6 @@ void dfs_reset_delayline(struct dfs_delayline *dl) dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK; } -void dfs_reset_filter_delaylines(struct dfs_filtertype *dft) -{ - int i; - struct dfs_filter *df; - for (i = 0; i < DFS_MAX_NUM_RADAR_FILTERS; i++) { - df = &dft->ft_filters[i]; - dfs_reset_delayline(&(df->rf_dl)); - } -} - void dfs_reset_radarq(struct ath_dfs *dfs) { struct dfs_event *event; @@ -183,6 +216,8 @@ int dfs_init_radar_filters(struct ieee80211com *ic, struct dfs_bin5pulse *b5pulses = NULL; int32_t min_rssithresh = DFS_MAX_RSSI_VALUE; uint32_t max_pulsedur = 0; + uint32_t b5_rssithresh; + uint32_t b5_maxdur; if (dfs == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, @@ -299,6 +334,10 @@ int dfs_init_radar_filters(struct ieee80211com *ic, } rf = &(ft->ft_filters[ft->ft_numfilters++]); dfs_reset_delayline(&rf->rf_dl); + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + dfs_reset_delayline(&rf->rf_dl_ext_seg); + numpulses = dfs_radars[p].rp_numpulses; rf->rf_numpulses = numpulses; @@ -359,9 +398,24 @@ int dfs_init_radar_filters(struct ieee80211com *ic, __func__); goto bad4; } + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + dfs->dfs_b5radars_ext_seg = + (struct dfs_bin5radars *)os_malloc(NULL, numb5radars * + sizeof(struct dfs_bin5radars), + GFP_KERNEL); + if (dfs->dfs_b5radars_ext_seg == NULL) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s:Fail allocate memory for ext bin5 radars", + __func__); + goto bad4; + } + } + for (n = 0; n < numb5radars; n++) { dfs->dfs_b5radars[n].br_pulse = b5pulses[n]; - dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= 1000000; + dfs->dfs_b5radars[n].br_pulse.b5_timewindow *= + DFS_BIN5_TIME_WINDOW_UNITS_MULTIPLIER; if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < min_rssithresh) min_rssithresh = @@ -369,7 +423,30 @@ int dfs_init_radar_filters(struct ieee80211com *ic, if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur) max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur; } - dfs_reset_alldelaylines(dfs); + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) { + for (n = 0; n < numb5radars; n++) { + dfs->dfs_b5radars_ext_seg[n].br_pulse = b5pulses[n]; + dfs->dfs_b5radars_ext_seg[n].br_pulse.b5_timewindow *= + DFS_BIN5_TIME_WINDOW_UNITS_MULTIPLIER; + b5_rssithresh = + dfs->dfs_b5radars_ext_seg[n].br_pulse.b5_rssithresh; + if (b5_rssithresh < min_rssithresh) + min_rssithresh = b5_rssithresh; + + b5_maxdur = + dfs->dfs_b5radars_ext_seg[n].br_pulse.b5_maxdur; + if (b5_maxdur > max_pulsedur) + max_pulsedur = b5_maxdur; + + } + } + + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + + if (ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); + dfs_reset_radarq(dfs); dfs->dfs_curchan_radindex = -1; dfs->dfs_extchan_radindex = -1; diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.c b/core/sap/dfs/src/dfs_phyerr_tlv.c index 89a6c0b471b4..aaf568636282 100644 --- a/core/sap/dfs/src/dfs_phyerr_tlv.c +++ b/core/sap/dfs/src/dfs_phyerr_tlv.c @@ -35,6 +35,16 @@ #include "dfs_phyerr.h" #include "dfs_phyerr_tlv.h" +/** + * enum RADAR_SUMMARY_VERSION - Radar summary report version + * @DFS_RADAR_SUMMARY_REPORT_VERSION_2: DFS-2 radar summary report + * @DFS_RADAR_SUMMARY_REPORT_VERSION_3: DFS-3 radar summary report + */ +typedef enum { +DFS_RADAR_SUMMARY_REPORT_VERSION_2 = 1, +DFS_RADAR_SUMMARY_REPORT_VERSION_3 = 2, +} RADAR_SUMMARY_VERSION; + /* * Parsed radar status */ @@ -48,6 +58,28 @@ struct rx_radar_status { int delta_diff; int sidx; int freq_offset; /* in KHz */ + int agc_total_gain; + int agc_mb_gain; + /*Parsed only for DFS-3*/ + int radar_subchan_mask; + RADAR_SUMMARY_VERSION rsu_version; + /* + * The parameters below are present only in + * DFS-3 radar summary report and need to be + * parsed only for DFS-3. + */ + /* DFS-3 Only */ + int pulse_height; + /* DFS-3 Only */ + int triggering_agc_event; + /* DFS-3 Only */ + int pulse_rssi; + /* DFS-3 Only */ + int radar_fft_pri80_inband_power; + /* DFS-3 Only */ + int radar_fft_ext80_inband_power; + /* DFS-3 Only */ + int radar_80p80_segid; }; struct rx_search_fft_report { @@ -106,9 +138,22 @@ radar_summary_print(struct ath_dfs *dfs, struct rx_radar_status *rsu, bool enable_log) { + int is_chip_oversampling; + if (!enable_log) return; + /* + * Oversampling needs to be turned on for + * older chipsets that support DFS-2. + * it needs to be turned off for chips + * that support DFS-3. + */ + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + is_chip_oversampling = 0; + else + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "\n ############ Radar Summary ############\n"); @@ -152,7 +197,7 @@ radar_summary_print(struct ath_dfs *dfs, "%s: frequency offset = %d.%d MHz (oversampling = %d)\n", __func__, (int) (rsu->freq_offset / 1000), (int) abs(rsu->freq_offset % 1000), - PERE_IS_OVERSAMPLING(dfs)); + is_chip_oversampling); CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "\n ###################################\n"); @@ -168,50 +213,165 @@ radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, struct rx_radar_status *rsu) { uint32_t rs[2]; + uint32_t dfs3_rs[5]; int freq_centre, freq; + int is_chip_oversampling; - /* Drop out if we have < 2 DWORDs available */ - if (len < sizeof(rs)) { - DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR | - ATH_DEBUG_DFS_PHYERR_SUM, - "%s: len (%zu) < expected (%zu)!", - __func__, len, sizeof(rs)); + /* + * Drop out if we have < 2 DWORDs available for DFS-2 + * and drop out if we have < 5 DWORDS available for DFS-3 + */ + if ((dfs->ic->dfs_hw_bd_id == DFS_HWBD_QCA6174) && + (len < sizeof(rs))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: DFS-2 radar summary len = (%zu) wrong, expected = (%zu)", + __func__, len, sizeof(rs)); + } else if ((dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) && + (len < sizeof(dfs3_rs))) { + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, + "%s: DFS-3 radar summary len = (%zu) wrong, expected = (%zu)", + __func__, len, sizeof(dfs3_rs)); } /* - * Since the TLVs may be unaligned for some reason - * we take a private copy into aligned memory. - * This enables us to use the HAL-like accessor macros - * into the DWORDs to access sub-DWORD fields. + * If the length of TLV is equal to + * DFS3_RADAR_PULSE_SUMMARY_TLV_LENGTH + * then it means the radar summary report + * has 5 DWORDS and we need to parse the + * report accordingly. + * Else if the length is equal to + * DFS2_RADAR_PULSE_SUMMARY_TLV_LENGTH then + * it the radar summary report will have only + * two DWORDS so we parse for only two DWORDS. */ - OS_MEMCPY(rs, buf, sizeof(rs)); + if (len == DFS3_RADAR_PULSE_SUMMARY_TLV_LENGTH) { + /* + * Since the TLVs may be unaligned for some reason + * we take a private copy into aligned memory. + * This enables us to use the HAL-like accessor macros + * into the DWORDs to access sub-DWORD fields. + */ + OS_MEMCPY(dfs3_rs, buf, sizeof(dfs3_rs)); - DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, - "%s: two 32 bit values are: %08x %08x", __func__, rs[0], - rs[1]); -/* DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s (p=%p):", __func__, buf); */ + /* + * Oversampling is only needed to be + * turned on for older chips that support + * DFS-2. It needs to be turned off for chips + * that support DFS-3. + */ + is_chip_oversampling = 0; - /* Populate the fields from the summary report */ - rsu->tsf_offset = - MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_TSF_OFFSET); - rsu->pulse_duration = - MS(rs[RADAR_REPORT_PULSE_REG_2], RADAR_REPORT_PULSE_DUR); - rsu->is_chirp = - MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_IS_CHIRP); - rsu->sidx = - sign_extend_32(MS - (rs[RADAR_REPORT_PULSE_REG_1], - RADAR_REPORT_PULSE_SIDX), 10); - rsu->freq_offset = - calc_freq_offset(rsu->sidx, PERE_IS_OVERSAMPLING(dfs)); + /* + * populate the version of the radar summary report + * based on the TLV length to differentiate between + * DFS-2 and DFS-3 radar summary report. + */ + rsu->rsu_version = DFS_RADAR_SUMMARY_REPORT_VERSION_3; - /* These are only relevant if the pulse is a chirp */ - rsu->delta_peak = - sign_extend_32(MS - (rs[RADAR_REPORT_PULSE_REG_1], - RADAR_REPORT_PULSE_DELTA_PEAK), 6); - rsu->delta_diff = - MS(rs[RADAR_REPORT_PULSE_REG_1], RADAR_REPORT_PULSE_DELTA_DIFF); + /* Populate the fields from the summary report */ + rsu->tsf_offset = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_TSF_OFFSET); + rsu->pulse_duration = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_DUR); + rsu->is_chirp = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_IS_CHIRP); + rsu->sidx = sign_extend_32(MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_SIDX), 10); + rsu->freq_offset = calc_freq_offset(rsu->sidx, + is_chip_oversampling); + /* These are only relevant if the pulse is a chirp */ + rsu->delta_peak = sign_extend_32( + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_DELTA_PEAK), + 6); + rsu->delta_diff = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_DELTA_DIFF); + /* For false detection Debug */ + rsu->agc_total_gain = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_AGC_TOTAL_GAIN); + rsu->agc_mb_gain = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_AGC_MB_GAIN); + /* + * radar_subchan_mask will be used in the future to identify the + * sub channel that encoutered radar pulses and block those + * channels in NOL accordingly. + */ + rsu->radar_subchan_mask = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_SUBCHAN_MASK); + + rsu->pulse_height = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_3], + RADAR_REPORT_PULSE_HEIGHT); + rsu->triggering_agc_event = + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_4], + RADAR_REPORT_TRIGGERING_AGC_EVENT); + rsu->pulse_rssi = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_4], + RADAR_REPORT_PULSE_RSSI); + rsu->radar_fft_pri80_inband_power = + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_5], + RADAR_REPORT_FFT_PRI80_INBAND_POWER); + rsu->radar_fft_ext80_inband_power = + MS(dfs3_rs[RADAR_REPORT_PULSE_REG_5], + RADAR_REPORT_FFT_EXT80_INBAND_POWER); + rsu->radar_80p80_segid = MS(dfs3_rs[RADAR_REPORT_PULSE_REG_5], + RADAR_REPORT_80P80_SEGID); + } else { + /* + * Since the TLVs may be unaligned for some reason + * we take a private copy into aligned memory. + * This enables us to use the HAL-like accessor macros + * into the DWORDs to access sub-DWORD fields. + */ + OS_MEMCPY(rs, buf, sizeof(rs)); + + DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s: two 32 bit values are: %08x %08x", __func__, rs[0], + rs[1]); + /* + * DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, + "%s (p=%p):", __func__, buf); + */ + + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); + /* + * populate the version of the radar summary report + * based on the TLV length to differentiate between + * DFS-2 and DFS-3 radar summary report. + */ + rsu->rsu_version = DFS_RADAR_SUMMARY_REPORT_VERSION_2; + + /* Populate the fields from the summary report */ + rsu->tsf_offset = + MS(rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_TSF_OFFSET); + rsu->pulse_duration = + MS(rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_DUR); + rsu->is_chirp = + MS(rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_IS_CHIRP); + rsu->sidx = + sign_extend_32(MS(rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_SIDX), 10); + rsu->freq_offset = + calc_freq_offset(rsu->sidx, is_chip_oversampling); + + /* These are only relevant if the pulse is a chirp */ + rsu->delta_peak = + sign_extend_32(MS(rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_DELTA_PEAK), 6); + rsu->delta_diff = + MS(rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_PULSE_DELTA_DIFF); + + /* For false detection Debug */ + rsu->agc_total_gain = + MS(rs[RADAR_REPORT_PULSE_REG_1], + RADAR_REPORT_AGC_TOTAL_GAIN); + rsu->agc_mb_gain = + MS(rs[RADAR_REPORT_PULSE_REG_2], + RADAR_REPORT_PULSE_AGC_MB_GAIN); + + } /* WAR for FCC Type 4 */ /* @@ -441,19 +601,21 @@ static int tlv_calc_freq_info(struct ath_dfs *dfs, struct rx_radar_status *rs) cdf_spin_lock_bh(&dfs->ic->chan_lock); /* - * For now, the only 11ac channel with freq1/freq2 setup is - * VHT80. - * - * XXX should have a flag macro to check this! + * calculate the channel center frequency for + * 160MHz and 80p80 MHz including the legacy + * channel widths. */ - if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) { + if (IEEE80211_IS_CHAN_11AC_VHT160(dfs->ic->ic_curchan)) { + chan_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; + } else if (IEEE80211_IS_CHAN_11AC_VHT80P80(dfs->ic->ic_curchan)) { + if (rs->radar_80p80_segid == DFS_80P80_SEG0) + chan_centre = + dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; + else + chan_centre = + dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg2; + } else if (IEEE80211_IS_CHAN_11AC_VHT80(dfs->ic->ic_curchan)) { /* 11AC, so cfreq1/cfreq2 are setup */ - - /* - * XXX if it's 80+80 this won't work - need to use seg - * appropriately! - */ - chan_centre = dfs->ic->ic_curchan->ic_vhtop_ch_freq_seg1; } else { /* HT20/HT40 */ @@ -505,6 +667,18 @@ tlv_calc_event_freq_pulse(struct ath_dfs *dfs, struct rx_radar_status *rs, { int chan_width; int chan_centre; + int is_chip_oversampling; + + /* + * Oversampling needs to be turned on for + * older chipsets that support DFS-2. + * it needs to be turned off for chips + * that support DFS-3. + */ + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + is_chip_oversampling = 0; + else + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); /* Fetch the channel centre frequency in MHz */ chan_centre = tlv_calc_freq_info(dfs, rs); @@ -517,7 +691,7 @@ tlv_calc_event_freq_pulse(struct ath_dfs *dfs, struct rx_radar_status *rs, * XXX this needs to take into account the core clock speed * XXX for half/quarter rate mode. */ - if (PERE_IS_OVERSAMPLING(dfs)) + if (is_chip_oversampling) chan_width = (44000 * 2 / 128); else chan_width = (40000 * 2 / 128); @@ -559,13 +733,25 @@ tlv_calc_event_freq_chirp(struct ath_dfs *dfs, struct rx_radar_status *rs, int32_t total_bw; int32_t chan_centre; int32_t freq_1, freq_2; + int is_chip_oversampling; + + /* + * Oversampling needs to be turned on for + * older chipsets that support DFS-2. + * it needs to be turned off for chips + * that support DFS-3. + */ + if (dfs->ic->dfs_hw_bd_id != DFS_HWBD_QCA6174) + is_chip_oversampling = 0; + else + is_chip_oversampling = PERE_IS_OVERSAMPLING(dfs); /* * KHz isn't enough resolution here! * So treat it as deci-hertz (10Hz) and convert back to KHz * later. */ - if (PERE_IS_OVERSAMPLING(dfs)) + if (is_chip_oversampling) bin_resolution = (44000 * 100) / 128; else bin_resolution = (40000 * 100) / 128; @@ -691,6 +877,13 @@ 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; + + /* + * Copy the segment ID from the radar summary report + * only when radar summary report version is DFS-3. + */ + if (rs.rsu_version == DFS_RADAR_SUMMARY_REPORT_VERSION_3) + e->radar_80p80_segid = rs.radar_80p80_segid; /* * XXX TODO: add a "chirp detection enabled" capability or config * bit somewhere, in case for some reason the hardware chirp diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.h b/core/sap/dfs/src/dfs_phyerr_tlv.h index d65375267cfd..61da81c3ad09 100644 --- a/core/sap/dfs/src/dfs_phyerr_tlv.h +++ b/core/sap/dfs/src/dfs_phyerr_tlv.h @@ -66,6 +66,13 @@ #define TAG_ID_SEARCH_FFT_REPORT 0xFB #define TAG_ID_RADAR_PULSE_SUMMARY 0xF8 + +/* DFS-2 Radar pulse summary Length */ +#define DFS2_RADAR_PULSE_SUMMARY_TLV_LENGTH 8 + +/* DFS-3 Radar pulse summary length */ +#define DFS3_RADAR_PULSE_SUMMARY_TLV_LENGTH 20 + /* * Radar pulse summary * @@ -110,6 +117,37 @@ #define RADAR_REPORT_PULSE_DUR 0x000000FF #define RADAR_REPORT_PULSE_DUR_S 0 +/* + * These are the new TLV's in the DFS-3 + * radar summary report. Three new DWORDS + * have been added to radar summary report + * as part of DFS-3 as defined below. + */ + +#define RADAR_REPORT_PULSE_REG_3 0x02 + +#define RADAR_REPORT_PULSE_HEIGHT 0x000003FF +#define RADAR_REPORT_PULSE_HEIGHT_S 0 + +#define RADAR_REPORT_PULSE_REG_4 0x03 + +#define RADAR_REPORT_TRIGGERING_AGC_EVENT 0xC0000000 +#define RADAR_REPORT_TRIGGERING_AGC_EVENT_S 30 + +#define RADAR_REPORT_PULSE_RSSI 0X3FFC0000 +#define RADAR_REPORT_PULSE_RSSI_S 18 + +#define RADAR_REPORT_PULSE_REG_5 0x04 + +#define RADAR_REPORT_FFT_PRI80_INBAND_POWER 0x1FFF8000 +#define RADAR_REPORT_FFT_PRI80_INBAND_POWER_S 15 + +#define RADAR_REPORT_FFT_EXT80_INBAND_POWER 0x00007FFE +#define RADAR_REPORT_FFT_EXT80_INBAND_POWER_S 1 + +#define RADAR_REPORT_80P80_SEGID 0x00000001 +#define RADAR_REPORT_80P80_SEGID_S 0 + #define SEARCH_FFT_REPORT_REG_1 0x00 #define SEARCH_FFT_REPORT_TOTAL_GAIN_DB 0xFF800000 diff --git a/core/sap/dfs/src/dfs_process_phyerr.c b/core/sap/dfs/src/dfs_process_phyerr.c index 38a49deb3766..0a806b4db8c4 100644 --- a/core/sap/dfs/src/dfs_process_phyerr.c +++ b/core/sap/dfs/src/dfs_process_phyerr.c @@ -737,6 +737,15 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, event->re_chanindex = dfs->dfs_curchan_radindex; event->re_flags = 0; event->sidx = e.sidx; + /* + * Copy the segment ID of the phyerror + * from the radar summary report only + * if SAP is operating in 80p80 mode + * and both primary and extension segments + * are DFS. + */ + if (chan->ic_80p80_both_dfs) + event->radar_80p80_segid = e.radar_80p80_segid; /* * Handle chirp flags. diff --git a/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c index c5a586c10341..3c05d322707a 100644 --- a/core/sap/dfs/src/dfs_process_radarevent.c +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -127,27 +127,31 @@ int dfs_process_radarevent(struct ath_dfs *dfs, uint64_t deltafull_ts = 0, this_ts, deltaT; struct dfs_ieee80211_channel *thischan; struct dfs_pulseline *pl; - static uint32_t test_ts = 0; static uint32_t diff_ts = 0; int ext_chan_event_flag = 0; #if 0 int pri_multiplier = 2; #endif int i; + int seg_id = DFS_80P80_SEG0; + struct dfs_delayline *dl; if (dfs == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, "%s[%d]: dfs is NULL", __func__, __LINE__); return 0; } - pl = dfs->pulses; cdf_spin_lock_bh(&dfs->ic->chan_lock); if (!(IEEE80211_IS_CHAN_DFS(dfs->ic->ic_curchan))) { cdf_spin_unlock_bh(&dfs->ic->chan_lock); DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: radar event on non-DFS chan", __func__); dfs_reset_radarq(dfs); - dfs_reset_alldelaylines(dfs); + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); + return 0; } @@ -218,6 +222,12 @@ int dfs_process_radarevent(struct ath_dfs *dfs, } events_processed++; re = *event; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + seg_id = re.radar_80p80_segid; + else + seg_id = DFS_80P80_SEG0; + + pl = (seg_id == 0) ? dfs->pulses : dfs->pulses_ext_seg; OS_MEMZERO(event, sizeof(struct dfs_event)); ATH_DFSEVENTQ_LOCK(dfs); @@ -375,8 +385,13 @@ 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; - diff_ts = (uint32_t) this_ts - test_ts; - test_ts = (uint32_t) this_ts; + if (seg_id == 0) { + diff_ts = (uint32_t) this_ts - dfs->test_ts; + dfs->test_ts = (uint32_t) this_ts; + } else { + diff_ts = (u_int32_t)this_ts - dfs->test_ts_ext_seg; + dfs->test_ts_ext_seg = (u_int32_t)this_ts; + } DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "ts%u %u %u diff %u pl->pl_lastelem.p_time=%llu", (uint32_t) this_ts, re.re_dur, re.re_rssi, diff_ts, @@ -402,7 +417,7 @@ int dfs_process_radarevent(struct ath_dfs *dfs, * harsh environments, but helps with false detects. */ if (diff_ts < 100) { - dfs_reset_alldelaylines(dfs); + dfs_reset_alldelaylines(dfs, seg_id); dfs_reset_radarq(dfs); } found = 0; @@ -512,23 +527,36 @@ int dfs_process_radarevent(struct ath_dfs *dfs, p++) { struct dfs_bin5radars *br; - br = &(dfs->dfs_b5radars[p]); + br = (seg_id == 0) ? + &(dfs->dfs_b5radars[p]) : + &(dfs->dfs_b5radars_ext_seg[p]); + if (dfs_bin5_check_pulse(dfs, &re, br)) { - /* This is a valid Bin5 pulse, check if it belongs to a burst */ + /* + * This is a valid Bin5 pulse, + * check if it belongs to a burst + */ re.re_dur = - dfs_retain_bin5_burst_pattern(dfs, - diff_ts, - re. - re_dur); - /* Remember our computed duration for the next pulse in the burst (if needed) */ - dfs->dfs_rinfo.dfs_bin5_chirp_ts = - this_ts; - dfs->dfs_rinfo.dfs_last_bin5_dur = - re.re_dur; + dfs_retain_bin5_burst_pattern(dfs, + diff_ts, re.re_dur, seg_id); + /* + * Remember our computed duration for + * the next pulse in the burst + * (if needed) + */ + if (seg_id == 0) + dfs->dfs_rinfo. + dfs_last_bin5_dur = + re.re_dur; + else + dfs->dfs_rinfo. + dfs_last_bin5_dur_ext_seg = + re.re_dur; if (dfs_bin5_addpulse (dfs, br, &re, this_ts)) { - found |= dfs_bin5_check(dfs); + found |= dfs_bin5_check(dfs, + seg_id); } } else { DFS_DPRINTK(dfs, @@ -607,19 +635,18 @@ int dfs_process_radarevent(struct ath_dfs *dfs, for (p = 0, found = 0; (p < ft->ft_numfilters) && (!found); p++) { rf = &(ft->ft_filters[p]); + dl = (seg_id == 0) ? &rf->rf_dl : + &rf->rf_dl_ext_seg; if ((re.re_dur >= rf->rf_mindur) && (re.re_dur <= rf->rf_maxdur)) { /* The above check is probably not necessary */ deltaT = - (this_ts < - rf->rf_dl. - dl_last_ts) - ? (int64_t) ((DFS_TSF_WRAP - - rf->rf_dl. - dl_last_ts) + - this_ts + - 1) : this_ts - - rf->rf_dl.dl_last_ts; + (this_ts < dl->dl_last_ts) ? + (int64_t) + ((DFS_TSF_WRAP - + dl->dl_last_ts) + + this_ts + 1) : + this_ts - dl->dl_last_ts; if ((deltaT < rf->rf_minpri) && (deltaT != 0)) { @@ -663,8 +690,8 @@ int dfs_process_radarevent(struct ath_dfs *dfs, long)deltaT, rf->rf_minpri); /* But update the last time stamp */ - rf->rf_dl.dl_last_ts = - this_ts; + dl->dl_last_ts = + this_ts; continue; } } else { @@ -702,13 +729,13 @@ int dfs_process_radarevent(struct ath_dfs *dfs, long)deltaT, rf->rf_minpri); /* But update the last time stamp */ - rf->rf_dl.dl_last_ts = - this_ts; + dl->dl_last_ts = + this_ts; continue; } } dfs_add_pulse(dfs, rf, &re, deltaT, - this_ts); + this_ts, seg_id); /* If this is an extension channel event, flag it for false alarm reduction */ if (re.re_chanindex == @@ -717,25 +744,23 @@ int dfs_process_radarevent(struct ath_dfs *dfs, } if (rf->rf_patterntype == 2) { found = - dfs_staggered_check(dfs, rf, - (uint32_t) - deltaT, - re. - re_dur); + dfs_staggered_check(dfs, + rf, + (uint32_t)deltaT, + re.re_dur, seg_id); } else { found = dfs_bin_check(dfs, rf, - (uint32_t) - deltaT, - re.re_dur, - ext_chan_event_flag); + (uint32_t)deltaT, + re.re_dur, + ext_chan_event_flag, + seg_id); } if (dfs-> dfs_debug_mask & ATH_DEBUG_DFS2) { - dfs_print_delayline(dfs, - &rf->rf_dl); + dfs_print_delayline(dfs, dl); } - rf->rf_dl.dl_last_ts = this_ts; + dl->dl_last_ts = this_ts; } } ft->ft_last_ts = this_ts; @@ -746,9 +771,10 @@ int dfs_process_radarevent(struct ath_dfs *dfs, ft->ft_mindur, rf != NULL ? rf->rf_pulseid : -1); CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, - "%s[%d]:### Found on channel minDur = %d,filterId = %d ###", + "%s[%d]:### Found on channel minDur = %d,filterId = %d seg_id = %d ###", __func__,__LINE__,ft->ft_mindur, - rf != NULL ? rf->rf_pulseid : -1); + rf != NULL ? rf->rf_pulseid : -1, + seg_id); } tabledepth++; } @@ -761,10 +787,21 @@ dfsfound: /* Collect stats */ dfs->ath_dfs_stats.num_radar_detects++; thischan = &rs->rs_chan; + + /* + * Since we support 80p80 mode, indicate the + * segment on which the radar has been detected. + * only if both segments are dfs in 80p80 mode + * and the radar is found on ext the segment + * ic_radar_found_segid is to 1, in all other + * cases it is set to 0. + */ + dfs->ic->ic_curchan->ic_radar_found_segid = seg_id; + CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, - "%s[%d]: ### RADAR FOUND ON CHANNEL %d (%d MHz) ###", - __func__, __LINE__, thischan->ic_ieee, - thischan->ic_freq); + "%s[%d]:### RADAR FOUND ON CHANNEL %d (%d MHz),seg_id=%d ###", + __func__, __LINE__, thischan->ic_ieee, + thischan->ic_freq, seg_id); DFS_PRINTK("Radar found on channel %d (%d MHz)", thischan->ic_ieee, thischan->ic_freq); @@ -775,7 +812,22 @@ dfsfound: ath_hal_setrxfilter(ah, rfilt); #endif dfs_reset_radarq(dfs); - dfs_reset_alldelaylines(dfs); + + /* + * For now reset both segments + * until we have changes for us + * to do sub-channel marking which + * enables SAP to continue to use the 80 + * segment where radar was not detected + * and as a result CAC can be avoided on + * that segment. Currently we do not support + * sub-channel marking. + */ + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG0); + + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dfs_reset_alldelaylines(dfs, DFS_80P80_SEG1); + /* XXX Should we really enable again? Maybe not... */ /* No reason to re-enable so far - Ajay*/ #if 0 diff --git a/core/sap/dfs/src/dfs_staggered.c b/core/sap/dfs/src/dfs_staggered.c index 71c04b573b0a..cf00e741d1ad 100644 --- a/core/sap/dfs/src/dfs_staggered.c +++ b/core/sap/dfs/src/dfs_staggered.c @@ -96,7 +96,7 @@ static int is_unique_pri(uint32_t highestpri, uint32_t midpri, } int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, - uint32_t deltaT, uint32_t width) + uint32_t deltaT, uint32_t width, int seg_id) { uint32_t refpri, refdur, searchpri = 0, deltapri; /* , averagerefpri; */ uint32_t n, i, primargin, durmargin; @@ -112,7 +112,11 @@ int dfs_staggered_check(struct ath_dfs *dfs, struct dfs_filter *rf, uint32_t midscore = 0, midscoreindex = 0, midpri = 0; uint32_t highestscore = 0, highestscoreindex = 0, highestpri = 0; - dl = &rf->rf_dl; + if (dfs->ic->ic_curchan->ic_80p80_both_dfs) + dl = (seg_id == 0) ? &rf->rf_dl : &rf->rf_dl_ext_seg; + else + dl = &rf->rf_dl; + if (dl->dl_numelems < (rf->rf_threshold - 1)) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "numelems %d < threshold for filter %d\n", diff --git a/core/wma/inc/wma_dfs_interface.h b/core/wma/inc/wma_dfs_interface.h index 27fa5b4fe31a..39f031740270 100644 --- a/core/wma/inc/wma_dfs_interface.h +++ b/core/wma/inc/wma_dfs_interface.h @@ -91,6 +91,12 @@ #define IEEE80211_IS_CHAN_11AC_VHT80(_c) \ (((_c)->ic_flags & IEEE80211_CHAN_11AC_VHT80) == \ IEEE80211_CHAN_11AC_VHT80) +#define IEEE80211_IS_CHAN_11AC_VHT80P80(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_VHT80P80) == \ + IEEE80211_CHAN_VHT80P80) +#define IEEE80211_IS_CHAN_11AC_VHT160(_c) \ + (((_c)->ic_flags & IEEE80211_CHAN_VHT160) == \ + IEEE80211_CHAN_VHT160) #define CHANNEL_108G \ (IEEE80211_CHAN_2GHZ|IEEE80211_CHAN_OFDM|IEEE80211_CHAN_TURBO) @@ -120,6 +126,8 @@ * @ic_vhtop_ch_freq_seg1: channel center frequency * @ic_vhtop_ch_freq_seg2: Channel Center frequency applicable * @ic_pri_freq_center_freq_mhz_separation: separation b/w pri and center freq + * @ic_80p80_both_dfs: Flag indicating if both 80p80 segments are dfs + * @ic_radar_found_segid: Indicates seg ID on which radar is found in 80p80 mode */ struct dfs_ieee80211_channel { uint32_t ic_freq; @@ -137,6 +145,7 @@ struct dfs_ieee80211_channel { uint32_t ic_vhtop_ch_freq_seg2; int ic_pri_freq_center_freq_mhz_separation; bool ic_80p80_both_dfs; + int ic_radar_found_segid; }; /**