Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic More interrupt handling, more debug code, less ma...



details:   https://anonhg.NetBSD.org/src/rev/bea1d5e1a09e
branches:  trunk
changeset: 802920:bea1d5e1a09e
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Oct 08 18:24:21 2014 +0000

description:
More interrupt handling, more debug code, less magic numbers.

diffstat:

 sys/dev/ic/dwc_gmac.c |  209 +++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 172 insertions(+), 37 deletions(-)

diffs (truncated from 343 to 300 lines):

diff -r 0d5919208352 -r bea1d5e1a09e sys/dev/ic/dwc_gmac.c
--- a/sys/dev/ic/dwc_gmac.c     Wed Oct 08 18:23:32 2014 +0000
+++ b/sys/dev/ic/dwc_gmac.c     Wed Oct 08 18:24:21 2014 +0000
@@ -39,7 +39,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.7 2014/09/14 18:28:37 martin Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.8 2014/10/08 18:24:21 martin Exp $");
 
 /* #define     DWC_GMAC_DEBUG  1 */
 
@@ -86,17 +86,37 @@
 static void dwc_gmac_start(struct ifnet *ifp);
 static int dwc_gmac_queue(struct dwc_gmac_softc *sc, struct mbuf *m0);
 static int dwc_gmac_ioctl(struct ifnet *, u_long, void *);
-
+static void dwc_gmac_tx_intr(struct dwc_gmac_softc *sc);
+static void dwc_gmac_rx_intr(struct dwc_gmac_softc *sc);
 
 #define        TX_DESC_OFFSET(N)       ((AWGE_RX_RING_COUNT+(N)) \
                                    *sizeof(struct dwc_gmac_dev_dmadesc))
+#define        TX_NEXT(N)              (((N)+1) & (AWGE_TX_RING_COUNT-1))
 
 #define RX_DESC_OFFSET(N)      ((N)*sizeof(struct dwc_gmac_dev_dmadesc))
+#define        RX_NEXT(N)              (((N)+1) & (AWGE_RX_RING_COUNT-1))
+
+
+
+#define        GMAC_DEF_DMA_INT_MASK   (GMAC_DMA_INT_TIE|GMAC_DMA_INT_RIE| \
+                               GMAC_DMA_INT_NIE|GMAC_DMA_INT_AIE| \
+                               GMAC_DMA_INT_FBE|GMAC_DMA_INT_UNE)
+
+#define        GMAC_DMA_INT_ERRORS     (GMAC_DMA_INT_AIE|GMAC_DMA_INT_ERE| \
+                               GMAC_DMA_INT_FBE|GMAC_DMA_INT_ETE| \
+                               GMAC_DMA_INT_RWE|GMAC_DMA_INT_RUE| \
+                               GMAC_DMA_INT_UNE|GMAC_DMA_INT_OVE| \
+                               GMAC_DMA_INT_TJE|GMAC_DMA_INT_TUE)
+
+#define        AWIN_DEF_MAC_INTRMASK   \
+       (AWIN_GMAC_MAC_INT_TSI | AWIN_GMAC_MAC_INT_ANEG |       \
+       AWIN_GMAC_MAC_INT_LINKCHG | AWIN_GMAC_MAC_INT_RGSMII)
 
 
 #ifdef DWC_GMAC_DEBUG
 static void dwc_gmac_dump_dma(struct dwc_gmac_softc *sc);
 static void dwc_gmac_dump_tx_desc(struct dwc_gmac_softc *sc);
+static void dwc_dump_and_abort(struct dwc_gmac_softc *sc, const char *msg);
 #endif
 
 void
@@ -127,8 +147,10 @@
                 * try to read one from the current filter setup,
                 * before resetting the chip.
                 */
-               maclo = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_ADDR0LO);
-               machi = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_ADDR0HI);
+               maclo = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+                   AWIN_GMAC_MAC_ADDR0LO);
+               machi = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+                   AWIN_GMAC_MAC_ADDR0HI);
                enaddr[0] = maclo & 0x0ff;
                enaddr[1] = (maclo >> 8) & 0x0ff;
                enaddr[2] = (maclo >> 16) & 0x0ff;
@@ -137,10 +159,6 @@
                enaddr[5] = (machi >> 8) & 0x0ff;
        }
 
-#ifdef DWC_GMAC_DEBUG
-       dwc_gmac_dump_dma(sc);
-#endif
-
        /*
         * Init chip and do intial setup
         */
@@ -210,8 +228,10 @@
        /*
         * Enable interrupts
         */
-       bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTR, AWIN_DEF_MAC_INTRMASK);
-       bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE, GMAC_DEF_DMA_INT_MASK);
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTR,
+           AWIN_DEF_MAC_INTRMASK);
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE,
+           GMAC_DEF_DMA_INT_MASK);
 
        return;
 
@@ -364,7 +384,7 @@
 
                desc = &sc->sc_rxq.r_desc[i];
                desc->ddesc_data = htole32(physaddr);
-               next = (i+1) % AWGE_RX_RING_COUNT;
+               next = RX_NEXT(i);
                desc->ddesc_next = htole32(ring->r_physaddr 
                    + next * sizeof(*desc));
                desc->ddesc_cntl = htole32(
@@ -528,7 +548,7 @@
                }
                ring->t_desc[i].ddesc_next = htole32(
                    ring->t_physaddr + sizeof(struct dwc_gmac_dev_dmadesc)
-                   *((i+1)%AWGE_TX_RING_COUNT));
+                   *TX_NEXT(i));
        }
 
        return 0;
@@ -706,11 +726,6 @@
                    bus_space_read_4(sc->sc_bst, sc->sc_bsh,
                        AWIN_GMAC_DMA_OPMODE) | GMAC_DMA_OP_TXSTART);
        }
-
-#ifdef DWC_GMAC_DEBUG
-       dwc_gmac_dump_dma(sc);
-       dwc_gmac_dump_tx_desc(sc);
-#endif
 }
 
 static void
@@ -745,6 +760,11 @@
        uint32_t flags, len;
        int error, i, first;
 
+#ifdef DWC_GMAC_DEBUG
+       aprint_normal_dev(sc->sc_dev,
+           "dwc_gmac_queue: adding mbuf chain %p\n", m0);
+#endif
+
        first = sc->sc_txq.t_cur;
        map = sc->sc_txq.t_data[first].td_map;
        flags = 0;
@@ -763,23 +783,24 @@
        }
 
        data = NULL;
-       flags = DDESC_CNTL_TXFIRST|DDESC_CNTL_TXINT|DDESC_CNTL_TXCHAIN;
+       flags = DDESC_CNTL_TXFIRST|DDESC_CNTL_TXCHAIN;
        for (i = 0; i < map->dm_nsegs; i++) {
                data = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
-
-#ifdef DWC_GMAC_DEBUG
-               aprint_normal_dev(sc->sc_dev, "enqueing desc #%d data %08lx "
-                   "len %lu\n", sc->sc_txq.t_cur,
-                   (unsigned long)map->dm_segs[i].ds_addr,
-                   (unsigned long)map->dm_segs[i].ds_len);
-#endif
-
                desc = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
 
                desc->ddesc_data = htole32(map->dm_segs[i].ds_addr);
                len = __SHIFTIN(map->dm_segs[i].ds_len,DDESC_CNTL_SIZE1MASK);
                if (i == map->dm_nsegs-1)
-                       flags |= DDESC_CNTL_TXLAST;
+                       flags |= DDESC_CNTL_TXLAST|DDESC_CNTL_TXINT;
+
+#ifdef DWC_GMAC_DEBUG
+               aprint_normal_dev(sc->sc_dev, "enqueing desc #%d data %08lx "
+                   "len %lu (flags: %08x, len: %08x)\n", sc->sc_txq.t_cur,
+                   (unsigned long)map->dm_segs[i].ds_addr,
+                   (unsigned long)map->dm_segs[i].ds_len,
+                   flags, len);
+#endif
+
                desc->ddesc_cntl = htole32(len|flags);
                flags &= ~DDESC_CNTL_TXFIRST;
 
@@ -789,10 +810,9 @@
                 */
                if (i)
                        desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+
                sc->sc_txq.t_queued++;
-
-               sc->sc_txq.t_cur = (sc->sc_txq.t_cur + 1)
-                   & (AWGE_TX_RING_COUNT-1);
+               sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
        }
 
        /* Pass first to device */
@@ -846,29 +866,105 @@
        return error;
 }
 
+static void
+dwc_gmac_tx_intr(struct dwc_gmac_softc *sc)
+{
+       struct dwc_gmac_tx_data *data;
+       struct dwc_gmac_dev_dmadesc *desc;
+       uint32_t flags;
+       int i;
+
+       for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0;
+           i = TX_NEXT(i), sc->sc_txq.t_queued--) {
+
+#ifdef DWC_GMAC_DEBUG
+               aprint_normal_dev(sc->sc_dev,
+                   "dwc_gmac_tx_intr: checking desc #%d (t_queued: %d)\n",
+                   i, sc->sc_txq.t_queued);
+#endif
+
+               desc = &sc->sc_txq.t_desc[i];
+               dwc_gmac_txdesc_sync(sc, i, i+1,
+                   BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+               flags = le32toh(desc->ddesc_status);
+               if (flags & DDESC_STATUS_OWNEDBYDEV)
+                       break;
+               data = &sc->sc_txq.t_data[i];
+               if (data->td_m == NULL)
+                       continue;
+               sc->sc_ec.ec_if.if_opackets++;
+               bus_dmamap_sync(sc->sc_dmat, data->td_active, 0,
+                   data->td_active->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+               bus_dmamap_unload(sc->sc_dmat, data->td_active);
+
+#ifdef DWC_GMAC_DEBUG
+               aprint_normal_dev(sc->sc_dev,
+                   "dwc_gmac_tx_intr: done with packet at desc #%d, "
+                   "freeing mbuf %p\n", i, data->td_m);
+#endif
+
+               m_freem(data->td_m);
+               data->td_m = NULL;
+       }
+
+       sc->sc_txq.t_next = i;
+
+       if (sc->sc_txq.t_queued < AWGE_TX_RING_COUNT) {
+               sc->sc_ec.ec_if.if_flags &= ~IFF_OACTIVE;
+       }
+}
+
+static void
+dwc_gmac_rx_intr(struct dwc_gmac_softc *sc)
+{
+#ifdef DWC_GMAC_DEBUG
+       aprint_normal_dev(sc->sc_dev, "rx intr\n");
+       /* XXX */
+#endif
+}
+
 int
 dwc_gmac_intr(struct dwc_gmac_softc *sc)
 {
        uint32_t status, dma_status;
+       int rv = 0;
 
        status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTR);
        if (status & AWIN_GMAC_MII_IRQ) {
                (void)bus_space_read_4(sc->sc_bst, sc->sc_bsh,
                    AWIN_GMAC_MII_STATUS);
+               rv = 1;
                mii_pollstat(&sc->sc_mii);
        }
 
        dma_status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
            AWIN_GMAC_DMA_STATUS);
 
-printf("%s: INTR status: %08x, DMA status: %08x\n", device_xname(sc->sc_dev),
-    status, dma_status);
+       if (dma_status & (GMAC_DMA_INT_NIE|GMAC_DMA_INT_AIE))
+               rv = 1;
+
+       if (dma_status & GMAC_DMA_INT_TIE)
+               dwc_gmac_tx_intr(sc);
+
+       if (dma_status & GMAC_DMA_INT_RIE)
+               dwc_gmac_rx_intr(sc);
 
-static size_t cnt = 0;
-if (++cnt > 20)
-       panic("enough now");
+       /*
+        * Check error conditions
+        */
+       if (dma_status & GMAC_DMA_INT_ERRORS) {
+               sc->sc_ec.ec_if.if_oerrors++;
+#ifdef DWC_GMAC_DEBUG
+               dwc_dump_and_abort(sc, "interrupt error condition");
+#endif
+       }
 
-       return 1;
+       /* ack interrupt */
+       if (dma_status)
+               bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+                   AWIN_GMAC_DMA_STATUS, dma_status & GMAC_DMA_INT_MASK);
+
+       return rv;
 }
 
 #ifdef DWC_GMAC_DEBUG
@@ -906,7 +1002,9 @@
 {
        int i;
 
-       aprint_normal_dev(sc->sc_dev, " TX DMA descriptors:\n");
+       aprint_normal_dev(sc->sc_dev, "TX queue: cur=%d, next=%d, queued=%d\n",
+           sc->sc_txq.t_cur, sc->sc_txq.t_next, sc->sc_txq.t_queued);
+       aprint_normal_dev(sc->sc_dev, "TX DMA descriptors:\n");
        for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
                struct dwc_gmac_dev_dmadesc *desc = &sc->sc_txq.t_desc[i];



Home | Main Index | Thread Index | Old Index