The following diff replaces the hand rolled code to deal with
really long mbuf chains with the use of m_defrag().
Index: fxp.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/fxp.c,v
retrieving revision 1.100
diff -u -p -r1.100 fxp.c
--- fxp.c 15 Oct 2009 17:54:54 -0000 1.100
+++ fxp.c 24 Dec 2009 19:40:44 -0000
@@ -678,8 +678,8 @@ fxp_start(struct ifnet *ifp)
struct fxp_softc *sc = ifp->if_softc;
struct fxp_txsw *txs = sc->sc_cbt_prod;
struct fxp_cb_tx *txc;
- struct mbuf *m0, *m = NULL;
- int cnt = sc->sc_cbt_cnt, seg;
+ struct mbuf *m0;
+ int cnt = sc->sc_cbt_cnt, seg, error;
if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING)
return;
@@ -696,33 +696,22 @@ fxp_start(struct ifnet *ifp)
if (m0 == NULL)
break;
- if (bus_dmamap_load_mbuf(sc->sc_dmat, txs->tx_map,
- m0, BUS_DMA_NOWAIT) != 0) {
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, txs->tx_map,
+ m0, BUS_DMA_NOWAIT);
+ if (error != 0 && error != EFBIG)
+ break;
+ if (error != 0) {
+ if (m_defrag(m0, M_DONTWAIT))
break;
- if (m0->m_pkthdr.len > MHLEN) {
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- 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;
if (bus_dmamap_load_mbuf(sc->sc_dmat, txs->tx_map,
- m, BUS_DMA_NOWAIT) != 0) {
- m_freem(m);
+ m0, BUS_DMA_NOWAIT) != 0)
break;
- }
}
+ /*
+ * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
+ */
IFQ_DEQUEUE(&ifp->if_snd, m0);
- if (m != NULL) {
- m_freem(m0);
- m0 = m;
- m = NULL;
- }
txs->tx_mbuf = m0;
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.