summaryrefslogtreecommitdiffstats
path: root/sys/dev/gem
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2005-07-24 18:12:31 +0000
committermarius <marius@FreeBSD.org>2005-07-24 18:12:31 +0000
commitf27e33d478ee07f3237b03a73be0637bf6d08320 (patch)
treeb722e32933e89f24478206373346ca0eb4df7745 /sys/dev/gem
parent570ffe8009f1ffd621a89fd406cd07ff51a6f5ab (diff)
downloadFreeBSD-src-f27e33d478ee07f3237b03a73be0637bf6d08320.zip
FreeBSD-src-f27e33d478ee07f3237b03a73be0637bf6d08320.tar.gz
- Wrap the handler and associated code for collecting completed RX
descriptors that are still marked owned in #ifdef GEM_RINT_TIMEOUT instead of #if 0 for convenience. - Remove stale code and comment about relying on the preset XIF config. - In case of a watchdog timeout call the init function instead of just the start function so the chip is properly reset. Merge from hme(4): - Convert to use bus_dmamap_load_mbuf_sg() for loading RX buffers. - Protect from a duplicate mbuf free panic in case the DMA engine hangs. Reviewed by: yongari Tested on: powerpc(grehan), sparc64 MFC after: 1 week
Diffstat (limited to 'sys/dev/gem')
-rw-r--r--sys/dev/gem/if_gem.c54
1 files changed, 23 insertions, 31 deletions
diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c
index 80db1ce..e996fd8 100644
--- a/sys/dev/gem/if_gem.c
+++ b/sys/dev/gem/if_gem.c
@@ -38,6 +38,10 @@ __FBSDID("$FreeBSD$");
#define GEM_DEBUG
#endif
+#if 0 /* XXX: In case of emergency, re-enable this. */
+#define GEM_RINT_TIMEOUT
+#endif
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -72,8 +76,6 @@ static void gem_start(struct ifnet *);
static void gem_stop(struct ifnet *, int);
static int gem_ioctl(struct ifnet *, u_long, caddr_t);
static void gem_cddma_callback(void *, bus_dma_segment_t *, int, int);
-static void gem_rxdma_callback(void *, bus_dma_segment_t *, int,
- bus_size_t, int);
static void gem_txdma_callback(void *, bus_dma_segment_t *, int,
bus_size_t, int);
static void gem_tick(void *);
@@ -97,7 +99,7 @@ static void gem_setladrf(struct gem_softc *);
struct mbuf *gem_get(struct gem_softc *, int, int);
static void gem_eint(struct gem_softc *, u_int);
static void gem_rint(struct gem_softc *);
-#if 0
+#ifdef GEM_RINT_TIMEOUT
static void gem_rint_timeout(void *);
#endif
static void gem_tint(struct gem_softc *);
@@ -224,7 +226,6 @@ gem_attach(sc)
sc->sc_rxsoft[i].rxs_mbuf = NULL;
}
-
gem_mifinit(sc);
if ((error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, gem_mediachange,
@@ -320,7 +321,9 @@ gem_attach(sc)
#endif
callout_init(&sc->sc_tick_ch, 0);
+#ifdef GEM_RINT_TIMEOUT
callout_init(&sc->sc_rx_ch, 0);
+#endif
return (0);
/*
@@ -427,22 +430,6 @@ gem_cddma_callback(xsc, segs, nsegs, error)
}
static void
-gem_rxdma_callback(xsc, segs, nsegs, totsz, error)
- void *xsc;
- bus_dma_segment_t *segs;
- int nsegs;
- bus_size_t totsz;
- int error;
-{
- struct gem_rxsoft *rxs = (struct gem_rxsoft *)xsc;
-
- if (error != 0)
- return;
- KASSERT(nsegs == 1, ("gem_rxdma_callback: bad dma segment count"));
- rxs->rxs_paddr = segs[0].ds_addr;
-}
-
-static void
gem_txdma_callback(xsc, segs, nsegs, totsz, error)
void *xsc;
bus_dma_segment_t *segs;
@@ -986,7 +973,6 @@ gem_load_txmbuf(sc, m0)
}
txd.txd_sc = sc;
txd.txd_txs = txs;
- txs->txs_mbuf = m0;
txs->txs_firstdesc = sc->sc_txnext;
error = bus_dmamap_load_mbuf(sc->sc_tdmatag, txs->txs_dmamap, m0,
gem_txdma_callback, &txd, BUS_DMA_NOWAIT);
@@ -1008,6 +994,7 @@ gem_load_txmbuf(sc, m0)
#endif
STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q);
STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
+ txs->txs_mbuf = m0;
sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc);
sc->sc_txfree -= txs->txs_ndescs;
@@ -1333,7 +1320,7 @@ gem_tint(sc)
#endif
}
-#if 0
+#ifdef GEM_RINT_TIMEOUT
static void
gem_rint_timeout(arg)
void *arg;
@@ -1359,7 +1346,9 @@ gem_rint(sc)
u_int32_t rxcomp;
int i, len, progress = 0;
+#ifdef GEM_RINT_TIMEOUT
callout_stop(&sc->sc_rx_ch);
+#endif
#ifdef GEM_DEBUG
CTR1(KTR_GEM, "%s: gem_rint", device_get_name(sc->sc_dev));
#endif
@@ -1382,7 +1371,7 @@ gem_rint(sc)
rxstat = GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags);
if (rxstat & GEM_RD_OWN) {
-#if 0 /* XXX: In case of emergency, re-enable this. */
+#ifdef GEM_RINT_TIMEOUT
/*
* The descriptor is still marked as owned, although
* it is supposed to have completed. This has been
@@ -1472,7 +1461,8 @@ gem_add_rxbuf(sc, idx)
{
struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx];
struct mbuf *m;
- int error;
+ bus_dma_segment_t segs[1];
+ int error, nsegs;
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
if (m == NULL)
@@ -1492,13 +1482,17 @@ gem_add_rxbuf(sc, idx)
rxs->rxs_mbuf = m;
- error = bus_dmamap_load_mbuf(sc->sc_rdmatag, rxs->rxs_dmamap,
- m, gem_rxdma_callback, rxs, BUS_DMA_NOWAIT);
- if (error != 0 || rxs->rxs_paddr == 0) {
+ error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap,
+ m, segs, &nsegs, BUS_DMA_NOWAIT);
+ /* If nsegs is wrong then the stack is corrupt. */
+ KASSERT(nsegs == 1, ("Too many segments returned!"));
+ if (error != 0) {
device_printf(sc->sc_dev, "can't load rx DMA map %d, error = "
"%d\n", idx, error);
- panic("gem_add_rxbuf"); /* XXX */
+ m_freem(m);
+ return (ENOBUFS);
}
+ rxs->rxs_paddr = segs[0].ds_addr;
bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, BUS_DMASYNC_PREREAD);
@@ -1591,7 +1585,7 @@ gem_watchdog(ifp)
++ifp->if_oerrors;
/* Try to get more packets going. */
- gem_start(ifp);
+ gem_init(ifp);
}
/*
@@ -1738,8 +1732,6 @@ gem_mii_statchg(dev)
bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, v);
/* XIF Configuration */
- /* We should really calculate all this rather than rely on defaults */
- v = bus_space_read_4(t, mac, GEM_MAC_XIF_CONFIG);
v = GEM_MAC_XIF_LINK_LED;
v |= GEM_MAC_XIF_TX_MII_ENA;
OpenPOWER on IntegriCloud