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@gmail.com>
Differential Revision:	https://reviews.freebsd.org/D13035
This commit is contained in:
Emmanuel Vadot 2017-11-18 21:04:39 +00:00
parent 0d2abe1e2b
commit 337c6940a9

View File

@ -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, struct mbuf **mp)
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,16 +406,32 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struct mbuf **mp)
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);
@ -459,6 +475,8 @@ awg_setup_txbuf(struct awg_softc *sc, int index, struct mbuf **mp)
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, struct mbuf **mp)
*/
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);