Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic awge: fix issue that caused rx packets to be corr...



details:   https://anonhg.NetBSD.org/src/rev/90036f4767f3
branches:  trunk
changeset: 455349:90036f4767f3
user:      tnn <tnn%NetBSD.org@localhost>
date:      Tue Oct 15 16:30:49 2019 +0000

description:
awge: fix issue that caused rx packets to be corrupt with DIAGNOSTIC kernel

It seems the hardware can only reliably do rx DMA to addresses that are
dcache size aligned. This is hinted at by some GMAC data sheets but hard to
find an authoritative source.

on non-DIAGNOSTIC kernels we always implicitly get MCLBYTES-aligned mbuf
data pointers, but with the reintroduction of POOL_REDZONE for DIAGNOSTIC
we can get 8-byte alignment due to redzone padding. So align rx pointers to
64 bytes which should be good for both arm32 and aarch64.

While here change some bus_dmamap_load() to bus_dmamap_load_mbuf() and add
one missing bus_dmamap_sync(). Also fixes the code to not assume that
MCLBYTES == AWGE_MAX_PACKET. User may override MCLSHIFT in kernel config.

diffstat:

 sys/dev/ic/dwc_gmac.c |  42 ++++++++++++++++++++++++++++--------------
 1 files changed, 28 insertions(+), 14 deletions(-)

diffs (113 lines):

diff -r c001b0eabd10 -r 90036f4767f3 sys/dev/ic/dwc_gmac.c
--- a/sys/dev/ic/dwc_gmac.c     Tue Oct 15 16:17:43 2019 +0000
+++ b/sys/dev/ic/dwc_gmac.c     Tue Oct 15 16:30:49 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac.c,v 1.65 2019/09/13 07:55:06 msaitoh Exp $ */
+/* $NetBSD: dwc_gmac.c,v 1.66 2019/10/15 16:30:49 tnn 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.65 2019/09/13 07:55:06 msaitoh Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.66 2019/10/15 16:30:49 tnn Exp $");
 
 /* #define     DWC_GMAC_DEBUG  1 */
 
@@ -499,15 +499,24 @@
                        error = ENOMEM;
                        goto fail;
                }
+               data->rd_m->m_len = data->rd_m->m_pkthdr.len
+                   = data->rd_m->m_ext.ext_size;
+               m_adj(data->rd_m,
+                   roundup((uintptr_t)data->rd_m->m_data & 0x3f, 0x40));
+               if (data->rd_m->m_len > AWGE_MAX_PACKET) {
+                       data->rd_m->m_len = data->rd_m->m_pkthdr.len
+                           = AWGE_MAX_PACKET;
+               }
 
-               error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
-                   mtod(data->rd_m, void *), MCLBYTES, NULL,
-                   BUS_DMA_READ | BUS_DMA_NOWAIT);
+               error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
+                   data->rd_m, BUS_DMA_READ | BUS_DMA_NOWAIT);
                if (error != 0) {
                        aprint_error_dev(sc->sc_dev,
                            "could not load rx buf DMA map #%d", i);
                        goto fail;
                }
+               bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
+                   data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
                physaddr = data->rd_map->dm_segs[0].ds_addr;
 
                desc = &sc->sc_rxq.r_desc[i];
@@ -516,7 +525,7 @@
                desc->ddesc_next = htole32(ring->r_physaddr
                    + next * sizeof(*desc));
                sc->sc_descm->rx_init_flags(desc);
-               sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+               sc->sc_descm->rx_set_len(desc, data->rd_m->m_len);
                sc->sc_descm->rx_set_owned_by_dev(desc);
        }
 
@@ -538,13 +547,15 @@
        struct dwc_gmac_rx_ring *ring)
 {
        struct dwc_gmac_dev_dmadesc *desc;
+       struct dwc_gmac_rx_data *data;
        int i;
 
        mutex_enter(&ring->r_mtx);
        for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
                desc = &sc->sc_rxq.r_desc[i];
+               data = &sc->sc_rxq.r_data[i];
                sc->sc_descm->rx_init_flags(desc);
-               sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+               sc->sc_descm->rx_set_len(desc, data->rd_m->m_len);
                sc->sc_descm->rx_set_owned_by_dev(desc);
        }
 
@@ -1264,6 +1275,11 @@
                        ifp->if_ierrors++;
                        goto skip;
                }
+               mnew->m_len = mnew->m_pkthdr.len = mnew->m_ext.ext_size;
+               m_adj(mnew, roundup((uintptr_t)mnew->m_data & 0x3f, 0x40));
+               if (mnew->m_len > AWGE_MAX_PACKET) {
+                       mnew->m_len = mnew->m_pkthdr.len = AWGE_MAX_PACKET;
+               }
 
                /* unload old DMA map */
                bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
@@ -1271,15 +1287,13 @@
                bus_dmamap_unload(sc->sc_dmat, data->rd_map);
 
                /* and reload with new mbuf */
-               error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
-                   mtod(mnew, void*), MCLBYTES, NULL,
-                   BUS_DMA_READ | BUS_DMA_NOWAIT);
+               error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
+                   mnew, BUS_DMA_READ | BUS_DMA_NOWAIT);
                if (error != 0) {
                        m_freem(mnew);
                        /* try to reload old mbuf */
-                       error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
-                           mtod(data->rd_m, void*), MCLBYTES, NULL,
-                           BUS_DMA_READ | BUS_DMA_NOWAIT);
+                       error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
+                           data->rd_m, BUS_DMA_READ | BUS_DMA_NOWAIT);
                        if (error != 0) {
                                panic("%s: could not load old rx mbuf",
                                    device_xname(sc->sc_dev));
@@ -1308,7 +1322,7 @@
                    data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
 
                sc->sc_descm->rx_init_flags(desc);
-               sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+               sc->sc_descm->rx_set_len(desc, data->rd_m->m_len);
                sc->sc_descm->rx_set_owned_by_dev(desc);
 
                bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,



Home | Main Index | Thread Index | Old Index