Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
0
static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
{
	static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24,
			       0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50,
			       0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1,
			       0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18,
			       0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8,
			       0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84,
			       0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3,
			       0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0};
	u32 len = 1200;
	struct ieee80211_tx_rate *rate;
	struct ieee80211_hw *hw = sc->hw;
	struct ath_hw *ah = sc->sc_ah;
	struct ieee80211_hdr *hdr;
	struct ieee80211_tx_info *tx_info;
	struct sk_buff *skb;
	struct ath_vif *avp;

	if (!sc->tx99_vif)
		return NULL;

	avp = (struct ath_vif *)sc->tx99_vif->drv_priv;

	skb = alloc_skb(len, GFP_KERNEL);
	if (!skb)
		return NULL;

	skb_put(skb, len);

	memset(skb->data, 0, len);

	hdr = (struct ieee80211_hdr *)skb->data;
	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA);
	hdr->duration_id = 0;

	memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
	memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);

	hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);

	tx_info = IEEE80211_SKB_CB(skb);
	memset(tx_info, 0, sizeof(*tx_info));
	rate = &tx_info->control.rates[0];
	tx_info->band = sc->cur_chan->chandef.chan->band;
	tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
	tx_info->control.vif = sc->tx99_vif;
	rate->count = 1;
	if (ah->curchan && IS_CHAN_HT(ah->curchan)) {
		rate->flags |= IEEE80211_TX_RC_MCS;
		if (IS_CHAN_HT40(ah->curchan))
			rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
	}

	memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data));

	return skb;
}
Esempio n. 4
0
static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
					      struct ath9k_hw_cal_data *cal,
					      int16_t *nfarray)
{
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath_nf_limits *limit;
	struct ath9k_nfcal_hist *h;
	bool high_nf_mid = false;
	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
	int i;

	h = cal->nfCalHist;
	limit = ath9k_hw_get_nf_limits(ah, ah->curchan);

	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (!(chainmask & (1 << i)) ||
		    ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
			continue;

		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];

		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
			h[i].currIndex = 0;

		if (h[i].invalidNFcount > 0) {
			h[i].invalidNFcount--;
			h[i].privNF = nfarray[i];
		} else {
			h[i].privNF =
				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
		}

		if (!h[i].privNF)
			continue;

		if (h[i].privNF > limit->max) {
			high_nf_mid = true;

			ath_dbg(common, CALIBRATE,
				"NFmid[%d] (%d) > MAX (%d), %s\n",
				i, h[i].privNF, limit->max,
				(cal->nfcal_interference ?
				 "not corrected (due to interference)" :
				 "correcting to MAX"));

			if (!cal->nfcal_interference)
				h[i].privNF = limit->max;
		}
	}

	if (!high_nf_mid)
		cal->nfcal_interference = false;
}
Esempio n. 5
0
static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
				     struct ath9k_channel *chan,
				     int freq_offset)
{
	int spur_freq_sd = 0;
	int spur_subchannel_sd = 0;
	int spur_delta_phase = 0;

	if (IS_CHAN_HT40(chan)) {
		if (freq_offset < 0) {
			if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
					   AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
				spur_subchannel_sd = 1;
			else
				spur_subchannel_sd = 0;

			spur_freq_sd = ((freq_offset + 10) << 9) / 11;

		} else {
			if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
			    AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
				spur_subchannel_sd = 0;
			else
				spur_subchannel_sd = 1;

			spur_freq_sd = ((freq_offset - 10) << 9) / 11;

		}

		spur_delta_phase = (freq_offset << 17) / 5;

	} else {
		spur_subchannel_sd = 0;
		spur_freq_sd = (freq_offset << 9) /11;
		spur_delta_phase = (freq_offset << 18) / 5;
	}

	spur_freq_sd = spur_freq_sd & 0x3ff;
	spur_delta_phase = spur_delta_phase & 0xfffff;

	ar9003_hw_spur_ofdm(ah,
			    freq_offset,
			    spur_freq_sd,
			    spur_delta_phase,
			    spur_subchannel_sd);
}
Esempio n. 6
0
/* Spur mitigation for OFDM */
static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah,
					 struct ath9k_channel *chan)
{
	int synth_freq;
	int range = 10;
	int freq_offset = 0;
	int mode;
	u8* spurChansPtr;
	unsigned int i;
	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;

	if (IS_CHAN_5GHZ(chan)) {
		spurChansPtr = &(eep->modalHeader5G.spurChans[0]);
		mode = 0;
	}
	else {
		spurChansPtr = &(eep->modalHeader2G.spurChans[0]);
		mode = 1;
	}

	if (spurChansPtr[0] == 0)
		return; /* No spur in the mode */

	if (IS_CHAN_HT40(chan)) {
		range = 19;
		if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
				   AR_PHY_GC_DYN2040_PRI_CH) == 0x0)
			synth_freq = chan->channel - 10;
		else
			synth_freq = chan->channel + 10;
	} else {
		range = 10;
		synth_freq = chan->channel;
	}

	ar9003_hw_spur_ofdm_clear(ah);

	for (i = 0; spurChansPtr[i] && i < 5; i++) {
		freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq;
		if (abs(freq_offset) < range) {
			ar9003_hw_spur_ofdm_work(ah, chan, freq_offset);
			break;
		}
	}
}
static void
ar9285WriteIni(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
{
	u_int modesIndex, freqIndex;
	int regWrites = 0;

	/* Setup the indices for the next set of register array writes */
	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
	freqIndex = 2;
	if (IS_CHAN_HT40(chan))
		modesIndex = 3;
	else if (IS_CHAN_108G(chan))
		modesIndex = 5;
	else
		modesIndex = 4;

	/* Set correct Baseband to analog shift setting to access analog chips. */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
	    modesIndex, regWrites);
	if (AR_SREV_KITE_12_OR_LATER(ah)) {
		regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain,
		    modesIndex, regWrites);
	}
	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
	    1, regWrites);

      	OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));

	if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		uint32_t val;
		val = OS_REG_READ(ah, AR_PCU_MISC_MODE2) &
			(~AR_PCU_MISC_MODE2_HWWAR1);
		OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
		OS_REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
	}

}
Esempio n. 8
0
static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
				       struct ath9k_channel *chan)
{
	u32 phymode;
	u32 enableDacFifo = 0;

	enableDacFifo =
		(REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);

	/* Enable 11n HT, 20 MHz */
	phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH |
		  AR_PHY_GC_SHORT_GI_40 | enableDacFifo;

	/* Configure baseband for dynamic 20/40 operation */
	if (IS_CHAN_HT40(chan)) {
		phymode |= AR_PHY_GC_DYN2040_EN;
		/* Configure control (primary) channel at +-10MHz */
		if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
		    (chan->chanmode == CHANNEL_G_HT40PLUS))
			phymode |= AR_PHY_GC_DYN2040_PRI_CH;

	}

	/* make sure we preserve INI settings */
	phymode |= REG_READ(ah, AR_PHY_GEN_CTRL);
	/* turn off Green Field detection for STA for now */
	phymode &= ~AR_PHY_GC_GF_DETECT_EN;

	REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode);

	/* Configure MAC for 20/40 operation */
	ath9k_hw_set11nmac2040(ah);

	/* global transmit timeout (25 TUs default)*/
	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
	/* carrier sense timeout */
	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
}
Esempio n. 9
0
static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
					      struct ath9k_hw_cal_data *cal,
					      int16_t *nfarray)
{
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath_nf_limits *limit;
	struct ath9k_nfcal_hist *h;
	bool high_nf_mid = false;
	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
	int i;

	h = cal->nfCalHist;
	limit = ath9k_hw_get_nf_limits(ah, ah->curchan);

	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (!(chainmask & (1 << i)) ||
		    ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
			continue;

		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];

		if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
			h[i].currIndex = 0;

		if (h[i].invalidNFcount > 0) {
			h[i].invalidNFcount--;
			h[i].privNF = nfarray[i];
		} else {
			h[i].privNF =
				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
		}

		if (!h[i].privNF)
			continue;

		if (h[i].privNF > limit->max) {
			high_nf_mid = true;

			ath_dbg(common, CALIBRATE,
				"NFmid[%d] (%d) > MAX (%d), %s\n",
				i, h[i].privNF, limit->max,
				(cal->nfcal_interference ?
				 "not corrected (due to interference)" :
				 "correcting to MAX"));

			/*
			 * Normally we limit the average noise floor by the
			 * hardware specific maximum here. However if we have
			 * encountered stuck beacons because of interference,
			 * we bypass this limit here in order to better deal
			 * with our environment.
			 */
			if (!cal->nfcal_interference)
				h[i].privNF = limit->max;
		}
	}

	/*
	 * If the noise floor seems normal for all chains, assume that
	 * there is no significant interference in the environment anymore.
	 * Re-enable the enforcement of the NF maximum again.
	 */
	if (!high_nf_mid)
		cal->nfcal_interference = false;
}
Esempio n. 10
0
extern void
ar9300_init_rate_txpower(struct ath_hal *ah, u_int mode,
                      HAL_CHANNEL_INTERNAL *chan,
                      u_int8_t power_per_rate[], u_int8_t chainmask)
{
    const HAL_RATE_TABLE *rt;
    HAL_BOOL is40 = IS_CHAN_HT40(chan);

    rt = ar9300_get_rate_table(ah, mode);
    HALASSERT(rt != NULL);

    switch (mode) {
    case HAL_MODE_11A:
        ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
                              AR9300_11A_RT_OFDM_OFFSET, chainmask);
        break;
    case HAL_MODE_11NA_HT20:
    case HAL_MODE_11NA_HT40PLUS:
    case HAL_MODE_11NA_HT40MINUS:
        ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
                              AR9300_11NA_RT_OFDM_OFFSET, chainmask);
        ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,
                            AR9300_11NA_RT_HT_SS_OFFSET,
                            AR9300_11NA_RT_HT_DS_OFFSET,
                            AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
        ar9300_init_rate_txpower_stbc(ah, rt, is40,
                            AR9300_11NA_RT_HT_SS_OFFSET,
                            AR9300_11NA_RT_HT_DS_OFFSET,
                            AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
        /* For FCC the array gain has to be factored for CDD mode */
        if (is_reg_dmn_fcc(chan->conformance_test_limit)) {
            ar9300_adjust_rate_txpower_cdd(ah, rt, is40, 
                            AR9300_11NA_RT_HT_SS_OFFSET,
                            AR9300_11NA_RT_HT_DS_OFFSET,
                            AR9300_11NA_RT_HT_TS_OFFSET, chainmask);
        }
        break;
    case HAL_MODE_11G:
        ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);
        ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
                              AR9300_11G_RT_OFDM_OFFSET, chainmask);
        break;
    case HAL_MODE_11B:
        ar9300_init_rate_txpower_cck(ah, rt, power_per_rate, chainmask);
        break;
    case HAL_MODE_11NG_HT20:
    case HAL_MODE_11NG_HT40PLUS:
    case HAL_MODE_11NG_HT40MINUS:
        ar9300_init_rate_txpower_cck(ah, rt, power_per_rate,  chainmask);
        ar9300_init_rate_txpower_ofdm(ah, rt, power_per_rate,
                              AR9300_11NG_RT_OFDM_OFFSET, chainmask);
        ar9300_init_rate_txpower_ht(ah, rt, is40, power_per_rate,
                            AR9300_11NG_RT_HT_SS_OFFSET,
                            AR9300_11NG_RT_HT_DS_OFFSET,
                            AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
        ar9300_init_rate_txpower_stbc(ah, rt, is40,
                            AR9300_11NG_RT_HT_SS_OFFSET,
                            AR9300_11NG_RT_HT_DS_OFFSET,
                            AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
        /* For FCC the array gain needs to be factored for CDD mode */
        if (is_reg_dmn_fcc(chan->conformance_test_limit)) {
            ar9300_adjust_rate_txpower_cdd(ah, rt, is40, 
                            AR9300_11NG_RT_HT_SS_OFFSET,
                            AR9300_11NG_RT_HT_DS_OFFSET,
                            AR9300_11NG_RT_HT_TS_OFFSET, chainmask);
        }
        break;
    default:
        HALDEBUG(ah, HAL_DEBUG_POWER_MGMT, "%s: invalid mode 0x%x\n",
             __func__, mode);
        HALASSERT(0);
        break;
    }

}
Esempio n. 11
0
int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
{
	struct ath9k_nfcal_hist *h = NULL;
	unsigned i, j;
	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
	struct ath_common *common = ath9k_hw_common(ah);
	s16 default_nf = ath9k_hw_get_default_nf(ah, chan);

	if (ah->caldata)
		h = ah->caldata->nfCalHist;

	ENABLE_REG_RMW_BUFFER(ah);
	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (chainmask & (1 << i)) {
			s16 nfval;

			if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan))
				continue;

			if (h)
				nfval = h[i].privNF;
			else
				nfval = default_nf;

			REG_RMW(ah, ah->nf_regs[i],
				(((u32) nfval << 1) & 0x1ff), 0x1ff);
		}
	}

	/*
	 * Load software filtered NF value into baseband internal minCCApwr
	 * variable.
	 */
	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_ENABLE_NF);
	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
	REG_RMW_BUFFER_FLUSH(ah);

	/*
	 * Wait for load to complete, should be fast, a few 10s of us.
	 * The max delay was changed from an original 250us to 10000us
	 * since 250us often results in NF load timeout and causes deaf
	 * condition during stress testing 12/12/2009
	 */
	for (j = 0; j < 10000; j++) {
		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
		     AR_PHY_AGC_CONTROL_NF) == 0)
			break;
		udelay(10);
	}

	/*
	 * We timed out waiting for the noisefloor to load, probably due to an
	 * in-progress rx. Simply return here and allow the load plenty of time
	 * to complete before the next calibration interval.  We need to avoid
	 * trying to load -50 (which happens below) while the previous load is
	 * still in progress as this can cause rx deafness. Instead by returning
	 * here, the baseband nf cal will just be capped by our present
	 * noisefloor until the next calibration timer.
	 */
	if (j == 10000) {
		ath_dbg(common, ANY,
			"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
			REG_READ(ah, AR_PHY_AGC_CONTROL));
		return -ETIMEDOUT;
	}

	/*
	 * Restore maxCCAPower register parameter again so that we're not capped
	 * by the median we just loaded.  This will be initial (and max) value
	 * of next noise floor calibration the baseband does.
	 */
	ENABLE_REG_RMW_BUFFER(ah);
	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (chainmask & (1 << i)) {
			if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan))
				continue;

			REG_RMW(ah, ah->nf_regs[i],
					(((u32) (-50) << 1) & 0x1ff), 0x1ff);
		}
	}
	REG_RMW_BUFFER_FLUSH(ah);

	return 0;
}
Esempio n. 12
0
/*
 * 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);
    }
}
Esempio n. 13
0
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);
    }
}