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_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;
}
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;
}
예제 #4
0
int dfs_bin_check(struct ath_softc *sc, struct dfs_filter *rf,
                             u_int32_t deltaT, u_int32_t width, int ext_chan_flag)
{
        u_int32_t refpri, refdur, searchpri, deltapri,deltapri_2,deltapri_3, 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;
        int lowprichk=3,pri_match=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(sc, ext_chan_flag, (rf->rf_patterntype==1));


        if(rf->rf_maxdur < 10) {
                durmargin = 4;
        }
        else {
                durmargin = 6;
        }

        if( rf->rf_patterntype == 1 ){
                found = dfs_bin_fixedpattern_check(sc, rf, width, ext_chan_flag);
                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;
                if (refpri < rf->rf_maxpri) { // use only valid PRI range for high score
                    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);
                        deltapri_2 = DFS_DIFF(searchpri, 2*refpri);
                        deltapri_3 = DFS_DIFF(searchpri, 3*refpri);
                        if (rf->rf_ignore_pri_window==2) {
                            pri_match = ((deltapri < primargin) || (deltapri_2 < primargin) || (deltapri_3 < primargin));
                        } else {
                            pri_match = (deltapri < primargin);
                        }

                        if (pri_match)
                            score[n]++;
                    }  
                } else {
                    score[n] = 0;
                }
                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 (rf->rf_ignore_pri_window > 0) {
            lowprichk = (rf->rf_threshold >> 1)+1;
        } else {