Date: Mon, 26 Nov 2012 02:31:28 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r243536 - stable/9/sys/dev/bge Message-ID: <201211260231.qAQ2VSJ2073039@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Mon Nov 26 02:31:28 2012 New Revision: 243536 URL: http://svnweb.freebsd.org/changeset/base/243536 Log: MFC r241215-241216,241219-241220,241341,241343: r241215: Don't touch EMAC Mode and TX/RX MAC Mode register when driver is not running. r241216: APE firmware touches EMAC Mode and TX/RX MAC Mode registers to keep the MAC connected to the outside world. So keep the accesses atomic. r241219: Add 40 microseconds delay after updating EMAC Mode register as recommended by Broadcom data sheet. r241220: Follow Broadcom datasheet: Delay 100 microseconds after enabling transmit MAC. Delay 10 microseconds after enabling receive MAC. r241341: Limit applying TX data corruption and FIFO workaround to BCM5719 A0. It's believed BCM5720 does not have the issue. r241343: Rework device detach. While here, move driver lock/callout initialization to the beginning of device attach for readability. Modified: stable/9/sys/dev/bge/if_bge.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) Modified: stable/9/sys/dev/bge/if_bge.c ============================================================================== --- stable/9/sys/dev/bge/if_bge.c Mon Nov 26 02:04:11 2012 (r243535) +++ stable/9/sys/dev/bge/if_bge.c Mon Nov 26 02:31:28 2012 (r243536) @@ -896,7 +896,11 @@ bge_miibus_statchg(device_t dev) { struct bge_softc *sc; struct mii_data *mii; + uint32_t mac_mode, rx_mode, tx_mode; + sc = device_get_softc(dev); + if ((sc->bge_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; mii = device_get_softc(sc->bge_miibus); if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == @@ -922,30 +926,40 @@ bge_miibus_statchg(device_t dev) sc->bge_link = 0; if (sc->bge_link == 0) return; - BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_PORTMODE); + + /* + * APE firmware touches these registers to keep the MAC + * connected to the outside world. Try to keep the + * accesses atomic. + */ + + /* Set the port mode (MII/GMII) to match the link speed. */ + mac_mode = CSR_READ_4(sc, BGE_MAC_MODE) & + ~(BGE_MACMODE_PORTMODE | BGE_MACMODE_HALF_DUPLEX); + tx_mode = CSR_READ_4(sc, BGE_TX_MODE); + rx_mode = CSR_READ_4(sc, BGE_RX_MODE); + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) - BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_GMII); + mac_mode |= BGE_PORTMODE_GMII; else - BGE_SETBIT(sc, BGE_MAC_MODE, BGE_PORTMODE_MII); + mac_mode |= BGE_PORTMODE_MII; + /* Set MAC flow control behavior to match link flow control settings. */ + tx_mode &= ~BGE_TXMODE_FLOWCTL_ENABLE; + rx_mode &= ~BGE_RXMODE_FLOWCTL_ENABLE; if (IFM_OPTIONS(mii->mii_media_active & IFM_FDX) != 0) { - BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); - if ((IFM_OPTIONS(mii->mii_media_active) & - IFM_ETH_TXPAUSE) != 0) - BGE_SETBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE); - else - BGE_CLRBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE); - if ((IFM_OPTIONS(mii->mii_media_active) & - IFM_ETH_RXPAUSE) != 0) - BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE); - else - BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE); - } else { - BGE_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); - BGE_CLRBIT(sc, BGE_TX_MODE, BGE_TXMODE_FLOWCTL_ENABLE); - BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_FLOWCTL_ENABLE); - } + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) + tx_mode |= BGE_TXMODE_FLOWCTL_ENABLE; + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) + rx_mode |= BGE_RXMODE_FLOWCTL_ENABLE; + } else + mac_mode |= BGE_MACMODE_HALF_DUPLEX; + + CSR_WRITE_4(sc, BGE_MAC_MODE, mac_mode); + DELAY(40); + CSR_WRITE_4(sc, BGE_TX_MODE, tx_mode); + CSR_WRITE_4(sc, BGE_RX_MODE, rx_mode); } /* @@ -1421,6 +1435,7 @@ bge_chipinit(struct bge_softc *sc) /* Clear the MAC control register */ CSR_WRITE_4(sc, BGE_MAC_MODE, 0); + DELAY(40); /* * Clear the MAC statistics block in the NIC's @@ -2033,6 +2048,7 @@ bge_blockinit(struct bge_softc *sc) /* Turn on DMA, clear stats */ CSR_WRITE_4(sc, BGE_MAC_MODE, val); + DELAY(40); /* Set misc. local control, enable interrupts on attentions */ CSR_WRITE_4(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); @@ -2105,8 +2121,8 @@ bge_blockinit(struct bge_softc *sc) * Adjust tx margin to prevent TX data corruption and * fix internal FIFO overflow. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5719 || - sc->bge_asicrev == BGE_ASICREV_BCM5720) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5719 && + sc->bge_chipid == BGE_CHIPID_BCM5719_A0) { dmactl &= ~(BGE_RDMA_RSRVCTRL_FIFO_LWM_MASK | BGE_RDMA_RSRVCTRL_FIFO_HWM_MASK | BGE_RDMA_RSRVCTRL_TXMRGN_MASK); @@ -2884,7 +2900,9 @@ bge_attach(device_t dev) sc = device_get_softc(dev); sc->bge_dev = dev; + BGE_LOCK_INIT(sc, device_get_nameunit(dev)); TASK_INIT(&sc->bge_intr_task, 0, bge_intr_task, sc); + callout_init_mtx(&sc->bge_stat_ch, &sc->bge_mtx, 0); /* * Map control/status registers. @@ -3243,8 +3261,6 @@ bge_attach(device_t dev) bge_devinfo(sc); - BGE_LOCK_INIT(sc, device_get_nameunit(dev)); - /* Try to reset the chip. */ if (bge_reset(sc)) { device_printf(sc->bge_dev, "chip reset failed\n"); @@ -3448,7 +3464,6 @@ again: * Call MI attach routine. */ ether_ifattach(ifp, eaddr); - callout_init_mtx(&sc->bge_stat_ch, &sc->bge_mtx, 0); /* Tell upper layer we support long frames. */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); @@ -3465,7 +3480,7 @@ again: if (sc->bge_tq == NULL) { device_printf(dev, "could not create taskqueue.\n"); ether_ifdetach(ifp); - error = ENXIO; + error = ENOMEM; goto fail; } taskqueue_start_threads(&sc->bge_tq, 1, PI_NET, "%s taskq", @@ -3473,23 +3488,19 @@ again: error = bus_setup_intr(dev, sc->bge_irq, INTR_TYPE_NET | INTR_MPSAFE, bge_msi_intr, NULL, sc, &sc->bge_intrhand); - if (error) - ether_ifdetach(ifp); } else error = bus_setup_intr(dev, sc->bge_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, bge_intr, sc, &sc->bge_intrhand); if (error) { - bge_detach(dev); + ether_ifdetach(ifp); device_printf(sc->bge_dev, "couldn't set up irq\n"); } - return (0); - fail: - bge_release_resources(sc); - + if (error) + bge_detach(dev); return (error); } @@ -3507,16 +3518,16 @@ bge_detach(device_t dev) ether_poll_deregister(ifp); #endif - BGE_LOCK(sc); - bge_stop(sc); - bge_reset(sc); - BGE_UNLOCK(sc); - - callout_drain(&sc->bge_stat_ch); + if (device_is_attached(dev)) { + ether_ifdetach(ifp); + BGE_LOCK(sc); + bge_stop(sc); + BGE_UNLOCK(sc); + callout_drain(&sc->bge_stat_ch); + } if (sc->bge_tq) taskqueue_drain(sc->bge_tq, &sc->bge_intr_task); - ether_ifdetach(ifp); if (sc->bge_flags & BGE_FLAG_TBI) { ifmedia_removeall(&sc->bge_ifmedia); @@ -3764,6 +3775,7 @@ bge_reset(struct bge_softc *sc) BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); CSR_WRITE_4(sc, BGE_MAC_MODE, 0); + DELAY(40); /* * The 5704 in TBI mode apparently needs some special @@ -5041,9 +5053,11 @@ bge_init_locked(struct bge_softc *sc) } /* Turn on transmitter. */ CSR_WRITE_4(sc, BGE_TX_MODE, mode | BGE_TXMODE_ENABLE); + DELAY(100); /* Turn on receiver. */ BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); + DELAY(10); /* * Set the number of good frames to receive after RX MBUF @@ -5079,11 +5093,11 @@ bge_init_locked(struct bge_softc *sc) bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); } - bge_ifmedia_upd_locked(ifp); - ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + bge_ifmedia_upd_locked(ifp); + callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc); } @@ -5160,6 +5174,7 @@ bge_ifmedia_upd_locked(struct ifnet *ifp BGE_SETBIT(sc, BGE_MAC_MODE, BGE_MACMODE_HALF_DUPLEX); } + DELAY(40); break; default: return (EINVAL); @@ -5635,9 +5650,11 @@ bge_link_upd(struct bge_softc *sc) if (status & BGE_MACSTAT_TBI_PCS_SYNCHED) { if (!sc->bge_link) { sc->bge_link++; - if (sc->bge_asicrev == BGE_ASICREV_BCM5704) + if (sc->bge_asicrev == BGE_ASICREV_BCM5704) { BGE_CLRBIT(sc, BGE_MAC_MODE, BGE_MACMODE_TBI_SEND_CFGS); + DELAY(40); + } CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF); if (bootverbose) if_printf(sc->bge_ifp, "link UP\n");
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211260231.qAQ2VSJ2073039>