svn commit: r325983 - head/sys/arm/allwinner

Emmanuel Vadot manu at FreeBSD.org
Sat Nov 18 21:04:40 UTC 2017


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 <guyyur at gmail.com>
  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);
 


More information about the svn-src-head mailing list