From 047258c7becbba49f513b8c20bf3e062bc4d7b3a Mon Sep 17 00:00:00 2001
From: Arnaud Lacombe <
[email protected]>
Date: Thu, 27 May 2010 01:25:42 -0400
Subject: [PATCH 6/6] ath(4) upgrade
---
sys/dev/ic/ath.c | 208 +++++++++++++------------------------------
sys/dev/ic/ath_netbsd.c | 7 +-
sys/dev/ic/athrate-sample.c | 5 +-
sys/dev/ic/athvar.h | 9 +--
4 files changed, 72 insertions(+), 157 deletions(-)
diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c
index ab1e537..39bd18d 100644
--- a/sys/dev/ic/ath.c
+++ b/sys/dev/ic/ath.c
@@ -78,6 +78,7 @@ __KERNEL_RCSID(0, "$NetBSD: ath.c,v 1.108 2010/01/19 22:06:24 pooka Exp $");
#include <net80211/ieee80211_netbsd.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
#include <net/bpf.h>
@@ -183,8 +184,7 @@ static void ath_calibrate(void *);
static int ath_newstate(struct ieee80211com *, enum ieee80211_state, int);
static void ath_setup_stationkey(struct ieee80211_node *);
static void ath_newassoc(struct ieee80211_node *, int);
-static int ath_getchannels(struct ath_softc *, u_int cc,
- HAL_BOOL outdoor, HAL_BOOL xchanmode);
+static int ath_getchannels(struct ath_softc *, u_int cc);
static void ath_led_event(struct ath_softc *, int);
static void ath_update_txpow(struct ath_softc *);
static void ath_freetx(struct mbuf *);
@@ -198,8 +198,6 @@ static void ath_announce(struct ath_softc *);
int ath_dwelltime = 200; /* 5 channels/second */
int ath_calinterval = 30; /* calibrate every 30 secs */
-int ath_outdoor = AH_TRUE; /* outdoor operation */
-int ath_xchanmode = AH_TRUE; /* enable extended channels */
int ath_countrycode = CTRY_DEFAULT; /* country code */
int ath_regdomain = 0; /* regulatory domain */
int ath_debug = 0;
@@ -275,13 +273,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
error = ENXIO;
goto bad;
}
- if (ah->ah_abi != HAL_ABI_VERSION) {
- if_printf(ifp, "HAL ABI mismatch detected "
- "(HAL:0x%x != driver:0x%x)\n",
- ah->ah_abi, HAL_ABI_VERSION);
- error = ENXIO;
- goto bad;
- }
sc->sc_ah = ah;
if (!prop_dictionary_set_bool(device_properties(sc->sc_dev),
@@ -339,8 +330,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
* is resposible for filtering this list based on settings
* like the phy mode.
*/
- error = ath_getchannels(sc, ath_countrycode,
- ath_outdoor, ath_xchanmode);
+ error = ath_getchannels(sc, ath_countrycode);
if (error != 0)
goto bad;
@@ -466,7 +456,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
*/
sc->sc_softled = (devid == AR5212_DEVID_IBM || devid == AR5211_DEVID);
if (sc->sc_softled) {
- ath_hal_gpioCfgOutput(ah, sc->sc_ledpin);
+ ath_hal_gpioCfgOutput(ah, sc->sc_ledpin,
+ HAL_GPIO_MUX_MAC_NETWORK_LED);
ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon);
}
@@ -721,7 +712,8 @@ ath_resume(struct ath_softc *sc)
ath_hal_resettxqueue(ah, i);
if (sc->sc_softled) {
- ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin);
+ ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin,
+ HAL_GPIO_MUX_MAC_NETWORK_LED);
ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon);
}
return true;
@@ -927,12 +919,12 @@ ath_chan2flags(struct ieee80211com *ic, struct ieee80211_channel *chan)
#define N(a) (sizeof(a) / sizeof(a[0]))
static const u_int modeflags[] = {
0, /* IEEE80211_MODE_AUTO */
- CHANNEL_A, /* IEEE80211_MODE_11A */
- CHANNEL_B, /* IEEE80211_MODE_11B */
- CHANNEL_PUREG, /* IEEE80211_MODE_11G */
+ IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */
+ IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */
+ IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */
0, /* IEEE80211_MODE_FH */
- CHANNEL_ST, /* IEEE80211_MODE_TURBO_A */
- CHANNEL_108G /* IEEE80211_MODE_TURBO_G */
+ IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_A */
+ IEEE80211_CHAN_108G /* IEEE80211_MODE_TURBO_G */
};
enum ieee80211_phymode mode = ieee80211_chan2mode(ic, chan);
@@ -1002,8 +994,8 @@ ath_init(struct ath_softc *sc)
* and then setup of the interrupt mask.
*/
ath_settkipmic(sc);
- sc->sc_curchan.channel = ic->ic_curchan->ic_freq;
- sc->sc_curchan.channelFlags = ath_chan2flags(ic, ic->ic_curchan);
+ sc->sc_curchan.ic_freq = ic->ic_curchan->ic_freq;
+ sc->sc_curchan.ic_flags = ath_chan2flags(ic, ic->ic_curchan);
if (!ath_hal_reset(ah, ic->ic_opmode, &sc->sc_curchan, AH_FALSE, &status)) {
if_printf(ifp, "unable to reset hardware; hal status %u\n",
status);
@@ -1175,8 +1167,8 @@ ath_reset(struct ifnet *ifp)
* constrained to reflect the current operating mode.
*/
c = ic->ic_curchan;
- sc->sc_curchan.channel = c->ic_freq;
- sc->sc_curchan.channelFlags = ath_chan2flags(ic, c);
+ sc->sc_curchan.ic_freq = c->ic_freq;
+ sc->sc_curchan.ic_flags = ath_chan2flags(ic, c);
ath_hal_intrset(ah, 0); /* disable interrupts */
ath_draintxq(sc); /* stop xmit side */
@@ -4105,8 +4097,6 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
u_int8_t txant = ds->ds_txstat.ts_antenna;
sc->sc_stats.ast_ant_tx[txant]++;
sc->sc_ant_tx[txant]++;
- if (ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)
- sc->sc_stats.ast_tx_altrate++;
sc->sc_stats.ast_tx_rssi =
ds->ds_txstat.ts_rssi;
ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi,
@@ -4430,7 +4420,7 @@ ath_chan_change(struct ath_softc *sc, struct ieee80211_channel *chan)
flags = IEEE80211_CHAN_G;
else
flags = IEEE80211_CHAN_B;
- if (IEEE80211_IS_CHAN_T(chan))
+ if (IEEE80211_IS_CHAN_TURBO(chan))
flags |= IEEE80211_CHAN_TURBO;
sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
htole16(chan->ic_freq);
@@ -4482,30 +4472,16 @@ ath_dfswait(void *arg)
static int
ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
{
- struct ath_hal *ah = sc->sc_ah;
struct ieee80211com *ic = &sc->sc_ic;
- HAL_CHANNEL hchan;
+ struct ath_hal *ah = sc->sc_ah;
+ struct ifnet *ifp = &sc->sc_if;
- /*
- * Convert to a HAL channel description with
- * the flags constrained to reflect the current
- * operating mode.
- */
- hchan.channel = chan->ic_freq;
- hchan.channelFlags = ath_chan2flags(ic, chan);
+ DPRINTF(sc, ATH_DEBUG_RESET, "%s: %u (%u MHz, flags 0x%x)\n",
+ __func__, ieee80211_chan2ieee(ic, chan),
+ chan->ic_freq, chan->ic_flags);
- DPRINTF(sc, ATH_DEBUG_RESET,
- "%s: %u (%u MHz, hal flags 0x%x) -> %u (%u MHz, hal flags 0x%x)\n",
- __func__,
- ath_hal_mhz2ieee(ah, sc->sc_curchan.channel,
- sc->sc_curchan.channelFlags),
- sc->sc_curchan.channel, sc->sc_curchan.channelFlags,
- ath_hal_mhz2ieee(ah, hchan.channel, hchan.channelFlags),
- hchan.channel, hchan.channelFlags);
- if (hchan.channel != sc->sc_curchan.channel ||
- hchan.channelFlags != sc->sc_curchan.channelFlags) {
+ if (chan != &sc->sc_curchan) {
HAL_STATUS status;
-
/*
* To switch channels clear any pending DMA operations;
* wait long enough for the RX fifo to drain, reset the
@@ -4515,25 +4491,21 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
ath_hal_intrset(ah, 0); /* disable interrupts */
ath_draintxq(sc); /* clear pending tx frames */
ath_stoprecv(sc); /* turn off frame recv */
- if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE, &status)) {
- if_printf(ic->ic_ifp, "%s: unable to reset "
- "channel %u (%u MHz, flags 0x%x hal flags 0x%x)\n",
+ if (!ath_hal_reset(ah, ic->ic_opmode, chan, AH_TRUE, &status)) {
+ if_printf(ifp, "%s: unable to reset "
+ "channel %u (%u MHz, flags 0x%x), hal status %u\n",
__func__, ieee80211_chan2ieee(ic, chan),
- chan->ic_freq, chan->ic_flags, hchan.channelFlags);
+ chan->ic_freq, chan->ic_flags, status);
return EIO;
}
- sc->sc_curchan = hchan;
- ath_update_txpow(sc); /* update tx power state */
- ath_restore_diversity(sc);
- sc->sc_calinterval = 1;
- sc->sc_caltries = 0;
+ sc->sc_diversity = ath_hal_getdiversity(ah);
/*
* Re-enable rx framework.
*/
if (ath_startrecv(sc) != 0) {
- if_printf(&sc->sc_if,
- "%s: unable to restart recv logic\n", __func__);
+ if_printf(ifp, "%s: unable to restart recv logic\n",
+ __func__);
return EIO;
}
@@ -4541,30 +4513,8 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
* Change channels and update the h/w rate map
* if we're switching; e.g. 11a to 11b/g.
*/
- ic->ic_ibss_chan = chan;
ath_chan_change(sc, chan);
-#if 0
- /*
- * Handle DFS required waiting period to determine
- * if channel is clear of radar traffic.
- */
- if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
-#define DFS_AND_NOT_CLEAR(_c) \
- (((_c)->privFlags & (CHANNEL_DFS | CHANNEL_DFS_CLEAR)) == CHANNEL_DFS)
- if (DFS_AND_NOT_CLEAR(&sc->sc_curchan)) {
- if_printf(&sc->sc_if,
- "wait for DFS clear channel signal\n");
- /* XXX stop sndq */
- sc->sc_if.if_flags |= IFF_OACTIVE;
- callout_reset(&sc->sc_dfs_ch,
- 2 * hz, ath_dfswait, sc);
- } else
- callout_stop(&sc->sc_dfs_ch);
-#undef DFS_NOT_CLEAR
- }
-#endif
-
/*
* Re-enable interrupts.
*/
@@ -4616,7 +4566,7 @@ ath_calibrate(void *arg)
if (!ath_hal_calibrate(ah, &sc->sc_curchan, &iqCalDone)) {
DPRINTF(sc, ATH_DEBUG_ANY,
"%s: calibration of channel %u failed\n",
- __func__, sc->sc_curchan.channel);
+ __func__, sc->sc_curchan.ic_freq);
sc->sc_stats.ast_per_calfail++;
}
/*
@@ -4870,76 +4820,45 @@ ath_newassoc(struct ieee80211_node *ni, int isnew)
}
static int
-ath_getchannels(struct ath_softc *sc, u_int cc,
- HAL_BOOL outdoor, HAL_BOOL xchanmode)
+ath_getchannels(struct ath_softc *sc, u_int cc)
{
-#define COMPAT (CHANNEL_ALL_NOTURBO|CHANNEL_PASSIVE)
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &sc->sc_if;
struct ath_hal *ah = sc->sc_ah;
- HAL_CHANNEL *chans;
- int i, ix, nchan;
-
- chans = malloc(IEEE80211_CHAN_MAX * sizeof(HAL_CHANNEL),
- M_TEMP, M_NOWAIT);
- if (chans == NULL) {
- if_printf(ifp, "unable to allocate channel table\n");
- return ENOMEM;
- }
- if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
- NULL, 0, NULL,
- cc, HAL_MODE_ALL, outdoor, xchanmode)) {
- u_int32_t rd;
-
- (void)ath_hal_getregdomain(ah, &rd);
- if_printf(ifp, "unable to collect channel list from hal; "
- "regdomain likely %u country code %u\n", rd, cc);
- free(chans, M_TEMP);
- return EINVAL;
- }
+ int nchans;
+ HAL_STATUS status;
/*
- * Convert HAL channels to ieee80211 ones and insert
- * them in the table according to their channel number.
+ * Collect channel set based on EEPROM contents.
*/
- for (i = 0; i < nchan; i++) {
- HAL_CHANNEL *c = &chans[i];
- u_int16_t flags;
-
- ix = ath_hal_mhz2ieee(ah, c->channel, c->channelFlags);
- if (ix > IEEE80211_CHAN_MAX) {
- if_printf(ifp, "bad hal channel %d (%u/%x) ignored\n",
- ix, c->channel, c->channelFlags);
- continue;
- }
- if (ix < 0) {
- /* XXX can't handle stuff <2400 right now */
- if (bootverbose)
- if_printf(ifp, "hal channel %d (%u/%x) "
- "cannot be handled; ignored\n",
- ix, c->channel, c->channelFlags);
- continue;
- }
- /*
- * Calculate net80211 flags; most are compatible
- * but some need massaging. Note the static turbo
- * conversion can be removed once net80211 is updated
- * to understand static vs. dynamic turbo.
- */
- flags = c->channelFlags & COMPAT;
- if (c->channelFlags & CHANNEL_STURBO)
- flags |= IEEE80211_CHAN_TURBO;
- if (ic->ic_channels[ix].ic_freq == 0) {
- ic->ic_channels[ix].ic_freq = c->channel;
- ic->ic_channels[ix].ic_flags = flags;
- } else {
- /* channels overlap; e.g. 11g and 11b */
- ic->ic_channels[ix].ic_flags |= flags;
- }
+ status = ath_hal_init_channels(ah, ic->ic_channels, IEEE80211_CHAN_MAX,
+ &nchans, HAL_MODE_ALL, CTRY_DEFAULT, SKU_NONE, AH_TRUE);
+ if (status != HAL_OK) {
+ if_printf(ifp, "%s: unable to collect channel list from hal, "
+ "status %d\n", __func__, status);
+ return EINVAL;
}
- free(chans, M_TEMP);
+#ifdef notyet
+ (void) ath_hal_getregdomain(ah, &sc->sc_eerd);
+ ath_hal_getcountrycode(ah, &sc->sc_eecc); /* NB: cannot fail */
+ /* XXX map Atheros sku's to net80211 SKU's */
+ /* XXX net80211 types too small */
+ ic->ic_regdomain.regdomain = (uint16_t) sc->sc_eerd;
+ ic->ic_regdomain.country = (uint16_t) sc->sc_eecc;
+ ic->ic_regdomain.isocc[0] = ' '; /* XXX don't know */
+ ic->ic_regdomain.isocc[1] = ' ';
+
+ ic->ic_regdomain.ecm = 1;
+ ic->ic_regdomain.location = 'I';
+
+ DPRINTF(sc, ATH_DEBUG_REGDOMAIN,
+ "%s: eeprom rd %u cc %u (mapped rd %u cc %u) location %c%s\n",
+ __func__, sc->sc_eerd, sc->sc_eecc,
+ ic->ic_regdomain.regdomain, ic->ic_regdomain.country,
+ ic->ic_regdomain.location, ic->ic_regdomain.ecm ? " ecm" : "");
+#endif
+
return 0;
-#undef COMPAT
}
static void
@@ -5411,7 +5330,7 @@ ath_announce(struct ath_softc *sc)
#define HAL_MODE_DUALBAND (HAL_MODE_11A|HAL_MODE_11B)
struct ifnet *ifp = &sc->sc_if;
struct ath_hal *ah = sc->sc_ah;
- u_int modes, cc;
+ u_int modes;
if_printf(ifp, "mac %d.%d phy %d.%d",
ah->ah_macVersion, ah->ah_macRev,
@@ -5421,8 +5340,7 @@ ath_announce(struct ath_softc *sc)
* to avoid falsely printing revs for inoperable parts.
* Dual-band radio revs are returned in the 5 GHz rev number.
*/
- ath_hal_getcountrycode(ah, &cc);
- modes = ath_hal_getwirelessmodes(ah, cc);
+ modes = ath_hal_getwirelessmodes(ah);
if ((modes & HAL_MODE_DUALBAND) == HAL_MODE_DUALBAND) {
if (ah->ah_analog5GhzRev && ah->ah_analog2GhzRev)
printf(" 5 GHz radio %d.%d 2 GHz radio %d.%d",
diff --git a/sys/dev/ic/ath_netbsd.c b/sys/dev/ic/ath_netbsd.c
index dbdc1cd..0f8c202 100644
--- a/sys/dev/ic/ath_netbsd.c
+++ b/sys/dev/ic/ath_netbsd.c
@@ -91,10 +91,6 @@ SYSCTL_SETUP(sysctl_ath, "sysctl ath subtree setup")
"chip calibration interval (secs)", calinterval)) != 0)
goto err;
- if ((rc = SYSCTL_GLOBAL_INT(CTLFLAG_READWRITE, "outdoor",
- "outdoor operation", outdoor)) != 0)
- goto err;
-
/* country code */
if ((rc = SYSCTL_GLOBAL_INT(CTLFLAG_READWRITE,
"countrycode", "country code", countrycode)) != 0)
@@ -194,7 +190,8 @@ ath_sysctl_softled(SYSCTLFN_ARGS)
if (softled != sc->sc_softled) {
if (softled) {
/* NB: handle any sc_ledpin change */
- ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin);
+ ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin,
+ HAL_GPIO_MUX_MAC_NETWORK_LED);
ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin,
!sc->sc_ledon);
}
diff --git a/sys/dev/ic/athrate-sample.c b/sys/dev/ic/athrate-sample.c
index 55e463c..e167e35 100644
--- a/sys/dev/ic/athrate-sample.c
+++ b/sys/dev/ic/athrate-sample.c
@@ -494,7 +494,10 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
int ndx = -1;
int mrr;
+ final_rate = 0;
+#ifdef FIXME
final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
+#endif
short_tries = ds->ds_txstat.ts_shortretry + 1;
long_tries = ds->ds_txstat.ts_longretry + 1;
frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
@@ -532,7 +535,7 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
long_tries);
}
- if (!mrr || !(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
+ if (!mrr || !(ds->ds_txstat.ts_rate /*& HAL_TXSTAT_ALTRATE*/)) {
/* only one rate was used */
ndx = rate_to_ndx(sn, final_rate);
DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n",
diff --git a/sys/dev/ic/athvar.h b/sys/dev/ic/athvar.h
index 83eb8b5..92bc372 100644
--- a/sys/dev/ic/athvar.h
+++ b/sys/dev/ic/athvar.h
@@ -222,7 +222,7 @@ struct ath_softc {
const HAL_RATE_TABLE *sc_currates; /* current rate table */
enum ieee80211_phymode sc_curmode; /* current phy mode */
u_int16_t sc_curtxpow; /* current tx power limit */
- HAL_CHANNEL sc_curchan; /* current h/w channel */
+ struct ieee80211_channel sc_curchan; /* current h/w channel */
u_int8_t sc_rixmap[256]; /* IEEE to h/w rate table ix */
struct {
u_int8_t ieeerate; /* IEEE rate */
@@ -324,8 +324,6 @@ void ath_sysctlattach(struct ath_softc *);
extern int ath_dwelltime;
extern int ath_calinterval;
-extern int ath_outdoor;
-extern int ath_xchanmode;
extern int ath_countrycode;
extern int ath_regdomain;
extern int ath_debug;
@@ -570,9 +568,8 @@ extern int ath_txbuf;
((*(_ah)->ah_procTxDesc)((_ah), (_ds), (_ts)))
#define ath_hal_gettxintrtxqs(_ah, _txqs) \
((*(_ah)->ah_getTxIntrQueue)((_ah), (_txqs)))
-
-#define ath_hal_gpioCfgOutput(_ah, _gpio) \
- ((*(_ah)->ah_gpioCfgOutput)((_ah), (_gpio)))
+#define ath_hal_gpioCfgOutput(_ah, _gpio, _type) \
+ ((*(_ah)->ah_gpioCfgOutput)((_ah), (_gpio), (_type)))
#define ath_hal_gpioset(_ah, _gpio, _b) \
((*(_ah)->ah_gpioSet)((_ah), (_gpio), (_b)))
--
1.7.1.rc0.7.g02125bc