aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-03-31 17:23:50 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-02 03:59:08 -0400
commit3fe7c4c9dca4fbbff92eb61a660690dad7029ec3 (patch)
tree01659162f1b5f034428b0bf75aa85e064eed4857 /drivers/net
parentcdfa9f6444ced9425e8e4fe4c2975a620e664b77 (diff)
net/igb: Fix kexec with igb (rev. 3)
Impact: Fix Yinghai Lu found one system with 82575EB where, in the kernel that is kexeced, probe igb failed with -2, the reason being that the adapter could not be brought back from D3 by the kexec kernel, most probably due to quirky hardware (it looks like the same behavior happened on forcedeth). Prevent igb from putting the adapter into D3 during shutdown except when we going to power off the system. For this purpose, seperate igb_shutdown() from igb_suspend() and use the appropriate PCI PM callbacks in both of them. Signed-off-by: "Rafael J. Wysocki" <rjw@sisk.pl> Reported-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/igb/igb_main.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 10b095d69b43..03aa9593dd9e 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -135,8 +135,8 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *, int, int);
135static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *); 135static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
136static void igb_restore_vf_multicasts(struct igb_adapter *adapter); 136static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
137 137
138static int igb_suspend(struct pci_dev *, pm_message_t);
139#ifdef CONFIG_PM 138#ifdef CONFIG_PM
139static int igb_suspend(struct pci_dev *, pm_message_t);
140static int igb_resume(struct pci_dev *); 140static int igb_resume(struct pci_dev *);
141#endif 141#endif
142static void igb_shutdown(struct pci_dev *); 142static void igb_shutdown(struct pci_dev *);
@@ -5060,7 +5060,7 @@ int igb_set_spd_dplx(struct igb_adapter *adapter, u16 spddplx)
5060 return 0; 5060 return 0;
5061} 5061}
5062 5062
5063static int igb_suspend(struct pci_dev *pdev, pm_message_t state) 5063static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake)
5064{ 5064{
5065 struct net_device *netdev = pci_get_drvdata(pdev); 5065 struct net_device *netdev = pci_get_drvdata(pdev);
5066 struct igb_adapter *adapter = netdev_priv(netdev); 5066 struct igb_adapter *adapter = netdev_priv(netdev);
@@ -5119,15 +5119,9 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state)
5119 wr32(E1000_WUFC, 0); 5119 wr32(E1000_WUFC, 0);
5120 } 5120 }
5121 5121
5122 /* make sure adapter isn't asleep if manageability/wol is enabled */ 5122 *enable_wake = wufc || adapter->en_mng_pt;
5123 if (wufc || adapter->en_mng_pt) { 5123 if (!*enable_wake)
5124 pci_enable_wake(pdev, PCI_D3hot, 1);
5125 pci_enable_wake(pdev, PCI_D3cold, 1);
5126 } else {
5127 igb_shutdown_fiber_serdes_link_82575(hw); 5124 igb_shutdown_fiber_serdes_link_82575(hw);
5128 pci_enable_wake(pdev, PCI_D3hot, 0);
5129 pci_enable_wake(pdev, PCI_D3cold, 0);
5130 }
5131 5125
5132 /* Release control of h/w to f/w. If f/w is AMT enabled, this 5126 /* Release control of h/w to f/w. If f/w is AMT enabled, this
5133 * would have already happened in close and is redundant. */ 5127 * would have already happened in close and is redundant. */
@@ -5135,12 +5129,29 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state)
5135 5129
5136 pci_disable_device(pdev); 5130 pci_disable_device(pdev);
5137 5131
5138 pci_set_power_state(pdev, pci_choose_state(pdev, state));
5139
5140 return 0; 5132 return 0;
5141} 5133}
5142 5134
5143#ifdef CONFIG_PM 5135#ifdef CONFIG_PM
5136static int igb_suspend(struct pci_dev *pdev, pm_message_t state)
5137{
5138 int retval;
5139 bool wake;
5140
5141 retval = __igb_shutdown(pdev, &wake);
5142 if (retval)
5143 return retval;
5144
5145 if (wake) {
5146 pci_prepare_to_sleep(pdev);
5147 } else {
5148 pci_wake_from_d3(pdev, false);
5149 pci_set_power_state(pdev, PCI_D3hot);
5150 }
5151
5152 return 0;
5153}
5154
5144static int igb_resume(struct pci_dev *pdev) 5155static int igb_resume(struct pci_dev *pdev)
5145{ 5156{
5146 struct net_device *netdev = pci_get_drvdata(pdev); 5157 struct net_device *netdev = pci_get_drvdata(pdev);
@@ -5193,7 +5204,14 @@ static int igb_resume(struct pci_dev *pdev)
5193 5204
5194static void igb_shutdown(struct pci_dev *pdev) 5205static void igb_shutdown(struct pci_dev *pdev)
5195{ 5206{
5196 igb_suspend(pdev, PMSG_SUSPEND); 5207 bool wake;
5208
5209 __igb_shutdown(pdev, &wake);
5210
5211 if (system_state == SYSTEM_POWER_OFF) {
5212 pci_wake_from_d3(pdev, wake);
5213 pci_set_power_state(pdev, PCI_D3hot);
5214 }
5197} 5215}
5198 5216
5199#ifdef CONFIG_NET_POLL_CONTROLLER 5217#ifdef CONFIG_NET_POLL_CONTROLLER