Port-sgimips archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: mec and resets



jacereda%gmail.com@localhost 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


Home | Main Index | Thread Index | Old Index