From owner-freebsd-net@FreeBSD.ORG Tue Nov 9 01:15:11 2010 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4DA69106566B for ; Tue, 9 Nov 2010 01:15:11 +0000 (UTC) (envelope-from pyunyh@gmail.com) Received: from mail-iw0-f182.google.com (mail-iw0-f182.google.com [209.85.214.182]) by mx1.freebsd.org (Postfix) with ESMTP id F1A1C8FC1A for ; Tue, 9 Nov 2010 01:15:10 +0000 (UTC) Received: by iwn39 with SMTP id 39so6896098iwn.13 for ; Mon, 08 Nov 2010 17:15:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:received:from:date:to:cc :subject:message-id:reply-to:references:mime-version:content-type :content-disposition:in-reply-to:user-agent; bh=L6RvDKXl/n2lMA54UKqEFhLJvOy5tBKberMOLvhZfvk=; b=PEzPKia76IrhZomW/KVYuP0RV4ATWXRLT2TXyx1Nz8TzD93JlpmDdsLi4VHZojdI4B 1UjXLfExU4DXKtDMgccVCt70yxvkjvrL7D6hw0B/i717Pu056TIyZoYX20oTJvdnCrhL 8LWC063bLbDPhvU1L9OvzgAIUlZTCbZUjGgvE= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:date:to:cc:subject:message-id:reply-to:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=w1zfmyhvUuGrstPAm/eUcVghJrPx1bWU4VD7OX79c82u+xpxB0XEQkYTZOKQ//IEiK RJ4U25O8g0JHyJPYBqLK5QX3SnjpEA13txp+L6GLOCrGlVDcR+WfIFV1Is8zGlHqOBSp A15cwwlvY51P5yIU5RXYvrhFnPFJA4pwxvgGs= Received: by 10.231.59.197 with SMTP id m5mr4714029ibh.94.1289265308879; Mon, 08 Nov 2010 17:15:08 -0800 (PST) Received: from pyunyh@gmail.com ([174.35.1.224]) by mx.google.com with ESMTPS id 34sm538040ibi.2.2010.11.08.17.15.05 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 08 Nov 2010 17:15:06 -0800 (PST) Received: by pyunyh@gmail.com (sSMTP sendmail emulation); Mon, 8 Nov 2010 17:14:10 -0800 From: Pyun YongHyeon Date: Mon, 8 Nov 2010 17:14:10 -0800 To: Yamagi Burmeister Message-ID: <20101109011410.GB1275@michelle.cdnetworks.com> References: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="HcAYCG3uE/tztfnV" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.3i Cc: freebsd-net@freebsd.org Subject: Re: [patch] WOL support for nfe(4) X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: pyunyh@gmail.com List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Nov 2010 01:15:11 -0000 --HcAYCG3uE/tztfnV Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Nov 05, 2010 at 11:10:37AM +0100, Yamagi Burmeister wrote: > 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. > Thanks for the patch. I attached slightly modified the code to better match other WOL capable drivers in tree. Because data sheet is not available I blindly made a patch based on your code. I have a couple of questions which I can't verify it on real hardware(I have no more access to the hardware). o If you established a gigabit link with link partner and shutdown your box, does the established link automatically change to 10 or 100Mbps? You can check it on your link partner. If your link partner still reports it established 1000Mbps link, we have to do other necessary work in driver(i.e. manually switching to 10/100Mbps). o When you put your box into suspend mode, can you wake up your box with WOL magic packet? o When your system boots up with/without WOL magic packet, sending WOL magic packets from other hosts can hang your box? o If you disabled WOL with ifconfig before system shutdown, can you still wakeup your box with WOL magic packet? o If you reprogram your station address with ifconfig(i.e. ifconfig nfe0 ether xx:xx:xx:xx:xx:xx), can you still wakeup your box with WOL magic packet? The patch I made didn't take into account management firmware so if you use the patch with IMPI, IMPI wouldn't work. But I think that's not an issue since all other parts of nfe(4) also ignores management firmware at this moment. --HcAYCG3uE/tztfnV Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="nfe.wol.patch" Index: sys/dev/nfe/if_nfe.c =================================================================== --- sys/dev/nfe/if_nfe.c (revision 214989) +++ sys/dev/nfe/if_nfe.c (working copy) @@ -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_set_wol(struct nfe_softc *); #ifdef NFE_DEBUG static int nfedebug = 0; @@ -586,6 +587,9 @@ if ((ifp->if_capabilities & IFCAP_HWCSUM) != 0) ifp->if_capabilities |= IFCAP_VLAN_HWCSUM; } + + if (pci_find_extcap(dev, PCIY_PMG, ®) == 0) + ifp->if_capabilities |= IFCAP_WOL_MAGIC; ifp->if_capenable = ifp->if_capabilities; /* @@ -752,6 +756,7 @@ NFE_LOCK(sc); nfe_stop(sc->nfe_ifp); + nfe_set_wol(sc); sc->nfe_suspended = 1; NFE_UNLOCK(sc); @@ -768,6 +773,7 @@ sc = device_get_softc(dev); NFE_LOCK(sc); + nfe_power(sc); ifp = sc->nfe_ifp; if (ifp->if_flags & IFF_UP) nfe_init_locked(sc); @@ -1714,6 +1720,10 @@ } } #endif /* DEVICE_POLLING */ + if ((mask & IFCAP_WOL_MAGIC) != 0 && + (ifp->if_capabilities & IFCAP_WOL_MAGIC) != 0) + ifp->if_capenable ^= IFCAP_WOL_MAGIC; + if ((sc->nfe_flags & NFE_HW_CSUM) != 0 && (mask & IFCAP_HWCSUM) != 0) { ifp->if_capenable ^= IFCAP_HWCSUM; @@ -2746,7 +2756,8 @@ 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); + /* Disable WOL. */ + NFE_WRITE(sc, NFE_WOL_CTL, 0); sc->rxtxctl &= ~NFE_RXTX_BIT2; NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); @@ -2917,18 +2928,8 @@ static int nfe_shutdown(device_t dev) { - struct nfe_softc *sc; - struct ifnet *ifp; - sc = device_get_softc(dev); - - NFE_LOCK(sc); - ifp = sc->nfe_ifp; - nfe_stop(ifp); - /* nfe_reset(sc); */ - NFE_UNLOCK(sc); - - return (0); + return (nfe_suspend(dev)); } @@ -3212,3 +3213,39 @@ stats->rx_broadcast += NFE_READ(sc, NFE_TX_BROADCAST); } } + +static void +nfe_set_wol(struct nfe_softc *sc) +{ + struct ifnet *ifp; + uint32_t wolctl; + int pmc; + uint16_t pmstat; + + NFE_LOCK_ASSERT(sc); + + if (pci_find_extcap(sc->nfe_dev, PCIY_PMG, &pmc) != 0) + return; + ifp = sc->nfe_ifp; + if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) + wolctl = NFE_WOL_MAGIC; + else + wolctl = 0; + NFE_WRITE(sc, NFE_WOL_CTL, wolctl); + if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) { + if ((sc->nfe_flags & NFE_PWR_MGMT) != 0) + NFE_WRITE(sc, NFE_PWR2_CTL, + NFE_READ(sc, NFE_PWR2_CTL) & ~NFE_PWR2_GATE_CLOCKS); + /* Enable RX. */ + NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, 0); + NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, 0); + NFE_WRITE(sc, NFE_RX_CTL, NFE_READ(sc, NFE_RX_CTL) | + NFE_RX_START); + } + /* Request PME if WOL is requested. */ + pmstat = pci_read_config(sc->nfe_dev, pmc + PCIR_POWER_STATUS, 2); + pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); + if ((ifp->if_capenable & IFCAP_WOL) != 0) + pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; + pci_write_config(sc->nfe_dev, pmc + PCIR_POWER_STATUS, pmstat, 2); +} Index: sys/dev/nfe/if_nfereg.h =================================================================== --- sys/dev/nfe/if_nfereg.h (revision 214989) +++ sys/dev/nfe/if_nfereg.h (working copy) @@ -190,6 +190,7 @@ #define NFE_PWR2_WAKEUP_MASK 0x0f11 #define NFE_PWR2_REVA3 (1 << 0) +#define NFE_PWR2_GATE_CLOCKS 0x0f00 #define NFE_MEDIA_SET 0x10000 #define NFE_MEDIA_1000T 0x00032 --HcAYCG3uE/tztfnV--