Author: jhb
Date: Tue Nov 24 18:34:47 2009
New Revision: 199762
URL: http://svn.freebsd.org/changeset/base/199762

Log:
  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

Modified:
  head/sys/mips/adm5120/if_admsw.c
  head/sys/mips/adm5120/if_admswvar.h

Modified: head/sys/mips/adm5120/if_admsw.c
==============================================================================
--- head/sys/mips/adm5120/if_admsw.c    Tue Nov 24 17:46:58 2009        
(r199761)
+++ head/sys/mips/adm5120/if_admsw.c    Tue Nov 24 18:34:47 2009        
(r199762)
@@ -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
                 * 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 disabl
 
                /* 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;
 }

Modified: head/sys/mips/adm5120/if_admswvar.h
==============================================================================
--- head/sys/mips/adm5120/if_admswvar.h Tue Nov 24 17:46:58 2009        
(r199761)
+++ head/sys/mips/adm5120/if_admswvar.h Tue Nov 24 18:34:47 2009        
(r199762)
@@ -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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to