1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-07 09:20:11 +00:00

- 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.
This commit is contained in:
John Baldwin 2009-11-19 22:06:40 +00:00
parent d95121b427
commit 7cf545d0a1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=199559
18 changed files with 207 additions and 122 deletions

View File

@ -124,7 +124,7 @@ static void cm_reset_locked(struct cm_softc *);
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);
}

View File

@ -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 */

View File

@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@ -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 @@ epstart_locked(struct ifnet *ifp)
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 @@ ep_intr(void *arg)
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 @@ ep_intr(void *arg)
#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 @@ ep_intr(void *arg)
/* 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, caddr_t data)
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, caddr_t data)
}
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);
}

View File

@ -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. */

View File

@ -391,16 +391,14 @@ fatm_check_heartbeat(struct fatm_softc *sc)
* 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);

View File

@ -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 */

View File

@ -135,7 +135,7 @@ static int malo_setup_hwdma(struct malo_softc *);
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_softc *sc)
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_softc *sc)
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, struct ieee80211_node *ni,
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 disable)
* 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);

View File

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

View File

@ -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_softc *sc)
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_softc *sc)
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 disable)
* 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, struct ieee80211_node *ni, struct mwl_txbuf *
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");

View File

@ -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 */

View File

@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
@ -121,6 +122,7 @@ static int snioctl(struct ifnet * ifp, u_long, caddr_t);
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 @@ snstart_locked(struct ifnet *ifp)
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 @@ snstart_locked(struct ifnet *ifp)
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 @@ snresume(struct ifnet *ifp)
* 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 @@ sn_intr(void *arg)
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, caddr_t data)
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, caddr_t data)
}
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);
}

View File

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

View File

@ -108,7 +108,7 @@ static int ste_ioctl(struct ifnet *, u_long, caddr_t);
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;
}

View File

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

View File

@ -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, caddr_t addr, int flag,
}
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);
if (sc->ti_timer == 0 || --sc->ti_timer > 0)
return;
/*
* When we're debugging, the chip is often stopped for long periods
* of time, and that would normally cause the watchdog timer to fire.
* Since that impedes debugging, we don't want to do that.
*/
if (sc->ti_flags & TI_FLAG_DEBUGING) {
TI_UNLOCK(sc);
if (sc->ti_flags & TI_FLAG_DEBUGING)
return;
}
ifp = sc->ti_ifp;
if_printf(ifp, "watchdog timeout -- resetting\n");
ti_stop(sc);
ti_init_locked(sc);
ifp->if_oerrors++;
TI_UNLOCK(sc);
}
/*
@ -3859,6 +3859,7 @@ ti_stop(sc)
sc->ti_tx_saved_considx = TI_TXCONS_UNSET;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
callout_stop(&sc->ti_watchdog);
}
/*

View File

@ -1038,6 +1038,8 @@ struct ti_softc {
int ti_if_flags;
int ti_txcnt;
struct mtx ti_mtx;
struct callout ti_watchdog;
int ti_timer;
ti_flag_vals ti_flags;
struct cdev *dev;
};

View File

@ -129,7 +129,7 @@ static void vx_init_locked(struct vx_softc *);
static int vx_ioctl(struct ifnet *, u_long, caddr_t);
static void vx_start(struct ifnet *);
static void vx_start_locked(struct ifnet *);
static void vx_watchdog(struct ifnet *);
static void vx_watchdog(void *);
static void vx_reset(struct vx_softc *);
static void vx_read(struct vx_softc *);
static struct mbuf *vx_get(struct vx_softc *, u_int);
@ -157,6 +157,7 @@ vx_attach(device_t dev)
mtx_init(&sc->vx_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
callout_init_mtx(&sc->vx_callout, &sc->vx_mtx, 0);
callout_init_mtx(&sc->vx_watchdog, &sc->vx_mtx, 0);
GO_WINDOW(0);
CSR_WRITE_2(sc, VX_COMMAND, GLOBAL_RESET);
VX_BUSY_WAIT;
@ -193,7 +194,6 @@ vx_attach(device_t dev)
ifp->if_start = vx_start;
ifp->if_ioctl = vx_ioctl;
ifp->if_init = vx_init;
ifp->if_watchdog = vx_watchdog;
ifp->if_softc = sc;
ether_ifattach(ifp, eaddr);
@ -269,6 +269,7 @@ vx_init_locked(struct vx_softc *sc)
/* Interface is now `running', with no output active. */
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
callout_reset(&sc->vx_watchdog, hz, vx_watchdog, sc);
/* Attempt to start output, if any. */
vx_start_locked(ifp);
@ -474,7 +475,7 @@ vx_start_locked(struct ifnet *ifp)
/* not enough room in FIFO - make sure */
if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ifp->if_timer = 1;
sc->vx_timer = 1;
return;
}
}
@ -513,7 +514,7 @@ vx_start_locked(struct ifnet *ifp)
CSR_WRITE_1(sc, VX_W1_TX_PIO_WR_1, 0); /* Padding */
++ifp->if_opackets;
ifp->if_timer = 1;
sc->vx_timer = 1;
readcheck:
if ((CSR_READ_2(sc, VX_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
@ -661,18 +662,18 @@ vx_intr(void *voidsc)
if (status & S_RX_COMPLETE)
vx_read(sc);
if (status & S_TX_AVAIL) {
ifp->if_timer = 0;
sc->vx_timer = 0;
sc->vx_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
vx_start_locked(sc->vx_ifp);
}
if (status & S_CARD_FAILURE) {
if_printf(ifp, "adapter failure (%x)\n", status);
ifp->if_timer = 0;
sc->vx_timer = 0;
vx_reset(sc);
break;
}
if (status & S_TX_COMPLETE) {
ifp->if_timer = 0;
sc->vx_timer = 0;
vx_txstat(sc);
vx_start_locked(ifp);
}
@ -970,26 +971,32 @@ vx_reset(struct vx_softc *sc)
}
static void
vx_watchdog(struct ifnet *ifp)
vx_watchdog(void *arg)
{
struct vx_softc *sc = ifp->if_softc;
struct vx_softc *sc;
struct ifnet *ifp;
VX_LOCK(sc);
sc = arg;
VX_LOCK_ASSERT(sc);
callout_reset(&sc->vx_watchdog, hz, vx_watchdog, sc);
if (sc->vx_timer == 0 || --sc->vx_timer > 0)
return;
ifp = sc->vx_ifp;
if (ifp->if_flags & IFF_DEBUG)
if_printf(ifp, "device timeout\n");
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
vx_start_locked(ifp);
vx_intr(sc);
VX_UNLOCK(sc);
}
void
vx_stop(struct vx_softc *sc)
{
struct ifnet *ifp = sc->vx_ifp;
VX_LOCK_ASSERT(sc);
ifp->if_timer = 0;
sc->vx_timer = 0;
callout_stop(&sc->vx_watchdog);
CSR_WRITE_2(sc, VX_COMMAND, RX_DISABLE);
CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK);

View File

@ -51,8 +51,10 @@ struct vx_softc {
int vx_tx_succ_ok; /* # packets sent in sequence */
/* w/o underrun */
struct callout vx_callout; /* Callout for timeouts */
struct callout vx_watchdog;
struct mtx vx_mtx;
int vx_buffill_pending;
int vx_timer;
};
#define CSR_WRITE_4(sc, reg, val) \