diff options
Diffstat (limited to 'sys/dev/ic/ath.c')
-rw-r--r-- | sys/dev/ic/ath.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c index 17bc87e7411..66517321c27 100644 --- a/sys/dev/ic/ath.c +++ b/sys/dev/ic/ath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ath.c,v 1.31 2005/07/19 23:04:37 reyk Exp $ */ +/* $OpenBSD: ath.c,v 1.32 2005/07/30 17:13:17 reyk Exp $ */ /* $NetBSD: ath.c,v 1.37 2004/08/18 21:59:39 dyoung Exp $ */ /*- @@ -88,7 +88,7 @@ int ath_init1(struct ath_softc *); int ath_intr1(struct ath_softc *); void ath_stop(struct ifnet *); void ath_start(struct ifnet *); -void ath_reset(struct ath_softc *); +void ath_reset(struct ath_softc *, int); int ath_media_change(struct ifnet *); void ath_watchdog(struct ifnet *); int ath_ioctl(struct ifnet *, u_long, caddr_t); @@ -124,6 +124,7 @@ void ath_draintxq(struct ath_softc *); void ath_stoprecv(struct ath_softc *); int ath_startrecv(struct ath_softc *); void ath_next_scan(void *); +int ath_set_slot_time(struct ath_softc *); void ath_calibrate(void *); HAL_LED_STATE ath_state_to_led(enum ieee80211_state); int ath_newstate(struct ieee80211com *, enum ieee80211_state, int); @@ -215,7 +216,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) struct ath_hal *ah; HAL_STATUS status; HAL_TXQ_INFO qinfo; - int error = 0; + int error = 0, i; DPRINTF(ATH_DEBUG_ANY, ("%s: devid 0x%x\n", __func__, devid)); @@ -311,12 +312,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) goto bad2; } - bzero(&qinfo, sizeof(qinfo)); - qinfo.tqi_subtype = HAL_WME_AC_BE; - sc->sc_txhalq = ath_hal_setup_tx_queue(ah, HAL_TX_QUEUE_DATA, &qinfo); - if (sc->sc_txhalq == (u_int) -1) { - if_printf(ifp, "unable to setup a data xmit queue!\n"); - goto bad2; + for (i = 0; i <= HAL_TX_QUEUE_ID_DATA_MAX; i++) { + bzero(&qinfo, sizeof(qinfo)); + qinfo.tqi_subtype = i; /* should be mapped to WME types */ + sc->sc_txhalq[i] = ath_hal_setup_tx_queue(ah, HAL_TX_QUEUE_DATA, &qinfo); + if (sc->sc_txhalq[i] == (u_int) -1) { + if_printf(ifp, "unable to setup a data xmit queue %u!\n", i); + goto bad2; + } } ifp->if_softc = sc; @@ -342,6 +345,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) | IEEE80211_C_IBSS /* ibss, nee adhoc, mode */ | IEEE80211_C_HOSTAP /* hostap mode */ | IEEE80211_C_MONITOR /* monitor mode */ + | IEEE80211_C_SHSLOT /* short slot time supported */ + | IEEE80211_C_SCANALL /* scan all channels */ | IEEE80211_C_SHPREAMBLE; /* short preamble supported */ /* @@ -603,8 +608,9 @@ ath_fatal_proc(void *arg, int pending) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - if_printf(ifp, "hardware error; resetting\n"); - ath_reset(sc); + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "hardware error; resetting\n"); + ath_reset(sc, 1); } void @@ -614,8 +620,9 @@ ath_rxorn_proc(void *arg, int pending) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - if_printf(ifp, "rx FIFO overrun; resetting\n"); - ath_reset(sc); + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "rx FIFO overrun; resetting\n"); + ath_reset(sc, 1); } void @@ -706,7 +713,7 @@ ath_init1(struct ath_softc *sc) error = EIO; goto done; } - + ath_set_slot_time(sc); /* * Setup the hardware after reset: the key cache * is filled as needed and the receive engine is @@ -814,7 +821,7 @@ ath_stop(struct ifnet *ifp) * and to reset the hardware when rf gain settings must be reset. */ void -ath_reset(struct ath_softc *sc) +ath_reset(struct ath_softc *sc, int full) { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; @@ -835,10 +842,11 @@ ath_reset(struct ath_softc *sc) ath_draintxq(sc); /* stop xmit side */ ath_stoprecv(sc); /* stop recv side */ /* NB: indicate channel change so we do a full reset */ - if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE, &status)) { + if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, full ? AH_TRUE : AH_FALSE, &status)) { if_printf(ifp, "%s: unable to reset hardware; hal status %u\n", __func__, status); } + ath_set_slot_time(sc); /* In case channel changed, save as a node channel */ ic->ic_bss->ni_chan = ic->ic_ibss_chan; ath_hal_set_intr(ah, sc->sc_imask); @@ -998,7 +1006,7 @@ ath_watchdog(struct ifnet *ifp) if (sc->sc_tx_timer) { if (--sc->sc_tx_timer == 0) { if_printf(ifp, "device timeout\n"); - ath_reset(sc); + ath_reset(sc, 1); ifp->if_oerrors++; sc->sc_stats.ast_watchdog++; return; @@ -1097,7 +1105,7 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (ic->ic_opmode != IEEE80211_M_MONITOR) ath_init(ifp); /* XXX lose error */ else - ath_reset(sc); + ath_reset(sc, 1); } error = 0; } @@ -2088,6 +2096,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, const HAL_RATE_TABLE *rt; HAL_BOOL shortPreamble; struct ath_node *an; + u_int8_t hwqueue = HAL_TX_QUEUE_ID_DATA_MIN; wh = mtod(m0, struct ieee80211_frame *); iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; @@ -2359,6 +2368,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, IEEE80211_RATE_VAL; sc->sc_txtap.wt_txpower = 30; sc->sc_txtap.wt_antenna = antenna; + sc->sc_txtap.wt_hwqueue = hwqueue; M_DUP_PKTHDR(&mb, m0); mb.m_data = (caddr_t)&sc->sc_txtap; @@ -2421,7 +2431,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, s = splnet(); TAILQ_INSERT_TAIL(&sc->sc_txq, bf, bf_list); if (sc->sc_txlink == NULL) { - ath_hal_put_tx_buf(ah, sc->sc_txhalq, bf->bf_daddr); + ath_hal_put_tx_buf(ah, sc->sc_txhalq[hwqueue], bf->bf_daddr); DPRINTF(ATH_DEBUG_XMIT, ("%s: TXDP0 = %p (%p)\n", __func__, (caddr_t)bf->bf_daddr, bf->bf_desc)); } else { @@ -2432,7 +2442,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, sc->sc_txlink = &bf->bf_desc[bf->bf_nseg - 1].ds_link; splx(s); - ath_hal_tx_start(ah, sc->sc_txhalq); + ath_hal_tx_start(ah, sc->sc_txhalq[hwqueue]); return 0; } @@ -2450,10 +2460,6 @@ ath_tx_proc(void *arg, int npending) int sr, lr, s; HAL_STATUS status; - DPRINTF(ATH_DEBUG_TX_PROC, ("%s: pending %u tx queue %p, " - "link %p\n", __func__, npending, - (caddr_t)(u_intptr_t) ath_hal_get_tx_buf(sc->sc_ah, - sc->sc_txhalq), sc->sc_txlink)); for (;;) { s = splnet(); bf = TAILQ_FIRST(&sc->sc_txq); @@ -2536,19 +2542,21 @@ ath_draintxq(struct ath_softc *sc) struct ifnet *ifp = &ic->ic_if; struct ieee80211_node *ni; struct ath_buf *bf; - int s; + int s, i; /* XXX return value */ if (!sc->sc_invalid) { - /* don't touch the hardware if marked invalid */ - (void) ath_hal_stop_tx_dma(ah, sc->sc_txhalq); - DPRINTF(ATH_DEBUG_RESET, - ("%s: tx queue %p, link %p\n", __func__, - (caddr_t)(u_intptr_t) ath_hal_get_tx_buf(ah, sc->sc_txhalq), - sc->sc_txlink)); + for (i = 0; i <= HAL_TX_QUEUE_ID_DATA_MAX; i++) { + /* don't touch the hardware if marked invalid */ + (void) ath_hal_stop_tx_dma(ah, sc->sc_txhalq[i]); + DPRINTF(ATH_DEBUG_RESET, + ("%s: tx queue %d (%p), link %p\n", __func__, i, + (caddr_t)(u_intptr_t) ath_hal_get_tx_buf(ah, sc->sc_txhalq[i]), + sc->sc_txlink)); + } (void) ath_hal_stop_tx_dma(ah, sc->sc_bhalq); DPRINTF(ATH_DEBUG_RESET, - ("%s: beacon queue %p\n", __func__, + ("%s: beacon queue (%p)\n", __func__, (caddr_t)(u_intptr_t)ath_hal_get_tx_buf(ah, sc->sc_bhalq))); } for (;;) { @@ -2690,6 +2698,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ieee80211_chan2ieee(ic, chan), chan->ic_freq); return EIO; } + ath_set_slot_time(sc); /* * Re-enable rx framework. */ @@ -2740,6 +2749,18 @@ ath_next_scan(void *arg) splx(s); } +int +ath_set_slot_time(struct ath_softc *sc) +{ + struct ath_hal *ah = sc->sc_ah; + struct ieee80211com *ic = &sc->sc_ic; + + if (ic->ic_flags & IEEE80211_F_SHSLOT) + return (ath_hal_set_slot_time(ah, HAL_SLOT_TIME_9)); + + return (0); +} + /* * Periodically recalibrate the PHY to account * for temperature/environment changes. @@ -2774,7 +2795,7 @@ ath_calibrate(void *arg) * to load new gain values. */ sc->sc_stats.ast_per_rfgain++; - ath_reset(sc); + ath_reset(sc, 1); } if (!ath_hal_calibrate(ah, &hchan)) { DPRINTF(ATH_DEBUG_ANY, |