e1000e: Feature Enable PHY Ultra Low Power Mode (ULP)
ULP is a power saving feature that reduces the power consumption of the PHY when a cable is not connected. ULP is gated on the following conditions: 1) The hardware must support ULP. Currently this is only I218 devices from Intel 2) ULP is initiated by the driver, so, no driver results in no ULP. 3) ULP's implementation utilizes Runtime Power Management to toggle its execution. ULP is enabled/disabled based on the state of Runtime PM. 4) ULP is not active when wake-on-unicast, multicast or broadcast is active as these features are mutually-exclusive. Since the PHY is in an unavailable state while ULP is active, any access of the PHY registers will fail. This is resolved by utilizing kernel calls that cause the device to exit Runtime PM (e.g. pm_runtime_get_sync) and then, after PHY access is complete, allow the device to resume Runtime PM (e.g. pm_runtime_put_sync). Under certain conditions, toggling the LANPHYPC is necessary to disable ULP mode. Break out existing code to toggle LANPHYPC to a new function to avoid code duplication. Signed-off-by: Dave Ertman <davidx.m.ertman@intel.com> Cc: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:

committed by
Jeff Kirsher

parent
63eb48f151
commit
74f350ee08
@@ -5856,7 +5856,7 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
|
||||
static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
|
||||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 i, mac_reg;
|
||||
u32 i, mac_reg, wuc;
|
||||
u16 phy_reg, wuc_enable;
|
||||
int retval;
|
||||
|
||||
@@ -5903,13 +5903,18 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
|
||||
phy_reg |= BM_RCTL_RFCE;
|
||||
hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg);
|
||||
|
||||
wuc = E1000_WUC_PME_EN;
|
||||
if (wufc & (E1000_WUFC_MAG | E1000_WUFC_LNKC))
|
||||
wuc |= E1000_WUC_APME;
|
||||
|
||||
/* enable PHY wakeup in MAC register */
|
||||
ew32(WUFC, wufc);
|
||||
ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
|
||||
ew32(WUC, (E1000_WUC_PHY_WAKE | E1000_WUC_APMPME |
|
||||
E1000_WUC_PME_STATUS | wuc));
|
||||
|
||||
/* configure and enable PHY wakeup in PHY registers */
|
||||
hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc);
|
||||
hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
|
||||
hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, wuc);
|
||||
|
||||
/* activate PHY wakeup */
|
||||
wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
|
||||
@@ -6012,8 +6017,19 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
|
||||
e1000_power_down_phy(adapter);
|
||||
}
|
||||
|
||||
if (adapter->hw.phy.type == e1000_phy_igp_3)
|
||||
if (adapter->hw.phy.type == e1000_phy_igp_3) {
|
||||
e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
|
||||
} else if (hw->mac.type == e1000_pch_lpt) {
|
||||
if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
|
||||
/* ULP does not support wake from unicast, multicast
|
||||
* or broadcast.
|
||||
*/
|
||||
retval = e1000_enable_ulp_lpt_lp(hw, !runtime);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* Release control of h/w to f/w. If f/w is AMT enabled, this
|
||||
* would have already happened in close and is redundant.
|
||||
|
Reference in New Issue
Block a user