mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-17 15:27:36 +00:00
- Use m_collapse(9) instead of m_defrag(9) if possible. This results
in a noticeable reduction in system time spent. - If bus_dmamap_load_mbuf_sg(9) fails with EFBIG and we already have defragmented the mbuf chain, don't bother to defragment and load it a second time just yet as it's likely to fail again anyway. MFC after: 3 days
This commit is contained in:
parent
6adb632eeb
commit
993a741ac6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=182079
@ -3138,7 +3138,7 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
|
||||
bus_dma_segment_t segs[DC_MAXFRAGS];
|
||||
struct dc_desc *f;
|
||||
struct mbuf *m;
|
||||
int chainlen, cur, error, first, frag, i, idx, nseg;
|
||||
int cur, defragged, error, first, frag, i, idx, nseg;
|
||||
|
||||
/*
|
||||
* If there's no way we can send any packets, return now.
|
||||
@ -3146,22 +3146,30 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
|
||||
if (DC_TX_LIST_CNT - sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_RSVD)
|
||||
return (ENOBUFS);
|
||||
|
||||
/*
|
||||
* Count the number of frags in this chain to see if
|
||||
* we need to m_defrag. Since the descriptor list is shared
|
||||
* by all packets, we'll m_defrag long chains so that they
|
||||
* do not use up the entire list, even if they would fit.
|
||||
*/
|
||||
chainlen = 0;
|
||||
for (m = *m_head; m != NULL; m = m->m_next)
|
||||
chainlen++;
|
||||
|
||||
m = NULL;
|
||||
if ((sc->dc_flags & DC_TX_COALESCE && ((*m_head)->m_next != NULL ||
|
||||
sc->dc_flags & DC_TX_ALIGN)) || (chainlen > DC_TX_LIST_CNT / 4) ||
|
||||
(DC_TX_LIST_CNT - (chainlen + sc->dc_cdata.dc_tx_cnt) <=
|
||||
DC_TX_LIST_RSVD)) {
|
||||
defragged = 0;
|
||||
if (sc->dc_flags & DC_TX_COALESCE &&
|
||||
((*m_head)->m_next != NULL || sc->dc_flags & DC_TX_ALIGN)) {
|
||||
m = m_defrag(*m_head, M_DONTWAIT);
|
||||
defragged = 1;
|
||||
} else {
|
||||
/*
|
||||
* Count the number of frags in this chain to see if we
|
||||
* need to m_collapse. Since the descriptor list is shared
|
||||
* by all packets, we'll m_collapse long chains so that they
|
||||
* do not use up the entire list, even if they would fit.
|
||||
*/
|
||||
i = 0;
|
||||
for (m = *m_head; m != NULL; m = m->m_next)
|
||||
i++;
|
||||
if (i > DC_TX_LIST_CNT / 4 ||
|
||||
DC_TX_LIST_CNT - i + sc->dc_cdata.dc_tx_cnt <=
|
||||
DC_TX_LIST_RSVD) {
|
||||
m = m_collapse(*m_head, M_DONTWAIT, DC_MAXFRAGS);
|
||||
defragged = 1;
|
||||
}
|
||||
}
|
||||
if (defragged != 0) {
|
||||
if (m == NULL) {
|
||||
m_freem(*m_head);
|
||||
*m_head = NULL;
|
||||
@ -3169,15 +3177,16 @@ dc_encap(struct dc_softc *sc, struct mbuf **m_head)
|
||||
}
|
||||
*m_head = m;
|
||||
}
|
||||
|
||||
idx = sc->dc_cdata.dc_tx_prod;
|
||||
error = bus_dmamap_load_mbuf_sg(sc->dc_mtag,
|
||||
sc->dc_cdata.dc_tx_map[idx], *m_head, segs, &nseg, 0);
|
||||
if (error == EFBIG) {
|
||||
m = m_defrag(*m_head, M_DONTWAIT);
|
||||
if (m == NULL) {
|
||||
if (defragged != 0 || (m = m_collapse(*m_head, M_DONTWAIT,
|
||||
DC_MAXFRAGS)) == NULL) {
|
||||
m_freem(*m_head);
|
||||
*m_head = NULL;
|
||||
return (ENOBUFS);
|
||||
return (defragged != 0 ? error : ENOBUFS);
|
||||
}
|
||||
*m_head = m;
|
||||
error = bus_dmamap_load_mbuf_sg(sc->dc_mtag,
|
||||
|
Loading…
Reference in New Issue
Block a user