Skip to content

Commit

Permalink
NET/e1000: Fix powering off during shutdown
Browse files Browse the repository at this point in the history
Prevent e1000 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 e1000_shutdown() from e1000_suspend()
and use the appropriate PCI PM callbacks in both of them.

Signed-off-by: "Rafael J. Wysocki" <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
rjwysocki authored and davem330 committed Apr 16, 2009
1 parent 719bfea commit b43fcd7
Showing 1 changed file with 33 additions and 13 deletions.
46 changes: 33 additions & 13 deletions drivers/net/e1000/e1000_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
static void e1000_restore_vlan(struct e1000_adapter *adapter);

static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
#ifdef CONFIG_PM
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
static int e1000_resume(struct pci_dev *pdev);
#endif
static void e1000_shutdown(struct pci_dev *pdev);
Expand Down Expand Up @@ -4601,7 +4601,7 @@ int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
return 0;
}

static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
Expand Down Expand Up @@ -4664,22 +4664,18 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)

ew32(WUC, E1000_WUC_PME_EN);
ew32(WUFC, wufc);
pci_enable_wake(pdev, PCI_D3hot, 1);
pci_enable_wake(pdev, PCI_D3cold, 1);
} else {
ew32(WUC, 0);
ew32(WUFC, 0);
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0);
}

e1000_release_manageability(adapter);

*enable_wake = !!wufc;

/* make sure adapter isn't asleep if manageability is enabled */
if (adapter->en_mng_pt) {
pci_enable_wake(pdev, PCI_D3hot, 1);
pci_enable_wake(pdev, PCI_D3cold, 1);
}
if (adapter->en_mng_pt)
*enable_wake = true;

if (hw->phy_type == e1000_phy_igp_3)
e1000_phy_powerdown_workaround(hw);
Expand All @@ -4693,12 +4689,29 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)

pci_disable_device(pdev);

pci_set_power_state(pdev, pci_choose_state(pdev, state));

return 0;
}

#ifdef CONFIG_PM
static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
{
int retval;
bool wake;

retval = __e1000_shutdown(pdev, &wake);
if (retval)
return retval;

if (wake) {
pci_prepare_to_sleep(pdev);
} else {
pci_wake_from_d3(pdev, false);
pci_set_power_state(pdev, PCI_D3hot);
}

return 0;
}

static int e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
Expand Down Expand Up @@ -4753,7 +4766,14 @@ static int e1000_resume(struct pci_dev *pdev)

static void e1000_shutdown(struct pci_dev *pdev)
{
e1000_suspend(pdev, PMSG_SUSPEND);
bool wake;

__e1000_shutdown(pdev, &wake);

if (system_state == SYSTEM_POWER_OFF) {
pci_wake_from_d3(pdev, wake);
pci_set_power_state(pdev, PCI_D3hot);
}
}

#ifdef CONFIG_NET_POLL_CONTROLLER
Expand Down

0 comments on commit b43fcd7

Please sign in to comment.