Source-Changes-HG archive

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

[src/netbsd-6]: src/sys/dev/marvell Apply patch (requested by msaitoh in tick...



details:   https://anonhg.NetBSD.org/src/rev/102a027be559
branches:  netbsd-6
changeset: 775474:102a027be559
user:      riz <riz%NetBSD.org@localhost>
date:      Tue Nov 20 22:26:03 2012 +0000

description:
Apply patch (requested by msaitoh in ticket #671):

sys/dev/marvell/if_mvgbe.c              1.19-1.23, 1.26-1.31
sys/dev/marvell/mvgbereg.h              1.4-1.5, 1.7

Add missing bus_dmamap_sync() for the RX buffer.
Fix device timeout problem.
Fix broken hardware checksumming.
Fix a bug that kernel panics when the system get a packet while calling
mvgbe_stop (via ifconfig down).
Add missing mii_tick() call.
Change style a bit.
Don't use M_HASFCS flag.
When an interrput is link change, notify link change to mii layer using
mii_pollstat().
Fix a bug that the alignment of jumbo buffer(MVGBE_JLEN) is miscalculated.

diffstat:

 sys/dev/marvell/if_mvgbe.c |  176 ++++++++++++++++++++++++++++++++------------
 sys/dev/marvell/mvgbereg.h |    8 +-
 2 files changed, 133 insertions(+), 51 deletions(-)

diffs (truncated from 457 to 300 lines):

diff -r 13c2db519711 -r 102a027be559 sys/dev/marvell/if_mvgbe.c
--- a/sys/dev/marvell/if_mvgbe.c        Tue Nov 20 22:19:20 2012 +0000
+++ b/sys/dev/marvell/if_mvgbe.c        Tue Nov 20 22:26:03 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_mvgbe.c,v 1.16 2012/02/02 19:43:04 tls Exp $        */
+/*     $NetBSD: if_mvgbe.c,v 1.16.2.1 2012/11/20 22:26:03 riz Exp $    */
 /*
  * Copyright (c) 2007, 2008 KIYOHARA Takashi
  * All rights reserved.
@@ -25,13 +25,15 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.16 2012/02/02 19:43:04 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mvgbe.c,v 1.16.2.1 2012/11/20 22:26:03 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
+#include <sys/callout.h>
 #include <sys/device.h>
 #include <sys/endian.h>
 #include <sys/errno.h>
+#include <sys/kernel.h>
 #include <sys/kmem.h>
 #include <sys/mutex.h>
 #include <sys/sockio.h>
@@ -89,7 +91,9 @@
        (MVGBE_RX_RING_CNT + 1) % MVGBE_RX_RING_CNT);
 
 #define MVGBE_JSLOTS           384     /* XXXX */
-#define MVGBE_JLEN             ((MVGBE_MRU + MVGBE_RXBUF_ALIGN)&~MVGBE_RXBUF_MASK)
+#define MVGBE_JLEN \
+    ((MVGBE_MRU + MVGBE_HWHEADER_SIZE + MVGBE_RXBUF_ALIGN - 1) & \
+    ~MVGBE_RXBUF_MASK)
 #define MVGBE_NTXSEG           30
 #define MVGBE_JPAGESZ          PAGE_SIZE
 #define MVGBE_RESID \
@@ -195,17 +199,20 @@
 
        bus_space_tag_t sc_iot;
        bus_space_handle_t sc_ioh;
-       bus_space_handle_t sc_dafh;             /* dest address filter handle */
+       bus_space_handle_t sc_dafh;     /* dest address filter handle */
        bus_dma_tag_t sc_dmat;
 
        struct ethercom sc_ethercom;
        struct mii_data sc_mii;
        u_int8_t sc_enaddr[ETHER_ADDR_LEN];     /* station addr */
 
+       callout_t sc_tick_ch;           /* tick callout */
+
        struct mvgbe_chain_data sc_cdata;
        struct mvgbe_ring_data *sc_rdata;
        bus_dmamap_t sc_ring_map;
        int sc_if_flags;
+       int sc_wdogsoft;
 
        LIST_HEAD(__mvgbe_jfreehead, mvgbe_jpool_entry) sc_jfree_listhead;
        LIST_HEAD(__mvgbe_jinusehead, mvgbe_jpool_entry) sc_jinuse_listhead;
@@ -235,6 +242,7 @@
 static int mvgbe_match(device_t, struct cfdata *, void *);
 static void mvgbe_attach(device_t, device_t, void *);
 
+static void mvgbe_tick(void *);
 static int mvgbe_intr(void *);
 
 static void mvgbe_start(struct ifnet *);
@@ -336,7 +344,7 @@
 static void
 mvgbec_attach(device_t parent, device_t self, void *aux)
 {
-       struct mvgbec_softc *sc = device_private(self);
+       struct mvgbec_softc *csc = device_private(self);
        struct marvell_attach_args *mva = aux, gbea;
        struct mvgbe_softc *port;
        struct mii_softc *mii;
@@ -347,10 +355,10 @@
        aprint_naive("\n");
        aprint_normal(": Marvell Gigabit Ethernet Controller\n");
 
-       sc->sc_dev = self;
-       sc->sc_iot = mva->mva_iot;
+       csc->sc_dev = self;
+       csc->sc_iot = mva->mva_iot;
        if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset,
-           mva->mva_size, &sc->sc_ioh)) {
+           mva->mva_size, &csc->sc_ioh)) {
                aprint_error_dev(self, "Cannot map registers\n");
                return;
        }
@@ -359,15 +367,15 @@
                mvgbec0 = self;
                
        phyaddr = 0;
-       MVGBE_WRITE(sc, MVGBE_PHYADDR, phyaddr);
+       MVGBE_WRITE(csc, MVGBE_PHYADDR, phyaddr);
 
-       mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET);
+       mutex_init(&csc->sc_mtx, MUTEX_DEFAULT, IPL_NET);
 
        /* Disable and clear Gigabit Ethernet Unit interrupts */
-       MVGBE_WRITE(sc, MVGBE_EUIM, 0);
-       MVGBE_WRITE(sc, MVGBE_EUIC, 0);
+       MVGBE_WRITE(csc, MVGBE_EUIM, 0);
+       MVGBE_WRITE(csc, MVGBE_EUIC, 0);
 
-       mvgbec_wininit(sc);
+       mvgbec_wininit(csc);
 
        memset(&gbea, 0, sizeof(gbea));
        for (i = 0; i < __arraycount(mvgbe_ports); i++) {
@@ -375,17 +383,17 @@
                    mvgbe_ports[i].unit != mva->mva_unit)
                        continue;
 
-               sc->sc_flags = mvgbe_ports[i].flags;
+               csc->sc_flags = mvgbe_ports[i].flags;
 
                for (j = 0; j < mvgbe_ports[i].ports; j++) {
                        gbea.mva_name = "mvgbe";
                        gbea.mva_model = mva->mva_model;
-                       gbea.mva_iot = sc->sc_iot;
-                       gbea.mva_ioh = sc->sc_ioh;
+                       gbea.mva_iot = csc->sc_iot;
+                       gbea.mva_ioh = csc->sc_ioh;
                        gbea.mva_unit = j;
                        gbea.mva_dmat = mva->mva_dmat;
                        gbea.mva_irq = mvgbe_ports[i].irqs[j];
-                       child = config_found_sm_loc(sc->sc_dev, "mvgbec", NULL,
+                       child = config_found_sm_loc(csc->sc_dev, "mvgbec", NULL,
                            &gbea, mvgbec_print, mvgbec_search);
                        if (child) {
                                port = device_private(child);
@@ -395,7 +403,7 @@
                }
                break;
        }
-       MVGBE_WRITE(sc, MVGBE_PHYADDR, phyaddr);
+       MVGBE_WRITE(csc, MVGBE_PHYADDR, phyaddr);
 }
 
 static int
@@ -629,6 +637,8 @@
        sc->sc_dev = self;
        sc->sc_port = mva->mva_unit;
        sc->sc_iot = mva->mva_iot;
+       callout_init(&sc->sc_tick_ch, 0);
+       callout_setfunc(&sc->sc_tick_ch, mvgbe_tick, sc);
        if (bus_space_subregion(mva->mva_iot, mva->mva_ioh,
            MVGBE_PORTR_BASE + mva->mva_unit * MVGBE_PORTR_SIZE,
            MVGBE_PORTR_SIZE, &sc->sc_ioh)) {
@@ -799,6 +809,21 @@
 }
 
 
+static void
+mvgbe_tick(void *arg)
+{
+       struct mvgbe_softc *sc = arg;
+       struct mii_data *mii = &sc->sc_mii;
+       int s;
+
+       s = splnet();
+       mii_tick(mii);
+       /* Need more work */
+       splx(s);
+
+       callout_schedule(&sc->sc_tick_ch, hz);
+}
+
 static int
 mvgbe_intr(void *arg)
 {
@@ -822,6 +847,9 @@
 
                claimed = 1;
 
+               if (!(ifp->if_flags & IFF_RUNNING))
+                       break;
+
                if (ice & MVGBE_ICE_LINKCHG) {
                        if (MVGBE_READ(sc, MVGBE_PS) & MVGBE_PS_LINKUP) {
                                /* Enable port RX and TX. */
@@ -831,6 +859,9 @@
                                MVGBE_WRITE(sc, MVGBE_RQC, MVGBE_RQC_DISQ(0));
                                MVGBE_WRITE(sc, MVGBE_TQC, MVGBE_TQC_DISQ);
                        }
+
+                       /* Notify link change event to mii layer */
+                       mii_pollstat(&sc->sc_mii);
                }
 
                if (ic & (MVGBE_IC_RXBUF | MVGBE_IC_RXERROR))
@@ -901,7 +932,8 @@
                /*
                 * Set a timeout in case the chip goes out to lunch.
                 */
-               ifp->if_timer = 5;
+               ifp->if_timer = 1;
+               sc->sc_wdogsoft = 1;
        }
 }
 
@@ -1045,6 +1077,8 @@
            MVGBE_ICE_TXERR |
            MVGBE_ICE_LINKCHG);
 
+       callout_schedule(&sc->sc_tick_ch, hz);
+
        ifp->if_flags |= IFF_RUNNING;
        ifp->if_flags &= ~IFF_OACTIVE;
 
@@ -1056,12 +1090,15 @@
 mvgbe_stop(struct ifnet *ifp, int disable)
 {
        struct mvgbe_softc *sc = ifp->if_softc;
+       struct mvgbec_softc *csc = device_private(device_parent(sc->sc_dev));
        struct mvgbe_chain_data *cdata = &sc->sc_cdata;
        uint32_t reg;
        int i, cnt;
 
        DPRINTFN(2, ("mvgbe_stop\n"));
 
+       callout_stop(&sc->sc_tick_ch);
+
        /* Stop Rx port activity. Check port Rx activity. */
        reg = MVGBE_READ(sc, MVGBE_RQC);
        if (reg & MVGBE_RQC_ENQ_MASK)
@@ -1128,7 +1165,16 @@
        reg = MVGBE_READ(sc, MVGBE_PSC);
        MVGBE_WRITE(sc, MVGBE_PSC, reg & ~MVGBE_PSC_PORTEN);
 
-       /* Disable interrupts */
+       /*
+        * Disable and clear interrupts
+        * 0) controller interrupt
+        * 1) port interrupt cause
+        * 2) port interrupt mask
+        */
+       MVGBE_WRITE(csc, MVGBE_EUIM, 0);
+       MVGBE_WRITE(csc, MVGBE_EUIC, 0);
+       MVGBE_WRITE(sc, MVGBE_IC, 0);
+       MVGBE_WRITE(sc, MVGBE_ICE, 0);
        MVGBE_WRITE(sc, MVGBE_PIM, 0);
        MVGBE_WRITE(sc, MVGBE_PEIM, 0);
 
@@ -1160,11 +1206,22 @@
         */
        mvgbe_txeof(sc);
        if (sc->sc_cdata.mvgbe_tx_cnt != 0) {
-               aprint_error_ifnet(ifp, "watchdog timeout\n");
+               if (sc->sc_wdogsoft) {
+                       /*
+                        * There is race condition between CPU and DMA
+                        * engine. When DMA engine encounters queue end,
+                        * it clears MVGBE_TQC_ENQ bit.
+                        */
+                       MVGBE_WRITE(sc, MVGBE_TQC, MVGBE_TQC_ENQ);
+                       ifp->if_timer = 5;
+                       sc->sc_wdogsoft = 0;
+               } else {
+                       aprint_error_ifnet(ifp, "watchdog timeout\n");
 
-               ifp->if_oerrors++;
+                       ifp->if_oerrors++;
 
-               mvgbe_init(ifp);
+                       mvgbe_init(ifp);
+               }
        }
 }
 
@@ -1291,6 +1348,7 @@
        struct mvgbe_chain *c;
        struct mvgbe_rx_desc *r;
        int align;
+       vaddr_t offset;
 
        if (m == NULL) {
                void *buf = NULL;
@@ -1333,11 +1391,15 @@
        c = &sc->sc_cdata.mvgbe_rx_chain[i];
        r = c->mvgbe_desc;
        c->mvgbe_mbuf = m_new;
-       r->bufptr = dmamap->dm_segs[0].ds_addr +
-           (((vaddr_t)m_new->m_data - (vaddr_t)sc->sc_cdata.mvgbe_jumbo_buf));
+       offset = (vaddr_t)m_new->m_data - (vaddr_t)sc->sc_cdata.mvgbe_jumbo_buf;
+       r->bufptr = dmamap->dm_segs[0].ds_addr + offset;
        r->bufsize = MVGBE_JLEN & ~MVGBE_RXBUF_MASK;
        r->cmdsts = MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_ENABLE_INTERRUPT;
 
+       /* Invalidate RX buffer */
+       bus_dmamap_sync(sc->sc_dmat, dmamap, offset, r->bufsize,
+           BUS_DMASYNC_PREREAD);
+
        MVGBE_CDRXSYNC(sc, i, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
        return 0;
@@ -1582,7 +1644,8 @@
                f = &sc->sc_rdata->mvgbe_tx_ring[current];



Home | Main Index | Thread Index | Old Index