From owner-svn-src-stable@FreeBSD.ORG Tue Nov 2 23:35:08 2010 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E9B0C106566B; Tue, 2 Nov 2010 23:35:08 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D62CE8FC14; Tue, 2 Nov 2010 23:35:08 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oA2NZ8Qd098377; Tue, 2 Nov 2010 23:35:08 GMT (envelope-from yongari@svn.freebsd.org) Received: (from yongari@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oA2NZ84K098374; Tue, 2 Nov 2010 23:35:08 GMT (envelope-from yongari@svn.freebsd.org) Message-Id: <201011022335.oA2NZ84K098374@svn.freebsd.org> From: Pyun YongHyeon Date: Tue, 2 Nov 2010 23:35:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214704 - stable/8/sys/dev/bge X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Nov 2010 23:35:09 -0000 Author: yongari Date: Tue Nov 2 23:35:08 2010 New Revision: 214704 URL: http://svn.freebsd.org/changeset/base/214704 Log: MFC r213485,213710,213812: r213485: Overhaul MII register access routine and remove unnecessary BGE_MI_MODE register accesses. Previously bge(4) used to read BGE_MI_MODE register to detect whether it needs to disable autopolling feature or not. Because we don't touch autopolling in other part of driver there is no reason to read BGE_MI_MODE register given that we know default value in advance. In order to achieve the goal, check whether the controller has CPMU(Central Power Mangement Unit) capability. If controller has CPMU feature, use 500KHz MII management interface(mdio/mdc) frequency regardless core clock frequency. Otherwise use default MII clock. While I'm here, add CPMU register definition. In bge_miibus_readreg(), rearrange code a bit and remove goto statement. In bge_miibus_writereg(), make sure to restore autopolling even if MII write failed. The delay time inserted after accessing BGE_MI_MODE register increased from 40us to 80us. The default PHY address is now stored in softc. All PHYs supported by bge(4) currently uses PHY address 1 but it will be changed when we add newer controllers. This change will make it easier to change default PHY address depending on PHY models. Submitted by: davidch r213710: Remove one last reference of BGE_MI_MODE register for auto polling. Previously bge(4) always enabled auto polling for non-BGE_FLAG_TBI controllers. With this change, auto polling is not used anymore so polling through mii(4) was introduced. Reviewed by: davidch r213812: Fix a regression introduced in r213710. r213710 removed the use of auto polling such that it made all controllers obtain link status information from the state of the LNKRDY input signal. Broadcom recommends disabling auto polling such that driver should rely on PHY interrupts for link status change indications. Unfortunately it seems some controllers(BCM5703, BCM5704 and BCM5705) have PHY related issues so Linux took other approach to workaround it. bge(4) didn't follow that and it used to enable auto polling to workaround it. Restore this old behavior for BCM5700 family controllers and BCM5705 to use auto polling. For BCM5700 and BCM5701, it seems it does not need to enable auto polling but I restored it for safety. Special thanks to marius who tried lots of patches with patience. Reported by: marius Tested by: marius Modified: stable/8/sys/dev/bge/if_bge.c stable/8/sys/dev/bge/if_bgereg.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/dev/bge/if_bge.c ============================================================================== --- stable/8/sys/dev/bge/if_bge.c Tue Nov 2 23:26:07 2010 (r214703) +++ stable/8/sys/dev/bge/if_bge.c Tue Nov 2 23:35:08 2010 (r214704) @@ -768,38 +768,34 @@ static int bge_miibus_readreg(device_t dev, int phy, int reg) { struct bge_softc *sc; - uint32_t val, autopoll; + uint32_t val; int i; sc = device_get_softc(dev); - /* - * Broadcom's own driver always assumes the internal - * PHY is at GMII address 1. On some chips, the PHY responds - * to accesses at all addresses, which could cause us to - * bogusly attach the PHY 32 times at probe type. Always - * restricting the lookup to address 1 is simpler than - * trying to figure out which chips revisions should be - * special-cased. - */ - if (phy != 1) + /* Prevent the probe from finding incorrect devices. */ + if (phy != sc->bge_phy_addr) return (0); - /* Reading with autopolling on may trigger PCI errors */ - autopoll = CSR_READ_4(sc, BGE_MI_MODE); - if (autopoll & BGE_MIMODE_AUTOPOLL) { - BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL); - DELAY(40); + /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ + if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) { + CSR_WRITE_4(sc, BGE_MI_MODE, + sc->bge_mi_mode & ~BGE_MIMODE_AUTOPOLL); + DELAY(80); } CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY | BGE_MIPHY(phy) | BGE_MIREG(reg)); + /* Poll for the PHY register access to complete. */ for (i = 0; i < BGE_TIMEOUT; i++) { DELAY(10); val = CSR_READ_4(sc, BGE_MI_COMM); - if (!(val & BGE_MICOMM_BUSY)) + if ((val & BGE_MICOMM_BUSY) == 0) { + DELAY(5); + val = CSR_READ_4(sc, BGE_MI_COMM); break; + } } if (i == BGE_TIMEOUT) { @@ -807,16 +803,12 @@ bge_miibus_readreg(device_t dev, int phy "PHY read timed out (phy %d, reg %d, val 0x%08x)\n", phy, reg, val); val = 0; - goto done; } - DELAY(5); - val = CSR_READ_4(sc, BGE_MI_COMM); - -done: - if (autopoll & BGE_MIMODE_AUTOPOLL) { - BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL); - DELAY(40); + /* Restore the autopoll bit if necessary. */ + if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) { + CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode); + DELAY(80); } if (val & BGE_MICOMM_READFAIL) @@ -829,7 +821,6 @@ static int bge_miibus_writereg(device_t dev, int phy, int reg, int val) { struct bge_softc *sc; - uint32_t autopoll; int i; sc = device_get_softc(dev); @@ -838,11 +829,11 @@ bge_miibus_writereg(device_t dev, int ph (reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL)) return (0); - /* Reading with autopolling on may trigger PCI errors */ - autopoll = CSR_READ_4(sc, BGE_MI_MODE); - if (autopoll & BGE_MIMODE_AUTOPOLL) { - BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL); - DELAY(40); + /* Clear the autopoll bit if set, otherwise may trigger PCI errors. */ + if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) { + CSR_WRITE_4(sc, BGE_MI_MODE, + sc->bge_mi_mode & ~BGE_MIMODE_AUTOPOLL); + DELAY(80); } CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY | @@ -857,17 +848,16 @@ bge_miibus_writereg(device_t dev, int ph } } - if (i == BGE_TIMEOUT) { + /* Restore the autopoll bit if necessary. */ + if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) { + CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode); + DELAY(80); + } + + if (i == BGE_TIMEOUT) device_printf(sc->bge_dev, "PHY write timed out (phy %d, reg %d, val %d)\n", phy, reg, val); - return (0); - } - - if (autopoll & BGE_MIMODE_AUTOPOLL) { - BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL); - DELAY(40); - } return (0); } @@ -1918,11 +1908,17 @@ bge_blockinit(struct bge_softc *sc) BGE_MACSTAT_LINK_CHANGED); CSR_WRITE_4(sc, BGE_MI_STS, 0); - /* Enable PHY auto polling (for MII/GMII only) */ + /* + * Enable attention when the link has changed state for + * devices that use auto polling. + */ if (sc->bge_flags & BGE_FLAG_TBI) { CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK); } else { - BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL | (10 << 16)); + if (sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) { + CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode); + DELAY(80); + } if (sc->bge_asicrev == BGE_ASICREV_BCM5700 && sc->bge_chipid != BGE_CHIPID_BCM5700_B2) CSR_WRITE_4(sc, BGE_MAC_EVT_ENB, @@ -2502,6 +2498,9 @@ bge_attach(device_t dev) sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); + /* Set default PHY address. */ + sc->bge_phy_addr = 1; + /* * Don't enable Ethernet@WireSpeed for the 5700, 5906, or the * 5705 A0 and A1 chips. @@ -2575,6 +2574,20 @@ bge_attach(device_t dev) sc->bge_phy_flags |= BGE_PHY_BER_BUG; } + /* Identify the chips that use an CPMU. */ + if (sc->bge_asicrev == BGE_ASICREV_BCM5784 || + sc->bge_asicrev == BGE_ASICREV_BCM5761 || + sc->bge_asicrev == BGE_ASICREV_BCM5785 || + sc->bge_asicrev == BGE_ASICREV_BCM57780) + sc->bge_flags |= BGE_FLAG_CPMU_PRESENT; + if ((sc->bge_flags & BGE_FLAG_CPMU_PRESENT) != 0) + sc->bge_mi_mode = BGE_MIMODE_500KHZ_CONST; + else + sc->bge_mi_mode = BGE_MIMODE_BASE; + /* Enable auto polling for BCM570[0-5]. */ + if (BGE_IS_5700_FAMILY(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5705) + sc->bge_mi_mode |= BGE_MIMODE_AUTOPOLL; + /* * All controllers that are not 5755 or higher have 4GB * boundary DMA bug. @@ -4948,7 +4961,7 @@ bge_link_upd(struct bge_softc *sc) if_printf(sc->bge_ifp, "link DOWN\n"); if_link_state_change(sc->bge_ifp, LINK_STATE_DOWN); } - } else if (CSR_READ_4(sc, BGE_MI_MODE) & BGE_MIMODE_AUTOPOLL) { + } else if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) { /* * Some broken BCM chips have BGE_STATFLAG_LINKSTATE_CHANGED bit * in status word always set. Workaround this bug by reading @@ -4976,9 +4989,17 @@ bge_link_upd(struct bge_softc *sc) } } else { /* - * Discard link events for MII/GMII controllers - * if MI auto-polling is disabled. + * For controllers that call mii_tick, we have to poll + * link status. */ + mii = device_get_softc(sc->bge_miibus); + mii_pollstat(mii); + if (!sc->bge_link && mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + bge_miibus_statchg(sc->bge_dev); + sc->bge_link = 1; + } else + sc->bge_link = 0; } /* Clear the attention. */ Modified: stable/8/sys/dev/bge/if_bgereg.h ============================================================================== --- stable/8/sys/dev/bge/if_bgereg.h Tue Nov 2 23:26:07 2010 (r214703) +++ stable/8/sys/dev/bge/if_bgereg.h Tue Nov 2 23:35:08 2010 (r214704) @@ -863,9 +863,12 @@ #define BGE_MISTS_LINK 0x00000001 #define BGE_MISTS_10MBPS 0x00000002 +#define BGE_MIMODE_CLK_10MHZ 0x00000001 #define BGE_MIMODE_SHORTPREAMBLE 0x00000002 #define BGE_MIMODE_AUTOPOLL 0x00000010 #define BGE_MIMODE_CLKCNT 0x001F0000 +#define BGE_MIMODE_500KHZ_CONST 0x00008000 +#define BGE_MIMODE_BASE 0x000C0000 /* @@ -1221,6 +1224,51 @@ /* Receive List Selector Status register */ #define BGE_RXLSSTAT_ERROR 0x00000004 +#define BGE_CPMU_CTRL 0x3600 +#define BGE_CPMU_LSPD_10MB_CLK 0x3604 +#define BGE_CPMU_LSPD_1000MB_CLK 0x360C +#define BGE_CPMU_LNK_AWARE_PWRMD 0x3610 +#define BGE_CPMU_HST_ACC 0x361C +#define BGE_CPMU_CLCK_STAT 0x3630 +#define BGE_CPMU_MUTEX_REQ 0x365C +#define BGE_CPMU_MUTEX_GNT 0x3660 +#define BGE_CPMU_PHY_STRAP 0x3664 + +/* Central Power Management Unit (CPMU) register */ +#define BGE_CPMU_CTRL_LINK_IDLE_MODE 0x00000200 +#define BGE_CPMU_CTRL_LINK_AWARE_MODE 0x00000400 +#define BGE_CPMU_CTRL_LINK_SPEED_MODE 0x00004000 +#define BGE_CPMU_CTRL_GPHY_10MB_RXONLY 0x00010000 + +/* Link Speed 10MB/No Link Power Mode Clock Policy register */ +#define BGE_CPMU_LSPD_10MB_MACCLK_MASK 0x001F0000 +#define BGE_CPMU_LSPD_10MB_MACCLK_6_25 0x00130000 + +/* Link Speed 1000MB Power Mode Clock Policy register */ +#define BGE_CPMU_LSPD_1000MB_MACCLK_62_5 0x00000000 +#define BGE_CPMU_LSPD_1000MB_MACCLK_12_5 0x00110000 +#define BGE_CPMU_LSPD_1000MB_MACCLK_MASK 0x001F0000 + +/* Link Aware Power Mode Clock Policy register */ +#define BGE_CPMU_LNK_AWARE_MACCLK_MASK 0x001F0000 +#define BGE_CPMU_LNK_AWARE_MACCLK_6_25 0x00130000 + +#define BGE_CPMU_HST_ACC_MACCLK_MASK 0x001F0000 +#define BGE_CPMU_HST_ACC_MACCLK_6_25 0x00130000 + +/* CPMU Clock Status register */ +#define BGE_CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001F0000 +#define BGE_CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 +#define BGE_CPMU_CLCK_STAT_MAC_CLCK_12_5 0x00110000 +#define BGE_CPMU_CLCK_STAT_MAC_CLCK_6_25 0x00130000 + +/* CPMU Mutex Request register */ +#define BGE_CPMU_MUTEX_REQ_DRIVER 0x00001000 +#define BGE_CPMU_MUTEX_GNT_DRIVER 0x00001000 + +/* CPMU GPHY Strap register */ +#define BGE_CPMU_PHY_STRAP_IS_SERDES 0x00000020 + /* * Mbuf Cluster Free registers (has nothing to do with BSD mbufs) */ @@ -2665,6 +2713,7 @@ struct bge_softc { #define BGE_FLAG_JUMBO 0x00000002 #define BGE_FLAG_EADDR 0x00000008 #define BGE_FLAG_MII_SERDES 0x00000010 +#define BGE_FLAG_CPMU_PRESENT 0x00000020 #define BGE_FLAG_MSI 0x00000100 #define BGE_FLAG_PCIX 0x00000200 #define BGE_FLAG_PCIE 0x00000400 @@ -2707,7 +2756,9 @@ struct bge_softc { uint32_t bge_rx_max_coal_bds; uint32_t bge_tx_max_coal_bds; uint32_t bge_tx_buf_ratio; + uint32_t bge_mi_mode; int bge_if_flags; + int bge_phy_addr; int bge_txcnt; int bge_link; /* link state */ int bge_link_evt; /* pending link event */