diff options
author | tmm <tmm@FreeBSD.org> | 2002-03-23 19:43:15 +0000 |
---|---|---|
committer | tmm <tmm@FreeBSD.org> | 2002-03-23 19:43:15 +0000 |
commit | b004f846650d2b4557c3bd674a96672a970f1b0b (patch) | |
tree | 73dce8b86a48d31813798ad37382811ddd497552 /sys/dev/gem | |
parent | 67873bb7a8246bf8d6726b0912d5d7de275e340a (diff) | |
download | FreeBSD-src-b004f846650d2b4557c3bd674a96672a970f1b0b.zip FreeBSD-src-b004f846650d2b4557c3bd674a96672a970f1b0b.tar.gz |
In some cases, RX descriptors that are signalled to have been completed
by the hardware are still marked as owned. Handle this by installing a
timeout handler to collect this descriptor to avoid having received
packets remain unhandled until the next one arrives.
Diffstat (limited to 'sys/dev/gem')
-rw-r--r-- | sys/dev/gem/if_gem.c | 22 | ||||
-rw-r--r-- | sys/dev/gem/if_gemvar.h | 7 |
2 files changed, 26 insertions, 3 deletions
diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c index 019dbbb..50d1814 100644 --- a/sys/dev/gem/if_gem.c +++ b/sys/dev/gem/if_gem.c @@ -90,6 +90,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 *); +static void gem_rint_timeout(void *); static void gem_tint(struct gem_softc *); #ifdef notyet static void gem_power(int, void *); @@ -299,6 +300,7 @@ gem_attach(sc) #endif callout_init(&sc->sc_tick_ch, 0); + callout_init(&sc->sc_rx_ch, 0); return (0); /* @@ -1392,6 +1394,14 @@ gem_tint(sc) gem_start(ifp); } +static void +gem_rint_timeout(arg) + void *arg; +{ + + gem_rint((struct gem_softc *)arg); +} + /* * Receive interrupt. */ @@ -1408,6 +1418,7 @@ gem_rint(sc) u_int64_t rxstat; int i, len; + callout_stop(&sc->sc_rx_ch); DPRINTF(sc, ("%s: gem_rint\n", device_get_name(sc->sc_dev))); CTR1(KTR_GEM, "%s: gem_rint", device_get_name(sc->sc_dev)); /* @@ -1427,11 +1438,16 @@ gem_rint(sc) rxstat = GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags); if (rxstat & GEM_RD_OWN) { - printf("gem_rint: completed descriptor " - "still owned %d\n", i); /* - * We have processed all of the receive buffers. + * The descriptor is still marked as owned, although + * it is supposed to have completed. This has been + * observed on some machines. Just exiting here + * might leave the packet sitting around until another + * one arrives to trigger a new interrupt, which is + * generally undesirable, so set up a timeout. */ + callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, + gem_rint_timeout, sc); break; } diff --git a/sys/dev/gem/if_gemvar.h b/sys/dev/gem/if_gemvar.h index 8abce88..9e6c7ee 100644 --- a/sys/dev/gem/if_gemvar.h +++ b/sys/dev/gem/if_gemvar.h @@ -60,6 +60,12 @@ #define GEM_NEXTRX(x) ((x + 1) & GEM_NRXDESC_MASK) /* + * How many ticks to wait until to retry on a RX descriptor that is still owned + * by the hardware. + */ +#define GEM_RXOWN_TICKS (hz / 50) + +/* * Control structures are DMA'd to the GEM chip. We allocate them in * a single clump that maps to a single DMA segment to make several things * easier. @@ -132,6 +138,7 @@ struct gem_softc { struct mii_data *sc_mii; /* MII media control */ device_t sc_dev; /* generic device information */ struct callout sc_tick_ch; /* tick callout */ + struct callout sc_rx_ch; /* delayed rx callout */ /* The following bus handles are to be provided by the bus front-end */ bus_space_tag_t sc_bustag; /* bus tag */ |