summaryrefslogtreecommitdiffstats
path: root/sys/dev/bce
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2007-01-11 03:17:28 +0000
committerdelphij <delphij@FreeBSD.org>2007-01-11 03:17:28 +0000
commit83499bc2d958aa69d2fa52ddaa4c7e8d3d04b929 (patch)
treefc680fb03443e0aa75145e4566ca1ba603eee513 /sys/dev/bce
parenta379d6b5a481f8396d68e25339b4e8704740afdf (diff)
downloadFreeBSD-src-83499bc2d958aa69d2fa52ddaa4c7e8d3d04b929.zip
FreeBSD-src-83499bc2d958aa69d2fa52ddaa4c7e8d3d04b929.tar.gz
- Instead of if_watchdog/if_timer interface use our own timer
that piggybacks on bce_tick() callout. - Instead of unconditionally resetting the controller, try to skip the reset in case we got a pause frame, like em(4) did. - Lock bce_tick() using callout_init_mtx(). Discussed with/Reviewed by: glebius, scottl, davidch
Diffstat (limited to 'sys/dev/bce')
-rw-r--r--sys/dev/bce/if_bce.c55
-rw-r--r--sys/dev/bce/if_bcereg.h2
2 files changed, 28 insertions, 29 deletions
diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
index 70cb64b..b091101 100644
--- a/sys/dev/bce/if_bce.c
+++ b/sys/dev/bce/if_bce.c
@@ -303,7 +303,7 @@ static int bce_tx_encap (struct bce_softc *, struct mbuf **);
static void bce_start_locked (struct ifnet *);
static void bce_start (struct ifnet *);
static int bce_ioctl (struct ifnet *, u_long, caddr_t);
-static void bce_watchdog (struct ifnet *);
+static void bce_watchdog (struct bce_softc *);
static int bce_ifmedia_upd (struct ifnet *);
static void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *);
static void bce_init_locked (struct bce_softc *);
@@ -326,7 +326,6 @@ static void bce_poll (struct ifnet *, enum poll_cmd, int);
static void bce_intr (void *);
static void bce_set_rx_mode (struct bce_softc *);
static void bce_stats_update (struct bce_softc *);
-static void bce_tick_locked (struct bce_softc *);
static void bce_tick (void *);
static void bce_add_sysctls (struct bce_softc *);
@@ -721,8 +720,6 @@ bce_attach(device_t dev)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = bce_ioctl;
ifp->if_start = bce_start;
- ifp->if_timer = 0;
- ifp->if_watchdog = bce_watchdog;
ifp->if_init = bce_init;
ifp->if_mtu = ETHERMTU;
ifp->if_hwassist = BCE_IF_HWASSIST;
@@ -766,7 +763,7 @@ bce_attach(device_t dev)
#if __FreeBSD_version < 500000
callout_init(&sc->bce_stat_ch);
#else
- callout_init(&sc->bce_stat_ch, CALLOUT_MPSAFE);
+ callout_init_mtx(&sc->bce_stat_ch, &sc->bce_mtx, 0);
#endif
/* Hookup IRQ last. */
@@ -3123,7 +3120,7 @@ bce_stop(struct bce_softc *sc)
}
ifp->if_flags = itmp;
- ifp->if_timer = 0;
+ sc->watchdog_timer = 0;
sc->bce_link = 0;
@@ -3889,7 +3886,7 @@ bce_phy_intr(struct bce_softc *sc)
sc->bce_link = 0;
callout_stop(&sc->bce_stat_ch);
- bce_tick_locked(sc);
+ bce_tick(sc);
/* Update the status_attn_bits_ack field in the status block. */
if (new_link_state) {
@@ -4296,7 +4293,7 @@ bce_tx_intr(struct bce_softc *sc)
}
/* Clear the TX timeout timer. */
- ifp->if_timer = 0;
+ sc->watchdog_timer = 0;
/* Clear the tx hardware queue full flag. */
if ((sc->used_tx_bd + BCE_TX_SLACK_SPACE) < USABLE_TX_BD) {
@@ -4762,7 +4759,7 @@ bce_start_locked(struct ifnet *ifp)
REG_WR(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq);
/* Set the tx timeout. */
- ifp->if_timer = BCE_TX_TIMEOUT;
+ sc->watchdog_timer = BCE_TX_TIMEOUT;
bce_start_locked_exit:
return;
@@ -4995,25 +4992,34 @@ bce_ioctl_exit:
/* Nothing. */
/****************************************************************************/
static void
-bce_watchdog(struct ifnet *ifp)
+bce_watchdog(struct bce_softc *sc)
{
- struct bce_softc *sc = ifp->if_softc;
DBRUN(BCE_WARN_SEND,
bce_dump_driver_state(sc);
bce_dump_status_block(sc));
+ BCE_LOCK_ASSERT(sc);
+
+ if (sc->watchdog_timer == 0 || --sc->watchdog_timer)
+ return;
+
+ /*
+ * If we are in this routine because of pause frames, then
+ * don't reset the hardware.
+ */
+ if (REG_RD(sc, BCE_EMAC_TX_STATUS) & BCE_EMAC_TX_STATUS_XOFFED)
+ return;
+
BCE_PRINTF(sc, "%s(%d): Watchdog timeout occurred, resetting!\n",
__FILE__, __LINE__);
/* DBRUN(BCE_FATAL, bce_breakpoint(sc)); */
- BCE_LOCK(sc);
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ sc->bce_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
bce_init_locked(sc);
- ifp->if_oerrors++;
- BCE_UNLOCK(sc);
+ sc->bce_ifp->if_oerrors++;
}
@@ -5514,8 +5520,9 @@ bce_stats_update(struct bce_softc *sc)
static void
-bce_tick_locked(struct bce_softc *sc)
+bce_tick(void *xsc)
{
+ struct bce_softc *sc = xsc;
struct mii_data *mii = NULL;
struct ifnet *ifp;
u32 msg;
@@ -5535,6 +5542,9 @@ bce_tick_locked(struct bce_softc *sc)
/* Update the statistics from the hardware statistics block. */
bce_stats_update(sc);
+ /* Check that chip hasn't hang. */
+ bce_watchdog(sc);
+
/* Schedule the next tick. */
callout_reset(
&sc->bce_stat_ch, /* callout */
@@ -5569,19 +5579,6 @@ bce_tick_locked_exit:
}
-static void
-bce_tick(void *xsc)
-{
- struct bce_softc *sc;
-
- sc = xsc;
-
- BCE_LOCK(sc);
- bce_tick_locked(sc);
- BCE_UNLOCK(sc);
-}
-
-
#ifdef BCE_DEBUG
/****************************************************************************/
/* Allows the driver state to be dumped through the sysctl interface. */
diff --git a/sys/dev/bce/if_bcereg.h b/sys/dev/bce/if_bcereg.h
index ec37324..e268dc8 100644
--- a/sys/dev/bce/if_bcereg.h
+++ b/sys/dev/bce/if_bcereg.h
@@ -4755,6 +4755,8 @@ struct bce_softc
int bce_link;
struct callout bce_stat_ch;
+ int watchdog_timer; /* ticks until chip reset */
+
/* Frame size and mbuf allocation size for RX frames. */
u32 max_frame_size;
int mbuf_alloc_size;
OpenPOWER on IntegriCloud