summaryrefslogtreecommitdiffstats
path: root/sys/dev/vx
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/vx
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/vx')
-rw-r--r--sys/dev/vx/if_vx.c33
-rw-r--r--sys/dev/vx/if_vxvar.h2
2 files changed, 22 insertions, 13 deletions
diff --git a/sys/dev/vx/if_vx.c b/sys/dev/vx/if_vx.c
index c810c71..0dea9bf 100644
--- a/sys/dev/vx/if_vx.c
+++ b/sys/dev/vx/if_vx.c
@@ -129,7 +129,7 @@ static void vx_init_locked(struct vx_softc *);
static int vx_ioctl(struct ifnet *, u_long, caddr_t);
static void vx_start(struct ifnet *);
static void vx_start_locked(struct ifnet *);
-static void vx_watchdog(struct ifnet *);
+static void vx_watchdog(void *);
static void vx_reset(struct vx_softc *);
static void vx_read(struct vx_softc *);
static struct mbuf *vx_get(struct vx_softc *, u_int);
@@ -157,6 +157,7 @@ vx_attach(device_t dev)
mtx_init(&sc->vx_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
callout_init_mtx(&sc->vx_callout, &sc->vx_mtx, 0);
+ callout_init_mtx(&sc->vx_watchdog, &sc->vx_mtx, 0);
GO_WINDOW(0);
CSR_WRITE_2(sc, VX_COMMAND, GLOBAL_RESET);
VX_BUSY_WAIT;
@@ -193,7 +194,6 @@ vx_attach(device_t dev)
ifp->if_start = vx_start;
ifp->if_ioctl = vx_ioctl;
ifp->if_init = vx_init;
- ifp->if_watchdog = vx_watchdog;
ifp->if_softc = sc;
ether_ifattach(ifp, eaddr);
@@ -269,6 +269,7 @@ vx_init_locked(struct vx_softc *sc)
/* Interface is now `running', with no output active. */
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ callout_reset(&sc->vx_watchdog, hz, vx_watchdog, sc);
/* Attempt to start output, if any. */
vx_start_locked(ifp);
@@ -474,7 +475,7 @@ startagain:
/* not enough room in FIFO - make sure */
if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- ifp->if_timer = 1;
+ sc->vx_timer = 1;
return;
}
}
@@ -513,7 +514,7 @@ startagain:
CSR_WRITE_1(sc, VX_W1_TX_PIO_WR_1, 0); /* Padding */
++ifp->if_opackets;
- ifp->if_timer = 1;
+ sc->vx_timer = 1;
readcheck:
if ((CSR_READ_2(sc, VX_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
@@ -661,18 +662,18 @@ vx_intr(void *voidsc)
if (status & S_RX_COMPLETE)
vx_read(sc);
if (status & S_TX_AVAIL) {
- ifp->if_timer = 0;
+ sc->vx_timer = 0;
sc->vx_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
vx_start_locked(sc->vx_ifp);
}
if (status & S_CARD_FAILURE) {
if_printf(ifp, "adapter failure (%x)\n", status);
- ifp->if_timer = 0;
+ sc->vx_timer = 0;
vx_reset(sc);
break;
}
if (status & S_TX_COMPLETE) {
- ifp->if_timer = 0;
+ sc->vx_timer = 0;
vx_txstat(sc);
vx_start_locked(ifp);
}
@@ -970,26 +971,32 @@ vx_reset(struct vx_softc *sc)
}
static void
-vx_watchdog(struct ifnet *ifp)
+vx_watchdog(void *arg)
{
- struct vx_softc *sc = ifp->if_softc;
+ struct vx_softc *sc;
+ struct ifnet *ifp;
- VX_LOCK(sc);
+ sc = arg;
+ VX_LOCK_ASSERT(sc);
+ callout_reset(&sc->vx_watchdog, hz, vx_watchdog, sc);
+ if (sc->vx_timer == 0 || --sc->vx_timer > 0)
+ return;
+
+ ifp = sc->vx_ifp;
if (ifp->if_flags & IFF_DEBUG)
if_printf(ifp, "device timeout\n");
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
vx_start_locked(ifp);
vx_intr(sc);
- VX_UNLOCK(sc);
}
void
vx_stop(struct vx_softc *sc)
{
- struct ifnet *ifp = sc->vx_ifp;
VX_LOCK_ASSERT(sc);
- ifp->if_timer = 0;
+ sc->vx_timer = 0;
+ callout_stop(&sc->vx_watchdog);
CSR_WRITE_2(sc, VX_COMMAND, RX_DISABLE);
CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK);
diff --git a/sys/dev/vx/if_vxvar.h b/sys/dev/vx/if_vxvar.h
index ec20a3f..8c312e2 100644
--- a/sys/dev/vx/if_vxvar.h
+++ b/sys/dev/vx/if_vxvar.h
@@ -51,8 +51,10 @@ struct vx_softc {
int vx_tx_succ_ok; /* # packets sent in sequence */
/* w/o underrun */
struct callout vx_callout; /* Callout for timeouts */
+ struct callout vx_watchdog;
struct mtx vx_mtx;
int vx_buffill_pending;
+ int vx_timer;
};
#define CSR_WRITE_4(sc, reg, val) \
OpenPOWER on IntegriCloud