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 | |
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')
-rw-r--r-- | drivers/net/e1000/e1000.h | 3 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_ethtool.c | 166 | ||||
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 47 |
3 files changed, 127 insertions, 89 deletions
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 70ba3783ad80..98afa9c2057e 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h | |||
@@ -246,7 +246,6 @@ struct e1000_adapter { | |||
246 | uint32_t bd_number; | 246 | uint32_t bd_number; |
247 | uint32_t rx_buffer_len; | 247 | uint32_t rx_buffer_len; |
248 | uint32_t wol; | 248 | uint32_t wol; |
249 | uint32_t ksp3_port_a; | ||
250 | uint32_t smartspeed; | 249 | uint32_t smartspeed; |
251 | uint32_t en_mng_pt; | 250 | uint32_t en_mng_pt; |
252 | uint16_t link_speed; | 251 | uint16_t link_speed; |
@@ -341,7 +340,9 @@ struct e1000_adapter { | |||
341 | boolean_t tso_force; | 340 | boolean_t tso_force; |
342 | #endif | 341 | #endif |
343 | boolean_t smart_power_down; /* phy smart power down */ | 342 | boolean_t smart_power_down; /* phy smart power down */ |
343 | boolean_t quad_port_a; | ||
344 | unsigned long flags; | 344 | unsigned long flags; |
345 | uint32_t eeprom_wol; | ||
345 | }; | 346 | }; |
346 | 347 | ||
347 | enum e1000_state_t { | 348 | enum e1000_state_t { |
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 | ||
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index c128f62fa45e..9071b78c77f9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -681,9 +681,9 @@ e1000_probe(struct pci_dev *pdev, | |||
681 | unsigned long flash_start, flash_len; | 681 | unsigned long flash_start, flash_len; |
682 | 682 | ||
683 | static int cards_found = 0; | 683 | static int cards_found = 0; |
684 | static int e1000_ksp3_port_a = 0; /* global ksp3 port a indication */ | 684 | static int global_quad_port_a = 0; /* global ksp3 port a indication */ |
685 | int i, err, pci_using_dac; | 685 | int i, err, pci_using_dac; |
686 | uint16_t eeprom_data; | 686 | uint16_t eeprom_data = 0; |
687 | uint16_t eeprom_apme_mask = E1000_EEPROM_APME; | 687 | uint16_t eeprom_apme_mask = E1000_EEPROM_APME; |
688 | if ((err = pci_enable_device(pdev))) | 688 | if ((err = pci_enable_device(pdev))) |
689 | return err; | 689 | return err; |
@@ -786,15 +786,6 @@ e1000_probe(struct pci_dev *pdev, | |||
786 | if (e1000_check_phy_reset_block(&adapter->hw)) | 786 | if (e1000_check_phy_reset_block(&adapter->hw)) |
787 | DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); | 787 | DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); |
788 | 788 | ||
789 | /* if ksp3, indicate if it's port a being setup */ | ||
790 | if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && | ||
791 | e1000_ksp3_port_a == 0) | ||
792 | adapter->ksp3_port_a = 1; | ||
793 | e1000_ksp3_port_a++; | ||
794 | /* Reset for multiple KP3 adapters */ | ||
795 | if (e1000_ksp3_port_a == 4) | ||
796 | e1000_ksp3_port_a = 0; | ||
797 | |||
798 | if (adapter->hw.mac_type >= e1000_82543) { | 789 | if (adapter->hw.mac_type >= e1000_82543) { |
799 | netdev->features = NETIF_F_SG | | 790 | netdev->features = NETIF_F_SG | |
800 | NETIF_F_HW_CSUM | | 791 | NETIF_F_HW_CSUM | |
@@ -913,7 +904,37 @@ e1000_probe(struct pci_dev *pdev, | |||
913 | break; | 904 | break; |
914 | } | 905 | } |
915 | if (eeprom_data & eeprom_apme_mask) | 906 | if (eeprom_data & eeprom_apme_mask) |
916 | adapter->wol |= E1000_WUFC_MAG; | 907 | adapter->eeprom_wol |= E1000_WUFC_MAG; |
908 | |||
909 | /* now that we have the eeprom settings, apply the special cases | ||
910 | * where the eeprom may be wrong or the board simply won't support | ||
911 | * wake on lan on a particular port */ | ||
912 | switch (pdev->device) { | ||
913 | case E1000_DEV_ID_82546GB_PCIE: | ||
914 | adapter->eeprom_wol = 0; | ||
915 | break; | ||
916 | case E1000_DEV_ID_82546EB_FIBER: | ||
917 | case E1000_DEV_ID_82546GB_FIBER: | ||
918 | case E1000_DEV_ID_82571EB_FIBER: | ||
919 | /* Wake events only supported on port A for dual fiber | ||
920 | * regardless of eeprom setting */ | ||
921 | if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) | ||
922 | adapter->eeprom_wol = 0; | ||
923 | break; | ||
924 | case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: | ||
925 | /* if quad port adapter, disable WoL on all but port A */ | ||
926 | if (global_quad_port_a != 0) | ||
927 | adapter->eeprom_wol = 0; | ||
928 | else | ||
929 | adapter->quad_port_a = 1; | ||
930 | /* Reset for multiple quad port adapters */ | ||
931 | if (++global_quad_port_a == 4) | ||
932 | global_quad_port_a = 0; | ||
933 | break; | ||
934 | } | ||
935 | |||
936 | /* initialize the wol settings based on the eeprom settings */ | ||
937 | adapter->wol = adapter->eeprom_wol; | ||
917 | 938 | ||
918 | /* print bus type/speed/width info */ | 939 | /* print bus type/speed/width info */ |
919 | { | 940 | { |
@@ -4635,7 +4656,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4635 | e1000_set_multi(netdev); | 4656 | e1000_set_multi(netdev); |
4636 | 4657 | ||
4637 | /* turn on all-multi mode if wake on multicast is enabled */ | 4658 | /* turn on all-multi mode if wake on multicast is enabled */ |
4638 | if (adapter->wol & E1000_WUFC_MC) { | 4659 | if (wufc & E1000_WUFC_MC) { |
4639 | rctl = E1000_READ_REG(&adapter->hw, RCTL); | 4660 | rctl = E1000_READ_REG(&adapter->hw, RCTL); |
4640 | rctl |= E1000_RCTL_MPE; | 4661 | rctl |= E1000_RCTL_MPE; |
4641 | E1000_WRITE_REG(&adapter->hw, RCTL, rctl); | 4662 | E1000_WRITE_REG(&adapter->hw, RCTL, rctl); |