summaryrefslogtreecommitdiffstats
path: root/sys/dev/gem/if_gem.c
diff options
context:
space:
mode:
authortmm <tmm@FreeBSD.org>2002-03-23 19:43:15 +0000
committertmm <tmm@FreeBSD.org>2002-03-23 19:43:15 +0000
commitb004f846650d2b4557c3bd674a96672a970f1b0b (patch)
tree73dce8b86a48d31813798ad37382811ddd497552 /sys/dev/gem/if_gem.c
parent67873bb7a8246bf8d6726b0912d5d7de275e340a (diff)
downloadFreeBSD-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/if_gem.c')
-rw-r--r--sys/dev/gem/if_gem.c22
1 files changed, 19 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;
}
OpenPOWER on IntegriCloud