Date: Fri, 5 Nov 2010 11:10:37 +0100 (CET) From: Yamagi Burmeister <lists@yamagi.org> To: freebsd-net@freebsd.org Subject: [patch] WOL support for nfe(4) Message-ID: <alpine.BSF.2.00.1011051057350.9984@saya.home.yamagi.org>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] Hi, some time ago we migrated a lot of boxes from Linux to FreeBSD. Those machines have a "NVIDIA nForce4 CK804 MCP4" network adapter, supported by nfe(4). Even if nfe(4) at least tries to enable the WOL capability of the NIC it doesn't work and nfe(4) doesn't integrate with FreeBSDs (new) WOL framework. Since we are in need of WOL I spend some minutes to implement it the correct way. Attached are two patches: - if_nfe_wol_8.1.diff against FreeBSD 8.1-RELEASE-p1, this one is used on our servers. - if_nfe_wol_current.diff against -CURRENT r214831. This one is _untested_! But it should work... In case that the patches a stripped by mailman they can be found here: http://deponie.yamagi.org/freebsd/nfe/ This patch works reliable on our machines and nfe(4) runs without any problems with it. But nevertheless my skills in writting network drivers are somewhat limited therefor a review by somewhat with better knowledge of the WOL framework and maybe nfe(4) itself is highly anticipated. Ciao, Yamagi -- Homepage: www.yamagi.org Jabber: yamagi@yamagi.org GnuPG/GPG: 0xEFBCCBCB [-- Attachment #2 --] --- if_nfe.c 2010-11-05 10:41:04.672351879 +0100 +++ if_nfe.c 2010-11-05 10:41:09.259689584 +0100 @@ -125,6 +125,7 @@ static void nfe_sysctl_node(struct nfe_softc *); static void nfe_stats_clear(struct nfe_softc *); static void nfe_stats_update(struct nfe_softc *); +static void nfe_enable_wol(struct nfe_softc *); #ifdef NFE_DEBUG static int nfedebug = 0; @@ -599,6 +600,10 @@ ifp->if_capabilities |= IFCAP_POLLING; #endif + /* Wake on LAN support */ + ifp->if_capabilities |= IFCAP_WOL_MAGIC; + ifp->if_capenable = ifp->if_capabilities; + /* Do MII setup */ error = mii_attach(dev, &sc->nfe_miibus, ifp, nfe_ifmedia_upd, nfe_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); @@ -769,6 +774,10 @@ NFE_LOCK(sc); ifp = sc->nfe_ifp; + + /* Disable WOL bits */ + NFE_WRITE(sc, NFE_WOL_CTL, 0); + if (ifp->if_flags & IFF_UP) nfe_init_locked(sc); sc->nfe_suspended = 0; @@ -1752,6 +1761,12 @@ ifp->if_hwassist &= ~CSUM_TSO; } + if ((mask & IFCAP_WOL) != 0 && + (ifp->if_capabilities & IFCAP_WOL) != 0) { + if ((mask & IFCAP_WOL_MAGIC) != 0) + ifp->if_capenable ^= IFCAP_WOL_MAGIC; + } + if (init > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { ifp->if_drv_flags &= ~IFF_DRV_RUNNING; nfe_init(sc); @@ -2746,7 +2761,6 @@ NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC); NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC); - NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); sc->rxtxctl &= ~NFE_RXTX_BIT2; NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); @@ -2806,12 +2820,6 @@ /* abort Tx */ NFE_WRITE(sc, NFE_TX_CTL, 0); - /* disable Rx */ - NFE_WRITE(sc, NFE_RX_CTL, 0); - - /* disable interrupts */ - nfe_disable_intr(sc); - sc->nfe_link = 0; /* free Rx and Tx mbufs still in the queues. */ @@ -2923,9 +2931,12 @@ sc = device_get_softc(dev); NFE_LOCK(sc); + nfe_enable_wol(sc); + NFE_UNLOCK(sc); + + NFE_LOCK(sc); ifp = sc->nfe_ifp; nfe_stop(ifp); - /* nfe_reset(sc); */ NFE_UNLOCK(sc); return (0); @@ -3212,3 +3223,17 @@ stats->rx_broadcast += NFE_READ(sc, NFE_TX_BROADCAST); } } + +static void +nfe_enable_wol(struct nfe_softc *sc) +{ + struct ifnet *ifp; + + NFE_LOCK_ASSERT(sc); + + ifp = sc->nfe_ifp; + + if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) + NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); +} + [-- Attachment #3 --] --- if_nfe.c 2010-11-05 10:36:43.300738161 +0100 +++ if_nfe.c 2010-11-05 10:39:04.712603916 +0100 @@ -125,6 +125,7 @@ static void nfe_sysctl_node(struct nfe_softc *); static void nfe_stats_clear(struct nfe_softc *); static void nfe_stats_update(struct nfe_softc *); +static void nfe_enable_wol(struct nfe_softc *); #ifdef NFE_DEBUG static int nfedebug = 0; @@ -600,6 +601,10 @@ ifp->if_capabilities |= IFCAP_POLLING; #endif + /* Wake on LAN support */ + ifp->if_capabilities |= IFCAP_WOL_MAGIC; + ifp->if_capenable = ifp->if_capabilities; + /* Do MII setup */ if (mii_phy_probe(dev, &sc->nfe_miibus, nfe_ifmedia_upd, nfe_ifmedia_sts)) { @@ -770,6 +775,10 @@ NFE_LOCK(sc); ifp = sc->nfe_ifp; + + /* Disable WOL bits */ + NFE_WRITE(sc, NFE_WOL_CTL, 0); + if (ifp->if_flags & IFF_UP) nfe_init_locked(sc); sc->nfe_suspended = 0; @@ -1753,6 +1762,12 @@ ifp->if_hwassist &= ~CSUM_TSO; } + if ((mask & IFCAP_WOL) != 0 && + (ifp->if_capabilities & IFCAP_WOL) != 0) { + if ((mask & IFCAP_WOL_MAGIC) != 0) + ifp->if_capenable ^= IFCAP_WOL_MAGIC; + } + if (init > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { ifp->if_drv_flags &= ~IFF_DRV_RUNNING; nfe_init(sc); @@ -2747,7 +2762,6 @@ NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC); NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC); - NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); sc->rxtxctl &= ~NFE_RXTX_BIT2; NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); @@ -2807,12 +2821,6 @@ /* abort Tx */ NFE_WRITE(sc, NFE_TX_CTL, 0); - /* disable Rx */ - NFE_WRITE(sc, NFE_RX_CTL, 0); - - /* disable interrupts */ - nfe_disable_intr(sc); - sc->nfe_link = 0; /* free Rx and Tx mbufs still in the queues. */ @@ -2924,9 +2932,12 @@ sc = device_get_softc(dev); NFE_LOCK(sc); + nfe_enable_wol(sc); + NFE_UNLOCK(sc); + + NFE_LOCK(sc); ifp = sc->nfe_ifp; nfe_stop(ifp); - /* nfe_reset(sc); */ NFE_UNLOCK(sc); return (0); @@ -3213,3 +3224,17 @@ stats->rx_broadcast += NFE_READ(sc, NFE_TX_BROADCAST); } } + +static void +nfe_enable_wol(struct nfe_softc *sc) +{ + struct ifnet *ifp; + + NFE_LOCK_ASSERT(sc); + + ifp = sc->nfe_ifp; + + if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) + NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); +} +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?alpine.BSF.2.00.1011051057350.9984>
