aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-04-15 13:43:43 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-16 05:15:22 -0400
commit4f9de721ab73a5271a79b126f7b5140b01a05c99 (patch)
treed27b7844406686840dcd5d4086a6956fbd4423ff /drivers
parentb43fcd7dc7bf0471b3bdda8fee3418e93ac25863 (diff)
NET/e1000e: Fix powering off during shutdown
Prevent e1000e from putting the adapter into D3 during shutdown except when we're going to power off the system, since doing that may generally cause problems with kexec to happen (such problems were observed for igb and forcedeth). For this purpose seperate e1000e_shutdown() from e1000e_suspend() and use the appropriate PCI PM callbacks in both of them. Signed-off-by: "Rafael J. Wysocki" <rjw@sisk.pl> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/e1000e/netdev.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 3b0f0877380..1693ed116b1 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -4346,7 +4346,7 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
4346 } 4346 }
4347} 4347}
4348 4348
4349static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) 4349static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
4350{ 4350{
4351 struct net_device *netdev = pci_get_drvdata(pdev); 4351 struct net_device *netdev = pci_get_drvdata(pdev);
4352 struct e1000_adapter *adapter = netdev_priv(netdev); 4352 struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -4409,20 +4409,16 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
4409 4409
4410 ew32(WUC, E1000_WUC_PME_EN); 4410 ew32(WUC, E1000_WUC_PME_EN);
4411 ew32(WUFC, wufc); 4411 ew32(WUFC, wufc);
4412 pci_enable_wake(pdev, PCI_D3hot, 1);
4413 pci_enable_wake(pdev, PCI_D3cold, 1);
4414 } else { 4412 } else {
4415 ew32(WUC, 0); 4413 ew32(WUC, 0);
4416 ew32(WUFC, 0); 4414 ew32(WUFC, 0);
4417 pci_enable_wake(pdev, PCI_D3hot, 0);
4418 pci_enable_wake(pdev, PCI_D3cold, 0);
4419 } 4415 }
4420 4416
4417 *enable_wake = !!wufc;
4418
4421 /* make sure adapter isn't asleep if manageability is enabled */ 4419 /* make sure adapter isn't asleep if manageability is enabled */
4422 if (adapter->flags & FLAG_MNG_PT_ENABLED) { 4420 if (adapter->flags & FLAG_MNG_PT_ENABLED)
4423 pci_enable_wake(pdev, PCI_D3hot, 1); 4421 *enable_wake = true;
4424 pci_enable_wake(pdev, PCI_D3cold, 1);
4425 }
4426 4422
4427 if (adapter->hw.phy.type == e1000_phy_igp_3) 4423 if (adapter->hw.phy.type == e1000_phy_igp_3)
4428 e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); 4424 e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
@@ -4435,6 +4431,26 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
4435 4431
4436 pci_disable_device(pdev); 4432 pci_disable_device(pdev);
4437 4433
4434 return 0;
4435}
4436
4437static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake)
4438{
4439 if (sleep && wake) {
4440 pci_prepare_to_sleep(pdev);
4441 return;
4442 }
4443
4444 pci_wake_from_d3(pdev, wake);
4445 pci_set_power_state(pdev, PCI_D3hot);
4446}
4447
4448static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
4449 bool wake)
4450{
4451 struct net_device *netdev = pci_get_drvdata(pdev);
4452 struct e1000_adapter *adapter = netdev_priv(netdev);
4453
4438 /* 4454 /*
4439 * The pci-e switch on some quad port adapters will report a 4455 * The pci-e switch on some quad port adapters will report a
4440 * correctable error when the MAC transitions from D0 to D3. To 4456 * correctable error when the MAC transitions from D0 to D3. To
@@ -4450,14 +4466,12 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
4450 pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, 4466 pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL,
4451 (devctl & ~PCI_EXP_DEVCTL_CERE)); 4467 (devctl & ~PCI_EXP_DEVCTL_CERE));
4452 4468
4453 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 4469 e1000_power_off(pdev, sleep, wake);
4454 4470
4455 pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl); 4471 pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl);
4456 } else { 4472 } else {
4457 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 4473 e1000_power_off(pdev, sleep, wake);
4458 } 4474 }
4459
4460 return 0;
4461} 4475}
4462 4476
4463static void e1000e_disable_l1aspm(struct pci_dev *pdev) 4477static void e1000e_disable_l1aspm(struct pci_dev *pdev)
@@ -4486,6 +4500,18 @@ static void e1000e_disable_l1aspm(struct pci_dev *pdev)
4486} 4500}
4487 4501
4488#ifdef CONFIG_PM 4502#ifdef CONFIG_PM
4503static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
4504{
4505 int retval;
4506 bool wake;
4507
4508 retval = __e1000_shutdown(pdev, &wake);
4509 if (!retval)
4510 e1000_complete_shutdown(pdev, true, wake);
4511
4512 return retval;
4513}
4514
4489static int e1000_resume(struct pci_dev *pdev) 4515static int e1000_resume(struct pci_dev *pdev)
4490{ 4516{
4491 struct net_device *netdev = pci_get_drvdata(pdev); 4517 struct net_device *netdev = pci_get_drvdata(pdev);
@@ -4549,7 +4575,12 @@ static int e1000_resume(struct pci_dev *pdev)
4549 4575
4550static void e1000_shutdown(struct pci_dev *pdev) 4576static void e1000_shutdown(struct pci_dev *pdev)
4551{ 4577{
4552 e1000_suspend(pdev, PMSG_SUSPEND); 4578 bool wake = false;
4579
4580 __e1000_shutdown(pdev, &wake);
4581
4582 if (system_state == SYSTEM_POWER_OFF)
4583 e1000_complete_shutdown(pdev, false, wake);
4553} 4584}
4554 4585
4555#ifdef CONFIG_NET_POLL_CONTROLLER 4586#ifdef CONFIG_NET_POLL_CONTROLLER