* Re: hibernate event order question [not found] ` <200805172156.12686.rjw@sisk.pl> @ 2008-05-17 22:36 ` Tobias Diedrich 2008-05-17 23:24 ` Tobias Diedrich 0 siblings, 1 reply; 8+ messages in thread From: Tobias Diedrich @ 2008-05-17 22:36 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: netdev, linux-kernel, Ayaz Abdulla Rafael J. Wysocki wrote: > > Now for my question: > > AFAICS the ordering of events is as follows: > > 1) User reqests hibernate > > 2) Tasks are frozen > > 3) Device suspend callbacks get called > > 4) Device resume callbacks get called > > 5) Memory image is written to disk > > 6) Device suspend callbacks get called again to prepare for the system sleep > state. According to my pci postcard this is not the case. I modified nv_suspend to wiggle port 0x80 with mdelay(100) between 0xa0/0x50 wiggles and mdelay(1000) before returning, so it is easily countable. nv_suspend is called only once per ethernet port (step 3 above). I have not yet tried adding a suspend_late handler. > > In my case, I think the fix for the first bug (promiscous mode does > > not get restored on resume) breaks wake-on-lan (since the new value > > of NvRegPacketFilterFlags may be incompatible with wake-on-lan). I reconfirmed this. Without the promiscous mode bugfix, wake-on-lan (partially) works. With the promiscous mode bugfix the machine doesn't wake up. This is also easily explainable by 6) not happening. :) > > Shouldn't there be a 'prepare for poweroff'-callback, which gets > > called > > before the system is powered off for real? > > Yes, it should and it's called in recent kernels. For what values of 'recent'? I'm running 2.6.26-rc2 here. :) How do I hook into this callback? (suspend_late maybe? Going to try that one next...) -- Tobias PGP: http://9ac7e0bc.uguu.de このメールは十割再利用されたビットで作られています。 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: hibernate event order question 2008-05-17 22:36 ` hibernate event order question Tobias Diedrich @ 2008-05-17 23:24 ` Tobias Diedrich 2008-05-18 10:45 ` Rafael J. Wysocki 0 siblings, 1 reply; 8+ messages in thread From: Tobias Diedrich @ 2008-05-17 23:24 UTC (permalink / raw) To: Rafael J. Wysocki, netdev, linux-kernel, Ayaz Abdulla Tobias Diedrich wrote: > > > Shouldn't there be a 'prepare for poweroff'-callback, which gets > > > called > > > before the system is powered off for real? > > > > Yes, it should and it's called in recent kernels. > > For what values of 'recent'? > I'm running 2.6.26-rc2 here. :) > How do I hook into this callback? > (suspend_late maybe? Going to try that one next...) Ok, this patch fixes the 'regression' introduced by the previous patch (at least for me ;)): Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c =================================================================== --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 01:10:18.000000000 +0200 +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 01:11:33.000000000 +0200 @@ -5828,8 +5828,24 @@ out: return rc; } + +static void nv_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + + if (netif_running(dev)) + nv_close(dev); + + pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); + pci_enable_wake(pdev, PCI_D3cold, np->wolenabled); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); +} #else #define nv_suspend NULL +#define nv_shutdown NULL #define nv_resume NULL #endif /* CONFIG_PM */ @@ -6000,6 +6016,7 @@ .remove = __devexit_p(nv_remove), .suspend = nv_suspend, .resume = nv_resume, + .shutdown = nv_shutdown, }; static int __init init_nic(void) -- Tobias PGP: http://9ac7e0bc.uguu.de このメールは十割再利用されたビットで作られています。 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: hibernate event order question 2008-05-17 23:24 ` Tobias Diedrich @ 2008-05-18 10:45 ` Rafael J. Wysocki 2008-05-18 11:22 ` Tobias Diedrich 0 siblings, 1 reply; 8+ messages in thread From: Rafael J. Wysocki @ 2008-05-18 10:45 UTC (permalink / raw) To: Tobias Diedrich; +Cc: netdev, linux-kernel, Ayaz Abdulla On Sunday, 18 of May 2008, Tobias Diedrich wrote: > Tobias Diedrich wrote: > > > > Shouldn't there be a 'prepare for poweroff'-callback, which gets > > > > called > > > > before the system is powered off for real? > > > > > > Yes, it should and it's called in recent kernels. > > > > For what values of 'recent'? > > I'm running 2.6.26-rc2 here. :) > > How do I hook into this callback? > > (suspend_late maybe? Going to try that one next...) > > Ok, this patch fixes the 'regression' introduced by the previous > patch (at least for me ;)): Well, what exactly do you do to hibernate the box? > Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c > =================================================================== > --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 01:10:18.000000000 +0200 > +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 01:11:33.000000000 +0200 > @@ -5828,8 +5828,24 @@ > out: > return rc; > } > + > +static void nv_shutdown(struct pci_dev *pdev) > +{ > + struct net_device *dev = pci_get_drvdata(pdev); > + struct fe_priv *np = netdev_priv(dev); > + u8 __iomem *base = get_hwbase(dev); > + > + if (netif_running(dev)) > + nv_close(dev); > + > + pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); > + pci_enable_wake(pdev, PCI_D3cold, np->wolenabled); > + pci_disable_device(pdev); > + pci_set_power_state(pdev, PCI_D3hot); > +} > #else > #define nv_suspend NULL > +#define nv_shutdown NULL > #define nv_resume NULL > #endif /* CONFIG_PM */ > > @@ -6000,6 +6016,7 @@ > .remove = __devexit_p(nv_remove), > .suspend = nv_suspend, > .resume = nv_resume, > + .shutdown = nv_shutdown, > }; > > static int __init init_nic(void) > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: hibernate event order question 2008-05-18 10:45 ` Rafael J. Wysocki @ 2008-05-18 11:22 ` Tobias Diedrich 2008-05-18 11:32 ` Rafael J. Wysocki 0 siblings, 1 reply; 8+ messages in thread From: Tobias Diedrich @ 2008-05-18 11:22 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: netdev, linux-kernel, Ayaz Abdulla Rafael J. Wysocki wrote: > On Sunday, 18 of May 2008, Tobias Diedrich wrote: > > Tobias Diedrich wrote: > > > > > Shouldn't there be a 'prepare for poweroff'-callback, which gets > > > > > called > > > > > before the system is powered off for real? > > > > > > > > Yes, it should and it's called in recent kernels. > > > > > > For what values of 'recent'? > > > I'm running 2.6.26-rc2 here. :) > > > How do I hook into this callback? > > > (suspend_late maybe? Going to try that one next...) > > > > Ok, this patch fixes the 'regression' introduced by the previous > > patch (at least for me ;)): > > Well, what exactly do you do to hibernate the box? /usr/local/bin/s2disk: |#!/bin/sh | |SYSPRINTK=/proc/sys/kernel/printk |OLDPRINTK=$(cat $SYSPRINTK) |chvt 1 |# work around forcedeth wake-on-lan bug |#rmmod forcedeth |echo 9 > $SYSPRINTK |# shutdown/reboot/platform |echo shutdown > /sys/power/disk |echo disk > /sys/power/state |echo "$OLDPRINTK" > $SYSPRINTK |# work around forcedeth wake-on-lan bug |#modprobe forcedeth |#brctl addif br0 eth0 |#brctl addif br0 eth1 |#ifconfig eth0 up |#ifconfig eth1 up I now also now why I get the 'swapped mac' problem: In my case (DEV_HAS_CORRECT_MACADDR unset and NVREG_TRANSMITPOLL_MAC_ADDR_REV unset on probe) nv_probe() reads the original macaddress in reversed order to correct it and sets NVREG_TRANSMITPOLL_MAC_ADDR_REV. However the suspend/resume path does not touch the mac address at all, so after a cold boot and resume from disk the macaddress is again in 'BIOS order' and NVREG_TRANSMITPOLL_MAC_ADDR_REV is unset, but NVREG_TRANSMITPOLL_MAC_ADDR_REV gets set unconditionally in nv_resume(), so the net effect is that the MAC is now reversed. With the promisc fix this is hidden for my brige setup and only noticeable at the next hibernate, where I now have to use a reversed MAC to wakeup the device. The following patch (on top of the other two) fixes this by saving and restoring the memory mapped device configuration space in suspend/resume. The shutdown hook is still needed since the promisc mode seems to be incompatible with wake on lan. It also reorders the code in suspend/resume to match that in e100/e1000e. (configuration space is also saved for devices that are not running) Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c =================================================================== --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 11:26:12.000000000 +0200 +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 13:00:23.000000000 +0200 @@ -426,6 +426,7 @@ #define NV_PCI_REGSZ_VER1 0x270 #define NV_PCI_REGSZ_VER2 0x2d4 #define NV_PCI_REGSZ_VER3 0x604 +#define NV_PCI_REGSZ_MAX 0x604 /* various timeout delays: all in usec */ #define NV_TXRX_RESET_DELAY 4 @@ -784,6 +785,9 @@ /* flow control */ u32 pause_flags; + + /* power saved state */ + u32 saved_config_space[NV_PCI_REGSZ_MAX/4]; }; /* @@ -5785,19 +5789,24 @@ { struct net_device *dev = pci_get_drvdata(pdev); struct fe_priv *np = netdev_priv(dev); - - if (!netif_running(dev)) - goto out; + u8 __iomem *base = get_hwbase(dev); + int i; netif_device_detach(dev); - // Gross. - nv_close(dev); + if (netif_running(dev)) { + // Gross. + nv_close(dev); + } + + /* save non-pci configuration space */ + for (i = 0;i <= np->register_size/sizeof(u32); i++) + np->saved_config_space[i] = readl(base + i*sizeof(u32)); pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); + pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); -out: return 0; } @@ -5805,27 +5814,25 @@ static int nv_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int rc = 0; - u32 txreg; - - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); + int i, rc = 0; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); + /* ack any pending wake events, disable PME */ pci_enable_wake(pdev, PCI_D0, 0); - /* restore mac address reverse flag */ - txreg = readl(base + NvRegTransmitPoll); - txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV; - writel(txreg, base + NvRegTransmitPoll); + /* restore non-pci configuration space */ + for (i = 0;i <= np->register_size/sizeof(u32); i++) + writel(np->saved_config_space[i], base+i*sizeof(u32)); + + netif_device_attach(dev); + if (netif_running(dev)) { + rc = nv_open(dev); + nv_set_multicast(dev); + } - rc = nv_open(dev); - nv_set_multicast(dev); -out: return rc; } @@ -5833,7 +5840,6 @@ { struct net_device *dev = pci_get_drvdata(pdev); struct fe_priv *np = netdev_priv(dev); - u8 __iomem *base = get_hwbase(dev); if (netif_running(dev)) nv_close(dev); @@ -5841,7 +5847,9 @@ pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); pci_enable_wake(pdev, PCI_D3cold, np->wolenabled); pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); + if (np->wolenabled) + pci_set_power_state(pdev, PCI_D3hot); + else pci_set_power_state(pdev, PCI_D3cold); } #else #define nv_suspend NULL -- Tobias PGP: http://9ac7e0bc.uguu.de このメールは十割再利用されたビットで作られています。 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: hibernate event order question 2008-05-18 11:22 ` Tobias Diedrich @ 2008-05-18 11:32 ` Rafael J. Wysocki 2008-05-18 12:24 ` Tobias Diedrich 0 siblings, 1 reply; 8+ messages in thread From: Rafael J. Wysocki @ 2008-05-18 11:32 UTC (permalink / raw) To: Tobias Diedrich; +Cc: netdev, linux-kernel, Ayaz Abdulla On Sunday, 18 of May 2008, Tobias Diedrich wrote: > Rafael J. Wysocki wrote: > > On Sunday, 18 of May 2008, Tobias Diedrich wrote: > > > Tobias Diedrich wrote: > > > > > > Shouldn't there be a 'prepare for poweroff'-callback, which gets > > > > > > called > > > > > > before the system is powered off for real? > > > > > > > > > > Yes, it should and it's called in recent kernels. > > > > > > > > For what values of 'recent'? > > > > I'm running 2.6.26-rc2 here. :) > > > > How do I hook into this callback? > > > > (suspend_late maybe? Going to try that one next...) > > > > > > Ok, this patch fixes the 'regression' introduced by the previous > > > patch (at least for me ;)): > > > > Well, what exactly do you do to hibernate the box? > > |#!/bin/sh > | > |SYSPRINTK=/proc/sys/kernel/printk > |OLDPRINTK=$(cat $SYSPRINTK) > |chvt 1 > |# work around forcedeth wake-on-lan bug > |#rmmod forcedeth > |echo 9 > $SYSPRINTK > |# shutdown/reboot/platform > |echo shutdown > /sys/power/disk You don't see the devices' suspend callbacks invoked before powering off because of this. Change that to 'platform' (unless that breaks things). > |echo disk > /sys/power/state > |echo "$OLDPRINTK" > $SYSPRINTK > |# work around forcedeth wake-on-lan bug > |#modprobe forcedeth > |#brctl addif br0 eth0 > |#brctl addif br0 eth1 > |#ifconfig eth0 up > |#ifconfig eth1 up > > I now also now why I get the 'swapped mac' problem: > > In my case (DEV_HAS_CORRECT_MACADDR unset and > NVREG_TRANSMITPOLL_MAC_ADDR_REV unset on probe) > nv_probe() reads the original macaddress in reversed order to > correct it and sets NVREG_TRANSMITPOLL_MAC_ADDR_REV. > > However the suspend/resume path does not touch the mac address at > all, so after a cold boot and resume from disk the macaddress is > again in 'BIOS order' and NVREG_TRANSMITPOLL_MAC_ADDR_REV is unset, > but NVREG_TRANSMITPOLL_MAC_ADDR_REV gets set unconditionally in > nv_resume(), so the net effect is that the MAC is now reversed. > > With the promisc fix this is hidden for my brige setup and only > noticeable at the next hibernate, where I now have to use a reversed > MAC to wakeup the device. > > The following patch (on top of the other two) fixes this by saving > and restoring the memory mapped device configuration space in > suspend/resume. The shutdown hook is still needed since the promisc > mode seems to be incompatible with wake on lan. > > It also reorders the code in suspend/resume to match that in e100/e1000e. > (configuration space is also saved for devices that are not running) I'm unable to comment on the device-specific things, but apart from this the patch looks okay to me except for one thing. > Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c > =================================================================== > --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 11:26:12.000000000 +0200 > +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 13:00:23.000000000 +0200 > @@ -426,6 +426,7 @@ > #define NV_PCI_REGSZ_VER1 0x270 > #define NV_PCI_REGSZ_VER2 0x2d4 > #define NV_PCI_REGSZ_VER3 0x604 > +#define NV_PCI_REGSZ_MAX 0x604 > > /* various timeout delays: all in usec */ > #define NV_TXRX_RESET_DELAY 4 > @@ -784,6 +785,9 @@ > > /* flow control */ > u32 pause_flags; > + > + /* power saved state */ > + u32 saved_config_space[NV_PCI_REGSZ_MAX/4]; > }; > > /* > @@ -5785,19 +5789,24 @@ > { > struct net_device *dev = pci_get_drvdata(pdev); > struct fe_priv *np = netdev_priv(dev); > - > - if (!netif_running(dev)) > - goto out; > + u8 __iomem *base = get_hwbase(dev); > + int i; > > netif_device_detach(dev); > > - // Gross. > - nv_close(dev); > + if (netif_running(dev)) { > + // Gross. > + nv_close(dev); > + } > + > + /* save non-pci configuration space */ > + for (i = 0;i <= np->register_size/sizeof(u32); i++) > + np->saved_config_space[i] = readl(base + i*sizeof(u32)); > > pci_save_state(pdev); > pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); > + pci_disable_device(pdev); > pci_set_power_state(pdev, pci_choose_state(pdev, state)); > -out: > > return 0; > } > @@ -5805,27 +5814,25 @@ > static int nv_resume(struct pci_dev *pdev) > { > struct net_device *dev = pci_get_drvdata(pdev); > + struct fe_priv *np = netdev_priv(dev); > u8 __iomem *base = get_hwbase(dev); > - int rc = 0; > - u32 txreg; > - > - if (!netif_running(dev)) > - goto out; > - > - netif_device_attach(dev); > + int i, rc = 0; > > pci_set_power_state(pdev, PCI_D0); > pci_restore_state(pdev); > + /* ack any pending wake events, disable PME */ > pci_enable_wake(pdev, PCI_D0, 0); > > - /* restore mac address reverse flag */ > - txreg = readl(base + NvRegTransmitPoll); > - txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV; > - writel(txreg, base + NvRegTransmitPoll); > + /* restore non-pci configuration space */ > + for (i = 0;i <= np->register_size/sizeof(u32); i++) > + writel(np->saved_config_space[i], base+i*sizeof(u32)); > + > + netif_device_attach(dev); > + if (netif_running(dev)) { > + rc = nv_open(dev); > + nv_set_multicast(dev); > + } > > - rc = nv_open(dev); > - nv_set_multicast(dev); > -out: > return rc; > } > > @@ -5833,7 +5840,6 @@ > { > struct net_device *dev = pci_get_drvdata(pdev); > struct fe_priv *np = netdev_priv(dev); > - u8 __iomem *base = get_hwbase(dev); > > if (netif_running(dev)) > nv_close(dev); > @@ -5841,7 +5847,9 @@ > pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); > pci_enable_wake(pdev, PCI_D3cold, np->wolenabled); > pci_disable_device(pdev); > - pci_set_power_state(pdev, PCI_D3hot); > + if (np->wolenabled) > + pci_set_power_state(pdev, PCI_D3hot); > + else pci_set_power_state(pdev, PCI_D3cold); I'm not sure if it's possible to put the device into D3cold without actually removing power from it. > } > #else > #define nv_suspend NULL > Thanks, Rafael ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: hibernate event order question 2008-05-18 11:32 ` Rafael J. Wysocki @ 2008-05-18 12:24 ` Tobias Diedrich 2008-05-18 12:29 ` Rafael J. Wysocki 0 siblings, 1 reply; 8+ messages in thread From: Tobias Diedrich @ 2008-05-18 12:24 UTC (permalink / raw) To: Rafael J. Wysocki; +Cc: netdev, linux-kernel, Ayaz Abdulla Rafael J. Wysocki wrote: > On Sunday, 18 of May 2008, Tobias Diedrich wrote: > > Rafael J. Wysocki wrote: > > > On Sunday, 18 of May 2008, Tobias Diedrich wrote: > > > > Tobias Diedrich wrote: > > > > > > > Shouldn't there be a 'prepare for poweroff'-callback, which gets > > > > > > > called > > > > > > > before the system is powered off for real? > > > > > > > > > > > > Yes, it should and it's called in recent kernels. > > > > > > > > > > For what values of 'recent'? > > > > > I'm running 2.6.26-rc2 here. :) > > > > > How do I hook into this callback? > > > > > (suspend_late maybe? Going to try that one next...) > > > > > > > > Ok, this patch fixes the 'regression' introduced by the previous > > > > patch (at least for me ;)): > > > > > > Well, what exactly do you do to hibernate the box? > > > > |#!/bin/sh > > | > > |SYSPRINTK=/proc/sys/kernel/printk > > |OLDPRINTK=$(cat $SYSPRINTK) > > |chvt 1 > > |# work around forcedeth wake-on-lan bug > > |#rmmod forcedeth > > |echo 9 > $SYSPRINTK > > |# shutdown/reboot/platform > > |echo shutdown > /sys/power/disk > > You don't see the devices' suspend callbacks invoked before powering off > because of this. Change that to 'platform' (unless that breaks things). Hmm, I think someone recommended to use shutdown since that is supposed to be more reliable. Anyway, I think the shutdown hook is good anyway since I suspect that if I do a normal system shutdown with promiscous mode still on, then wake-on-lan would also not work? I haven't checked that though. At least I think the shutdown hook won't hurt. :) > I'm unable to comment on the device-specific things, but apart from this the > patch looks okay to me except for one thing. > > + if (np->wolenabled) > > + pci_set_power_state(pdev, PCI_D3hot); > > + else pci_set_power_state(pdev, PCI_D3cold); > > I'm not sure if it's possible to put the device into D3cold without actually > removing power from it. Ok, I've cleaned it up a bit and split it up properly (I think): http://www.tdiedrich.de/~ranma/patches/forcedeth/2.6.26-rc2/ series: forcedeth.resume.promisc.patch forcedeth.hibernate.wol.patch forcedeth.swappedmac.patch forcedeth.reorder_suspend_resume.patch forcedeth.resume.promisc.patch: nv_open() resets multicast settings, call nv_set_multicast(dev) to restore them. (Maybe this should rather be moved into nv_open()) Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c =================================================================== --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 13:52:59.000000000 +0200 +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 13:53:02.000000000 +0200 @@ -5823,6 +5823,7 @@ writel(txreg, base + NvRegTransmitPoll); rc = nv_open(dev); + nv_set_multicast(dev); out: return rc; } forcedeth.hibernate.wol.patch: When hibernating in 'shutdown' mode, after saving the image the suspend hook is not called again. However, if the device is in promiscous mode, wake-on-lan will not work. This adds a shutdown hook to setup wake-on-lan before the final shutdown. Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c =================================================================== --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 13:53:02.000000000 +0200 +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 13:53:06.000000000 +0200 @@ -5827,8 +5827,23 @@ out: return rc; } + +static void nv_shutdown(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct fe_priv *np = netdev_priv(dev); + + if (netif_running(dev)) + nv_close(dev); + + pci_enable_wake(pdev, PCI_D3hot, np->wolenabled); + pci_enable_wake(pdev, PCI_D3cold, np->wolenabled); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); +} #else #define nv_suspend NULL +#define nv_shutdown NULL #define nv_resume NULL #endif /* CONFIG_PM */ @@ -5999,6 +6014,7 @@ .remove = __devexit_p(nv_remove), .suspend = nv_suspend, .resume = nv_resume, + .shutdown = nv_shutdown, }; static int __init init_nic(void) forcedeth.swappedmac.patch: The memory mapped device configuration space is lost during hibernate. Save and restore it (fixes 'swapped mac' problem). Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c =================================================================== --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 13:53:06.000000000 +0200 +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 13:53:10.000000000 +0200 @@ -426,6 +426,7 @@ #define NV_PCI_REGSZ_VER1 0x270 #define NV_PCI_REGSZ_VER2 0x2d4 #define NV_PCI_REGSZ_VER3 0x604 +#define NV_PCI_REGSZ_MAX 0x604 /* various timeout delays: all in usec */ #define NV_TXRX_RESET_DELAY 4 @@ -784,6 +785,9 @@ /* flow control */ u32 pause_flags; + + /* power saved state */ + u32 saved_config_space[NV_PCI_REGSZ_MAX/4]; }; /* @@ -5785,6 +5789,8 @@ { struct net_device *dev = pci_get_drvdata(pdev); struct fe_priv *np = netdev_priv(dev); + u8 __iomem *base = get_hwbase(dev); + int i; if (!netif_running(dev)) goto out; @@ -5794,6 +5800,10 @@ // Gross. nv_close(dev); + /* save non-pci configuration space */ + for (i = 0;i <= np->register_size/sizeof(u32); i++) + np->saved_config_space[i] = readl(base + i*sizeof(u32)); + pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); pci_set_power_state(pdev, pci_choose_state(pdev, state)); @@ -5804,9 +5814,9 @@ static int nv_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); - int rc = 0; - u32 txreg; + int i, rc = 0; if (!netif_running(dev)) goto out; @@ -5817,10 +5827,9 @@ pci_restore_state(pdev); pci_enable_wake(pdev, PCI_D0, 0); - /* restore mac address reverse flag */ - txreg = readl(base + NvRegTransmitPoll); - txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV; - writel(txreg, base + NvRegTransmitPoll); + /* restore non-pci configuration space */ + for (i = 0;i <= np->register_size/sizeof(u32); i++) + writel(np->saved_config_space[i], base+i*sizeof(u32)); rc = nv_open(dev); nv_set_multicast(dev); forcedeth.reorder_suspend_resume.patch: Match the suspend/resume code ordering in e100/e1000e more closely. For example the configuration space should be saved on suspend even for devices that are not up. Index: linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c =================================================================== --- linux-2.6.26-rc2.forcedwol.orig/drivers/net/forcedeth.c 2008-05-18 13:53:10.000000000 +0200 +++ linux-2.6.26-rc2.forcedwol/drivers/net/forcedeth.c 2008-05-18 13:54:04.000000000 +0200 @@ -5792,22 +5792,20 @@ u8 __iomem *base = get_hwbase(dev); int i; - if (!netif_running(dev)) - goto out; - + if (netif_running(dev)) { + // Gross. + nv_close(dev); + } netif_device_detach(dev); - // Gross. - nv_close(dev); - /* save non-pci configuration space */ for (i = 0;i <= np->register_size/sizeof(u32); i++) np->saved_config_space[i] = readl(base + i*sizeof(u32)); pci_save_state(pdev); pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); + pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); -out: return 0; } @@ -5818,22 +5816,20 @@ u8 __iomem *base = get_hwbase(dev); int i, rc = 0; - if (!netif_running(dev)) - goto out; - - netif_device_attach(dev); - pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); + /* ack any pending wake events, disable PME */ pci_enable_wake(pdev, PCI_D0, 0); /* restore non-pci configuration space */ for (i = 0;i <= np->register_size/sizeof(u32); i++) writel(np->saved_config_space[i], base+i*sizeof(u32)); - rc = nv_open(dev); - nv_set_multicast(dev); -out: + netif_device_attach(dev); + if (netif_running(dev)) { + rc = nv_open(dev); + nv_set_multicast(dev); + } return rc; } -- Tobias PGP: http://9ac7e0bc.uguu.de このメールは十割再利用されたビットで作られています。 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: hibernate event order question 2008-05-18 12:24 ` Tobias Diedrich @ 2008-05-18 12:29 ` Rafael J. Wysocki 0 siblings, 0 replies; 8+ messages in thread From: Rafael J. Wysocki @ 2008-05-18 12:29 UTC (permalink / raw) To: Tobias Diedrich; +Cc: netdev, linux-kernel, Ayaz Abdulla, Stephen Hemminger On Sunday, 18 of May 2008, Tobias Diedrich wrote: > Rafael J. Wysocki wrote: > > On Sunday, 18 of May 2008, Tobias Diedrich wrote: > > > Rafael J. Wysocki wrote: > > > > On Sunday, 18 of May 2008, Tobias Diedrich wrote: > > > > > Tobias Diedrich wrote: > > > > > > > > Shouldn't there be a 'prepare for poweroff'-callback, which gets > > > > > > > > called > > > > > > > > before the system is powered off for real? > > > > > > > > > > > > > > Yes, it should and it's called in recent kernels. > > > > > > > > > > > > For what values of 'recent'? > > > > > > I'm running 2.6.26-rc2 here. :) > > > > > > How do I hook into this callback? > > > > > > (suspend_late maybe? Going to try that one next...) > > > > > > > > > > Ok, this patch fixes the 'regression' introduced by the previous > > > > > patch (at least for me ;)): > > > > > > > > Well, what exactly do you do to hibernate the box? > > > > > > |#!/bin/sh > > > | > > > |SYSPRINTK=/proc/sys/kernel/printk > > > |OLDPRINTK=$(cat $SYSPRINTK) > > > |chvt 1 > > > |# work around forcedeth wake-on-lan bug > > > |#rmmod forcedeth > > > |echo 9 > $SYSPRINTK > > > |# shutdown/reboot/platform > > > |echo shutdown > /sys/power/disk > > > > You don't see the devices' suspend callbacks invoked before powering off > > because of this. Change that to 'platform' (unless that breaks things). > > Hmm, I think someone recommended to use shutdown since that is > supposed to be more reliable. > Anyway, I think the shutdown hook is good anyway since I suspect > that if I do a normal system shutdown with promiscous mode still on, > then wake-on-lan would also not work? > I haven't checked that though. > At least I think the shutdown hook won't hurt. :) No, it won't. > > I'm unable to comment on the device-specific things, but apart from this the > > patch looks okay to me except for one thing. > > > + if (np->wolenabled) > > > + pci_set_power_state(pdev, PCI_D3hot); > > > + else pci_set_power_state(pdev, PCI_D3cold); > > > > I'm not sure if it's possible to put the device into D3cold without actually > > removing power from it. > > Ok, I've cleaned it up a bit and split it up properly (I think): > http://www.tdiedrich.de/~ranma/patches/forcedeth/2.6.26-rc2/ > series: Can you send those patches as a series of messages, please? > forcedeth.resume.promisc.patch > forcedeth.hibernate.wol.patch > forcedeth.swappedmac.patch > forcedeth.reorder_suspend_resume.patch Thanks, Rafael ^ permalink raw reply [flat|nested] 8+ messages in thread
* hibernate event order question @ 2008-05-17 17:50 Tobias Diedrich 0 siblings, 0 replies; 8+ messages in thread From: Tobias Diedrich @ 2008-05-17 17:50 UTC (permalink / raw) To: linux-netdev, linux-kernel, Ayaz Abdulla Hello, for some time now I had the problem that after a suspend to disk network connectivitiy was down and also wake-on-lan would not work. First a bit of information, for the real question please see (*) below. Now I just found the ethtool -d (register dump) option and decided I want to try to debug this long-standing bug: http://bugzilla.kernel.org/show_bug.cgi?id=8381 I already found out why network connectivity is down after resume: The interfaces eth0 and eth1 are bridged into br0. The bridging code sets the interfaces into promiscous mode, but this is not properly restored after resume. This bug is easily fixable by calling nv_set_multicast(dev) either from within nv_open() or after nv_open() in nv_resume(). The second problem (does not wol after s2disk) is still unsolved though. However I have found that wake-on-lan works fine if I "rmmod forcedeth" before suspending. This is even a usable workaround for me, since the bridge device stays configured and I just have to reload forcedeth and readd the interfaces to the bridge after resume. (*) Now for my question: AFAICS the ordering of events is as follows: 1) User reqests hibernate 2) Tasks are frozen 3) Device suspend callbacks get called 4) Device resume callbacks get called 5) Memory image is written to disk Now, the problem I see with this is that while step 3) prepares the device for suspend (and wake-on-lan), step 4) may undo some of this preparation. In my case, I think the fix for the first bug (promiscous mode does not get restored on resume) breaks wake-on-lan (since the new value of NvRegPacketFilterFlags may be incompatible with wake-on-lan). Shouldn't there be a 'prepare for poweroff'-callback, which gets called before the system is powered off for real? --- linux-2.6.26-rc2/drivers/net/forcedeth.c 2008-05-17 14:22:06.000000000 +0200 +++ linux-2.6.26-rc2/drivers/net/forcedeth.c 2008-05-17 19:48:56.000000000 +0200 @@ -5823,6 +5823,7 @@ writel(txreg, base + NvRegTransmitPoll); rc = nv_open(dev); + nv_set_multicast(dev); out: return rc; } -- Tobias PGP: http://9ac7e0bc.uguu.de このメールは十割再利用されたビットで作られています。 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-05-18 12:29 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20080517175046.GA9032@yamamaya.is-a-geek.org>
[not found] ` <200805172156.12686.rjw@sisk.pl>
2008-05-17 22:36 ` hibernate event order question Tobias Diedrich
2008-05-17 23:24 ` Tobias Diedrich
2008-05-18 10:45 ` Rafael J. Wysocki
2008-05-18 11:22 ` Tobias Diedrich
2008-05-18 11:32 ` Rafael J. Wysocki
2008-05-18 12:24 ` Tobias Diedrich
2008-05-18 12:29 ` Rafael J. Wysocki
2008-05-17 17:50 Tobias Diedrich
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox