diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2000-01-16 16:17:57 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2000-01-16 16:17:57 +0000 |
commit | 0edd59fa80959f48bc18b1a9e7d41f36722c0152 (patch) | |
tree | 49a5446db5c150f8bdd22985924726465b0babbc /sys/dev/pci | |
parent | 2587d38cdc9088f53720da616d105fa1fe1278d1 (diff) |
Merge with FreeBSD:
o add a new routine, dc_coal(), that copies tx data into a single mbuf
o use it on the dm910x chips
Tested by jsthyer@uncg.edu
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_dc.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/sys/dev/pci/if_dc.c b/sys/dev/pci/if_dc.c index 3b19de7d7e4..08aba98d684 100644 --- a/sys/dev/pci/if_dc.c +++ b/sys/dev/pci/if_dc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_dc.c,v 1.8 2000/01/10 04:18:30 jason Exp $ */ +/* $OpenBSD: if_dc.c,v 1.9 2000/01/16 16:17:56 jason Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -31,7 +31,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/pci/if_dc.c,v 1.4 2000/01/03 15:28:46 wpaul Exp $ + * $FreeBSD: src/sys/pci/if_dc.c,v 1.5 2000/01/12 22:24:05 wpaul Exp $ */ /* @@ -181,6 +181,8 @@ void dc_acpi __P((struct device *, void *)); struct dc_type *dc_devtype __P((void *)); int dc_newbuf __P((struct dc_softc *, int, struct mbuf *)); int dc_encap __P((struct dc_softc *, struct mbuf *, u_int32_t *)); +int dc_coal __P((struct dc_softc *, struct mbuf **)); + void dc_pnic_rx_bug_war __P((struct dc_softc *, int)); int dc_rx_resync __P((struct dc_softc *)); void dc_rxeof __P((struct dc_softc *)); @@ -1368,7 +1370,7 @@ void dc_attach(parent, self, aux) PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_DAVICOM_DM9102) { found = 1; sc->dc_type = DC_TYPE_DM9102; - sc->dc_flags |= DC_TX_USE_TX_INTR; + sc->dc_flags |= DC_TX_COALESCE|DC_TX_USE_TX_INTR; sc->dc_flags |= DC_REDUCED_MII_POLL; sc->dc_pmode = DC_PMODE_MII; } @@ -2285,6 +2287,39 @@ int dc_encap(sc, m_head, txidx) } /* + * Coalesce an mbuf chain into a single mbuf cluster buffer. + * Needed for some really badly behaved chips that just can't + * do scatter/gather correctly. + */ +int dc_coal(sc, m_head) + struct dc_softc *sc; + struct mbuf **m_head; +{ + struct mbuf *m_new, *m; + + m = *m_head; + MGETHDR(m_new, M_DONTWAIT, MT_DATA); + if (m_new == NULL) { + printf("dc%d: no memory for tx list", sc->dc_unit); + return(ENOBUFS); + } + if (m->m_pkthdr.len > MHLEN) { + MCLGET(m_new, M_DONTWAIT); + if (!(m_new->m_flags & M_EXT)) { + m_freem(m_new); + printf("dc%d: no memory for tx list", sc->dc_unit); + return(ENOBUFS); + } + } + m_copydata(m, 0, m->m_pkthdr.len, mtod(m_new, caddr_t)); + m_new->m_pkthdr.len = m_new->m_len = m->m_pkthdr.len; + m_freem(m); + *m_head = m_new; + + return(0); +} + +/* * Main transmit routine. To avoid having to do mbuf copies, we put pointers * to the mbuf data regions directly in the transmit lists. We also save a * copy of the pointers since the transmit list fragment pointers are @@ -2313,6 +2348,14 @@ void dc_start(ifp) if (m_head == NULL) break; + if (sc->dc_flags & DC_TX_COALESCE) { + if (dc_coal(sc, &m_head)) { + IF_PREPEND(&ifp->if_snd, m_head); + ifp->if_flags |= IFF_OACTIVE; + break; + } + } + if (dc_encap(sc, m_head, &idx)) { IF_PREPEND(&ifp->if_snd, m_head); ifp->if_flags |= IFF_OACTIVE; |