From owner-freebsd-bugs@FreeBSD.ORG Tue Jan 31 11:50:03 2006 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 [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 97CA016A420 for ; Tue, 31 Jan 2006 11:50:03 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9380643D55 for ; Tue, 31 Jan 2006 11:50:02 +0000 (GMT) (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 k0VBo2hN048372 for ; Tue, 31 Jan 2006 11:50:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k0VBo2Hi048371; Tue, 31 Jan 2006 11:50:02 GMT (envelope-from gnats) Resent-Date: Tue, 31 Jan 2006 11:50:02 GMT Resent-Message-Id: <200601311150.k0VBo2Hi048371@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, Rene de Vries Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id BAEE516A420 for ; Tue, 31 Jan 2006 11:49:24 +0000 (GMT) (envelope-from rene@sigmix.tunix.nl) Received: from sigmix.tunix.nl (bastixp.tunix.nl [217.149.223.38]) by mx1.FreeBSD.org (Postfix) with ESMTP id 05E3943D4C for ; Tue, 31 Jan 2006 11:49:23 +0000 (GMT) (envelope-from rene@sigmix.tunix.nl) Received: from sigmix.tunix.nl (localhost [127.0.0.1]) by sigmix.tunix.nl (8.13.4/8.13.4) with ESMTP id k0VBnLxV049602 for ; Tue, 31 Jan 2006 12:49:21 +0100 (CET) (envelope-from rene@sigmix.tunix.nl) Received: (from rene@localhost) by sigmix.tunix.nl (8.13.4/8.13.3/Submit) id k0VBnL22049601; Tue, 31 Jan 2006 12:49:21 +0100 (CET) (envelope-from rene) Message-Id: <200601311149.k0VBnL22049601@sigmix.tunix.nl> Date: Tue, 31 Jan 2006 12:49:21 +0100 (CET) From: Geert Jan de Groot To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: kern/92599: BUG: IEEE 802.3 compliance of autonegotiation process X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Rene de Vries List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 Jan 2006 11:50:03 -0000 >Number: 92599 >Category: kern >Synopsis: BUG: IEEE 802.3 compliance of autonegotiation process >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 Jan 31 11:50:01 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Geert Jan de Groot >Release: FreeBSD 6.0 i386 >Organization: Tunix Internet Security & Training >Environment: System: FreeBSD sigmix.tunix.nl 6.0 FreeBSD 6.0-RELEASE #0: Tue Jan 10 15:53:21 CET 2006 root@sigmix.tunix.nl:/usr/obj/usr/src/sys/SIGMIX i386 >Description: This patch fixes 3 problems: A. dcphy inadvertently accepts 100BASE-T4 technology When a link partner announces 100BASE-T4 capability, dcphy will accept and choose this technology, even though it is not supported and we don't announce it ourselves. dcphy should mask the link partner's announcement with our own capabilities, so we only accept the highest technology we commonly share. This bug is triggered when connecting SYM-based 21143 boards to a Cisco 3550 switch, which inadvertently announces 100BASE-T4 capability even though it doesn't do 100BASE-T4. Symptom is dat the 21143 eventually switches to 100BASE-TX while the 3550 switch switches to 100BASE-TX,FDX, or the link may not come up at all. Files affected: dev/mii/dcphy.c B. Autonegotiation selection order is wrong Autonegotiation selection is based on selecting the highest common technology both link partners will accept. For this to work, IEEE 802.3 defines a priority order in which the technologies are selected. As of IEEE 802.3-2002, annex 28B.3, the list is, from high to low: 1000BASE-T full-duplex 1000BASE-T 100BASE-T2 full-duplex 100BASE-TX full-duplex 100BASE-T2 100BASE-T4 100BASE-TX 10BASE-T full-duplex 10BASE-T However, the PHY code that reads the link partner capability registers and decides on the highest common technology, didn't use this order: the priority of 100BASE-T4 was too high (which helped to trigger bug A above). While I think that it is unlikely that we will encounter 100BASE-T4 technology in the field in the future, having a wrong order may lead to more bugs and incompatibilities so the testing order was changed to match the IEEE spec. Files affected: dev/mii/amphy.c dev/mii/dcphy.c dev/mii/nsphy.c dev/mii/rlphy.c dev/mii/tdkphy.c dev/mii/ukphy_subr.c dev/txp/if_txp.c C. if_txp: mask link partner's capability mask against own capabilities From code inspection, it looks like we don't mask the capabilities of the link partner against our own, which means that a technology may be selected that we don't support. The fix is roughly similar to B. above, but I didn't have a 3C990 to test with and hence this patch is untested. Files affected: dev/txp/if_txp.c Author: Geert Jan de Groot >How-To-Repeat: See description >Fix: Diff against FreeBSD 6.0: Index: dev/mii/amphy.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/mii/amphy.c,v retrieving revision 1.1.1.6 diff -c -r1.1.1.6 amphy.c *** dev/mii/amphy.c 9 Dec 2005 08:06:35 -0000 1.1.1.6 --- dev/mii/amphy.c 25 Jan 2006 09:14:04 -0000 *************** *** 264,273 **** if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { anlpar = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR); ! if (anlpar & ANLPAR_T4) ! mii->mii_media_active |= IFM_100_T4; ! else if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) --- 264,277 ---- if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { anlpar = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR); ! /* ! * the order of these tests is dictated by ! * IEEE 802.3-2002 annex 28B, chapter 28B.3 ! */ ! if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_T4) + mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) Index: dev/mii/dcphy.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/mii/dcphy.c,v retrieving revision 1.1.1.5 diff -c -r1.1.1.5 dcphy.c *** dev/mii/dcphy.c 9 Dec 2005 08:06:35 -0000 1.1.1.5 --- dev/mii/dcphy.c 25 Jan 2006 09:14:04 -0000 *************** *** 369,380 **** if (tstat & DC_TSTAT_LP_CAN_NWAY) { anlpar = tstat >> 16; ! if (anlpar & ANLPAR_T4 && ! sc->mii_capabilities & BMSR_100TXHDX) ! mii->mii_media_active |= IFM_100_T4; ! else if (anlpar & ANLPAR_TX_FD && sc->mii_capabilities & BMSR_100TXFDX) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX && sc->mii_capabilities & BMSR_100TXHDX) mii->mii_media_active |= IFM_100_TX; --- 369,384 ---- if (tstat & DC_TSTAT_LP_CAN_NWAY) { anlpar = tstat >> 16; ! /* ! * the order of these tests is dictated by ! * IEEE 802.3-2002 annex 28B, chapter 28B.3 ! */ ! if (anlpar & ANLPAR_TX_FD && sc->mii_capabilities & BMSR_100TXFDX) mii->mii_media_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_T4 && + sc->mii_capabilities & BMSR_100T4) + mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX && sc->mii_capabilities & BMSR_100TXHDX) mii->mii_media_active |= IFM_100_TX; Index: dev/mii/nsphy.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/mii/nsphy.c,v retrieving revision 1.1.1.5 diff -c -r1.1.1.5 nsphy.c *** dev/mii/nsphy.c 9 Dec 2005 08:06:35 -0000 1.1.1.5 --- dev/mii/nsphy.c 25 Jan 2006 09:14:04 -0000 *************** *** 354,363 **** if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { anlpar = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR); ! if (anlpar & ANLPAR_T4) ! mii->mii_media_active |= IFM_100_T4; ! else if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) --- 354,367 ---- if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { anlpar = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR); ! /* ! * the order of these tests is dictated by ! * IEEE 802.3-2002 annex 28B, chapter 28B.3 ! */ ! if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_T4) + mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) Index: dev/mii/rlphy.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/mii/rlphy.c,v retrieving revision 1.1.1.6 diff -c -r1.1.1.6 rlphy.c *** dev/mii/rlphy.c 9 Dec 2005 08:06:35 -0000 1.1.1.6 --- dev/mii/rlphy.c 25 Jan 2006 09:14:04 -0000 *************** *** 289,298 **** if ((anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR))) { ! if (anlpar & ANLPAR_T4) ! mii->mii_media_active |= IFM_100_T4; ! else if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) --- 289,302 ---- if ((anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR))) { ! /* ! * the order of these tests is dictated by ! * IEEE 802.3-2002 annex 28B, chapter 28B.3 ! */ ! if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_T4) + mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) Index: dev/mii/tdkphy.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/mii/tdkphy.c,v retrieving revision 1.1.1.2 diff -c -r1.1.1.2 tdkphy.c *** dev/mii/tdkphy.c 9 Dec 2005 08:06:35 -0000 1.1.1.2 --- dev/mii/tdkphy.c 25 Jan 2006 09:14:04 -0000 *************** *** 277,286 **** * ANLPAR doesn't get set on my card, but we check it anyway, * since it is mentioned in the 78Q2120 specs. */ ! if (anlpar & ANLPAR_T4) ! mii->mii_media_active |= IFM_100_T4; ! else if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) --- 277,290 ---- * ANLPAR doesn't get set on my card, but we check it anyway, * since it is mentioned in the 78Q2120 specs. */ ! /* ! * the order of these tests is dictated by ! * IEEE 802.3-2002 annex 28B, chapter 28B.3 ! */ ! if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_T4) + mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) Index: dev/mii/ukphy_subr.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/mii/ukphy_subr.c,v retrieving revision 1.1.1.5 diff -c -r1.1.1.5 ukphy_subr.c *** dev/mii/ukphy_subr.c 20 Jul 2005 11:57:40 -0000 1.1.1.5 --- dev/mii/ukphy_subr.c 25 Jan 2006 09:14:04 -0000 *************** *** 99,108 **** } anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR); ! if (anlpar & ANLPAR_T4) ! mii->mii_media_active |= IFM_100_T4; ! else if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) --- 99,112 ---- } anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR); ! /* ! * the order of these tests is dictated by ! * IEEE 802.3-2002 annex 28B, chapter 28B.3 ! */ ! if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_T4) + mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) Index: dev/txp/if_txp.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/txp/if_txp.c,v retrieving revision 1.1.1.6 diff -c -r1.1.1.6 if_txp.c *** dev/txp/if_txp.c 9 Dec 2005 08:06:36 -0000 1.1.1.6 --- dev/txp/if_txp.c 25 Jan 2006 09:14:05 -0000 *************** *** 1644,1650 **** { struct txp_softc *sc = ifp->if_softc; struct ifmedia *ifm = &sc->sc_ifmedia; ! u_int16_t bmsr, bmcr, anlpar; ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; --- 1644,1650 ---- { struct txp_softc *sc = ifp->if_softc; struct ifmedia *ifm = &sc->sc_ifmedia; ! u_int16_t bmsr, bmcr, anar, anlpar; ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; *************** *** 1664,1669 **** --- 1664,1674 ---- &anlpar, NULL, NULL, 1)) goto bail; + if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_ANAR, 0, + &anar, NULL, NULL, 1)) + goto bail; + anlpar &= anar; + if (bmsr & BMSR_LINK) ifmr->ifm_status |= IFM_ACTIVE; *************** *** 1681,1691 **** ifmr->ifm_active |= IFM_NONE; return; } ! ! if (anlpar & ANLPAR_T4) ! ifmr->ifm_active |= IFM_100_T4; ! else if (anlpar & ANLPAR_TX_FD) ifmr->ifm_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_TX) ifmr->ifm_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) --- 1686,1699 ---- ifmr->ifm_active |= IFM_NONE; return; } ! /* ! * the order of these tests is dictated by ! * IEEE 802.3-2002 annex 28B, chapter 28B.3 ! */ ! if (anlpar & ANLPAR_TX_FD) ifmr->ifm_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_T4) + ifmr->ifm_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX) ifmr->ifm_active |= IFM_100_TX; else if (anlpar & ANLPAR_10_FD) >Release-Note: >Audit-Trail: >Unformatted: