From 63d8fb2cb6793f871b7d245f4ddf5912fd864a15 Mon Sep 17 00:00:00 2001 From: dyoung Date: Wed, 23 Nov 2005 04:12:33 +0000 Subject: [PATCH] Miscellaneous Realtek RTL8180L driver improvements: 1 Added new sysctl controls for debugging. 2 Improve detection & support for hardware WEP. 3 Revamp handling of transmit descriptor rings. 4 Reliably IFF_OACTIVE when transmit descriptors are available, to stop the transmit section of the driver from freezing up. 5 Fix beacon transmission in adhoc and hostap modes. XXX There is a wart in hostap mode, where beacons are transmitted at 1/2 the correct rate. Load beacon descriptors when the RTW_INTR_BINT interrupt arrives; schedule RTW_INTR_BINT 1ms ahead of the target beacon time. 6 Recover more gracefully from tx/rx errors: avoid transmitter/receiver/chip resets. Try to re-synchronize software state with hardware state---e.g., load next descriptor pointer from hardware. 7 Activate the transmit watchdog timer for beacons as well as other packets. 8 Introduce rtw_idle() that waits for transmit DMA to finish; call it before resetting the transmitter. --- sys/dev/ic/rtw.c | 508 ++++++++++++++++++++++++++++++-------------- sys/dev/ic/rtwreg.h | 6 +- sys/dev/ic/rtwvar.h | 60 +++--- 3 files changed, 384 insertions(+), 190 deletions(-) diff --git a/sys/dev/ic/rtw.c b/sys/dev/ic/rtw.c index f50d27b71798..1a52d7b3b58a 100644 --- a/sys/dev/ic/rtw.c +++ b/sys/dev/ic/rtw.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtw.c,v 1.57 2005/11/18 16:53:56 skrll Exp $ */ +/* $NetBSD: rtw.c,v 1.58 2005/11/23 04:12:33 dyoung Exp $ */ /*- * Copyright (c) 2004, 2005 David Young. All rights reserved. * @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.57 2005/11/18 16:53:56 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.58 2005/11/23 04:12:33 dyoung Exp $"); #include "bpfilter.h" @@ -79,12 +79,12 @@ __KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.57 2005/11/18 16:53:56 skrll Exp $"); panic __msg ; \ } while (0) -int rtw_rfprog_fallback = 0; -int rtw_host_rfio = 0; +static int rtw_rfprog_fallback = 0; +static int rtw_host_rfio = 0; #ifdef RTW_DEBUG int rtw_debug = 0; -int rtw_rxbufs_limit = RTW_RXQLEN; +static int rtw_rxbufs_limit = RTW_RXQLEN; #endif /* RTW_DEBUG */ #define NEXT_ATTACH_STATE(sc, state) do { \ @@ -93,10 +93,18 @@ int rtw_rxbufs_limit = RTW_RXQLEN; sc->sc_attach_state = state; \ } while (0) +static int rtw_xmtr_restart = 0; +static int rtw_do_chip_reset = 0; +static int rtw_ring_reset = 0; + int rtw_dwelltime = 200; /* milliseconds */ static struct ieee80211_cipher rtw_cipher_wep; static void rtw_start(struct ifnet *); +static void rtw_reset_oactive(struct rtw_softc *); +static struct mbuf *rtw_beacon_alloc(struct rtw_softc *, + struct ieee80211_node *); +static u_int rtw_txring_next(struct rtw_regs *, struct rtw_txdesc_blk *); static void rtw_io_enable(struct rtw_regs *, uint8_t, int); static int rtw_key_delete(struct ieee80211com *, const struct ieee80211_key *); @@ -143,6 +151,28 @@ SYSCTL_SETUP(sysctl_rtw, "sysctl rtw(4) subtree setup") NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) goto err; + if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, + "chip_reset", SYSCTL_DESCR("Gratuitously reset chip on rcvr error"), + NULL, 0, &rtw_do_chip_reset, 0, + CTL_CREATE, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, + "ring_reset", SYSCTL_DESCR("Reset ring pointers on rcvr error"), + NULL, 0, &rtw_ring_reset, 0, + CTL_CREATE, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, + "xmtr_restart", + SYSCTL_DESCR("Gratuitously reset xmtr on rcvr error"), + NULL, 0, &rtw_xmtr_restart, 0, + CTL_CREATE, CTL_EOL)) != 0) + goto err; + #ifdef RTW_DEBUG /* control debugging printfs */ if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, @@ -530,7 +560,7 @@ rtw_chip_reset(struct rtw_regs *regs, const char *dvname) } static int -rtw_wep_decap(struct ieee80211_key *k, struct mbuf *m, int force) +rtw_wep_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) { struct ieee80211_key keycopy; @@ -539,7 +569,7 @@ rtw_wep_decap(struct ieee80211_key *k, struct mbuf *m, int force) keycopy = *k; keycopy.wk_flags &= ~IEEE80211_KEY_SWCRYPT; - return (*ieee80211_cipher_wep.ic_decap)(&keycopy, m, force); + return (*ieee80211_cipher_wep.ic_decap)(&keycopy, m, hdrlen); } static int @@ -569,11 +599,6 @@ rtw_key_set(struct ieee80211com *ic, const struct ieee80211_key *k, if (k->wk_keyix >= IEEE80211_WEP_NKID) return 0; - if (k->wk_cipher == &ieee80211_cipher_wep) { - rtw_cipher_wep = ieee80211_cipher_wep; - rtw_cipher_wep.ic_decap = rtw_wep_decap; - ic->ic_nw_keys[k->wk_keyix].wk_cipher = &rtw_cipher_wep; - } sc->sc_flags &= ~RTW_F_DK_VALID; return 1; @@ -598,9 +623,9 @@ rtw_key_update_end(struct ieee80211com *ic) DPRINTF(sc, RTW_DEBUG_KEY, ("%s:\n", __func__)); - if ((sc->sc_flags & RTW_F_DK_VALID) != 0) - return; - if ((sc->sc_flags & RTW_F_ENABLED) == 0) + if ((sc->sc_flags & RTW_F_DK_VALID) != 0 || + (sc->sc_flags & RTW_F_ENABLED) == 0 || + (sc->sc_flags & RTW_F_INVALID) != 0) return; rtw_io_enable(&sc->sc_regs, RTW_CR_RE | RTW_CR_TE, 0); @@ -609,10 +634,20 @@ rtw_key_update_end(struct ieee80211com *ic) (ifp->if_flags & IFF_RUNNING) != 0); } +static __inline int +rtw_key_hwsupp(uint32_t flags, const struct ieee80211_key *k) +{ + if (k->wk_cipher->ic_cipher != IEEE80211_CIPHER_WEP) + return 0; + + return ((flags & RTW_C_RXWEP_40) != 0 && k->wk_keylen == 5) || + ((flags & RTW_C_RXWEP_104) != 0 && k->wk_keylen == 13); +} + static void rtw_wep_setkeys(struct rtw_softc *sc, struct ieee80211_key *wk, int txkey) { - uint8_t cfg0, psr, scr; + uint8_t psr, scr; int i, tx_key_len; struct rtw_regs *regs; union rtw_keys *rk; @@ -622,35 +657,45 @@ rtw_wep_setkeys(struct rtw_softc *sc, struct ieee80211_key *wk, int txkey) (void)memset(rk->rk_keys, 0, sizeof(rk->rk_keys)); + /* Temporarily use software crypto for all keys. */ + for (i = 0; i < IEEE80211_WEP_NKID; i++) { + if (wk[i].wk_cipher == &rtw_cipher_wep) + wk[i].wk_cipher = &ieee80211_cipher_wep; + } + rtw_set_access(regs, RTW_ACCESS_CONFIG); psr = RTW_READ8(regs, RTW_PSR); scr = RTW_READ8(regs, RTW_SCR); - cfg0 = RTW_READ8(regs, RTW_CONFIG0); scr &= ~(RTW_SCR_KM_MASK | RTW_SCR_TXSECON | RTW_SCR_RXSECON); - cfg0 &= ~(RTW_CONFIG0_WEP104 | RTW_CONFIG0_WEP40); if ((sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) == 0) goto out; + if (!rtw_key_hwsupp(sc->sc_flags, &wk[txkey])) + goto out; + tx_key_len = wk[txkey].wk_keylen; switch (tx_key_len) { case 5: - scr |= RTW_SCR_RXSECON | RTW_SCR_KM_WEP40; + scr |= RTW_SCR_KM_WEP40; break; case 13: - scr |= RTW_SCR_RXSECON | RTW_SCR_KM_WEP104; + scr |= RTW_SCR_KM_WEP104; break; default: goto out; } - cfg0 |= RTW_CONFIG0_WEP104 | RTW_CONFIG0_WEP40; + scr |= RTW_SCR_RXSECON; for (i = 0; i < IEEE80211_WEP_NKID; i++) { - if (wk[i].wk_keylen != tx_key_len) + if (wk[i].wk_keylen != tx_key_len || + wk[i].wk_cipher->ic_cipher != IEEE80211_CIPHER_WEP) continue; + /* h/w will decrypt, s/w still strips headers */ + wk[i].wk_cipher = &rtw_cipher_wep; (void)memcpy(rk->rk_keys[i], wk[i].wk_key, wk[i].wk_keylen); } @@ -664,12 +709,9 @@ out: bus_space_barrier(regs->r_bt, regs->r_bh, RTW_DK0, sizeof(rk->rk_words), BUS_SPACE_BARRIER_SYNC); - printf("%s: psr = %#" PRIx8, sc->sc_dev.dv_xname, psr); - + RTW_WBW(regs, RTW_DK0, RTW_PSR); RTW_WRITE8(regs, RTW_PSR, psr); - - RTW_WRITE8(regs, RTW_CONFIG0, cfg0); - RTW_WBW(regs, RTW_CONFIG0, RTW_SCR); + RTW_WBW(regs, RTW_PSR, RTW_SCR); RTW_WRITE8(regs, RTW_SCR, scr); RTW_SYNC(regs, RTW_SCR, RTW_SCR); rtw_set_access(regs, RTW_ACCESS_NONE); @@ -841,6 +883,11 @@ rtw_srom_parse(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold, *rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM), RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1); + if ((RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_WEP104) != 0) + *flags |= RTW_C_RXWEP_104; + + *flags |= RTW_C_RXWEP_40; /* XXX */ + *rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID); switch (*rfchipid) { case RTW_RFCHIPID_GCT: /* this combo seen in the wild */ @@ -1062,9 +1109,9 @@ rtw_init_channels(enum rtw_locale locale, #undef ADD_CHANNEL } + static __inline void -rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale, - const char *dvname) +rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale) { uint8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0); @@ -1129,11 +1176,32 @@ static void rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *tdb) { int pri; - u_int ndesc[RTW_NTXPRI] = - {RTW_NTXDESCLO, RTW_NTXDESCMD, RTW_NTXDESCHI, RTW_NTXDESCBCN}; + /* nfree: the number of free descriptors in each ring. + * The beacon ring is a special case: I do not let the + * driver use all of the descriptors on the beacon ring. + * The reasons are two-fold: + * + * (1) A BEACON descriptor's OWN bit is (apparently) not + * updated, so the driver cannot easily know if the descriptor + * belongs to it, or if it is racing the NIC. If the NIC + * does not OWN every descriptor, then the driver can safely + * update the descriptors when RTW_TBDA points at tdb_next. + * + * (2) I hope that the NIC will process more than one BEACON + * descriptor in a single beacon interval, since that will + * enable multiple-BSS support. Since the NIC does not + * clear the OWN bit, there is no natural place for it to + * stop processing BEACON desciptors. Maybe it will *not* + * stop processing them! I do not want to chance the NIC + * looping around and around a saturated beacon ring, so + * I will leave one descriptor unOWNed at all times. + */ + u_int nfree[RTW_NTXPRI] = + {RTW_NTXDESCLO, RTW_NTXDESCMD, RTW_NTXDESCHI, + RTW_NTXDESCBCN - 1}; for (pri = 0; pri < RTW_NTXPRI; pri++) { - tdb[pri].tdb_nfree = ndesc[pri]; + tdb[pri].tdb_nfree = nfree[pri]; tdb[pri].tdb_next = 0; } } @@ -1151,6 +1219,7 @@ rtw_txsoft_blk_init(struct rtw_txsoft_blk *tsb) ts->ts_mbuf = NULL; SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q); } + tsb->tsb_tx_timer = 0; return 0; } @@ -1343,7 +1412,6 @@ rtw_rxdesc_init_all(struct rtw_rxdesc_blk *rdb, struct rtw_rxsoft *ctl, int kick rs = &ctl[i]; rtw_rxdesc_init(rdb, rs, i, kick); } - rdb->rdb_next = 0; } static void @@ -1621,6 +1689,7 @@ rtw_txsofts_release(bus_dma_tag_t dmat, struct ieee80211com *ic, SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q); SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q); } + tsb->tsb_tx_timer = 0; } static __inline void @@ -1658,14 +1727,33 @@ rtw_collect_txpkt(struct rtw_softc *sc, struct rtw_txdesc_blk *tdb, condstring, rts_retry, data_retry)); } +static void +rtw_reset_oactive(struct rtw_softc *sc) +{ + short oflags; + int pri; + struct rtw_txsoft_blk *tsb; + struct rtw_txdesc_blk *tdb; + oflags = sc->sc_if.if_flags; + for (pri = 0; pri < RTW_NTXPRI; pri++) { + tsb = &sc->sc_txsoft_blk[pri]; + tdb = &sc->sc_txdesc_blk[pri]; + if (!SIMPLEQ_EMPTY(&tsb->tsb_freeq) && tdb->tdb_nfree > 0) + sc->sc_if.if_flags &= ~IFF_OACTIVE; + } + if (oflags != sc->sc_if.if_flags) { + DPRINTF(sc, RTW_DEBUG_OACTIVE, + ("%s: reset OACTIVE\n", __func__)); + } +} + /* Collect transmitted packets. */ static __inline void rtw_collect_txring(struct rtw_softc *sc, struct rtw_txsoft_blk *tsb, - struct rtw_txdesc_blk *tdb) + struct rtw_txdesc_blk *tdb, int force) { int ndesc; struct rtw_txsoft *ts; - struct ifnet *ifp = &sc->sc_if; while ((ts = SIMPLEQ_FIRST(&tsb->tsb_dirtyq)) != NULL) { ndesc = 1 + ts->ts_last - ts->ts_first; @@ -1677,22 +1765,28 @@ rtw_collect_txring(struct rtw_softc *sc, struct rtw_txsoft_blk *tsb, rtw_txdescs_sync(tdb, ts->ts_first, ndesc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - if ((tdb->tdb_desc[ts->ts_last].td_stat & + if (force) { + int i; + for (i = ts->ts_first; ; i = RTW_NEXT_IDX(tdb, i)) { + tdb->tdb_desc[i].td_stat &= + ~htole32(RTW_TXSTAT_OWN); + if (i == ts->ts_last) + break; + } + rtw_txdescs_sync(tdb, ts->ts_first, ndesc, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + } else if ((tdb->tdb_desc[ts->ts_last].td_stat & htole32(RTW_TXSTAT_OWN)) != 0) break; - if (&sc->sc_txdesc_blk[RTW_TXPRIBCN] == tdb) { - RTW_DPRINTF(RTW_DEBUG_BEACON, - ("%s: collected beacon\n", __func__)); - } - rtw_collect_txpkt(sc, tdb, ts, ndesc); SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q); SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q); - ifp->if_flags &= ~IFF_OACTIVE; } + /* no more pending transmissions, cancel watchdog */ if (ts == NULL) tsb->tsb_tx_timer = 0; + rtw_reset_oactive(sc); } static void @@ -1707,21 +1801,61 @@ rtw_intr_tx(struct rtw_softc *sc, uint16_t isr) tsb = &sc->sc_txsoft_blk[pri]; tdb = &sc->sc_txdesc_blk[pri]; - rtw_collect_txring(sc, tsb, tdb); - - if ((isr & RTW_INTR_TX) != 0) - rtw_start(ifp); + rtw_collect_txring(sc, tsb, tdb, 0); } - /* TBD */ + if ((isr & RTW_INTR_TX) != 0) + rtw_start(ifp); + return; } static void rtw_intr_beacon(struct rtw_softc *sc, uint16_t isr) { - /* TBD */ - return; + u_int next; + uint32_t tsfth, tsftl; + struct ieee80211com *ic; + struct rtw_txdesc_blk *tdb = &sc->sc_txdesc_blk[RTW_TXPRIBCN]; + struct rtw_txsoft_blk *tsb = &sc->sc_txsoft_blk[RTW_TXPRIBCN]; + struct mbuf *m; + + tsfth = RTW_READ(&sc->sc_regs, RTW_TSFTRH); + tsftl = RTW_READ(&sc->sc_regs, RTW_TSFTRL); + + if ((isr & (RTW_INTR_TBDOK|RTW_INTR_TBDER)) != 0) { + next = rtw_txring_next(&sc->sc_regs, tdb); + RTW_DPRINTF(RTW_DEBUG_BEACON, + ("%s: beacon ring %sprocessed, isr = %#04" PRIx16 + ", next %u expected %u, %" PRIu64 "\n", __func__, + (next == tdb->tdb_next) ? "" : "un", isr, next, + tdb->tdb_next, (uint64_t)tsfth << 32 | tsftl)); + if ((RTW_READ8(&sc->sc_regs, RTW_TPPOLL) & RTW_TPPOLL_BQ) == 0){ + rtw_collect_txring(sc, tsb, tdb, 1); + tdb->tdb_next = 0; + } + } + /* Start beacon transmission. */ + + if ((isr & RTW_INTR_BCNINT) != 0 && + sc->sc_ic.ic_state == IEEE80211_S_RUN && + SIMPLEQ_EMPTY(&tsb->tsb_dirtyq)) { + RTW_DPRINTF(RTW_DEBUG_BEACON, + ("%s: beacon prep. time, isr = %#04" PRIx16 + ", %16" PRIu64 "\n", __func__, isr, + (uint64_t)tsfth << 32 | tsftl)); + ic = &sc->sc_ic; + m = rtw_beacon_alloc(sc, ic->ic_bss); + + if (m == NULL) { + printf("%s: could not allocate beacon\n", + sc->sc_dev.dv_xname); + return; + } + m->m_pkthdr.rcvif = (void *)ieee80211_ref_node(ic->ic_bss); + IF_ENQUEUE(&sc->sc_beaconq, m); + rtw_start(&sc->sc_if); + } } static void @@ -1767,28 +1901,35 @@ rtw_dump_rings(struct rtw_softc *sc) static void rtw_hwring_setup(struct rtw_softc *sc) { + int pri; struct rtw_regs *regs = &sc->sc_regs; + struct rtw_txdesc_blk *tdb; + + sc->sc_txdesc_blk[RTW_TXPRILO].tdb_basereg = RTW_TLPDA; + sc->sc_txdesc_blk[RTW_TXPRILO].tdb_base = RTW_RING_BASE(sc, hd_txlo); + sc->sc_txdesc_blk[RTW_TXPRIMD].tdb_basereg = RTW_TNPDA; + sc->sc_txdesc_blk[RTW_TXPRIMD].tdb_base = RTW_RING_BASE(sc, hd_txmd); + sc->sc_txdesc_blk[RTW_TXPRIHI].tdb_basereg = RTW_THPDA; + sc->sc_txdesc_blk[RTW_TXPRIHI].tdb_base = RTW_RING_BASE(sc, hd_txhi); + sc->sc_txdesc_blk[RTW_TXPRIBCN].tdb_basereg = RTW_TBDA; + sc->sc_txdesc_blk[RTW_TXPRIBCN].tdb_base = RTW_RING_BASE(sc, hd_bcn); + + for (pri = 0; pri < RTW_NTXPRI; pri++) { + tdb = &sc->sc_txdesc_blk[pri]; + RTW_WRITE(regs, tdb->tdb_basereg, tdb->tdb_base); + RTW_DPRINTF(RTW_DEBUG_XMIT_DESC, + ("%s: reg[tdb->tdb_basereg] <- %" PRIxPTR "\n", __func__, + (uintptr_t)tdb->tdb_base)); + } + RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(sc, hd_rx)); - RTW_WRITE(regs, RTW_TLPDA, RTW_RING_BASE(sc, hd_txlo)); - RTW_WRITE(regs, RTW_TNPDA, RTW_RING_BASE(sc, hd_txmd)); - RTW_WRITE(regs, RTW_THPDA, RTW_RING_BASE(sc, hd_txhi)); - RTW_WRITE(regs, RTW_TBDA, RTW_RING_BASE(sc, hd_bcn)); - RTW_SYNC(regs, RTW_TLPDA, RTW_RDSAR); - RTW_DPRINTF(RTW_DEBUG_XMIT_DESC, - ("%s: reg[TLPDA] <- %" PRIxPTR "\n", __func__, - (uintptr_t)RTW_RING_BASE(sc, hd_txlo))); - RTW_DPRINTF(RTW_DEBUG_XMIT_DESC, - ("%s: reg[TNPDA] <- %" PRIxPTR "\n", __func__, - (uintptr_t)RTW_RING_BASE(sc, hd_txmd))); - RTW_DPRINTF(RTW_DEBUG_XMIT_DESC, - ("%s: reg[THPDA] <- %" PRIxPTR "\n", __func__, - (uintptr_t)RTW_RING_BASE(sc, hd_txhi))); - RTW_DPRINTF(RTW_DEBUG_XMIT_DESC, - ("%s: reg[TBDA] <- %" PRIxPTR "\n", __func__, - (uintptr_t)RTW_RING_BASE(sc, hd_bcn))); + RTW_DPRINTF(RTW_DEBUG_RECV_DESC, ("%s: reg[RDSAR] <- %" PRIxPTR "\n", __func__, (uintptr_t)RTW_RING_BASE(sc, hd_rx))); + + RTW_SYNC(regs, RTW_TLPDA, RTW_RDSAR); + } static int @@ -1813,13 +1954,14 @@ rtw_swring_setup(struct rtw_softc *sc) rtw_rxdescs_sync(rdb, 0, rdb->rdb_ndesc, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); rtw_rxdesc_init_all(rdb, sc->sc_rxsoft, 1); + rdb->rdb_next = 0; rtw_txdescs_sync_all(&sc->sc_txdesc_blk[0]); return 0; } static void -rtw_txdesc_blk_reset(struct rtw_txdesc_blk *tdb) +rtw_txdesc_blk_init(struct rtw_txdesc_blk *tdb) { int i; @@ -1827,43 +1969,81 @@ rtw_txdesc_blk_reset(struct rtw_txdesc_blk *tdb) sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc); for (i = 0; i < tdb->tdb_ndesc; i++) tdb->tdb_desc[i].td_next = htole32(RTW_NEXT_DESC(tdb, i)); - tdb->tdb_nfree = tdb->tdb_ndesc; - tdb->tdb_next = 0; +} + +static u_int +rtw_txring_next(struct rtw_regs *regs, struct rtw_txdesc_blk *tdb) +{ + return (le32toh(RTW_READ(regs, tdb->tdb_basereg)) - tdb->tdb_base) / + sizeof(struct rtw_txdesc); +} + +static void +rtw_txring_fixup(struct rtw_softc *sc) +{ + int pri; + u_int next; + struct rtw_txdesc_blk *tdb; + struct rtw_regs *regs = &sc->sc_regs; + + for (pri = 0; pri < RTW_NTXPRI; pri++) { + tdb = &sc->sc_txdesc_blk[pri]; + next = rtw_txring_next(regs, tdb); + if (tdb->tdb_next == next) + continue; + printf("%s: tx-ring %d expected next %u, read %u\n", __func__, + pri, tdb->tdb_next, next); + tdb->tdb_next = next; + } +} + +static void +rtw_rxring_fixup(struct rtw_softc *sc) +{ + u_int next; + uint32_t rdsar; + struct rtw_rxdesc_blk *rdb; + + rdsar = le32toh(RTW_READ(&sc->sc_regs, RTW_RDSAR)); + next = (rdsar - RTW_RING_BASE(sc, hd_rx)) / sizeof(struct rtw_rxdesc); + + rdb = &sc->sc_rxdesc_blk; + if (rdb->rdb_next != next) { + printf("%s: rx-ring expected next %u, read %u\n", __func__, + rdb->rdb_next, next); + rdb->rdb_next = next; + } } static void rtw_txdescs_reset(struct rtw_softc *sc) { int pri; - struct rtw_txdesc_blk *tdb; for (pri = 0; pri < RTW_NTXPRI; pri++) { - tdb = &sc->sc_txdesc_blk[pri]; - rtw_txsofts_release(sc->sc_dmat, &sc->sc_ic, - &sc->sc_txsoft_blk[pri]); - rtw_txdesc_blk_reset(tdb); - rtw_txdescs_sync(tdb, 0, tdb->tdb_ndesc, - BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); + rtw_collect_txring(sc, &sc->sc_txsoft_blk[pri], + &sc->sc_txdesc_blk[pri], 1); } } -static void -rtw_rxdescs_reset(struct rtw_softc *sc) -{ - rtw_rxdesc_init_all(&sc->sc_rxdesc_blk, &sc->sc_rxsoft[0], 1); -} - static void rtw_intr_ioerror(struct rtw_softc *sc, uint16_t isr) { - struct ifnet *ifp = &sc->sc_if; + uint8_t cr = 0; + int xmtr = 0, rcvr = 0; struct rtw_regs *regs = &sc->sc_regs; - if ((isr & RTW_INTR_TXFOVW) != 0) + if ((isr & RTW_INTR_TXFOVW) != 0) { printf("%s: tx fifo overflow\n", sc->sc_dev.dv_xname); + xmtr = 1; + cr |= RTW_CR_TE; + } - if ((isr & (RTW_INTR_RDU|RTW_INTR_RXFOVW)) == 0) + if ((isr & (RTW_INTR_RDU|RTW_INTR_RXFOVW)) != 0) { + cr = RTW_CR_RE; + rcvr = 1; return; + } RTW_DPRINTF(RTW_DEBUG_BUGS, ("%s: restarting xmit/recv, isr %" PRIx16 "\n", sc->sc_dev.dv_xname, isr)); @@ -1872,23 +2052,27 @@ rtw_intr_ioerror(struct rtw_softc *sc, uint16_t isr) rtw_dump_rings(sc); #endif /* RTW_DEBUG */ - rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 0); + rtw_io_enable(regs, cr, 0); /* Collect rx'd packets. Refresh rx buffers. */ - rtw_intr_rx(sc, 0); - /* Collect tx'd packets. */ - rtw_intr_tx(sc, 0); + if (rcvr) + rtw_intr_rx(sc, 0); + /* Collect tx'd packets. XXX let's hope this stops the transmit + * timeouts. + */ + if (xmtr) + rtw_txdescs_reset(sc); RTW_WRITE16(regs, RTW_IMR, 0); RTW_SYNC(regs, RTW_IMR, RTW_IMR); - rtw_chip_reset1(regs, sc->sc_dev.dv_xname); - rtw_wep_setkeys(sc, sc->sc_ic.ic_nw_keys, sc->sc_ic.ic_def_txkey); + if (rtw_do_chip_reset) { + rtw_chip_reset1(regs, sc->sc_dev.dv_xname); + rtw_wep_setkeys(sc, sc->sc_ic.ic_nw_keys, + sc->sc_ic.ic_def_txkey); + } - rtw_rxdescs_reset(sc); - rtw_txdescs_reset(sc); - - rtw_hwring_setup(sc); + rtw_rxdesc_init_all(&sc->sc_rxdesc_blk, &sc->sc_rxsoft[0], 1); #ifdef RTW_DEBUG rtw_dump_rings(sc); @@ -1896,8 +2080,11 @@ rtw_intr_ioerror(struct rtw_softc *sc, uint16_t isr) RTW_WRITE16(regs, RTW_IMR, sc->sc_inten); RTW_SYNC(regs, RTW_IMR, RTW_IMR); - rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1); - ifp->if_flags &= ~IFF_OACTIVE; + if (rcvr) + rtw_rxring_fixup(sc); + rtw_io_enable(regs, cr, 1); + if (xmtr) + rtw_txring_fixup(sc); } static __inline void @@ -2497,19 +2684,6 @@ allmulti: return; } -#define IEEE80211_BEACON_TIMESTAMP_LEN 8 -#define IEEE80211_BEACON_BINTVL_LEN 2 -#define IEEE80211_BEACON_CAPINFO_LEN 2 -#define IEEE80211_TLV_SSID_LEN(__esslen) (2 + (__esslen)) -#define IEEE80211_TLV_SUPRATES_LEN(__nrates) (2 + (__nrates)) -#define IEEE80211_TLV_XSUPRATES_LEN(__nrates) (2 + (__nrates)) -#define IEEE80211_TLV_DSPARMS_LEN 3 -#define IEEE80211_TLV_IBSSPARMS 4 -#define IEEE80211_TLV_MIN_TIM 6 - -#define IEEE80211_TLV_ALLRATES_LEN(__nrates) \ - (((__nrates) > IEEE80211_RATE_SIZE) ? 4 + (__nrates) : 2 + (__nrates)) - static struct mbuf * rtw_beacon_alloc(struct rtw_softc *sc, struct ieee80211_node *ni) { @@ -2517,11 +2691,10 @@ rtw_beacon_alloc(struct rtw_softc *sc, struct ieee80211_node *ni) struct mbuf *m; struct ieee80211_beacon_offsets boff; - m = ieee80211_beacon_alloc(ic, ni, &boff); - - RTW_DPRINTF(RTW_DEBUG_BEACON, - ("%s: m %p len %u\n", __func__, m, m->m_len)); - + if ((m = ieee80211_beacon_alloc(ic, ni, &boff)) != NULL) { + RTW_DPRINTF(RTW_DEBUG_BEACON, + ("%s: m %p len %u\n", __func__, m, m->m_len)); + } return m; } @@ -2831,6 +3004,8 @@ rtw_txring_choose(struct rtw_softc *sc, struct rtw_txsoft_blk **tsbp, tdb = &sc->sc_txdesc_blk[pri]; if (SIMPLEQ_EMPTY(&tsb->tsb_freeq) || tdb->tdb_nfree == 0) { + if (tsb->tsb_tx_timer == 0) + tsb->tsb_tx_timer = 5; *tsbp = NULL; *tdbp = NULL; return -1; @@ -2850,7 +3025,10 @@ rtw_80211_dequeue(struct rtw_softc *sc, struct ifqueue *ifq, int pri, if (IF_IS_EMPTY(ifq)) return NULL; if (rtw_txring_choose(sc, tsbp, tdbp, pri) == -1) { + DPRINTF(sc, RTW_DEBUG_XMIT_RSRC, ("%s: no ring %d descriptor\n", + __func__, pri)); *if_flagsp |= IFF_OACTIVE; + sc->sc_if.if_timer = 1; return NULL; } IF_DEQUEUE(ifq, m); @@ -2913,8 +3091,10 @@ rtw_dequeue(struct ifnet *ifp, struct rtw_txsoft_blk **tsbp, pri = ((m0->m_flags & M_PWR_SAV) != 0) ? RTW_TXPRIHI : RTW_TXPRIMD; if (rtw_txring_choose(sc, tsbp, tdbp, pri) == -1) { - DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no descriptor\n", __func__)); + DPRINTF(sc, RTW_DEBUG_XMIT_RSRC, ("%s: no ring %d descriptor\n", + __func__, pri)); *if_flagsp |= IFF_OACTIVE; + sc->sc_if.if_timer = 1; return 0; } @@ -3014,7 +3194,6 @@ rtw_dmamap_load_txbuf(bus_dma_tag_t dmat, bus_dmamap_t dmam, struct mbuf *chain, return NULL; } else if (dmam->dm_nsegs > ndescfree) { printf("%s: too many tx segments\n", dvname); - *ifflagsp |= IFF_OACTIVE; bus_dmamap_unload(dmat, dmam); m_freem(m0); return NULL; @@ -3028,11 +3207,11 @@ rtw_print_txdesc(struct rtw_softc *sc, const char *action, struct rtw_txsoft *ts, struct rtw_txdesc_blk *tdb, int desc) { struct rtw_txdesc *td = &tdb->tdb_desc[desc]; - DPRINTF(sc, RTW_DEBUG_XMIT_DESC, ("%s: %p %s txdesc[%d] ctl0 %#08x " - "ctl1 %#08x buf %#08x len %#08x\n", + DPRINTF(sc, RTW_DEBUG_XMIT_DESC, ("%s: %p %s txdesc[%d] next %#08x " + "buf %#08x ctl0 %#08x ctl1 %#08x len %#08x\n", sc->sc_dev.dv_xname, ts, action, desc, - le32toh(td->td_ctl0), - le32toh(td->td_ctl1), le32toh(td->td_buf), + le32toh(td->td_buf), le32toh(td->td_next), + le32toh(td->td_ctl0), le32toh(td->td_ctl1), le32toh(td->td_len))); } #endif /* RTW_DEBUG */ @@ -3257,11 +3436,10 @@ rtw_start(struct ifnet *ifp) SIMPLEQ_REMOVE_HEAD(&tsb->tsb_freeq, ts_q); SIMPLEQ_INSERT_TAIL(&tsb->tsb_dirtyq, ts, ts_q); - if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN]) { + if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN]) sc->sc_led_state.ls_event |= RTW_LED_S_TX; - tsb->tsb_tx_timer = 5; - ifp->if_timer = 1; - } + tsb->tsb_tx_timer = 5; + ifp->if_timer = 1; tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL); tppoll &= ~RTW_TPPOLL_SALL; tppoll |= tsb->tsb_poll & RTW_TPPOLL_ALL; @@ -3279,10 +3457,26 @@ post_dequeue_err: return; } +static void +rtw_idle(struct rtw_regs *regs) +{ + int active; + + /* request stop DMA; wait for packets to stop transmitting. */ + + RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); + RTW_WBR(regs, RTW_TPPOLL, RTW_TPPOLL); + + for (active = 0; active < 300 && + (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ACTIVE) != 0; active++) + DELAY(10); + printf("%s: transmit DMA idle in %dus\n", __func__, active * 10); +} + static void rtw_watchdog(struct ifnet *ifp) { - int pri; + int pri, tx_timeouts = 0; struct rtw_softc *sc; struct rtw_txsoft_blk *tsb; @@ -3298,28 +3492,30 @@ rtw_watchdog(struct ifnet *ifp) if (tsb->tsb_tx_timer == 0) continue; - - if (--tsb->tsb_tx_timer == 0) { + else if (--tsb->tsb_tx_timer == 0) { if (SIMPLEQ_EMPTY(&tsb->tsb_dirtyq)) continue; printf("%s: transmit timeout, priority %d\n", ifp->if_xname, pri); ifp->if_oerrors++; - /* Stop Tx DMA, disable transmitter, clear - * Tx rings, and restart. - * - * TBD Stop/restart just the broken ring? - */ - RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL_SALL); - RTW_SYNC(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL); - rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 0); - rtw_txdescs_reset(sc); - rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 1); - ifp->if_flags &= ~IFF_OACTIVE; - rtw_start(ifp); + tx_timeouts++; } else ifp->if_timer = 1; } + + if (tx_timeouts > 0) { + /* Stop Tx DMA, disable xmtr, flush Tx rings, enable xmtr, + * reset s/w tx-ring pointers, and start transmission. + * + * TBD Stop/restart just the broken rings? + */ + rtw_idle(&sc->sc_regs); + rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 0); + rtw_txdescs_reset(sc); + rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 1); + rtw_txring_fixup(sc); + rtw_start(ifp); + } ieee80211_watchdog(&sc->sc_ic); return; } @@ -3340,7 +3536,7 @@ rtw_next_scan(void *arg) static void rtw_join_bss(struct rtw_softc *sc, uint8_t *bssid, uint16_t intval0) { - uint16_t bcnitv, intval; + uint16_t bcnitv, bintritv, intval; int i; struct rtw_regs *regs = &sc->sc_regs; @@ -3356,10 +3552,13 @@ rtw_join_bss(struct rtw_softc *sc, uint8_t *bssid, uint16_t intval0) bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK; bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK); RTW_WRITE16(regs, RTW_BCNITV, bcnitv); + /* interrupt host 1ms before the TBTT */ + bintritv = RTW_READ16(regs, RTW_BINTRITV) & ~RTW_BINTRITV_BINTRITV; + bintritv |= LSHIFT(1000, RTW_BINTRITV_BINTRITV); + RTW_WRITE16(regs, RTW_BINTRITV, bintritv); /* magic from Linux */ RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND)); RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV)); - rtw_set_access(regs, RTW_ACCESS_NONE); rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1); @@ -3371,7 +3570,6 @@ rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) { struct ifnet *ifp = ic->ic_ifp; struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc; - struct mbuf *m; enum ieee80211_state ostate; int error; @@ -3411,15 +3609,6 @@ rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) case IEEE80211_M_HOSTAP: case IEEE80211_M_IBSS: rtw_set_nettype(sc, IEEE80211_M_MONITOR); - m = rtw_beacon_alloc(sc, ic->ic_bss); - if (m == NULL) { - printf("%s: could not allocate beacon\n", - sc->sc_dev.dv_xname); - } else { - IF_ENQUEUE(&sc->sc_beaconq, m); - m->m_pkthdr.rcvif = - (void *)ieee80211_ref_node(ic->ic_bss); - } /*FALLTHROUGH*/ case IEEE80211_M_AHDEMO: case IEEE80211_M_STA: @@ -3439,12 +3628,6 @@ rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) if (nstate != IEEE80211_S_SCAN) callout_stop(&sc->sc_scan_ch); - /* Start beacon transmission. */ - if (nstate == IEEE80211_S_RUN && - (ic->ic_opmode == IEEE80211_M_HOSTAP || - ic->ic_opmode == IEEE80211_M_IBSS)) - rtw_start(ifp); - return (*sc->sc_mtbl.mt_newstate)(ic, nstate, arg); } @@ -3759,7 +3942,8 @@ rtw_txdesc_blk_setup(struct rtw_txdesc_blk *tdb, struct rtw_txdesc *desc, (void)memset(tdb->tdb_desc, 0, sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc); - rtw_txdesc_blk_reset(tdb); + rtw_txdesc_blk_init(tdb); + tdb->tdb_next = 0; } static void @@ -3856,6 +4040,9 @@ rtw_attach(struct rtw_softc *sc) struct rtw_txsoft_blk *tsb; int pri, rc; + rtw_cipher_wep = ieee80211_cipher_wep; + rtw_cipher_wep.ic_decap = rtw_wep_decap; + NEXT_ATTACH_STATE(sc, DETACHED); switch (RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK) { @@ -4002,8 +4189,7 @@ rtw_attach(struct rtw_softc *sc) ("%s: PHY delay %d\n", sc->sc_dev.dv_xname, sc->sc_phydelay)); if (sc->sc_locale == RTW_LOCALE_UNKNOWN) - rtw_identify_country(&sc->sc_regs, &sc->sc_locale, - sc->sc_dev.dv_xname); + rtw_identify_country(&sc->sc_regs, &sc->sc_locale); rtw_init_channels(sc->sc_locale, &sc->sc_ic.ic_channels, sc->sc_dev.dv_xname); diff --git a/sys/dev/ic/rtwreg.h b/sys/dev/ic/rtwreg.h index d57a51a58b63..7ee1e0b59bd7 100644 --- a/sys/dev/ic/rtwreg.h +++ b/sys/dev/ic/rtwreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtwreg.h,v 1.13 2005/02/27 00:27:02 perry Exp $ */ +/* $NetBSD: rtwreg.h,v 1.14 2005/11/23 04:12:33 dyoung Exp $ */ /*- * Copyright (c) 2004, 2005 David Young. All rights reserved. * @@ -195,7 +195,7 @@ #define RTW_INTR_TX (RTW_INTR_TLPDER|RTW_INTR_TLPDOK|RTW_INTR_THPDER|\ RTW_INTR_THPDOK|RTW_INTR_TNPDER|RTW_INTR_TNPDOK|\ RTW_INTR_TBDER|RTW_INTR_TBDOK) -#define RTW_INTR_BEACON (RTW_INTR_BCNINT) +#define RTW_INTR_BEACON (RTW_INTR_BCNINT|RTW_INTR_TBDER|RTW_INTR_TBDOK) #define RTW_INTR_IOERROR (RTW_INTR_TXFOVW|RTW_INTR_RXFOVW|RTW_INTR_RDU) #define RTW_TCR 0x40 /* Transmit Configuration Register, 32b */ @@ -779,6 +779,8 @@ /* Start all queues. */ #define RTW_TPPOLL_ALL (RTW_TPPOLL_BQ | RTW_TPPOLL_HPQ | \ RTW_TPPOLL_NPQ | RTW_TPPOLL_LPQ) +/* Check all queues' activity. */ +#define RTW_TPPOLL_ACTIVE RTW_TPPOLL_ALL /* Stop all queues. */ #define RTW_TPPOLL_SALL (RTW_TPPOLL_SBQ | RTW_TPPOLL_SHPQ | \ RTW_TPPOLL_SNPQ | RTW_TPPOLL_SLPQ) diff --git a/sys/dev/ic/rtwvar.h b/sys/dev/ic/rtwvar.h index 403bda44f056..7476eefb3307 100644 --- a/sys/dev/ic/rtwvar.h +++ b/sys/dev/ic/rtwvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtwvar.h,v 1.24 2005/06/27 05:49:13 dyoung Exp $ */ +/* $NetBSD: rtwvar.h,v 1.25 2005/11/23 04:12:33 dyoung Exp $ */ /*- * Copyright (c) 2004, 2005 David Young. All rights reserved. * @@ -37,31 +37,33 @@ #include #ifdef RTW_DEBUG -#define RTW_DEBUG_TUNE 0x000001 -#define RTW_DEBUG_PKTFILT 0x000002 -#define RTW_DEBUG_XMIT 0x000004 -#define RTW_DEBUG_XMIT_DESC 0x000008 -#define RTW_DEBUG_NODE 0x000010 -#define RTW_DEBUG_PWR 0x000020 -#define RTW_DEBUG_ATTACH 0x000040 -#define RTW_DEBUG_REGDUMP 0x000080 -#define RTW_DEBUG_ACCESS 0x000100 -#define RTW_DEBUG_RESET 0x000200 -#define RTW_DEBUG_INIT 0x000400 -#define RTW_DEBUG_IOSTATE 0x000800 -#define RTW_DEBUG_RECV 0x001000 -#define RTW_DEBUG_RECV_DESC 0x002000 -#define RTW_DEBUG_IO_KICK 0x004000 -#define RTW_DEBUG_INTR 0x008000 -#define RTW_DEBUG_PHY 0x010000 -#define RTW_DEBUG_PHYIO 0x020000 -#define RTW_DEBUG_PHYBITIO 0x040000 -#define RTW_DEBUG_TIMEOUT 0x080000 -#define RTW_DEBUG_BUGS 0x100000 -#define RTW_DEBUG_BEACON 0x200000 -#define RTW_DEBUG_LED 0x400000 -#define RTW_DEBUG_KEY 0x800000 -#define RTW_DEBUG_MAX 0xffffff +#define RTW_DEBUG_TUNE 0x0000001 +#define RTW_DEBUG_PKTFILT 0x0000002 +#define RTW_DEBUG_XMIT 0x0000004 +#define RTW_DEBUG_XMIT_DESC 0x0000008 +#define RTW_DEBUG_NODE 0x0000010 +#define RTW_DEBUG_PWR 0x0000020 +#define RTW_DEBUG_ATTACH 0x0000040 +#define RTW_DEBUG_REGDUMP 0x0000080 +#define RTW_DEBUG_ACCESS 0x0000100 +#define RTW_DEBUG_RESET 0x0000200 +#define RTW_DEBUG_INIT 0x0000400 +#define RTW_DEBUG_IOSTATE 0x0000800 +#define RTW_DEBUG_RECV 0x0001000 +#define RTW_DEBUG_RECV_DESC 0x0002000 +#define RTW_DEBUG_IO_KICK 0x0004000 +#define RTW_DEBUG_INTR 0x0008000 +#define RTW_DEBUG_PHY 0x0010000 +#define RTW_DEBUG_PHYIO 0x0020000 +#define RTW_DEBUG_PHYBITIO 0x0040000 +#define RTW_DEBUG_TIMEOUT 0x0080000 +#define RTW_DEBUG_BUGS 0x0100000 +#define RTW_DEBUG_BEACON 0x0200000 +#define RTW_DEBUG_LED 0x0400000 +#define RTW_DEBUG_KEY 0x0800000 +#define RTW_DEBUG_XMIT_RSRC 0x1000000 +#define RTW_DEBUG_OACTIVE 0x2000000 +#define RTW_DEBUG_MAX 0x3ffffff extern int rtw_debug; #define RTW_DPRINTF(__flags, __x) \ @@ -102,6 +104,8 @@ enum rtw_rfchipid { #define RTW_F_SLEEP 0x00000040 /* chip is asleep */ #define RTW_F_INVALID 0x00000080 /* chip is absent */ #define RTW_F_DK_VALID 0x00000100 /* keys in DK0-DK3 are valid */ +#define RTW_C_RXWEP_40 0x00000200 /* h/w decrypts 40-bit WEP */ +#define RTW_C_RXWEP_104 0x00000400 /* h/w decrypts 104-bit WEP */ /* all PHY flags */ #define RTW_F_ALLPHY (RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV) enum rtw_access {RTW_ACCESS_NONE = 0, @@ -158,7 +162,7 @@ struct rtw_txsoft { #define RTW_TXQLENLO 64 /* low-priority queue length */ #define RTW_TXQLENMD 64 /* medium-priority */ #define RTW_TXQLENHI 64 /* high-priority */ -#define RTW_TXQLENBCN 2 /* beacon */ +#define RTW_TXQLENBCN 8 /* beacon */ #define RTW_NTXDESCLO RTW_TXQLENLO #define RTW_NTXDESCMD RTW_TXQLENMD @@ -186,6 +190,8 @@ struct rtw_txdesc_blk { bus_dmamap_t tdb_dmamap; bus_addr_t tdb_physbase; bus_addr_t tdb_ofs; + bus_size_t tdb_basereg; + uint32_t tdb_base; struct rtw_txdesc *tdb_desc; };