Use our own callout instead of if_slowtimo() for driving lance_watchdog()

in order to avoid races accessing if_timer.
This commit is contained in:
marius 2006-12-06 02:14:31 +00:00
parent d6685ecfb2
commit a1536822a0
4 changed files with 25 additions and 12 deletions

View File

@ -385,7 +385,7 @@ am7990_tint(struct lance_softc *sc)
sc->sc_first_td = bix;
ifp->if_timer = sc->sc_no_td > 0 ? 5 : 0;
sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0;
}
/*
@ -575,7 +575,7 @@ am7990_start_locked(struct lance_softc *sc)
sc->sc_last_td = bix;
if (enq > 0)
ifp->if_timer = 5;
sc->sc_wdog_timer = 5;
}
#ifdef LEDEBUG

View File

@ -423,7 +423,7 @@ am79900_tint(struct lance_softc *sc)
sc->sc_first_td = bix;
ifp->if_timer = sc->sc_no_td > 0 ? 5 : 0;
sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0;
}
/*
@ -614,7 +614,7 @@ am79900_start_locked(struct lance_softc *sc)
sc->sc_last_td = bix;
if (enq > 0)
ifp->if_timer = 5;
sc->sc_wdog_timer = 5;
}
#ifdef LEDEBUG

View File

@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/socket.h>
@ -101,7 +102,7 @@ devclass_t le_devclass;
static void lance_start(struct ifnet *);
static void lance_stop(struct lance_softc *);
static void lance_init(void *);
static void lance_watchdog(struct ifnet *);
static void lance_watchdog(void *s);
static int lance_mediachange(struct ifnet *);
static void lance_mediastatus(struct ifnet *, struct ifmediareq *);
static int lance_ioctl(struct ifnet *, u_long, caddr_t);
@ -119,12 +120,13 @@ lance_config(struct lance_softc *sc, const char* name, int unit)
if (ifp == NULL)
return (ENOSPC);
callout_init_mtx(&sc->sc_wdog_ch, &sc->sc_mtx, 0);
/* Initialize ifnet structure. */
ifp->if_softc = sc;
if_initname(ifp, name, unit);
ifp->if_start = lance_start;
ifp->if_ioctl = lance_ioctl;
ifp->if_watchdog = lance_watchdog;
ifp->if_init = lance_init;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
#ifdef LANCE_REVC_BUG
@ -213,6 +215,7 @@ lance_detach(struct lance_softc *sc)
LE_LOCK(sc);
lance_stop(sc);
LE_UNLOCK(sc);
callout_drain(&sc->sc_wdog_ch);
ether_ifdetach(ifp);
if_free(ifp);
}
@ -257,7 +260,8 @@ lance_stop(struct lance_softc *sc)
* Mark the interface down and cancel the watchdog timer.
*/
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
ifp->if_timer = 0;
callout_stop(&sc->sc_wdog_ch);
sc->sc_wdog_timer = 0;
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
}
@ -327,7 +331,8 @@ lance_init_locked(struct lance_softc *sc)
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_timer = 0;
sc->sc_wdog_timer = 0;
callout_reset(&sc->sc_wdog_ch, hz, lance_watchdog, sc);
(*sc->sc_start_locked)(sc);
} else
if_printf(ifp, "controller failed to initialize\n");
@ -434,15 +439,21 @@ lance_get(struct lance_softc *sc, int boff, int totlen)
}
static void
lance_watchdog(struct ifnet *ifp)
lance_watchdog(void *xsc)
{
struct lance_softc *sc = ifp->if_softc;
struct lance_softc *sc = (struct lance_softc *)xsc;
struct ifnet *ifp = sc->sc_ifp;
LE_LOCK_ASSERT(sc, MA_OWNED);
if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) {
callout_reset(&sc->sc_wdog_ch, hz, lance_watchdog, sc);
return;
}
LE_LOCK(sc);
if_printf(ifp, "device timeout\n");
++ifp->if_oerrors;
lance_init_locked(sc);
LE_UNLOCK(sc);
}
static int

View File

@ -48,6 +48,8 @@ struct lance_softc {
struct ifnet *sc_ifp;
struct ifmedia sc_media;
struct mtx sc_mtx;
struct callout sc_wdog_ch;
int sc_wdog_timer;
/*
* Memory functions: