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: