summaryrefslogtreecommitdiffstats
path: root/sys/dev/ti
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-11-19 22:06:40 +0000
committerjhb <jhb@FreeBSD.org>2009-11-19 22:06:40 +0000
commitaffabaa85e18565f9c0a68b33c5b0f2e0587f05a (patch)
tree8407585eec2a1c0c6cadd011a7eb682949649bde /sys/dev/ti
parentd49024b6f48c6368a3af0f695133bdc2a695e281 (diff)
downloadFreeBSD-src-affabaa85e18565f9c0a68b33c5b0f2e0587f05a.zip
FreeBSD-src-affabaa85e18565f9c0a68b33c5b0f2e0587f05a.tar.gz
- Add a private timer to drive the transmit watchdog instead of using
if_watchdog and if_timer. - Fix some issues in detach for sn(4), ste(4), and ti(4). Primarily this means calling ether_ifdetach() before anything else.
Diffstat (limited to 'sys/dev/ti')
-rw-r--r--sys/dev/ti/if_ti.c43
-rw-r--r--sys/dev/ti/if_tireg.h2
2 files changed, 24 insertions, 21 deletions
diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c
index 488d038..20130bc 100644
--- a/sys/dev/ti/if_ti.c
+++ b/sys/dev/ti/if_ti.c
@@ -194,7 +194,7 @@ static void ti_init(void *);
static void ti_init_locked(void *);
static void ti_init2(struct ti_softc *);
static void ti_stop(struct ti_softc *);
-static void ti_watchdog(struct ifnet *);
+static void ti_watchdog(void *);
static int ti_shutdown(device_t);
static int ti_ifmedia_upd(struct ifnet *);
static void ti_ifmedia_sts(struct ifnet *, struct ifmediareq *);
@@ -2285,6 +2285,7 @@ ti_attach(dev)
mtx_init(&sc->ti_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
+ callout_init_mtx(&sc->ti_watchdog, &sc->ti_mtx, 0);
ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts);
ifp = sc->ti_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
@@ -2486,7 +2487,6 @@ ti_attach(dev)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = ti_ioctl;
ifp->if_start = ti_start;
- ifp->if_watchdog = ti_watchdog;
ifp->if_init = ti_init;
ifp->if_baudrate = 1000000000;
ifp->if_mtu = ETHERMTU;
@@ -2565,24 +2565,22 @@ ti_detach(dev)
{
struct ti_softc *sc;
struct ifnet *ifp;
- int attached;
sc = device_get_softc(dev);
if (sc->dev)
destroy_dev(sc->dev);
KASSERT(mtx_initialized(&sc->ti_mtx), ("ti mutex not initialized"));
- attached = device_is_attached(dev);
- TI_LOCK(sc);
ifp = sc->ti_ifp;
- if (attached)
- ti_stop(sc);
- TI_UNLOCK(sc);
- if (attached)
+ if (device_is_attached(dev)) {
ether_ifdetach(ifp);
+ TI_LOCK(sc);
+ ti_stop(sc);
+ TI_UNLOCK(sc);
+ }
/* These should only be active if attach succeeded */
- if (attached)
- bus_generic_detach(dev);
+ callout_drain(&sc->ti_watchdog);
+ bus_generic_detach(dev);
ti_free_dmamaps(sc);
ifmedia_removeall(&sc->ifmedia);
@@ -2866,7 +2864,7 @@ ti_txeof(sc)
}
sc->ti_tx_saved_considx = idx;
- ifp->if_timer = sc->ti_txcnt > 0 ? 5 : 0;
+ sc->ti_timer = sc->ti_txcnt > 0 ? 5 : 0;
}
static void
@@ -3121,7 +3119,7 @@ ti_start_locked(ifp)
/*
* Set a timeout in case the chip goes out to lunch.
*/
- ifp->if_timer = 5;
+ sc->ti_timer = 5;
}
}
@@ -3225,6 +3223,7 @@ static void ti_init2(sc)
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc);
/*
* Make sure to set media properly. We have to do this
@@ -3786,30 +3785,31 @@ ti_ioctl2(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
}
static void
-ti_watchdog(ifp)
- struct ifnet *ifp;
+ti_watchdog(void *arg)
{
struct ti_softc *sc;
+ struct ifnet *ifp;
- sc = ifp->if_softc;
- TI_LOCK(sc);
+ sc = arg;
+ TI_LOCK_ASSERT(sc);
+ callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc);
+ if (sc->ti_timer == 0 || --sc->ti_timer > 0)
+ return;
/*
* When we're debugging, the chip is often stopped for long periods
* of time, and that would normally cause the watchdog timer to fire.
* Since that impedes debugging, we don't want to do that.
*/
- if (sc->ti_flags & TI_FLAG_DEBUGING) {
- TI_UNLOCK(sc);
+ if (sc->ti_flags & TI_FLAG_DEBUGING)
return;
- }
+ ifp = sc->ti_ifp;
if_printf(ifp, "watchdog timeout -- resetting\n");
ti_stop(sc);
ti_init_locked(sc);
ifp->if_oerrors++;
- TI_UNLOCK(sc);
}
/*
@@ -3859,6 +3859,7 @@ ti_stop(sc)
sc->ti_tx_saved_considx = TI_TXCONS_UNSET;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ callout_stop(&sc->ti_watchdog);
}
/*
diff --git a/sys/dev/ti/if_tireg.h b/sys/dev/ti/if_tireg.h
index 5f0bda9..070a70a 100644
--- a/sys/dev/ti/if_tireg.h
+++ b/sys/dev/ti/if_tireg.h
@@ -1038,6 +1038,8 @@ struct ti_softc {
int ti_if_flags;
int ti_txcnt;
struct mtx ti_mtx;
+ struct callout ti_watchdog;
+ int ti_timer;
ti_flag_vals ti_flags;
struct cdev *dev;
};
OpenPOWER on IntegriCloud