diff options
author | Auke Kok <auke-jan.h.kok@intel.com> | 2006-10-19 23:28:12 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-20 10:26:35 -0700 |
commit | e8e82b76e0312827f5ae04b573a05b02854a447e (patch) | |
tree | 3a6942b8abade23aafc489b84ca66decad7d3ff4 /drivers | |
parent | ce9e3d9953c8cb67001719b5516da2928e956be4 (diff) |
[PATCH] e100: fix reboot -f with netconsole enabled
When rebooting with netconsole over e100, the driver shutdown code would
deadlock with netpoll. Reduce shutdown code to a bare minimum while retaining
WoL and suspend functionality.
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/e100.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 27d5d2f02533..a3a08a5dd185 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2039,7 +2039,6 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu) return 0; } -#ifdef CONFIG_PM static int e100_asf(struct nic *nic) { /* ASF can be enabled from eeprom */ @@ -2048,7 +2047,6 @@ static int e100_asf(struct nic *nic) !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); } -#endif static int e100_up(struct nic *nic) { @@ -2715,34 +2713,32 @@ static void __devexit e100_remove(struct pci_dev *pdev) } } +#ifdef CONFIG_PM static int e100_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); - if (netif_running(netdev)) - e100_down(nic); - e100_hw_reset(nic); - netif_device_detach(netdev); + netif_poll_disable(nic->netdev); + del_timer_sync(&nic->watchdog); + netif_carrier_off(nic->netdev); -#ifdef CONFIG_PM pci_save_state(pdev); - if (nic->flags & (wol_magic | e100_asf(nic))) -#else - if (nic->flags & (wol_magic)) -#endif - pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); - else - /* disable PME */ - pci_enable_wake(pdev, 0, 0); + + if ((nic->flags & wol_magic) | e100_asf(nic)) { + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } else { + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + } pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pci_set_power_state(pdev, PCI_D3hot); return 0; } -#ifdef CONFIG_PM static int e100_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -2764,7 +2760,23 @@ static int e100_resume(struct pci_dev *pdev) static void e100_shutdown(struct pci_dev *pdev) { - e100_suspend(pdev, PMSG_SUSPEND); + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev_priv(netdev); + + netif_poll_disable(nic->netdev); + del_timer_sync(&nic->watchdog); + netif_carrier_off(nic->netdev); + + if ((nic->flags & wol_magic) | e100_asf(nic)) { + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } else { + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + } + + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); } /* ------------------ PCI Error Recovery infrastructure -------------- */ @@ -2848,9 +2860,9 @@ static struct pci_driver e100_driver = { .id_table = e100_id_table, .probe = e100_probe, .remove = __devexit_p(e100_remove), +#ifdef CONFIG_PM /* Power Management hooks */ .suspend = e100_suspend, -#ifdef CONFIG_PM .resume = e100_resume, #endif .shutdown = e100_shutdown, |