Hi,
This diff makes the pcn driver use m_defrag for fragmented mbuf chains,
cheers,
Kim
Index: if_pcn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_pcn.c,v
retrieving revision 1.36
diff -u -p -r1.36 if_pcn.c
--- if_pcn.c 14 Mar 2015 03:38:48 -0000 1.36
+++ if_pcn.c 27 Mar 2015 12:17:24 -0000
@@ -851,25 +851,23 @@ pcn_start(struct ifnet *ifp)
* were short on resources. In this case, we'll copy
* and try again.
*/
- if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
- BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- break;
- if (m0->m_pkthdr.len > MHLEN) {
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- m_freem(m);
- break;
- }
- }
- m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
- m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
- error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
- m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
- if (error)
- break;
- }
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
+ BUS_DMA_WRITE|BUS_DMA_NOWAIT);
+ switch (error) {
+ case 0:
+ break;
+ case EFBIG:
+ if ((error = m_defrag(m0, M_DONTWAIT)) == 0 &&
+ (error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
+ m0, BUS_DMA_WRITE|BUS_DMA_NOWAIT)) == 0)
+ break;
+
+ /* FALLTHROUGH */
+ default:
+ IFQ_DEQUEUE(&ifp->if_snd, m0);
+ m_freem(m);
+ continue;
+ }
/*
* Ensure we have enough descriptors free to describe