Author: manu
Date: Sat Nov 18 21:04:39 2017
New Revision: 325983
URL: https://svnweb.freebsd.org/changeset/base/325983

Log:
  if_awg: rename tx functions to match other drivers and free mbuf on 
m_collapse failure
  
  - use awg_encap and awg_txeof names to match iflib and other network drivers.
  - handle m_collapse failure similarly by freeing the mbuf rather than 
reenqueuing it where it will continue to fail.
  
  Submitted by: Guy Yur <[email protected]>
  Differential Revision:        https://reviews.freebsd.org/D13035

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:59:20 2017        
(r325982)
+++ head/sys/arm/allwinner/if_awg.c     Sat Nov 18 21:04:39 2017        
(r325983)
@@ -388,7 +388,7 @@ awg_media_change(if_t ifp)
 }
 
 static int
-awg_setup_txbuf(struct awg_softc *sc, int index, struct mbuf **mp)
+awg_encap(struct awg_softc *sc, struct mbuf **mp)
 {
        bus_dmamap_t map;
        bus_dma_segment_t segs[TX_MAX_SEGS];
@@ -397,7 +397,7 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struc
        uint32_t flags, status;
        struct mbuf *m;
 
-       cur = first = index;
+       cur = first = sc->tx.cur;
        map = sc->tx.buf_map[first].map;
 
        m = *mp;
@@ -406,18 +406,34 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struc
        if (error == EFBIG) {
                m = m_collapse(m, M_NOWAIT, TX_MAX_SEGS);
                if (m == NULL) {
-                       device_printf(sc->dev, "awg_setup_txbuf: m_collapse 
failed\n");
-                       return (0);
+                       device_printf(sc->dev, "awg_encap: m_collapse 
failed\n");
+                       m_freem(*mp);
+                       *mp = NULL;
+                       return (ENOMEM);
                }
                *mp = m;
                error = bus_dmamap_load_mbuf_sg(sc->tx.buf_tag, map, m,
                    segs, &nsegs, BUS_DMA_NOWAIT);
+               if (error != 0) {
+                       m_freem(*mp);
+                       *mp = NULL;
+               }
        }
        if (error != 0) {
-               device_printf(sc->dev, "awg_setup_txbuf: 
bus_dmamap_load_mbuf_sg failed\n");
-               return (0);
+               device_printf(sc->dev, "awg_encap: bus_dmamap_load_mbuf_sg 
failed\n");
+               return (error);
        }
+       if (nsegs == 0) {
+               m_freem(*mp);
+               *mp = NULL;
+               return (EIO);
+       }
 
+       if (sc->tx.queued + nsegs > TX_DESC_COUNT) {
+               bus_dmamap_unload(sc->tx.buf_tag, map);
+               return (ENOBUFS);
+       }
+
        bus_dmamap_sync(sc->tx.buf_tag, map, BUS_DMASYNC_PREWRITE);
 
        flags = TX_FIR_DESC;
@@ -459,6 +475,8 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struc
                cur = TX_NEXT(cur);
        }
 
+       sc->tx.cur = cur;
+
        /* 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;
@@ -471,7 +489,7 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struc
         */
        sc->tx.desc_ring[first].status = htole32(TX_DESC_CTL);
 
-       return (nsegs);
+       return (0);
 }
 
 static void
@@ -546,7 +564,7 @@ awg_start_locked(struct awg_softc *sc)
        struct mbuf *m;
        uint32_t val;
        if_t ifp;
-       int cnt, nsegs;
+       int cnt, err;
 
        AWG_ASSERT_LOCKED(sc);
 
@@ -560,22 +578,19 @@ awg_start_locked(struct awg_softc *sc)
                return;
 
        for (cnt = 0; ; cnt++) {
-               if (sc->tx.queued >= TX_DESC_COUNT - TX_MAX_SEGS) {
-                       if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
-                       break;
-               }
-
                m = if_dequeue(ifp);
                if (m == NULL)
                        break;
 
-               nsegs = awg_setup_txbuf(sc, sc->tx.cur, &m);
-               if (nsegs == 0) {
-                       if_sendq_prepend(ifp, m);
+               err = awg_encap(sc, &m);
+               if (err != 0) {
+                       if (err == ENOBUFS)
+                               if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
+                       if (m != NULL)
+                               if_sendq_prepend(ifp, m);
                        break;
                }
                if_bpfmtap(ifp, m);
-               sc->tx.cur = TX_SKIP(sc->tx.cur, nsegs);
        }
 
        if (cnt != 0) {
@@ -911,7 +926,7 @@ awg_rxintr(struct awg_softc *sc)
 }
 
 static void
-awg_txintr(struct awg_softc *sc)
+awg_txeof(struct awg_softc *sc)
 {
        struct emac_desc *desc;
        uint32_t status, size;
@@ -964,7 +979,7 @@ awg_intr(void *arg)
                awg_rxintr(sc);
 
        if (val & TX_INT)
-               awg_txintr(sc);
+               awg_txeof(sc);
 
        if (val & (TX_INT | TX_BUF_UA_INT)) {
                if (!if_sendq_empty(sc->ifp))
@@ -993,7 +1008,7 @@ awg_poll(if_t ifp, enum poll_cmd cmd, int count)
        }
 
        rx_npkts = awg_rxintr(sc);
-       awg_txintr(sc);
+       awg_txeof(sc);
        if (!if_sendq_empty(ifp))
                awg_start_locked(sc);
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to