summaryrefslogtreecommitdiffstats
path: root/sys/mips/adm5120
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-11-24 18:34:47 +0000
committerjhb <jhb@FreeBSD.org>2009-11-24 18:34:47 +0000
commitbb91b31a51b4a785508c09cb5b0a6ab634f47a7b (patch)
treeb2d97b1f582c47482e45e201249e684b9a522a17 /sys/mips/adm5120
parenta25c3915deae5a8049a07aa2ddd20c29b98b6a7e (diff)
downloadFreeBSD-src-bb91b31a51b4a785508c09cb5b0a6ab634f47a7b.zip
FreeBSD-src-bb91b31a51b4a785508c09cb5b0a6ab634f47a7b.tar.gz
Use a single private timer to drive the transmit watchdog rather than using
if_watchdog and if_timer from the first port. Reviewed by: gonzo
Diffstat (limited to 'sys/mips/adm5120')
-rw-r--r--sys/mips/adm5120/if_admsw.c33
-rw-r--r--sys/mips/adm5120/if_admswvar.h4
2 files changed, 24 insertions, 13 deletions
diff --git a/sys/mips/adm5120/if_admsw.c b/sys/mips/adm5120/if_admsw.c
index fff8930..91864c4 100644
--- a/sys/mips/adm5120/if_admsw.c
+++ b/sys/mips/adm5120/if_admsw.c
@@ -128,7 +128,7 @@ static uint8_t vlan_matrix[SW_DEVS] = {
/* ifnet entry points */
static void admsw_start(struct ifnet *);
-static void admsw_watchdog(struct ifnet *);
+static void admsw_watchdog(void *);
static int admsw_ioctl(struct ifnet *, u_long, caddr_t);
static void admsw_init(void *);
static void admsw_stop(struct ifnet *, int);
@@ -398,6 +398,7 @@ admsw_attach(device_t dev)
device_printf(sc->sc_dev, "base Ethernet address %s\n",
ether_sprintf(enaddr));
+ callout_init(&sc->sc_watchdog, 1);
rid = 0;
if ((sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@@ -536,8 +537,6 @@ admsw_attach(device_t dev)
ifp->if_ioctl = admsw_ioctl;
ifp->if_output = ether_output;
ifp->if_start = admsw_start;
- ifp->if_watchdog = admsw_watchdog;
- ifp->if_timer = 0;
ifp->if_init = admsw_init;
ifp->if_mtu = ETHERMTU;
ifp->if_baudrate = IF_Mbps(100);
@@ -733,7 +732,7 @@ admsw_start(struct ifnet *ifp)
BPF_MTAP(ifp, m0);
/* Set a watchdog timer in case the chip flakes out. */
- sc->sc_ifnet[0]->if_timer = 5;
+ sc->sc_timer = 5;
}
}
@@ -743,25 +742,29 @@ admsw_start(struct ifnet *ifp)
* Watchdog timer handler.
*/
static void
-admsw_watchdog(struct ifnet *ifp)
+admsw_watchdog(void *arg)
{
- struct admsw_softc *sc = ifp->if_softc;
+ struct admsw_softc *sc = arg;
int vlan;
+ callout_reset(&sc->watchdog, hz, admsw_watchdog, sc);
+ if (sc->sc_timer == 0 || --sc->timer > 0)
+ return;
+
/* Check if an interrupt was lost. */
if (sc->sc_txfree == ADMSW_NTXLDESC) {
device_printf(sc->sc_dev, "watchdog false alarm\n");
return;
}
- if (sc->sc_ifnet[0]->if_timer != 0)
+ if (sc->sc_timer != 0)
device_printf(sc->sc_dev, "watchdog timer is %d!\n",
- sc->sc_ifnet[0]->if_timer);
+ sc->sc_timer);
admsw_txintr(sc, 0);
if (sc->sc_txfree == ADMSW_NTXLDESC) {
device_printf(sc->sc_dev, "tx IRQ lost (queue empty)\n");
return;
}
- if (sc->sc_ifnet[0]->if_timer != 0) {
+ if (sc->sc_timer != 0) {
device_printf(sc->sc_dev, "tx IRQ lost (timer recharged)\n");
return;
}
@@ -938,7 +941,7 @@ admsw_txintr(struct admsw_softc *sc, int prio)
* cancel the watchdog timer.
*/
if (sc->sc_txfree == ADMSW_NTXLDESC)
- ifp->if_timer = 0;
+ sc->sc_timer = 0;
}
@@ -1096,6 +1099,9 @@ admsw_init(void *xsc)
~(ADMSW_INTR_SHD | ADMSW_INTR_SLD |
ADMSW_INTR_RHD | ADMSW_INTR_RLD |
ADMSW_INTR_HDF | ADMSW_INTR_LDF));
+
+ callout_reset(&sc->sc_watchdog, hz,
+ admsw_watchdog, sc);
}
sc->ndevs++;
}
@@ -1137,11 +1143,14 @@ admsw_stop(struct ifnet *ifp, int disable)
/* disable interrupts */
REG_WRITE(ADMSW_INT_MASK, INT_MASK);
+
+ /* Cancel the watchdog timer. */
+ sc->sc_timer = 0;
+ callout_stop(&sc->sc_watchdog);
}
- /* Mark the interface as down and cancel the watchdog timer. */
+ /* Mark the interface as down. */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- ifp->if_timer = 0;
return;
}
diff --git a/sys/mips/adm5120/if_admswvar.h b/sys/mips/adm5120/if_admswvar.h
index a94bb89..1304fac 100644
--- a/sys/mips/adm5120/if_admswvar.h
+++ b/sys/mips/adm5120/if_admswvar.h
@@ -132,7 +132,9 @@ struct admsw_softc {
bus_dma_tag_t sc_bufs_dmat; /* bus DMA tag for buffers */
struct ifmedia sc_ifmedia[SW_DEVS];
int ndevs; /* number of IFF_RUNNING interfaces */
- struct ifnet *sc_ifnet[SW_DEVS];
+ struct ifnet *sc_ifnet[SW_DEVS];
+ struct callout sc_watchdog;
+ int sc_timer;
/* Ethernet common data */
void *sc_ih; /* interrupt cookie */
struct resource *irq_res;
OpenPOWER on IntegriCloud