From owner-freebsd-bugs@FreeBSD.ORG Tue Apr 24 19:40:06 2007 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6788C16A406 for ; Tue, 24 Apr 2007 19:40:06 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id 4D59013C469 for ; Tue, 24 Apr 2007 19:40:06 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id l3OJe6A6050742 for ; Tue, 24 Apr 2007 19:40:06 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id l3OJe6KY050741; Tue, 24 Apr 2007 19:40:06 GMT (envelope-from gnats) Resent-Date: Tue, 24 Apr 2007 19:40:06 GMT Resent-Message-Id: <200704241940.l3OJe6KY050741@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Ed Schouten Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 60CAE16A401 for ; 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 ; 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 To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: kern/112089: re(4): only works after a lot of patching X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Ed Schouten List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Apr 2007 19:40:06 -0000 >Number: 112089 >Category: kern >Synopsis: re(4): only works after a lot of patching >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Apr 24 19:40:05 GMT 2007 >Closed-Date: >Last-Modified: >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: port 0xa800-0xa8ff mem 0xfeaff000-0xfeafffff irq 19 at device 0.0 on pci3 miibus0: on re0 rgephy0: 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: >Unformatted: