Index: sys/net/iflib.c =================================================================== --- sys/net/iflib.c +++ sys/net/iflib.c @@ -334,6 +334,7 @@ #endif uint64_t ift_no_tx_dma_setup; uint64_t ift_no_desc_avail; + uint64_t ift_mbuf_collapse_failed; uint64_t ift_mbuf_defrag_failed; uint64_t ift_mbuf_defrag; uint64_t ift_map_failed; @@ -2257,7 +2258,7 @@ txq->ift_in_use = txq->ift_gen = txq->ift_cidx = txq->ift_pidx = txq->ift_no_desc_avail = 0; txq->ift_closed = txq->ift_mbuf_defrag = txq->ift_mbuf_defrag_failed = 0; txq->ift_no_tx_dma_setup = txq->ift_txd_encap_efbig = txq->ift_map_failed = 0; - txq->ift_pullups = 0; + txq->ift_pullups = txq->ift_mbuf_collapse_failed = 0; ifmp_ring_reset_stats(txq->ift_br); for (j = 0, di = txq->ift_ifdi; j < ctx->ifc_nhwtxqs; j++, di++) bzero((void *)di->idi_vaddr, di->idi_size); @@ -3087,13 +3088,18 @@ switch (err) { case EFBIG: /* try collapse once and defrag once */ - if (remap == 0) + if (remap == 0) { m_head = m_collapse(*m_headp, M_NOWAIT, max_segs); + if (m_head == NULL) { + txq->ift_mbuf_collapse_failed++; + remap++; + } + } if (remap == 1) m_head = m_defrag(*m_headp, M_NOWAIT); - remap++; - if (__predict_false(m_head == NULL)) + if (__predict_false(m_head == NULL || remap > 1)) goto defrag_failed; + remap++; txq->ift_mbuf_defrag++; *m_headp = m_head; goto retry; @@ -4144,7 +4150,9 @@ scctx->isc_tx_tso_size_max = FREEBSD_TSO_SIZE_MAX; /* TSO parameters - dig these out of the data sheet - simply correspond to tag setup */ - ifp->if_hw_tsomaxsegcount = scctx->isc_tx_tso_segments_max; + + /* use one segment less to avoid calling m_collapse/m_defrag */ + ifp->if_hw_tsomaxsegcount = scctx->isc_tx_tso_segments_max - 1; ifp->if_hw_tsomax = scctx->isc_tx_tso_size_max; ifp->if_hw_tsomaxsegsize = scctx->isc_tx_tso_segsize_max; if (scctx->isc_rss_table_size == 0) @@ -5515,6 +5523,9 @@ SYSCTL_ADD_QUAD(ctx_list, queue_list, OID_AUTO, "mbuf_defrag_failed", CTLFLAG_RD, &txq->ift_mbuf_defrag_failed, "# of times m_defrag failed"); + SYSCTL_ADD_QUAD(ctx_list, queue_list, OID_AUTO, "mbuf_collapse_failed", + CTLFLAG_RD, + &txq->ift_mbuf_collapse_failed, "# of times m_collapse failed"); SYSCTL_ADD_QUAD(ctx_list, queue_list, OID_AUTO, "no_desc_avail", CTLFLAG_RD, &txq->ift_no_desc_avail, "# of times no descriptors were available");