int dfs_get_filter_threshold(struct ath_softc *sc, struct dfs_filter *rf, int is_extchan_detect) { int ext_chan_busy=0; int thresh, adjust_thresh=0; struct ath_dfs *dfs = sc->sc_dfs; thresh = rf->rf_threshold; if (IS_CHAN_HT40(&sc->sc_curchan)) { ext_chan_busy = ath_hal_get11nextbusy(sc->sc_ah); if(ext_chan_busy >= 0) { dfs->dfs_rinfo.ext_chan_busy_ts = ath_hal_gettsf64(sc->sc_ah); dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; } else { // Check to see if the cached value of ext_chan_busy can be used ext_chan_busy = 0; if (dfs->dfs_rinfo.dfs_ext_chan_busy) { if (dfs->dfs_rinfo.rn_lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) { ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy; DFS_DPRINTK(sc, ATH_DEBUG_DFS2," THRESH Use cached copy of ext_chan_busy extchanbusy=%d rn_lastfull_ts=%llu ext_chan_busy_ts=%llu\n", ext_chan_busy ,(unsigned long long)dfs->dfs_rinfo.rn_lastfull_ts, (unsigned long long)dfs->dfs_rinfo.ext_chan_busy_ts); } } } adjust_thresh = adjust_thresh_per_chan_busy(ext_chan_busy, thresh); DFS_DPRINTK(sc, ATH_DEBUG_DFS2," filterID=%d extchanbusy=%d adjust_thresh=%d\n", rf->rf_pulseid, ext_chan_busy, adjust_thresh); thresh += adjust_thresh; } return thresh; }
/* * Finds the radar state entry that matches the current channel */ struct dfs_state * dfs_getchanstate(struct ath_softc *sc, u_int8_t *index, int ext_chan_flag) { struct ath_dfs *dfs=sc->sc_dfs; struct dfs_state *rs=NULL; int i; HAL_CHANNEL *cmp_ch; if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS,"%s: sc_dfs is NULL\n", __func__); return NULL; } if (ext_chan_flag) { cmp_ch = (ath_hal_get_extension_channel(sc->sc_ah)); if (cmp_ch) { DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "Extension channel freq = %u flags=0x%x\n", cmp_ch->channel, cmp_ch->priv_flags); } else { return NULL; } } else { cmp_ch = &sc->sc_curchan; DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "Primary channel freq = %u flags=0x%x\n", cmp_ch->channel, cmp_ch->priv_flags); } for (i=0;i<DFS_NUM_RADAR_STATES; i++) { if ((dfs->dfs_radar[i].rs_chan.channel == cmp_ch->channel) && (dfs->dfs_radar[i].rs_chan.channel_flags == cmp_ch->channel_flags)) { if (index != NULL) *index = (u_int8_t) i; return &(dfs->dfs_radar[i]); } } /* No existing channel found, look for first free channel state entry */ for (i=0; i<DFS_NUM_RADAR_STATES; i++) { if (dfs->dfs_radar[i].rs_chan.channel == 0) { rs = &(dfs->dfs_radar[i]); /* Found one, set channel info and default thresholds */ rs->rs_chan = *cmp_ch; rs->rs_firpwr = dfs->dfs_defaultparams.pe_firpwr; rs->rs_radarrssi = dfs->dfs_defaultparams.pe_rrssi; rs->rs_height = dfs->dfs_defaultparams.pe_height; rs->rs_pulserssi = dfs->dfs_defaultparams.pe_prssi; rs->rs_inband = dfs->dfs_defaultparams.pe_inband; /* 5413 specific */ rs->rs_relpwr = dfs->dfs_defaultparams.pe_relpwr; rs->rs_relstep = dfs->dfs_defaultparams.pe_relstep; rs->rs_maxlen = dfs->dfs_defaultparams.pe_maxlen; if (index != NULL) *index = (u_int8_t) i; return (rs); } } DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "%s: No more radar states left.\n", __func__); return(NULL); }
void ath_ar_enable(struct ath_softc *sc) { struct ath_dfs *dfs=sc->sc_dfs; struct dfs_ar_state *ar; HAL_CHANNEL *chan= &sc->sc_curchan; HAL_PHYERR_PARAM pe; u_int32_t rfilt=0; if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return; } ar = (struct dfs_ar_state *) &dfs->dfs_ar_state; if (dfs->dfs_proc_phyerr & (DFS_RADAR_EN | DFS_AR_EN)) { if ((chan->channel_flags & CHANNEL_108G) == CHANNEL_108G) { /* We are in turbo G, so enable AR */ DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: Enabling AR\n", __func__); dfs_reset_ar(sc); ar->ar_radarrssi = DFS_AR_RADAR_RSSI_THR; rfilt = ath_hal_getrxfilter(sc->sc_ah); pe.pe_firpwr = HAL_PHYERR_PARAM_NOVAL; pe.pe_height = HAL_PHYERR_PARAM_NOVAL; pe.pe_prssi = HAL_PHYERR_PARAM_NOVAL; pe.pe_inband = HAL_PHYERR_PARAM_NOVAL; pe.pe_relpwr = HAL_PHYERR_PARAM_NOVAL; pe.pe_maxlen = HAL_PHYERR_PARAM_NOVAL; pe.pe_relstep = HAL_PHYERR_PARAM_NOVAL; pe.pe_usefir128 = 0; pe.pe_blockradar = 0; pe.pe_enmaxrssi = 0; pe.pe_rrssi = ar->ar_radarrssi; ath_hal_enabledfs(sc->sc_ah, &pe); /* Enable strong signal fast antenna diversity since accurate * 1-2us radar * detection is not important for AR anyways. */ ath_hal_setcapability(sc->sc_ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, dfs->dfs_rinfo.rn_fastdivGCval, NULL); rfilt |= HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(sc->sc_ah, rfilt); } } else { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: Disabling AR\n", __func__); rfilt = ath_hal_getrxfilter(sc->sc_ah); rfilt &= ~HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(sc->sc_ah,rfilt); /* Enable strong signal fast antenna diversity */ ath_hal_setcapability(sc->sc_ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, dfs->dfs_rinfo.rn_fastdivGCval, NULL); } }
void dfs_print_activity(struct ath_softc *sc) { int chan_busy=0, ext_chan_busy=0; u_int32_t rxclear=0, rxframe=0, txframe=0, cycles=0; cycles = ath_hal_getMibCycleCountsPct(sc->sc_ah,&rxclear, &rxframe, &txframe); chan_busy = cycles; ext_chan_busy = ath_hal_get11nextbusy(sc->sc_ah); DFS_DPRINTK(sc, ATH_DEBUG_DFS,"cycles=%d rxclear=%d rxframe=%d txframe=%d extchanbusy=%d\n", cycles, rxclear, rxframe, txframe, ext_chan_busy); DFS_DPRINTK(sc, ATH_DEBUG_DFS, "FILT_OFDM=0x%x FILT_CCK=0x%x\n",(0x00FFFFFF & OS_REG_READ(sc->sc_ah, 0x8124)), (0x00FFFFFF & OS_REG_READ(sc->sc_ah, 0x8128))); return; }
int dfs_get_pri_margin(struct ath_softc *sc, int is_extchan_detect, int is_fixed_pattern) { int adjust_pri=0, ext_chan_busy=0; int pri_margin; struct ath_dfs *dfs = sc->sc_dfs; if (is_fixed_pattern) pri_margin = DFS_DEFAULT_FIXEDPATTERN_PRI_MARGIN; else pri_margin = DFS_DEFAULT_PRI_MARGIN; if (IS_CHAN_HT40(&sc->sc_curchan)) { ext_chan_busy = ath_hal_get11nextbusy(sc->sc_ah); if(ext_chan_busy >= 0) { dfs->dfs_rinfo.ext_chan_busy_ts = ath_hal_gettsf64(sc->sc_ah); dfs->dfs_rinfo.dfs_ext_chan_busy = ext_chan_busy; } else { // Check to see if the cached value of ext_chan_busy can be used ext_chan_busy = 0; if (dfs->dfs_rinfo.dfs_ext_chan_busy ) { if (dfs->dfs_rinfo.rn_lastfull_ts < dfs->dfs_rinfo.ext_chan_busy_ts) { ext_chan_busy = dfs->dfs_rinfo.dfs_ext_chan_busy; DFS_DPRINTK(sc, ATH_DEBUG_DFS2," PRI Use cached copy of ext_chan_busy extchanbusy=%d \n", ext_chan_busy); } } } adjust_pri = adjust_pri_per_chan_busy(ext_chan_busy, pri_margin); pri_margin -= adjust_pri; } return pri_margin; }
void dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan) { #define TIME_IN_MS 1000 u_int32_t nol_time_left_ms; struct ieee80211_channel chan; int i; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); return; } for (i = 0; i < nchan; i++) { nol_time_left_ms = adf_os_ticks_to_msecs(adf_os_ticks() - dfs_nol[i].nol_start_ticks); if (nol_time_left_ms < dfs_nol[i].nol_timeout_ms) { chan.ic_freq = dfs_nol[i].nol_freq; chan.ic_flags= 0; chan.ic_flagext = 0; nol_time_left_ms = (dfs_nol[i].nol_timeout_ms - nol_time_left_ms); dfs_nol_addchan(dfs, &chan, (nol_time_left_ms / TIME_IN_MS)); } } #undef TIME_IN_MS dfs_nol_update(dfs); }
void dfs_add_pulse(struct ath_dfs_host *dfs, struct dfs_filter *rf, struct dfs_event *re, u_int32_t deltaT) { u_int32_t index,n, window, pri; struct dfs_delayline *dl; 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) */ if ((dl->dl_numelems) == DFS_MAX_DL_SIZE) dl->dl_firstelem = (dl->dl_firstelem + 1) & DFS_MAX_DL_MASK; else dl->dl_numelems++; dl->dl_lastelem = index; dl->dl_elems[index].de_time = deltaT; window = deltaT; dl->dl_elems[index].de_dur = re->re_dur; dl->dl_elems[index].de_rssi = re->re_rssi; for (n=0;n<dl->dl_numelems-1; n++) { index = (index-1) & DFS_MAX_DL_MASK; pri = dl->dl_elems[index].de_time; window += pri; if (window > rf->rf_filterlen) { dl->dl_firstelem = (index+1) & DFS_MAX_DL_MASK; dl->dl_numelems = n+1; } } DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "dl firstElem = %d lastElem = %d\n",dl->dl_firstelem, dl->dl_lastelem); }
void dfs_print_filters(struct ath_softc *sc) { struct ath_dfs *dfs=sc->sc_dfs; struct dfs_filtertype *ft = NULL; struct dfs_filter *rf; int i,j; if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return; } for (i=0; i<DFS_MAX_RADAR_TYPES; i++) { if (dfs->dfs_radarf[i] != NULL) { ft = dfs->dfs_radarf[i]; if((ft->ft_numfilters > DFS_MAX_NUM_RADAR_FILTERS) || (!ft->ft_numfilters)) continue; printk("===========ft->ft_numfilters=%u===========\n", ft->ft_numfilters); for (j=0; j<ft->ft_numfilters; j++) { rf = &(ft->ft_filters[j]); printk("filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n",j, rf->rf_pulseid, rf->rf_numpulses, rf->rf_minpri, rf->rf_maxpri, rf->rf_threshold, rf->rf_filterlen, rf->rf_mindur, rf->rf_maxdur); } } } }
/* * Parse the radar summary frame. * * The frame contents _minus_ the TLV are passed in. */ static void radar_summary_parse(struct ath_dfs *dfs, const char *buf, size_t len, struct rx_radar_status *rsu) { uint32_t rs[2]; /* 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 (%d) < expected (%d)!\n", __func__, len, sizeof(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. */ OS_MEMCPY(rs, buf, sizeof(rs)); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x\n", __func__, rs[0], rs[1]); // DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s (p=%p):\n", __func__, buf); /* 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)); /* 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); }
/* * Process an Owl-style phy error. * * Return 1 on success or 0 on failure. */ int dfs_process_phyerr_owl(struct ath_dfs *dfs, void *buf, uint16_t datalen, uint8_t rssi, uint8_t ext_rssi, uint32_t rs_tstamp, uint64_t fulltsf, struct dfs_phy_err *e) { const char *cbuf = (const char *)buf; uint8_t dur; int event_width; /* XXX this shouldn't be kept count here */ dfs->ath_dfs_stats.owl_phy_errors++; /* * HW cannot detect extension channel radar so it only passes us * primary channel radar data */ if (datalen == 0) dur = 0; else dur = ((uint8_t *) cbuf)[0]; /* * This is a spurious event; toss. */ if (rssi == 0 && dur == 0) dfs->ath_dfs_stats.datalen_discards++; return 0; /* * Fill out dfs_phy_err with the information we have * at hand. */ OS_MEMSET(e, 0, sizeof(*e)); e->rssi = rssi; e->dur = dur; e->is_pri = 1; e->is_ext = 0; e->is_dc = 0; e->is_early = 1; e->fulltsf = fulltsf; e->rs_tstamp = rs_tstamp; /* * Owl only ever reports events on the primary channel; * it doesn't even see events on the secondary channel. */ event_width = dfs_get_event_freqwidth(dfs); e->freq = dfs_get_event_freqcentre(dfs, 1, 0, 0) * 1000; e->freq_lo = e->freq - (event_width / 2) * 1000; e->freq_hi = e->freq + (event_width / 2) * 1000; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR_SUM, "%s: rssi=%u dur=%u,freq=%dMHz, freq_lo=%dMHz, freq_hi=%dMHz\n", __func__, rssi, dur, e->freq / 1000, e->freq_lo / 1000, e->freq_hi / 1000); return 1; }
u_int8_t dfs_retain_bin5_burst_pattern(struct ath_dfs_host *dfs, u_int32_t diff_ts, u_int8_t old_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 cannot detect the chirping // SPLIT pulses will have a time stamp difference of < 50 if (diff_ts < 50) { DFS_DPRINTK(dfs,ATH_DEBUG_DFS1,"%s SPLIT pulse diffTs=%u dur=%d (old_dur=%d)\n", __func__, diff_ts, dfs->dfs_rinfo.dfs_last_bin5_dur, old_dur); } // Check if this is the 2nd or 3rd pulse in the same burst, PRI will be between 1000 and 2000 us if(((diff_ts >= DFS_BIN5_PRI_LOWER_LIMIT) && (diff_ts <= DFS_BIN5_PRI_HIGHER_LIMIT))) { //This pulse belongs to the same burst as the pulse before, so return the same random duration for it DFS_DPRINTK(dfs,ATH_DEBUG_DFS1,"%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); return (dfs->dfs_rinfo.dfs_last_bin5_dur); } // This pulse does not belong to this burst, return unchanged duration return old_dur; }
/* * Delete the given frequency/chwidth from the NOL. */ static void dfs_nol_delete(struct ath_dfs *dfs, u_int16_t delfreq, u_int16_t delchwidth) { struct dfs_nolelem *nol,**prev_next; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return; } DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: remove channel=%d/%d MHz from NOL\n", __func__, delfreq, delchwidth); prev_next = &(dfs->dfs_nol); nol = dfs->dfs_nol; while (nol != NULL) { if (nol->nol_freq == delfreq && nol->nol_chwidth == delchwidth) { *prev_next = nol->nol_next; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s removing channel %d/%dMHz from NOL tstamp=%d\n", __func__, nol->nol_freq, nol->nol_chwidth, (adf_os_ticks_to_msecs(adf_os_ticks()) / 1000)); OS_CANCEL_TIMER(&nol->nol_timer); OS_FREE(nol); nol = NULL; nol = *prev_next; /* Update the NOL counter */ dfs->dfs_nol_count--; /* Be paranoid! */ if (dfs->dfs_nol_count < 0) { DFS_PRINTK("%s: dfs_nol_count < 0; eek!\n", __func__); dfs->dfs_nol_count = 0; } } else { prev_next = &(nol->nol_next); nol = nol->nol_next; } } }
static void radar_fft_search_report_parse(struct ath_dfs *dfs, const char *buf, size_t len, struct rx_search_fft_report *rsfr) { uint32_t rs[2]; /* 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 (%d) < expected (%d)!\n", __func__, len, sizeof(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. */ OS_MEMCPY(rs, buf, sizeof(rs)); rsfr->total_gain_db = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_TOTAL_GAIN_DB); rsfr->base_pwr_db = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_BASE_PWR_DB); rsfr->fft_chn_idx = MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_FFT_CHN_IDX); rsfr->peak_sidx = sign_extend_32(MS(rs[SEARCH_FFT_REPORT_REG_1], SEARCH_FFT_REPORT_PEAK_SIDX), 12); rsfr->relpwr_db = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_RELPWR_DB); rsfr->avgpwr_db = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_AVGPWR_DB); rsfr->peak_mag = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_PEAK_MAG); rsfr->num_str_bins_ib = MS(rs[SEARCH_FFT_REPORT_REG_2], SEARCH_FFT_REPORT_NUM_STR_BINS_IB); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: two 32 bit values are: %08x %08x\n", __func__, rs[0], rs[1]); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->total_gain_db = %d\n", __func__, rsfr->total_gain_db); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->base_pwr_db = %d\n", __func__, rsfr->base_pwr_db); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->fft_chn_idx = %d\n", __func__, rsfr->fft_chn_idx); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->peak_sidx = %d\n", __func__, rsfr->peak_sidx); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->relpwr_db = %d\n", __func__, rsfr->relpwr_db); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->avgpwr_db = %d\n", __func__, rsfr->avgpwr_db); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->peak_mag = %d\n", __func__, rsfr->peak_mag); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR,"%s: rsfr->num_str_bins_ib = %d\n", __func__, rsfr->num_str_bins_ib); }
void dfs_reset_ar(struct ath_softc *sc) { struct ath_dfs *dfs=sc->sc_dfs; if (dfs == NULL) { DFS_DPRINTK(sc,ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return; } OS_MEMZERO(&dfs->dfs_ar_state, sizeof(dfs->dfs_ar_state)); dfs->dfs_ar_state.ar_packetthreshold = DFS_AR_PKT_COUNT_THRESH; dfs->dfs_ar_state.ar_parthreshold = DFS_AR_ACK_DETECT_PAR_THRESH; }
void dfs_print_nol(struct ath_dfs *dfs) { struct dfs_nolelem *nol; int i = 0; uint32_t diff_ms, remaining_sec; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); return; } nol = dfs->dfs_nol; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: NOL\n", __func__); while (nol != NULL) { diff_ms = adf_os_ticks_to_msecs(adf_os_ticks() - nol->nol_start_ticks); diff_ms = (nol->nol_timeout_ms - diff_ms); remaining_sec = diff_ms / 1000; /* convert to seconds */ printk("nol:%d channel=%d MHz width=%d MHz time left=%u seconds nol starttick=%llu \n", i++, nol->nol_freq, nol->nol_chwidth, remaining_sec, (unsigned long long)nol->nol_start_ticks); nol = nol->nol_next; } }
void dfs_print_delayline(struct ath_softc *sc, struct dfs_delayline *dl) { int i=0,index; struct dfs_delayelem *de; index = dl->dl_lastelem; for (i=0; i<dl->dl_numelems; i++) { de = &dl->dl_elems[index]; DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "Elem %d: ts = %u (0x%x) dur=%u\n",i, de->de_time, de->de_time, de->de_dur); index = (index - 1)& DFS_MAX_DL_MASK; } }
void dfs_reset_radarq(struct ath_dfs *dfs) { struct dfs_event *event; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL", __func__); return; } ATH_DFSQ_LOCK(dfs); ATH_DFSEVENTQ_LOCK(dfs); while (!STAILQ_EMPTY(&(dfs->dfs_radarq))) { event = STAILQ_FIRST(&(dfs->dfs_radarq)); STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); OS_MEMZERO(event, sizeof(struct dfs_event)); STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); } ATH_DFSEVENTQ_UNLOCK(dfs); ATH_DFSQ_UNLOCK(dfs); }
void ath_ar_disable(struct ath_softc *sc) { u_int32_t rfilt; HAL_CHANNEL *chan=&sc->sc_curchan; struct ath_dfs *dfs=sc->sc_dfs; if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return; } if ((chan->channel_flags & CHANNEL_108G) == CHANNEL_108G) { /* Enable strong signal fast antenna diversity */ ath_hal_setcapability(sc->sc_ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, dfs->dfs_rinfo.rn_fastdivGCval, NULL); rfilt = ath_hal_getrxfilter(sc->sc_ah); rfilt &= ~HAL_RX_FILTER_PHYERR; ath_hal_setrxfilter(sc->sc_ah, rfilt); dfs_reset_ar(sc); dfs_reset_arq(sc); } }
void dfs_radar_task (unsigned long arg) { struct ath_dfs_host *dfs = (struct ath_dfs_host *)arg; A_INT16 chan_index; A_UINT8 bangradar; //printk("\n%s\n",__func__); if(dfs_process_radarevent_host(dfs, &chan_index, &bangradar)){ if(!bangradar){ DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Radar detected on channel idx %d\n", __func__, chan_index); } /* TODO: The radar detected event is sent from host in timer * context which could potentially cause issues with sleepable * WMI. Change this to process context later. */ DFS_RADAR_DETECTED(dfs->dev_hdl, chan_index, bangradar); } }
void dfs_add_pulse(struct ath_softc *sc, struct dfs_filter *rf, struct dfs_event *re, u_int32_t deltaT, u_int64_t this_ts) { u_int32_t index,n, window; struct dfs_delayline *dl; 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) if ((dl->dl_numelems) == DFS_MAX_DL_SIZE) dl->dl_firstelem = (dl->dl_firstelem + 1) & DFS_MAX_DL_MASK; else dl->dl_numelems++; dl->dl_lastelem = index; dl->dl_elems[index].de_time = deltaT; dl->dl_elems[index].de_ts = this_ts; window = deltaT; dl->dl_elems[index].de_dur = re->re_dur; dl->dl_elems[index].de_rssi = re->re_rssi; for (n=0;n<dl->dl_numelems-1; n++) { index = (index-1) & DFS_MAX_DL_MASK; /* * calculate window based on full time stamp instead of deltaT * deltaT (de_time) may result in incorrect window value */ window = (u_int32_t) (this_ts - dl->dl_elems[index].de_ts); if (window > rf->rf_filterlen) { dl->dl_firstelem = (index+1) & DFS_MAX_DL_MASK; dl->dl_numelems = n+1; } } DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "dl firstElem = %d lastElem = %d\n",dl->dl_firstelem, dl->dl_lastelem); }
static void radar_summary_print(struct ath_dfs *dfs, struct rx_radar_status *rsu) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " pulsedur=%d\n", rsu->pulse_duration); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " rssi=%d\n", rsu->rssi); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " ischirp=%d\n", rsu->is_chirp); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " sidx=%d\n", rsu->sidx); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " raw tsf=%d\n", rsu->raw_tsf); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " tsf_offset=%d\n", rsu->tsf_offset); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " cooked tsf=%d\n", rsu->raw_tsf - rsu->tsf_offset); DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, " frequency offset=%d.%d MHz (oversampling=%d)\n", (int) (rsu->freq_offset / 1000), (int) abs(rsu->freq_offset % 1000), PERE_IS_OVERSAMPLING(dfs)); }
/* * Clear all delay lines for all filter types */ void dfs_reset_alldelaylines(struct ath_softc *sc) { struct ath_dfs *dfs=sc->sc_dfs; struct dfs_filtertype *ft = NULL; struct dfs_filter *rf; struct dfs_delayline *dl; struct dfs_pulseline *pl; int i,j; if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return; } pl = dfs->pulses; /* reset the pulse log */ pl->pl_firstelem = pl->pl_numelems = 0; pl->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; for (i=0; i<DFS_MAX_RADAR_TYPES; i++) { if (dfs->dfs_radarf[i] != NULL) { ft = dfs->dfs_radarf[i]; for (j=0; j<ft->ft_numfilters; j++) { rf = &(ft->ft_filters[j]); dl = &(rf->rf_dl); if(dl != NULL) { OS_MEMZERO(dl, sizeof(struct dfs_delayline)); dl->dl_lastelem = (0xFFFFFFFF) & DFS_MAX_DL_MASK; } } } } 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; } }
void dfs_get_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int *nchan) { struct dfs_nolelem *nol; *nchan = 0; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); return; } nol = dfs->dfs_nol; while (nol != NULL) { dfs_nol[*nchan].nol_freq = nol->nol_freq; dfs_nol[*nchan].nol_chwidth = nol->nol_chwidth; dfs_nol[*nchan].nol_start_ticks = nol->nol_start_ticks; dfs_nol[*nchan].nol_timeout_ms = nol->nol_timeout_ms; ++(*nchan); nol = nol->nol_next; } }
void dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, uint8_t r_rssi, uint8_t r_ext_rssi, uint32_t r_rs_tstamp, uint64_t r_fulltsf, bool enable_log) { struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; struct dfs_ieee80211_channel *chan = ic->ic_curchan; struct dfs_event *event; struct dfs_phy_err e; int empty; if (dfs == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, "%s: sc_dfs is NULL\n", __func__); return; } dfs->dfs_phyerr_count++; dump_phyerr_contents(buf, datalen); /* * XXX The combined_rssi_ok support has been removed. * This was only clear for Owl. * * XXX TODO: re-add this; it requires passing in the ctl/ext * RSSI set from the RX status descriptor. * * XXX TODO TODO: this may be done for us from the legacy * phy error path in ath_dev; please review that code. */ /* * At this time we have a radar pulse that we need to examine and * queue. But if dfs_process_radarevent already detected radar and set * CHANNEL_INTERFERENCE flag then do not queue any more radar data. * When we are in a new channel this flag will be clear and we will * start queueing data for new channel. (EV74162) */ if (dfs->dfs_debug_mask & ATH_DEBUG_DFS_PHYERR_PKT) dump_phyerr_contents(buf, datalen); if (chan == NULL) { CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR, "%s: chan is NULL\n", __func__); return; } cdf_spin_lock_bh(&ic->chan_lock); if (IEEE80211_IS_CHAN_RADAR(chan)) { cdf_spin_unlock_bh(&ic->chan_lock); DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s: Radar already found in the channel, " " do not queue radar data\n", __func__); return; } cdf_spin_unlock_bh(&ic->chan_lock); dfs->ath_dfs_stats.total_phy_errors++; DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s[%d] phyerr %d len %d\n", __func__, __LINE__, dfs->ath_dfs_stats.total_phy_errors, datalen); /* * hardware stores this as 8 bit signed value. * we will cap it at 0 if it is a negative number */ if (r_rssi & 0x80) r_rssi = 0; if (r_ext_rssi & 0x80) r_ext_rssi = 0; OS_MEMSET(&e, 0, sizeof(e)); /* * This is a bit evil - instead of just passing in * the chip version, the existing code uses a set * of HAL capability bits to determine what is * possible. * * The way I'm decoding it is thus: * * + DFS enhancement? Merlin or later * + DFS extension channel? Sowl or later. (Howl?) * + otherwise, Owl (and legacy.) */ if (dfs->dfs_caps.ath_chip_is_bb_tlv) { if (dfs_process_phyerr_bb_tlv(dfs, buf, datalen, r_rssi, r_ext_rssi, r_rs_tstamp, r_fulltsf, &e, enable_log) == 0) { dfs->dfs_phyerr_reject_count++; return; } else { if (dfs->dfs_phyerr_freq_min > e.freq) dfs->dfs_phyerr_freq_min = e.freq; if (dfs->dfs_phyerr_freq_max < e.freq) dfs->dfs_phyerr_freq_max = e.freq; } } else if (dfs->dfs_caps.ath_dfs_use_enhancement) { if (dfs_process_phyerr_merlin(dfs, buf, datalen, r_rssi, r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0) { return; } } else if (dfs->dfs_caps.ath_dfs_ext_chan_ok) { if (dfs_process_phyerr_sowl(dfs, buf, datalen, r_rssi, r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0) { return; } } else { if (dfs_process_phyerr_owl(dfs, buf, datalen, r_rssi, r_ext_rssi, r_rs_tstamp, r_fulltsf, &e) == 0) { return; } } CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO, "\n %s: Frequency at which the phyerror was injected = %d", __func__, e.freq); /* * If the hardware supports radar reporting on the extension channel * it will supply FFT data for longer radar pulses. * * TLV chips don't go through this software check - the hardware * check should be enough. If we want to do software checking * later on then someone will have to craft an FFT parser * suitable for the TLV FFT data format. */ if ((!dfs->dfs_caps.ath_chip_is_bb_tlv) && dfs->dfs_caps.ath_dfs_ext_chan_ok) { /* * HW has a known issue with chirping pulses injected at or * around DC in 40MHz mode. Such pulses are reported with * much lower durations and SW then discards them because * they do not fit the minimum bin5 pulse duration. * * To work around this issue, if a pulse is within a 10us * range of the bin5 min duration, check if the pulse is * chirping. If the pulse is chirping, bump up the duration * to the minimum bin5 duration. * * This makes sure that a valid chirping pulse will not be * discarded because of incorrect low duration. * * TBD - Is it possible to calculate the 'real' duration of * the pulse using the slope of the FFT data? * * TBD - Use FFT data to differentiate between radar pulses * and false PHY errors. * This will let us reduce the number of false alarms seen. * * BIN 5 chirping pulses are only for FCC or Japan MMK4 domain */ if (((dfs->dfsdomain == DFS_FCC_DOMAIN) || (dfs->dfsdomain == DFS_MKK4_DOMAIN)) && (e.dur >= MAYBE_BIN5_DUR) && (e.dur < MAX_BIN5_DUR)) { int add_dur; int slope = 0, dc_found = 0; /* * Set the event chirping flags; as we're doing * an actual chirp check. */ e.do_check_chirp = 1; e.is_hw_chirp = 0; e.is_sw_chirp = 0; /* * dfs_check_chirping() expects is_pri and is_ext * to be '1' for true and '0' for false for now, * as the function itself uses these values in * constructing things rather than testing them * for 'true' or 'false'. */ add_dur = dfs_check_chirping(dfs, buf, datalen, (e.is_pri ? 1 : 0), (e.is_ext ? 1 : 0), &slope, &dc_found); if (add_dur) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "old dur %d slope =%d\n", e.dur, slope); e.is_sw_chirp = 1; /* bump up to a random bin5 pulse duration */ if (e.dur < MIN_BIN5_DUR) { e.dur = dfs_get_random_bin5_dur(dfs, e.fulltsf); } DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "new dur %d\n", e.dur); } else { /* set the duration so that it is rejected */ e.is_sw_chirp = 0; e.dur = MAX_BIN5_DUR + 100; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "is_chirping = %d dur=%d\n", add_dur, e.dur); } } else { /* * We have a pulse that is either bigger than * MAX_BIN5_DUR or * less than MAYBE_BIN5_DUR */ if ((dfs->dfsdomain == DFS_FCC_DOMAIN) || (dfs->dfsdomain == DFS_MKK4_DOMAIN)) { /* * XXX Would this result in very large pulses * wrapping around to become short pulses? */ if (e.dur >= MAX_BIN5_DUR) { /* * set the duration so that it is * rejected */ e.dur = MAX_BIN5_DUR + 50; } } } } /* * Add the parsed, checked and filtered entry to the radar pulse * event list. This is then checked by dfs_radar_processevent(). * * XXX TODO: some filtering is still done below this point - fix * XXX this! */ ATH_DFSEVENTQ_LOCK(dfs); empty = STAILQ_EMPTY(&(dfs->dfs_eventq)); ATH_DFSEVENTQ_UNLOCK(dfs); if (empty) { return; } /* * If the channel is a turbo G channel, then the event is * for the adaptive radio (AR) pattern matching rather than * radar detection. */ cdf_spin_lock_bh(&ic->chan_lock); if ((chan->ic_flags & CHANNEL_108G) == CHANNEL_108G) { cdf_spin_unlock_bh(&ic->chan_lock); if (!(dfs->dfs_proc_phyerr & DFS_AR_EN)) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "%s: DFS_AR_EN not enabled\n", __func__); return; } ATH_DFSEVENTQ_LOCK(dfs); event = STAILQ_FIRST(&(dfs->dfs_eventq)); if (event == NULL) { ATH_DFSEVENTQ_UNLOCK(dfs); DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: no more events space left\n", __func__); return; } STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); ATH_DFSEVENTQ_UNLOCK(dfs); event->re_rssi = e.rssi; event->re_dur = e.dur; event->re_full_ts = e.fulltsf; event->re_ts = (e.rs_tstamp) & DFS_TSMASK; event->re_chanindex = dfs->dfs_curchan_radindex; event->re_flags = 0; event->sidx = e.sidx; /* * Handle chirp flags. */ if (e.do_check_chirp) { event->re_flags |= DFS_EVENT_CHECKCHIRP; if (e.is_hw_chirp) event->re_flags |= DFS_EVENT_HW_CHIRP; if (e.is_sw_chirp) event->re_flags |= DFS_EVENT_SW_CHIRP; } ATH_ARQ_LOCK(dfs); STAILQ_INSERT_TAIL(&(dfs->dfs_arq), event, re_list); ATH_ARQ_UNLOCK(dfs); } else { if (IEEE80211_IS_CHAN_DFS(chan)) { cdf_spin_unlock_bh(&ic->chan_lock); if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, "%s: DFS_RADAR_EN not enabled\n", __func__); return; } /* * rssi is not accurate for short pulses, so do * not filter based on that for short duration pulses * * XXX do this filtering above? */ if (dfs->dfs_caps.ath_dfs_ext_chan_ok) { if ((e.rssi < dfs->dfs_rinfo.rn_minrssithresh && (e.dur > 4)) || e.dur > (dfs->dfs_rinfo.rn_maxpulsedur)) { dfs->ath_dfs_stats.rssi_discards++; DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "Extension channel pulse is " "discarded: dur=%d, " "maxpulsedur=%d, rssi=%d, " "minrssi=%d\n", e.dur, dfs->dfs_rinfo. rn_maxpulsedur, e.rssi, dfs->dfs_rinfo. rn_minrssithresh); return; } } else { if (e.rssi < dfs->dfs_rinfo.rn_minrssithresh || e.dur > dfs->dfs_rinfo.rn_maxpulsedur) { /* XXX TODO add a debug statement? */ dfs->ath_dfs_stats.rssi_discards++; return; } } /* * Add the event to the list, if there's space. */ ATH_DFSEVENTQ_LOCK(dfs); event = STAILQ_FIRST(&(dfs->dfs_eventq)); if (event == NULL) { ATH_DFSEVENTQ_UNLOCK(dfs); DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: no more events space left\n", __func__); return; } STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); ATH_DFSEVENTQ_UNLOCK(dfs); dfs->dfs_phyerr_queued_count++; dfs->dfs_phyerr_w53_counter++; event->re_dur = e.dur; event->re_full_ts = e.fulltsf; event->re_ts = (e.rs_tstamp) & DFS_TSMASK; event->re_rssi = e.rssi; event->sidx = e.sidx; /* * Handle chirp flags. */ if (e.do_check_chirp) { event->re_flags |= DFS_EVENT_CHECKCHIRP; if (e.is_hw_chirp) event->re_flags |= DFS_EVENT_HW_CHIRP; if (e.is_sw_chirp) event->re_flags |= DFS_EVENT_SW_CHIRP; } /* * Correctly set which channel is being reported on */ if (e.is_pri) { event->re_chanindex = dfs->dfs_curchan_radindex; } else { if (dfs->dfs_extchan_radindex == -1) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s - phyerr on ext channel\n", __func__); } event->re_chanindex = dfs->dfs_extchan_radindex; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_PHYERR, "%s New extension channel event is added " "to queue\n", __func__); } ATH_DFSQ_LOCK(dfs); STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list); ATH_DFSQ_UNLOCK(dfs); } else { cdf_spin_unlock_bh(&ic->chan_lock); } } /* * Schedule the radar/AR task as appropriate. * * XXX isn't a lock needed for ath_radar_tasksched? */ /* * Commenting out the dfs_process_ar_event() since the function is never * called at run time as dfs_arq will be empty and the function * dfs_process_ar_event is obsolete and function definition is removed * as part of dfs_ar.c file * * if (!STAILQ_EMPTY(&dfs->dfs_arq)) * // XXX shouldn't this be a task/timer too? * dfs_process_ar_event(dfs, ic->ic_curchan); */ if (!STAILQ_EMPTY(&dfs->dfs_radarq) && !dfs->ath_radar_tasksched) { dfs->ath_radar_tasksched = 1; OS_SET_TIMER(&dfs->ath_dfs_task_timer, 0); } #undef EXT_CH_RADAR_FOUND #undef PRI_CH_RADAR_FOUND #undef EXT_CH_RADAR_EARLY_FOUND }
int dfs_bin_pri_check(struct ath_dfs_host *dfs, struct dfs_filter *rf, struct dfs_delayline *dl, u_int32_t score, u_int32_t refpri, u_int32_t refdur, int ext_chan_flag, u_int32_t ext_chan_busy) { u_int32_t searchpri, searchdur, searchrssi, deltapri, deltadur, averagerefpri=0; int primultiples[6]; int delayindex, dindex; u_int32_t i, j, primargin, durmargin, highscore=score, highscoreindex=0; int numpulses=1; /*first pulse in the burst is most likely being filtered out based on maxfilterlen */ /*Use the adjusted PRI margin to reduce false alarms */ /* For non fixed pattern types, rf->rf_patterntype=0*/ primargin = dfs_get_pri_margin(ext_chan_flag, (rf->rf_patterntype==1), dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy); if(rf->rf_maxdur < 10) { durmargin = 4; } else { durmargin = 6; } if( score > 1) { for (i=0;i<dl->dl_numelems; i++) { dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; searchpri = dl->dl_elems[dindex].de_time; deltapri = DFS_DIFF(searchpri, refpri); if( deltapri < primargin) averagerefpri += searchpri; } refpri = (averagerefpri/score); /*average */ } /* Note: Following primultiple calculation should be done once per filter * during initialization stage (dfs_attach) and stored in its array * atleast for fixed frequency types like FCC Bin1 to save some CPU cycles. * multiplication, devide operators in the following code are left as it is * for readability hoping the complier will use left/right shifts wherever possible */ if( refpri > rf->rf_maxpri) { primultiples[0] = (refpri - refdur)/2; primultiples[1] = refpri; primultiples[2] = refpri + primultiples[0]; primultiples[3] = (refpri - refdur)*2; primultiples[4] = primultiples[3] + primultiples[0]; primultiples[5] = primultiples[3] + refpri; } else { primultiples[0] = refpri; primultiples[1] = refpri + primultiples[0]; primultiples[2] = refpri + primultiples[1]; primultiples[3] = refpri + primultiples[2]; primultiples[4] = refpri + primultiples[3]; primultiples[5] = refpri + primultiples[4]; } DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "pri0 = %d pri1 = %d pri2 = %d pri3 = %d pri4 = %d pri5 = %d\n", primultiples[0], primultiples[1], primultiples[2], primultiples[3], primultiples[4], primultiples[5]); DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "refpri = %d high score = %d index = %d numpulses = %d\n", refpri, highscore, highscoreindex, numpulses); /* Count the other delay elements that have pri and dur with in the * acceptable range from the reference one */ for (i=0; i<dl->dl_numelems; i++) { delayindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; searchpri = dl->dl_elems[delayindex].de_time; if( searchpri == 0) { /* This events PRI is zero, take it as a * valid pulse but decrement next event's PRI by refpri */ dindex = (delayindex+1)& DFS_MAX_DL_MASK; dl->dl_elems[dindex].de_time -= refpri; searchpri = refpri; } searchdur = dl->dl_elems[delayindex].de_dur; searchrssi = dl->dl_elems[delayindex].de_rssi; deltadur = DFS_DIFF(searchdur, refdur); for(j=0; j<6; j++) { deltapri = DFS_DIFF(searchpri, primultiples[j]); /* May need to revisit this as this increases the primargin by 5*/ /* if( deltapri < (primargin+j)) { */ if( deltapri < (primargin)) { if( deltadur < durmargin) { if( (refdur < 8) || ((refdur >=8)&& (searchrssi < 250))) { numpulses++; 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, numpulses, deltapri, j); } } break; } } } return numpulses; }
int dfs_bin_fixedpattern_check(struct ath_dfs_host *dfs, struct dfs_filter *rf, u_int32_t dur, int ext_chan_flag, u_int32_t ext_chan_busy) { struct dfs_pulseline *pl = dfs->pulses; int i, n, refpri, primargin, numpulses=0; u_int64_t start_ts, end_ts, event_ts, prev_event_ts, next_event_ts, window_start, window_end; u_int32_t index, next_index, deltadur; /* For fixed pattern types, rf->rf_patterntype=1*/ primargin = dfs_get_pri_margin(ext_chan_flag, (rf->rf_patterntype==1),dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy); refpri = (rf->rf_minpri + rf->rf_maxpri)/2; index = pl->pl_lastelem; end_ts = pl->pl_elems[index].p_time; start_ts = end_ts - (refpri*rf->rf_numpulses); DFS_DPRINTK(dfs, ATH_DEBUG_DFS3, "lastelem ts=%llu start_ts=%llu, end_ts=%llu\n", (unsigned long long)pl->pl_elems[index].p_time, (unsigned long long)start_ts, (unsigned long long)end_ts); /* find the index of first element in our window of interest */ for(i=0;i<pl->pl_numelems;i++) { index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK; if(pl->pl_elems[index].p_time >= start_ts ) continue; else { index = (index) & DFS_MAX_PULSE_BUFFER_MASK; break; } } for (n=0;n<=rf->rf_numpulses; n++) { window_start = (start_ts + (refpri*n))-(primargin+n); window_end = window_start + 2*(primargin+n); DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "window_start %u window_end %u \n", (u_int32_t)window_start, (u_int32_t)window_end); for(i=0;i<pl->pl_numelems;i++) { prev_event_ts = pl->pl_elems[index].p_time; index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; event_ts = pl->pl_elems[index].p_time; next_index = (index+1) & DFS_MAX_PULSE_BUFFER_MASK; next_event_ts = pl->pl_elems[next_index].p_time; DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "ts %u \n", (u_int32_t)event_ts); if( (event_ts <= window_end) && (event_ts >= window_start)){ deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur); if( (pl->pl_elems[index].p_dur == 1) || ((dur != 1) && (deltadur <= 2))) { numpulses++; DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "numpulses %u \n", numpulses); break; } } else if( event_ts > window_end) { index = (index-1) & DFS_MAX_PULSE_BUFFER_MASK; break; } else if( event_ts == prev_event_ts) { if( ((next_event_ts - event_ts) > refpri) || ((next_event_ts - event_ts) == 0)) { deltadur = DFS_DIFF(pl->pl_elems[index].p_dur, dur); if( (pl->pl_elems[index].p_dur == 1) || ((pl->pl_elems[index].p_dur != 1) && (deltadur <= 2))) { numpulses++; DFS_DPRINTK(dfs, ATH_DEBUG_DFS2, "zero PRI: numpulses %u \n", numpulses); break; } } } } } if (numpulses >= dfs_get_filter_threshold(rf, ext_chan_flag, dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy)) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "%s FOUND filterID=%u numpulses=%d unadj thresh=%d\n", __func__, rf->rf_pulseid, numpulses, rf->rf_threshold); return 1; } else return 0; }
int dfs_bin_check(struct ath_dfs_host *dfs, struct dfs_filter *rf, u_int32_t deltaT, u_int32_t width, int ext_chan_flag, u_int32_t ext_chan_busy) { u_int32_t refpri, refdur, searchpri, deltapri, averagerefpri; u_int32_t n, i, primargin, durmargin, highscore, highscoreindex; int score[DFS_MAX_DL_SIZE], delayindex, dindex, found=0; struct dfs_delayline *dl; u_int32_t scoreindex, lowpriindex= 0, lowpri = 0xffff; int numpulses=0; dl = &rf->rf_dl; if( dl->dl_numelems < (rf->rf_threshold-1)) { return 0; } if( deltaT > rf->rf_filterlen) return 0; primargin = dfs_get_pri_margin(ext_chan_flag, (rf->rf_patterntype==1), dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy); if(rf->rf_maxdur < 10) { durmargin = 4; } else { durmargin = 6; } if( rf->rf_patterntype == 1 ){ found = dfs_bin_fixedpattern_check(dfs, rf, width, ext_chan_flag, ext_chan_busy); if(found) { dl->dl_numelems = 0; } return found; } OS_MEMZERO(score, sizeof(int)*DFS_MAX_DL_SIZE); /* find out the lowest pri */ for (n=0;n<dl->dl_numelems; n++) { delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; refpri = dl->dl_elems[delayindex].de_time; if( refpri == 0) continue; else if(refpri < lowpri) { lowpri = dl->dl_elems[delayindex].de_time; lowpriindex = n; } } /* find out the each delay element's pri score */ for (n=0;n<dl->dl_numelems; n++) { delayindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; refpri = dl->dl_elems[delayindex].de_time; if( refpri == 0) continue; for (i=0;i<dl->dl_numelems; i++) { dindex = (dl->dl_firstelem + i) & DFS_MAX_DL_MASK; searchpri = dl->dl_elems[dindex].de_time; deltapri = DFS_DIFF(searchpri, refpri); if( deltapri < primargin) score[n]++; } if( score[n] > rf->rf_threshold) { /* we got the most possible candidate, * no need to continue further */ break; } } /* find out the high scorer */ highscore = 0; highscoreindex = 0; for (n=0;n<dl->dl_numelems; n++) { if( score[n] > highscore) { highscore = score[n]; highscoreindex = n; } else if( score[n] == highscore ) { /*more than one pri has highscore take the least pri */ delayindex = (dl->dl_firstelem + highscoreindex) & DFS_MAX_DL_MASK; dindex = (dl->dl_firstelem + n) & DFS_MAX_DL_MASK; if( dl->dl_elems[dindex].de_time <= dl->dl_elems[delayindex].de_time ) { highscoreindex = n; } } } /* find the average pri of pulses around the pri of highscore or * the pulses around the lowest pri */ if( highscore < 3) { scoreindex = lowpriindex; } else { scoreindex = highscoreindex; } /* We got the possible pri, save its parameters as reference */ delayindex = (dl->dl_firstelem + scoreindex) & DFS_MAX_DL_MASK; refdur = dl->dl_elems[delayindex].de_dur; refpri = dl->dl_elems[delayindex].de_time; averagerefpri = 0; numpulses = dfs_bin_pri_check(dfs, rf, dl, score[scoreindex], refpri, refdur, ext_chan_flag, ext_chan_busy); if (numpulses >= dfs_get_filter_threshold(rf, ext_chan_flag, dfs->dfs_rinfo.rn_lastfull_ts, ext_chan_busy)) { found = 1; DFS_DPRINTK(dfs, ATH_DEBUG_DFS1, "ext_flag=%d MATCH filter=%u numpulses=%u thresh=%u refpri=%d primargin=%d\n", ext_chan_flag, rf->rf_pulseid, numpulses,rf->rf_threshold, refpri, primargin); dfs_print_delayline(dfs, &rf->rf_dl); dfs_print_filter(dfs, rf); } return found; }
/* This function Initialize the radar filter tables * if the ath dfs domain is uninitalized or * ath dfs domain is different from hal dfs domain */ int dfs_init_radar_filters(struct ieee80211com *ic, struct ath_dfs_radar_tab_info *radar_info) { u_int32_t T, Tmax; int numpulses,p,n, i; int numradars = 0, numb5radars = 0; struct ath_dfs *dfs = (struct ath_dfs *)ic->ic_dfs; struct dfs_filtertype *ft = NULL; struct dfs_filter *rf=NULL; struct dfs_pulse *dfs_radars; struct dfs_bin5pulse *b5pulses=NULL; int32_t min_rssithresh=DFS_MAX_RSSI_VALUE; u_int32_t max_pulsedur=0; if (dfs == NULL) { VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "%s[%d]: dfs is NULL", __func__, __LINE__); return DFS_STATUS_FAIL; } /* clear up the dfs domain flag first */ #ifndef ATH_DFS_RADAR_DETECTION_ONLY dfs->ath_dfs_isdfsregdomain = 0; #endif /* * If radar_info is NULL or dfsdomain is NULL, treat * the rest of the radar configuration as suspect. */ if (radar_info == NULL || radar_info->dfsdomain == 0) { VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "%s[%d]: Unknown dfs domain %d ", __func__, __LINE__, dfs->dfsdomain); /* Disable radar detection since we don't have a radar domain */ dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; /* Returning success though we are not completing init. A failure * will fail dfs_attach also. */ return DFS_STATUS_SUCCESS; } VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:dfsdomain=%d, numradars=%d, numb5radars=%d", __func__, __LINE__, radar_info->dfsdomain, radar_info->numradars, radar_info->numb5radars); dfs->dfsdomain = radar_info->dfsdomain; dfs_radars = radar_info->dfs_radars; numradars = radar_info->numradars; b5pulses = radar_info->b5pulses; numb5radars = radar_info->numb5radars; /* XXX this should be an explicit copy of some sort! */ dfs->dfs_defaultparams = radar_info->dfs_defaultparams; #ifndef ATH_DFS_RADAR_DETECTION_ONLY dfs->ath_dfs_isdfsregdomain = 1; #endif dfs->dfs_rinfo.rn_numradars = 0; /* Clear filter type table */ for (n = 0; n < 256; n++) { for (i=0;i<DFS_MAX_RADAR_OVERLAP; i++) (dfs->dfs_radartable[n])[i] = -1; } /* Now, initialize the radar filters */ for (p=0; p<numradars; p++) { ft = NULL; for (n=0; n<dfs->dfs_rinfo.rn_numradars; n++) { if ((dfs_radars[p].rp_pulsedur == dfs->dfs_radarf[n]->ft_filterdur) && (dfs_radars[p].rp_numpulses == dfs->dfs_radarf[n]->ft_numpulses) && (dfs_radars[p].rp_mindur == dfs->dfs_radarf[n]->ft_mindur) && (dfs_radars[p].rp_maxdur == dfs->dfs_radarf[n]->ft_maxdur)) { ft = dfs->dfs_radarf[n]; break; } } if (ft == NULL) { /* No filter of the appropriate dur was found */ if ((dfs->dfs_rinfo.rn_numradars+1) >DFS_MAX_RADAR_TYPES) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Too many filter types", __func__); goto bad4; } ft = dfs->dfs_radarf[dfs->dfs_rinfo.rn_numradars]; ft->ft_numfilters = 0; ft->ft_numpulses = dfs_radars[p].rp_numpulses; ft->ft_patterntype = dfs_radars[p].rp_patterntype; ft->ft_mindur = dfs_radars[p].rp_mindur; ft->ft_maxdur = dfs_radars[p].rp_maxdur; ft->ft_filterdur = dfs_radars[p].rp_pulsedur; ft->ft_rssithresh = dfs_radars[p].rp_rssithresh; ft->ft_rssimargin = dfs_radars[p].rp_rssimargin; ft->ft_minpri = 1000000; if (ft->ft_rssithresh < min_rssithresh) min_rssithresh = ft->ft_rssithresh; if (ft->ft_maxdur > max_pulsedur) max_pulsedur = ft->ft_maxdur; for (i=ft->ft_mindur; i<=ft->ft_maxdur; i++) { u_int32_t stop=0,tableindex=0; while ((tableindex < DFS_MAX_RADAR_OVERLAP) && (!stop)) { if ((dfs->dfs_radartable[i])[tableindex] == -1) stop = 1; else tableindex++; } if (stop) { (dfs->dfs_radartable[i])[tableindex] = (int8_t) (dfs->dfs_rinfo.rn_numradars); } else { DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: Too many overlapping radar filters", __func__); goto bad4; } } dfs->dfs_rinfo.rn_numradars++; } rf = &(ft->ft_filters[ft->ft_numfilters++]); dfs_reset_delayline(&rf->rf_dl); numpulses = dfs_radars[p].rp_numpulses; rf->rf_numpulses = numpulses; rf->rf_patterntype = dfs_radars[p].rp_patterntype; rf->rf_pulseid = dfs_radars[p].rp_pulseid; rf->rf_mindur = dfs_radars[p].rp_mindur; rf->rf_maxdur = dfs_radars[p].rp_maxdur; rf->rf_numpulses = dfs_radars[p].rp_numpulses; rf->rf_ignore_pri_window = dfs_radars[p].rp_ignore_pri_window; T = (100000000/dfs_radars[p].rp_max_pulsefreq) - 100*(dfs_radars[p].rp_meanoffset); rf->rf_minpri = dfs_round((int32_t)T - (100*(dfs_radars[p].rp_pulsevar))); Tmax = (100000000/dfs_radars[p].rp_pulsefreq) - 100*(dfs_radars[p].rp_meanoffset); rf->rf_maxpri = dfs_round((int32_t)Tmax + (100*(dfs_radars[p].rp_pulsevar))); if( rf->rf_minpri < ft->ft_minpri ) ft->ft_minpri = rf->rf_minpri; rf->rf_fixed_pri_radar_pulse = ( dfs_radars[p].rp_max_pulsefreq == dfs_radars[p].rp_pulsefreq ) ? 1 : 0; rf->rf_threshold = dfs_radars[p].rp_threshold; rf->rf_filterlen = rf->rf_maxpri * rf->rf_numpulses; VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]: minprf = %d maxprf = %d pulsevar = %d thresh=%d", __func__,__LINE__,dfs_radars[p].rp_pulsefreq, dfs_radars[p].rp_max_pulsefreq, dfs_radars[p].rp_pulsevar, rf->rf_threshold); VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:minpri = %d maxpri = %d filterlen = %d filterID = %d",__func__,__LINE__, rf->rf_minpri, rf->rf_maxpri, rf->rf_filterlen, rf->rf_pulseid); } #ifdef DFS_DEBUG dfs_print_filters(ic); #endif dfs->dfs_rinfo.rn_numbin5radars = numb5radars; if (dfs->dfs_b5radars != NULL) OS_FREE(dfs->dfs_b5radars); dfs->dfs_b5radars = (struct dfs_bin5radars *)OS_MALLOC(NULL, numb5radars * sizeof(struct dfs_bin5radars), GFP_KERNEL); if (dfs->dfs_b5radars == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: cannot allocate memory for 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; if (dfs->dfs_b5radars[n].br_pulse.b5_rssithresh < min_rssithresh) min_rssithresh = dfs->dfs_b5radars[n].br_pulse.b5_rssithresh; if (dfs->dfs_b5radars[n].br_pulse.b5_maxdur > max_pulsedur) max_pulsedur = dfs->dfs_b5radars[n].br_pulse.b5_maxdur; } dfs_reset_alldelaylines(dfs); dfs_reset_radarq(dfs); dfs->dfs_curchan_radindex = -1; dfs->dfs_extchan_radindex = -1; dfs->dfs_rinfo.rn_minrssithresh = min_rssithresh; /* Convert durations to TSF ticks */ dfs->dfs_rinfo.rn_maxpulsedur = dfs_round((int32_t)((max_pulsedur*100/80)*100)); /* relax the max pulse duration a little bit due to inaccuracy caused by chirping. */ dfs->dfs_rinfo.rn_maxpulsedur = dfs->dfs_rinfo.rn_maxpulsedur +20; VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]: DFS min filter rssiThresh = %d", __func__, __LINE__, min_rssithresh); VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO, "%s[%d]:DFS max pulse dur = %d ticks", __func__ ,__LINE__, dfs->dfs_rinfo.rn_maxpulsedur); return DFS_STATUS_SUCCESS; bad4: return DFS_STATUS_FAIL; }
int dfs_process_radarevent(struct ath_softc *sc, HAL_CHANNEL *chan) { struct ath_dfs *dfs=sc->sc_dfs; struct ath_hal *ah=sc->sc_ah; struct dfs_event re,*event; struct dfs_state *rs=NULL; struct dfs_filtertype *ft; struct dfs_filter *rf; int found, retval = 0, p, empty; int events_processed = 0; u_int32_t tabledepth, rfilt, index; u_int64_t deltafull_ts = 0, this_ts, deltaT; HAL_CHANNEL *thischan; HAL_PHYERR_PARAM pe; struct dfs_pulseline *pl; static u_int32_t test_ts = 0; static u_int32_t diff_ts = 0; int ext_chan_event_flag = 0; if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_sfs is NULL\n", __func__); return 0; } pl = dfs->pulses; if ( ! (sc->sc_curchan.priv_flags & CHANNEL_DFS)) { DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "%s: radar event on non-DFS chan\n", __func__); dfs_reset_radarq(sc); dfs_reset_alldelaylines(sc); return 0; } #ifndef ATH_DFS_RADAR_DETECTION_ONLY /* TEST : Simulate radar bang, make sure we add the channel to NOL (bug 29968) */ if (dfs->dfs_bangradar) { /* bangradar will always simulate radar found on the primary channel */ rs = &dfs->dfs_radar[dfs->dfs_curchan_radindex]; dfs->dfs_bangradar = 0; /* reset */ DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: bangradar\n", __func__); retval = 1; goto dfsfound; } #endif ATH_DFSQ_LOCK(dfs); empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); ATH_DFSQ_UNLOCK(dfs); while ((!empty) && (!retval) && (events_processed < MAX_EVENTS)) { ATH_DFSQ_LOCK(dfs); event = STAILQ_FIRST(&(dfs->dfs_radarq)); if (event != NULL) STAILQ_REMOVE_HEAD(&(dfs->dfs_radarq), re_list); ATH_DFSQ_UNLOCK(dfs); if (event == NULL) { empty = 1; break; } events_processed++; re = *event; OS_MEMZERO(event, sizeof(struct dfs_event)); ATH_DFSEVENTQ_LOCK(dfs); STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), event, re_list); ATH_DFSEVENTQ_UNLOCK(dfs); found = 0; if (re.re_chanindex < DFS_NUM_RADAR_STATES) rs = &dfs->dfs_radar[re.re_chanindex]; else { ATH_DFSQ_LOCK(dfs); empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); ATH_DFSQ_UNLOCK(dfs); continue; } if (rs->rs_chan.priv_flags & CHANNEL_INTERFERENCE) { ATH_DFSQ_LOCK(dfs); empty = STAILQ_EMPTY(&(dfs->dfs_radarq)); ATH_DFSQ_UNLOCK(dfs); continue; } if (dfs->dfs_rinfo.rn_lastfull_ts == 0) { /* * Either not started, or 64-bit rollover exactly to zero * Just prepend zeros to the 15-bit ts */ dfs->dfs_rinfo.rn_ts_prefix = 0; this_ts = (u_int64_t) re.re_ts; } else { /* WAR 23031- patch duplicate ts on very short pulses */ /* This pacth has two problems in linux environment. * 1)The time stamp created and hence PRI depends entirely on the latency. * If the latency is high, it possibly can split two consecutive * pulses in the same burst so far away (the same amount of latency) * that make them look like they are from differenct bursts. It is * observed to happen too often. It sure makes the detection fail. * 2)Even if the latency is not that bad, it simply shifts the duplicate * timestamps to a new duplicate timestamp based on how they are processed. * This is not worse but not good either. * * Take this pulse as a good one and create a probable PRI later */ if (re.re_dur == 0 && re.re_ts == dfs->dfs_rinfo.rn_last_unique_ts) { debug_dup[debug_dup_cnt++] = '1'; DFS_DPRINTK(sc, ATH_DEBUG_DFS1, "\n %s deltaT is 0 \n", __func__); } else { dfs->dfs_rinfo.rn_last_unique_ts = re.re_ts; debug_dup[debug_dup_cnt++] = '0'; } if (debug_dup_cnt >= 32){ debug_dup_cnt = 0; } if (re.re_ts <= dfs->dfs_rinfo.rn_last_ts) { dfs->dfs_rinfo.rn_ts_prefix += (((u_int64_t) 1) << DFS_TSSHIFT); /* Now, see if it's been more than 1 wrap */ deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; if (deltafull_ts > ((u_int64_t)((DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts))) deltafull_ts -= (DFS_TSMASK - dfs->dfs_rinfo.rn_last_ts) + 1 + re.re_ts; deltafull_ts = deltafull_ts >> DFS_TSSHIFT; if (deltafull_ts > 1) { dfs->dfs_rinfo.rn_ts_prefix += ((deltafull_ts - 1) << DFS_TSSHIFT); } } else { deltafull_ts = re.re_full_ts - dfs->dfs_rinfo.rn_lastfull_ts; if (deltafull_ts > (u_int64_t) DFS_TSMASK) { deltafull_ts = deltafull_ts >> DFS_TSSHIFT; dfs->dfs_rinfo.rn_ts_prefix += ((deltafull_ts - 1) << DFS_TSSHIFT); } }
void dfs_print_filter(struct ath_softc *sc, struct dfs_filter *rf) { DFS_DPRINTK(sc, ATH_DEBUG_DFS1, "filterID[%d] rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n", rf->rf_pulseid, rf->rf_numpulses, rf->rf_minpri, rf->rf_maxpri, rf->rf_threshold, rf->rf_filterlen, rf->rf_mindur, rf->rf_maxdur); }