- 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
This commit is contained in:
Xin LI 2007-01-11 03:17:28 +00:00
parent 0fb18ca82e
commit 5411f54447
2 changed files with 28 additions and 29 deletions

View File

@ -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(struct ifnet *ifp, u_long command, caddr_t data)
/* 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(struct bce_softc *sc)
}
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. */

View File

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