From owner-freebsd-bugs@FreeBSD.ORG Fri Jan 16 13:40:27 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 386BD16A4CE for ; Fri, 16 Jan 2004 13:40:27 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3291A43D62 for ; Fri, 16 Jan 2004 13:40:06 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i0GLe6FR004503 for ; Fri, 16 Jan 2004 13:40:06 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i0GLe6X5004502; Fri, 16 Jan 2004 13:40:06 -0800 (PST) (envelope-from gnats) Resent-Date: Fri, 16 Jan 2004 13:40:06 -0800 (PST) Resent-Message-Id: <200401162140.i0GLe6X5004502@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, Tim Draegen-Gilman Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6E4DD16A4CE for ; Fri, 16 Jan 2004 13:35:22 -0800 (PST) Received: from www.freebsd.org (www.freebsd.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id C6CB443D31 for ; Fri, 16 Jan 2004 13:35:17 -0800 (PST) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.12.10/8.12.10) with ESMTP id i0GLZHdL036055 for ; Fri, 16 Jan 2004 13:35:17 -0800 (PST) (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.12.10/8.12.10/Submit) id i0GLZHAh036043; Fri, 16 Jan 2004 13:35:17 -0800 (PST) (envelope-from nobody) Message-Id: <200401162135.i0GLZHAh036043@www.freebsd.org> Date: Fri, 16 Jan 2004 13:35:17 -0800 (PST) From: Tim Draegen-Gilman To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-2.0 Subject: kern/61448: RealTek driver (rl) fails to adjust TX threshold on TX underrun X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 16 Jan 2004 21:40:27 -0000 >Number: 61448 >Category: kern >Synopsis: RealTek driver (rl) fails to adjust TX threshold on TX underrun >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Jan 16 13:40:05 PST 2004 >Closed-Date: >Last-Modified: >Originator: Tim Draegen-Gilman >Release: 4.8 >Organization: Vernier Networks, Inc. >Environment: FreeBSD 4.8-RELEASE i386 >Description: The rl driver fails to properly detect the TX underflow condition. This stems from a RealTek documentation ambiguity. This failure to detect TX underflow leads to the driver never being able to increase the TX threshold, which causes the NIC to (over time) continue to underflow. This results in malformed packets appearing on the wire. >How-To-Repeat: 1. Get yourself a RealTek 8139-based NIC. 2. Connect your NIC to a Cisco Switch 3. Watch as the Cisco reports CRC errors. 4. CRC errors exactly match unaddressed TX underflow condition from RealTek chip. >Fix: The follwing patch corrects this problem. It adds comments, deals with the underflow condition while processing a "TX_OK" bit (this is the documentation flaw -- underflow and OK are both set at the same time), increases the Tx threshold step from 32 to 64, adds a sanity check to provide a TX threshold ceiling, and avoids reset/init cycle of the chip on out-put error (this is a bit heavy handed). The two debug printfs can be removed (but are necessary to show that the "underrun" and "OK" bits are both set at the same time). Index: freebsd/sys/pci/if_rl.c =================================================================== RCS file: /home/cvs/ambit2/freebsd/sys/pci/if_rl.c,v retrieving revision 1.4 diff -u -r1.4 if_rl.c --- freebsd/sys/pci/if_rl.c 20 Jun 2003 04:24:31 -0000 1.4 +++ freebsd/sys/pci/if_rl.c 16 Jan 2004 02:36:51 -0000 @@ -1209,36 +1209,48 @@ * frames that have been uploaded. */ do { + /* Grab the TX status */ txstat = CSR_READ_4(sc, RL_LAST_TXSTAT(sc)); + + /* Only deal with OK, Underrun, and Abort conditions */ if (!(txstat & (RL_TXSTAT_TX_OK| RL_TXSTAT_TX_UNDERRUN|RL_TXSTAT_TXABRT))) break; - ifp->if_collisions += (txstat & RL_TXSTAT_COLLCNT) >> 24; - + /* Free up memory */ if (RL_LAST_TXMBUF(sc) != NULL) { m_freem(RL_LAST_TXMBUF(sc)); RL_LAST_TXMBUF(sc) = NULL; } - if (txstat & RL_TXSTAT_TX_OK) - ifp->if_opackets++; - else { - int oldthresh; + + /* Deal with abort/out-of-window condition */ + if (txstat & (RL_TXSTAT_OUTOFWIN | RL_TXSTAT_TXABRT)) { ifp->if_oerrors++; - if ((txstat & RL_TXSTAT_TXABRT) || - (txstat & RL_TXSTAT_OUTOFWIN)) - CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG); - oldthresh = sc->rl_txthresh; - /* error recovery */ - rl_reset(sc); - rl_init(sc); + + printf("rl_txeof error: TSR is %x\n", txstat); + + /* If abort-condition, clear the abort */ + if (txstat & RL_TXSTAT_TXABRT) { + CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CLRABRT); + } + } else { + ifp->if_opackets++; + /* - * If there was a transmit underrun, - * bump the TX threshold. + * Update the RX threshold if underrun is reported. + * Datasheet says threshold must be between 000001 and + * 111111 inclusive. We start at 000011 (96). */ - if (txstat & RL_TXSTAT_TX_UNDERRUN) - sc->rl_txthresh = oldthresh + 32; - return; + if ((txstat & RL_TXSTAT_TX_UNDERRUN) && + (sc->rl_txthresh < 2016)) { + sc->rl_txthresh += 64; + printf("rl_txeof underrun: TSR is %x, txthresh now %d\n", txstat, + sc->rl_txthresh); + } + + /* Update collision count, if any */ + ifp->if_collisions += + (txstat & RL_TXSTAT_COLLCNT) >> 24; } RL_INC(sc->rl_cdata.last_tx); ifp->if_flags &= ~IFF_OACTIVE; >Release-Note: >Audit-Trail: >Unformatted: