diff options
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_sis.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/sys/pci/if_sis.c b/sys/pci/if_sis.c index 7f72c39..fa4006e 100644 --- a/sys/pci/if_sis.c +++ b/sys/pci/if_sis.c @@ -1878,9 +1878,33 @@ sis_encap(sc, m_head, txidx) { struct sis_desc *f = NULL; struct mbuf *m; - int frag, cur, cnt = 0; + int frag, cur, cnt = 0, chainlen = 0; /* + * If there's no way we can send any packets, return now. + */ + if (SIS_TX_LIST_CNT - sc->sis_cdata.sis_tx_cnt < 2) + 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. + */ + + for (m = m_head; m != NULL; m = m->m_next) + chainlen++; + + if ((chainlen > SIS_TX_LIST_CNT / 4) || + ((SIS_TX_LIST_CNT - (chainlen + sc->sis_cdata.sis_tx_cnt)) < 2)) { + m = m_defrag(m_head, M_DONTWAIT); + if (m == NULL) + return (ENOBUFS); + m_head = m; + } + + /* * Start packing the mbufs in this chain into * the fragment pointers. Stop when we run out * of fragments or hit the end of the mbuf chain. |