- 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:
parent
d95121b427
commit
7cf545d0a1
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user