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); } }
/* * Explicity disable radar reporting. * * Return 0 if it was disabled, < 0 on error. */ int ath_dfs_radar_disable(struct ath_softc *sc) { #if 0 HAL_PHYERR_PARAM pe; (void) ath_hal_getdfsthresh(sc->sc_ah, &pe); pe.pe_enabled = 0; (void) ath_hal_enabledfs(sc->sc_ah, &pe); return (0); #else return (0); #endif }
/* * Enable radar check. Return 1 if the driver should * enable radar PHY errors, or 0 if not. */ int ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan) { #if 0 HAL_PHYERR_PARAM pe; /* Check if the hardware supports radar reporting */ /* XXX TODO: migrate HAL_CAP_RADAR/HAL_CAP_AR to somewhere public! */ if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PHYDIAG, 0, NULL) != HAL_OK) return (0); /* Check if the current channel is radar-enabled */ if (! IEEE80211_IS_CHAN_DFS(chan)) return (0); /* Fetch the default parameters */ memset(&pe, '\0', sizeof(pe)); if (! ath_hal_getdfsdefaultthresh(sc->sc_ah, &pe)) return (0); /* Enable radar PHY error reporting */ sc->sc_dodfs = 1; /* Tell the hardware to enable radar reporting */ pe.pe_enabled = 1; /* Flip on extension channel events only if doing HT40 */ if (IEEE80211_IS_CHAN_HT40(chan)) pe.pe_extchannel = 1; else pe.pe_extchannel = 0; ath_hal_enabledfs(sc->sc_ah, &pe); /* * Disable strong signal fast diversity - needed for * AR5212 and similar PHYs for reliable short pulse * duration. */ (void) ath_hal_setcapability(sc->sc_ah, HAL_CAP_DIVERSITY, 2, 0, NULL); return (1); #else return (0); #endif }
/* * Handle ioctl requests from the diagnostic interface. * * The initial part of this code resembles ath_ioctl_diag(); * it's likely a good idea to reduce duplication between * these two routines. */ int ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad) { unsigned int id = ad->ad_id & ATH_DIAG_ID; void *indata = NULL; void *outdata = NULL; u_int32_t insize = ad->ad_in_size; u_int32_t outsize = ad->ad_out_size; int error = 0; HAL_PHYERR_PARAM peout; HAL_PHYERR_PARAM *pe; if (ad->ad_id & ATH_DIAG_IN) { /* * Copy in data. */ indata = malloc(insize, M_TEMP, M_NOWAIT); if (indata == NULL) { error = ENOMEM; goto bad; } error = copyin(ad->ad_in_data, indata, insize); if (error) goto bad; } if (ad->ad_id & ATH_DIAG_DYN) { /* * Allocate a buffer for the results (otherwise the HAL * returns a pointer to a buffer where we can read the * results). Note that we depend on the HAL leaving this * pointer for us to use below in reclaiming the buffer; * may want to be more defensive. */ outdata = malloc(outsize, M_TEMP, M_NOWAIT); if (outdata == NULL) { error = ENOMEM; goto bad; } } switch (id) { case DFS_SET_THRESH: if (insize < sizeof(HAL_PHYERR_PARAM)) { error = EINVAL; break; } pe = (HAL_PHYERR_PARAM *) indata; ath_hal_enabledfs(sc->sc_ah, pe); break; case DFS_GET_THRESH: memset(&peout, 0, sizeof(peout)); outsize = sizeof(HAL_PHYERR_PARAM); ath_hal_getdfsthresh(sc->sc_ah, &peout); pe = (HAL_PHYERR_PARAM *) outdata; memcpy(pe, &peout, sizeof(*pe)); break; default: error = EINVAL; } if (outsize < ad->ad_out_size) ad->ad_out_size = outsize; if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size)) error = EFAULT; bad: if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) free(indata, M_TEMP); if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL) free(outdata, M_TEMP); return (error); }
int dfs_set_thresholds(struct ath_softc *sc, const u_int32_t threshtype, const u_int32_t value) { struct ath_dfs *dfs=sc->sc_dfs; int16_t chanindex; struct dfs_state *rs; HAL_PHYERR_PARAM pe; if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return 0; } chanindex = dfs->dfs_curchan_radindex; if ((chanindex <0) || (chanindex >= DFS_NUM_RADAR_STATES)) return 0; 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_rrssi = HAL_PHYERR_PARAM_NOVAL; /* 5413 specific */ pe.pe_relpwr = HAL_PHYERR_PARAM_NOVAL; pe.pe_relstep = HAL_PHYERR_PARAM_NOVAL; pe.pe_maxlen = HAL_PHYERR_PARAM_NOVAL; rs = &(dfs->dfs_radar[chanindex]); switch (threshtype) { case DFS_PARAM_FIRPWR: rs->rs_firpwr = (int32_t) value; pe.pe_firpwr = rs->rs_firpwr; break; case DFS_PARAM_RRSSI: rs->rs_radarrssi = value; pe.pe_rrssi = value; break; case DFS_PARAM_HEIGHT: rs->rs_height = value; pe.pe_height = value; break; case DFS_PARAM_PRSSI: rs->rs_pulserssi = value; pe.pe_prssi = value; break; case DFS_PARAM_INBAND: rs->rs_inband = value; pe.pe_inband = value; break; /* 5413 specific */ case DFS_PARAM_RELPWR: rs->rs_relpwr = value; pe.pe_relpwr = value; break; case DFS_PARAM_RELSTEP: rs->rs_relstep = value; pe.pe_relstep = value; break; case DFS_PARAM_MAXLEN: rs->rs_maxlen = value; pe.pe_maxlen = value; break; } ath_hal_enabledfs(sc->sc_ah, &pe); return 1; }
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; }