summaryrefslogtreecommitdiffstats
path: root/sys/dev/gem
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2006-12-06 02:04:25 +0000
committermarius <marius@FreeBSD.org>2006-12-06 02:04:25 +0000
commit4298c9bcb6ea4ab94650afd06fc11a7143dca6e4 (patch)
tree0cfe6b81c966756a4cedd0c79e1407dd60c06f17 /sys/dev/gem
parentd073ded5d056dae30e2a0a2215ecd11334211c21 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/dev/gem/if_gem.c46
-rw-r--r--sys/dev/gem/if_gemvar.h1
2 files changed, 25 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);
}
/*
diff --git a/sys/dev/gem/if_gemvar.h b/sys/dev/gem/if_gemvar.h
index abfe327..28ac061 100644
--- a/sys/dev/gem/if_gemvar.h
+++ b/sys/dev/gem/if_gemvar.h
@@ -130,6 +130,7 @@ struct gem_softc {
u_char sc_enaddr[6];
struct callout sc_tick_ch; /* tick callout */
struct callout sc_rx_ch; /* delayed rx callout */
+ int sc_wdog_timer; /* watchdog timer */
/* The following bus handles are to be provided by the bus front-end */
bus_space_tag_t sc_bustag; /* bus tag */
OpenPOWER on IntegriCloud