diff options
author | Jay Cliburn <jacliburn@bellsouth.net> | 2008-05-09 23:12:07 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-13 01:30:24 -0400 |
commit | 08e0f1dc8388b3e134c714672c59edc2a7059430 (patch) | |
tree | d213ff1fed80abadf05bb66247d7b97ed73e1133 /drivers/net/atlx | |
parent | ff772b27e5f65c1a186e9f0741f0d00ef7002799 (diff) |
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: Jay Cliburn <jacliburn@bellsouth.net>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/atlx')
-rw-r--r-- | drivers/net/atlx/atl1.c | 125 |
1 files changed, 80 insertions, 45 deletions
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 3beb44e80ba0..12fb3e5529d1 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
@@ -2781,64 +2781,93 @@ static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2781 | struct atl1_hw *hw = &adapter->hw; | 2781 | struct atl1_hw *hw = &adapter->hw; |
2782 | u32 ctrl = 0; | 2782 | u32 ctrl = 0; |
2783 | u32 wufc = adapter->wol; | 2783 | u32 wufc = adapter->wol; |
2784 | u32 val; | ||
2785 | int retval; | ||
2786 | u16 speed; | ||
2787 | u16 duplex; | ||
2784 | 2788 | ||
2785 | netif_device_detach(netdev); | 2789 | netif_device_detach(netdev); |
2786 | if (netif_running(netdev)) | 2790 | if (netif_running(netdev)) |
2787 | atl1_down(adapter); | 2791 | atl1_down(adapter); |
2788 | 2792 | ||
2793 | retval = pci_save_state(pdev); | ||
2794 | if (retval) | ||
2795 | return retval; | ||
2796 | |||
2789 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); | 2797 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); |
2790 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); | 2798 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); |
2791 | if (ctrl & BMSR_LSTATUS) | 2799 | val = ctrl & BMSR_LSTATUS; |
2800 | if (val) | ||
2792 | wufc &= ~ATLX_WUFC_LNKC; | 2801 | wufc &= ~ATLX_WUFC_LNKC; |
2793 | 2802 | ||
2794 | /* reduce speed to 10/100M */ | 2803 | if (val && wufc) { |
2795 | if (wufc) { | 2804 | val = atl1_get_speed_and_duplex(hw, &speed, &duplex); |
2796 | atl1_phy_enter_power_saving(hw); | 2805 | if (val) { |
2797 | /* if resume, let driver to re- setup link */ | 2806 | if (netif_msg_ifdown(adapter)) |
2798 | hw->phy_configured = false; | 2807 | dev_printk(KERN_DEBUG, &pdev->dev, |
2799 | atl1_set_mac_addr(hw); | 2808 | "error getting speed/duplex\n"); |
2800 | atlx_set_multi(netdev); | 2809 | goto disable_wol; |
2810 | } | ||
2801 | 2811 | ||
2802 | ctrl = 0; | 2812 | ctrl = 0; |
2803 | /* turn on magic packet wol */ | ||
2804 | if (wufc & ATLX_WUFC_MAG) | ||
2805 | ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; | ||
2806 | 2813 | ||
2807 | /* turn on Link change WOL */ | 2814 | /* enable magic packet WOL */ |
2808 | if (wufc & ATLX_WUFC_LNKC) | 2815 | if (wufc & ATLX_WUFC_MAG) |
2809 | ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); | 2816 | ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN); |
2810 | iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); | 2817 | iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); |
2811 | 2818 | ioread32(hw->hw_addr + REG_WOL_CTRL); | |
2812 | /* turn on all-multi mode if wake on multicast is enabled */ | 2819 | |
2813 | ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); | 2820 | /* configure the mac */ |
2814 | ctrl &= ~MAC_CTRL_DBG; | 2821 | ctrl = MAC_CTRL_RX_EN; |
2815 | ctrl &= ~MAC_CTRL_PROMIS_EN; | 2822 | ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 : |
2816 | if (wufc & ATLX_WUFC_MC) | 2823 | MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT); |
2817 | ctrl |= MAC_CTRL_MC_ALL_EN; | 2824 | if (duplex == FULL_DUPLEX) |
2818 | else | 2825 | ctrl |= MAC_CTRL_DUPLX; |
2819 | ctrl &= ~MAC_CTRL_MC_ALL_EN; | 2826 | ctrl |= (((u32)adapter->hw.preamble_len & |
2820 | 2827 | MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); | |
2821 | /* turn on broadcast mode if wake on-BC is enabled */ | 2828 | if (adapter->vlgrp) |
2822 | if (wufc & ATLX_WUFC_BC) | 2829 | ctrl |= MAC_CTRL_RMV_VLAN; |
2830 | if (wufc & ATLX_WUFC_MAG) | ||
2823 | ctrl |= MAC_CTRL_BC_EN; | 2831 | ctrl |= MAC_CTRL_BC_EN; |
2824 | else | ||
2825 | ctrl &= ~MAC_CTRL_BC_EN; | ||
2826 | |||
2827 | /* enable RX */ | ||
2828 | ctrl |= MAC_CTRL_RX_EN; | ||
2829 | iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); | 2832 | iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); |
2830 | pci_enable_wake(pdev, PCI_D3hot, 1); | 2833 | ioread32(hw->hw_addr + REG_MAC_CTRL); |
2831 | pci_enable_wake(pdev, PCI_D3cold, 1); | 2834 | |
2832 | } else { | 2835 | /* poke the PHY */ |
2833 | iowrite32(0, hw->hw_addr + REG_WOL_CTRL); | 2836 | ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); |
2834 | pci_enable_wake(pdev, PCI_D3hot, 0); | 2837 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; |
2835 | pci_enable_wake(pdev, PCI_D3cold, 0); | 2838 | iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); |
2839 | ioread32(hw->hw_addr + REG_PCIE_PHYMISC); | ||
2840 | |||
2841 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); | ||
2842 | goto exit; | ||
2836 | } | 2843 | } |
2837 | 2844 | ||
2838 | pci_save_state(pdev); | 2845 | if (!val && wufc) { |
2846 | ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); | ||
2847 | iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); | ||
2848 | ioread32(hw->hw_addr + REG_WOL_CTRL); | ||
2849 | iowrite32(0, hw->hw_addr + REG_MAC_CTRL); | ||
2850 | ioread32(hw->hw_addr + REG_MAC_CTRL); | ||
2851 | hw->phy_configured = false; | ||
2852 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); | ||
2853 | goto exit; | ||
2854 | } | ||
2855 | |||
2856 | disable_wol: | ||
2857 | iowrite32(0, hw->hw_addr + REG_WOL_CTRL); | ||
2858 | ioread32(hw->hw_addr + REG_WOL_CTRL); | ||
2859 | ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); | ||
2860 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; | ||
2861 | iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); | ||
2862 | ioread32(hw->hw_addr + REG_PCIE_PHYMISC); | ||
2863 | atl1_phy_enter_power_saving(hw); | ||
2864 | hw->phy_configured = false; | ||
2865 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
2866 | exit: | ||
2867 | if (netif_running(netdev)) | ||
2868 | pci_disable_msi(adapter->pdev); | ||
2839 | pci_disable_device(pdev); | 2869 | pci_disable_device(pdev); |
2840 | 2870 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | |
2841 | pci_set_power_state(pdev, PCI_D3hot); | ||
2842 | 2871 | ||
2843 | return 0; | 2872 | return 0; |
2844 | } | 2873 | } |
@@ -2852,20 +2881,26 @@ static int atl1_resume(struct pci_dev *pdev) | |||
2852 | pci_set_power_state(pdev, PCI_D0); | 2881 | pci_set_power_state(pdev, PCI_D0); |
2853 | pci_restore_state(pdev); | 2882 | pci_restore_state(pdev); |
2854 | 2883 | ||
2855 | /* FIXME: check and handle */ | ||
2856 | err = pci_enable_device(pdev); | 2884 | err = pci_enable_device(pdev); |
2885 | if (err) { | ||
2886 | if (netif_msg_ifup(adapter)) | ||
2887 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
2888 | "error enabling pci device\n"); | ||
2889 | return err; | ||
2890 | } | ||
2891 | |||
2892 | pci_set_master(pdev); | ||
2893 | iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); | ||
2857 | pci_enable_wake(pdev, PCI_D3hot, 0); | 2894 | pci_enable_wake(pdev, PCI_D3hot, 0); |
2858 | pci_enable_wake(pdev, PCI_D3cold, 0); | 2895 | pci_enable_wake(pdev, PCI_D3cold, 0); |
2859 | 2896 | ||
2860 | iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); | 2897 | atl1_reset_hw(&adapter->hw); |
2861 | atl1_reset(adapter); | 2898 | adapter->cmb.cmb->int_stats = 0; |
2862 | 2899 | ||
2863 | if (netif_running(netdev)) | 2900 | if (netif_running(netdev)) |
2864 | atl1_up(adapter); | 2901 | atl1_up(adapter); |
2865 | netif_device_attach(netdev); | 2902 | netif_device_attach(netdev); |
2866 | 2903 | ||
2867 | atl1_via_workaround(adapter); | ||
2868 | |||
2869 | return 0; | 2904 | return 0; |
2870 | } | 2905 | } |
2871 | #else | 2906 | #else |