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
This commit is contained in:
John Baldwin 2009-11-24 18:34:47 +00:00
parent fd4d32feb2
commit 31e119ed7d
2 changed files with 24 additions and 13 deletions

View File

@ -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;
}

View File

@ -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;