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