Date: Fri, 8 Oct 2010 20:33:43 +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-8@freebsd.org Subject: svn commit: r213616 - stable/8/sys/dev/sis Message-ID: <201010082033.o98KXhbi012875@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Fri Oct 8 20:33:43 2010 New Revision: 213616 URL: http://svn.freebsd.org/changeset/base/213616 Log: MFC r212116: Overhaul link state change handling. Previously sis(4) blindly configured TX/RX MACs before getting a valid link. After that, when link state change callback is called, it called device initialization again to reconfigure TX/RX MACs depending on resolved link state. This hack created several bad side effects and it required more hacks to not collide with sis_tick callback as well as disabling switching to currently selected media in device initialization. Also it seems sis(4) was used to be a template driver for long time so other drivers which was modeled after sis(4) also should be changed. TX/RX MACs are now reconfigured after getting a valid link. Fix for short cable error is also applied after getting a link because it's only valid when the resolved speed is 100Mbps. While I'm here slightly reorganize interrupt handler such that sis(4) always read SIS_ISR register to see whether the interrupt is ours or not. This change removes another hack and make it possible to nuke sis_stopped variable in softc. Modified: stable/8/sys/dev/sis/if_sis.c stable/8/sys/dev/sis/if_sisreg.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/sis/if_sis.c ============================================================================== --- stable/8/sys/dev/sis/if_sis.c Fri Oct 8 20:31:35 2010 (r213615) +++ stable/8/sys/dev/sis/if_sis.c Fri Oct 8 20:33:43 2010 (r213616) @@ -697,10 +697,86 @@ static void sis_miibus_statchg(device_t dev) { struct sis_softc *sc; + struct mii_data *mii; + struct ifnet *ifp; + uint32_t reg; sc = device_get_softc(dev); SIS_LOCK_ASSERT(sc); - sis_initl(sc); + + mii = device_get_softc(sc->sis_miibus); + ifp = sc->sis_ifp; + if (mii == NULL || ifp == NULL || + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + return; + + sc->sis_link = 0; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + sc->sis_link++; + CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_10); + break; + case IFM_100_TX: + sc->sis_link++; + CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_100); + break; + default: + break; + } + } + + if (sc->sis_link == 0) { + /* + * Stopping MACs seem to reset SIS_TX_LISTPTR and + * SIS_RX_LISTPTR which in turn requires resetting + * TX/RX buffers. So just don't do anything for + * lost link. + */ + return; + } + + /* Set full/half duplex mode. */ + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { + SIS_SETBIT(sc, SIS_TX_CFG, + (SIS_TXCFG_IGN_HBEAT | SIS_TXCFG_IGN_CARR)); + SIS_SETBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); + } else { + SIS_CLRBIT(sc, SIS_TX_CFG, + (SIS_TXCFG_IGN_HBEAT | SIS_TXCFG_IGN_CARR)); + SIS_CLRBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); + } + + if (sc->sis_type == SIS_TYPE_83816) { + /* + * MPII03.D: Half Duplex Excessive Collisions. + * Also page 49 in 83816 manual + */ + SIS_SETBIT(sc, SIS_TX_CFG, SIS_TXCFG_MPII03D); + } + + if (sc->sis_type == SIS_TYPE_83815 && sc->sis_srr < NS_SRR_16A && + IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) { + /* + * Short Cable Receive Errors (MP21.E) + */ + CSR_WRITE_4(sc, NS_PHY_PAGE, 0x0001); + reg = CSR_READ_4(sc, NS_PHY_DSPCFG) & 0xfff; + CSR_WRITE_4(sc, NS_PHY_DSPCFG, reg | 0x1000); + DELAY(100); + reg = CSR_READ_4(sc, NS_PHY_TDATA) & 0xff; + if ((reg & 0x0080) == 0 || (reg > 0xd8 && reg <= 0xff)) { + device_printf(sc->sis_dev, + "Applying short cable fix (reg=%x)\n", reg); + CSR_WRITE_4(sc, NS_PHY_TDATA, 0x00e8); + SIS_SETBIT(sc, NS_PHY_DSPCFG, 0x20); + } + CSR_WRITE_4(sc, NS_PHY_PAGE, 0); + } + /* Enable TX/RX MACs. */ + SIS_CLRBIT(sc, SIS_CSR, SIS_CSR_TX_DISABLE | SIS_CSR_RX_DISABLE); + SIS_SETBIT(sc, SIS_CSR, SIS_CSR_TX_ENABLE | SIS_CSR_RX_ENABLE); } static uint32_t @@ -1613,23 +1689,14 @@ sis_tick(void *xsc) sc = xsc; SIS_LOCK_ASSERT(sc); - sc->in_tick = 1; ifp = sc->sis_ifp; mii = device_get_softc(sc->sis_miibus); mii_tick(mii); - sis_watchdog(sc); - - if (!sc->sis_link && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->sis_link++; - if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - sis_startl(ifp); - } - + if (sc->sis_link == 0) + sis_miibus_statchg(sc->sis_dev); callout_reset(&sc->sis_stat_ch, hz, sis_tick, sc); - sc->in_tick = 0; } #ifdef DEVICE_POLLING @@ -1693,9 +1760,6 @@ sis_intr(void *arg) sc = arg; ifp = sc->sis_ifp; - if (sc->sis_stopped) /* Most likely shared interrupt */ - return; - SIS_LOCK(sc); #ifdef DEVICE_POLLING if (ifp->if_capenable & IFCAP_POLLING) { @@ -1704,17 +1768,17 @@ sis_intr(void *arg) } #endif + /* Reading the ISR register clears all interrupts. */ + status = CSR_READ_4(sc, SIS_ISR); + if ((status & SIS_INTRS) == 0) { + /* Not ours. */ + SIS_UNLOCK(sc); + } + /* Disable interrupts. */ CSR_WRITE_4(sc, SIS_IER, 0); - for (;;) { - SIS_LOCK_ASSERT(sc); - /* Reading the ISR register clears all interrupts. */ - status = CSR_READ_4(sc, SIS_ISR); - - if ((status & SIS_INTRS) == 0) - break; - + for (;(status & SIS_INTRS) != 0;) { if (status & (SIS_ISR_TX_DESC_OK | SIS_ISR_TX_ERR | SIS_ISR_TX_OK | SIS_ISR_TX_IDLE) ) @@ -1733,7 +1797,10 @@ sis_intr(void *arg) if (status & SIS_ISR_SYSERR) { sis_reset(sc); sis_initl(sc); + SIS_UNLOCK(sc); + return; } + status = CSR_READ_4(sc, SIS_ISR); } /* Re-enable interrupts. */ @@ -1908,7 +1975,6 @@ sis_initl(struct sis_softc *sc) * Cancel pending I/O and free all RX/TX buffers. */ sis_stop(sc); - sc->sis_stopped = 0; #ifdef notyet if (sc->sis_type == SIS_TYPE_83815 && sc->sis_srr >= NS_SRR_16A) { @@ -1972,7 +2038,6 @@ sis_initl(struct sis_softc *sc) CSR_WRITE_4(sc, NS_PHY_PAGE, 0); } - /* * For the NatSemi chip, we have to explicitly enable the * reception of ARP frames, as well as turn on the 'perfect @@ -2030,52 +2095,11 @@ sis_initl(struct sis_softc *sc) /* Accept Long Packets for VLAN support */ SIS_SETBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_JABBER); - /* Set TX configuration */ - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) { - CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_10); - } else { - CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_100); - } - - /* Set full/half duplex mode. */ - if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { - SIS_SETBIT(sc, SIS_TX_CFG, - (SIS_TXCFG_IGN_HBEAT|SIS_TXCFG_IGN_CARR)); - SIS_SETBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); - } else { - SIS_CLRBIT(sc, SIS_TX_CFG, - (SIS_TXCFG_IGN_HBEAT|SIS_TXCFG_IGN_CARR)); - SIS_CLRBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); - } - - if (sc->sis_type == SIS_TYPE_83816) { - /* - * MPII03.D: Half Duplex Excessive Collisions. - * Also page 49 in 83816 manual - */ - SIS_SETBIT(sc, SIS_TX_CFG, SIS_TXCFG_MPII03D); - } - - if (sc->sis_type == SIS_TYPE_83815 && sc->sis_srr < NS_SRR_16A && - IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) { - uint32_t reg; - - /* - * Short Cable Receive Errors (MP21.E) - */ - CSR_WRITE_4(sc, NS_PHY_PAGE, 0x0001); - reg = CSR_READ_4(sc, NS_PHY_DSPCFG) & 0xfff; - CSR_WRITE_4(sc, NS_PHY_DSPCFG, reg | 0x1000); - DELAY(100); - reg = CSR_READ_4(sc, NS_PHY_TDATA) & 0xff; - if ((reg & 0x0080) == 0 || (reg > 0xd8 && reg <= 0xff)) { - device_printf(sc->sis_dev, - "Applying short cable fix (reg=%x)\n", reg); - CSR_WRITE_4(sc, NS_PHY_TDATA, 0x00e8); - SIS_SETBIT(sc, NS_PHY_DSPCFG, 0x20); - } - CSR_WRITE_4(sc, NS_PHY_PAGE, 0); - } + /* + * Assume 100Mbps link, actual MAC configuration is done + * after getting a valid link. + */ + CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_100); /* * Enable interrupts. @@ -2092,19 +2116,16 @@ sis_initl(struct sis_softc *sc) #endif CSR_WRITE_4(sc, SIS_IER, 1); - /* Enable receiver and transmitter. */ - SIS_CLRBIT(sc, SIS_CSR, SIS_CSR_TX_DISABLE|SIS_CSR_RX_DISABLE); - SIS_SETBIT(sc, SIS_CSR, SIS_CSR_RX_ENABLE); + /* Clear MAC disable. */ + SIS_CLRBIT(sc, SIS_CSR, SIS_CSR_TX_DISABLE | SIS_CSR_RX_DISABLE); -#ifdef notdef + sc->sis_link = 0; mii_mediachg(mii); -#endif ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - if (!sc->in_tick) - callout_reset(&sc->sis_stat_ch, hz, sis_tick, sc); + callout_reset(&sc->sis_stat_ch, hz, sis_tick, sc); } /* @@ -2226,10 +2247,6 @@ sis_watchdog(struct sis_softc *sc) { SIS_LOCK_ASSERT(sc); - if (sc->sis_stopped) { - SIS_UNLOCK(sc); - return; - } if (sc->sis_watchdog_timer == 0 || --sc->sis_watchdog_timer >0) return; @@ -2257,9 +2274,8 @@ sis_stop(struct sis_softc *sc) struct sis_txdesc *txd; int i; - if (sc->sis_stopped) - return; SIS_LOCK_ASSERT(sc); + ifp = sc->sis_ifp; sc->sis_watchdog_timer = 0; @@ -2303,8 +2319,6 @@ sis_stop(struct sis_softc *sc) txd->tx_m = NULL; } } - - sc->sis_stopped = 1; } /* Modified: stable/8/sys/dev/sis/if_sisreg.h ============================================================================== --- stable/8/sys/dev/sis/if_sisreg.h Fri Oct 8 20:31:35 2010 (r213615) +++ stable/8/sys/dev/sis/if_sisreg.h Fri Oct 8 20:33:43 2010 (r213616) @@ -471,11 +471,9 @@ struct sis_softc { bus_addr_t sis_tx_paddr; struct callout sis_stat_ch; int sis_watchdog_timer; - int sis_stopped; #ifdef DEVICE_POLLING int rxcycles; #endif - int in_tick; struct mtx sis_mtx; };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010082033.o98KXhbi012875>