void ath_phyerr_attach(struct ath_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; sc->sc_phyerr_cap = 0; if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR, NULL) == HAL_OK) { sc->sc_phyerr_cap |= ATH_RADAR_EN; if ((ic->ic_ath_cap & (IEEE80211_ATHC_TURBOP)) && (ic->ic_ath_cap & (IEEE80211_ATHC_AR))) sc->sc_phyerr_cap |= ATH_RADAR_AR_EN; } sc->sc_phyerr_state = (void *) kmalloc(sizeof(struct ath_phyerr_state), GFP_KERNEL); ath_reset_radar(sc); ath_reset_ar(sc); };
/* * 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 }
/* * Attach to a device instance. Setup the public definition * of how much per-node space we need and setup the private * phy tables that have rate control parameters. These tables * are normally part of the Atheros hal but are not included * in our hal as the rate control data was not being used and * was considered proprietary (at the time). */ struct atheros_softc * ath_rate_attach(struct ath_hal *ah) { struct atheros_softc *asc; RC_OS_MALLOC(&asc, sizeof(struct atheros_softc), RATECTRL_MEMTAG); if (asc == NULL) return NULL; OS_MEMZERO(asc, sizeof(struct atheros_softc)); /* * Use the magic number to figure out the chip type. * There's probably a better way to do this but for * now this suffices. * * NB: We don't have a separate set of tables for the * 5210; treat it like a 5211 since it has the same * tx descriptor format and (hopefully) sufficiently * similar operating characteristics to work ok. */ switch (ah->ah_magic) { #ifdef AH_SUPPORT_AR5212 case 0x19570405: case 0x19541014: /* 5212 */ ar5212AttachRateTables(asc); asc->prate_maprix = ar5212_rate_maprix; break; #endif case 0x19641014: /* 5416 */ case 0x19741014: /* 9300 */ ar5416AttachRateTables(asc); asc->prate_maprix = ar5416_rate_maprix; break; default: ASSERT(0); break; } /* Save Maximum TX Trigger Level (used for 11n) */ ath_hal_getcapability(ah, HAL_CAP_TX_TRIG_LEVEL_MAX, 0, &asc->txTrigLevelMax); /* return alias for atheros_softc * */ return asc; }
int spectral_enter_raw_capture_mode(ath_dev_t dev, void *indata) { struct ath_softc *sc = ATH_DEV_TO_SC(dev); SPECTRAL_ADC_CAPTURE_PARAMS *params = (SPECTRAL_ADC_CAPTURE_PARAMS*)indata; HAL_CHANNEL hchan; int error = 0; if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_RAW_ADC_CAPTURE, 0, NULL) != HAL_OK) { DPRINTF(sc, ATH_DEBUG_ANY, "%s[%d]: called but raw capture mode not supported!\n", __func__, __LINE__); return -ENOTSUP; } /* sanity check input version */ if (params->version != SPECTRAL_ADC_API_VERSION) { DPRINTF(sc, ATH_DEBUG_ANY, "%s[%d]: version mismatch: expect %d got %d\n", __func__, __LINE__, params->version, SPECTRAL_ADC_API_VERSION); return -EINVAL; } if (sc->sc_invalid) { DPRINTF(sc, ATH_DEBUG_ANY, "%s[%d]: called but device is invalid or removed!\n", __func__, __LINE__); return -ENXIO; } if (sc->sc_raw_adc_capture_enabled) { DPRINTF(sc, ATH_DEBUG_ANY, "%s[%d]: already raw capture mode - calling spectral_exit_raw_capture_mode() first\n", __func__, __LINE__); spectral_exit_raw_capture_mode(dev); } /* save current channel and chain mask so we can restore later */ sc->sc_save_rx_chainmask = sc->sc_rx_chainmask; sc->sc_save_current_chan = sc->sc_curchan; sc->sc_save_current_opmode = sc->sc_opmode; /* ensure chain mask is valid */ params->chain_info.chain_mask &= sc->sc_rx_chainmask; /* store requested capture params */ sc->sc_adc_chain_mask = params->chain_info.chain_mask; sc->sc_adc_num_chains = sc->sc_mask2chains[params->chain_info.chain_mask]; sc->sc_adc_capture_flags = params->capture_flags; /* set new chain mask */ ath_set_rx_chainmask(dev, params->chain_info.chain_mask); /* change channel to that requested */ OS_MEMZERO(&hchan, sizeof(hchan)); hchan.channel = params->freq; if (hchan.channel > 5000) hchan.channel_flags = CHANNEL_A_HT20; else hchan.channel_flags = CHANNEL_G_HT20; sc->sc_full_reset = 1; /* ensure we do a full reset */ ath_set_channel(dev, &hchan, 0, 0, 0); /* save channel info to return with capture data later */ sc->sc_adc_chan_flags = sc->sc_curchan.channel_flags; sc->sc_adc_freq = sc->sc_curchan.channel; sc->sc_adc_ieee = ath_hal_mhz2ieee(sc->sc_ah, sc->sc_adc_freq, sc->sc_adc_chan_flags); /* did the channel change succeed ?*/ if (sc->sc_curchan.channel != hchan.channel || sc->sc_curchan.channel_flags != hchan.channel_flags) { DPRINTF(sc, ATH_DEBUG_ANY, "%s[%d]: set chan to %dMhz[%x] FAILED! current chan=%dMhz[0x%x]\n", __func__, __LINE__, hchan.channel, hchan.channel_flags, sc->sc_curchan.channel, sc->sc_curchan.channel_flags); error = -EINVAL; } else { /* ok, all set up - enter raw capture mode */ DPRINTF(sc, ATH_DEBUG_ANY, "%s[%d]: chan is now %dMhz flags=0x%x mask=0x%x\n", __func__, __LINE__, sc->sc_curchan.channel, sc->sc_curchan.channel_flags, params->chain_info.chain_mask); sc->sc_raw_adc_capture_enabled = 1; sc->sc_opmode = HAL_M_RAW_ADC_CAPTURE; ath_hal_enable_test_addac_mode(sc->sc_ah); } return error; }
/* * Calculate the receive filter according to the * operating mode and state: * * o always accept unicast, broadcast, and multicast traffic * o accept PHY error frames when hardware doesn't have MIB support * to count and we need them for ANI (sta mode only until recently) * and we are not scanning (ANI is disabled) * NB: older hal's add rx filter bits out of sight and we need to * blindly preserve them * o probe request frames are accepted only when operating in * hostap, adhoc, mesh, or monitor modes * o enable promiscuous mode * - when in monitor mode * - if interface marked PROMISC (assumes bridge setting is filtered) * o accept beacons: * - when operating in station mode for collecting rssi data when * the station is otherwise quiet, or * - when operating in adhoc mode so the 802.11 layer creates * node table entries for peers, * - when scanning * - when doing s/w beacon miss (e.g. for ap+sta) * - when operating in ap mode in 11g to detect overlapping bss that * require protection * - when operating in mesh mode to detect neighbors * o accept control frames: * - when in monitor mode * XXX HT protection for 11n */ u_int32_t ath_calcrxfilter(struct ath_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; u_int32_t rfilt; rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST; if (!sc->sc_needmib && !sc->sc_scanning) rfilt |= HAL_RX_FILTER_PHYERR; if (ic->ic_opmode != IEEE80211_M_STA) rfilt |= HAL_RX_FILTER_PROBEREQ; /* XXX ic->ic_monvaps != 0? */ if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_promisc > 0) rfilt |= HAL_RX_FILTER_PROM; /* * Only listen to all beacons if we're scanning. * * Otherwise we only really need to hear beacons from * our own BSSID. * * IBSS? software beacon miss? Just receive all beacons. * We need to hear beacons/probe requests from everyone so * we can merge ibss. */ if (ic->ic_opmode == IEEE80211_M_IBSS || sc->sc_swbmiss) { rfilt |= HAL_RX_FILTER_BEACON; } else if (ic->ic_opmode == IEEE80211_M_STA) { if (sc->sc_do_mybeacon && ! sc->sc_scanning) { rfilt |= HAL_RX_FILTER_MYBEACON; } else { /* scanning, non-mybeacon chips */ rfilt |= HAL_RX_FILTER_BEACON; } } /* * NB: We don't recalculate the rx filter when * ic_protmode changes; otherwise we could do * this only when ic_protmode != NONE. */ if (ic->ic_opmode == IEEE80211_M_HOSTAP && IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_BEACON; /* * Enable hardware PS-POLL RX only for hostap mode; * STA mode sends PS-POLL frames but never * receives them. */ if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PSPOLL, 0, NULL) == HAL_OK && ic->ic_opmode == IEEE80211_M_HOSTAP) rfilt |= HAL_RX_FILTER_PSPOLL; if (sc->sc_nmeshvaps) { rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_hasbmatch) rfilt |= HAL_RX_FILTER_BSSID; else rfilt |= HAL_RX_FILTER_PROM; } if (ic->ic_opmode == IEEE80211_M_MONITOR) rfilt |= HAL_RX_FILTER_CONTROL; /* * Enable RX of compressed BAR frames only when doing * 802.11n. Required for A-MPDU. */ if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_COMPBAR; /* * Enable radar PHY errors if requested by the * DFS module. */ if (sc->sc_dodfs) rfilt |= HAL_RX_FILTER_PHYRADAR; /* * Enable spectral PHY errors if requested by the * spectral module. */ if (sc->sc_dospectral) rfilt |= HAL_RX_FILTER_PHYRADAR; DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, %s\n", __func__, rfilt, ieee80211_opmode_name[ic->ic_opmode]); return rfilt; }
/* 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 ath_softc *sc ) { u_int32_t T, Tmax, haldfsdomain; int numpulses,p,n, i; int numradars = 0, numb5radars = 0; struct ath_dfs *dfs = sc->sc_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 ) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "dfs is NULL %s",__func__); return 1; } /* clear up the dfs domain flag first */ #ifndef ATH_DFS_RADAR_DETECTION_ONLY dfs->sc_dfs_isdfsregdomain = 0; #endif /* clear athsstats/DFS related information */ sc->sc_stats.ast_dfs_stats.event_count = 0; sc->sc_stats.ast_dfs_stats.chirp_count = 0; sc->sc_stats.ast_dfs_stats.num_filter = 0; if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR, NULL) == HAL_OK) { /* Init DFS radar filters */ ath_hal_getcapability(sc->sc_ah, HAL_CAP_DFS_DMN, 0, &haldfsdomain); if ( (dfs->dfsdomain == DFS_UNINIT_DOMAIN) || ( dfs->dfsdomain != haldfsdomain ) ) { /* set the dfs domain from HAL */ dfs->dfsdomain = haldfsdomain; DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "DFS domain=%d\n",dfs->dfsdomain); if (domainoverride != DFS_UNINIT_DOMAIN) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "Overriding DFS domain with %d\n",domainoverride); dfs->dfsdomain = domainoverride; } dfs_radars = ath_hal_getdfsradars(sc->sc_ah, dfs->dfsdomain, &numradars, &b5pulses, &numb5radars, &(dfs->dfs_defaultparams)); if (dfs_radars == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: Unknown dfs domain %d\n", __func__, dfs->dfsdomain); /* Disable radar detection since we don't have a radar domain */ dfs->dfs_proc_phyerr &= ~DFS_RADAR_EN; return 0; } #ifndef ATH_DFS_RADAR_DETECTION_ONLY dfs->sc_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(sc, ATH_DEBUG_DFS, "%s: Too many filter types\n", __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(sc, ATH_DEBUG_DFS, "%s: Too many overlapping radar filters\n", __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; DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "minprf = %d maxprf = %d pulsevar = %d thresh=%d\n", dfs_radars[p].rp_pulsefreq, dfs_radars[p].rp_max_pulsefreq, dfs_radars[p].rp_pulsevar, rf->rf_threshold); DFS_DPRINTK(sc, ATH_DEBUG_DFS2, "minpri = %d maxpri = %d filterlen = %d filterID = %d\n", rf->rf_minpri, rf->rf_maxpri, rf->rf_filterlen, rf->rf_pulseid); /* initialize athsstats/DFS related information */ i = sc->sc_stats.ast_dfs_stats.num_filter; sc->sc_stats.ast_dfs_stats.fstat[i].max_pri_count = 0; sc->sc_stats.ast_dfs_stats.fstat[i].max_used_pri = 0; sc->sc_stats.ast_dfs_stats.fstat[i].excess_pri = 0; sc->sc_stats.ast_dfs_stats.fstat[i].pri_threshold_reached = 0; sc->sc_stats.ast_dfs_stats.fstat[i].dur_threshold_reached = 0; sc->sc_stats.ast_dfs_stats.fstat[i].rssi_threshold_reached = 0; sc->sc_stats.ast_dfs_stats.fstat[i].filter_id = rf->rf_pulseid; sc->sc_stats.ast_dfs_stats.num_filter++; } #ifdef DFS_DEBUG dfs_print_filters(sc); #endif dfs->dfs_rinfo.rn_numbin5radars = numb5radars; if ( dfs->dfs_b5radars == NULL ) { dfs->dfs_b5radars = (struct dfs_bin5radars *)OS_MALLOC(sc->sc_osdev, numb5radars * sizeof(struct dfs_bin5radars), GFP_KERNEL); if (dfs->dfs_b5radars == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: cannot allocate memory for bin5 radars\n", __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(sc); dfs_reset_radarq(sc); 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; DFS_DPRINTK (sc, ATH_DEBUG_DFS, "DFS min filter rssiThresh = %d\n",min_rssithresh); DFS_DPRINTK (sc, ATH_DEBUG_DFS, "DFS max pulse dur = %d ticks\n", dfs->dfs_rinfo.rn_maxpulsedur); return 0; bad4: return 1; } } return 0; }
/* * Calculate the receive filter according to the * operating mode and state: * * o always accept unicast, broadcast, and multicast traffic * o accept PHY error frames when hardware doesn't have MIB support * to count and we need them for ANI (sta mode only until recently) * and we are not scanning (ANI is disabled) * NB: older hal's add rx filter bits out of sight and we need to * blindly preserve them * o probe request frames are accepted only when operating in * hostap, adhoc, mesh, or monitor modes * o enable promiscuous mode * - when in monitor mode * - if interface marked PROMISC (assumes bridge setting is filtered) * o accept beacons: * - when operating in station mode for collecting rssi data when * the station is otherwise quiet, or * - when operating in adhoc mode so the 802.11 layer creates * node table entries for peers, * - when scanning * - when doing s/w beacon miss (e.g. for ap+sta) * - when operating in ap mode in 11g to detect overlapping bss that * require protection * - when operating in mesh mode to detect neighbors * o accept control frames: * - when in monitor mode * XXX HT protection for 11n */ u_int32_t ath_calcrxfilter(struct ath_softc *sc) { struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; u_int32_t rfilt; rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST; if (!sc->sc_needmib && !sc->sc_scanning) rfilt |= HAL_RX_FILTER_PHYERR; if (ic->ic_opmode != IEEE80211_M_STA) rfilt |= HAL_RX_FILTER_PROBEREQ; /* XXX ic->ic_monvaps != 0? */ if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC)) rfilt |= HAL_RX_FILTER_PROM; if (ic->ic_opmode == IEEE80211_M_STA || ic->ic_opmode == IEEE80211_M_IBSS || sc->sc_swbmiss || sc->sc_scanning) rfilt |= HAL_RX_FILTER_BEACON; /* * NB: We don't recalculate the rx filter when * ic_protmode changes; otherwise we could do * this only when ic_protmode != NONE. */ if (ic->ic_opmode == IEEE80211_M_HOSTAP && IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_BEACON; /* * Enable hardware PS-POLL RX only for hostap mode; * STA mode sends PS-POLL frames but never * receives them. */ if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PSPOLL, 0, NULL) == HAL_OK && ic->ic_opmode == IEEE80211_M_HOSTAP) rfilt |= HAL_RX_FILTER_PSPOLL; if (sc->sc_nmeshvaps) { rfilt |= HAL_RX_FILTER_BEACON; if (sc->sc_hasbmatch) rfilt |= HAL_RX_FILTER_BSSID; else rfilt |= HAL_RX_FILTER_PROM; } if (ic->ic_opmode == IEEE80211_M_MONITOR) rfilt |= HAL_RX_FILTER_CONTROL; /* * Enable RX of compressed BAR frames only when doing * 802.11n. Required for A-MPDU. */ if (IEEE80211_IS_CHAN_HT(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_COMPBAR; /* * Enable radar PHY errors if requested by the * DFS module. */ if (sc->sc_dodfs) rfilt |= HAL_RX_FILTER_PHYRADAR; /* * Enable spectral PHY errors if requested by the * spectral module. */ if (sc->sc_dospectral) rfilt |= HAL_RX_FILTER_PHYRADAR; DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, %s if_flags 0x%x\n", __func__, rfilt, ieee80211_opmode_name[ic->ic_opmode], ifp->if_flags); return rfilt; }
int dfs_attach(struct ath_softc *sc) { int i, n; struct ath_dfs *dfs = sc->sc_dfs; #define N(a) (sizeof(a)/sizeof(a[0])) if (dfs != NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: sc_dfs was not NULL\n", __func__); return 1; } dfs = (struct ath_dfs *)OS_MALLOC(sc->sc_osdev, sizeof(struct ath_dfs), GFP_KERNEL); if (dfs == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: ath_dfs allocation failed\n", __func__); return 1; } OS_MEMZERO(dfs, sizeof (struct ath_dfs)); sc->sc_dfs = dfs; dfs->dfs_nol=NULL; dfs_clear_stats(sc); /* Get capability information - can extension channel radar be detected and should we use combined radar RSSI or not.*/ if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_COMBINED_RADAR_RSSI, 0, 0) == HAL_OK) { sc->sc_dfs->sc_dfs_combined_rssi_ok = 1; } else { sc->sc_dfs->sc_dfs_combined_rssi_ok = 0; } if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) { sc->sc_dfs->sc_dfs_ext_chan_ok = 1; } else { sc->sc_dfs->sc_dfs_ext_chan_ok = 0; } if (ath_hal_hasenhanceddfssupport(sc->sc_ah)) { sc->sc_dfs->sc_dfs_use_enhancement = 1; DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: use DFS enhancements\n", __func__); } else { sc->sc_dfs->sc_dfs_use_enhancement = 0; } sc->sc_dfs->sc_dfs_cac_time = ATH_DFS_WAIT_MS; sc->sc_dfs->sc_dfstesttime = ATH_DFS_TEST_RETURN_PERIOD_MS; ATH_DFSQ_LOCK_INIT(dfs); STAILQ_INIT(&dfs->dfs_radarq); ATH_ARQ_LOCK_INIT(dfs); STAILQ_INIT(&dfs->dfs_arq); STAILQ_INIT(&(dfs->dfs_eventq)); ATH_DFSEVENTQ_LOCK_INIT(dfs); dfs->events = (struct dfs_event *)OS_MALLOC(sc->sc_osdev, sizeof(struct dfs_event)*DFS_MAX_EVENTS, GFP_KERNEL); if (dfs->events == NULL) { OS_FREE(dfs); sc->sc_dfs = NULL; DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: events allocation failed\n", __func__); return 1; } for (i=0; i<DFS_MAX_EVENTS; i++) { STAILQ_INSERT_TAIL(&(dfs->dfs_eventq), &dfs->events[i], re_list); } dfs->pulses = (struct dfs_pulseline *)OS_MALLOC(sc->sc_osdev, sizeof(struct dfs_pulseline), GFP_KERNEL); if (dfs->pulses == NULL) { OS_FREE(dfs->events); dfs->events = NULL; OS_FREE(dfs); sc->sc_dfs = NULL; DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: pulse buffer allocation failed\n", __func__); return 1; } dfs->pulses->pl_lastelem = DFS_MAX_PULSE_BUFFER_MASK; #ifdef ATH_ENABLE_AR if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_AR, NULL) == HAL_OK) { dfs_reset_ar(sc); dfs_reset_arq(sc); dfs->dfs_proc_phyerr |= DFS_AR_EN; } #endif if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_PHYDIAG, HAL_CAP_RADAR, NULL) == HAL_OK) { u_int32_t val; /* * If we have fast diversity capability, read off * Strong Signal fast diversity count set in the ini * file, and store so we can restore the value when * radar is disabled */ if (ath_hal_getcapability(sc->sc_ah, HAL_CAP_DIVERSITY, HAL_CAP_STRONG_DIV, &val) == HAL_OK) { dfs->dfs_rinfo.rn_fastdivGCval = val; } dfs->dfs_proc_phyerr |= DFS_RADAR_EN; /* Allocate memory for radar filters */ for (n=0; n<DFS_MAX_RADAR_TYPES; n++) { dfs->dfs_radarf[n] = (struct dfs_filtertype *)OS_MALLOC(sc->sc_osdev, sizeof(struct dfs_filtertype),GFP_KERNEL); if (dfs->dfs_radarf[n] == NULL) { DFS_DPRINTK(sc,ATH_DEBUG_DFS, "%s: cannot allocate memory for radar filter types\n", __func__); goto bad1; } OS_MEMZERO(dfs->dfs_radarf[n], sizeof(struct dfs_filtertype)); } /* Allocate memory for radar table */ dfs->dfs_radartable = (int8_t **)OS_MALLOC(sc->sc_osdev, 256*sizeof(int8_t *), GFP_KERNEL); if (dfs->dfs_radartable == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: cannot allocate memory for radar table\n", __func__); goto bad1; } for (n=0; n<256; n++) { dfs->dfs_radartable[n] = OS_MALLOC(sc->sc_osdev, DFS_MAX_RADAR_OVERLAP*sizeof(int8_t), GFP_KERNEL); if (dfs->dfs_radartable[n] == NULL) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, "%s: cannot allocate memory for radar table entry\n", __func__); goto bad2; } } if (usenol != 1) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, " %s: Disabling Channel NOL\n", __func__); } dfs->dfs_rinfo.rn_use_nol = usenol; /* Init the cached extension channel busy for false alarm reduction */ dfs->dfs_rinfo.ext_chan_busy_ts = ath_hal_gettsf64(sc->sc_ah); dfs->dfs_rinfo.dfs_ext_chan_busy = 0; /* Init the Bin5 chirping related data */ dfs->dfs_rinfo.dfs_bin5_chirp_ts = dfs->dfs_rinfo.ext_chan_busy_ts; dfs->dfs_rinfo.dfs_last_bin5_dur = MAX_BIN5_DUR; dfs->dfs_b5radars = NULL; if ( dfs_init_radar_filters( sc ) ) { DFS_DPRINTK(sc, ATH_DEBUG_DFS, " %s: Radar Filter Intialization Failed \n", __func__); return 1; } } return 0; bad2: OS_FREE(dfs->dfs_radartable); dfs->dfs_radartable = NULL; bad1: for (n=0; n<DFS_MAX_RADAR_TYPES; n++) { if (dfs->dfs_radarf[n] != NULL) { OS_FREE(dfs->dfs_radarf[n]); dfs->dfs_radarf[n] = NULL; } } if (dfs->pulses) { OS_FREE(dfs->pulses); dfs->pulses = NULL; } if (dfs->events) { OS_FREE(dfs->events); dfs->events = NULL; } if (sc->sc_dfs) { OS_FREE(sc->sc_dfs); sc->sc_dfs = NULL; } return 1; #undef N }
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; }
HAL_STATUS ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, a_uint32_t capability, a_uint32_t *result) { return ath_hal_getcapability(ah, type, capability, result); }
/* * Enable radar detection and set the radar parameters per the * values in pe */ void ar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { u_int32_t val; struct ath_hal_private *ahp = AH_PRIVATE(ah); HAL_CHANNEL_INTERNAL *ichan = ahp->ah_curchan; struct ath_hal_9300 *ah9300 = AH9300(ah); bool asleep = ah9300->ah_chip_full_sleep; int reg_writes = 0; if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { ar9300_set_power_mode(ah, HAL_PM_AWAKE, true); } val = OS_REG_READ(ah, AR_PHY_RADAR_0); val |= AR_PHY_RADAR_0_FFT_ENA | AR_PHY_RADAR_0_ENA; if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_FIRPWR; val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); } if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_RRSSI; val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); } if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_HEIGHT; val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); } if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_PRSSI; if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { if (ah->ah_use_cac_prssi) { val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI); } else { val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); } } else { val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); } } if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_INBAND; val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); } OS_REG_WRITE(ah, AR_PHY_RADAR_0, val); val = OS_REG_READ(ah, AR_PHY_RADAR_1); val |= AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK; if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_1_MAXLEN; val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN); } if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); } if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); } OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); if (ath_hal_getcapability(ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) { val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); if (IS_CHAN_HT40(ichan)) { /* Enable extension channel radar detection */ OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val | AR_PHY_RADAR_EXT_ENA); } else { /* HT20 mode, disable extension channel radar detect */ OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); } } /* apply DFS postamble array from INI column 0 is register ID, column 1 is HT20 value, colum2 is HT40 value */ if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_OSPREY_22(ah) || AR_SREV_SCORPION(ah)) { REG_WRITE_ARRAY(&ah9300->ah_ini_dfs,IS_CHAN_HT40(ichan)? 2:1, reg_writes); } #ifdef ATH_HAL_DFS_CHIRPING_FIX_APH128 HDPRINTF(ah, HAL_DBG_DFS,"DFS change the timing value\n"); if (AR_SREV_AR9580(ah) && IS_CHAN_HT40(ichan)) { OS_REG_WRITE(ah, AR_PHY_TIMING6, 0x3140c00a); } #endif if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) { ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true); } }
void ar9300EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe) { u_int32_t val; struct ath_hal_private *ahp = AH_PRIVATE(ah); HAL_CHANNEL_INTERNAL *ichan = ahp->ah_curchan; val = OS_REG_READ(ah, AR_PHY_RADAR_0); if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_FIRPWR; val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR); } if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_RRSSI; val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI); } if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_HEIGHT; val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT); } if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_PRSSI; if (AR_SREV_AR9580(ah)) { if (ah->ah_use_cac_prssi) { val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI); } else { val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); } } else { val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI); } } if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_0_INBAND; val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND); } /*Enable FFT data*/ val |= AR_PHY_RADAR_0_FFT_ENA; OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA); val = OS_REG_READ(ah, AR_PHY_RADAR_1); val |= (AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK); if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) { val &= ~AR_PHY_RADAR_1_MAXLEN; val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN); } OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); if (ath_hal_getcapability(ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) { if (IS_CHAN_HT40(ichan)) { /*Enable extension channel radar detection*/ val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val | AR_PHY_RADAR_EXT_ENA); } else { /*HT20 mode, disable extension channel radar detect*/ val = OS_REG_READ(ah, AR_PHY_RADAR_EXT); OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA); } } if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) { val = OS_REG_READ(ah, AR_PHY_RADAR_1); val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH; val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH); OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); } if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) { val = OS_REG_READ(ah, AR_PHY_RADAR_1); val &= ~AR_PHY_RADAR_1_RELPWR_THRESH; val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH); OS_REG_WRITE(ah, AR_PHY_RADAR_1, val); } }