From owner-svn-src-head@FreeBSD.ORG Thu Nov 19 22:06:40 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C2AD51065695; Thu, 19 Nov 2009 22:06:40 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AD7AF8FC21; Thu, 19 Nov 2009 22:06:40 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nAJM6eRX021347; Thu, 19 Nov 2009 22:06:40 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nAJM6e99021330; Thu, 19 Nov 2009 22:06:40 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200911192206.nAJM6e99021330@svn.freebsd.org> From: John Baldwin Date: Thu, 19 Nov 2009 22:06:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r199559 - in head/sys/dev: cm ep fatm malo mwl sn ste ti vx X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Nov 2009 22:06:40 -0000 Author: jhb Date: Thu Nov 19 22:06:40 2009 New Revision: 199559 URL: http://svn.freebsd.org/changeset/base/199559 Log: - 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. Modified: head/sys/dev/cm/smc90cx6.c head/sys/dev/cm/smc90cx6var.h head/sys/dev/ep/if_ep.c head/sys/dev/ep/if_epvar.h head/sys/dev/fatm/if_fatm.c head/sys/dev/fatm/if_fatmvar.h head/sys/dev/malo/if_malo.c head/sys/dev/malo/if_malo.h head/sys/dev/mwl/if_mwl.c head/sys/dev/mwl/if_mwlvar.h head/sys/dev/sn/if_sn.c head/sys/dev/sn/if_snvar.h head/sys/dev/ste/if_ste.c head/sys/dev/ste/if_stereg.h head/sys/dev/ti/if_ti.c head/sys/dev/ti/if_tireg.h head/sys/dev/vx/if_vx.c head/sys/dev/vx/if_vxvar.h Modified: head/sys/dev/cm/smc90cx6.c ============================================================================== --- head/sys/dev/cm/smc90cx6.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/cm/smc90cx6.c Thu Nov 19 22:06:40 2009 (r199559) @@ -124,7 +124,7 @@ static void cm_reset_locked(struct cm_so void cm_start(struct ifnet *); void cm_start_locked(struct ifnet *); int cm_ioctl(struct ifnet *, unsigned long, caddr_t); -void cm_watchdog(struct ifnet *); +void cm_watchdog(void *); void cm_srint_locked(void *vsc); static void cm_tint_locked(struct cm_softc *, int); void cm_reconwatch_locked(void *); @@ -194,11 +194,9 @@ cm_attach(dev) ifp->if_output = arc_output; ifp->if_start = cm_start; ifp->if_ioctl = cm_ioctl; - ifp->if_watchdog = cm_watchdog; ifp->if_init = cm_init; /* XXX IFQ_SET_READY(&ifp->if_snd); */ ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - ifp->if_timer = 0; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; arc_ifattach(ifp, linkaddress); @@ -210,6 +208,7 @@ cm_attach(dev) #endif callout_init_mtx(&sc->sc_recon_ch, &sc->sc_mtx, 0); + callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0); if_printf(ifp, "link addr 0x%02x (%d)\n", linkaddress, linkaddress); return 0; @@ -315,6 +314,7 @@ cm_reset_locked(sc) ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + callout_reset(&sc->sc_watchdog_timer, hz, cm_watchdog, sc); cm_start_locked(ifp); } @@ -332,7 +332,8 @@ cm_stop_locked(sc) GETREG(CMRESET); /* Stop watchdog timer */ - sc->sc_ifp->if_timer = 0; + callout_stop(&sc->sc_watchdog_timer); + sc->sc_timer = 0; } void @@ -464,7 +465,7 @@ cm_start_locked(ifp) PUTREG(CMCMD, CM_TX(buffer)); PUTREG(CMSTAT, sc->sc_intmask); - ifp->if_timer = ARCTIMEOUT; + sc->sc_timer = ARCTIMEOUT; } m_freem(m); @@ -627,7 +628,7 @@ cm_tint_locked(sc, isr) if (isr & CM_TMA || sc->sc_broadcast[buffer]) ifp->if_opackets++; #ifdef CMRETRANSMIT - else if (ifp->if_flags & IFF_LINK2 && ifp->if_timer > 0 + else if (ifp->if_flags & IFF_LINK2 && sc->sc_timer > 0 && --sc->sc_retransmits[buffer] > 0) { /* retransmit same buffer */ PUTREG(CMCMD, CM_TX(buffer)); @@ -657,7 +658,7 @@ cm_tint_locked(sc, isr) */ PUTREG(CMCMD, CM_TX(buffer)); /* init watchdog timer */ - ifp->if_timer = ARCTIMEOUT; + sc->sc_timer = ARCTIMEOUT; #if defined(CM_DEBUG) && (CM_DEBUG > 1) if_printf(ifp, @@ -669,7 +670,7 @@ cm_tint_locked(sc, isr) sc->sc_intmask &= ~CM_TA; PUTREG(CMSTAT, sc->sc_intmask); /* ... and watchdog timer */ - ifp->if_timer = 0; + sc->sc_timer = 0; #ifdef CM_DEBUG if_printf(ifp, "tint: no more buffers to send, status 0x%02x\n", @@ -920,12 +921,13 @@ cm_ioctl(ifp, command, data) * retransmission is implemented). */ void -cm_watchdog(ifp) - struct ifnet *ifp; +cm_watchdog(void *arg) { - struct cm_softc *sc = ifp->if_softc; + struct cm_softc *sc; - CM_LOCK(sc); + sc = arg; + callout_reset(&sc->sc_watchdog_timer, hz, cm_watchdog, sc); + if (sc->sc_timer == 0 || --sc->sc_timer > 0) + return; PUTREG(CMCMD, CM_TXDIS); - CM_UNLOCK(sc); } Modified: head/sys/dev/cm/smc90cx6var.h ============================================================================== --- head/sys/dev/cm/smc90cx6var.h Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/cm/smc90cx6var.h Thu Nov 19 22:06:40 2009 (r199559) @@ -77,6 +77,8 @@ struct cm_softc { u_long sc_reconcount_excessive; /* for the above */ #define ARC_EXCESSIVE_RECONS 20 #define ARC_EXCESSIVE_RECONS_REWARN 400 + struct callout sc_watchdog_timer; + int sc_timer; u_char sc_intmask; u_char sc_rx_act; /* 2..3 */ u_char sc_tx_act; /* 0..1 */ Modified: head/sys/dev/ep/if_ep.c ============================================================================== --- head/sys/dev/ep/if_ep.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/ep/if_ep.c Thu Nov 19 22:06:40 2009 (r199559) @@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -91,10 +92,12 @@ static int ep_media2if_media[] = static void epinit(void *); static int epioctl(struct ifnet *, u_long, caddr_t); static void epstart(struct ifnet *); -static void epwatchdog(struct ifnet *); +static void ep_intr_locked(struct ep_softc *); static void epstart_locked(struct ifnet *); static void epinit_locked(struct ep_softc *); +static void eptick(void *); +static void epwatchdog(struct ep_softc *); /* if_media functions */ static int ep_ifmedia_upd(struct ifnet *); @@ -302,12 +305,12 @@ ep_attach(struct ep_softc *sc) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = epstart; ifp->if_ioctl = epioctl; - ifp->if_watchdog = epwatchdog; ifp->if_init = epinit; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; IFQ_SET_READY(&ifp->if_snd); + callout_init_mtx(&sc->watchdog_timer, &sc->sc_mtx, 0); if (!sc->epb.mii_trans) { ifmedia_init(&sc->ifmedia, 0, ep_ifmedia_upd, ep_ifmedia_sts); @@ -361,6 +364,7 @@ ep_detach(device_t dev) ifp->if_drv_flags &= ~IFF_DRV_RUNNING; EP_UNLOCK(sc); ether_ifdetach(ifp); + callout_drain(&sc->watchdog_timer); ep_free(dev); if_free(ifp); @@ -457,6 +461,7 @@ epinit_locked(struct ep_softc *sc) GO_WINDOW(sc, 1); epstart_locked(ifp); + callout_reset(&sc->watchdog_timer, hz, eptick, sc); } static void @@ -556,7 +561,7 @@ startagain: BPF_MTAP(ifp, m0); - ifp->if_timer = 2; + sc->tx_timer = 2; ifp->if_opackets++; m_freem(m0); @@ -583,20 +588,26 @@ void ep_intr(void *arg) { struct ep_softc *sc; - int status; - struct ifnet *ifp; sc = (struct ep_softc *) arg; EP_LOCK(sc); + ep_intr_locked(sc); + EP_UNLOCK(sc); +} + +static void +ep_intr_locked(struct ep_softc *sc) +{ + int status; + struct ifnet *ifp; + /* XXX 4.x splbio'd here to reduce interruptability */ /* * quick fix: Try to detect an interrupt when the card goes away. */ - if (sc->gone || CSR_READ_2(sc, EP_STATUS) == 0xffff) { - EP_UNLOCK(sc); + if (sc->gone || CSR_READ_2(sc, EP_STATUS) == 0xffff) return; - } ifp = sc->ifp; CSR_WRITE_2(sc, EP_COMMAND, SET_INTR_MASK); /* disable all Ints */ @@ -612,14 +623,14 @@ rescan: epread(sc); if (status & S_TX_AVAIL) { /* we need ACK */ - ifp->if_timer = 0; + sc->tx_timer = 0; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; GO_WINDOW(sc, 1); CSR_READ_2(sc, EP_W1_FREE_TX); epstart_locked(ifp); } if (status & S_CARD_FAILURE) { - ifp->if_timer = 0; + sc->tx_timer = 0; #ifdef EP_LOCAL_STATS device_printf(sc->dev, "\n\tStatus: %x\n", status); GO_WINDOW(sc, 4); @@ -642,11 +653,10 @@ rescan: #endif epinit_locked(sc); - EP_UNLOCK(sc); return; } if (status & S_TX_COMPLETE) { - ifp->if_timer = 0; + sc->tx_timer = 0; /* * We need ACK. We do it at the end. * @@ -700,7 +710,6 @@ rescan: /* re-enable Ints */ CSR_WRITE_2(sc, EP_COMMAND, SET_INTR_MASK | S_5_INTS); - EP_UNLOCK(sc); } static void @@ -933,7 +942,6 @@ epioctl(struct ifnet *ifp, u_long cmd, c EP_LOCK(sc); if (((ifp->if_flags & IFF_UP) == 0) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) { - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; epstop(sc); } else /* reinitialize card on any parameter change */ @@ -966,15 +974,27 @@ epioctl(struct ifnet *ifp, u_long cmd, c } static void -epwatchdog(struct ifnet *ifp) +eptick(void *arg) { - struct ep_softc *sc = ifp->if_softc; + struct ep_softc *sc; + + sc = arg; + if (sc->tx_timer != 0 && --sc->tx_timer == 0) + epwatchdog(sc); + callout_reset(&sc->watchdog_timer, hz, eptick, sc); +} + +static void +epwatchdog(struct ep_softc *sc) +{ + struct ifnet *ifp; + ifp = sc->ifp; if (sc->gone) return; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - epstart(ifp); - ep_intr(ifp->if_softc); + epstart_locked(ifp); + ep_intr_locked(sc); } static void @@ -997,4 +1017,7 @@ epstop(struct ep_softc *sc) CSR_WRITE_2(sc, EP_COMMAND, SET_RD_0_MASK); CSR_WRITE_2(sc, EP_COMMAND, SET_INTR_MASK); CSR_WRITE_2(sc, EP_COMMAND, SET_RX_FILTER); + + sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + callout_stop(&sc->watchdog_timer); } Modified: head/sys/dev/ep/if_epvar.h ============================================================================== --- head/sys/dev/ep/if_epvar.h Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/ep/if_epvar.h Thu Nov 19 22:06:40 2009 (r199559) @@ -45,6 +45,9 @@ struct ep_softc { bus_space_tag_t bst; void *ep_intrhand; + struct callout watchdog_timer; + int tx_timer; + u_short ep_connectors; /* Connectors on this card. */ u_char ep_connector; /* Configured connector. */ Modified: head/sys/dev/fatm/if_fatm.c ============================================================================== --- head/sys/dev/fatm/if_fatm.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/fatm/if_fatm.c Thu Nov 19 22:06:40 2009 (r199559) @@ -391,16 +391,14 @@ fatm_check_heartbeat(struct fatm_softc * * Ensure that the heart is still beating. */ static void -fatm_watchdog(struct ifnet *ifp) +fatm_watchdog(void *arg) { - struct fatm_softc *sc = ifp->if_softc; + struct fatm_softc *sc; - FATM_LOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - fatm_check_heartbeat(sc); - ifp->if_timer = 5; - } - FATM_UNLOCK(sc); + sc = arg; + FATM_CHECKLOCK(sc); + fatm_check_heartbeat(sc); + callout_reset(&sc->watchdog_timer, hz * 5, fatm_watchdog, sc); } /* @@ -474,7 +472,7 @@ fatm_stop(struct fatm_softc *sc) (void)fatm_reset(sc); /* stop watchdog */ - sc->ifp->if_timer = 0; + callout_stop(&sc->watchdog_timer); if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) { sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); @@ -1341,7 +1339,7 @@ fatm_init_locked(struct fatm_softc *sc) /* * Start the watchdog timer */ - sc->ifp->if_timer = 5; + callout_reset(&sc->watchdog_timer, hz * 5, fatm_watchdog, sc); /* start SUNI */ utopia_start(&sc->utopia); @@ -2543,6 +2541,7 @@ fatm_detach(device_t dev) FATM_UNLOCK(sc); atm_ifdetach(sc->ifp); /* XXX race */ } + callout_drain(&sc->watchdog_timer); if (sc->ih != NULL) bus_teardown_intr(dev, sc->irqres, sc->ih); @@ -2784,6 +2783,7 @@ fatm_attach(device_t dev) cv_init(&sc->cv_regs, "fatm_regs"); sysctl_ctx_init(&sc->sysctl_ctx); + callout_init_mtx(&sc->watchdog_timer, &sc->mtx, 0); /* * Make the sysctl tree @@ -2824,7 +2824,6 @@ fatm_attach(device_t dev) ifp->if_flags = IFF_SIMPLEX; ifp->if_ioctl = fatm_ioctl; ifp->if_start = fatm_start; - ifp->if_watchdog = fatm_watchdog; ifp->if_init = fatm_init; ifp->if_linkmib = &IFP2IFATM(sc->ifp)->mib; ifp->if_linkmiblen = sizeof(IFP2IFATM(sc->ifp)->mib); Modified: head/sys/dev/fatm/if_fatmvar.h ============================================================================== --- head/sys/dev/fatm/if_fatmvar.h Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/fatm/if_fatmvar.h Thu Nov 19 22:06:40 2009 (r199559) @@ -188,6 +188,7 @@ struct fatm_softc { struct ifnet *ifp; /* common part */ struct mtx mtx; /* lock this structure */ struct ifmedia media; /* media */ + struct callout watchdog_timer; int init_state; /* initialisation step */ int memid; /* resource id for card memory */ Modified: head/sys/dev/malo/if_malo.c ============================================================================== --- head/sys/dev/malo/if_malo.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/malo/if_malo.c Thu Nov 19 22:06:40 2009 (r199559) @@ -135,7 +135,7 @@ static int malo_setup_hwdma(struct malo_ static void malo_txq_init(struct malo_softc *, struct malo_txq *, int); static void malo_tx_cleanupq(struct malo_softc *, struct malo_txq *); static void malo_start(struct ifnet *); -static void malo_watchdog(struct ifnet *); +static void malo_watchdog(void *); static int malo_ioctl(struct ifnet *, u_long, caddr_t); static void malo_updateslot(struct ifnet *); static int malo_newstate(struct ieee80211vap *, enum ieee80211_state, int); @@ -191,6 +191,7 @@ malo_attach(uint16_t devid, struct malo_ ic = ifp->if_l2com; MALO_LOCK_INIT(sc); + callout_init_mtx(&sc->malo_watchdog_timer, &sc->malo_mtx, 0); /* set these up early for if_printf use */ if_initname(ifp, device_get_name(sc->malo_dev), @@ -272,7 +273,6 @@ malo_attach(uint16_t devid, struct malo_ ifp->if_softc = sc; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; ifp->if_start = malo_start; - ifp->if_watchdog = malo_watchdog; ifp->if_ioctl = malo_ioctl; ifp->if_init = malo_init; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); @@ -1076,7 +1076,7 @@ malo_tx_proc(void *arg, int npending) if (nreaped != 0) { ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_timer = 0; + sc->malo_timer = 0; malo_start(ifp); } } @@ -1260,7 +1260,7 @@ malo_tx_start(struct malo_softc *sc, str MALO_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); ifp->if_opackets++; - ifp->if_timer = 5; + sc->malo_timer = 5; MALO_TXQ_UNLOCK(txq); return 0; #undef IEEE80211_DIR_DSTODS @@ -1339,10 +1339,17 @@ malo_start(struct ifnet *ifp) } static void -malo_watchdog(struct ifnet *ifp) +malo_watchdog(void *arg) { - struct malo_softc *sc = ifp->if_softc; + struct malo_softc *sc; + struct ifnet *ifp; + + sc = arg; + callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); + if (sc->malo_timer == 0 || --sc->malo_timer > 0) + return; + ifp = sc->malo_ifp; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->malo_invalid) { if_printf(ifp, "watchdog timeout\n"); @@ -1536,6 +1543,7 @@ malo_init_locked(struct malo_softc *sc) ifp->if_drv_flags |= IFF_DRV_RUNNING; malo_hal_intrset(mh, sc->malo_imask); + callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); } static void @@ -1699,7 +1707,8 @@ malo_stop_locked(struct ifnet *ifp, int * is gone (invalid). */ ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - ifp->if_timer = 0; + callout_stop(&sc->malo_watchdog_timer); + sc->malo_timer = 0; /* diable interrupt. */ malo_hal_intrset(mh, 0); /* turn off the radio. */ @@ -2241,6 +2250,7 @@ malo_detach(struct malo_softc *sc) * Other than that, it's straightforward... */ ieee80211_ifdetach(ic); + callout_drain(&sc->malo_watchdog_timer); malo_dma_cleanup(sc); malo_tx_cleanup(sc); malo_hal_detach(sc->malo_mh); Modified: head/sys/dev/malo/if_malo.h ============================================================================== --- head/sys/dev/malo/if_malo.h Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/malo/if_malo.h Thu Nov 19 22:06:40 2009 (r199559) @@ -550,6 +550,8 @@ struct malo_softc { struct malo_txq malo_txq[MALO_NUM_TX_QUEUES]; struct task malo_txtask; /* tx int processing */ + struct callout malo_watchdog_timer; + int malo_timer; struct malo_tx_radiotap_header malo_tx_th; struct malo_rx_radiotap_header malo_rx_th; Modified: head/sys/dev/mwl/if_mwl.c ============================================================================== --- head/sys/dev/mwl/if_mwl.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/mwl/if_mwl.c Thu Nov 19 22:06:40 2009 (r199559) @@ -98,7 +98,7 @@ static void mwl_start(struct ifnet *); static int mwl_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static int mwl_media_change(struct ifnet *); -static void mwl_watchdog(struct ifnet *); +static void mwl_watchdog(void *); static int mwl_ioctl(struct ifnet *, u_long, caddr_t); static void mwl_radar_proc(void *, int); static void mwl_chanswitch_proc(void *, int); @@ -360,6 +360,7 @@ mwl_attach(uint16_t devid, struct mwl_so goto bad1; callout_init(&sc->sc_timer, CALLOUT_MPSAFE); + callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0); sc->sc_tq = taskqueue_create("mwl_taskq", M_NOWAIT, taskqueue_thread_enqueue, &sc->sc_tq); @@ -401,7 +402,6 @@ mwl_attach(uint16_t devid, struct mwl_so ifp->if_softc = sc; ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; ifp->if_start = mwl_start; - ifp->if_watchdog = mwl_watchdog; ifp->if_ioctl = mwl_ioctl; ifp->if_init = mwl_init; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); @@ -558,6 +558,7 @@ mwl_detach(struct mwl_softc *sc) * Other than that, it's straightforward... */ ieee80211_ifdetach(ic); + callout_drain(&sc->sc_watchdog); mwl_dma_cleanup(sc); mwl_tx_cleanup(sc); mwl_hal_detach(sc->sc_mh); @@ -1214,6 +1215,7 @@ mwl_init_locked(struct mwl_softc *sc) ifp->if_drv_flags |= IFF_DRV_RUNNING; mwl_hal_intrset(mh, sc->sc_imask); + callout_reset(&sc->sc_watchdog, hz, mwl_watchdog, sc); return 0; } @@ -1251,7 +1253,8 @@ mwl_stop_locked(struct ifnet *ifp, int d * Shutdown the hardware and driver. */ ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - ifp->if_timer = 0; + callout_stop(&sc->sc_watchdog); + sc->sc_tx_timer = 0; mwl_draintxq(sc); } } @@ -3411,7 +3414,7 @@ mwl_tx_start(struct mwl_softc *sc, struc MWL_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); ifp->if_opackets++; - ifp->if_timer = 5; + sc->sc_tx_timer = 5; MWL_TXQ_UNLOCK(txq); return 0; @@ -3558,7 +3561,7 @@ mwl_tx_proc(void *arg, int npending) if (nreaped != 0) { ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_timer = 0; + sc->sc_tx_timer = 0; if (!IFQ_IS_EMPTY(&ifp->if_snd)) { /* NB: kick fw; the tx thread may have been preempted */ mwl_hal_txstart(sc->sc_mh, 0); @@ -3624,7 +3627,7 @@ mwl_draintxq(struct mwl_softc *sc) for (i = 0; i < MWL_NUM_TX_QUEUES; i++) mwl_tx_draintxq(sc, &sc->sc_txq[i]); ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_timer = 0; + sc->sc_tx_timer = 0; } #ifdef MWL_DIAGAPI @@ -4770,10 +4773,17 @@ mwl_txq_dump(struct mwl_txq *txq) #endif static void -mwl_watchdog(struct ifnet *ifp) +mwl_watchdog(void *arg) { - struct mwl_softc *sc = ifp->if_softc; + struct mwl_softc *sc; + struct ifnet *ifp; + + sc = arg; + callout_reset(&sc->sc_watchdog, hz, mwl_watchdog, sc); + if (sc->sc_tx_timer == 0 || --sc->sc_tx_timer > 0) + return; + ifp = sc->sc_ifp; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->sc_invalid) { if (mwl_hal_setkeepalive(sc->sc_mh)) if_printf(ifp, "transmit timeout (firmware hung?)\n"); Modified: head/sys/dev/mwl/if_mwlvar.h ============================================================================== --- head/sys/dev/mwl/if_mwlvar.h Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/mwl/if_mwlvar.h Thu Nov 19 22:06:40 2009 (r199559) @@ -255,6 +255,8 @@ struct mwl_softc { bus_space_tag_t sc_io1t; struct mtx sc_mtx; /* master lock (recursive) */ struct taskqueue *sc_tq; /* private task queue */ + struct callout sc_watchdog; + int sc_tx_timer; unsigned int sc_invalid : 1, /* disable hardware accesses */ sc_recvsetup:1, /* recv setup */ sc_csapending:1,/* 11h channel switch pending */ Modified: head/sys/dev/sn/if_sn.c ============================================================================== --- head/sys/dev/sn/if_sn.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/sn/if_sn.c Thu Nov 19 22:06:40 2009 (r199559) @@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -121,6 +122,7 @@ static int snioctl(struct ifnet * ifp, u static void snresume(struct ifnet *); +static void snintr_locked(struct sn_softc *); static void sninit_locked(void *); static void snstart_locked(struct ifnet *); @@ -128,7 +130,7 @@ static void sninit(void *); static void snread(struct ifnet *); static void snstart(struct ifnet *); static void snstop(struct sn_softc *); -static void snwatchdog(struct ifnet *); +static void snwatchdog(void *); static void sn_setmcast(struct sn_softc *); static int sn_getmcf(struct ifnet *ifp, u_char *mcf); @@ -170,6 +172,7 @@ sn_attach(device_t dev) } SN_LOCK_INIT(sc); + callout_init_mtx(&sc->watchdog, &sc->sc_mtx, 0); snstop(sc); sc->pages_wanted = -1; @@ -202,13 +205,11 @@ sn_attach(device_t dev) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = snstart; ifp->if_ioctl = snioctl; - ifp->if_watchdog = snwatchdog; ifp->if_init = sninit; ifp->if_baudrate = 10000000; IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; IFQ_SET_READY(&ifp->if_snd); - ifp->if_timer = 0; ether_ifattach(ifp, eaddr); @@ -233,9 +234,11 @@ sn_detach(device_t dev) struct sn_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->ifp; - snstop(sc); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; ether_ifdetach(ifp); + SN_LOCK(sc); + snstop(sc); + SN_UNLOCK(sc); + callout_drain(&sc->watchdog); sn_deactivate(dev); if_free(ifp); SN_LOCK_DESTROY(sc); @@ -342,6 +345,7 @@ sninit_locked(void *xsc) */ ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + callout_reset(&sc->watchdog, hz, snwatchdog, sc); /* * Attempt to push out any waiting packets. @@ -463,7 +467,7 @@ startagain: CSR_WRITE_1(sc, INTR_MASK_REG_B, mask); sc->intr_mask = mask; - ifp->if_timer = 1; + sc->timer = 1; ifp->if_drv_flags |= IFF_DRV_OACTIVE; sc->pages_wanted = numPages; return; @@ -548,7 +552,7 @@ startagain: CSR_WRITE_2(sc, MMU_CMD_REG_W, MMUCR_ENQUEUE); ifp->if_drv_flags |= IFF_DRV_OACTIVE; - ifp->if_timer = 1; + sc->timer = 1; BPF_MTAP(ifp, top); @@ -657,7 +661,7 @@ snresume(struct ifnet *ifp) packet_no = CSR_READ_1(sc, ALLOC_RESULT_REG_B); if (packet_no & ARR_FAILED) { if_printf(ifp, "Memory allocation failed. Weird.\n"); - ifp->if_timer = 1; + sc->timer = 1; goto try_start; } /* @@ -755,24 +759,32 @@ try_start: * Now pass control to snstart() to queue any additional packets */ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - snstart(ifp); + snstart_locked(ifp); /* * We've sent something, so we're active. Set a watchdog in case the * TX_EMPTY interrupt is lost. */ ifp->if_drv_flags |= IFF_DRV_OACTIVE; - ifp->if_timer = 1; + sc->timer = 1; return; } - void sn_intr(void *arg) { - int status, interrupts; struct sn_softc *sc = (struct sn_softc *) arg; + + SN_LOCK(sc); + snintr_locked(sc); + SN_UNLOCK(sc); +} + +static void +snintr_locked(struct sn_softc *sc) +{ + int status, interrupts; struct ifnet *ifp = sc->ifp; /* @@ -783,12 +795,10 @@ sn_intr(void *arg) uint16_t tx_status; uint16_t card_stats; - SN_LOCK(sc); - /* * Clear the watchdog. */ - ifp->if_timer = 0; + sc->timer = 0; SMC_SELECT_BANK(sc, 2); @@ -981,7 +991,6 @@ out: mask |= CSR_READ_1(sc, INTR_MASK_REG_B); CSR_WRITE_1(sc, INTR_MASK_REG_B, mask); sc->intr_mask = mask; - SN_UNLOCK(sc); } static void @@ -1136,7 +1145,6 @@ snioctl(struct ifnet *ifp, u_long cmd, c SN_LOCK(sc); if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) { - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; snstop(sc); } else { /* reinitialize card on any parameter change */ @@ -1161,9 +1169,16 @@ snioctl(struct ifnet *ifp, u_long cmd, c } static void -snwatchdog(struct ifnet *ifp) +snwatchdog(void *arg) { - sn_intr(ifp->if_softc); + struct sn_softc *sc; + + sc = arg; + SN_ASSERT_LOCKED(sc); + callout_reset(&sc->watchdog, hz, snwatchdog, sc); + if (sc->timer == 0 || --sc->timer > 0) + return; + snintr_locked(sc); } @@ -1193,7 +1208,9 @@ snstop(struct sn_softc *sc) /* * Cancel watchdog. */ - ifp->if_timer = 0; + sc->timer = 0; + callout_stop(&sc->watchdog); + ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); } Modified: head/sys/dev/sn/if_snvar.h ============================================================================== --- head/sys/dev/sn/if_snvar.h Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/sn/if_snvar.h Thu Nov 19 22:06:40 2009 (r199559) @@ -33,6 +33,8 @@ struct sn_softc { struct ifnet *ifp; struct mtx sc_mtx; + struct callout watchdog; + int timer; int pages_wanted; /* Size of outstanding MMU ALLOC */ int intr_mask; /* Most recently set interrupt mask */ device_t dev; Modified: head/sys/dev/ste/if_ste.c ============================================================================== --- head/sys/dev/ste/if_ste.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/ste/if_ste.c Thu Nov 19 22:06:40 2009 (r199559) @@ -108,7 +108,7 @@ static int ste_ioctl(struct ifnet *, u_l static int ste_encap(struct ste_softc *, struct ste_chain *, struct mbuf *); static void ste_start(struct ifnet *); static void ste_start_locked(struct ifnet *); -static void ste_watchdog(struct ifnet *); +static void ste_watchdog(struct ste_softc *); static int ste_shutdown(device_t); static int ste_newbuf(struct ste_softc *, struct ste_chain_onefrag *, struct mbuf *); @@ -924,7 +924,7 @@ ste_txeof(sc) sc->ste_cdata.ste_tx_cons = idx; if (idx == sc->ste_cdata.ste_tx_prod) - ifp->if_timer = 0; + sc->ste_timer = 0; } static void @@ -960,6 +960,8 @@ ste_stats_update(xsc) } } + if (sc->ste_timer > 0 && --sc->ste_timer == 0) + ste_watchdog(sc); callout_reset(&sc->ste_stat_callout, hz, ste_stats_update, sc); return; @@ -1094,7 +1096,6 @@ ste_attach(dev) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ste_ioctl; ifp->if_start = ste_start; - ifp->if_watchdog = ste_watchdog; ifp->if_init = ste_init; IFQ_SET_MAXLEN(&ifp->if_snd, STE_TX_LIST_CNT - 1); ifp->if_snd.ifq_drv_maxlen = STE_TX_LIST_CNT - 1; @@ -1159,11 +1160,11 @@ ste_detach(dev) /* These should only be active if attach succeeded */ if (device_is_attached(dev)) { + ether_ifdetach(ifp); STE_LOCK(sc); ste_stop(sc); STE_UNLOCK(sc); callout_drain(&sc->ste_stat_callout); - ether_ifdetach(ifp); } if (sc->ste_miibus) device_delete_child(dev, sc->ste_miibus); @@ -1708,7 +1709,7 @@ ste_start_locked(ifp) BPF_MTAP(ifp, cur_tx->ste_mbuf); STE_INC(idx, STE_TX_LIST_CNT); - ifp->if_timer = 5; + sc->ste_timer = 5; } sc->ste_cdata.ste_tx_prod = idx; @@ -1716,13 +1717,12 @@ ste_start_locked(ifp) } static void -ste_watchdog(ifp) - struct ifnet *ifp; +ste_watchdog(struct ste_softc *sc) { - struct ste_softc *sc; + struct ifnet *ifp; - sc = ifp->if_softc; - STE_LOCK(sc); + ifp = sc->ste_ifp; + STE_LOCK_ASSERT(sc); ifp->if_oerrors++; if_printf(ifp, "watchdog timeout\n"); @@ -1736,7 +1736,6 @@ ste_watchdog(ifp) if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) ste_start_locked(ifp); - STE_UNLOCK(sc); return; } Modified: head/sys/dev/ste/if_stereg.h ============================================================================== --- head/sys/dev/ste/if_stereg.h Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/ste/if_stereg.h Thu Nov 19 22:06:40 2009 (r199559) @@ -517,6 +517,7 @@ struct ste_softc { int ste_tx_thresh; u_int8_t ste_link; int ste_if_flags; + int ste_timer; struct ste_chain *ste_tx_prev; struct ste_list_data *ste_ldata; struct ste_chain_data ste_cdata; Modified: head/sys/dev/ti/if_ti.c ============================================================================== --- head/sys/dev/ti/if_ti.c Thu Nov 19 22:06:19 2009 (r199558) +++ head/sys/dev/ti/if_ti.c Thu Nov 19 22:06:40 2009 (r199559) @@ -194,7 +194,7 @@ static void ti_init(void *); static void ti_init_locked(void *); static void ti_init2(struct ti_softc *); static void ti_stop(struct ti_softc *); -static void ti_watchdog(struct ifnet *); +static void ti_watchdog(void *); static int ti_shutdown(device_t); static int ti_ifmedia_upd(struct ifnet *); static void ti_ifmedia_sts(struct ifnet *, struct ifmediareq *); @@ -2285,6 +2285,7 @@ ti_attach(dev) mtx_init(&sc->ti_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); + callout_init_mtx(&sc->ti_watchdog, &sc->ti_mtx, 0); ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts); ifp = sc->ti_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { @@ -2486,7 +2487,6 @@ ti_attach(dev) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ti_ioctl; ifp->if_start = ti_start; - ifp->if_watchdog = ti_watchdog; ifp->if_init = ti_init; ifp->if_baudrate = 1000000000; ifp->if_mtu = ETHERMTU; @@ -2565,24 +2565,22 @@ ti_detach(dev) { struct ti_softc *sc; struct ifnet *ifp; - int attached; sc = device_get_softc(dev); if (sc->dev) destroy_dev(sc->dev); KASSERT(mtx_initialized(&sc->ti_mtx), ("ti mutex not initialized")); - attached = device_is_attached(dev); - TI_LOCK(sc); ifp = sc->ti_ifp; - if (attached) - ti_stop(sc); - TI_UNLOCK(sc); - if (attached) + if (device_is_attached(dev)) { ether_ifdetach(ifp); + TI_LOCK(sc); + ti_stop(sc); + TI_UNLOCK(sc); + } /* These should only be active if attach succeeded */ - if (attached) - bus_generic_detach(dev); + callout_drain(&sc->ti_watchdog); + bus_generic_detach(dev); ti_free_dmamaps(sc); ifmedia_removeall(&sc->ifmedia); @@ -2866,7 +2864,7 @@ ti_txeof(sc) } sc->ti_tx_saved_considx = idx; - ifp->if_timer = sc->ti_txcnt > 0 ? 5 : 0; + sc->ti_timer = sc->ti_txcnt > 0 ? 5 : 0; } static void @@ -3121,7 +3119,7 @@ ti_start_locked(ifp) /* * Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; + sc->ti_timer = 5; } } @@ -3225,6 +3223,7 @@ static void ti_init2(sc) ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc); /* * Make sure to set media properly. We have to do this @@ -3786,30 +3785,31 @@ ti_ioctl2(struct cdev *dev, u_long cmd, } static void -ti_watchdog(ifp) - struct ifnet *ifp; +ti_watchdog(void *arg) { struct ti_softc *sc; + struct ifnet *ifp; - sc = ifp->if_softc; - TI_LOCK(sc); + sc = arg; + TI_LOCK_ASSERT(sc); + callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***