Commit 08e0f1dc authored by Jay Cliburn's avatar Jay Cliburn Committed by Jeff Garzik

atl1: fix broken suspend and resume

Fix atl1_suspend() and atl1_resume() so they actually work.  We'll use
the suspend function for wake-on-lan in addition to just suspending.
Signed-off-by: default avatarJay Cliburn <jacliburn@bellsouth.net>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent ff772b27
...@@ -2781,64 +2781,93 @@ static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -2781,64 +2781,93 @@ static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
struct atl1_hw *hw = &adapter->hw; struct atl1_hw *hw = &adapter->hw;
u32 ctrl = 0; u32 ctrl = 0;
u32 wufc = adapter->wol; u32 wufc = adapter->wol;
u32 val;
int retval;
u16 speed;
u16 duplex;
netif_device_detach(netdev); netif_device_detach(netdev);
if (netif_running(netdev)) if (netif_running(netdev))
atl1_down(adapter); atl1_down(adapter);
retval = pci_save_state(pdev);
if (retval)
return retval;
atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
if (ctrl & BMSR_LSTATUS) val = ctrl & BMSR_LSTATUS;
if (val)
wufc &= ~ATLX_WUFC_LNKC; wufc &= ~ATLX_WUFC_LNKC;
/* reduce speed to 10/100M */ if (val && wufc) {
if (wufc) { val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
atl1_phy_enter_power_saving(hw); if (val) {
/* if resume, let driver to re- setup link */ if (netif_msg_ifdown(adapter))
hw->phy_configured = false; dev_printk(KERN_DEBUG, &pdev->dev,
atl1_set_mac_addr(hw); "error getting speed/duplex\n");
atlx_set_multi(netdev); goto disable_wol;
}
ctrl = 0; ctrl = 0;
/* turn on magic packet wol */
if (wufc & ATLX_WUFC_MAG)
ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
/* turn on Link change WOL */ /* enable magic packet WOL */
if (wufc & ATLX_WUFC_LNKC) if (wufc & ATLX_WUFC_MAG)
ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN);
iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
ioread32(hw->hw_addr + REG_WOL_CTRL);
/* turn on all-multi mode if wake on multicast is enabled */
ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); /* configure the mac */
ctrl &= ~MAC_CTRL_DBG; ctrl = MAC_CTRL_RX_EN;
ctrl &= ~MAC_CTRL_PROMIS_EN; ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 :
if (wufc & ATLX_WUFC_MC) MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT);
ctrl |= MAC_CTRL_MC_ALL_EN; if (duplex == FULL_DUPLEX)
else ctrl |= MAC_CTRL_DUPLX;
ctrl &= ~MAC_CTRL_MC_ALL_EN; ctrl |= (((u32)adapter->hw.preamble_len &
MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT);
/* turn on broadcast mode if wake on-BC is enabled */ if (adapter->vlgrp)
if (wufc & ATLX_WUFC_BC) ctrl |= MAC_CTRL_RMV_VLAN;
if (wufc & ATLX_WUFC_MAG)
ctrl |= MAC_CTRL_BC_EN; ctrl |= MAC_CTRL_BC_EN;
else
ctrl &= ~MAC_CTRL_BC_EN;
/* enable RX */
ctrl |= MAC_CTRL_RX_EN;
iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL);
pci_enable_wake(pdev, PCI_D3hot, 1); ioread32(hw->hw_addr + REG_MAC_CTRL);
pci_enable_wake(pdev, PCI_D3cold, 1);
} else { /* poke the PHY */
iowrite32(0, hw->hw_addr + REG_WOL_CTRL); ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
pci_enable_wake(pdev, PCI_D3hot, 0); ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
pci_enable_wake(pdev, PCI_D3cold, 0); iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
goto exit;
} }
pci_save_state(pdev); if (!val && wufc) {
ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
ioread32(hw->hw_addr + REG_WOL_CTRL);
iowrite32(0, hw->hw_addr + REG_MAC_CTRL);
ioread32(hw->hw_addr + REG_MAC_CTRL);
hw->phy_configured = false;
pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
goto exit;
}
disable_wol:
iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
ioread32(hw->hw_addr + REG_WOL_CTRL);
ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
atl1_phy_enter_power_saving(hw);
hw->phy_configured = false;
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
exit:
if (netif_running(netdev))
pci_disable_msi(adapter->pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
pci_set_power_state(pdev, PCI_D3hot);
return 0; return 0;
} }
...@@ -2852,20 +2881,26 @@ static int atl1_resume(struct pci_dev *pdev) ...@@ -2852,20 +2881,26 @@ static int atl1_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0); pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev); pci_restore_state(pdev);
/* FIXME: check and handle */
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) {
if (netif_msg_ifup(adapter))
dev_printk(KERN_DEBUG, &pdev->dev,
"error enabling pci device\n");
return err;
}
pci_set_master(pdev);
iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3hot, 0);
pci_enable_wake(pdev, PCI_D3cold, 0); pci_enable_wake(pdev, PCI_D3cold, 0);
iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); atl1_reset_hw(&adapter->hw);
atl1_reset(adapter); adapter->cmb.cmb->int_stats = 0;
if (netif_running(netdev)) if (netif_running(netdev))
atl1_up(adapter); atl1_up(adapter);
netif_device_attach(netdev); netif_device_attach(netdev);
atl1_via_workaround(adapter);
return 0; return 0;
} }
#else #else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment