diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2010-12-31 21:23:56 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2010-12-31 21:23:56 +0000 |
commit | 0b6d62f095cb4dece152a6de03a65095436aed03 (patch) | |
tree | c718432dd18de647218e092767c3a7ab40e83d7d /sys | |
parent | 72bc7ae677c0c13cc45512ec2a960a2c71227142 (diff) |
limit the number of Tx chains used on some 3-stream AR9380 chips
for MCS0~15 to not exceed the PCIe power requirements.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/ar9003.c | 60 | ||||
-rw-r--r-- | sys/dev/ic/ar9380.c | 11 | ||||
-rw-r--r-- | sys/dev/ic/ar9380reg.h | 3 | ||||
-rw-r--r-- | sys/dev/ic/athnvar.h | 5 |
4 files changed, 57 insertions, 22 deletions
diff --git a/sys/dev/ic/ar9003.c b/sys/dev/ic/ar9003.c index 6afce3f9224..dab3f03a297 100644 --- a/sys/dev/ic/ar9003.c +++ b/sys/dev/ic/ar9003.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9003.c,v 1.19 2010/12/31 14:06:05 damien Exp $ */ +/* $OpenBSD: ar9003.c,v 1.20 2010/12/31 21:23:55 damien Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -868,7 +868,7 @@ ar9003_rx_process(struct athn_softc *sc, int qid) ieee80211_michael_mic_failure(ic, 0); /* * XXX Check that it is not a control frame - * (invalid MIC failures on valid ctl frames.) + * (invalid MIC failures on valid ctl frames). */ } ifp->if_ierrors++; @@ -1546,12 +1546,29 @@ ar9003_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, SM(AR_TXC16_PACKET_DUR2, series[2].dur) | SM(AR_TXC16_PACKET_DUR3, series[3].dur); - /* Use the same Tx chains for all tries. */ - ds->ds_ctl18 = - SM(AR_TXC18_CHAIN_SEL0, sc->txchainmask) | - SM(AR_TXC18_CHAIN_SEL1, sc->txchainmask) | - SM(AR_TXC18_CHAIN_SEL2, sc->txchainmask) | - SM(AR_TXC18_CHAIN_SEL3, sc->txchainmask); + if ((sc->flags & ATHN_FLAG_3TREDUCE_CHAIN) && + ic->ic_curmode == IEEE80211_MODE_11A) { + /* + * In order to not exceed PCIe power requirements, we only + * use two Tx chains for MCS0~15 on 5GHz band on these chips. + */ + ds->ds_ctl18 = + SM(AR_TXC18_CHAIN_SEL0, + (ridx[0] <= ATHN_RIDX_MCS15) ? 0x3 : sc->txchainmask) | + SM(AR_TXC18_CHAIN_SEL1, + (ridx[1] <= ATHN_RIDX_MCS15) ? 0x3 : sc->txchainmask) | + SM(AR_TXC18_CHAIN_SEL2, + (ridx[2] <= ATHN_RIDX_MCS15) ? 0x3 : sc->txchainmask) | + SM(AR_TXC18_CHAIN_SEL3, + (ridx[3] <= ATHN_RIDX_MCS15) ? 0x3 : sc->txchainmask); + } else { + /* Use the same Tx chains for all tries. */ + ds->ds_ctl18 = + SM(AR_TXC18_CHAIN_SEL0, sc->txchainmask) | + SM(AR_TXC18_CHAIN_SEL1, sc->txchainmask) | + SM(AR_TXC18_CHAIN_SEL2, sc->txchainmask) | + SM(AR_TXC18_CHAIN_SEL3, sc->txchainmask); + } #ifdef notyet #ifndef IEEE80211_NO_HT /* Use the same short GI setting for all tries. */ @@ -1572,7 +1589,7 @@ ar9003_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, ds->ds_ctl15 |= AR_TXC15_RTSCTS_QUAL01; ds->ds_ctl16 |= AR_TXC16_RTSCTS_QUAL23; } - /* Select protection rate (suboptimal but ok.) */ + /* Select protection rate (suboptimal but ok). */ protridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK2; if (ds->ds_ctl11 & AR_TXC11_RTS_ENABLE) { @@ -1781,7 +1798,14 @@ ar9003_init_chains(struct athn_softc *sc) AR_WRITE(sc, AR_PHY_RX_CHAINMASK, sc->rxchainmask); AR_WRITE(sc, AR_PHY_CAL_CHAINMASK, sc->rxchainmask); - AR_WRITE(sc, AR_SELFGEN_MASK, sc->txchainmask); + if (sc->flags & ATHN_FLAG_3TREDUCE_CHAIN) { + /* + * All self-generated frames are sent using two Tx chains + * on these chips to not exceed PCIe power requirements. + */ + AR_WRITE(sc, AR_SELFGEN_MASK, 0x3); + } else + AR_WRITE(sc, AR_SELFGEN_MASK, sc->txchainmask); AR_WRITE_BARRIER(sc); } @@ -1798,7 +1822,7 @@ ar9003_set_rxchains(struct athn_softc *sc) void ar9003_read_noisefloor(struct athn_softc *sc, int16_t *nf, int16_t *nf_ext) { -/* Sign-extends 9-bit value (assumes upper bits are zeroes.) */ +/* Sign-extends 9-bit value (assumes upper bits are zeroes). */ #define SIGN_EXT(v) (((v) ^ 0x100) - 0x100) uint32_t reg; int i; @@ -2068,7 +2092,7 @@ ar9003_calib_iq(struct athn_softc *sc) int ar9003_get_iq_corr(struct athn_softc *sc, int32_t res[6], int32_t coeff[2]) { -/* Sign-extends 12-bit value (assumes upper bits are zeroes.) */ +/* Sign-extends 12-bit value (assumes upper bits are zeroes). */ #define SIGN_EXT(v) (((v) ^ 0x800) - 0x800) #define SCALE (1 << 15) #define SHIFT (1 << 8) @@ -2123,7 +2147,7 @@ ar9003_get_iq_corr(struct athn_softc *sc, int32_t res[6], int32_t coeff[2]) cos[i] = (cos[i] * SCALE) / div; } - /* Compute IQ mismatch (solve 4x4 linear equation.) */ + /* Compute IQ mismatch (solve 4x4 linear equation). */ f1 = cos[0] - cos[1]; f3 = sin[0] - sin[1]; f2 = (f1 * f1 + f3 * f3) / SCALE; @@ -2362,7 +2386,7 @@ ar9003_paprd_calib(struct athn_softc *sc, struct ieee80211_channel *c) for (i = 0; i < AR9003_TX_GAIN_TABLE_SIZE; i++) sc->txgain[i] = AR_READ(sc, AR_PHY_TXGAIN_TABLE(i)); - /* Set Tx power of training signal (use setting for MCS0.) */ + /* Set Tx power of training signal (use setting for MCS0). */ sc->trainpow = MS(AR_READ(sc, AR_PHY_PWRTX_RATE5), AR_PHY_PWRTX_RATE5_POWERTXHT20_0) - 4; @@ -2455,7 +2479,7 @@ ar9003_set_training_gain(struct athn_softc *sc, int chain) /* * Get desired gain for training signal power (take into account - * current temperature/voltage.) + * current temperature/voltage). */ gain = ar9003_get_desired_txgain(sc, chain, sc->trainpow); /* Find entry in table. */ @@ -2505,7 +2529,7 @@ get_scale(int val) { int log = 0; - /* Find the log base 2 (position of highest bit set.) */ + /* Find the log base 2 (position of highest bit set). */ while (val >>= 1) log++; @@ -2691,7 +2715,7 @@ ar9003_compute_predistortion(struct athn_softc *sc, const uint32_t *lo, sc->pa_in[chain][i] = in; } - /* Compute average theta of first 5 bins (linear region.) */ + /* Compute average theta of first 5 bins (linear region). */ tavg = 0; for (i = 1; i <= 5; i++) tavg += t[i]; @@ -2782,7 +2806,7 @@ ar9003_enable_predistorter(struct athn_softc *sc, int chain) reg = RW(reg, AR_PHY_PA_GAIN123_PA_GAIN1, sc->gain1[chain]); AR_WRITE(sc, AR_PHY_PA_GAIN123_B(chain), reg); - /* Indicate Tx power used for calibration (training signal.) */ + /* Indicate Tx power used for calibration (training signal). */ reg = AR_READ(sc, AR_PHY_PAPRD_CTRL1_B(chain)); reg = RW(reg, AR_PHY_PAPRD_CTRL1_POWER_AT_AM2AM_CAL, sc->trainpow); AR_WRITE(sc, AR_PHY_PAPRD_CTRL1_B(chain), reg); diff --git a/sys/dev/ic/ar9380.c b/sys/dev/ic/ar9380.c index 6e50027417a..f025e3eb1a6 100644 --- a/sys/dev/ic/ar9380.c +++ b/sys/dev/ic/ar9380.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9380.c,v 1.8 2010/12/31 14:06:05 damien Exp $ */ +/* $OpenBSD: ar9380.c,v 1.9 2010/12/31 21:23:55 damien Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -19,7 +19,7 @@ /* * Driver for Atheros 802.11a/g/n chipsets. - * Routines for AR9380 and AR9381 chipsets. + * Routines for AR9380 and AR9485 chipsets. */ #include "bpfilter.h" @@ -158,6 +158,13 @@ ar9380_setup(struct athn_softc *sc) /* Enable PA predistortion if supported. */ if (base->featureEnable & AR_EEP_PAPRD) sc->flags |= ATHN_FLAG_PAPRD; + /* + * Some 3-stream chips may exceed the PCIe power requirements, + * requiring to reduce the number of Tx chains in some cases. + */ + if ((base->miscConfiguration & AR_EEP_CHAIN_MASK_REDUCE) && + sc->txchainmask == 0x7) + sc->flags |= ATHN_FLAG_3TREDUCE_CHAIN; /* Select initialization values based on ROM. */ type = MS(eep->baseEepHeader.txrxgain, AR_EEP_RX_GAIN); diff --git a/sys/dev/ic/ar9380reg.h b/sys/dev/ic/ar9380reg.h index 1429d4cf31a..fc9136f7c28 100644 --- a/sys/dev/ic/ar9380reg.h +++ b/sys/dev/ic/ar9380reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9380reg.h,v 1.13 2010/12/31 18:08:14 damien Exp $ */ +/* $OpenBSD: ar9380reg.h,v 1.14 2010/12/31 21:23:55 damien Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -93,6 +93,7 @@ struct ar9380_base_eep_hdr { uint8_t miscConfiguration; #define AR_EEP_DRIVE_STRENGTH 0x01 +#define AR_EEP_CHAIN_MASK_REDUCE 0x08 uint8_t eepromWriteEnableGpio; uint8_t wlanDisableGpio; diff --git a/sys/dev/ic/athnvar.h b/sys/dev/ic/athnvar.h index 090e66b424e..6e073176944 100644 --- a/sys/dev/ic/athnvar.h +++ b/sys/dev/ic/athnvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: athnvar.h,v 1.26 2010/12/31 14:06:05 damien Exp $ */ +/* $OpenBSD: athnvar.h,v 1.27 2010/12/31 21:23:55 damien Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -419,6 +419,8 @@ struct athn_softc { void (*sc_disable)(struct athn_softc *); void (*sc_power)(struct athn_softc *, int); void (*sc_disable_aspm)(struct athn_softc *); + void (*sc_enable_extsynch)( + struct athn_softc *); int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); @@ -446,6 +448,7 @@ struct athn_softc { #define ATHN_FLAG_11N (1 << 11) #define ATHN_FLAG_AN_TOP2_FIXUP (1 << 12) #define ATHN_FLAG_NON_ENTERPRISE (1 << 13) +#define ATHN_FLAG_3TREDUCE_CHAIN (1 << 14) uint8_t ngpiopins; int led_pin; |