summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2010-12-31 21:23:56 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2010-12-31 21:23:56 +0000
commit0b6d62f095cb4dece152a6de03a65095436aed03 (patch)
treec718432dd18de647218e092767c3a7ab40e83d7d /sys
parent72bc7ae677c0c13cc45512ec2a960a2c71227142 (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.c60
-rw-r--r--sys/dev/ic/ar9380.c11
-rw-r--r--sys/dev/ic/ar9380reg.h3
-rw-r--r--sys/dev/ic/athnvar.h5
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;