Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/broadcom If IFF_LINK2 is set, copy all transmit...



details:   https://anonhg.NetBSD.org/src/rev/949dec442393
branches:  trunk
changeset: 782395:949dec442393
user:      matt <matt%NetBSD.org@localhost>
date:      Thu Nov 01 21:33:12 2012 +0000

description:
If IFF_LINK2 is set, copy all transmitted packets into a single mbuf to
avoid DMA corruption problems with chained buffers.
Fix various conditions with setting INTMASK.

diffstat:

 sys/arch/arm/broadcom/bcm53xx_eth.c |  59 ++++++++++++++++++++++++++----------
 1 files changed, 43 insertions(+), 16 deletions(-)

diffs (179 lines):

diff -r 99dc7a0cb85f -r 949dec442393 sys/arch/arm/broadcom/bcm53xx_eth.c
--- a/sys/arch/arm/broadcom/bcm53xx_eth.c       Thu Nov 01 21:29:42 2012 +0000
+++ b/sys/arch/arm/broadcom/bcm53xx_eth.c       Thu Nov 01 21:33:12 2012 +0000
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: bcm53xx_eth.c,v 1.14 2012/10/26 05:28:41 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: bcm53xx_eth.c,v 1.15 2012/11/01 21:33:12 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -138,7 +138,7 @@
 
        uint32_t sc_maxfrm;
        uint32_t sc_cmdcfg;
-       volatile uint32_t sc_intmask;
+       uint32_t sc_intmask;
        uint32_t sc_rcvlazy;
        volatile uint32_t sc_soft_flags;
 #define        SOFT_RXINTR             0x01
@@ -1381,6 +1381,31 @@
                } else {
                        txq->txq_next = NULL;
                }
+               /*
+                * If LINK2 is set and this packet uses multiple mbufs,
+                * consolidate it into a single mbuf.
+                */
+               if (m->m_next != NULL && (sc->sc_if.if_flags & IFF_LINK2)) {
+                       struct mbuf *m0 = m_gethdr(M_DONTWAIT, m->m_type);
+                       if (m0 == NULL) {
+                               txq->txq_next = m;
+                               return true;
+                       }
+                       M_COPY_PKTHDR(m0, m);
+                       MCLAIM(m0, m->m_owner);
+                       if (m0->m_pkthdr.len > MHLEN) {
+                               MCLGET(m0, M_DONTWAIT);
+                               if ((m0->m_flags & M_EXT) == 0) {
+                                       m_freem(m0);
+                                       txq->txq_next = m;
+                                       return true;
+                               }
+                       }
+                       m0->m_len = m->m_pkthdr.len;
+                       m_copydata(m, 0, m0->m_len, mtod(m0, void *));
+                       m_freem(m);
+                       m = m0;
+               }
                int error = bcmeth_txq_map_load(sc, txq, m);
                if (error) {
                        aprint_error_dev(sc->sc_dev,
@@ -1566,11 +1591,12 @@
 
        mutex_enter(sc->sc_hwlock);
 
+       uint32_t intmask = sc->sc_intmask;
        sc->sc_ev_intr.ev_count++;
 
        for (;;) {
                uint32_t intstatus = bcmeth_read_4(sc, GMAC_INTSTATUS);
-               intstatus &= sc->sc_intmask;
+               intstatus &= intmask;
                bcmeth_write_4(sc, GMAC_INTSTATUS, intstatus);  /* write 1 to clear */
                if (intstatus == 0) {
                        break;
@@ -1581,8 +1607,7 @@
 #endif
                if (intstatus & RCVINT) {
                        struct bcmeth_rxqueue * const rxq = &sc->sc_rxq;
-                       intstatus &= ~RCVINT;
-                       atomic_and_32(&sc->sc_intmask, (uint32_t)~RCVINT);
+                       intmask &= ~RCVINT;
 
                        uint32_t rcvsts0 = bcmeth_read_4(sc, rxq->rxq_reg_rcvsts0);
                        uint32_t descs = __SHIFTOUT(rcvsts0, RCV_CURRDSCR);
@@ -1610,17 +1635,16 @@
                }
 
                if (intstatus & XMTINT_0) {
-                       intstatus &= ~XMTINT_0;
-                       atomic_and_32(&sc->sc_intmask, (uint32_t)~XMTINT_0);
+                       intmask &= ~XMTINT_0;
                        soft_flags |= SOFT_TXINTR;
                }
 
                if (intstatus & RCVDESCUF) {
-                       intstatus &= ~RCVDESCUF;
-                       atomic_and_32(&sc->sc_intmask, (uint32_t)~RCVDESCUF);
+                       intmask &= ~RCVDESCUF;
                        work_flags |= WORK_RXUNDERFLOW;
                }
 
+               intstatus &= intmask;
                if (intstatus) {
                        aprint_error_dev(sc->sc_dev,
                            "intr: intstatus=%#x\n", intstatus);
@@ -1638,14 +1662,13 @@
                            bcmeth_read_4(sc, sc->sc_txq.txq_reg_xmtptr),
                            bcmeth_read_4(sc, sc->sc_txq.txq_reg_xmtsts0),
                            bcmeth_read_4(sc, sc->sc_txq.txq_reg_xmtsts1));
-                       Debugger();
-                       atomic_and_32(&sc->sc_intmask, ~intstatus);
+                       intmask &= ~intstatus;
                        work_flags |= WORK_REINIT;
                        break;
                }
        }
 
-       if (work_flags | soft_flags) {
+       if (intmask != sc->sc_intmask) {
                bcmeth_write_4(sc, GMAC_INTMASK, sc->sc_intmask);
        }
 
@@ -1675,6 +1698,7 @@
 {
        struct bcmeth_softc * const sc = arg;
        struct ifnet * const ifp = &sc->sc_if;
+       uint32_t intmask = 0;
 
        mutex_enter(sc->sc_lock);
 
@@ -1695,7 +1719,7 @@
                } else {
                        ifp->if_flags &= ~IFF_OACTIVE;
                }
-               atomic_or_32(&sc->sc_intmask, XMTINT_0);
+               intmask |= XMTINT_0;
        }
 
        if (soft_flags & SOFT_RXINTR) {
@@ -1703,12 +1727,13 @@
                 * Let's consume 
                 */
                bcmeth_rxq_consume(sc, &sc->sc_rxq);
-               atomic_or_32(&sc->sc_intmask, RCVINT);
+               intmask |= RCVINT;
        }
 
        if (ifp->if_flags & IFF_RUNNING) {
                bcmeth_rxq_produce(sc, &sc->sc_rxq);
                mutex_spin_enter(sc->sc_hwlock);
+               sc->sc_intmask |= intmask;
                bcmeth_write_4(sc, GMAC_INTMASK, sc->sc_intmask);
                mutex_spin_exit(sc->sc_hwlock);
        }
@@ -1721,6 +1746,7 @@
 {
        struct bcmeth_softc * const sc = arg;
        struct ifnet * const ifp = &sc->sc_if;
+       uint32_t intmask = 0;
 
        mutex_enter(sc->sc_lock);
 
@@ -1741,7 +1767,7 @@
                if (threshold >= rxq->rxq_last - rxq->rxq_first) {
                        threshold = rxq->rxq_last - rxq->rxq_first - 1;
                } else {
-                       atomic_or_32(&sc->sc_intmask, RCVDESCUF);
+                       intmask |= RCVDESCUF;
                }
                aprint_normal_dev(sc->sc_dev,
                    "increasing receive buffers from %zu to %zu\n",
@@ -1754,12 +1780,13 @@
                 * Let's consume 
                 */
                bcmeth_rxq_consume(sc, &sc->sc_rxq);
-               atomic_or_32(&sc->sc_intmask, RCVINT);
+               intmask |= RCVINT;
        }
 
        if (ifp->if_flags & IFF_RUNNING) {
                bcmeth_rxq_produce(sc, &sc->sc_rxq);
                mutex_spin_enter(sc->sc_hwlock);
+               sc->sc_intmask |= intmask;
                bcmeth_write_4(sc, GMAC_INTMASK, sc->sc_intmask);
                mutex_spin_exit(sc->sc_hwlock);
        }



Home | Main Index | Thread Index | Old Index