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:
parent
d6685ecfb2
commit
a1536822a0
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user