Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Ertman and committed by
Jeff Kirsher
74f350ee 63eb48f1

+354 -33
+5 -3
drivers/net/ethernet/intel/e1000e/defines.h
··· 28 28 29 29 /* Definitions for power management and wakeup registers */ 30 30 /* Wake Up Control */ 31 - #define E1000_WUC_APME 0x00000001 /* APM Enable */ 32 - #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ 33 - #define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ 31 + #define E1000_WUC_APME 0x00000001 /* APM Enable */ 32 + #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ 33 + #define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ 34 + #define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ 35 + #define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ 34 36 35 37 /* Wake Up Filter Control */ 36 38 #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+8
drivers/net/ethernet/intel/e1000e/hw.h
··· 648 648 649 649 #define E1000_ICH8_SHADOW_RAM_WORDS 2048 650 650 651 + /* I218 PHY Ultra Low Power (ULP) states */ 652 + enum e1000_ulp_state { 653 + e1000_ulp_state_unknown, 654 + e1000_ulp_state_off, 655 + e1000_ulp_state_on, 656 + }; 657 + 651 658 struct e1000_dev_spec_ich8lan { 652 659 bool kmrn_lock_loss_workaround_enabled; 653 660 struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; 654 661 bool nvm_k1_enabled; 655 662 bool eee_disable; 656 663 u16 eee_lp_ability; 664 + enum e1000_ulp_state ulp_state; 657 665 }; 658 666 659 667 struct e1000_hw {
+298 -26
drivers/net/ethernet/intel/e1000e/ich8lan.c
··· 143 143 static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); 144 144 static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); 145 145 static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); 146 + static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force); 146 147 static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw); 148 + static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state); 147 149 148 150 static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) 149 151 { ··· 242 240 } 243 241 244 242 /** 243 + * e1000_toggle_lanphypc_pch_lpt - toggle the LANPHYPC pin value 244 + * @hw: pointer to the HW structure 245 + * 246 + * Toggling the LANPHYPC pin value fully power-cycles the PHY and is 247 + * used to reset the PHY to a quiescent state when necessary. 248 + **/ 249 + static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) 250 + { 251 + u32 mac_reg; 252 + 253 + /* Set Phy Config Counter to 50msec */ 254 + mac_reg = er32(FEXTNVM3); 255 + mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; 256 + mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; 257 + ew32(FEXTNVM3, mac_reg); 258 + 259 + /* Toggle LANPHYPC Value bit */ 260 + mac_reg = er32(CTRL); 261 + mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; 262 + mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; 263 + ew32(CTRL, mac_reg); 264 + e1e_flush(); 265 + usleep_range(10, 20); 266 + mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; 267 + ew32(CTRL, mac_reg); 268 + e1e_flush(); 269 + 270 + if (hw->mac.type < e1000_pch_lpt) { 271 + msleep(50); 272 + } else { 273 + u16 count = 20; 274 + 275 + do { 276 + usleep_range(5000, 10000); 277 + } while (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LPCD) && count--); 278 + 279 + msleep(30); 280 + } 281 + } 282 + 283 + /** 245 284 * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds 246 285 * @hw: pointer to the HW structure 247 286 * ··· 299 256 * non-managed 82579 and newer adapters. 300 257 */ 301 258 e1000_gate_hw_phy_config_ich8lan(hw, true); 259 + 260 + /* It is not possible to be certain of the current state of ULP 261 + * so forcibly disable it. 262 + */ 263 + hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_unknown; 264 + e1000_disable_ulp_lpt_lp(hw, true); 302 265 303 266 ret_val = hw->phy.ops.acquire(hw); 304 267 if (ret_val) { ··· 351 302 break; 352 303 } 353 304 354 - e_dbg("Toggling LANPHYPC\n"); 355 - 356 - /* Set Phy Config Counter to 50msec */ 357 - mac_reg = er32(FEXTNVM3); 358 - mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; 359 - mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; 360 - ew32(FEXTNVM3, mac_reg); 361 - 362 305 /* Toggle LANPHYPC Value bit */ 363 - mac_reg = er32(CTRL); 364 - mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; 365 - mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; 366 - ew32(CTRL, mac_reg); 367 - e1e_flush(); 368 - usleep_range(10, 20); 369 - mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; 370 - ew32(CTRL, mac_reg); 371 - e1e_flush(); 372 - if (hw->mac.type < e1000_pch_lpt) { 373 - msleep(50); 374 - } else { 375 - u16 count = 20; 376 - do { 377 - usleep_range(5000, 10000); 378 - } while (!(er32(CTRL_EXT) & 379 - E1000_CTRL_EXT_LPCD) && count--); 380 - usleep_range(30000, 60000); 306 + e1000_toggle_lanphypc_pch_lpt(hw); 307 + if (hw->mac.type >= e1000_pch_lpt) { 381 308 if (e1000_phy_is_accessible_pchlan(hw)) 382 309 break; 383 310 ··· 1028 1003 ew32(LTRV, reg); 1029 1004 1030 1005 return 0; 1006 + } 1007 + 1008 + /** 1009 + * e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP 1010 + * @hw: pointer to the HW structure 1011 + * @to_sx: boolean indicating a system power state transition to Sx 1012 + * 1013 + * When link is down, configure ULP mode to significantly reduce the power 1014 + * to the PHY. If on a Manageability Engine (ME) enabled system, tell the 1015 + * ME firmware to start the ULP configuration. If not on an ME enabled 1016 + * system, configure the ULP mode by software. 1017 + */ 1018 + s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) 1019 + { 1020 + u32 mac_reg; 1021 + s32 ret_val = 0; 1022 + u16 phy_reg; 1023 + 1024 + if ((hw->mac.type < e1000_pch_lpt) || 1025 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) || 1026 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_V) || 1027 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM2) || 1028 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V2) || 1029 + (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_on)) 1030 + return 0; 1031 + 1032 + if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { 1033 + /* Request ME configure ULP mode in the PHY */ 1034 + mac_reg = er32(H2ME); 1035 + mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS; 1036 + ew32(H2ME, mac_reg); 1037 + 1038 + goto out; 1039 + } 1040 + 1041 + if (!to_sx) { 1042 + int i = 0; 1043 + 1044 + /* Poll up to 5 seconds for Cable Disconnected indication */ 1045 + while (!(er32(FEXT) & E1000_FEXT_PHY_CABLE_DISCONNECTED)) { 1046 + /* Bail if link is re-acquired */ 1047 + if (er32(STATUS) & E1000_STATUS_LU) 1048 + return -E1000_ERR_PHY; 1049 + 1050 + if (i++ == 100) 1051 + break; 1052 + 1053 + msleep(50); 1054 + } 1055 + e_dbg("CABLE_DISCONNECTED %s set after %dmsec\n", 1056 + (er32(FEXT) & 1057 + E1000_FEXT_PHY_CABLE_DISCONNECTED) ? "" : "not", i * 50); 1058 + } 1059 + 1060 + ret_val = hw->phy.ops.acquire(hw); 1061 + if (ret_val) 1062 + goto out; 1063 + 1064 + /* Force SMBus mode in PHY */ 1065 + ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); 1066 + if (ret_val) 1067 + goto release; 1068 + phy_reg |= CV_SMB_CTRL_FORCE_SMBUS; 1069 + e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); 1070 + 1071 + /* Force SMBus mode in MAC */ 1072 + mac_reg = er32(CTRL_EXT); 1073 + mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; 1074 + ew32(CTRL_EXT, mac_reg); 1075 + 1076 + /* Set Inband ULP Exit, Reset to SMBus mode and 1077 + * Disable SMBus Release on PERST# in PHY 1078 + */ 1079 + ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); 1080 + if (ret_val) 1081 + goto release; 1082 + phy_reg |= (I218_ULP_CONFIG1_RESET_TO_SMBUS | 1083 + I218_ULP_CONFIG1_DISABLE_SMB_PERST); 1084 + if (to_sx) { 1085 + if (er32(WUFC) & E1000_WUFC_LNKC) 1086 + phy_reg |= I218_ULP_CONFIG1_WOL_HOST; 1087 + 1088 + phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; 1089 + } else { 1090 + phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; 1091 + } 1092 + e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); 1093 + 1094 + /* Set Disable SMBus Release on PERST# in MAC */ 1095 + mac_reg = er32(FEXTNVM7); 1096 + mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST; 1097 + ew32(FEXTNVM7, mac_reg); 1098 + 1099 + /* Commit ULP changes in PHY by starting auto ULP configuration */ 1100 + phy_reg |= I218_ULP_CONFIG1_START; 1101 + e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); 1102 + release: 1103 + hw->phy.ops.release(hw); 1104 + out: 1105 + if (ret_val) 1106 + e_dbg("Error in ULP enable flow: %d\n", ret_val); 1107 + else 1108 + hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on; 1109 + 1110 + return ret_val; 1111 + } 1112 + 1113 + /** 1114 + * e1000_disable_ulp_lpt_lp - unconfigure Ultra Low Power mode for LynxPoint-LP 1115 + * @hw: pointer to the HW structure 1116 + * @force: boolean indicating whether or not to force disabling ULP 1117 + * 1118 + * Un-configure ULP mode when link is up, the system is transitioned from 1119 + * Sx or the driver is unloaded. If on a Manageability Engine (ME) enabled 1120 + * system, poll for an indication from ME that ULP has been un-configured. 1121 + * If not on an ME enabled system, un-configure the ULP mode by software. 1122 + * 1123 + * During nominal operation, this function is called when link is acquired 1124 + * to disable ULP mode (force=false); otherwise, for example when unloading 1125 + * the driver or during Sx->S0 transitions, this is called with force=true 1126 + * to forcibly disable ULP. 1127 + */ 1128 + static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) 1129 + { 1130 + s32 ret_val = 0; 1131 + u32 mac_reg; 1132 + u16 phy_reg; 1133 + int i = 0; 1134 + 1135 + if ((hw->mac.type < e1000_pch_lpt) || 1136 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) || 1137 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_V) || 1138 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM2) || 1139 + (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V2) || 1140 + (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_off)) 1141 + return 0; 1142 + 1143 + if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { 1144 + if (force) { 1145 + /* Request ME un-configure ULP mode in the PHY */ 1146 + mac_reg = er32(H2ME); 1147 + mac_reg &= ~E1000_H2ME_ULP; 1148 + mac_reg |= E1000_H2ME_ENFORCE_SETTINGS; 1149 + ew32(H2ME, mac_reg); 1150 + } 1151 + 1152 + /* Poll up to 100msec for ME to clear ULP_CFG_DONE */ 1153 + while (er32(FWSM) & E1000_FWSM_ULP_CFG_DONE) { 1154 + if (i++ == 10) { 1155 + ret_val = -E1000_ERR_PHY; 1156 + goto out; 1157 + } 1158 + 1159 + usleep_range(10000, 20000); 1160 + } 1161 + e_dbg("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10); 1162 + 1163 + if (force) { 1164 + mac_reg = er32(H2ME); 1165 + mac_reg &= ~E1000_H2ME_ENFORCE_SETTINGS; 1166 + ew32(H2ME, mac_reg); 1167 + } else { 1168 + /* Clear H2ME.ULP after ME ULP configuration */ 1169 + mac_reg = er32(H2ME); 1170 + mac_reg &= ~E1000_H2ME_ULP; 1171 + ew32(H2ME, mac_reg); 1172 + } 1173 + 1174 + goto out; 1175 + } 1176 + 1177 + ret_val = hw->phy.ops.acquire(hw); 1178 + if (ret_val) 1179 + goto out; 1180 + 1181 + if (force) 1182 + /* Toggle LANPHYPC Value bit */ 1183 + e1000_toggle_lanphypc_pch_lpt(hw); 1184 + 1185 + /* Unforce SMBus mode in PHY */ 1186 + ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); 1187 + if (ret_val) { 1188 + /* The MAC might be in PCIe mode, so temporarily force to 1189 + * SMBus mode in order to access the PHY. 1190 + */ 1191 + mac_reg = er32(CTRL_EXT); 1192 + mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; 1193 + ew32(CTRL_EXT, mac_reg); 1194 + 1195 + msleep(50); 1196 + 1197 + ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, 1198 + &phy_reg); 1199 + if (ret_val) 1200 + goto release; 1201 + } 1202 + phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; 1203 + e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); 1204 + 1205 + /* Unforce SMBus mode in MAC */ 1206 + mac_reg = er32(CTRL_EXT); 1207 + mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; 1208 + ew32(CTRL_EXT, mac_reg); 1209 + 1210 + /* When ULP mode was previously entered, K1 was disabled by the 1211 + * hardware. Re-Enable K1 in the PHY when exiting ULP. 1212 + */ 1213 + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_PM_CTRL, &phy_reg); 1214 + if (ret_val) 1215 + goto release; 1216 + phy_reg |= HV_PM_CTRL_K1_ENABLE; 1217 + e1000_write_phy_reg_hv_locked(hw, HV_PM_CTRL, phy_reg); 1218 + 1219 + /* Clear ULP enabled configuration */ 1220 + ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); 1221 + if (ret_val) 1222 + goto release; 1223 + phy_reg &= ~(I218_ULP_CONFIG1_IND | 1224 + I218_ULP_CONFIG1_STICKY_ULP | 1225 + I218_ULP_CONFIG1_RESET_TO_SMBUS | 1226 + I218_ULP_CONFIG1_WOL_HOST | 1227 + I218_ULP_CONFIG1_INBAND_EXIT | 1228 + I218_ULP_CONFIG1_DISABLE_SMB_PERST); 1229 + e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); 1230 + 1231 + /* Commit ULP changes by starting auto ULP configuration */ 1232 + phy_reg |= I218_ULP_CONFIG1_START; 1233 + e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); 1234 + 1235 + /* Clear Disable SMBus Release on PERST# in MAC */ 1236 + mac_reg = er32(FEXTNVM7); 1237 + mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST; 1238 + ew32(FEXTNVM7, mac_reg); 1239 + 1240 + release: 1241 + hw->phy.ops.release(hw); 1242 + if (force) { 1243 + e1000_phy_hw_reset(hw); 1244 + msleep(50); 1245 + } 1246 + out: 1247 + if (ret_val) 1248 + e_dbg("Error in ULP disable flow: %d\n", ret_val); 1249 + else 1250 + hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_off; 1251 + 1252 + return ret_val; 1031 1253 } 1032 1254 1033 1255 /**
+22
drivers/net/ethernet/intel/e1000e/ich8lan.h
··· 58 58 59 59 #define E1000_FWSM_WLOCK_MAC_MASK 0x0380 60 60 #define E1000_FWSM_WLOCK_MAC_SHIFT 7 61 + #define E1000_FWSM_ULP_CFG_DONE 0x00000400 /* Low power cfg done */ 61 62 62 63 /* Shared Receive Address Registers */ 63 64 #define E1000_SHRAL_PCH_LPT(_i) (0x05408 + ((_i) * 8)) 64 65 #define E1000_SHRAH_PCH_LPT(_i) (0x0540C + ((_i) * 8)) 66 + 67 + #define E1000_H2ME 0x05B50 /* Host to ME */ 68 + #define E1000_H2ME_ULP 0x00000800 /* ULP Indication Bit */ 69 + #define E1000_H2ME_ENFORCE_SETTINGS 0x00001000 /* Enforce Settings */ 65 70 66 71 #define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ 67 72 (ID_LED_OFF1_OFF2 << 8) | \ ··· 80 75 81 76 #define E1000_ICH8_LAN_INIT_TIMEOUT 1500 82 77 78 + /* FEXT register bit definition */ 79 + #define E1000_FEXT_PHY_CABLE_DISCONNECTED 0x00000004 80 + 83 81 #define E1000_FEXTNVM_SW_CONFIG 1 84 82 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* different on ICH8M */ 85 83 ··· 95 87 96 88 #define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 97 89 #define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200 90 + 91 + #define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020 98 92 99 93 #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL 100 94 ··· 164 154 #define CV_SMB_CTRL PHY_REG(769, 23) 165 155 #define CV_SMB_CTRL_FORCE_SMBUS 0x0001 166 156 157 + /* I218 Ultra Low Power Configuration 1 Register */ 158 + #define I218_ULP_CONFIG1 PHY_REG(779, 16) 159 + #define I218_ULP_CONFIG1_START 0x0001 /* Start auto ULP config */ 160 + #define I218_ULP_CONFIG1_IND 0x0004 /* Pwr up from ULP indication */ 161 + #define I218_ULP_CONFIG1_STICKY_ULP 0x0010 /* Set sticky ULP mode */ 162 + #define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */ 163 + #define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */ 164 + #define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */ 165 + #define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */ 166 + 167 167 /* SMBus Address Phy Register */ 168 168 #define HV_SMB_ADDR PHY_REG(768, 26) 169 169 #define HV_SMB_ADDR_MASK 0x007F ··· 208 188 /* PHY Power Management Control */ 209 189 #define HV_PM_CTRL PHY_REG(770, 17) 210 190 #define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 191 + #define HV_PM_CTRL_K1_ENABLE 0x4000 211 192 212 193 #define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ 213 194 ··· 283 262 s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data); 284 263 s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data); 285 264 s32 e1000_set_eee_pchlan(struct e1000_hw *hw); 265 + s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx); 286 266 #endif /* _E1000E_ICH8LAN_H_ */
+20 -4
drivers/net/ethernet/intel/e1000e/netdev.c
··· 5856 5856 static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) 5857 5857 { 5858 5858 struct e1000_hw *hw = &adapter->hw; 5859 - u32 i, mac_reg; 5859 + u32 i, mac_reg, wuc; 5860 5860 u16 phy_reg, wuc_enable; 5861 5861 int retval; 5862 5862 ··· 5903 5903 phy_reg |= BM_RCTL_RFCE; 5904 5904 hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg); 5905 5905 5906 + wuc = E1000_WUC_PME_EN; 5907 + if (wufc & (E1000_WUFC_MAG | E1000_WUFC_LNKC)) 5908 + wuc |= E1000_WUC_APME; 5909 + 5906 5910 /* enable PHY wakeup in MAC register */ 5907 5911 ew32(WUFC, wufc); 5908 - ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); 5912 + ew32(WUC, (E1000_WUC_PHY_WAKE | E1000_WUC_APMPME | 5913 + E1000_WUC_PME_STATUS | wuc)); 5909 5914 5910 5915 /* configure and enable PHY wakeup in PHY registers */ 5911 5916 hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc); 5912 - hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); 5917 + hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, wuc); 5913 5918 5914 5919 /* activate PHY wakeup */ 5915 5920 wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; ··· 6017 6012 e1000_power_down_phy(adapter); 6018 6013 } 6019 6014 6020 - if (adapter->hw.phy.type == e1000_phy_igp_3) 6015 + if (adapter->hw.phy.type == e1000_phy_igp_3) { 6021 6016 e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); 6017 + } else if (hw->mac.type == e1000_pch_lpt) { 6018 + if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC))) 6019 + /* ULP does not support wake from unicast, multicast 6020 + * or broadcast. 6021 + */ 6022 + retval = e1000_enable_ulp_lpt_lp(hw, !runtime); 6023 + 6024 + if (retval) 6025 + return retval; 6026 + } 6027 + 6022 6028 6023 6029 /* Release control of h/w to f/w. If f/w is AMT enabled, this 6024 6030 * would have already happened in close and is redundant.
+1
drivers/net/ethernet/intel/e1000e/regs.h
··· 32 32 #define E1000_SCTL 0x00024 /* SerDes Control - RW */ 33 33 #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ 34 34 #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ 35 + #define E1000_FEXT 0x0002C /* Future Extended - RW */ 35 36 #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ 36 37 #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ 37 38 #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */