Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Add support for jumbo Ethernet frames on the DP8...
details: https://anonhg.NetBSD.org/src/rev/58ae81f6faf9
branches: trunk
changeset: 512152:58ae81f6faf9
user: thorpej <thorpej%NetBSD.org@localhost>
date: Sat Jul 07 02:32:38 2001 +0000
description:
Add support for jumbo Ethernet frames on the DP83820.
diffstat:
sys/dev/pci/if_sip.c | 262 ++++++++++++++++++++++++++++++++++----------------
1 files changed, 176 insertions(+), 86 deletions(-)
diffs (truncated from 437 to 300 lines):
diff -r dec5c106f143 -r 58ae81f6faf9 sys/dev/pci/if_sip.c
--- a/sys/dev/pci/if_sip.c Sat Jul 07 01:44:21 2001 +0000
+++ b/sys/dev/pci/if_sip.c Sat Jul 07 02:32:38 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_sip.c,v 1.35 2001/06/30 22:35:05 thorpej Exp $ */
+/* $NetBSD: if_sip.c,v 1.36 2001/07/07 02:32:38 thorpej Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -78,8 +78,6 @@
*
* - Support the 10-bit interface on the DP83820 (for fiber).
*
- * - Support jumbo packets on the DP83820.
- *
* - Reduce the interrupt load.
*/
@@ -147,8 +145,18 @@
/*
* Receive descriptor list size. We have one Rx buffer per incoming
* packet, so this logic is a little simpler.
+ *
+ * Actually, on the DP83820, we allow the packet to consume more than
+ * one buffer, in order to support jumbo Ethernet frames. In that
+ * case, a packet may consume up to 5 buffers (assuming a 2048 byte
+ * mbuf cluster). 256 receive buffers is only 51 maximum size packets,
+ * so we'd better be quick about handling receive interrupts.
*/
+#if defined(DP83820)
+#define SIP_NRXDESC 256
+#else
#define SIP_NRXDESC 128
+#endif /* DP83820 */
#define SIP_NRXDESC_MASK (SIP_NRXDESC - 1)
#define SIP_NEXTRX(x) (((x) + 1) & SIP_NRXDESC_MASK)
@@ -272,11 +280,33 @@
struct sip_txsq sc_txdirtyq; /* dirty Tx descsofts */
int sc_rxptr; /* next ready Rx descriptor/descsoft */
+#if defined(DP83820)
+ int sc_rxdiscard;
+ int sc_rxlen;
+ struct mbuf *sc_rxhead;
+ struct mbuf *sc_rxtail;
+ struct mbuf **sc_rxtailp;
+#endif /* DP83820 */
};
/* sc_flags */
#define SIPF_PAUSED 0x00000001 /* paused (802.3x flow control) */
+#ifdef DP83820
+#define SIP_RXCHAIN_RESET(sc) \
+do { \
+ (sc)->sc_rxtailp = &(sc)->sc_rxhead; \
+ *(sc)->sc_rxtailp = NULL; \
+ (sc)->sc_rxlen = 0; \
+} while (/*CONSTCOND*/0)
+
+#define SIP_RXCHAIN_LINK(sc, m) \
+do { \
+ *(sc)->sc_rxtailp = sc->sc_rxtail = (m); \
+ (sc)->sc_rxtailp = &(m)->m_next; \
+} while (/*CONSTCOND*/0)
+#endif /* DP83820 */
+
#ifdef SIP_EVENT_COUNTERS
#define SIP_EVCNT_INCR(ev) (ev)->ev_count++
#else
@@ -311,23 +341,24 @@
bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \
SIP_CDRXOFF((x)), sizeof(struct sip_desc), (ops))
-/*
- * Note we rely on MCLBYTES being a power of two below.
- */
#ifdef DP83820
#define SIP_INIT_RXDESC_EXTSTS __sipd->sipd_extsts = 0;
+#define SIP_RXBUF_LEN (MCLBYTES - 4)
#else
#define SIP_INIT_RXDESC_EXTSTS /* nothing */
+#define SIP_RXBUF_LEN (MCLBYTES - 1) /* field width */
#endif
#define SIP_INIT_RXDESC(sc, x) \
do { \
struct sip_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \
struct sip_desc *__sipd = &(sc)->sc_rxdescs[(x)]; \
\
- __sipd->sipd_link = htole32(SIP_CDRXADDR((sc), SIP_NEXTRX((x)))); \
- __sipd->sipd_bufptr = htole32(__rxs->rxs_dmamap->dm_segs[0].ds_addr); \
+ __sipd->sipd_link = \
+ htole32(SIP_CDRXADDR((sc), SIP_NEXTRX((x)))); \
+ __sipd->sipd_bufptr = \
+ htole32(__rxs->rxs_dmamap->dm_segs[0].ds_addr); \
__sipd->sipd_cmdsts = htole32(CMDSTS_INTR | \
- ((MCLBYTES - 1) & CMDSTS_SIZE_MASK)); \
+ (SIP_RXBUF_LEN & CMDSTS_SIZE_MASK)); \
SIP_INIT_RXDESC_EXTSTS \
SIP_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
} while (0)
@@ -790,9 +821,11 @@
#ifdef DP83820
/*
- * And the DP83820 can do VLAN tagging in hardware.
+ * And the DP83820 can do VLAN tagging in hardware, and
+ * support the jumbo Ethernet MTU.
*/
- sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_HWTAGGING;
+ sc->sc_ethercom.ec_capabilities |=
+ ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU;
/*
* The DP83820 can do IPv4, TCPv4, and UDPv4 checksums
@@ -937,10 +970,38 @@
IFQ_POLL(&ifp->if_snd, m0);
if (m0 == NULL)
break;
+#ifndef DP83820
m = NULL;
+#endif
dmamap = txs->txs_dmamap;
+#ifdef DP83820
+ /*
+ * Load the DMA map. If this fails, the packet either
+ * didn't fit in the allotted number of segments, or we
+ * were short on resources. For the too-many-segments
+ * case, we simply report an error and drop the packet,
+ * since we can't sanely copy a jumbo packet to a single
+ * buffer.
+ */
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
+ BUS_DMA_NOWAIT);
+ if (error) {
+ if (error == EFBIG) {
+ printf("%s: Tx packet consumes too many "
+ "DMA segments, dropping...\n",
+ sc->sc_dev.dv_xname);
+ IFQ_DEQUEUE(&ifp->if_snd, m0);
+ m_freem(m0);
+ continue;
+ }
+ /*
+ * Short on resources, just stop for now.
+ */
+ break;
+ }
+#else /* DP83820 */
/*
* Load the DMA map. If this fails, the packet either
* didn't fit in the alloted number of segments, or we
@@ -974,6 +1035,7 @@
break;
}
}
+#endif /* DP83820 */
/*
* Ensure we have enough descriptors free to describe
@@ -994,17 +1056,21 @@
*/
ifp->if_flags |= IFF_OACTIVE;
bus_dmamap_unload(sc->sc_dmat, dmamap);
+#ifndef DP83820
if (m != NULL)
m_freem(m);
+#endif
SIP_EVCNT_INCR(&sc->sc_ev_txdstall);
break;
}
IFQ_DEQUEUE(&ifp->if_snd, m0);
+#ifndef DP83820
if (m != NULL) {
m_freem(m0);
m0 = m;
}
+#endif
/*
* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
@@ -1425,7 +1491,7 @@
{
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct sip_rxsoft *rxs;
- struct mbuf *m;
+ struct mbuf *m, *tailm;
u_int32_t cmdsts, extsts;
int i, len;
@@ -1449,12 +1515,64 @@
break;
}
+ if (__predict_false(sc->sc_rxdiscard)) {
+ SIP_INIT_RXDESC(sc, i);
+ if ((cmdsts & CMDSTS_MORE) == 0) {
+ /* Reset our state. */
+ sc->sc_rxdiscard = 0;
+ }
+ continue;
+ }
+
+ bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
+ rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
+
+ m = rxs->rxs_mbuf;
+
/*
- * If an error occurred, update stats, clear the status
- * word, and leave the packet buffer in place. It will
- * simply be reused the next time the ring comes around.
+ * Add a new receive buffer to the ring.
*/
- if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_LONG|CMDSTS_Rx_RUNT|
+ if (SIP_DECL(add_rxbuf)(sc, i) != 0) {
+ /*
+ * Failed, throw away what we've done so
+ * far, and discard the rest of the packet.
+ */
+ ifp->if_ierrors++;
+ bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
+ rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
+ SIP_INIT_RXDESC(sc, i);
+ if (cmdsts & CMDSTS_MORE)
+ sc->sc_rxdiscard = 1;
+ if (sc->sc_rxhead != NULL)
+ m_freem(sc->sc_rxhead);
+ SIP_RXCHAIN_RESET(sc);
+ continue;
+ }
+
+ SIP_RXCHAIN_LINK(sc, m);
+
+ /*
+ * If this is not the end of the packet, keep
+ * looking.
+ */
+ if (cmdsts & CMDSTS_MORE) {
+ sc->sc_rxlen += m->m_len;
+ continue;
+ }
+
+ /*
+ * Okay, we have the entire packet now...
+ */
+ *sc->sc_rxtailp = NULL;
+ m = sc->sc_rxhead;
+ tailm = sc->sc_rxtail;
+
+ SIP_RXCHAIN_RESET(sc);
+
+ /*
+ * If an error occurred, update stats and drop the packet.
+ */
+ if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_RUNT|
CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
ifp->if_ierrors++;
if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
@@ -1466,101 +1584,66 @@
#define PRINTERR(bit, str) \
if (cmdsts & (bit)) \
printf("%s: %s\n", sc->sc_dev.dv_xname, str)
- PRINTERR(CMDSTS_Rx_LONG, "packet too long");
PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
#undef PRINTERR
- SIP_INIT_RXDESC(sc, i);
+ m_freem(m);
continue;
}
- bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
- rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
-
/*
- * No errors; receive the packet. Note, the DP83820
- * includes the CRC with every packet.
+ * No errors. Reset receive state.
+ *
+ * Note, the DP83820 includes the CRC with
+ * every packet.
*/
len = CMDSTS_SIZE(cmdsts);
-
-#ifdef __NO_STRICT_ALIGNMENT
+ tailm->m_len = len - sc->sc_rxlen;
+
/*
* If the packet is small enough to fit in a
* single header mbuf, allocate one and copy
* the data into it. This greatly reduces
* memory consumption when we receive lots
* of small packets.
Home |
Main Index |
Thread Index |
Old Index