diff options
Diffstat (limited to 'drivers/net/atlx/atl1.c')
-rw-r--r-- | drivers/net/atlx/atl1.c | 157 |
1 files changed, 90 insertions, 67 deletions
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 0afe522b8f7b..99e0b4cdc56f 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. | 2 | * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. |
3 | * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com> | 3 | * Copyright(c) 2006 - 2007 Chris Snook <csnook@redhat.com> |
4 | * Copyright(c) 2006 Jay Cliburn <jcliburn@gmail.com> | 4 | * Copyright(c) 2006 - 2008 Jay Cliburn <jcliburn@gmail.com> |
5 | * | 5 | * |
6 | * Derived from Intel e1000 driver | 6 | * Derived from Intel e1000 driver |
7 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. | 7 | * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. |
@@ -36,7 +36,6 @@ | |||
36 | * A very incomplete list of things that need to be dealt with: | 36 | * A very incomplete list of things that need to be dealt with: |
37 | * | 37 | * |
38 | * TODO: | 38 | * TODO: |
39 | * Wake on LAN. | ||
40 | * Add more ethtool functions. | 39 | * Add more ethtool functions. |
41 | * Fix abstruse irq enable/disable condition described here: | 40 | * Fix abstruse irq enable/disable condition described here: |
42 | * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2 | 41 | * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2 |
@@ -638,25 +637,6 @@ static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw) | |||
638 | } | 637 | } |
639 | 638 | ||
640 | /* | 639 | /* |
641 | *TODO: do something or get rid of this | ||
642 | */ | ||
643 | #ifdef CONFIG_PM | ||
644 | static s32 atl1_phy_enter_power_saving(struct atl1_hw *hw) | ||
645 | { | ||
646 | /* s32 ret_val; | ||
647 | * u16 phy_data; | ||
648 | */ | ||
649 | |||
650 | /* | ||
651 | ret_val = atl1_write_phy_reg(hw, ...); | ||
652 | ret_val = atl1_write_phy_reg(hw, ...); | ||
653 | .... | ||
654 | */ | ||
655 | return 0; | ||
656 | } | ||
657 | #endif | ||
658 | |||
659 | /* | ||
660 | * Resets the PHY and make all config validate | 640 | * Resets the PHY and make all config validate |
661 | * hw - Struct containing variables accessed by shared code | 641 | * hw - Struct containing variables accessed by shared code |
662 | * | 642 | * |
@@ -2027,6 +2007,7 @@ rrd_ok: | |||
2027 | /* Good Receive */ | 2007 | /* Good Receive */ |
2028 | pci_unmap_page(adapter->pdev, buffer_info->dma, | 2008 | pci_unmap_page(adapter->pdev, buffer_info->dma, |
2029 | buffer_info->length, PCI_DMA_FROMDEVICE); | 2009 | buffer_info->length, PCI_DMA_FROMDEVICE); |
2010 | buffer_info->dma = 0; | ||
2030 | skb = buffer_info->skb; | 2011 | skb = buffer_info->skb; |
2031 | length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); | 2012 | length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); |
2032 | 2013 | ||
@@ -2139,7 +2120,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, | |||
2139 | return -1; | 2120 | return -1; |
2140 | } | 2121 | } |
2141 | 2122 | ||
2142 | if (skb->protocol == ntohs(ETH_P_IP)) { | 2123 | if (skb->protocol == htons(ETH_P_IP)) { |
2143 | struct iphdr *iph = ip_hdr(skb); | 2124 | struct iphdr *iph = ip_hdr(skb); |
2144 | 2125 | ||
2145 | real_len = (((unsigned char *)iph - skb->data) + | 2126 | real_len = (((unsigned char *)iph - skb->data) + |
@@ -2784,64 +2765,92 @@ static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2784 | struct atl1_hw *hw = &adapter->hw; | 2765 | struct atl1_hw *hw = &adapter->hw; |
2785 | u32 ctrl = 0; | 2766 | u32 ctrl = 0; |
2786 | u32 wufc = adapter->wol; | 2767 | u32 wufc = adapter->wol; |
2768 | u32 val; | ||
2769 | int retval; | ||
2770 | u16 speed; | ||
2771 | u16 duplex; | ||
2787 | 2772 | ||
2788 | netif_device_detach(netdev); | 2773 | netif_device_detach(netdev); |
2789 | if (netif_running(netdev)) | 2774 | if (netif_running(netdev)) |
2790 | atl1_down(adapter); | 2775 | atl1_down(adapter); |
2791 | 2776 | ||
2777 | retval = pci_save_state(pdev); | ||
2778 | if (retval) | ||
2779 | return retval; | ||
2780 | |||
2792 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); | 2781 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); |
2793 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); | 2782 | atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); |
2794 | if (ctrl & BMSR_LSTATUS) | 2783 | val = ctrl & BMSR_LSTATUS; |
2784 | if (val) | ||
2795 | wufc &= ~ATLX_WUFC_LNKC; | 2785 | wufc &= ~ATLX_WUFC_LNKC; |
2796 | 2786 | ||
2797 | /* reduce speed to 10/100M */ | 2787 | if (val && wufc) { |
2798 | if (wufc) { | 2788 | val = atl1_get_speed_and_duplex(hw, &speed, &duplex); |
2799 | atl1_phy_enter_power_saving(hw); | 2789 | if (val) { |
2800 | /* if resume, let driver to re- setup link */ | 2790 | if (netif_msg_ifdown(adapter)) |
2801 | hw->phy_configured = false; | 2791 | dev_printk(KERN_DEBUG, &pdev->dev, |
2802 | atl1_set_mac_addr(hw); | 2792 | "error getting speed/duplex\n"); |
2803 | atlx_set_multi(netdev); | 2793 | goto disable_wol; |
2794 | } | ||
2804 | 2795 | ||
2805 | ctrl = 0; | 2796 | ctrl = 0; |
2806 | /* turn on magic packet wol */ | ||
2807 | if (wufc & ATLX_WUFC_MAG) | ||
2808 | ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; | ||
2809 | 2797 | ||
2810 | /* turn on Link change WOL */ | 2798 | /* enable magic packet WOL */ |
2811 | if (wufc & ATLX_WUFC_LNKC) | 2799 | if (wufc & ATLX_WUFC_MAG) |
2812 | ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); | 2800 | ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN); |
2813 | iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); | 2801 | iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); |
2802 | ioread32(hw->hw_addr + REG_WOL_CTRL); | ||
2803 | |||
2804 | /* configure the mac */ | ||
2805 | ctrl = MAC_CTRL_RX_EN; | ||
2806 | ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 : | ||
2807 | MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT); | ||
2808 | if (duplex == FULL_DUPLEX) | ||
2809 | ctrl |= MAC_CTRL_DUPLX; | ||
2810 | ctrl |= (((u32)adapter->hw.preamble_len & | ||
2811 | MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); | ||
2812 | if (adapter->vlgrp) | ||
2813 | ctrl |= MAC_CTRL_RMV_VLAN; | ||
2814 | if (wufc & ATLX_WUFC_MAG) | ||
2815 | ctrl |= MAC_CTRL_BC_EN; | ||
2816 | iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); | ||
2817 | ioread32(hw->hw_addr + REG_MAC_CTRL); | ||
2814 | 2818 | ||
2815 | /* turn on all-multi mode if wake on multicast is enabled */ | 2819 | /* poke the PHY */ |
2816 | ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); | 2820 | ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); |
2817 | ctrl &= ~MAC_CTRL_DBG; | 2821 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; |
2818 | ctrl &= ~MAC_CTRL_PROMIS_EN; | 2822 | iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); |
2819 | if (wufc & ATLX_WUFC_MC) | 2823 | ioread32(hw->hw_addr + REG_PCIE_PHYMISC); |
2820 | ctrl |= MAC_CTRL_MC_ALL_EN; | ||
2821 | else | ||
2822 | ctrl &= ~MAC_CTRL_MC_ALL_EN; | ||
2823 | 2824 | ||
2824 | /* turn on broadcast mode if wake on-BC is enabled */ | 2825 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); |
2825 | if (wufc & ATLX_WUFC_BC) | 2826 | goto exit; |
2826 | ctrl |= MAC_CTRL_BC_EN; | 2827 | } |
2827 | else | ||
2828 | ctrl &= ~MAC_CTRL_BC_EN; | ||
2829 | 2828 | ||
2830 | /* enable RX */ | 2829 | if (!val && wufc) { |
2831 | ctrl |= MAC_CTRL_RX_EN; | 2830 | ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); |
2832 | iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); | 2831 | iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); |
2833 | pci_enable_wake(pdev, PCI_D3hot, 1); | 2832 | ioread32(hw->hw_addr + REG_WOL_CTRL); |
2834 | pci_enable_wake(pdev, PCI_D3cold, 1); | 2833 | iowrite32(0, hw->hw_addr + REG_MAC_CTRL); |
2835 | } else { | 2834 | ioread32(hw->hw_addr + REG_MAC_CTRL); |
2836 | iowrite32(0, hw->hw_addr + REG_WOL_CTRL); | 2835 | hw->phy_configured = false; |
2837 | pci_enable_wake(pdev, PCI_D3hot, 0); | 2836 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); |
2838 | pci_enable_wake(pdev, PCI_D3cold, 0); | 2837 | goto exit; |
2839 | } | 2838 | } |
2840 | 2839 | ||
2841 | pci_save_state(pdev); | 2840 | disable_wol: |
2841 | iowrite32(0, hw->hw_addr + REG_WOL_CTRL); | ||
2842 | ioread32(hw->hw_addr + REG_WOL_CTRL); | ||
2843 | ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); | ||
2844 | ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; | ||
2845 | iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); | ||
2846 | ioread32(hw->hw_addr + REG_PCIE_PHYMISC); | ||
2847 | hw->phy_configured = false; | ||
2848 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
2849 | exit: | ||
2850 | if (netif_running(netdev)) | ||
2851 | pci_disable_msi(adapter->pdev); | ||
2842 | pci_disable_device(pdev); | 2852 | pci_disable_device(pdev); |
2843 | 2853 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | |
2844 | pci_set_power_state(pdev, PCI_D3hot); | ||
2845 | 2854 | ||
2846 | return 0; | 2855 | return 0; |
2847 | } | 2856 | } |
@@ -2855,20 +2864,26 @@ static int atl1_resume(struct pci_dev *pdev) | |||
2855 | pci_set_power_state(pdev, PCI_D0); | 2864 | pci_set_power_state(pdev, PCI_D0); |
2856 | pci_restore_state(pdev); | 2865 | pci_restore_state(pdev); |
2857 | 2866 | ||
2858 | /* FIXME: check and handle */ | ||
2859 | err = pci_enable_device(pdev); | 2867 | err = pci_enable_device(pdev); |
2868 | if (err) { | ||
2869 | if (netif_msg_ifup(adapter)) | ||
2870 | dev_printk(KERN_DEBUG, &pdev->dev, | ||
2871 | "error enabling pci device\n"); | ||
2872 | return err; | ||
2873 | } | ||
2874 | |||
2875 | pci_set_master(pdev); | ||
2876 | iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); | ||
2860 | pci_enable_wake(pdev, PCI_D3hot, 0); | 2877 | pci_enable_wake(pdev, PCI_D3hot, 0); |
2861 | pci_enable_wake(pdev, PCI_D3cold, 0); | 2878 | pci_enable_wake(pdev, PCI_D3cold, 0); |
2862 | 2879 | ||
2863 | iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); | 2880 | atl1_reset_hw(&adapter->hw); |
2864 | atl1_reset(adapter); | 2881 | adapter->cmb.cmb->int_stats = 0; |
2865 | 2882 | ||
2866 | if (netif_running(netdev)) | 2883 | if (netif_running(netdev)) |
2867 | atl1_up(adapter); | 2884 | atl1_up(adapter); |
2868 | netif_device_attach(netdev); | 2885 | netif_device_attach(netdev); |
2869 | 2886 | ||
2870 | atl1_via_workaround(adapter); | ||
2871 | |||
2872 | return 0; | 2887 | return 0; |
2873 | } | 2888 | } |
2874 | #else | 2889 | #else |
@@ -2876,6 +2891,13 @@ static int atl1_resume(struct pci_dev *pdev) | |||
2876 | #define atl1_resume NULL | 2891 | #define atl1_resume NULL |
2877 | #endif | 2892 | #endif |
2878 | 2893 | ||
2894 | static void atl1_shutdown(struct pci_dev *pdev) | ||
2895 | { | ||
2896 | #ifdef CONFIG_PM | ||
2897 | atl1_suspend(pdev, PMSG_SUSPEND); | ||
2898 | #endif | ||
2899 | } | ||
2900 | |||
2879 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2901 | #ifdef CONFIG_NET_POLL_CONTROLLER |
2880 | static void atl1_poll_controller(struct net_device *netdev) | 2902 | static void atl1_poll_controller(struct net_device *netdev) |
2881 | { | 2903 | { |
@@ -3122,7 +3144,8 @@ static struct pci_driver atl1_driver = { | |||
3122 | .probe = atl1_probe, | 3144 | .probe = atl1_probe, |
3123 | .remove = __devexit_p(atl1_remove), | 3145 | .remove = __devexit_p(atl1_remove), |
3124 | .suspend = atl1_suspend, | 3146 | .suspend = atl1_suspend, |
3125 | .resume = atl1_resume | 3147 | .resume = atl1_resume, |
3148 | .shutdown = atl1_shutdown | ||
3126 | }; | 3149 | }; |
3127 | 3150 | ||
3128 | /* | 3151 | /* |