diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2006-10-24 19:20:02 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2006-10-24 19:20:02 +0000 |
commit | 2562ded1b50d5a3b821ecf8fc66178d378f3bf02 (patch) | |
tree | 6a1bf93e7cd9df202b5d7ccb161fef966731c3c8 /sys/dev/ic | |
parent | 10612891ccfa100a71738a827aadd5b135879edb (diff) |
Fix RX DMA handling; until now the card stopped receiving interrupts
after it went one time through the RX ring (256 descriptors). Also
reset RX rings correctly after ifconfig down / up.
"COMMIT IT!!!" claudio@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/malo.c | 42 | ||||
-rw-r--r-- | sys/dev/ic/malo.h | 5 |
2 files changed, 39 insertions, 8 deletions
diff --git a/sys/dev/ic/malo.c b/sys/dev/ic/malo.c index 13d5ceaf8d8..af4a86ad1f7 100644 --- a/sys/dev/ic/malo.c +++ b/sys/dev/ic/malo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: malo.c,v 1.9 2006/10/22 00:18:42 mglocker Exp $ */ +/* $OpenBSD: malo.c,v 1.10 2006/10/24 19:20:01 mglocker Exp $ */ /* * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> @@ -166,6 +166,7 @@ int malo_alloc_cmd(struct malo_softc *sc); void malo_free_cmd(struct malo_softc *sc); int malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring, int count); +void malo_reset_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring); void malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring); int malo_alloc_tx_ring(struct malo_softc *sc, struct malo_tx_ring *ring, int count); @@ -484,7 +485,7 @@ malo_alloc_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring, int count) goto fail; } - desc->reserved1 = htole16(1); + desc->status = htole16(1); desc->physdata = htole32(data->map->dm_segs->ds_addr); desc->physnext = htole32(ring->physaddr + (i + 1) % count * sizeof(struct malo_rx_desc)); @@ -500,6 +501,20 @@ fail: malo_free_rx_ring(sc, ring); } void +malo_reset_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring) +{ + int i; + + for (i = 0; i < ring->count; i++) + ring->desc[i].status = 0; + + bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize, + BUS_DMASYNC_PREWRITE); + + ring->cur = ring->next = 0; +} + +void malo_free_rx_ring(struct malo_softc *sc, struct malo_rx_ring *ring) { struct malo_rx_data *data; @@ -868,6 +883,10 @@ malo_get_spec(struct malo_softc *sc) malo_mem_write4(sc, letoh32(spec->WcbBase0) & 0xffff, htole32(sc->sc_txring.physaddr)); + /* save DMA RX pointers for later use */ + sc->sc_RxPdRdPtr = letoh32(spec->RxPdRdPtr) & 0xffff; + sc->sc_RxPdWrPtr = letoh32(spec->RxPdWrPtr) & 0xffff; + return (0); } @@ -963,6 +982,8 @@ malo_stop(struct malo_softc *sc) ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + malo_reset_rx_ring(sc, &sc->sc_rxring); + DPRINTF(("%s: malo_stop\n", ifp->if_xname)); if (sc->sc_disable) sc->sc_disable(sc); @@ -1013,9 +1034,13 @@ malo_rx_intr(struct malo_softc *sc) struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *mnew, *m; + uint32_t rxRdPtr, rxWrPtr; int error, i; - for (i = 0; i < MALO_RX_RING_COUNT; i++) { + rxRdPtr = malo_mem_read4(sc, sc->sc_RxPdRdPtr); + rxWrPtr = malo_mem_read4(sc, sc->sc_RxPdWrPtr); + + for (i = 0; i < MALO_RX_RING_COUNT && rxRdPtr != rxWrPtr; i++) { desc = &sc->sc_rxring.desc[sc->sc_rxring.cur]; data = &sc->sc_rxring.data[sc->sc_rxring.cur]; @@ -1026,10 +1051,10 @@ malo_rx_intr(struct malo_softc *sc) DPRINTF(("rx intr idx=%d, rxctrl=0x%02x, rssi=%d, " "status=0x%02x, channel=%d, len=%d, res1=%02x, rate=%d, " "physdata=0x%04x, physnext=0x%04x, qosctrl=%02x, res2=%d\n", - i, desc->rxctrl, desc->rssi, desc->status, desc->channel, - letoh16(desc->len), desc->reserved1, desc->datarate, - desc->physdata, desc->physnext, desc->qosctrl, - desc->reserved2)); + sc->sc_rxring.cur, desc->rxctrl, desc->rssi, desc->status, + desc->channel, letoh16(desc->len), desc->reserved1, + desc->datarate, desc->physdata, desc->physnext, + desc->qosctrl, desc->reserved2)); if ((letoh32(desc->rxctrl) & 0x80) == 0) break; @@ -1124,6 +1149,7 @@ malo_rx_intr(struct malo_softc *sc) skip: desc->rxctrl = 0; + rxRdPtr = desc->physnext; bus_dmamap_sync(sc->sc_dmat, sc->sc_rxring.map, sc->sc_rxring.cur * sizeof(struct malo_rx_desc), @@ -1132,4 +1158,6 @@ skip: sc->sc_rxring.cur = (sc->sc_rxring.cur + 1) % MALO_RX_RING_COUNT; } + + malo_mem_write4(sc, sc->sc_RxPdRdPtr, rxRdPtr); } diff --git a/sys/dev/ic/malo.h b/sys/dev/ic/malo.h index ee8ef343899..5bbea597e3e 100644 --- a/sys/dev/ic/malo.h +++ b/sys/dev/ic/malo.h @@ -1,4 +1,4 @@ -/* $OpenBSD: malo.h,v 1.5 2006/10/21 23:16:34 mglocker Exp $ */ +/* $OpenBSD: malo.h,v 1.6 2006/10/24 19:20:01 mglocker Exp $ */ /* * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> @@ -92,6 +92,9 @@ struct malo_softc { uint32_t *sc_cookie; bus_addr_t sc_cookie_dmaaddr; + uint32_t sc_RxPdWrPtr; + uint32_t sc_RxPdRdPtr; + int (*sc_newstate) (struct ieee80211com *, enum ieee80211_state, int); |