Author: manu
Date: Sat Nov 18 20:46:31 2017
New Revision: 325979
URL: https://svnweb.freebsd.org/changeset/base/325979

Log:
  if_awg: store mbuf and dma mapping in the last segment of a tx frame instead 
of the first
  
  According to the datasheet, TX_DESC_CTL is cleared when whole frame is 
transmitted or all
  data in the current descriptor's buffer are transmitted.
  When the mbuf and mapping are stored in the first segment and in a scenario 
where a tx
  completion interrupt arrives for a frame and only the start of the next frame 
was transmitted,
  at the time of interrupt processing the mbuf and mapping will be freed when 
processing the
  first segment of the next frame but the other untrasmitted segments still 
need to use them.
  
  Submitted by: Guy Yur <guy...@gmail.com>
  Differential Revision:        https://reviews.freebsd.org/D13031

Modified:
  head/sys/arm/allwinner/if_awg.c

Modified: head/sys/arm/allwinner/if_awg.c
==============================================================================
--- head/sys/arm/allwinner/if_awg.c     Sat Nov 18 20:42:48 2017        
(r325978)
+++ head/sys/arm/allwinner/if_awg.c     Sat Nov 18 20:46:31 2017        
(r325979)
@@ -390,17 +390,19 @@ awg_media_change(if_t ifp)
 static int
 awg_setup_txbuf(struct awg_softc *sc, int index, struct mbuf **mp)
 {
+       bus_dmamap_t map;
        bus_dma_segment_t segs[TX_MAX_SEGS];
-       int error, nsegs, cur, first, i;
+       int error, nsegs, cur, first, last, i;
        u_int csum_flags;
        uint32_t flags, status;
        struct mbuf *m;
 
        cur = first = index;
+       map = sc->tx.buf_map[first].map;
 
        m = *mp;
-       error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag,
-           sc->tx.buf_map[index].map, m, segs, &nsegs, BUS_DMA_NOWAIT);
+       error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, map, m, segs,
+           &nsegs, BUS_DMA_NOWAIT);
        if (error == EFBIG) {
                m = m_collapse(m, M_NOWAIT, TX_MAX_SEGS);
                if (m == NULL) {
@@ -408,16 +410,15 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struc
                        return (0);
                }
                *mp = m;
-               error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag,
-                   sc->tx.buf_map[index].map, m, segs, &nsegs, BUS_DMA_NOWAIT);
+               error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, map, m,
+                   segs, &nsegs, BUS_DMA_NOWAIT);
        }
        if (error != 0) {
                device_printf(sc->dev, "awg_setup_txbuf: 
bus_dmamap_load_mbuf_sg failed\n");
                return (0);
        }
 
-       bus_dmamap_sync(sc->tx.buf_tag, sc->tx.buf_map[index].map,
-           BUS_DMASYNC_PREWRITE);
+       bus_dmamap_sync(sc->tx.buf_tag, map, BUS_DMASYNC_PREWRITE);
 
        flags = TX_FIR_DESC;
        status = 0;
@@ -458,7 +459,11 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struc
                cur = TX_NEXT(cur);
        }
 
-       sc->tx.buf_map[first].mbuf = m;
+       /* Store mapping and mbuf in the last segment */
+       last = TX_SKIP(cur, TX_DESC_COUNT - 1);
+       sc->tx.buf_map[first].map = sc->tx.buf_map[last].map;
+       sc->tx.buf_map[last].map = map;
+       sc->tx.buf_map[last].mbuf = m;
 
        /*
         * The whole mbuf chain has been DMA mapped,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to