Re: mec and resets
Izumi Tsutsui <[email protected]>
| Newsgroups | gmane.os.netbsd.ports.sgimips |
|---|---|
| Message-ID | <[email protected]> |
[email protected] wrote: > I copied 4 times base.tgz to the O2 and thought it was fixed, but > starting another scp the opposite direction (O2->Mac) while the scp > Mac->O2 was in progress hanged the machine. Hmm. Do you use 100baseTX or 10baseT? Anyway, could you try this one after reverting all if_mec.c changes? This one includes the following changes from the last one: - handle timeout in mec_intr() (and shows which interrupts linger on) - remove (revert) rxptr check in mec_rxintr() --- Index: if_mec.c =================================================================== RCS file: /cvsroot/src/sys/arch/sgimips/mace/if_mec.c,v retrieving revision 1.20 diff -u -r1.20 if_mec.c --- if_mec.c 14 May 2008 13:29:28 -0000 1.20 +++ if_mec.c 5 Aug 2008 14:18:50 -0000 @@ -125,6 +125,7 @@ #define MEC_NTXDESC 64 #define MEC_NTXDESC_MASK (MEC_NTXDESC - 1) #define MEC_NEXTTX(x) (((x) + 1) & MEC_NTXDESC_MASK) +#define MEC_NTXDESC_RSVD 4 /* * software state for TX @@ -342,7 +343,7 @@ static int mec_intr(void *arg); static void mec_stop(struct ifnet *, int); static void mec_rxintr(struct mec_softc *); -static void mec_txintr(struct mec_softc *); +static void mec_txintr(struct mec_softc *, uint32_t); static void mec_shutdown(void *); CFATTACH_DECL_NEW(mec, sizeof(struct mec_softc), @@ -836,7 +837,8 @@ break; m = NULL; - if (sc->sc_txpending == MEC_NTXDESC) { + if (sc->sc_txpending == MEC_NTXDESC - 1) { + /* preserve the last entry to avoid wraparound */ break; } @@ -1223,14 +1225,14 @@ bus_space_tag_t st = sc->sc_st; bus_space_handle_t sh = sc->sc_sh; struct ifnet *ifp = &sc->sc_ethercom.ec_if; - uint32_t statreg, statack, dmac; - int handled, sent; + uint32_t statreg, statack, txptr; + int timeout, handled, sent; DPRINTF(MEC_DEBUG_INTR, ("mec_intr: called\n")); handled = sent = 0; - for (;;) { + for (timeout = 10000; timeout > 0; timeout--) { statreg = bus_space_read_8(st, sh, MEC_INT_STATUS); DPRINTF(MEC_DEBUG_INTR, @@ -1249,18 +1251,15 @@ mec_rxintr(sc); } - dmac = bus_space_read_8(st, sh, MEC_DMA_CONTROL); - DPRINTF(MEC_DEBUG_INTR, - ("mec_intr: DMA_CONT = 0x%08x\n", dmac)); - if (statack & (MEC_INT_TX_EMPTY | MEC_INT_TX_PACKET_SENT | MEC_INT_TX_ABORT)) { - mec_txintr(sc); + txptr = (statreg & MEC_INT_TX_RING_BUFFER_ALIAS) + >> MEC_INT_TX_RING_BUFFER_SHIFT; + mec_txintr(sc, txptr); sent = 1; - if ((statack & MEC_INT_TX_EMPTY) != 0 && - (dmac & MEC_DMA_TX_INT_ENABLE) != 0) { + if ((statack & MEC_INT_TX_EMPTY) != 0) { /* * disable TX interrupt to stop * TX empty interrupt @@ -1282,7 +1281,13 @@ } } - if (sent) { + if (timeout == 0) { + printf("%s: sticky interrupts (statreg = 0x%08x), resetting\n", + device_xname(sc->sc_dev), statreg); + mec_init(ifp); + } + + if (sent && IFQ_IS_EMPTY(&ifp->if_snd)) { /* try to get more packets going */ mec_start(ifp); } @@ -1417,7 +1422,7 @@ } static void -mec_txintr(struct mec_softc *sc) +mec_txintr(struct mec_softc *sc, uint32_t txptr) { struct ifnet *ifp = &sc->sc_ethercom.ec_if; struct mec_txdesc *txd; @@ -1427,11 +1432,9 @@ int i; u_int col; - ifp->if_flags &= ~IFF_OACTIVE; - DPRINTF(MEC_DEBUG_TXINTR, ("mec_txintr: called\n")); - for (i = sc->sc_txdirty; sc->sc_txpending != 0; + for (i = sc->sc_txdirty; i != txptr && sc->sc_txpending != 0; i = MEC_NEXTTX(i), sc->sc_txpending--) { txd = &sc->sc_txdesc[i]; @@ -1478,6 +1481,8 @@ /* cancel the watchdog timer if there are no pending TX packets */ if (sc->sc_txpending == 0) ifp->if_timer = 0; + if (sc->sc_txpending < MEC_NTXDESC - MEC_NTXDESC_RSVD) + ifp->if_flags &= ~IFF_OACTIVE; } static void --- Izumi Tsutsui