提交 120cd576 编写于 作者: J Jesse Brandeburg 提交者: Auke Kok

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: NJesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: NAuke Kok <auke-jan.h.kok@intel.com>
上级 1db2740d
...@@ -246,7 +246,6 @@ struct e1000_adapter { ...@@ -246,7 +246,6 @@ struct e1000_adapter {
uint32_t bd_number; uint32_t bd_number;
uint32_t rx_buffer_len; uint32_t rx_buffer_len;
uint32_t wol; uint32_t wol;
uint32_t ksp3_port_a;
uint32_t smartspeed; uint32_t smartspeed;
uint32_t en_mng_pt; uint32_t en_mng_pt;
uint16_t link_speed; uint16_t link_speed;
...@@ -341,7 +340,9 @@ struct e1000_adapter { ...@@ -341,7 +340,9 @@ struct e1000_adapter {
boolean_t tso_force; boolean_t tso_force;
#endif #endif
boolean_t smart_power_down; /* phy smart power down */ boolean_t smart_power_down; /* phy smart power down */
boolean_t quad_port_a;
unsigned long flags; unsigned long flags;
uint32_t eeprom_wol;
}; };
enum e1000_state_t { enum e1000_state_t {
......
...@@ -1675,14 +1675,12 @@ e1000_diag_test(struct net_device *netdev, ...@@ -1675,14 +1675,12 @@ e1000_diag_test(struct net_device *netdev,
msleep_interruptible(4 * 1000); msleep_interruptible(4 * 1000);
} }
static void static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{ {
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
int retval = 1; /* fail by default */
switch (adapter->hw.device_id) { switch (hw->device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER: case E1000_DEV_ID_82543GC_COPPER:
case E1000_DEV_ID_82544EI_FIBER: case E1000_DEV_ID_82544EI_FIBER:
...@@ -1690,52 +1688,86 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ...@@ -1690,52 +1688,86 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546GB_QUAD_COPPER: case E1000_DEV_ID_82546GB_QUAD_COPPER:
case E1000_DEV_ID_82546GB_PCIE:
/* these don't support WoL at all */
wol->supported = 0; wol->supported = 0;
wol->wolopts = 0; break;
return;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* device id 10B5 port-A supports wol */
if (!adapter->ksp3_port_a) {
wol->supported = 0;
return;
}
/* KSP3 does not suppport UCAST wake-ups for any interface */
wol->supported = WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
if (adapter->wol & E1000_WUFC_EX)
DPRINTK(DRV, ERR, "Interface does not support "
"directed (unicast) frame wake-up packets\n");
wol->wolopts = 0;
goto do_defaults;
case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER: case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */ case E1000_DEV_ID_82571EB_SERDES:
case E1000_DEV_ID_82571EB_COPPER:
/* Wake events not supported on port B */
if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0; wol->supported = 0;
wol->wolopts = 0; break;
return;
} }
/* Fall Through */ /* return success for non excluded adapter ports */
retval = 0;
break;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* quad port adapters only support WoL on port A */
if (!adapter->quad_port_a) {
wol->supported = 0;
break;
}
/* return success for non excluded adapter ports */
retval = 0;
break;
default: default:
wol->supported = WAKE_UCAST | WAKE_MCAST | /* dual port cards only support WoL on port A from now on
WAKE_BCAST | WAKE_MAGIC; * unless it was enabled in the eeprom for port B
wol->wolopts = 0; * so exclude FUNC_1 ports from having WoL enabled */
if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1 &&
!adapter->eeprom_wol) {
wol->supported = 0;
break;
}
do_defaults: retval = 0;
if (adapter->wol & E1000_WUFC_EX) }
wol->wolopts |= WAKE_UCAST;
if (adapter->wol & E1000_WUFC_MC) return retval;
wol->wolopts |= WAKE_MCAST; }
if (adapter->wol & E1000_WUFC_BC)
wol->wolopts |= WAKE_BCAST; static void
if (adapter->wol & E1000_WUFC_MAG) e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
wol->wolopts |= WAKE_MAGIC; {
struct e1000_adapter *adapter = netdev_priv(netdev);
wol->supported = WAKE_UCAST | WAKE_MCAST |
WAKE_BCAST | WAKE_MAGIC;
wol->wolopts = 0;
/* this function will set ->supported = 0 and return 1 if wol is not
* supported by this hardware */
if (e1000_wol_exclusion(adapter, wol))
return; return;
/* apply any specific unsupported masks here */
switch (adapter->hw.device_id) {
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* KSP3 does not suppport UCAST wake-ups */
wol->supported &= ~WAKE_UCAST;
if (adapter->wol & E1000_WUFC_EX)
DPRINTK(DRV, ERR, "Interface does not support "
"directed (unicast) frame wake-up packets\n");
break;
default:
break;
} }
if (adapter->wol & E1000_WUFC_EX)
wol->wolopts |= WAKE_UCAST;
if (adapter->wol & E1000_WUFC_MC)
wol->wolopts |= WAKE_MCAST;
if (adapter->wol & E1000_WUFC_BC)
wol->wolopts |= WAKE_BCAST;
if (adapter->wol & E1000_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
} }
static int static int
...@@ -1744,52 +1776,36 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) ...@@ -1744,52 +1776,36 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
switch (adapter->hw.device_id) { if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
case E1000_DEV_ID_82542: return -EOPNOTSUPP;
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER: if (e1000_wol_exclusion(adapter, wol))
case E1000_DEV_ID_82544EI_FIBER:
case E1000_DEV_ID_82546EB_QUAD_COPPER:
case E1000_DEV_ID_82546GB_QUAD_COPPER:
case E1000_DEV_ID_82545EM_FIBER:
case E1000_DEV_ID_82545EM_COPPER:
return wol->wolopts ? -EOPNOTSUPP : 0; return wol->wolopts ? -EOPNOTSUPP : 0;
switch (hw->device_id) {
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* device id 10B5 port-A supports wol */
if (!adapter->ksp3_port_a)
return wol->wolopts ? -EOPNOTSUPP : 0;
if (wol->wolopts & WAKE_UCAST) { if (wol->wolopts & WAKE_UCAST) {
DPRINTK(DRV, ERR, "Interface does not support " DPRINTK(DRV, ERR, "Interface does not support "
"directed (unicast) frame wake-up packets\n"); "directed (unicast) frame wake-up packets\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
break;
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */
if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
return wol->wolopts ? -EOPNOTSUPP : 0;
/* Fall Through */
default: default:
if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) break;
return -EOPNOTSUPP;
adapter->wol = 0;
if (wol->wolopts & WAKE_UCAST)
adapter->wol |= E1000_WUFC_EX;
if (wol->wolopts & WAKE_MCAST)
adapter->wol |= E1000_WUFC_MC;
if (wol->wolopts & WAKE_BCAST)
adapter->wol |= E1000_WUFC_BC;
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
} }
/* these settings will always override what we currently have */
adapter->wol = 0;
if (wol->wolopts & WAKE_UCAST)
adapter->wol |= E1000_WUFC_EX;
if (wol->wolopts & WAKE_MCAST)
adapter->wol |= E1000_WUFC_MC;
if (wol->wolopts & WAKE_BCAST)
adapter->wol |= E1000_WUFC_BC;
if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
return 0; return 0;
} }
......
...@@ -681,9 +681,9 @@ e1000_probe(struct pci_dev *pdev, ...@@ -681,9 +681,9 @@ e1000_probe(struct pci_dev *pdev,
unsigned long flash_start, flash_len; unsigned long flash_start, flash_len;
static int cards_found = 0; static int cards_found = 0;
static int e1000_ksp3_port_a = 0; /* global ksp3 port a indication */ static int global_quad_port_a = 0; /* global ksp3 port a indication */
int i, err, pci_using_dac; int i, err, pci_using_dac;
uint16_t eeprom_data; uint16_t eeprom_data = 0;
uint16_t eeprom_apme_mask = E1000_EEPROM_APME; uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
if ((err = pci_enable_device(pdev))) if ((err = pci_enable_device(pdev)))
return err; return err;
...@@ -786,15 +786,6 @@ e1000_probe(struct pci_dev *pdev, ...@@ -786,15 +786,6 @@ e1000_probe(struct pci_dev *pdev,
if (e1000_check_phy_reset_block(&adapter->hw)) if (e1000_check_phy_reset_block(&adapter->hw))
DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n"); DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
/* if ksp3, indicate if it's port a being setup */
if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 &&
e1000_ksp3_port_a == 0)
adapter->ksp3_port_a = 1;
e1000_ksp3_port_a++;
/* Reset for multiple KP3 adapters */
if (e1000_ksp3_port_a == 4)
e1000_ksp3_port_a = 0;
if (adapter->hw.mac_type >= e1000_82543) { if (adapter->hw.mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG | netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM | NETIF_F_HW_CSUM |
...@@ -913,7 +904,37 @@ e1000_probe(struct pci_dev *pdev, ...@@ -913,7 +904,37 @@ e1000_probe(struct pci_dev *pdev,
break; break;
} }
if (eeprom_data & eeprom_apme_mask) if (eeprom_data & eeprom_apme_mask)
adapter->wol |= E1000_WUFC_MAG; adapter->eeprom_wol |= E1000_WUFC_MAG;
/* now that we have the eeprom settings, apply the special cases
* where the eeprom may be wrong or the board simply won't support
* wake on lan on a particular port */
switch (pdev->device) {
case E1000_DEV_ID_82546GB_PCIE:
adapter->eeprom_wol = 0;
break;
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber
* regardless of eeprom setting */
if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
adapter->eeprom_wol = 0;
break;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* if quad port adapter, disable WoL on all but port A */
if (global_quad_port_a != 0)
adapter->eeprom_wol = 0;
else
adapter->quad_port_a = 1;
/* Reset for multiple quad port adapters */
if (++global_quad_port_a == 4)
global_quad_port_a = 0;
break;
}
/* initialize the wol settings based on the eeprom settings */
adapter->wol = adapter->eeprom_wol;
/* print bus type/speed/width info */ /* print bus type/speed/width info */
{ {
...@@ -4635,7 +4656,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -4635,7 +4656,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
e1000_set_multi(netdev); e1000_set_multi(netdev);
/* turn on all-multi mode if wake on multicast is enabled */ /* turn on all-multi mode if wake on multicast is enabled */
if (adapter->wol & E1000_WUFC_MC) { if (wufc & E1000_WUFC_MC) {
rctl = E1000_READ_REG(&adapter->hw, RCTL); rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_MPE; rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl); E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册