On 2015/08/04 22:40, Stefan Fritsch wrote:
> someone mentioned to me the i217-LM problems that were reported on misc 
> end of May. It is possible that the patch below helps.

This fixes my Dell poweredge T20:
em0 at pci0 dev 25 function 0 "Intel I217-LM" rev 0x04: msi, address 
f8:b1:56:...

And doesn't break my X220:
em0 at pci0 dev 25 function 0 "Intel 82579LM" rev 0x04: msi, address 
f0:de:f1:...

Readers with I217 / I218 / 82579 devices, please test, especially if network
is currently WORKING for you. We know it fixes various issues but the important
thing is that this isn't at the expense of other systems.


> For us, it fixed a problem on a laptop with i217-LM (pci id 8086:153a) 
> where the receiving of packets would stop until the battery of the laptop 
> was removed (or until linux or freebsd were booted, which also have this 
> workaround). A normal reboot or power-cycle without removing the battery 
> did not help. Interestingly, not even the Intel PXE BIOS has the 
> workaround.
> 
> The problem would happen if the LAN cable was plugged in after the card 
> had already been initialized. If the LAN cable was always plugged in when 
> the laptop was powered on, the problem would not appear.
> 
> The workaround is part of the e1000_lv_jumbo_workaround_ich8lan() function 
> in e1000_ich8lan.c in freebsd, but only the part that is used if jumbo 
> packets are *not* configured. Linux has the same fix as 
> b20a774495671f037e7160ea2ce87 and da1e2046e5f5ab268e55d30d6b74099ade0aeb6f 
> with some more info in the commit messages.
> 
> This probably has quite some potential to cause regressions with other 
> boards, so i am not sure if it should go in before 5.8 release.
> 
> Cheers,
> Stefan
> 
> 
> --- a/sys/dev/pci/if_em_hw.c
> +++ b/sys/dev/pci/if_em_hw.c
> @@ -91,6 +91,7 @@ static int32_t      em_id_led_init(struct em_hw *);
>  static int32_t       em_init_lcd_from_nvm_config_region(struct em_hw *,  
> uint32_t,
>                   uint32_t);
>  static int32_t       em_init_lcd_from_nvm(struct em_hw *);
> +static int32_t       em_phy_no_cable_workaround(struct em_hw *);
>  static void  em_init_rx_addrs(struct em_hw *);
>  static void  em_initialize_hardware_bits(struct em_hw *);
>  static boolean_t em_is_onboard_nvm_eeprom(struct em_hw *);
> @@ -7018,6 +7019,96 @@ em_read_mac_addr(struct em_hw *hw)
>  }
>  
>  
> /******************************************************************************
> + * Explicitly disables jumbo frames and resets some PHY registers back to hw-
> + * defaults. This is necessary in case the ethernet cable was inserted AFTER
> + * the firmware initialized the PHY. Otherwise it is left in a state where
> + * it is possible to transmit but not receive packets. Observed on I217-LM 
> and
> + * fixed in FreeBSD's sys/dev/e1000/e1000_ich8lan.c.
> + *
> + * hw - Struct containing variables accessed by shared code
> + 
> *****************************************************************************/
> +STATIC int32_t
> +em_phy_no_cable_workaround(struct em_hw *hw) {
> +     int32_t ret_val, dft_ret_val;
> +     uint32_t mac_reg;
> +     uint16_t data, phy_reg;
> +
> +     /* disable Rx path while enabling workaround */
> +     em_read_phy_reg(hw, I2_DFT_CTRL, &phy_reg);
> +     ret_val = em_write_phy_reg(hw, I2_DFT_CTRL, phy_reg | (1 << 14));
> +     if (ret_val)
> +             return ret_val;
> +
> +     /* Write MAC register values back to h/w defaults */
> +     mac_reg = E1000_READ_REG(hw, FFLT_DBG);
> +     mac_reg &= ~(0xF << 14);
> +     E1000_WRITE_REG(hw, FFLT_DBG, mac_reg);
> +
> +     mac_reg = E1000_READ_REG(hw, RCTL);
> +     mac_reg &= ~E1000_RCTL_SECRC;
> +     E1000_WRITE_REG(hw, RCTL, mac_reg);
> +
> +     ret_val = em_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_CTRL, &data);
> +     if (ret_val)
> +             goto out;
> +     ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_CTRL,
> +         data & ~(1 << 0));
> +     if (ret_val)
> +             goto out;
> +
> +     ret_val = em_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, &data);
> +     if (ret_val)
> +             goto out;
> +
> +     data &= ~(0xF << 8);
> +     data |= (0xB << 8);
> +     ret_val = em_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL, data);
> +     if (ret_val)
> +             goto out;
> +
> +     /* Write PHY register values back to h/w defaults */
> +     em_read_phy_reg(hw, I2_SMBUS_CTRL, &data);
> +     data &= ~(0x7F << 5);
> +     ret_val = em_write_phy_reg(hw, I2_SMBUS_CTRL, data);
> +     if (ret_val)
> +             goto out;
> +
> +     em_read_phy_reg(hw, I2_MODE_CTRL, &data);
> +     data |= (1 << 13);
> +     ret_val = em_write_phy_reg(hw, I2_MODE_CTRL, data);
> +     if (ret_val)
> +             goto out;
> +
> +     /*
> +      * 776.20 and 776.23 are not documented in
> +      * i217-ethernet-controller-datasheet.pdf...
> +      */
> +     em_read_phy_reg(hw, PHY_REG(776, 20), &data);
> +     data &= ~(0x3FF << 2);
> +     data |= (0x8 << 2);
> +     ret_val = em_write_phy_reg(hw, PHY_REG(776, 20), data);
> +     if (ret_val)
> +             goto out;
> +
> +     ret_val = em_write_phy_reg(hw, PHY_REG(776, 23), 0x7E00);
> +     if (ret_val)
> +             goto out;
> +
> +     em_read_phy_reg(hw, I2_PCIE_POWER_CTRL, &data);
> +     ret_val = em_write_phy_reg(hw, I2_PCIE_POWER_CTRL, data & ~(1 << 10));
> +     if (ret_val)
> +             goto out;
> +
> +out:
> +     /* re-enable Rx path after enabling workaround */
> +     dft_ret_val = em_write_phy_reg(hw, I2_DFT_CTRL, phy_reg & ~(1 << 14));
> +     if (ret_val)
> +             return ret_val;
> +     else
> +             return dft_ret_val;
> +}
> +
> +/******************************************************************************
>   * Initializes receive address filters.
>   *
>   * hw - Struct containing variables accessed by shared code
> @@ -7033,6 +7124,11 @@ em_init_rx_addrs(struct em_hw *hw)
>       uint32_t rar_num;
>       DEBUGFUNC("em_init_rx_addrs");
>  
> +     if (hw->mac_type == em_pch_lpt || hw->mac_type == em_pch2lan)
> +             if (em_phy_no_cable_workaround(hw))
> +                     printf(" ...failed to apply em_phy_no_cable_"
> +                         "workaround.\n");
> +
>       /* Setup the receive address. */
>       DEBUGOUT("Programming MAC Address into RAR[0]\n");
>  
> diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h
> index 779d205..29781a1 100644
> --- a/sys/dev/pci/if_em_hw.h
> +++ b/sys/dev/pci/if_em_hw.h
> @@ -3713,6 +3713,12 @@ union ich8_hws_flash_regacc {
>  #define HV_KMRN_MODE_CTRL    PHY_REG(769, 16)
>  #define HV_KMRN_MDIO_SLOW    0x0400
>  
> +/* I217 definitions */
> +#define I2_DFT_CTRL          PHY_REG(769, 20)
> +#define I2_SMBUS_CTRL                PHY_REG(769, 23)
> +#define I2_MODE_CTRL         HV_KMRN_MODE_CTRL
> +#define I2_PCIE_POWER_CTRL   IGP3_KMRN_POWER_MNG_CTRL
> +
>  /* BM/HV Specific Registers */
>  #define BM_PORT_CTRL_PAGE                 769
>  #define BM_PCIE_PAGE                      770

Reply via email to