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