summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_sis.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci/if_sis.c')
-rw-r--r--sys/pci/if_sis.c26
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.
OpenPOWER on IntegriCloud