Date: Wed, 23 Nov 2011 23:29:19 +0000 (UTC) From: Pyun YongHyeon <yongari@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r227916 - in head/sys: dev/re pci Message-ID: <201111232329.pANNTJOn068037@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: yongari Date: Wed Nov 23 23:29:18 2011 New Revision: 227916 URL: http://svn.freebsd.org/changeset/base/227916 Log: To save more power, switch to 10/100Mbps link when controller is put into suspend/shutdown. Old PCI controllers performed that operation in firmware but for RTL8111C or newer controllers, it's responsibility of driver. It's not clear whether the firmware of RTL8111B still downgrades its speed to 10/100Mbps so leave it as it was. Modified: head/sys/dev/re/if_re.c head/sys/pci/if_rlreg.h Modified: head/sys/dev/re/if_re.c ============================================================================== --- head/sys/dev/re/if_re.c Wed Nov 23 22:16:45 2011 (r227915) +++ head/sys/dev/re/if_re.c Wed Nov 23 23:29:18 2011 (r227916) @@ -294,6 +294,7 @@ static void re_set_rxmode (struct rl_so static void re_reset (struct rl_softc *); static void re_setwol (struct rl_softc *); static void re_clrwol (struct rl_softc *); +static void re_set_linkspeed (struct rl_softc *); #ifdef RE_DIAG static int re_diag (struct rl_softc *); @@ -1431,17 +1432,18 @@ re_attach(device_t dev) case RL_HWREV_8168D: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP | - RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2; + RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 | RL_FLAG_WOL_MANLINK; break; case RL_HWREV_8168DP: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_AUTOPAD | - RL_FLAG_JUMBOV2 | RL_FLAG_WAIT_TXPOLL; + RL_FLAG_JUMBOV2 | RL_FLAG_WAIT_TXPOLL | RL_FLAG_WOL_MANLINK; break; case RL_HWREV_8168E: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | - RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2; + RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 | + RL_FLAG_WOL_MANLINK; break; case RL_HWREV_8168E_VL: case RL_HWREV_8168F: @@ -1449,7 +1451,7 @@ re_attach(device_t dev) sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2 | - RL_FLAG_CMDSTOP_WAIT_TXQ; + RL_FLAG_CMDSTOP_WAIT_TXQ | RL_FLAG_WOL_MANLINK; break; case RL_HWREV_8169_8110SB: case RL_HWREV_8169_8110SBL: @@ -3627,6 +3629,74 @@ re_shutdown(device_t dev) } static void +re_set_linkspeed(struct rl_softc *sc) +{ + struct mii_softc *miisc; + struct mii_data *mii; + int aneg, i, phyno; + + RL_LOCK_ASSERT(sc); + + mii = device_get_softc(sc->rl_miibus); + mii_pollstat(mii); + aneg = 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: + case IFM_100_TX: + return; + case IFM_1000_T: + aneg++; + break; + default: + break; + } + } + miisc = LIST_FIRST(&mii->mii_phys); + phyno = miisc->mii_phy; + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) + PHY_RESET(miisc); + re_miibus_writereg(sc->rl_dev, phyno, MII_100T2CR, 0); + re_miibus_writereg(sc->rl_dev, phyno, + MII_ANAR, ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA); + re_miibus_writereg(sc->rl_dev, phyno, + MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); + DELAY(1000); + if (aneg != 0) { + /* + * Poll link state until re(4) get a 10/100Mbps link. + */ + for (i = 0; i < MII_ANEGTICKS_GIGE; i++) { + mii_pollstat(mii); + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) + == (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + return; + default: + break; + } + } + RL_UNLOCK(sc); + pause("relnk", hz); + RL_LOCK(sc); + } + if (i == MII_ANEGTICKS_GIGE) + device_printf(sc->rl_dev, + "establishing a link failed, WOL may not work!"); + } + /* + * No link, force MAC to have 100Mbps, full-duplex link. + * MAC does not require reprogramming on resolved speed/duplex, + * so this is just for completeness. + */ + mii->mii_media_status = IFM_AVALID | IFM_ACTIVE; + mii->mii_media_active = IFM_ETHER | IFM_100_TX | IFM_FDX; +} + +static void re_setwol(struct rl_softc *sc) { struct ifnet *ifp; @@ -3648,6 +3718,8 @@ re_setwol(struct rl_softc *sc) } if ((ifp->if_capenable & IFCAP_WOL) != 0) { re_set_rxmode(sc); + if ((sc->rl_flags & RL_FLAG_WOL_MANLINK) != 0) + re_set_linkspeed(sc); if ((sc->rl_flags & RL_FLAG_WOLRXENB) != 0) CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RX_ENB); } Modified: head/sys/pci/if_rlreg.h ============================================================================== --- head/sys/pci/if_rlreg.h Wed Nov 23 22:16:45 2011 (r227915) +++ head/sys/pci/if_rlreg.h Wed Nov 23 23:29:18 2011 (r227916) @@ -914,6 +914,7 @@ struct rl_softc { #define RL_FLAG_MACSLEEP 0x00002000 #define RL_FLAG_WAIT_TXPOLL 0x00004000 #define RL_FLAG_CMDSTOP_WAIT_TXQ 0x00008000 +#define RL_FLAG_WOL_MANLINK 0x00010000 #define RL_FLAG_PCIE 0x40000000 #define RL_FLAG_LINK 0x80000000 };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201111232329.pANNTJOn068037>