summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/if_em_hw.c98
-rw-r--r--sys/dev/pci/if_em_hw.h8
2 files changed, 104 insertions, 2 deletions
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
index 9e9eef946c2..5f279bcbd64 100644
--- a/sys/dev/pci/if_em_hw.c
+++ b/sys/dev/pci/if_em_hw.c
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.c,v 1.86 2015/07/17 16:56:34 yuo Exp $ */
+/* $OpenBSD: if_em_hw.c,v 1.87 2015/08/05 18:31:14 sf Exp $ */
/*
* if_em_hw.c Shared functions for accessing and configuring the MAC
*/
@@ -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 779d2051dd6..03877f6745a 100644
--- a/sys/dev/pci/if_em_hw.h
+++ b/sys/dev/pci/if_em_hw.h
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.h,v 1.65 2015/06/04 18:33:41 dms Exp $ */
+/* $OpenBSD: if_em_hw.h,v 1.66 2015/08/05 18:31:14 sf Exp $ */
/* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */
/* 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