From ed@hoeg.nl  Tue Apr 24 19:37:52 2007
Return-Path: <ed@hoeg.nl>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 60CAE16A401
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 24 Apr 2007 19:37:52 +0000 (UTC)
	(envelope-from ed@hoeg.nl)
Received: from palm.hoeg.nl (mx0.hoeg.nl [83.98.131.211])
	by mx1.freebsd.org (Postfix) with ESMTP id C650613C46C
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 24 Apr 2007 19:37:51 +0000 (UTC)
	(envelope-from ed@hoeg.nl)
Received: by palm.hoeg.nl (Postfix, from userid 1000)
	id C2C031CC6E; Tue, 24 Apr 2007 21:37:50 +0200 (CEST)
Message-Id: <20070424193750.C2C031CC6E@palm.hoeg.nl>
Date: Tue, 24 Apr 2007 21:37:50 +0200 (CEST)
From: Ed Schouten <ed@fxq.nl>
Reply-To: Ed Schouten <ed@fxq.nl>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: re(4): only works after a lot of patching
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         112089
>Category:       kern
>Synopsis:       [re] [patch] re(4) only works after a lot of patching on ASUS P5B motherboard
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 24 19:40:05 GMT 2007
>Closed-Date:    Mon Jun 04 05:45:10 GMT 2007
>Last-Modified:  Mon Jun 04 05:45:10 GMT 2007
>Originator:     Ed Schouten
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
>Environment:
FreeBSD 6.2-STABLE #0: Sun Apr 22 17:39:47 CEST 2007

re0: <RealTek 8168/8111B PCIe Gigabit Ethernet> port 0xa800-0xa8ff mem 0xfeaff000-0xfeafffff irq 19 at device 0.0 on pci3
miibus0: <MII bus> on re0
rgephy0: <RTL8169S/8110S media interface> on miibus0
rgephy0:  10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, 1000baseT, 1000baseT-FDX, auto
re0: Ethernet address: 00:18:f3:75:0a:0d
re0: [FAST]

re0@pci3:0:0:   class=0x020000 card=0x81aa1043 chip=0x816810ec rev=0x01 hdr=0x00
    vendor     = 'Realtek Semiconductor'
    class      = network
    subclass   = ethernet
>Description:
My desktop with an ASUS P5B motherboard has an on-board re(4) network
interface. It has three problems, sorted by importance:

- I have to run `ifconfig re0 promisc' in order to accept IPv6 traffic
  properly.
- In a lot of cases, TCP traffic gets lost, causing important webpages
  like Google.com to not appear.
- Running `tcpdump -i re0 -n' renders the interface for about 8 seconds
  inactive.
>How-To-Repeat:
>Fix:
Based on a lot of emails on the FreeBSD mailinglists, I've composed a
patch that fixes these issues. I've been using it on my desktop for a
couple of months now and it's the only way I can use my NIC properly.

--- src/sys/dev/re/if_re.c	Thu Mar 15 19:34:07 2007
+++ src/sys/dev/re/if_re.c	Thu Mar 15 19:31:20 2007
@@ -249,6 +249,7 @@
 static int re_ioctl		(struct ifnet *, u_long, caddr_t);
 static void re_init		(void *);
 static void re_init_locked	(struct rl_softc *);
+static void re_init_rxcfg	(struct rl_softc *);
 static void re_stop		(struct rl_softc *);
 static void re_watchdog		(struct rl_softc *);
 static int re_suspend		(device_t);
@@ -620,6 +621,7 @@
 	struct ifmultiaddr	*ifma;
 	u_int32_t		rxfilt;
 	int			mcnt = 0;
+	u_int32_t		hwrev;
 
 	RL_LOCK_ASSERT(sc);
 
@@ -660,8 +662,24 @@
 		rxfilt &= ~RL_RXCFG_RX_MULTI;
 
 	CSR_WRITE_4(sc, RL_RXCFG, rxfilt);
-	CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
-	CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
+
+	/*
+	 * For some unfathomable reason, RealTek decided to reverse
+	 * the order of the multicast hash registers in the PCI Express
+	 * parts. This means we have to write the hash pattern in reverse
+	 * order for those devices.
+	 */
+
+	hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV;
+
+	if (hwrev == RL_HWREV_8100E || hwrev == RL_HWREV_8101E ||
+	    hwrev == RL_HWREV_8168_SPIN1 || hwrev == RL_HWREV_8168_SPIN2) {
+		CSR_WRITE_4(sc, RL_MAR0, bswap32(hashes[1]));
+		CSR_WRITE_4(sc, RL_MAR4, bswap32(hashes[0]));
+	} else {
+		CSR_WRITE_4(sc, RL_MAR0, hashes[0]);
+		CSR_WRITE_4(sc, RL_MAR4, hashes[1]);
+	}
 }
 
 static void
@@ -2040,7 +2058,8 @@
 	 * below can assemble the packet into a single buffer that's
 	 * padded out to the mininum frame size.
 	 */
-	if (arg.rl_flags && (*m_head)->m_pkthdr.len < RL_MIN_FRAMELEN)
+	if (arg.rl_flags && !(arg.rl_flags & RL_TDESC_CMD_TCPCSUM) &&
+	    (*m_head)->m_pkthdr.len < RL_MIN_FRAMELEN)
 		error = EFBIG;
 	else
 		error = bus_dmamap_load_mbuf(sc->rl_ldata.rl_mtag, map,
@@ -2243,7 +2262,6 @@
 {
 	struct ifnet		*ifp = sc->rl_ifp;
 	struct mii_data		*mii;
-	u_int32_t		rxcfg = 0;
 	union {
 		uint32_t align_dummy;
 		u_char eaddr[ETHER_ADDR_LEN];
@@ -2322,31 +2340,8 @@
 	CSR_WRITE_1(sc, RL_EARLY_TX_THRESH, 16);
 
 	CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG);
-
-	/* Set the individual bit to receive frames for this host only. */
-	rxcfg = CSR_READ_4(sc, RL_RXCFG);
-	rxcfg |= RL_RXCFG_RX_INDIV;
-
-	/* If we want promiscuous mode, set the allframes bit. */
-	if (ifp->if_flags & IFF_PROMISC)
-		rxcfg |= RL_RXCFG_RX_ALLPHYS;
-	else
-		rxcfg &= ~RL_RXCFG_RX_ALLPHYS;
-	CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
-
-	/*
-	 * Set capture broadcast bit to capture broadcast frames.
-	 */
-	if (ifp->if_flags & IFF_BROADCAST)
-		rxcfg |= RL_RXCFG_RX_BROAD;
-	else
-		rxcfg &= ~RL_RXCFG_RX_BROAD;
-	CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
-
-	/*
-	 * Program the multicast filter, if necessary.
-	 */
-	re_setmulti(sc);
+	
+	re_init_rxcfg(sc);
 
 #ifdef DEVICE_POLLING
 	/*
@@ -2412,6 +2407,39 @@
 	callout_reset(&sc->rl_stat_callout, hz, re_tick, sc);
 }
 
+static void
+re_init_rxcfg(sc)
+	struct rl_softc		*sc;
+{
+	u_int32_t		rxcfg;
+	struct ifnet		*ifp = sc->rl_ifp;
+
+	/* Set the individual bit to receive frames for this host only. */
+	rxcfg = CSR_READ_4(sc, RL_RXCFG);
+	rxcfg |= RL_RXCFG_RX_INDIV;
+
+	/* If we want promiscuous mode, set the allframes bit. */
+	if (ifp->if_flags & IFF_PROMISC)
+		rxcfg |= RL_RXCFG_RX_ALLPHYS;
+	else
+		rxcfg &= ~RL_RXCFG_RX_ALLPHYS;
+	CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
+
+	/*
+	 * Set capture broadcast bit to capture broadcast frames.
+	 */
+	if (ifp->if_flags & IFF_BROADCAST)
+		rxcfg |= RL_RXCFG_RX_BROAD;
+	else
+		rxcfg &= ~RL_RXCFG_RX_BROAD;
+	CSR_WRITE_4(sc, RL_RXCFG, rxcfg);
+
+	/*
+	 * Program the multicast filter, if necessary.
+	 */
+	re_setmulti(sc);
+}
+
 /*
  * Set media options.
  */
@@ -2473,10 +2501,16 @@
 		break;
 	case SIOCSIFFLAGS:
 		RL_LOCK(sc);
-		if (ifp->if_flags & IFF_UP)
-			re_init_locked(sc);
-		else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		if (ifp->if_flags & IFF_UP) {
+			if ((ifp->if_flags ^ sc->rl_if_flags) &
+			    (IFF_PROMISC | IFF_BROADCAST))
+				re_init_rxcfg(sc);
+			else
+				re_init_locked(sc);
+		} else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 			re_stop(sc);
+		}
+		sc->rl_if_flags = ifp->if_flags;
 		RL_UNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
--- src/sys/pci/if_rlreg.h	Sat Dec  2 00:07:27 2006
+++ src/sys/pci/if_rlreg.h	Sat Dec  2 00:18:53 2006
@@ -737,6 +737,7 @@
 	struct mtx		rl_intlock;
 	int			rl_txstart;
 	int			rl_link;
+	int			rl_if_flags;
 };
 
 #define	RL_LOCK(_sc)		mtx_lock(&(_sc)->rl_mtx)
>Release-Note:
>Audit-Trail:

From: Gavin Atkinson <gavin.atkinson@ury.york.ac.uk>
To: bug-followup@FreeBSD.org, ed@fxq.nl
Cc:  
Subject: Re: kern/112089: [re] [patch] re(4) only works after a lot of
	patching on ASUS P5B motherboard
Date: Fri, 18 May 2007 11:58:11 +0100

 This PR is basically asking for an MFC of sys/dev/re/if_re.c 1.81, 1.84
 and 1.89.  1.89 was MFC'd recently, which should hopefully fix the issue
 with tcpdump.  An MFC of 1.81 is needed to fix the IPv6 traffic problem,
 and an MFC of 1.84 should fix the problem with traffic getting list.
State-Changed-From-To: open->patched 
State-Changed-By: linimon 
State-Changed-When: Fri May 18 19:25:31 UTC 2007 
State-Changed-Why:  
From audit trail: 

An MFC of 1.81 is needed to fix the IPv6 traffic problem, and an MFC of 
1.84 should fix the problem with traffic getting list. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=112089 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/112089: commit references a PR
Date: Sun,  3 Jun 2007 07:43:22 +0000 (UTC)

 yongari     2007-06-03 07:43:15 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_6)
     sys/dev/re           if_re.c 
   Log:
   MFC if_re.c, 1.81 to RELENG_6
     Fix re_setmulti() so that it works correctly for PCIe chips where
     the multicast hash table are in reverse order compared to older
     devices.
   
   PR:     112089
   
   Revision   Changes    Path
   1.46.2.28  +19 -2     src/sys/dev/re/if_re.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/112089: commit references a PR
Date: Sun,  3 Jun 2007 07:47:46 +0000 (UTC)

 yongari     2007-06-03 07:47:40 UTC
 
   FreeBSD src repository
 
   Modified files:        (Branch: RELENG_6)
     sys/dev/re           if_re.c 
   Log:
   MFC if_re.c, 1.84 to RELENG_6
     The TCP checksum offload handling in the 8111B/8168B and 8101E PCIe can
     apparently be confused by short TCP segments that have been manually
     padded to the minimum ethernet frame size. The driver does short frame
     padding in software as a workaround for a bug in the 8169 PCI devices
     that causes short IP fragments to be corrupted due to an apparent
     conflict between the hardware autopadding and hardware IP checksumming.
   
     To fix this, we avoid software padding for short TCP segments, since
     the hardware seems to autopad and checksum these correctly (even the
     older 8169 NICs get these right). Short UDP packets appear to be
     handled correctly in all cases. This should work around the IP header
     checksum bug in the 8169 while not tripping the TCP checksum bug in
     the 8111B/8168B and 8101E.
   
   PR:     112089
   
   Revision   Changes    Path
   1.46.2.29  +6 -1      src/sys/dev/re/if_re.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: rafan 
State-Changed-When: Mon Jun 4 05:45:08 UTC 2007 
State-Changed-Why:  
MFC'ed by yongari@ 

http://www.freebsd.org/cgi/query-pr.cgi?pr=112089 
>Unformatted:
