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.
This commit is contained in:
parent
038148d678
commit
0d80b9bd88
@ -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;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,12 @@
|
||||
#define GEM_NRXDESC_MASK (GEM_NRXDESC - 1)
|
||||
#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
|
||||
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user