Hi,
This diff refactors the vio driver to use m_defrag when mbuf chains get
fragmented, thoughts?
Index: if_vio.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vio.c,v
retrieving revision 1.25
diff -u -p -r1.25 if_vio.c
--- if_vio.c 14 Mar 2015 03:38:48 -0000 1.25
+++ if_vio.c 27 Mar 2015 09:36:37 -0000
@@ -1149,40 +1149,27 @@ vio_encap(struct vio_softc *sc, int slot
{
struct virtio_softc *vsc = sc->sc_virtio;
bus_dmamap_t dmap= sc->sc_tx_dmamaps[slot];
- struct mbuf *m0 = NULL;
int r;
r = bus_dmamap_load_mbuf(vsc->sc_dmat, dmap, m,
BUS_DMA_WRITE|BUS_DMA_NOWAIT);
- if (r == 0) {
- *mnew = m;
- return r;
- }
- if (r != EFBIG)
- return r;
- /* EFBIG: mbuf chain is too fragmented */
- MGETHDR(m0, M_DONTWAIT, MT_DATA);
- if (m0 == NULL)
- return ENOBUFS;
- if (m->m_pkthdr.len > MHLEN) {
- MCLGETI(m0, M_DONTWAIT, NULL, m->m_pkthdr.len);
- if (!(m0->m_flags & M_EXT)) {
- m_freem(m0);
- return ENOBUFS;
- }
- }
- m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
- m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
- r = bus_dmamap_load_mbuf(vsc->sc_dmat, dmap, m0,
- BUS_DMA_NOWAIT|BUS_DMA_WRITE);
- if (r != 0) {
- m_freem(m0);
+ switch (r) {
+ case 0:
+ break;
+ case EFBIG:
+ if ((r = m_defrag(m, M_DONTWAIT)) == 0 &&
+ (r = bus_dmamap_load_mbuf(vsc->sc_dmat, dmap, m,
+ BUS_DMA_WRITE|BUS_DMA_NOWAIT)) == 0)
+ break;
+
+ /* FALLTHROUGH */
+ default:
printf("%s: tx dmamap load error %d\n", sc->sc_dev.dv_xname,
r);
return ENOBUFS;
}
- *mnew = m0;
- return 0;
+ *mnew = m;
+ return r;
}
/* free all the mbufs already put on vq; called from if_stop(disable) */