diff options
author | marius <marius@FreeBSD.org> | 2006-12-06 02:04:25 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2006-12-06 02:04:25 +0000 |
commit | 4298c9bcb6ea4ab94650afd06fc11a7143dca6e4 (patch) | |
tree | 0cfe6b81c966756a4cedd0c79e1407dd60c06f17 /sys/dev/gem/if_gem.c | |
parent | d073ded5d056dae30e2a0a2215ecd11334211c21 (diff) | |
download | FreeBSD-src-4298c9bcb6ea4ab94650afd06fc11a7143dca6e4.zip FreeBSD-src-4298c9bcb6ea4ab94650afd06fc11a7143dca6e4.tar.gz |
- Use the gem_tick() callout instead of if_slowtimo() for driving
gem_watchdog() in order to avoid races accessing if_timer.
While at it relax the watchdog a bit by reloading it in gem_tint()
if there are still packets enqueued.
- Don't bother to set if_mtu to ETHERMTU, ether_ifattach() does that.
- Fix inconsistencies in prototypes.
Diffstat (limited to 'sys/dev/gem/if_gem.c')
-rw-r--r-- | sys/dev/gem/if_gem.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c index ed9fd56..507825a 100644 --- a/sys/dev/gem/if_gem.c +++ b/sys/dev/gem/if_gem.c @@ -83,16 +83,16 @@ static void gem_cddma_callback(void *, bus_dma_segment_t *, int, int); static void gem_txdma_callback(void *, bus_dma_segment_t *, int, bus_size_t, int); static void gem_tick(void *); -static void gem_watchdog(struct ifnet *); +static int gem_watchdog(struct gem_softc *); static void gem_init(void *); -static void gem_init_locked(struct gem_softc *sc); -static void gem_init_regs(struct gem_softc *sc); +static void gem_init_locked(struct gem_softc *); +static void gem_init_regs(struct gem_softc *); static int gem_ringsize(int sz); static int gem_meminit(struct gem_softc *); static int gem_load_txmbuf(struct gem_softc *, struct mbuf *); static void gem_mifinit(struct gem_softc *); -static int gem_bitwait(struct gem_softc *sc, bus_addr_t r, - u_int32_t clr, u_int32_t set); +static int gem_bitwait(struct gem_softc *, bus_addr_t, u_int32_t, + u_int32_t); static int gem_reset_rx(struct gem_softc *); static int gem_reset_tx(struct gem_softc *); static int gem_disable_rx(struct gem_softc *); @@ -268,11 +268,9 @@ gem_attach(sc) ifp->if_softc = sc; if_initname(ifp, device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev)); - ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = gem_start; ifp->if_ioctl = gem_ioctl; - ifp->if_watchdog = gem_watchdog; ifp->if_init = gem_init; ifp->if_snd.ifq_maxlen = GEM_TXQUEUELEN; /* @@ -544,6 +542,9 @@ gem_tick(arg) GEM_LOCK_ASSERT(sc, MA_OWNED); mii_tick(sc->sc_mii); + if (gem_watchdog(sc) == EJUSTRETURN) + return; + callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); } @@ -657,7 +658,7 @@ gem_stop(ifp, disable) * Mark the interface down and cancel the watchdog timer. */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - ifp->if_timer = 0; + sc->sc_wdog_timer = 0; } /* @@ -982,11 +983,11 @@ gem_init_locked(sc) bus_space_write_4(t, h, GEM_RX_KICK, GEM_NRXDESC-4); /* Start the one second timer. */ + sc->sc_wdog_timer = 0; callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_timer = 0; sc->sc_ifflags = ifp->if_flags; } @@ -1223,10 +1224,10 @@ gem_start_locked(ifp) #endif /* Set a watchdog timer in case the chip flakes out. */ - ifp->if_timer = 5; + sc->sc_wdog_timer = 5; #ifdef GEM_DEBUG CTR2(KTR_GEM, "%s: gem_start: watchdog %d", - device_get_name(sc->sc_dev), ifp->if_timer); + device_get_name(sc->sc_dev), sc->sc_wdog_timer); #endif } } @@ -1355,13 +1356,12 @@ gem_tint(sc) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; gem_start_locked(ifp); - if (STAILQ_EMPTY(&sc->sc_txdirtyq)) - ifp->if_timer = 0; + sc->sc_wdog_timer = STAILQ_EMPTY(&sc->sc_txdirtyq) ? 0 : 5; } #ifdef GEM_DEBUG CTR2(KTR_GEM, "%s: gem_tint: watchdog %d", - device_get_name(sc->sc_dev), ifp->if_timer); + device_get_name(sc->sc_dev), sc->sc_wdog_timer); #endif } @@ -1616,14 +1616,13 @@ gem_intr(v) GEM_UNLOCK(sc); } - -static void -gem_watchdog(ifp) - struct ifnet *ifp; +static int +gem_watchdog(sc) + struct gem_softc *sc; { - struct gem_softc *sc = ifp->if_softc; - GEM_LOCK(sc); + GEM_LOCK_ASSERT(sc, MA_OWNED); + #ifdef GEM_DEBUG CTR3(KTR_GEM, "gem_watchdog: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x " "GEM_MAC_RX_CONFIG %x", @@ -1637,12 +1636,15 @@ gem_watchdog(ifp) bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_TX_CONFIG)); #endif + if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) + return (0); + device_printf(sc->sc_dev, "device timeout\n"); - ++ifp->if_oerrors; + ++sc->sc_ifp->if_oerrors; /* Try to get more packets going. */ gem_init_locked(sc); - GEM_UNLOCK(sc); + return (EJUSTRETURN); } /* |