Source-Changes-HG archive

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

[src/trunk]: src/sys Apply patch from FUKAUMI Naoki to fix ring buffer handli...



details:   https://anonhg.NetBSD.org/src/rev/b081d0658841
branches:  trunk
changeset: 336279:b081d0658841
user:      martin <martin%NetBSD.org@localhost>
date:      Mon Feb 23 19:05:16 2015 +0000

description:
Apply patch from FUKAUMI Naoki to fix ring buffer handling when the
ring fills completely.

diffstat:

 sys/arch/arm/rockchip/rockchip_emac.c |  63 ++++++++++++++++++++--------------
 sys/dev/ic/dwc_gmac.c                 |  54 ++++++++++++++++-------------
 2 files changed, 67 insertions(+), 50 deletions(-)

diffs (truncated from 309 to 300 lines):

diff -r f4df68d570a8 -r b081d0658841 sys/arch/arm/rockchip/rockchip_emac.c
--- a/sys/arch/arm/rockchip/rockchip_emac.c     Mon Feb 23 17:05:58 2015 +0000
+++ b/sys/arch/arm/rockchip/rockchip_emac.c     Mon Feb 23 19:05:16 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rockchip_emac.c,v 1.11 2015/01/17 15:05:24 jmcneill Exp $ */
+/* $NetBSD: rockchip_emac.c,v 1.12 2015/02/23 19:05:16 martin Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -29,7 +29,7 @@
 #include "opt_rkemac.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rockchip_emac.c,v 1.11 2015/01/17 15:05:24 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rockchip_emac.c,v 1.12 2015/02/23 19:05:16 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -84,6 +84,7 @@
        bus_dmamap_t td_map;
        bus_dmamap_t td_active;
        struct mbuf *td_m;
+       int td_nbufs;
 };
 
 struct rkemac_txring {
@@ -574,6 +575,10 @@
                }
                IFQ_DEQUEUE(&ifp->if_snd, m0);
                bpf_mtap(ifp, m0);
+               if (sc->sc_txq.t_queued == RKEMAC_TX_RING_COUNT) {
+                       ifp->if_flags |= IFF_OACTIVE;
+                       break;
+               }
        }
 
        if (sc->sc_txq.t_queued != old) {
@@ -679,15 +684,14 @@
 static int
 rkemac_queue(struct rkemac_softc *sc, struct mbuf *m0)
 {
-       struct rkemac_txdesc *tx;
        struct rkemac_txdata *td = NULL;
+       struct rkemac_txdesc *tx = NULL;
        bus_dmamap_t map;
-       uint32_t info, len;
+       uint32_t info, len, padlen;
        int error, first;
 
        first = sc->sc_txq.t_cur;
        map = sc->sc_txq.t_data[first].td_map;
-       info = 0;
 
        error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0,
            BUS_DMA_WRITE | BUS_DMA_NOWAIT);
@@ -698,8 +702,14 @@
 
        KASSERT(map->dm_nsegs > 0);
 
-       const u_int nbufs = map->dm_nsegs +
-           ((m0->m_pkthdr.len < ETHER_MIN_LEN) ? 1 : 0);
+       int nbufs = map->dm_nsegs;
+
+       if (m0->m_pkthdr.len < ETHER_MIN_LEN) {
+               padlen = ETHER_MIN_LEN - m0->m_pkthdr.len;
+               nbufs++;
+       } else {
+               padlen = 0;
+       }
 
        if (sc->sc_txq.t_queued + nbufs > RKEMAC_TX_RING_COUNT) {
                bus_dmamap_unload(sc->sc_dmat, map);
@@ -716,34 +726,34 @@
                tx->tx_info = htole32(info | len);
                info &= ~EMAC_TXDESC_FIRST;
                info |= EMAC_TXDESC_OWN;
-               if (i == map->dm_nsegs - 1) {
-                       if (m0->m_pkthdr.len < ETHER_MIN_LEN) {
-                               sc->sc_txq.t_queued++;
-                               sc->sc_txq.t_cur = (sc->sc_txq.t_cur + 1)
-                                   % RKEMAC_TX_RING_COUNT;
-                               td = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
-                               tx = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
-                               tx->tx_ptr = htole32(sc->sc_pad_physaddr);
-                               len = __SHIFTIN(ETHER_MIN_LEN -
-                                   m0->m_pkthdr.len , EMAC_TXDESC_TXLEN);
-                               tx->tx_info = htole32(info | len);
-                       }
-                       tx->tx_info |= htole32(EMAC_TXDESC_LAST);
-               }
 
                sc->sc_txq.t_queued++;
-               sc->sc_txq.t_cur =
-                   (sc->sc_txq.t_cur + 1) % RKEMAC_TX_RING_COUNT;
+               sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
        }
 
-       sc->sc_txq.t_desc[first].tx_info |= htole32(EMAC_TXDESC_OWN);
+       if (padlen) {
+               td = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
+               tx = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
+
+               tx->tx_ptr = htole32(sc->sc_pad_physaddr);
+               len = __SHIFTIN(padlen, EMAC_TXDESC_TXLEN);
+               tx->tx_info = htole32(info | len);
+
+               sc->sc_txq.t_queued++;
+               sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
+       }
+
+       tx->tx_info |= htole32(EMAC_TXDESC_LAST);
 
        td->td_m = m0;
        td->td_active = map;
+       td->td_nbufs = nbufs;
 
        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
            BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 
+       sc->sc_txq.t_desc[first].tx_info |= htole32(EMAC_TXDESC_OWN);
+
        return 0;
 }
 
@@ -770,8 +780,7 @@
        struct ifnet *ifp = &sc->sc_ec.ec_if;
        int i;
 
-       for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0;
-           i = TX_NEXT(i), sc->sc_txq.t_queued--) {
+       for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0; i = TX_NEXT(i)) {
                struct rkemac_txdata *td = &sc->sc_txq.t_data[i];
                struct rkemac_txdesc *tx = &sc->sc_txq.t_desc[i];
 
@@ -792,6 +801,8 @@
 
                m_freem(td->td_m);
                td->td_m = NULL;
+
+               sc->sc_txq.t_queued -= td->td_nbufs;
        }
 
        sc->sc_txq.t_next = i;
diff -r f4df68d570a8 -r b081d0658841 sys/dev/ic/dwc_gmac.c
--- a/sys/dev/ic/dwc_gmac.c     Mon Feb 23 17:05:58 2015 +0000
+++ b/sys/dev/ic/dwc_gmac.c     Mon Feb 23 19:05:16 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac.c,v 1.31 2015/01/08 14:44:43 jmcneill Exp $ */
+/* $NetBSD: dwc_gmac.c,v 1.32 2015/02/23 19:05:17 martin Exp $ */
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.31 2015/01/08 14:44:43 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.32 2015/02/23 19:05:17 martin Exp $");
 
 /* #define     DWC_GMAC_DEBUG  1 */
 
@@ -803,6 +803,10 @@
                }
                IFQ_DEQUEUE(&ifp->if_snd, m0);
                bpf_mtap(ifp, m0);
+               if (sc->sc_txq.t_queued == AWGE_TX_RING_COUNT) {
+                       ifp->if_flags |= IFF_OACTIVE;
+                       break;
+               }
        }
 
        if (sc->sc_txq.t_queued != old) {
@@ -847,7 +851,7 @@
        struct dwc_gmac_dev_dmadesc *desc = NULL;
        struct dwc_gmac_tx_data *data = NULL;
        bus_dmamap_t map;
-       uint32_t flags, len;
+       uint32_t flags, len, status;
        int error, i, first;
 
 #ifdef DWC_GMAC_DEBUG
@@ -857,7 +861,6 @@
 
        first = sc->sc_txq.t_cur;
        map = sc->sc_txq.t_data[first].td_map;
-       flags = 0;
 
        error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0,
            BUS_DMA_WRITE|BUS_DMA_NOWAIT);
@@ -867,21 +870,19 @@
                return error;
        }
 
-       if (sc->sc_txq.t_queued + map->dm_nsegs >= AWGE_TX_RING_COUNT) {
+       if (sc->sc_txq.t_queued + map->dm_nsegs > AWGE_TX_RING_COUNT) {
                bus_dmamap_unload(sc->sc_dmat, map);
                return ENOBUFS;
        }
 
-       data = NULL;
        flags = DDESC_CNTL_TXFIRST|DDESC_CNTL_TXCHAIN;
+       status = 0;
        for (i = 0; i < map->dm_nsegs; i++) {
                data = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
                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|DDESC_CNTL_TXINT;
+               len = __SHIFTIN(map->dm_segs[i].ds_len, DDESC_CNTL_SIZE1MASK);
 
 #ifdef DWC_GMAC_DEBUG
                aprint_normal_dev(sc->sc_dev, "enqueing desc #%d data %08lx "
@@ -898,16 +899,14 @@
                 * Defer passing ownership of the first descriptor
                 * until we are done.
                 */
-               if (i)
-                       desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+               desc->ddesc_status = htole32(status);
+               status |= DDESC_STATUS_OWNEDBYDEV;
 
                sc->sc_txq.t_queued++;
                sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
        }
 
-       /* Pass first to device */
-       sc->sc_txq.t_desc[first].ddesc_status
-           = htole32(DDESC_STATUS_OWNEDBYDEV);
+       desc->ddesc_cntl |= htole32(DDESC_CNTL_TXLAST|DDESC_CNTL_TXINT);
 
        data->td_m = m0;
        data->td_active = map;
@@ -915,6 +914,10 @@
        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 
+       /* Pass first to device */
+       sc->sc_txq.t_desc[first].ddesc_status =
+           htole32(DDESC_STATUS_OWNEDBYDEV);
+
        return 0;
 }
 
@@ -969,21 +972,19 @@
 static void
 dwc_gmac_tx_intr(struct dwc_gmac_softc *sc)
 {
+       struct ifnet *ifp = &sc->sc_ec.ec_if;
        struct dwc_gmac_tx_data *data;
        struct dwc_gmac_dev_dmadesc *desc;
-       uint32_t flags;
-       int i;
+       uint32_t status;
+       int i, nsegs;
 
-       for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0;
-           i = TX_NEXT(i), sc->sc_txq.t_queued--) {
-
+       for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0; i = TX_NEXT(i)) {
 #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];
                /*
                 * i+1 does not need to be a valid descriptor,
                 * this is just a special notion to just sync
@@ -991,15 +992,18 @@
                 */
                dwc_gmac_txdesc_sync(sc, i, i+1,
                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-               flags = le32toh(desc->ddesc_status);
 
-               if (flags & DDESC_STATUS_OWNEDBYDEV)
+               desc = &sc->sc_txq.t_desc[i];
+               status = le32toh(desc->ddesc_status);
+               if (status & DDESC_STATUS_OWNEDBYDEV)
                        break;
 
                data = &sc->sc_txq.t_data[i];
                if (data->td_m == NULL)
                        continue;
-               sc->sc_ec.ec_if.if_opackets++;
+
+               ifp->if_opackets++;
+               nsegs = data->td_active->dm_nsegs;
                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);
@@ -1012,12 +1016,14 @@
 
                m_freem(data->td_m);
                data->td_m = NULL;
+
+               sc->sc_txq.t_queued -= nsegs;
        }



Home | Main Index | Thread Index | Old Index