/* * 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); }
int dfs_radar_enable(struct ath_softc *sc) { struct ath_dfs *dfs=sc->sc_dfs; u_int32_t rfilt; HAL_CHANNEL *chan=&sc->sc_curchan; struct ath_hal *ah = sc->sc_ah; HAL_CHANNEL *ext_ch=ath_hal_get_extension_channel(ah); if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return -EIO; } rfilt = ath_hal_getrxfilter(ah); if ((dfs->dfs_proc_phyerr & (DFS_RADAR_EN | DFS_AR_EN)) && (sc->sc_opmode == HAL_M_HOSTAP || sc->sc_opmode == HAL_M_IBSS)) { if (chan->privFlags & CHANNEL_DFS) { struct dfs_state *rs_pri=NULL, *rs_ext=NULL; u_int8_t index_pri, index_ext; HAL_PHYERR_PARAM pe; dfs->sc_dfs_cac_time = ATH_DFS_WAIT_MS; if (dfs->dfsdomain == DFS_ETSI_DOMAIN) { if(IS_CHANNEL_WEATHER_RADAR(chan->channel)) { dfs->sc_dfs_cac_time = ATH_DFS_WEATHER_CHANNEL_WAIT_MS; } else { if (ext_ch && IS_CHANNEL_WEATHER_RADAR(ext_ch->channel)) { dfs->sc_dfs_cac_time = ATH_DFS_WEATHER_CHANNEL_WAIT_MS; } } } if(dfs->sc_dfs_cac_time != ATH_DFS_WAIT_MS) printk("WARNING!!! 10 minute CAC period as channel is a weather radar channel\n"); /* Disable radar detection in case we need to setup * a new channel state and radars are somehow being * reported. Avoids locking problem. */ rfilt = ath_hal_getrxfilter(ah); rfilt &= ~HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(ah, rfilt); /* Enable strong signal fast antenna diversity */ ath_hal_setcapability(ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, dfs->dfs_rinfo.rn_fastdivGCval, NULL); dfs_reset_alldelaylines(sc); rs_pri = dfs_getchanstate(sc, &index_pri, 0); if (ext_ch) { rs_ext = dfs_getchanstate(sc, &index_ext, 1); sc->sc_extchan = *ext_ch; } if (rs_pri != NULL && ((ext_ch==NULL)||(rs_ext != NULL))) { if (index_pri != dfs->dfs_curchan_radindex) dfs_reset_alldelaylines(sc); dfs->dfs_curchan_radindex = (int16_t) index_pri; if (rs_ext) dfs->dfs_extchan_radindex = (int16_t) index_ext; pe.pe_firpwr = rs_pri->rs_firpwr; pe.pe_rrssi = rs_pri->rs_radarrssi; pe.pe_height = rs_pri->rs_height; pe.pe_prssi = rs_pri->rs_pulserssi; pe.pe_inband = rs_pri->rs_inband; /* 5413 specific */ pe.pe_relpwr = rs_pri->rs_relpwr; pe.pe_relstep = rs_pri->rs_relstep; pe.pe_maxlen = rs_pri->rs_maxlen; /* Disable strong signal fast antenna diversity */ ath_hal_setcapability(ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, 1, NULL); ath_hal_enabledfs(sc->sc_ah, &pe); rfilt |= HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(ah, rfilt); DFS_DPRINTK(sc, ATH_DEBUG_DFS, "Enabled radar detection on channel %d\n", chan->channel); dfs->dur_multiplier = (ath_hal_is_fast_clock_enabled(sc->sc_ah) ? (DFS_FAST_CLOCK_MULTIPLIER) : (DFS_NO_FAST_CLOCK_MULTIPLIER)); DFS_DPRINTK(sc, ATH_DEBUG_DFS3, "%s: duration multiplier is %d\n", __func__, dfs->dur_multiplier); /* * Fast antenna diversity for strong signals disturbs * radar detection of 1-2us pusles. Enable fast diveristy * but disable the strong signal aspect of it */ if (ath_hal_getcapability(ah, HAL_CAP_DIVERSITY, 1, NULL) == HAL_OK) { ath_hal_setcapability(ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, 0, NULL); } } else DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: No more radar states left\n", __func__); } else { if (!(chan->channelFlags & CHANNEL_2GHZ)) { /* Enable strong signal fast antenna diversity */ ath_hal_setcapability(ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, dfs->dfs_rinfo.rn_fastdivGCval, NULL); /* Disable Radar if not 2GHZ channel and not DFS */ rfilt &= ~HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(ah, rfilt); } } } else { /* Enable strong signal fast antenna diversity */ ath_hal_setcapability(ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, dfs->dfs_rinfo.rn_fastdivGCval, NULL); /* Disable Radar if RADAR or AR not enabled */ rfilt &= ~HAL_RX_FILTER_PHYRADAR; ath_hal_setrxfilter(ah, rfilt); } return 0; }