Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
/*
 * 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);
}
Ejemplo n.º 3
0
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);

	}
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 8
0
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);
                    }
            }
    }
}
Ejemplo n.º 9
0
/*
 * 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);
}
Ejemplo n.º 10
0
/*
 * 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;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
/*
 * 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;
        }
    }
}
Ejemplo n.º 13
0
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);
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
    }
}
Ejemplo n.º 16
0
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;
	}
}
Ejemplo n.º 17
0
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);
}
Ejemplo n.º 18
0
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);
	}
}
Ejemplo n.º 19
0
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);
    } 

}
Ejemplo n.º 20
0
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);
}
Ejemplo n.º 21
0
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));
}
Ejemplo n.º 22
0
/*
 * 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;
        }
}
Ejemplo n.º 23
0
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;
    }
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 28
0
/* 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;
}
Ejemplo n.º 29
0
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);
				}
			}
Ejemplo n.º 30
0
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);
}