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

e1000e: Workaround for dropped packets in Gig/100 speeds on 82579

This is a workaround for a HW erratum on 82579 devices.
Erratum is #23 in Intel 6 Series Chipset and Intel C200 Series Chipset
specification Update June 2013.

Problem: 82579 parts experience packet loss in Gig and 100 speeds
when interconnect between PHY and MAC is exiting K1 power saving state.
This was previously believed to only affect 1Gig speed, but has been observed
at 100Mbs also.

Workaround: Disable K1 for 82579 devices at Gig and 100 speeds.

Signed-off-by: Dave Ertman <davidx.m.ertman@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

David Ertman and committed by
Jeff Kirsher
77e61146 9d4619c4

+13 -19
+12 -19
drivers/net/ethernet/intel/e1000e/ich8lan.c
··· 2493 2493 * e1000_k1_gig_workaround_lv - K1 Si workaround 2494 2494 * @hw: pointer to the HW structure 2495 2495 * 2496 - * Workaround to set the K1 beacon duration for 82579 parts 2496 + * Workaround to set the K1 beacon duration for 82579 parts in 10Mbps 2497 + * Disable K1 in 1000Mbps and 100Mbps 2497 2498 **/ 2498 2499 static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) 2499 2500 { 2500 2501 s32 ret_val = 0; 2501 2502 u16 status_reg = 0; 2502 - u32 mac_reg; 2503 - u16 phy_reg; 2504 2503 2505 2504 if (hw->mac.type != e1000_pch2lan) 2506 2505 return 0; 2507 2506 2508 - /* Set K1 beacon duration based on 1Gbps speed or otherwise */ 2507 + /* Set K1 beacon duration based on 10Mbs speed */ 2509 2508 ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); 2510 2509 if (ret_val) 2511 2510 return ret_val; 2512 2511 2513 2512 if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) 2514 2513 == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { 2515 - mac_reg = er32(FEXTNVM4); 2516 - mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; 2517 - 2518 - ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); 2519 - if (ret_val) 2520 - return ret_val; 2521 - 2522 - if (status_reg & HV_M_STATUS_SPEED_1000) { 2514 + if (status_reg & 2515 + (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) { 2523 2516 u16 pm_phy_reg; 2524 2517 2525 - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; 2526 - phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; 2527 - /* LV 1G Packet drop issue wa */ 2518 + /* LV 1G/100 Packet drop issue wa */ 2528 2519 ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg); 2529 2520 if (ret_val) 2530 2521 return ret_val; 2531 - pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA; 2522 + pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE; 2532 2523 ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg); 2533 2524 if (ret_val) 2534 2525 return ret_val; 2535 2526 } else { 2527 + u32 mac_reg; 2528 + 2529 + mac_reg = er32(FEXTNVM4); 2530 + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; 2536 2531 mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; 2537 - phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; 2532 + ew32(FEXTNVM4, mac_reg); 2538 2533 } 2539 - ew32(FEXTNVM4, mac_reg); 2540 - ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); 2541 2534 } 2542 2535 2543 2536 return ret_val;
+1
drivers/net/ethernet/intel/e1000e/phy.h
··· 164 164 #define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 165 165 #define HV_M_STATUS_SPEED_MASK 0x0300 166 166 #define HV_M_STATUS_SPEED_1000 0x0200 167 + #define HV_M_STATUS_SPEED_100 0x0100 167 168 #define HV_M_STATUS_LINK_UP 0x0040 168 169 169 170 #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4