Subject: kern/23055: gsip(4) cannot recieve jumbo frames properly
To: None <gnats-bugs@gnats.netbsd.org>
From: None <QFH002545@nifty.com>
List: netbsd-bugs
Date: 10/05/2003 11:12:01
>Number: 23055
>Category: kern
>Synopsis: gsip(4) cannot recieve jumbo frames.
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Oct 05 02:13:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:
>Release: NetBSD 1.6.1_STABLE
>Organization:
>Environment:
System: NetBSD that 1.6.1_STABLE NetBSD 1.6.1_STABLE (THATK6) #24: Sun Oct 5 10:02:02 JST 2003 root@that:/usr/src/sys/arch/i386/compile/THATK6 i386
Architecture: i386
Machine: i386 (k6-3/450MHz)
>Description:
>How-To-Repeat:
Set MTU > 1500, and send "jumbo-frame" PING packet from another machine.
>Fix:
Here is a quick-hack patch.
remained problem:
"device timeout" occurred if MTU >= 6000.
********************
diff -u if_sip.c.orig if_sip.c
--- if_sip.c.orig Fri Oct 3 22:38:03 2003
+++ if_sip.c Sun Oct 5 10:45:19 2003
@@ -358,7 +358,7 @@
#ifdef DP83820
#define SIP_INIT_RXDESC_EXTSTS __sipd->sipd_extsts = 0;
-#define SIP_RXBUF_LEN (MCLBYTES - 4)
+#define SIP_RXBUF_LEN (MCLBYTES - 8)
#else
#define SIP_INIT_RXDESC_EXTSTS /* nothing */
#define SIP_RXBUF_LEN (MCLBYTES - 1) /* field width */
@@ -999,7 +999,11 @@
* may trash the first few outgoing packets if the
* PCI bus is saturated.
*/
+#ifdef DP83820
+ sc->sc_tx_drain_thresh = 6400 / 32; /* from FreeBSD nge(4) */
+#else
sc->sc_tx_drain_thresh = 1504 / 32;
+#endif
/*
* Initialize the Rx FIFO drain threshold.
@@ -1107,7 +1111,11 @@
struct mbuf *m0, *m;
struct sip_txsoft *txs;
bus_dmamap_t dmamap;
- int error, firsttx, nexttx, lasttx, ofree, seg;
+ int error, nexttx, lasttx, seg;
+ int ofree = sc->sc_txfree;
+#if 0
+ int firsttx = sc->sc_txnext;
+#endif
#ifdef DP83820
u_int32_t extsts;
#endif
@@ -1122,13 +1130,6 @@
return;
/*
- * Remember the previous number of free descriptors and
- * the first descriptor we'll use.
- */
- ofree = sc->sc_txfree;
- firsttx = sc->sc_txnext;
-
- /*
* Loop through the send queue, setting up transmit descriptors
* until we drain the queue, or use up all available transmit
* descriptors.
@@ -1271,7 +1272,7 @@
sc->sc_txdescs[nexttx].sipd_bufptr =
htole32(dmamap->dm_segs[seg].ds_addr);
sc->sc_txdescs[nexttx].sipd_cmdsts =
- htole32((nexttx == firsttx ? 0 : CMDSTS_OWN) |
+ htole32((nexttx == sc->sc_txnext ? 0 : CMDSTS_OWN) |
CMDSTS_MORE | dmamap->dm_segs[seg].ds_len);
#ifdef DP83820
sc->sc_txdescs[nexttx].sipd_extsts = 0;
@@ -1341,6 +1342,15 @@
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
/*
+ * The entire packet is set up. Give the first descrptor
+ * to the chip now.
+ */
+ sc->sc_txdescs[sc->sc_txnext].sipd_cmdsts |=
+ htole32(CMDSTS_OWN);
+ SIP_CDTXSYNC(sc, sc->sc_txnext, 1,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
+ /*
* Store a pointer to the packet so we can free it later,
* and remember what txdirty will be once the packet is
* done.
@@ -1372,14 +1382,6 @@
if (sc->sc_txfree != ofree) {
/*
- * The entire packet chain is set up. Give the
- * first descrptor to the chip now.
- */
- sc->sc_txdescs[firsttx].sipd_cmdsts |= htole32(CMDSTS_OWN);
- SIP_CDTXSYNC(sc, firsttx, 1,
- BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-
- /*
* Start the transmit process. Note, the manual says
* that if there are no pending transmissions in the
* chip's internal queue (indicated by TXE being clear),
@@ -1695,7 +1697,7 @@
struct sip_rxsoft *rxs;
struct mbuf *m, *tailm;
u_int32_t cmdsts, extsts;
- int i, len;
+ int i, len, frame_len;
for (i = sc->sc_rxptr;; i = SIP_NEXTRX(i)) {
rxs = &sc->sc_rxsoft[i];
@@ -1768,6 +1770,7 @@
*sc->sc_rxtailp = NULL;
m = sc->sc_rxhead;
tailm = sc->sc_rxtail;
+ frame_len = sc->sc_rxlen;
SIP_RXCHAIN_RESET(sc);
@@ -1797,12 +1800,18 @@
/*
* No errors.
- *
- * Note, the DP83820 includes the CRC with
- * every packet.
*/
len = CMDSTS_SIZE(cmdsts);
+ frame_len += len;
+#if 0
+ /*
+ * ??? sc_rxlen is always 0 ???
+ * (SIP_EXCHAIN_RESET)
+ */
tailm->m_len = len - sc->sc_rxlen;
+#else
+ tailm->m_len = len;
+#endif
/*
* If the packet is small enough to fit in a
@@ -1888,9 +1897,9 @@
}
ifp->if_ipackets++;
- m->m_flags |= M_HASFCS;
m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = len;
+ m->m_flags |= M_HASFCS;
+ m->m_pkthdr.len = frame_len;
#if NBPFILTER > 0
/*
@@ -2294,14 +2303,30 @@
* Initialize the prototype RXCFG register.
*/
sc->sc_rxcfg |= (sc->sc_rx_drain_thresh << RXCFG_DRTH_SHIFT);
-#ifndef DP83820
+#ifdef DP83820
+ /*
+ * Accept long packets(including FCS) so we can handle
+ * 802.1q-tagged frames and jumbo frames properly.
+ */
+ sc->sc_rxcfg |= RXCFG_ALP;
+
+ /*
+ * Checksum offloading is disabled if the user selects
+ * an MTU larger than 8152 (8170 - 18). (from FreeBSD nge(4))
+ */
+ if (ifp->if_mtu >= 8152) {
+ ifp->if_capenable &= ~(IFCAP_CSUM_IPv4|
+ IFCAP_CSUM_TCPv4|
+ IFCAP_CSUM_UDPv4);
+ }
+#else
/*
* Accept packets >1518 bytes (including FCS) so we can handle
* 802.1q-tagged frames properly.
*/
if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU)
sc->sc_rxcfg |= RXCFG_ALP;
-#endif
+#endif /* DP83820 */
bus_space_write_4(st, sh, SIP_RXCFG, sc->sc_rxcfg);
#ifdef DP83820
--- if_sipreg.h.orig Sat Aug 16 09:23:04 2003
+++ if_sipreg.h Sun Oct 5 08:31:56 2003
@@ -80,8 +80,13 @@
* Transmit FIFO size. Used to compute the transmit drain threshold.
*
* The transmit FIFO is arranged as a 512 32-bit memory array.
+ * DP83820 has 8KB FIFO buffer.
*/
+#ifdef DP83820
+#define SIP_TXFIFO_SIZE (1024 * 8)
+#else
#define SIP_TXFIFO_SIZE (512 * 4)
+#endif
/*
* The SiS900 uses a single descriptor format for both transmit
*********************
>Release-Note:
>Audit-Trail:
>Unformatted: