From owner-svn-src-stable@FreeBSD.ORG Mon Feb 9 03:53:21 2009 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F0DF8106566B; Mon, 9 Feb 2009 03:53:20 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DD3468FC08; Mon, 9 Feb 2009 03:53:20 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n193rKIH044454; Mon, 9 Feb 2009 03:53:20 GMT (envelope-from yongari@svn.freebsd.org) Received: (from yongari@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n193rKkw044451; Mon, 9 Feb 2009 03:53:20 GMT (envelope-from yongari@svn.freebsd.org) Message-Id: <200902090353.n193rKkw044451@svn.freebsd.org> From: Pyun YongHyeon Date: Mon, 9 Feb 2009 03:53:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r188375 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fxp X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Feb 2009 03:53:21 -0000 Author: yongari Date: Mon Feb 9 03:53:20 2009 New Revision: 188375 URL: http://svn.freebsd.org/changeset/base/188375 Log: MFC r185354,185538: r185354: Add basic WOL support for 82550/82551/82558 and 82559 based controllers. ICH based controllers are treated as 82559. 82557, earlier revision of 82558 and 82559ER have no WOL capability. o WOL support requires help of a firmware so add check whether hardware is capable of handling magic frames by reading EEPROM. o Enable accepting WOL frames only when hardware is about to suspend or shutdown. Previously fxp(4) used to allow receipt of magic frame under normal operation mode which could cause hardware hang if magic frame is received by hardware. Datasheet clearly states driver should not allow WOL frames under normal operation mode. o Disable WOL frame reception in device attach so have fxp(4) immunize against system hang which can be triggered by magic packets when the hardware is not in fully initialized state. o Don't reset all hardware configuration data in fxp_stop() otherwise important configuration data is lost and this would reset WOL configuration to default state which in turn cause hardware hang on receipt of magic frames. To fix the issue, preserve hardware configuration data by issuing a selective reset. o Explicitly disable interrupts after issuing selective reset as reset may unmask interrupts. r185538: Make sure to clear PMDR register by writing back power management events. Just reading PMDR register was not enough to have fxp(4) immuninize against received magic packets during system boot. Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fxp/if_fxp.c stable/7/sys/dev/fxp/if_fxpreg.h stable/7/sys/dev/fxp/if_fxpvar.h Modified: stable/7/sys/dev/fxp/if_fxp.c ============================================================================== --- stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:48:49 2009 (r188374) +++ stable/7/sys/dev/fxp/if_fxp.c Mon Feb 9 03:53:20 2009 (r188375) @@ -405,7 +405,7 @@ fxp_attach(device_t dev) uint32_t val; uint16_t data, myea[ETHER_ADDR_LEN / 2]; u_char eaddr[ETHER_ADDR_LEN]; - int i, prefer_iomap; + int i, pmc, prefer_iomap; int error; error = 0; @@ -483,6 +483,17 @@ fxp_attach(device_t dev) sc->revision = pci_get_revid(dev); /* + * Check availability of WOL. 82559ER does not support WOL. + */ + if (sc->revision >= FXP_REV_82558_A4 && + sc->revision != FXP_REV_82559S_A) { + fxp_read_eeprom(sc, &data, 10, 1); + if ((data & 0x20) != 0 && + pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) + sc->flags |= FXP_FLAG_WOLCAP; + } + + /* * Determine whether we must use the 503 serial interface. */ fxp_read_eeprom(sc, &data, 6, 1); @@ -796,6 +807,11 @@ fxp_attach(device_t dev) ifp->if_capenable |= IFCAP_RXCSUM; } + if (sc->flags & FXP_FLAG_WOLCAP) { + ifp->if_capabilities |= IFCAP_WOL_MAGIC; + ifp->if_capenable |= IFCAP_WOL_MAGIC; + } + #ifdef DEVICE_POLLING /* Inform the world we support polling. */ ifp->if_capabilities |= IFCAP_POLLING; @@ -834,6 +850,19 @@ fxp_attach(device_t dev) goto fail; } + /* + * Configure hardware to reject magic frames otherwise + * system will hang on recipt of magic frames. + */ + if ((sc->flags & FXP_FLAG_WOLCAP) != 0) { + FXP_LOCK(sc); + /* Clear wakeup events. */ + CSR_WRITE_1(sc, FXP_CSR_PMDR, CSR_READ_1(sc, FXP_CSR_PMDR)); + fxp_init_body(sc); + fxp_stop(sc); + FXP_UNLOCK(sc); + } + fail: if (error) fxp_release(sc); @@ -956,17 +985,13 @@ fxp_detach(device_t dev) static int fxp_shutdown(device_t dev) { - struct fxp_softc *sc = device_get_softc(dev); /* * Make sure that DMA is disabled prior to reboot. Not doing * do could allow DMA to corrupt kernel memory during the * reboot before the driver initializes. */ - FXP_LOCK(sc); - fxp_stop(sc); - FXP_UNLOCK(sc); - return (0); + return (fxp_suspend(dev)); } /* @@ -978,9 +1003,25 @@ static int fxp_suspend(device_t dev) { struct fxp_softc *sc = device_get_softc(dev); + struct ifnet *ifp; + int pmc; + uint16_t pmstat; FXP_LOCK(sc); + ifp = sc->ifp; + if (pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) { + pmstat = pci_read_config(sc->dev, pmc + PCIR_POWER_STATUS, 2); + pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE); + if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) { + /* Request PME. */ + pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE; + sc->flags |= FXP_FLAG_WOL; + /* Reconfigure hardware to accept magic frames. */ + fxp_init_body(sc); + } + pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2); + } fxp_stop(sc); sc->suspended = 1; @@ -998,9 +1039,22 @@ fxp_resume(device_t dev) { struct fxp_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->ifp; + int pmc; + uint16_t pmstat; FXP_LOCK(sc); + if (pci_find_extcap(sc->dev, PCIY_PMG, &pmc) == 0) { + sc->flags &= ~FXP_FLAG_WOL; + pmstat = pci_read_config(sc->dev, pmc + PCIR_POWER_STATUS, 2); + /* Disable PME and clear PME status. */ + pmstat &= ~PCIM_PSTAT_PMEENABLE; + pci_write_config(sc->dev, pmc + PCIR_POWER_STATUS, pmstat, 2); + if ((sc->flags & FXP_FLAG_WOLCAP) != 0) + CSR_WRITE_1(sc, FXP_CSR_PMDR, + CSR_READ_1(sc, FXP_CSR_PMDR)); + } + CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); DELAY(10); @@ -2015,11 +2069,13 @@ fxp_stop(struct fxp_softc *sc) callout_stop(&sc->stat_ch); /* - * Issue software reset, which also unloads the microcode. + * Preserve PCI configuration, configure, IA/multicast + * setup and put RU and CU into idle state. */ - sc->flags &= ~FXP_FLAG_UCODE; - CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); + CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); DELAY(50); + /* Disable interrupts. */ + CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE); /* * Release any xmit buffers. @@ -2099,6 +2155,13 @@ fxp_init_body(struct fxp_softc *sc) */ fxp_stop(sc); + /* + * Issue software reset, which also unloads the microcode. + */ + sc->flags &= ~FXP_FLAG_UCODE; + CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET); + DELAY(50); + prm = (ifp->if_flags & IFF_PROMISC) ? 1 : 0; /* @@ -2215,8 +2278,7 @@ fxp_init_body(struct fxp_softc *sc) cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */ cbp->long_rx_en = sc->flags & FXP_FLAG_LONG_PKT_EN ? 1 : 0; cbp->ia_wake_en = 0; /* (don't) wake up on address match */ - cbp->magic_pkt_dis = 0; /* (don't) disable magic packet */ - /* must set wake_en in PMCSR also */ + cbp->magic_pkt_dis = sc->flags & FXP_FLAG_WOL ? 0 : 1; cbp->force_fdx = 0; /* (don't) force full duplex */ cbp->fdx_pin_en = 1; /* (enable) FDX# pin */ cbp->multi_ia = 0; /* (don't) accept multiple IAs */ @@ -2687,6 +2749,9 @@ fxp_ioctl(struct ifnet *ifp, u_long comm else ifp->if_hwassist &= ~CSUM_TSO; } + if ((mask & IFCAP_WOL_MAGIC) != 0 && + (ifp->if_capabilities & IFCAP_WOL_MAGIC) != 0) + ifp->if_capenable ^= IFCAP_WOL_MAGIC; if ((mask & IFCAP_VLAN_MTU) != 0 && (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) { ifp->if_capenable ^= IFCAP_VLAN_MTU; Modified: stable/7/sys/dev/fxp/if_fxpreg.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:48:49 2009 (r188374) +++ stable/7/sys/dev/fxp/if_fxpreg.h Mon Feb 9 03:53:20 2009 (r188375) @@ -46,6 +46,7 @@ #define FXP_CSR_EEPROMCONTROL 14 /* eeprom control (2 bytes) */ #define FXP_CSR_MDICONTROL 16 /* mdi control (4 bytes) */ #define FXP_CSR_FLOWCONTROL 0x19 /* flow control (2 bytes) */ +#define FXP_CSR_PMDR 0x1B /* power management driver (1 byte) */ #define FXP_CSR_GENCONTROL 0x1C /* general control (1 byte) */ /* Modified: stable/7/sys/dev/fxp/if_fxpvar.h ============================================================================== --- stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:48:49 2009 (r188374) +++ stable/7/sys/dev/fxp/if_fxpvar.h Mon Feb 9 03:53:20 2009 (r188375) @@ -201,6 +201,8 @@ struct fxp_softc { #define FXP_FLAG_EXT_RFA 0x0400 /* extended RFDs for csum offload */ #define FXP_FLAG_SAVE_BAD 0x0800 /* save bad pkts: bad size, CRC, etc */ #define FXP_FLAG_82559_RXCSUM 0x1000 /* 82559 compatible RX checksum */ +#define FXP_FLAG_WOLCAP 0x2000 /* WOL capability */ +#define FXP_FLAG_WOL 0x4000 /* WOL active */ /* Macros to ease CSR access. */ #define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg)