Call for testers: fxp(4) WOL
Pyun YongHyeon
pyunyh at gmail.com
Sat Nov 8 00:01:44 PST 2008
On Fri, Nov 07, 2008 at 08:48:44PM +0100, Alexey Shuvaev wrote:
> On Tue, Nov 04, 2008 at 10:42:46AM +0900, Pyun YongHyeon wrote:
> > On Mon, Nov 03, 2008 at 07:35:56PM +0100, Alexey Shuvaev wrote:
> > > Here are relevant messages from the verbose boot:
> > >
> > > fxp0: <Intel 82801CAM (ICH3) Pro/100 VE Ethernet> port 0xdf40-0xdf7f mem 0xfceff000-0xfcefffff irq 11 at device 8.0 on pci2
> >
> > If it's based on ICH controller it would be 82559.
> >
> > > fxp0: Reserved 0x1000 bytes for rid 0x10 type 3 at 0xfceff000
> > > fxp0: using memory space register mapping
> > > fxp0: PCI IDs: 8086 1031 1179 0001 0042
> > > fxp0: Dynamic Standby mode is disabled
> > > miibus0: <MII bus> on fxp0
> > > fxp0: XXX: driver didn't set ifq_maxlen
> > > ^^^
> > > Is this something to fix?
> > >
> >
> > fxp(4) didn't set ifq_maxlen and if_attach corrected this with
> > its default value. Normally network device drivers set this queue
> > length to number of Tx descriptors but it's completely up to
> > driver writers and I don't see compeling reason to change that.
> >
> Ok, I just was attracted by something with 'XXX'.
>
> > > However the system seems to honors only the BIOS settings, if I enable WOL in
> > > the BIOS the system wakes up from power-down or suspend (to ram) states
> > > regardless of fxp settings and with disabled WOL in BIOS it never
> > > wakes up.
> > >
> >
> > Yes that's an expected behaviour. BIOS option should be changed to
> > enable WOL if you want to wake up your box from power down. If
> > you don't want to wake up your box regardless of BIOS configuration
> > you have to disable WOL with ifconfig before shutting down your
> > box. Likewise even if you enable WOL with ifconfig(8) to wake up
> > your system, BIOS WOL option also should be enabled to make it
> > work.
> >
> > > The worse thing I have noticed is if I send WOL packet while the system is
> > > running it reliably hangs. It does not panic and switching virtual
> > > consoles works (and typing/deleting something in the shell prompt too),
> > > but the cooler runs at full power and you can't do anything else.
> > > This is both with patched fxp and that from -CURRENT.
> >
> > Hmm, I think that was old bebahviour of stock fxp(4). Previously
> > fxp(4) was programmed to accept WOL packets regardless of running
> > state of hardware. With my patch the WOL should be disabled for
> > normal operation and WOL is enabled again when you shutdown your
> > box. If sotck fxp(4) also show the same behaviour it's big security
> > hole.
> > ATM I have no idea how WOL packets can affect running box. :-(
> >
> I have tested more thoroughly and here are the results.
>
> FreeBSD-CURRENT (late oktober) without your patch
> (is it what you call 'stock'?):
Yes.
> interface up or down, WOL disabled or enabled in the BIOS -
> system hangs when receiving WOL packet.
> Breaking to debugger shows kernel running, namely 3 acpi threads,
> acpi_task_[0-2].
This is critical issue, your box is vulnerable to WOL attack.
> FreeBSD-CURRENT from 4 Nov 2008 with your patch:
> again, with WOL enabled in BIOS or not, system hangs with WOL packet,
> but only if interface is down.
> With interface (fxp0) up and running, nothing happens.
> However, I failed to disable WOL with ifconfig, notebook boots
> always when WOL enabled in the BIOS.
Maybe BIOS doesn't honor preprogrammed PCI configuration data?
Or the reset command in fxp_stop() might cleared some important
configuration data.
> Linux-Ubuntu uname: Linux ubuntu 2.6.22-14-generic #1 SMP
> Sun Oct 14 23:05:12 GMT 2007 i686 GNU/Linux (booted live from CD)
> The same results as with FreeBSD-CURRENT with your patch.
> Disabling wol with ethtool does not produce the desired results.
> Receiving WOL packet when interface is down does not hang the system,
> but it (according to top) consumes 70% in system with
> kacpid process consuming 98.5% of cpu.
>
Thanks a lot for your testing!
> > Thanks for testing. I'll think again.
> > By chance can you try Linux on your system and check whether it
> > works?
> >
> So, it seems your patch is making FreeBSD on par with Linux.
> If you need something more, you are welcome!
I still have no clue yet but would you try attached one after
backing out previous patch?
--
Regards,
Pyun YongHyeon
-------------- next part --------------
Index: sys/dev/fxp/if_fxp.c
===================================================================
--- sys/dev/fxp/if_fxp.c (revision 184742)
+++ sys/dev/fxp/if_fxp.c (working copy)
@@ -402,7 +402,7 @@
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;
@@ -480,6 +480,16 @@
sc->revision = pci_get_revid(dev);
/*
+ * Check availability of WOL.
+ */
+ if (sc->revision >= FXP_REV_82558_A4) {
+ 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);
@@ -778,6 +788,11 @@
ifp->if_capenable |= IFCAP_HWCSUM;
}
+ 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;
@@ -938,17 +953,13 @@
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));
}
/*
@@ -960,11 +971,27 @@
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;
FXP_UNLOCK(sc);
@@ -980,9 +1007,23 @@
{
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_WOL) != 0) {
+ /* Clear wakeup events. */
+ CSR_READ_1(sc, FXP_CSR_PMDR);
+ }
+ }
+
CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
DELAY(10);
@@ -1848,11 +1889,13 @@
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.
@@ -1932,6 +1975,13 @@
*/
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;
/*
@@ -2047,8 +2097,7 @@
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 */
@@ -2458,6 +2507,10 @@
}
}
#endif
+ if ((mask & IFCAP_WOL_MAGIC) != 0 &&
+ (ifp->if_capabilities & IFCAP_WOL_MAGIC) != 0)
+ ifp->if_capenable ^= IFCAP_WOL_MAGIC;
+
if (mask & IFCAP_VLAN_MTU) {
FXP_LOCK(sc);
ifp->if_capenable ^= IFCAP_VLAN_MTU;
Index: sys/dev/fxp/if_fxpreg.h
===================================================================
--- sys/dev/fxp/if_fxpreg.h (revision 184742)
+++ sys/dev/fxp/if_fxpreg.h (working copy)
@@ -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) */
/*
Index: sys/dev/fxp/if_fxpvar.h
===================================================================
--- sys/dev/fxp/if_fxpvar.h (revision 184742)
+++ sys/dev/fxp/if_fxpvar.h (working copy)
@@ -193,6 +193,8 @@
#define FXP_FLAG_DEFERRED_RNR 0x0200 /* DEVICE_POLLING deferred RNR */
#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_WOLCAP 0x1000 /* WOL supported */
+#define FXP_FLAG_WOL 0x2000 /* WOL active */
/* Macros to ease CSR access. */
#define CSR_READ_1(sc, reg) bus_read_1(sc->fxp_res[0], reg)
More information about the freebsd-current
mailing list