diff options
author | Auke Kok <auke-jan.h.kok@intel.com> | 2006-10-20 02:28:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-20 13:26:35 -0400 |
commit | e8e82b76e0312827f5ae04b573a05b02854a447e (patch) | |
tree | 3a6942b8abade23aafc489b84ca66decad7d3ff4 | |
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>
-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) | |||
2039 | return 0; | 2039 | return 0; |
2040 | } | 2040 | } |
2041 | 2041 | ||
2042 | #ifdef CONFIG_PM | ||
2043 | static int e100_asf(struct nic *nic) | 2042 | static int e100_asf(struct nic *nic) |
2044 | { | 2043 | { |
2045 | /* ASF can be enabled from eeprom */ | 2044 | /* ASF can be enabled from eeprom */ |
@@ -2048,7 +2047,6 @@ static int e100_asf(struct nic *nic) | |||
2048 | !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && | 2047 | !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && |
2049 | ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); | 2048 | ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); |
2050 | } | 2049 | } |
2051 | #endif | ||
2052 | 2050 | ||
2053 | static int e100_up(struct nic *nic) | 2051 | static int e100_up(struct nic *nic) |
2054 | { | 2052 | { |
@@ -2715,34 +2713,32 @@ static void __devexit e100_remove(struct pci_dev *pdev) | |||
2715 | } | 2713 | } |
2716 | } | 2714 | } |
2717 | 2715 | ||
2716 | #ifdef CONFIG_PM | ||
2718 | static int e100_suspend(struct pci_dev *pdev, pm_message_t state) | 2717 | static int e100_suspend(struct pci_dev *pdev, pm_message_t state) |
2719 | { | 2718 | { |
2720 | struct net_device *netdev = pci_get_drvdata(pdev); | 2719 | struct net_device *netdev = pci_get_drvdata(pdev); |
2721 | struct nic *nic = netdev_priv(netdev); | 2720 | struct nic *nic = netdev_priv(netdev); |
2722 | 2721 | ||
2723 | if (netif_running(netdev)) | 2722 | netif_poll_disable(nic->netdev); |
2724 | e100_down(nic); | 2723 | del_timer_sync(&nic->watchdog); |
2725 | e100_hw_reset(nic); | 2724 | netif_carrier_off(nic->netdev); |
2726 | netif_device_detach(netdev); | ||
2727 | 2725 | ||
2728 | #ifdef CONFIG_PM | ||
2729 | pci_save_state(pdev); | 2726 | pci_save_state(pdev); |
2730 | if (nic->flags & (wol_magic | e100_asf(nic))) | 2727 | |
2731 | #else | 2728 | if ((nic->flags & wol_magic) | e100_asf(nic)) { |
2732 | if (nic->flags & (wol_magic)) | 2729 | pci_enable_wake(pdev, PCI_D3hot, 1); |
2733 | #endif | 2730 | pci_enable_wake(pdev, PCI_D3cold, 1); |
2734 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); | 2731 | } else { |
2735 | else | 2732 | pci_enable_wake(pdev, PCI_D3hot, 0); |
2736 | /* disable PME */ | 2733 | pci_enable_wake(pdev, PCI_D3cold, 0); |
2737 | pci_enable_wake(pdev, 0, 0); | 2734 | } |
2738 | 2735 | ||
2739 | pci_disable_device(pdev); | 2736 | pci_disable_device(pdev); |
2740 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 2737 | pci_set_power_state(pdev, PCI_D3hot); |
2741 | 2738 | ||
2742 | return 0; | 2739 | return 0; |
2743 | } | 2740 | } |
2744 | 2741 | ||
2745 | #ifdef CONFIG_PM | ||
2746 | static int e100_resume(struct pci_dev *pdev) | 2742 | static int e100_resume(struct pci_dev *pdev) |
2747 | { | 2743 | { |
2748 | struct net_device *netdev = pci_get_drvdata(pdev); | 2744 | struct net_device *netdev = pci_get_drvdata(pdev); |
@@ -2764,7 +2760,23 @@ static int e100_resume(struct pci_dev *pdev) | |||
2764 | 2760 | ||
2765 | static void e100_shutdown(struct pci_dev *pdev) | 2761 | static void e100_shutdown(struct pci_dev *pdev) |
2766 | { | 2762 | { |
2767 | e100_suspend(pdev, PMSG_SUSPEND); | 2763 | struct net_device *netdev = pci_get_drvdata(pdev); |
2764 | struct nic *nic = netdev_priv(netdev); | ||
2765 | |||
2766 | netif_poll_disable(nic->netdev); | ||
2767 | del_timer_sync(&nic->watchdog); | ||
2768 | netif_carrier_off(nic->netdev); | ||
2769 | |||
2770 | if ((nic->flags & wol_magic) | e100_asf(nic)) { | ||
2771 | pci_enable_wake(pdev, PCI_D3hot, 1); | ||
2772 | pci_enable_wake(pdev, PCI_D3cold, 1); | ||
2773 | } else { | ||
2774 | pci_enable_wake(pdev, PCI_D3hot, 0); | ||
2775 | pci_enable_wake(pdev, PCI_D3cold, 0); | ||
2776 | } | ||
2777 | |||
2778 | pci_disable_device(pdev); | ||
2779 | pci_set_power_state(pdev, PCI_D3hot); | ||
2768 | } | 2780 | } |
2769 | 2781 | ||
2770 | /* ------------------ PCI Error Recovery infrastructure -------------- */ | 2782 | /* ------------------ PCI Error Recovery infrastructure -------------- */ |
@@ -2848,9 +2860,9 @@ static struct pci_driver e100_driver = { | |||
2848 | .id_table = e100_id_table, | 2860 | .id_table = e100_id_table, |
2849 | .probe = e100_probe, | 2861 | .probe = e100_probe, |
2850 | .remove = __devexit_p(e100_remove), | 2862 | .remove = __devexit_p(e100_remove), |
2863 | #ifdef CONFIG_PM | ||
2851 | /* Power Management hooks */ | 2864 | /* Power Management hooks */ |
2852 | .suspend = e100_suspend, | 2865 | .suspend = e100_suspend, |
2853 | #ifdef CONFIG_PM | ||
2854 | .resume = e100_resume, | 2866 | .resume = e100_resume, |
2855 | #endif | 2867 | #endif |
2856 | .shutdown = e100_shutdown, | 2868 | .shutdown = e100_shutdown, |