diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2006-08-31 17:27:46 -0400 |
---|---|---|
committer | Auke Kok <juke-jan.h.kok@intel.com> | 2006-08-31 17:27:46 -0400 |
commit | 120cd57644f85b280b538ee403423641167913a9 (patch) | |
tree | 32c35ef6464c0894c6c279d378493c9d6a289402 /drivers/net/e1000/e1000_ethtool.c | |
parent | 1db2740d78c74eb11c4d0906047d9c13229a89a4 (diff) |
e1000: unify WoL capability detection code
WoL is constantly giving problems and needed a rewrite. Consolidates
all WoL capabilities into a single function, and disables WoL for all
other ports on the device except for port A.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Diffstat (limited to 'drivers/net/e1000/e1000_ethtool.c')
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 166 |
1 files changed, 91 insertions, 75 deletions
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index ab2f153d5735..04030729882b 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
@@ -1675,14 +1675,12 @@ e1000_diag_test(struct net_device *netdev, | |||
1675 | msleep_interruptible(4 * 1000); | 1675 | msleep_interruptible(4 * 1000); |
1676 | } | 1676 | } |
1677 | 1677 | ||
1678 | static void | 1678 | static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) |
1679 | e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | ||
1680 | { | 1679 | { |
1681 | struct e1000_adapter *adapter = netdev_priv(netdev); | ||
1682 | struct e1000_hw *hw = &adapter->hw; | 1680 | struct e1000_hw *hw = &adapter->hw; |
1681 | int retval = 1; /* fail by default */ | ||
1683 | 1682 | ||
1684 | switch (adapter->hw.device_id) { | 1683 | switch (hw->device_id) { |
1685 | case E1000_DEV_ID_82542: | ||
1686 | case E1000_DEV_ID_82543GC_FIBER: | 1684 | case E1000_DEV_ID_82543GC_FIBER: |
1687 | case E1000_DEV_ID_82543GC_COPPER: | 1685 | case E1000_DEV_ID_82543GC_COPPER: |
1688 | case E1000_DEV_ID_82544EI_FIBER: | 1686 | case E1000_DEV_ID_82544EI_FIBER: |
@@ -1690,52 +1688,86 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
1690 | case E1000_DEV_ID_82545EM_FIBER: | 1688 | case E1000_DEV_ID_82545EM_FIBER: |
1691 | case E1000_DEV_ID_82545EM_COPPER: | 1689 | case E1000_DEV_ID_82545EM_COPPER: |
1692 | case E1000_DEV_ID_82546GB_QUAD_COPPER: | 1690 | case E1000_DEV_ID_82546GB_QUAD_COPPER: |
1691 | case E1000_DEV_ID_82546GB_PCIE: | ||
1692 | /* these don't support WoL at all */ | ||
1693 | wol->supported = 0; | 1693 | wol->supported = 0; |
1694 | wol->wolopts = 0; | 1694 | break; |
1695 | return; | ||
1696 | |||
1697 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | ||
1698 | /* device id 10B5 port-A supports wol */ | ||
1699 | if (!adapter->ksp3_port_a) { | ||
1700 | wol->supported = 0; | ||
1701 | return; | ||
1702 | } | ||
1703 | /* KSP3 does not suppport UCAST wake-ups for any interface */ | ||
1704 | wol->supported = WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; | ||
1705 | |||
1706 | if (adapter->wol & E1000_WUFC_EX) | ||
1707 | DPRINTK(DRV, ERR, "Interface does not support " | ||
1708 | "directed (unicast) frame wake-up packets\n"); | ||
1709 | wol->wolopts = 0; | ||
1710 | goto do_defaults; | ||
1711 | |||
1712 | case E1000_DEV_ID_82546EB_FIBER: | 1695 | case E1000_DEV_ID_82546EB_FIBER: |
1713 | case E1000_DEV_ID_82546GB_FIBER: | 1696 | case E1000_DEV_ID_82546GB_FIBER: |
1714 | case E1000_DEV_ID_82571EB_FIBER: | 1697 | case E1000_DEV_ID_82571EB_FIBER: |
1715 | /* Wake events only supported on port A for dual fiber */ | 1698 | case E1000_DEV_ID_82571EB_SERDES: |
1699 | case E1000_DEV_ID_82571EB_COPPER: | ||
1700 | /* Wake events not supported on port B */ | ||
1716 | if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { | 1701 | if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { |
1717 | wol->supported = 0; | 1702 | wol->supported = 0; |
1718 | wol->wolopts = 0; | 1703 | break; |
1719 | return; | ||
1720 | } | 1704 | } |
1721 | /* Fall Through */ | 1705 | /* return success for non excluded adapter ports */ |
1722 | 1706 | retval = 0; | |
1707 | break; | ||
1708 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | ||
1709 | /* quad port adapters only support WoL on port A */ | ||
1710 | if (!adapter->quad_port_a) { | ||
1711 | wol->supported = 0; | ||
1712 | break; | ||
1713 | } | ||
1714 | /* return success for non excluded adapter ports */ | ||
1715 | retval = 0; | ||
1716 | break; | ||
1723 | default: | 1717 | default: |
1724 | wol->supported = WAKE_UCAST | WAKE_MCAST | | 1718 | /* dual port cards only support WoL on port A from now on |
1725 | WAKE_BCAST | WAKE_MAGIC; | 1719 | * unless it was enabled in the eeprom for port B |
1726 | wol->wolopts = 0; | 1720 | * so exclude FUNC_1 ports from having WoL enabled */ |
1721 | if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1 && | ||
1722 | !adapter->eeprom_wol) { | ||
1723 | wol->supported = 0; | ||
1724 | break; | ||
1725 | } | ||
1727 | 1726 | ||
1728 | do_defaults: | 1727 | retval = 0; |
1729 | if (adapter->wol & E1000_WUFC_EX) | 1728 | } |
1730 | wol->wolopts |= WAKE_UCAST; | 1729 | |
1731 | if (adapter->wol & E1000_WUFC_MC) | 1730 | return retval; |
1732 | wol->wolopts |= WAKE_MCAST; | 1731 | } |
1733 | if (adapter->wol & E1000_WUFC_BC) | 1732 | |
1734 | wol->wolopts |= WAKE_BCAST; | 1733 | static void |
1735 | if (adapter->wol & E1000_WUFC_MAG) | 1734 | e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) |
1736 | wol->wolopts |= WAKE_MAGIC; | 1735 | { |
1736 | struct e1000_adapter *adapter = netdev_priv(netdev); | ||
1737 | |||
1738 | wol->supported = WAKE_UCAST | WAKE_MCAST | | ||
1739 | WAKE_BCAST | WAKE_MAGIC; | ||
1740 | wol->wolopts = 0; | ||
1741 | |||
1742 | /* this function will set ->supported = 0 and return 1 if wol is not | ||
1743 | * supported by this hardware */ | ||
1744 | if (e1000_wol_exclusion(adapter, wol)) | ||
1737 | return; | 1745 | return; |
1746 | |||
1747 | /* apply any specific unsupported masks here */ | ||
1748 | switch (adapter->hw.device_id) { | ||
1749 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | ||
1750 | /* KSP3 does not suppport UCAST wake-ups */ | ||
1751 | wol->supported &= ~WAKE_UCAST; | ||
1752 | |||
1753 | if (adapter->wol & E1000_WUFC_EX) | ||
1754 | DPRINTK(DRV, ERR, "Interface does not support " | ||
1755 | "directed (unicast) frame wake-up packets\n"); | ||
1756 | break; | ||
1757 | default: | ||
1758 | break; | ||
1738 | } | 1759 | } |
1760 | |||
1761 | if (adapter->wol & E1000_WUFC_EX) | ||
1762 | wol->wolopts |= WAKE_UCAST; | ||
1763 | if (adapter->wol & E1000_WUFC_MC) | ||
1764 | wol->wolopts |= WAKE_MCAST; | ||
1765 | if (adapter->wol & E1000_WUFC_BC) | ||
1766 | wol->wolopts |= WAKE_BCAST; | ||
1767 | if (adapter->wol & E1000_WUFC_MAG) | ||
1768 | wol->wolopts |= WAKE_MAGIC; | ||
1769 | |||
1770 | return; | ||
1739 | } | 1771 | } |
1740 | 1772 | ||
1741 | static int | 1773 | static int |
@@ -1744,52 +1776,36 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
1744 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1776 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1745 | struct e1000_hw *hw = &adapter->hw; | 1777 | struct e1000_hw *hw = &adapter->hw; |
1746 | 1778 | ||
1747 | switch (adapter->hw.device_id) { | 1779 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) |
1748 | case E1000_DEV_ID_82542: | 1780 | return -EOPNOTSUPP; |
1749 | case E1000_DEV_ID_82543GC_FIBER: | 1781 | |
1750 | case E1000_DEV_ID_82543GC_COPPER: | 1782 | if (e1000_wol_exclusion(adapter, wol)) |
1751 | case E1000_DEV_ID_82544EI_FIBER: | ||
1752 | case E1000_DEV_ID_82546EB_QUAD_COPPER: | ||
1753 | case E1000_DEV_ID_82546GB_QUAD_COPPER: | ||
1754 | case E1000_DEV_ID_82545EM_FIBER: | ||
1755 | case E1000_DEV_ID_82545EM_COPPER: | ||
1756 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1783 | return wol->wolopts ? -EOPNOTSUPP : 0; |
1757 | 1784 | ||
1785 | switch (hw->device_id) { | ||
1758 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | 1786 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: |
1759 | /* device id 10B5 port-A supports wol */ | ||
1760 | if (!adapter->ksp3_port_a) | ||
1761 | return wol->wolopts ? -EOPNOTSUPP : 0; | ||
1762 | |||
1763 | if (wol->wolopts & WAKE_UCAST) { | 1787 | if (wol->wolopts & WAKE_UCAST) { |
1764 | DPRINTK(DRV, ERR, "Interface does not support " | 1788 | DPRINTK(DRV, ERR, "Interface does not support " |
1765 | "directed (unicast) frame wake-up packets\n"); | 1789 | "directed (unicast) frame wake-up packets\n"); |
1766 | return -EOPNOTSUPP; | 1790 | return -EOPNOTSUPP; |
1767 | } | 1791 | } |
1768 | 1792 | break; | |
1769 | case E1000_DEV_ID_82546EB_FIBER: | ||
1770 | case E1000_DEV_ID_82546GB_FIBER: | ||
1771 | case E1000_DEV_ID_82571EB_FIBER: | ||
1772 | /* Wake events only supported on port A for dual fiber */ | ||
1773 | if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) | ||
1774 | return wol->wolopts ? -EOPNOTSUPP : 0; | ||
1775 | /* Fall Through */ | ||
1776 | |||
1777 | default: | 1793 | default: |
1778 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) | 1794 | break; |
1779 | return -EOPNOTSUPP; | ||
1780 | |||
1781 | adapter->wol = 0; | ||
1782 | |||
1783 | if (wol->wolopts & WAKE_UCAST) | ||
1784 | adapter->wol |= E1000_WUFC_EX; | ||
1785 | if (wol->wolopts & WAKE_MCAST) | ||
1786 | adapter->wol |= E1000_WUFC_MC; | ||
1787 | if (wol->wolopts & WAKE_BCAST) | ||
1788 | adapter->wol |= E1000_WUFC_BC; | ||
1789 | if (wol->wolopts & WAKE_MAGIC) | ||
1790 | adapter->wol |= E1000_WUFC_MAG; | ||
1791 | } | 1795 | } |
1792 | 1796 | ||
1797 | /* these settings will always override what we currently have */ | ||
1798 | adapter->wol = 0; | ||
1799 | |||
1800 | if (wol->wolopts & WAKE_UCAST) | ||
1801 | adapter->wol |= E1000_WUFC_EX; | ||
1802 | if (wol->wolopts & WAKE_MCAST) | ||
1803 | adapter->wol |= E1000_WUFC_MC; | ||
1804 | if (wol->wolopts & WAKE_BCAST) | ||
1805 | adapter->wol |= E1000_WUFC_BC; | ||
1806 | if (wol->wolopts & WAKE_MAGIC) | ||
1807 | adapter->wol |= E1000_WUFC_MAG; | ||
1808 | |||
1793 | return 0; | 1809 | return 0; |
1794 | } | 1810 | } |
1795 | 1811 | ||