Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Nov 2009 14:23:09 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r199380 - head/sys/dev/ed
Message-ID:  <200911171423.nAHEN98w011955@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Tue Nov 17 14:23:09 2009
New Revision: 199380
URL: http://svn.freebsd.org/changeset/base/199380

Log:
  Use a private callout timer to drive the transmit watchdog instead of using
  if_watchdog and if_timer.  The driver already contained an optional stats
  timer that individual attachments could use to provide a 'tick' event.  The
  stats timer only ran if the tick function pointer was non-NULL and the
  attachment's tick routine had to call callout_reset(), etc.  Now the driver
  always schedules a stat timer and manages the callout_reset() internally.
  This timer is used to drive the watchdog and will also call the attachment's
  'tick' handler if one is provided.
  
  Tested by:	WATANABE Kazuhiro

Modified:
  head/sys/dev/ed/if_ed.c
  head/sys/dev/ed/if_ed_pccard.c
  head/sys/dev/ed/if_edvar.h

Modified: head/sys/dev/ed/if_ed.c
==============================================================================
--- head/sys/dev/ed/if_ed.c	Tue Nov 17 14:14:07 2009	(r199379)
+++ head/sys/dev/ed/if_ed.c	Tue Nov 17 14:23:09 2009	(r199380)
@@ -77,7 +77,8 @@ static int	ed_ioctl(struct ifnet *, u_lo
 static void	ed_start(struct ifnet *);
 static void	ed_start_locked(struct ifnet *);
 static void	ed_reset(struct ifnet *);
-static void	ed_watchdog(struct ifnet *);
+static void	ed_tick(void *);
+static void	ed_watchdog(struct ed_softc *);
 
 static void	ed_ds_getmcaf(struct ed_softc *, uint32_t *);
 
@@ -281,7 +282,6 @@ ed_attach(device_t dev)
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_start = ed_start;
 	ifp->if_ioctl = ed_ioctl;
-	ifp->if_watchdog = ed_watchdog;
 	ifp->if_init = ed_init;
 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
 	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
@@ -381,8 +381,8 @@ ed_detach(device_t dev)
 			ed_stop(sc);
 		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 		ED_UNLOCK(sc);
-		callout_drain(&sc->tick_ch);
 		ether_ifdetach(ifp);
+		callout_drain(&sc->tick_ch);
 	}
 	if (sc->irq_res != NULL && sc->irq_handle)
 		bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
@@ -447,26 +447,42 @@ void
 ed_stop(struct ed_softc *sc)
 {
 	ED_ASSERT_LOCKED(sc);
-	if (sc->sc_tick)
-		callout_stop(&sc->tick_ch);
+	callout_stop(&sc->tick_ch);
 	ed_stop_hw(sc);
 }
 
 /*
+ * Periodic timer used to drive the watchdog and attachment-specific
+ * tick handler.
+ */
+static void
+ed_tick(void *arg)
+{
+	struct ed_softc *sc;
+
+	sc = arg;
+	ED_ASSERT_LOCKED(sc);
+	if (sc->sc_tick)
+		sc->sc_tick(sc);
+	if (sc->tx_timer != 0 && --sc->tx_timer == 0)
+		ed_watchdog(sc);
+	callout_reset(&sc->tick_ch, hz, ed_tick, sc);
+}
+
+/*
  * Device timeout/watchdog routine. Entered if the device neglects to
  *	generate an interrupt after a transmit has been started on it.
  */
 static void
-ed_watchdog(struct ifnet *ifp)
+ed_watchdog(struct ed_softc *sc)
 {
-	struct ed_softc *sc = ifp->if_softc;
+	struct ifnet *ifp;
 
+	ifp = sc->ifp;
 	log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
 	ifp->if_oerrors++;
 
-	ED_LOCK(sc);
 	ed_reset(ifp);
-	ED_UNLOCK(sc);
 }
 
 /*
@@ -499,7 +515,7 @@ ed_init_locked(struct ed_softc *sc)
 
 	/* reset transmitter flags */
 	sc->xmit_busy = 0;
-	ifp->if_timer = 0;
+	sc->tx_timer = 0;
 
 	sc->txb_inuse = 0;
 	sc->txb_new = 0;
@@ -612,8 +628,7 @@ ed_init_locked(struct ed_softc *sc)
 	 */
 	ed_start_locked(ifp);
 
-	if (sc->sc_tick)
-		callout_reset(&sc->tick_ch, hz, sc->sc_tick, sc);
+	callout_reset(&sc->tick_ch, hz, ed_tick, sc);
 }
 
 /*
@@ -622,7 +637,6 @@ ed_init_locked(struct ed_softc *sc)
 static __inline void
 ed_xmit(struct ed_softc *sc)
 {
-	struct ifnet *ifp = sc->ifp;
 	unsigned short len;
 
 	len = sc->txb_len[sc->txb_next_tx];
@@ -660,7 +674,7 @@ ed_xmit(struct ed_softc *sc)
 	/*
 	 * Set a timer just in case we never hear from the board again
 	 */
-	ifp->if_timer = 2;
+	sc->tx_timer = 2;
 }
 
 /*
@@ -1023,7 +1037,7 @@ edintr(void *arg)
 			/*
 			 * clear watchdog timer
 			 */
-			ifp->if_timer = 0;
+			sc->tx_timer = 0;
 
 			/*
 			 * Add in total number of collisions on last

Modified: head/sys/dev/ed/if_ed_pccard.c
==============================================================================
--- head/sys/dev/ed/if_ed_pccard.c	Tue Nov 17 14:14:07 2009	(r199379)
+++ head/sys/dev/ed/if_ed_pccard.c	Tue Nov 17 14:23:09 2009	(r199380)
@@ -250,7 +250,7 @@ static const struct ed_product {
  */
 static int	ed_pccard_probe(device_t);
 static int	ed_pccard_attach(device_t);
-static void	ed_pccard_tick(void *);
+static void	ed_pccard_tick(struct ed_softc *);
 
 static int	ed_pccard_dl100xx(device_t dev, const struct ed_product *);
 static void	ed_pccard_dl100xx_mii_reset(struct ed_softc *sc);
@@ -1196,9 +1196,8 @@ ed_child_detached(device_t dev, device_t
 }
 
 static void
-ed_pccard_tick(void *arg)
+ed_pccard_tick(struct ed_softc *sc)
 {
-	struct ed_softc *sc = arg;
 	struct mii_data *mii;
 	int media = 0;
 
@@ -1223,7 +1222,6 @@ ed_pccard_tick(void *arg)
 		}
 		
 	}
-	callout_reset(&sc->tick_ch, hz, ed_pccard_tick, sc);
 }
 
 static device_method_t ed_pccard_methods[] = {

Modified: head/sys/dev/ed/if_edvar.h
==============================================================================
--- head/sys/dev/ed/if_edvar.h	Tue Nov 17 14:14:07 2009	(r199379)
+++ head/sys/dev/ed/if_edvar.h	Tue Nov 17 14:23:09 2009	(r199380)
@@ -65,11 +65,12 @@ struct ed_softc {
 	void	(*mii_writebits)(struct ed_softc *, u_int, int);
 	u_int	(*mii_readbits)(struct ed_softc *, int);
 	struct callout	      tick_ch;
-        void	(*sc_tick)(void *);
+        void	(*sc_tick)(struct ed_softc *);
 	void (*readmem)(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
 	    uint16_t amount);
 	u_short	(*sc_write_mbufs)(struct ed_softc *, struct mbuf *, bus_size_t);
 
+	int	tx_timer;
 	int	nic_offset;	/* NIC (DS8390) I/O bus address offset */
 	int	asic_offset;	/* ASIC I/O bus address offset */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911171423.nAHEN98w011955>