aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000
diff options
context:
space:
mode:
authorJesse Brandeburg <jesse.brandeburg@intel.com>2006-08-31 17:27:46 -0400
committerAuke Kok <juke-jan.h.kok@intel.com>2006-08-31 17:27:46 -0400
commit120cd57644f85b280b538ee403423641167913a9 (patch)
tree32c35ef6464c0894c6c279d378493c9d6a289402 /drivers/net/e1000
parent1db2740d78c74eb11c4d0906047d9c13229a89a4 (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.h3
-rw-r--r--drivers/net/e1000/e1000_ethtool.c166
-rw-r--r--drivers/net/e1000/e1000_main.c47
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
347enum e1000_state_t { 348enum 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
1678static void 1678static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
1679e1000_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
1728do_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; 1733static void
1735 if (adapter->wol & E1000_WUFC_MAG) 1734e1000_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
1741static int 1773static 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);