summaryrefslogtreecommitdiffstats
path: root/sys/dev/e1000
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2011-02-11 01:00:26 +0000
committerjfv <jfv@FreeBSD.org>2011-02-11 01:00:26 +0000
commit869db2f9c7d5f723092f3122028c0c0f24272953 (patch)
tree7464df57d4e704b077e48d49af1d4ff284e20c98 /sys/dev/e1000
parent9bbe414a1e37ffb2f6f03a38a511a3e18b67ff14 (diff)
downloadFreeBSD-src-869db2f9c7d5f723092f3122028c0c0f24272953.zip
FreeBSD-src-869db2f9c7d5f723092f3122028c0c0f24272953.tar.gz
Add support for the new I350 family of 1G interfaces.
- this also includes virtualization support on these devices Correct some vlan issues we were seeing in test, jumbo frames on vlans did not work correctly, this was all due to confused logic around HW filters, the new code should now work for all uses. Important fix: when mbuf resources are depeleted, it was possible to completely empty the RX ring, and then the RX engine would stall forever. This is fixed by a flag being set whenever the refresh code fails due to an mbuf shortage, also the local timer now makes sure that all queues get an interrupt when it runs, the interrupt code will then always call rxeof, and in that routine the first thing done is now to check the refresh flag and call refresh_mbufs. This has been verified to fix this type 'hang'. Similar code will follow in the other drivers. Finally, sync up shared code for the I350 support. Thanks to everyone that has been reporting issues, and helping in the debug/test process!!
Diffstat (limited to 'sys/dev/e1000')
-rw-r--r--sys/dev/e1000/e1000_82575.c481
-rw-r--r--sys/dev/e1000/e1000_82575.h16
-rw-r--r--sys/dev/e1000/e1000_api.c30
-rw-r--r--sys/dev/e1000/e1000_api.h1
-rw-r--r--sys/dev/e1000/e1000_defines.h181
-rw-r--r--sys/dev/e1000/e1000_hw.h38
-rw-r--r--sys/dev/e1000/e1000_mac.c24
-rw-r--r--sys/dev/e1000/e1000_mac.h5
-rw-r--r--sys/dev/e1000/e1000_manage.c87
-rw-r--r--sys/dev/e1000/e1000_manage.h4
-rw-r--r--sys/dev/e1000/e1000_mbx.c8
-rw-r--r--sys/dev/e1000/e1000_nvm.c43
-rw-r--r--sys/dev/e1000/e1000_nvm.h1
-rw-r--r--sys/dev/e1000/e1000_osdep.c2
-rw-r--r--sys/dev/e1000/e1000_phy.c243
-rw-r--r--sys/dev/e1000/e1000_phy.h10
-rw-r--r--sys/dev/e1000/e1000_regs.h36
-rw-r--r--sys/dev/e1000/e1000_vf.c4
-rw-r--r--sys/dev/e1000/e1000_vf.h15
-rw-r--r--sys/dev/e1000/if_igb.c213
-rw-r--r--sys/dev/e1000/if_igb.h7
21 files changed, 1121 insertions, 328 deletions
diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c
index bc04b45..03c70e0 100644
--- a/sys/dev/e1000/e1000_82575.c
+++ b/sys/dev/e1000/e1000_82575.c
@@ -60,10 +60,14 @@ static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
u16 *data);
static s32 e1000_reset_hw_82575(struct e1000_hw *hw);
static s32 e1000_reset_hw_82580(struct e1000_hw *hw);
-static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw,
+static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw,
u32 offset, u16 *data);
-static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw,
+static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw,
u32 offset, u16 data);
+static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw,
+ bool active);
+static s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw,
+ bool active);
static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw,
bool active);
static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw);
@@ -86,6 +90,14 @@ static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw);
static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw);
static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw);
+static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset);
+static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
+ u16 offset);
+static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
static const u16 e1000_82580_rxpbs_table[] =
{ 36, 72, 144, 1, 2, 4, 8, 16,
@@ -115,6 +127,7 @@ static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
ext_mdio = !!(reg & E1000_MDIC_DEST);
break;
case e1000_82580:
+ case e1000_i350:
reg = E1000_READ_REG(hw, E1000_MDICNFG);
ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
break;
@@ -165,7 +178,7 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
e1000_reset_mdicnfg_82580(hw);
-
+
if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) {
phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575;
phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
@@ -182,11 +195,17 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
/* Verify phy id and set remaining function pointers */
switch (phy->id) {
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
case M88E1111_I_PHY_ID:
phy->type = e1000_phy_m88;
phy->ops.check_polarity = e1000_check_polarity_m88;
phy->ops.get_info = e1000_get_phy_info_m88;
- phy->ops.get_cable_length = e1000_get_cable_length_m88;
+ if (phy->id == I347AT4_E_PHY_ID ||
+ phy->id == M88E1112_E_PHY_ID)
+ phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
+ else
+ phy->ops.get_cable_length = e1000_get_cable_length_m88;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
break;
case IGP03E1000_E_PHY_ID:
@@ -200,11 +219,14 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
break;
case I82580_I_PHY_ID:
+ case I350_I_PHY_ID:
phy->type = e1000_phy_82580;
phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82577;
phy->ops.get_cable_length = e1000_get_cable_length_82577;
phy->ops.get_info = e1000_get_phy_info_82577;
+ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
break;
default:
ret_val = -E1000_ERR_PHY;
@@ -227,6 +249,16 @@ static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_nvm_params_82575");
+ size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
+ /*
+ * Added to a constant, "size" becomes the left-shift value
+ * for setting word_size.
+ */
+ size += NVM_WORD_SIZE_BASE_SHIFT;
+
+ nvm->word_size = 1 << size;
+
nvm->opcode_bits = 8;
nvm->delay_usec = 1;
switch (nvm->override) {
@@ -244,30 +276,36 @@ static s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
break;
}
- nvm->type = e1000_nvm_eeprom_spi;
-
- size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
- E1000_EECD_SIZE_EX_SHIFT);
+ nvm->type = e1000_nvm_eeprom_spi;
- /*
- * Added to a constant, "size" becomes the left-shift value
- * for setting word_size.
- */
- size += NVM_WORD_SIZE_BASE_SHIFT;
+ if (nvm->word_size == (1 << 15)) {
+ nvm->page_size = 128;
+ }
- /* EEPROM access above 16k is unsupported */
- if (size > 14)
- size = 14;
- nvm->word_size = 1 << size;
/* Function Pointers */
- nvm->ops.acquire = e1000_acquire_nvm_82575;
- nvm->ops.read = e1000_read_nvm_eerd;
- nvm->ops.release = e1000_release_nvm_82575;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.acquire = e1000_acquire_nvm_82575;
+ if (nvm->word_size < (1 << 15)) {
+ nvm->ops.read = e1000_read_nvm_eerd;
+ } else {
+ nvm->ops.read = e1000_read_nvm_spi;
+ }
+ nvm->ops.release = e1000_release_nvm_82575;
nvm->ops.valid_led_default = e1000_valid_led_default_82575;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
- nvm->ops.write = e1000_write_nvm_spi;
+ switch (hw->mac.type) {
+ case e1000_82580:
+ nvm->ops.validate = e1000_validate_nvm_checksum_82580;
+ nvm->ops.update = e1000_update_nvm_checksum_82580;
+ break;
+ case e1000_i350:
+ nvm->ops.validate = e1000_validate_nvm_checksum_i350;
+ nvm->ops.update = e1000_update_nvm_checksum_i350;
+ break;
+ default:
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
+ }
+ nvm->ops.write = e1000_write_nvm_spi;
return E1000_SUCCESS;
}
@@ -318,6 +356,12 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
if (mac->type == e1000_82580)
mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
+ if (mac->type == e1000_i350) {
+ mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
+ /* Enable EEE default settings for i350 */
+ dev_spec->eee_disable = FALSE;
+ }
+
/* Set if part includes ASF firmware */
mac->asf_firmware_present = TRUE;
/* FWSM register */
@@ -550,6 +594,7 @@ static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
break;
case e1000_82580:
+ case e1000_i350:
mdic = E1000_READ_REG(hw, E1000_MDICNFG);
mdic &= E1000_MDICNFG_PHY_MASK;
phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
@@ -730,6 +775,103 @@ out:
}
/**
+ * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
+ * @hw: pointer to the HW structure
+ * @active: TRUE to enable LPLU, FALSE to disable
+ *
+ * Sets the LPLU D0 state according to the active flag. When
+ * activating LPLU this function also disables smart speed
+ * and vice versa. LPLU will not be activated unless the
+ * device autonegotiation advertisement meets standards of
+ * either 10 or 10/100 or 10/100/1000 at all duplexes.
+ * This is a function pointer entry point only called by
+ * PHY setup routines.
+ **/
+static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = E1000_SUCCESS;
+ u16 data;
+
+ DEBUGFUNC("e1000_set_d0_lplu_state_82580");
+
+ data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+
+ if (active) {
+ data |= E1000_82580_PM_D0_LPLU;
+
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ } else {
+ data &= ~E1000_82580_PM_D0_LPLU;
+
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on) {
+ data |= E1000_82580_PM_SPD;
+ } else if (phy->smart_speed == e1000_smart_speed_off) {
+ data &= ~E1000_82580_PM_SPD;
+ }
+ }
+
+ E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
+ * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3
+ * @hw: pointer to the HW structure
+ * @active: boolean used to enable/disable lplu
+ *
+ * Success returns 0, Failure returns 1
+ *
+ * The low power link up (lplu) state is set to the power management level D3
+ * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
+ * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
+ * is used during Dx states where the power conservation is most important.
+ * During driver activity, SmartSpeed should be enabled so performance is
+ * maintained.
+ **/
+s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = E1000_SUCCESS;
+ u16 data;
+
+ DEBUGFUNC("e1000_set_d3_lplu_state_82580");
+
+ data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
+
+ if (!active) {
+ data &= ~E1000_82580_PM_D3_LPLU;
+ /*
+ * LPLU and SmartSpeed are mutually exclusive. LPLU is used
+ * during Dx states where the power conservation is most
+ * important. During driver activity we should enable
+ * SmartSpeed, so performance is maintained.
+ */
+ if (phy->smart_speed == e1000_smart_speed_on) {
+ data |= E1000_82580_PM_SPD;
+ } else if (phy->smart_speed == e1000_smart_speed_off) {
+ data &= ~E1000_82580_PM_SPD;
+ }
+ } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+ data |= E1000_82580_PM_D3_LPLU;
+ /* When LPLU is enabled, we should disable SmartSpeed */
+ data &= ~E1000_82580_PM_SPD;
+ }
+
+ E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
+ return ret_val;
+}
+
+/**
* e1000_acquire_nvm_82575 - Request for access to EEPROM
* @hw: pointer to the HW structure
*
@@ -1076,7 +1218,7 @@ void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
{
- u32 ctrl, icr;
+ u32 ctrl;
s32 ret_val;
DEBUGFUNC("e1000_reset_hw_82575");
@@ -1126,7 +1268,7 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
/* Install any alternate MAC address into RAR0 */
ret_val = e1000_check_alt_mac_addr_generic(hw);
@@ -1222,7 +1364,11 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
}
switch (hw->phy.type) {
case e1000_phy_m88:
- ret_val = e1000_copper_link_setup_m88(hw);
+ if (hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID)
+ ret_val = e1000_copper_link_setup_m88_gen2(hw);
+ else
+ ret_val = e1000_copper_link_setup_m88(hw);
break;
case e1000_phy_igp_3:
ret_val = e1000_copper_link_setup_igp(hw);
@@ -1570,7 +1716,7 @@ static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
}
/**
- * e1000_rx_fifo_flush_82575 - Clean rx fifo after RX enable
+ * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable
* @hw: pointer to the HW structure
*
* After rx enable if managability is enabled then there is likely some
@@ -1588,7 +1734,7 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
return;
- /* Disable all RX queues */
+ /* Disable all Rx queues */
for (i = 0; i < 4; i++) {
rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i));
E1000_WRITE_REG(hw, E1000_RXDCTL(i),
@@ -1626,7 +1772,7 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
E1000_WRITE_FLUSH(hw);
msec_delay(2);
- /* Enable RX queues that were previously enabled and restore our
+ /* Enable Rx queues that were previously enabled and restore our
* previous state
*/
for (i = 0; i < 4; i++)
@@ -1709,6 +1855,7 @@ void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
switch (hw->mac.type) {
case e1000_82576:
+ case e1000_i350:
dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
if (enable) {
dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
@@ -1747,6 +1894,14 @@ void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
break;
+ case e1000_i350:
+ dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
+ if (enable)
+ dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ else
+ dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
+ break;
default:
/* Currently no other hardware supports loopback */
break;
@@ -1839,7 +1994,7 @@ static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u32 mdicnfg;
- u16 nvm_data;
+ u16 nvm_data = 0;
DEBUGFUNC("e1000_reset_mdicnfg_82580");
@@ -1878,7 +2033,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
s32 ret_val = E1000_SUCCESS;
/* BH SW mailbox bit in SW_FW_SYNC */
u16 swmbsw_mask = E1000_SW_SYNCH_MB;
- u32 ctrl, icr;
+ u32 ctrl;
bool global_device_reset = hw->dev_spec._82575.global_device_reset;
DEBUGFUNC("e1000_reset_hw_82580");
@@ -1940,7 +2095,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
ret_val = e1000_reset_mdicnfg_82580(hw);
if (ret_val)
@@ -1957,7 +2112,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
}
/**
- * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual RX PBA size
+ * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size
* @data: data received by reading RXPBS register
*
* The 82580 uses a table based approach for packet buffer allocation sizes.
@@ -1975,3 +2130,263 @@ u16 e1000_rxpbs_adjust_82580(u32 data)
return ret_val;
}
+
+/**
+ * e1000_validate_nvm_checksum_with_offset - Validate EEPROM
+ * checksum
+ * @hw: pointer to the HW structure
+ * @offset: offset in words of the checksum protected region
+ *
+ * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ * and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_with_offset");
+
+ for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+
+ if (checksum != (u16) NVM_SUM) {
+ DEBUGOUT("NVM Checksum Invalid\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_update_nvm_checksum_with_offset - Update EEPROM
+ * checksum
+ * @hw: pointer to the HW structure
+ * @offset: offset in words of the checksum protected region
+ *
+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ * up to the checksum. Then calculates the EEPROM checksum and writes the
+ * value to the EEPROM.
+ **/
+s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+ s32 ret_val;
+ u16 checksum = 0;
+ u16 i, nvm_data;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_with_offset");
+
+ for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
+ ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error while updating checksum.\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+ checksum = (u16) NVM_SUM - checksum;
+ ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
+ &checksum);
+ if (ret_val)
+ DEBUGOUT("NVM Write Error while updating checksum.\n");
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Calculates the EEPROM section checksum by reading/adding each word of
+ * the EEPROM and then verifies that the sum of the EEPROM is
+ * equal to 0xBABA.
+ **/
+static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 eeprom_regions_count = 1;
+ u16 j, nvm_data;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_82580");
+
+ ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error\n");
+ goto out;
+ }
+
+ if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
+ /* if chekcsums compatibility bit is set validate checksums
+ * for all 4 ports. */
+ eeprom_regions_count = 4;
+ }
+
+ for (j = 0; j < eeprom_regions_count; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_validate_nvm_checksum_with_offset(hw,
+ nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_update_nvm_checksum_82580 - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM section checksums for all 4 ports by reading/adding
+ * each word of the EEPROM up to the checksum. Then calculates the EEPROM
+ * checksum and writes the value to the EEPROM.
+ **/
+static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 j, nvm_data;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_82580");
+
+ ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Read Error while updating checksum"
+ " compatibility bit.\n");
+ goto out;
+ }
+
+ if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) {
+ /* set compatibility bit to validate checksums appropriately */
+ nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
+ ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
+ &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("NVM Write Error while updating checksum"
+ " compatibility bit.\n");
+ goto out;
+ }
+ }
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
+ if (ret_val) {
+ goto out;
+ }
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Calculates the EEPROM section checksum by reading/adding each word of
+ * the EEPROM and then verifies that the sum of the EEPROM is
+ * equal to 0xBABA.
+ **/
+static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 j;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_validate_nvm_checksum_i350");
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_validate_nvm_checksum_with_offset(hw,
+ nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_update_nvm_checksum_i350 - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM section checksums for all 4 ports by reading/adding
+ * each word of the EEPROM up to the checksum. Then calculates the EEPROM
+ * checksum and writes the value to the EEPROM.
+ **/
+static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 j;
+ u16 nvm_offset;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_i350");
+
+ for (j = 0; j < 4; j++) {
+ nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+ ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
+ if (ret_val != E1000_SUCCESS)
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_set_eee_i350 - Enable/disable EEE support
+ * @hw: pointer to the HW structure
+ *
+ * Enable/disable EEE based on setting in dev_spec structure.
+ *
+ **/
+s32 e1000_set_eee_i350(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u32 ipcnfg, eeer, ctrl_ext;
+
+ DEBUGFUNC("e1000_set_eee_i350");
+
+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ if ((hw->mac.type != e1000_i350) ||
+ (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK))
+ goto out;
+ ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG);
+ eeer = E1000_READ_REG(hw, E1000_EEER);
+
+ /* enable or disable per user setting */
+ if (!(hw->dev_spec._82575.eee_disable)) {
+ ipcnfg |= (E1000_IPCNFG_EEE_1G_AN |
+ E1000_IPCNFG_EEE_100M_AN);
+ eeer |= (E1000_EEER_TX_LPI_EN |
+ E1000_EEER_RX_LPI_EN |
+ E1000_EEER_LPI_FC);
+
+ } else {
+ ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN |
+ E1000_IPCNFG_EEE_100M_AN);
+ eeer &= ~(E1000_EEER_TX_LPI_EN |
+ E1000_EEER_RX_LPI_EN |
+ E1000_EEER_LPI_FC);
+ }
+ E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg);
+ E1000_WRITE_REG(hw, E1000_EEER, eeer);
+ E1000_READ_REG(hw, E1000_IPCNFG);
+ E1000_READ_REG(hw, E1000_EEER);
+out:
+
+ return ret_val;
+}
diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h
index eb05262..e895d58 100644
--- a/sys/dev/e1000/e1000_82575.h
+++ b/sys/dev/e1000/e1000_82575.h
@@ -52,6 +52,7 @@
#define E1000_RAR_ENTRIES_82575 16
#define E1000_RAR_ENTRIES_82576 24
#define E1000_RAR_ENTRIES_82580 24
+#define E1000_RAR_ENTRIES_I350 32
#define E1000_SW_SYNCH_MB 0x00000100
#define E1000_STAT_DEV_RST_SET 0x00100000
#define E1000_CTRL_DEV_RST 0x20000000
@@ -200,8 +201,8 @@ union e1000_adv_rx_desc {
__le32 data;
struct {
__le16 pkt_info; /*RSS type, Pkt type*/
- __le16 hdr_info; /* Split Header,
- * header buffer len*/
+ /* Split Header, header buffer len */
+ __le16 hdr_info;
} hs_rss;
} lo_dword;
union {
@@ -425,6 +426,14 @@ struct e1000_adv_tx_context_desc {
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
+#define E1000_VMOLR_VPE 0x00800000 /* VLAN promiscuous enable */
+#define E1000_VMOLR_UPE 0x20000000 /* Unicast promisuous enable */
+#define E1000_DVMOLR_HIDVLAN 0x20000000 /* Vlan hiding enable */
+#define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
+#define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */
+
+#define E1000_PBRWAC_WALPB 0x00000007 /* Wrap around event on LAN Rx PB */
+#define E1000_PBRWAC_PBE 0x00000008 /* Rx packet buffer empty */
#define E1000_VLVF_ARRAY_SIZE 32
#define E1000_VLVF_VLANID_MASK 0x00000FFF
@@ -455,7 +464,7 @@ struct e1000_adv_tx_context_desc {
#define ALL_QUEUES 0xFFFF
-/* RX packet buffer size defines */
+/* Rx packet buffer size defines */
#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable);
void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf);
@@ -472,4 +481,5 @@ void e1000_vfta_set_vf(struct e1000_hw *, u16, bool);
void e1000_rlpml_set_vf(struct e1000_hw *, u16);
s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
u16 e1000_rxpbs_adjust_82580(u32 data);
+s32 e1000_set_eee_i350(struct e1000_hw *);
#endif /* _E1000_82575_H_ */
diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c
index b3a7ef9..b470cdd 100644
--- a/sys/dev/e1000/e1000_api.c
+++ b/sys/dev/e1000/e1000_api.c
@@ -314,11 +314,22 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82580_QUAD_FIBER:
case E1000_DEV_ID_DH89XXCC_SGMII:
case E1000_DEV_ID_DH89XXCC_SERDES:
+ case E1000_DEV_ID_DH89XXCC_BACKPLANE:
+ case E1000_DEV_ID_DH89XXCC_SFP:
mac->type = e1000_82580;
break;
+ case E1000_DEV_ID_I350_COPPER:
+ case E1000_DEV_ID_I350_FIBER:
+ case E1000_DEV_ID_I350_SERDES:
+ case E1000_DEV_ID_I350_SGMII:
+ mac->type = e1000_i350;
+ break;
case E1000_DEV_ID_82576_VF:
mac->type = e1000_vfadapt;
break;
+ case E1000_DEV_ID_I350_VF:
+ mac->type = e1000_vfadapt_i350;
+ break;
default:
/* Should never have loaded on this device */
ret_val = -E1000_ERR_MAC_INIT;
@@ -412,11 +423,15 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_82575:
case e1000_82576:
case e1000_82580:
+ case e1000_i350:
e1000_init_function_pointers_82575(hw);
break;
case e1000_vfadapt:
e1000_init_function_pointers_vf(hw);
break;
+ case e1000_vfadapt_i350:
+ e1000_init_function_pointers_vf(hw);
+ break;
default:
DEBUGOUT("Hardware not supported\n");
ret_val = -E1000_ERR_CONFIG;
@@ -1173,21 +1188,6 @@ s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size)
}
/**
- * e1000_read_pba_num - Read device part number
- * @hw: pointer to the HW structure
- * @pba_num: pointer to device part number
- *
- * Reads the product board assembly (PBA) number from the EEPROM and stores
- * the value in pba_num.
- * Currently no func pointer exists and all implementations are handled in the
- * generic version of this function.
- **/
-s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
-{
- return e1000_read_pba_num_generic(hw, pba_num);
-}
-
-/**
* e1000_validate_nvm_checksum - Verifies NVM (EEPROM) checksum
* @hw: pointer to the HW structure
*
diff --git a/sys/dev/e1000/e1000_api.h b/sys/dev/e1000/e1000_api.h
index 36ba712..2621a6e 100644
--- a/sys/dev/e1000/e1000_api.h
+++ b/sys/dev/e1000/e1000_api.h
@@ -96,7 +96,6 @@ s32 e1000_phy_commit(struct e1000_hw *hw);
void e1000_power_up_phy(struct e1000_hw *hw);
void e1000_power_down_phy(struct e1000_hw *hw);
s32 e1000_read_mac_addr(struct e1000_hw *hw);
-s32 e1000_read_pba_num(struct e1000_hw *hw, u32 *part_num);
s32 e1000_read_pba_string(struct e1000_hw *hw, u8 *pba_num,
u32 pba_num_size);
s32 e1000_read_pba_length(struct e1000_hw *hw, u32 *pba_num_size);
diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h
index 5d09ad9..a1eec00 100644
--- a/sys/dev/e1000/e1000_defines.h
+++ b/sys/dev/e1000/e1000_defines.h
@@ -46,6 +46,7 @@
#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
#define E1000_WUC_LSCWE 0x00000010 /* Link Status wake up enable */
+#define E1000_WUC_PPROXYE 0x00000010 /* Protocol Proxy Enable */
#define E1000_WUC_LSCWO 0x00000020 /* Link Status wake up override */
#define E1000_WUC_SPM 0x80000000 /* Enable SPM */
#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */
@@ -77,6 +78,7 @@
#define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */
#define E1000_WUFC_FLX6 0x00400000 /* Flexible Filter 6 Enable */
#define E1000_WUFC_FLX7 0x00800000 /* Flexible Filter 7 Enable */
+#define E1000_WUFC_FW_RST 0x80000000 /* Wake on FW Reset Enable */
#define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/
#define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */
#define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /*Mask for 4 flexible filters*/
@@ -324,6 +326,8 @@
#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */
#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */
#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */
+#define E1000_MANC_MPROXYE 0x40000000 /* Mngment Proxy Enable */
+#define E1000_MANC_EN_BMC2OS 0x10000000 /* OS2BMC is enabled or not */
#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
@@ -346,9 +350,9 @@
#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
-#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min thresh size */
-#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min thresh size */
-#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min thresh size */
+#define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
+#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* Rx desc min thresh size */
+#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* Rx desc min thresh size */
#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */
#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */
@@ -357,14 +361,14 @@
#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */
#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
-#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
-#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
-#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
-#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
+#define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024 0x00010000 /* Rx buffer size 1024 */
+#define E1000_RCTL_SZ_512 0x00020000 /* Rx buffer size 512 */
+#define E1000_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */
/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
+#define E1000_RCTL_SZ_16384 0x00010000 /* Rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192 0x00020000 /* Rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096 0x00030000 /* Rx buffer size 4096 */
#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
@@ -409,6 +413,7 @@
#define E1000_SWFW_CSR_SM 0x08
#define E1000_SWFW_PHY2_SM 0x20
#define E1000_SWFW_PHY3_SM 0x40
+#define E1000_SWFW_SW_MNG_SM 0x400
/* FACTPS Definitions */
#define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */
@@ -645,7 +650,7 @@
/* Transmit Control */
#define E1000_TCTL_RST 0x00000001 /* software reset */
-#define E1000_TCTL_EN 0x00000002 /* enable tx */
+#define E1000_TCTL_EN 0x00000002 /* enable Tx */
#define E1000_TCTL_BCE 0x00000004 /* busy check enable */
#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
@@ -780,10 +785,10 @@
#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
-#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
-#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
-#define E1000_ICR_RXO 0x00000040 /* rx overrun */
-#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
+#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */
+#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */
+#define E1000_ICR_RXO 0x00000040 /* Rx overrun */
+#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */
#define E1000_ICR_VMMB 0x00000100 /* VM MB event */
#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */
#define E1000_ICR_RXCFG 0x00000400 /* Rx /c/ ordered set */
@@ -819,12 +824,14 @@
#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
#define E1000_ICR_FER 0x00400000 /* Fatal Error */
+#define E1000_ICR_THS 0x00800000 /* ICR.THS: Thermal Sensor Event*/
+#define E1000_ICR_MDDET 0x10000000 /* Malicious Driver Detect */
/* PBA ECC Register */
#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */
#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */
-#define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */
-#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
-#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */
+#define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */
+#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
+#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */
/* Extended Interrupt Cause Read */
#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */
@@ -874,10 +881,10 @@
#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */
-#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
-#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
-#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */
-#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
+#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
+#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
+#define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */
+#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */
#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */
#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
@@ -913,6 +920,8 @@
#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */
#define E1000_IMS_FER E1000_ICR_FER /* Fatal Error */
+#define E1000_IMS_THS E1000_ICR_THS /* ICR.TS: Thermal Sensor Event*/
+#define E1000_IMS_MDDET E1000_ICR_MDDET /* Malicious Driver Detect */
/* Extended Interrupt Mask Set */
#define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */
#define E1000_EIMS_RX_QUEUE1 E1000_EICR_RX_QUEUE1 /* Rx Queue 1 Interrupt */
@@ -929,10 +938,10 @@
#define E1000_ICS_TXDW E1000_ICR_TXDW /* Tx desc written back */
#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
-#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
-#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
-#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */
-#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
+#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
+#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
+#define E1000_ICS_RXO E1000_ICR_RXO /* Rx overrun */
+#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */
#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* Rx /c/ ordered set */
#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
@@ -976,14 +985,14 @@
#define E1000_EITR_ITR_INT_MASK 0x0000FFFF
/* E1000_EITR_CNT_IGNR is only for 82576 and newer */
-#define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
+#define E1000_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
/* Transmit Descriptor Control */
-#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
-#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
-#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
-#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
-#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
+#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
+#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
/* Enable the counting of descriptors still to be processed. */
@@ -1010,8 +1019,10 @@
#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
#define E1000_RAL_MAC_ADDR_LEN 4
#define E1000_RAH_MAC_ADDR_LEN 2
-#define E1000_RAH_POOL_MASK 0x03FC0000
-#define E1000_RAH_POOL_1 0x00040000
+#define E1000_RAH_QUEUE_MASK_82575 0x000C0000
+#define E1000_RAH_POOL_MASK 0x03FC0000
+#define E1000_RAH_POOL_SHIFT 18
+#define E1000_RAH_POOL_1 0x00040000
/* Error Codes */
#define E1000_SUCCESS 0
@@ -1073,17 +1084,17 @@
#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */
-#define E1000_TSYNCTXCTL_VALID 0x00000001 /* tx timestamp valid */
-#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable tx timestampping */
+#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */
+#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
-#define E1000_TSYNCRXCTL_VALID 0x00000001 /* rx timestamp valid */
-#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* rx type mask */
+#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */
+#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00
#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02
#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
#define E1000_TSYNCRXCTL_TYPE_ALL 0x08
#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
-#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable rx timestampping */
+#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
#define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF
#define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00
@@ -1129,6 +1140,23 @@
#define E1000_MDICNFG_PHY_MASK 0x03E00000
#define E1000_MDICNFG_PHY_SHIFT 21
+#define E1000_THSTAT_LOW_EVENT 0x20000000 /* Low thermal threshold */
+#define E1000_THSTAT_MID_EVENT 0x00200000 /* Mid thermal threshold */
+#define E1000_THSTAT_HIGH_EVENT 0x00002000 /* High thermal threshold */
+#define E1000_THSTAT_PWR_DOWN 0x00000001 /* Power Down Event */
+#define E1000_THSTAT_LINK_THROTTLE 0x00000002 /* Link Speed Throttle Event */
+
+/* Powerville EEE defines */
+#define E1000_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Enable 1G AN */
+#define E1000_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Enable 100M AN */
+#define E1000_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */
+#define E1000_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */
+#define E1000_EEER_LPI_FC 0x00040000 /* EEER Enable on Flow Control*/
+/* EEE status */
+#define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability negotiated */
+#define E1000_EEER_RX_LPI_STATUS 0x40000000 /* Rx in LPI state */
+#define E1000_EEER_TX_LPI_STATUS 0x80000000 /* Tx in LPI state */
+
/* PCI Express Control */
#define E1000_GCR_RXD_NO_SNOOP 0x00000001
#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
@@ -1316,6 +1344,8 @@
#define NVM_FLASH_VERSION 0x0032
#define NVM_ALT_MAC_ADDR_PTR 0x0037
#define NVM_CHECKSUM_REG 0x003F
+#define NVM_COMPATIBILITY_REG_3 0x0003
+#define NVM_COMPATIBILITY_BIT_MASK 0x8000
#define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */
#define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */
@@ -1447,6 +1477,8 @@
#define IGP01E1000_I_PHY_ID 0x02A80380
#define M88E1011_I_REV_4 0x04
#define M88E1111_I_PHY_ID 0x01410CC0
+#define M88E1112_E_PHY_ID 0x01410C90
+#define I347AT4_E_PHY_ID 0x01410DC0
#define GG82563_E_PHY_ID 0x01410CA0
#define IGP03E1000_E_PHY_ID 0x02A80390
#define IFE_E_PHY_ID 0x02A80330
@@ -1458,6 +1490,7 @@
#define I82578_E_PHY_ID 0x004DD040
#define I82579_E_PHY_ID 0x01540090
#define I82580_I_PHY_ID 0x015403A0
+#define I350_I_PHY_ID 0x015403B0
#define IGP04E1000_E_PHY_ID 0x02A80391
#define M88_VENDOR 0x0141
@@ -1550,10 +1583,46 @@
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300
-#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
+
+/* M88E1111 Specific Registers */
+#define M88E1111_PHY_PAGE_SELECT1 0x16 /* for registers 0-28 */
+#define M88E1111_PHY_PAGE_SELECT2 0x1D /* for registers 30-31 */
+
+/* M88E1111 page select register mask */
+#define M88E1111_PHY_PAGE_SELECT_MASK1 0xFF
+#define M88E1111_PHY_PAGE_SELECT_MASK2 0x3F
+
+/* Intel I347AT4 Registers */
+
+#define I347AT4_PCDL 0x10 /* PHY Cable Diagnostics Length */
+#define I347AT4_PCDC 0x15 /* PHY Cable Diagnostics Control */
+#define I347AT4_PAGE_SELECT 0x16
+
+/* I347AT4 Extended PHY Specific Control Register */
+/*
+ * Number of times we will attempt to autonegotiate before downshifting if we
+ * are the master
+ */
+#define I347AT4_PSCR_DOWNSHIFT_ENABLE 0x0800
+#define I347AT4_PSCR_DOWNSHIFT_MASK 0x7000
+#define I347AT4_PSCR_DOWNSHIFT_1X 0x0000
+#define I347AT4_PSCR_DOWNSHIFT_2X 0x1000
+#define I347AT4_PSCR_DOWNSHIFT_3X 0x2000
+#define I347AT4_PSCR_DOWNSHIFT_4X 0x3000
+#define I347AT4_PSCR_DOWNSHIFT_5X 0x4000
+#define I347AT4_PSCR_DOWNSHIFT_6X 0x5000
+#define I347AT4_PSCR_DOWNSHIFT_7X 0x6000
+#define I347AT4_PSCR_DOWNSHIFT_8X 0x7000
+
+/* I347AT4 PHY Cable Diagnostics Control */
+#define I347AT4_PCDC_CABLE_LENGTH_UNIT 0x0400 /* 0=cm 1=meters */
+
+/* M88E1112 only registers */
+#define M88E1112_VCT_DSP_DISTANCE 0x001A
/* M88EC018 Rev 2 specific DownShift settings */
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
@@ -1688,6 +1757,13 @@
#define E1000_LSECRXCTRL_RP 0x00000080
#define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33
+/* Tx Rate-Scheduler Config fields */
+#define E1000_RTTBCNRC_RS_ENA 0x80000000
+#define E1000_RTTBCNRC_RF_DEC_MASK 0x00003FFF
+#define E1000_RTTBCNRC_RF_INT_SHIFT 14
+#define E1000_RTTBCNRC_RF_INT_MASK \
+ (E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT)
+
/* DMA Coalescing register fields */
#define E1000_DMACR_DMACWT_MASK 0x00003FFF /* DMA Coalescing
@@ -1719,5 +1795,26 @@
#define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision based
on DMA coal */
+/* Proxy Filer Control */
+#define E1000_PROXYFC_D0 0x00000001 /* Enable offload in D0 */
+#define E1000_PROXYFC_EX 0x00000004 /* Directed exact proxy */
+#define E1000_PROXYFC_MC 0x00000008 /* Directed Multicast
+ * Proxy */
+#define E1000_PROXYFC_BC 0x00000010 /* Broadcast Proxy Enable */
+#define E1000_PROXYFC_ARP_DIRECTED 0x00000020 /* Directed ARP Proxy
+ * Enable */
+#define E1000_PROXYFC_IPV4 0x00000040 /* Directed IPv4 Enable */
+#define E1000_PROXYFC_IPV6 0x00000080 /* Directed IPv6 Enable */
+#define E1000_PROXYFC_NS 0x00000200 /* IPv4 Neighborhood
+ * Solicitation */
+#define E1000_PROXYFC_ARP 0x00000800 /* ARP Request Proxy
+ * Enable */
+/* Proxy Status */
+#define E1000_PROXYS_CLEAR 0xFFFFFFFF /* Clear */
+
+/* Firmware Status */
+#define E1000_FWSTS_FWRI 0x80000000 /* Firmware Reset
+ * Indication */
+
#endif /* _E1000_DEFINES_H_ */
diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h
index e80e870..686a5d8 100644
--- a/sys/dev/e1000/e1000_hw.h
+++ b/sys/dev/e1000/e1000_hw.h
@@ -140,6 +140,7 @@ struct e1000_hw;
#define E1000_DEV_ID_82576_NS_SERDES 0x1518
#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
#define E1000_DEV_ID_82576_VF 0x10CA
+#define E1000_DEV_ID_I350_VF 0x1520
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
@@ -150,8 +151,14 @@ struct e1000_hw;
#define E1000_DEV_ID_82580_SGMII 0x1511
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
-#define E1000_DEV_ID_DH89XXCC_SGMII 0x0436
-#define E1000_DEV_ID_DH89XXCC_SERDES 0x0438
+#define E1000_DEV_ID_I350_COPPER 0x1521
+#define E1000_DEV_ID_I350_FIBER 0x1522
+#define E1000_DEV_ID_I350_SERDES 0x1523
+#define E1000_DEV_ID_I350_SGMII 0x1524
+#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
+#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
+#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
+#define E1000_DEV_ID_DH89XXCC_SFP 0x0440
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
@@ -196,7 +203,9 @@ enum e1000_mac_type {
e1000_82575,
e1000_82576,
e1000_82580,
+ e1000_i350,
e1000_vfadapt,
+ e1000_vfadapt_i350,
e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
};
@@ -701,8 +710,8 @@ struct e1000_nvm_operations {
struct e1000_mac_info {
struct e1000_mac_operations ops;
- u8 addr[6];
- u8 perm_addr[6];
+ u8 addr[ETH_ADDR_LEN];
+ u8 perm_addr[ETH_ADDR_LEN];
enum e1000_mac_type type;
@@ -872,7 +881,7 @@ struct e1000_shadow_ram {
bool modified;
};
-#define E1000_SHADOW_RAM_WORDS 2048
+#define E1000_SHADOW_RAM_WORDS 2048
struct e1000_dev_spec_ich8lan {
bool kmrn_lock_loss_workaround_enabled;
@@ -886,11 +895,12 @@ struct e1000_dev_spec_ich8lan {
struct e1000_dev_spec_82575 {
bool sgmii_active;
bool global_device_reset;
+ bool eee_disable;
};
struct e1000_dev_spec_vf {
- u32 vf_number;
- u32 v2p_mailbox;
+ u32 vf_number;
+ u32 v2p_mailbox;
};
struct e1000_hw {
@@ -909,14 +919,14 @@ struct e1000_hw {
struct e1000_host_mng_dhcp_cookie mng_cookie;
union {
- struct e1000_dev_spec_82541 _82541;
- struct e1000_dev_spec_82542 _82542;
- struct e1000_dev_spec_82543 _82543;
- struct e1000_dev_spec_82571 _82571;
+ struct e1000_dev_spec_82541 _82541;
+ struct e1000_dev_spec_82542 _82542;
+ struct e1000_dev_spec_82543 _82543;
+ struct e1000_dev_spec_82571 _82571;
struct e1000_dev_spec_80003es2lan _80003es2lan;
- struct e1000_dev_spec_ich8lan ich8lan;
- struct e1000_dev_spec_82575 _82575;
- struct e1000_dev_spec_vf vf;
+ struct e1000_dev_spec_ich8lan ich8lan;
+ struct e1000_dev_spec_82575 _82575;
+ struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c
index 1216671..1d6aa9b 100644
--- a/sys/dev/e1000/e1000_mac.c
+++ b/sys/dev/e1000/e1000_mac.c
@@ -34,6 +34,9 @@
#include "e1000_api.h"
+static s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
+static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw);
+static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
@@ -244,7 +247,7 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
bus->speed = e1000_bus_speed_unknown;
break;
}
-
+
bus->width = (enum e1000_bus_width)((pcie_link_status &
PCIE_LINK_WIDTH_MASK) >>
PCIE_LINK_WIDTH_SHIFT);
@@ -399,10 +402,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
if (ret_val)
goto out;
- /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
- if (!((nvm_data & NVM_COMPAT_LOM) ||
- (hw->device_id == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
- (hw->device_id == E1000_DEV_ID_82571EB_SERDES_QUAD)))
+ if (!(nvm_data & NVM_COMPAT_LOM))
goto out;
ret_val = hw->nvm.ops.read(hw, NVM_ALT_MAC_ADDR_PTR, 1,
@@ -801,7 +801,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
mac->autoneg_failed = 1;
goto out;
}
- DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+ DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -824,7 +824,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
* and disable forced link in the Device Control register
* in an attempt to auto-negotiate with our link partner.
*/
- DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
@@ -869,7 +869,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
mac->autoneg_failed = 1;
goto out;
}
- DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+ DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
/* Disable auto-negotiation in the TXCW register */
E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -892,7 +892,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
* and disable forced link in the Device Control register
* in an attempt to auto-negotiate with our link partner.
*/
- DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+ DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
@@ -1097,7 +1097,7 @@ void e1000_config_collision_dist_generic(struct e1000_hw *hw)
* Polls for link up by reading the status register, if link fails to come
* up with auto-negotiation, then the link is forced if a signal is detected.
**/
-s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
+static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
u32 i, status;
@@ -1149,7 +1149,7 @@ out:
* Write the flow control settings to the Transmit Config Word Register (TXCW)
* base on the flow control settings in e1000_mac_info.
**/
-s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
+static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
u32 txcw;
@@ -1264,7 +1264,7 @@ s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw)
* Read the EEPROM for the default values for flow control and store the
* values.
**/
-s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
+static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u16 nvm_data;
diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h
index 348d660..9af30b5 100644
--- a/sys/dev/e1000/e1000_mac.h
+++ b/sys/dev/e1000/e1000_mac.h
@@ -52,8 +52,6 @@ s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw);
s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw);
s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw);
s32 e1000_cleanup_led_generic(struct e1000_hw *hw);
-s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw);
-s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw);
s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw);
s32 e1000_disable_pcie_master_generic(struct e1000_hw *hw);
s32 e1000_force_mac_fc_generic(struct e1000_hw *hw);
@@ -71,8 +69,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw);
s32 e1000_led_on_generic(struct e1000_hw *hw);
s32 e1000_led_off_generic(struct e1000_hw *hw);
void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count);
-s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
+ u8 *mc_addr_list, u32 mc_addr_count);
s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw);
s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw);
s32 e1000_setup_led_generic(struct e1000_hw *hw);
diff --git a/sys/dev/e1000/e1000_manage.c b/sys/dev/e1000/e1000_manage.c
index 0b295f8..7782739 100644
--- a/sys/dev/e1000/e1000_manage.c
+++ b/sys/dev/e1000/e1000_manage.c
@@ -34,8 +34,6 @@
#include "e1000_api.h"
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
-
/**
* e1000_calculate_checksum - Calculate checksum for buffer
* @buffer: pointer to EEPROM
@@ -44,10 +42,10 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
* Calculates the checksum for some buffer on a specified length. The
* checksum calculated is returned.
**/
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
+u8 e1000_calculate_checksum(u8 *buffer, u32 length)
{
u32 i;
- u8 sum = 0;
+ u8 sum = 0;
DEBUGFUNC("e1000_calculate_checksum");
@@ -404,3 +402,84 @@ out:
return ret_val;
}
+/**
+ * e1000_host_interface_command - Writes buffer to host interface
+ * @hw: pointer to the HW structure
+ * @buffer: contains a command to write
+ * @length: the byte length of the buffer, must be multiple of 4 bytes
+ *
+ * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS
+ * else returns E1000_ERR_HOST_INTERFACE_COMMAND.
+ **/
+s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
+{
+ u32 hicr, i;
+ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_host_interface_command");
+
+ if (!(hw->mac.arc_subsystem_valid)) {
+ DEBUGOUT("Hardware doesn't support host interface command.\n");
+ goto out;
+ }
+
+ if (!hw->mac.asf_firmware_present) {
+ DEBUGOUT("Firmware is not present.\n");
+ goto out;
+ }
+
+ if (length == 0 || length & 0x3 ||
+ length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
+ DEBUGOUT("Buffer length failure.\n");
+ ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Check that the host interface is enabled. */
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ if ((hicr & E1000_HICR_EN) == 0) {
+ DEBUGOUT("E1000_HOST_EN bit disabled.\n");
+ ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ /* Calculate length in DWORDs */
+ length >>= 2;
+
+ /*
+ * The device driver writes the relevant command block
+ * into the ram area.
+ */
+ for (i = 0; i < length; i++)
+ E1000_WRITE_REG_ARRAY_DWORD(hw,
+ E1000_HOST_IF,
+ i,
+ *((u32 *)buffer + i));
+
+ /* Setting this bit tells the ARC that a new command is pending. */
+ E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
+
+ for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
+ hicr = E1000_READ_REG(hw, E1000_HICR);
+ if (!(hicr & E1000_HICR_C))
+ break;
+ msec_delay(1);
+ }
+
+ /* Check command successful completion. */
+ if (i == E1000_HI_COMMAND_TIMEOUT ||
+ (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
+ DEBUGOUT("Command has failed with no status valid.\n");
+ ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
+ goto out;
+ }
+
+ for (i = 0; i < length; i++)
+ *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
+ E1000_HOST_IF,
+ i);
+
+out:
+ return ret_val;
+}
+
diff --git a/sys/dev/e1000/e1000_manage.h b/sys/dev/e1000/e1000_manage.h
index 146caeb..6a0c2a0 100644
--- a/sys/dev/e1000/e1000_manage.h
+++ b/sys/dev/e1000/e1000_manage.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2010, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,8 @@ s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw,
u8 *buffer, u16 length);
bool e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+u8 e1000_calculate_checksum(u8 *buffer, u32 length);
+s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length);
enum e1000_mng_mode {
e1000_mng_mode_none = 0,
diff --git a/sys/dev/e1000/e1000_mbx.c b/sys/dev/e1000/e1000_mbx.c
index 65dab38..14af886 100644
--- a/sys/dev/e1000/e1000_mbx.c
+++ b/sys/dev/e1000/e1000_mbx.c
@@ -736,7 +736,9 @@ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
- if (hw->mac.type == e1000_82576) {
+ switch (hw->mac.type) {
+ case e1000_82576:
+ case e1000_i350:
mbx->timeout = 0;
mbx->usec_delay = 0;
@@ -755,8 +757,8 @@ s32 e1000_init_mbx_params_pf(struct e1000_hw *hw)
mbx->stats.reqs = 0;
mbx->stats.acks = 0;
mbx->stats.rsts = 0;
+ default:
+ return E1000_SUCCESS;
}
-
- return E1000_SUCCESS;
}
diff --git a/sys/dev/e1000/e1000_nvm.c b/sys/dev/e1000/e1000_nvm.c
index 05c7931..e10ac8c 100644
--- a/sys/dev/e1000/e1000_nvm.c
+++ b/sys/dev/e1000/e1000_nvm.c
@@ -383,7 +383,6 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
struct e1000_nvm_info *nvm = &hw->nvm;
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
s32 ret_val = E1000_SUCCESS;
- u16 timeout = 0;
u8 spi_stat_reg;
DEBUGFUNC("e1000_ready_nvm_eeprom");
@@ -397,11 +396,12 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_EECD, eecd);
} else
if (nvm->type == e1000_nvm_eeprom_spi) {
+ u16 timeout = NVM_MAX_RETRY_SPI;
+
/* Clear SK and CS */
eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
E1000_WRITE_REG(hw, E1000_EECD, eecd);
usec_delay(1);
- timeout = NVM_MAX_RETRY_SPI;
/*
* Read "Status Register" repeatedly until the LSB is cleared.
@@ -783,7 +783,7 @@ out:
* Reads the product board assembly (PBA) number from the EEPROM and stores
* the value in pba_num.
**/
-s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
u32 pba_num_size)
{
s32 ret_val;
@@ -953,43 +953,6 @@ out:
}
/**
- * e1000_read_pba_num_generic - Read device part number
- * @hw: pointer to the HW structure
- * @pba_num: pointer to device part number
- *
- * Reads the product board assembly (PBA) number from the EEPROM and stores
- * the value in pba_num.
- **/
-s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num)
-{
- s32 ret_val;
- u16 nvm_data;
-
- DEBUGFUNC("e1000_read_pba_num_generic");
-
- ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
- if (ret_val) {
- DEBUGOUT("NVM Read Error\n");
- goto out;
- } else if (nvm_data == NVM_PBA_PTR_GUARD) {
- DEBUGOUT("NVM Not Supported\n");
- ret_val = E1000_NOT_IMPLEMENTED;
- goto out;
- }
- *pba_num = (u32)(nvm_data << 16);
-
- ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
- if (ret_val) {
- DEBUGOUT("NVM Read Error\n");
- goto out;
- }
- *pba_num |= nvm_data;
-
-out:
- return ret_val;
-}
-
-/**
* e1000_read_mac_addr_generic - Read device MAC address
* @hw: pointer to the HW structure
*
diff --git a/sys/dev/e1000/e1000_nvm.h b/sys/dev/e1000/e1000_nvm.h
index 36ee444..61ea0b1 100644
--- a/sys/dev/e1000/e1000_nvm.h
+++ b/sys/dev/e1000/e1000_nvm.h
@@ -44,7 +44,6 @@ s32 e1000_acquire_nvm_generic(struct e1000_hw *hw);
s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg);
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw);
-s32 e1000_read_pba_num_generic(struct e1000_hw *hw, u32 *pba_num);
s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
u32 pba_num_size);
s32 e1000_read_pba_length_generic(struct e1000_hw *hw, u32 *pba_num_size);
diff --git a/sys/dev/e1000/e1000_osdep.c b/sys/dev/e1000/e1000_osdep.c
index feaf47a..d5eccc4 100644
--- a/sys/dev/e1000/e1000_osdep.c
+++ b/sys/dev/e1000/e1000_osdep.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2009, Intel Corporation
+ Copyright (c) 2001-2010, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c
index fb66623..f01fde4 100644
--- a/sys/dev/e1000/e1000_phy.c
+++ b/sys/dev/e1000/e1000_phy.c
@@ -42,21 +42,21 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
u16 *data, bool read);
/* Cable length tables */
-static const u16 e1000_m88_cable_length_table[] =
- { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
+static const u16 e1000_m88_cable_length_table[] = {
+ 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
(sizeof(e1000_m88_cable_length_table) / \
sizeof(e1000_m88_cable_length_table[0]))
-static const u16 e1000_igp_2_cable_length_table[] =
- { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
- 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
- 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
- 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
- 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
- 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
- 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
- 104, 109, 114, 118, 121, 124};
+static const u16 e1000_igp_2_cable_length_table[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
+ 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
+ 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
+ 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
+ 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
+ 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
+ 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
+ 124};
#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
(sizeof(e1000_igp_2_cable_length_table) / \
sizeof(e1000_igp_2_cable_length_table[0]))
@@ -281,9 +281,9 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
goto out;
}
*data = (u16) mdic;
-
+
/*
- * Allow some time after each MDIC transaction to avoid
+ * Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
@@ -353,7 +353,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
}
/*
- * Allow some time after each MDIC transaction to avoid
+ * Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction.
*/
if (hw->mac.type == e1000_pch2lan)
@@ -841,7 +841,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
}
}
- /* Enable CRS on TX. This must be set for half-duplex operation. */
+ /* Enable CRS on Tx. This must be set for half-duplex operation. */
ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
if (ret_val)
goto out;
@@ -882,10 +882,9 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
if (ret_val)
goto out;
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
/* For BM PHY this bit is downshift enable */
- if (phy->type == e1000_phy_bm)
- phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ if (phy->type != e1000_phy_bm)
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
/*
* Options:
@@ -1003,6 +1002,91 @@ out:
}
/**
+ * e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
+ * @hw: pointer to the HW structure
+ *
+ * Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
+ * Also enables and sets the downshift parameters.
+ **/
+s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_copper_link_setup_m88_gen2");
+
+ if (phy->reset_disable) {
+ ret_val = E1000_SUCCESS;
+ goto out;
+ }
+
+ /* Enable CRS on Tx. This must be set for half-duplex operation. */
+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ goto out;
+
+ /*
+ * Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+ */
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+ switch (phy->mdix) {
+ case 1:
+ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+ break;
+ case 2:
+ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+ break;
+ case 3:
+ /* M88E1112 does not support this mode) */
+ if (phy->id != M88E1112_E_PHY_ID) {
+ phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+ break;
+ }
+ case 0:
+ default:
+ phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+ break;
+ }
+
+ /*
+ * Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+ * 1 - Enabled
+ */
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+ if (phy->disable_polarity_correction == 1)
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+
+ /* Enable downshift and setting it to X6 */
+ phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
+ phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
+ phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
+
+ ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ goto out;
+
+ /* Commit the changes. */
+ ret_val = phy->ops.commit(hw);
+ if (ret_val) {
+ DEBUGOUT("Error committing the PHY changes\n");
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
* e1000_copper_link_setup_igp - Setup igp PHY's for copper link
* @hw: pointer to the HW structure
*
@@ -1570,7 +1654,9 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;
if (!link) {
- if (hw->phy.type != e1000_phy_m88) {
+ if (hw->phy.type != e1000_phy_m88 ||
+ hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID) {
DEBUGOUT("Link taking longer than expected.\n");
} else {
/*
@@ -1595,7 +1681,9 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
goto out;
}
- if (hw->phy.type != e1000_phy_m88)
+ if (hw->phy.type != e1000_phy_m88 ||
+ hw->phy.id == I347AT4_E_PHY_ID ||
+ hw->phy.id == M88E1112_E_PHY_ID)
goto out;
ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
@@ -2136,6 +2224,95 @@ out:
return ret_val;
}
+s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val;
+ u16 phy_data, phy_data2, index, default_page, is_cm;
+
+ DEBUGFUNC("e1000_get_cable_length_m88_gen2");
+
+ switch (hw->phy.id) {
+ case I347AT4_E_PHY_ID:
+ /* Remember the original page select and set it to 7 */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+ &default_page);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
+ if (ret_val)
+ goto out;
+
+ /* Get cable length from PHY Cable Diagnostics Control Reg */
+ ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
+ &phy_data);
+ if (ret_val)
+ goto out;
+
+ /* Check if the unit of cable length is meters or cm */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
+ if (ret_val)
+ goto out;
+
+ is_cm = !(phy_data & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+ /* Populate the phy structure with cable length in meters */
+ phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+ phy->cable_length = phy_data / (is_cm ? 100 : 1);
+
+ /* Reset the page selec to its original value */
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+ default_page);
+ if (ret_val)
+ goto out;
+ break;
+ case M88E1112_E_PHY_ID:
+ /* Remember the original page select and set it to 5 */
+ ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
+ &default_page);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
+ &phy_data);
+ if (ret_val)
+ goto out;
+
+ index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT;
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
+ ret_val = -E1000_ERR_PHY;
+ goto out;
+ }
+
+ phy->min_cable_length = e1000_m88_cable_length_table[index];
+ phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
+
+ phy->cable_length = (phy->min_cable_length +
+ phy->max_cable_length) / 2;
+
+ /* Reset the page select to its original value */
+ ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
+ default_page);
+ if (ret_val)
+ goto out;
+
+ break;
+ default:
+ ret_val = -E1000_ERR_PHY;
+ goto out;
+ }
+
+out:
+ return ret_val;
+}
+
/**
* e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY
* @hw: pointer to the HW structure
@@ -2154,11 +2331,12 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
u16 phy_data, i, agc_value = 0;
u16 cur_agc_index, max_agc_index = 0;
u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
- u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
- {IGP02E1000_PHY_AGC_A,
- IGP02E1000_PHY_AGC_B,
- IGP02E1000_PHY_AGC_C,
- IGP02E1000_PHY_AGC_D};
+ static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
+ IGP02E1000_PHY_AGC_A,
+ IGP02E1000_PHY_AGC_B,
+ IGP02E1000_PHY_AGC_C,
+ IGP02E1000_PHY_AGC_D
+ };
DEBUGFUNC("e1000_get_cable_length_igp_2");
@@ -2607,6 +2785,8 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
case M88E1000_E_PHY_ID:
case M88E1111_I_PHY_ID:
case M88E1011_I_PHY_ID:
+ case I347AT4_E_PHY_ID:
+ case M88E1112_E_PHY_ID:
phy_type = e1000_phy_m88;
break;
case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
@@ -2675,7 +2855,7 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
* If phy_type is valid, break - we found our
* PHY address
*/
- if (phy_type != e1000_phy_unknown) {
+ if (phy_type != e1000_phy_unknown) {
ret_val = E1000_SUCCESS;
goto out;
}
@@ -2716,9 +2896,7 @@ static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
{
s32 ret_val;
- u32 page_select = 0;
u32 page = offset >> IGP_PAGE_SHIFT;
- u32 page_shift = 0;
DEBUGFUNC("e1000_write_phy_reg_bm");
@@ -2736,6 +2914,8 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ u32 page_shift, page_select;
+
/*
* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
@@ -2777,9 +2957,7 @@ out:
s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
{
s32 ret_val;
- u32 page_select = 0;
u32 page = offset >> IGP_PAGE_SHIFT;
- u32 page_shift = 0;
DEBUGFUNC("e1000_read_phy_reg_bm");
@@ -2797,6 +2975,8 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
if (offset > MAX_PHY_MULTI_PAGE_REG) {
+ u32 page_shift, page_select;
+
/*
* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
@@ -2980,8 +3160,7 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
}
/* Select page 800 */
- ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
+ ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
(BM_WUC_PAGE << IGP_PAGE_SHIFT));
/* Write the page 800 offset value using opcode 0x11 */
diff --git a/sys/dev/e1000/e1000_phy.h b/sys/dev/e1000/e1000_phy.h
index c42ef6c..0da4a88 100644
--- a/sys/dev/e1000/e1000_phy.h
+++ b/sys/dev/e1000/e1000_phy.h
@@ -49,10 +49,12 @@ s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
s32 e1000_copper_link_autoneg(struct e1000_hw *hw);
s32 e1000_copper_link_setup_igp(struct e1000_hw *hw);
s32 e1000_copper_link_setup_m88(struct e1000_hw *hw);
+s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw);
s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw);
s32 e1000_get_cable_length_m88(struct e1000_hw *hw);
+s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw);
s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw);
s32 e1000_get_cfg_done_generic(struct e1000_hw *hw);
s32 e1000_get_phy_id(struct e1000_hw *hw);
@@ -120,6 +122,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
/* BM/HV Specific Registers */
#define BM_PORT_CTRL_PAGE 769
+#define BM_PORT_GEN_CFG_REG PHY_REG(BM_PORT_CTRL_PAGE, 17)
#define BM_PCIE_PAGE 770
#define BM_WUC_PAGE 800
#define BM_WUC_ADDRESS_OPCODE 0x11
@@ -170,6 +173,12 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
#define I82577_DSTATUS_CABLE_LENGTH 0x03FC
#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
+/* 82580 PHY Power Management */
+#define E1000_82580_PHY_POWER_MGMT 0xE14
+#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
+#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
+#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
+
/* BM PHY Copper Specific Control 1 */
#define BM_CS_CTRL1 16
#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */
@@ -234,6 +243,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
+#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002
diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h
index 38ccff3..f3f265d 100644
--- a/sys/dev/e1000/e1000_regs.h
+++ b/sys/dev/e1000/e1000_regs.h
@@ -91,6 +91,7 @@
#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
+#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
@@ -129,6 +130,7 @@
#define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */
#define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
#define E1000_IRPBS 0x02404 /* Same as RXPBS, renamed for newer adapters - RW */
+#define E1000_PBRWAC 0x024E8 /* Rx packet buffer wrap around counter - RO */
#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */
#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
/*
@@ -429,6 +431,7 @@
#define E1000_UFUSE 0x05B78 /* UFUSE - RO */
#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
#define E1000_HICR 0x08F00 /* Host Interface Control */
+#define E1000_FWSTS 0x08F0C /* FW Status */
/* RSS registers */
#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
@@ -465,6 +468,14 @@
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */
+#define E1000_VMRVLAN 0x05D90 /* Virtual Mirror Rule VLAN */
+#define E1000_VMRVM 0x05DA0 /* Virtual Mirror Rule VM */
+#define E1000_MDFB 0x03558 /* Malicious Driver free block */
+#define E1000_LVMMC 0x03548 /* Last VM Misbehavior cause */
+#define E1000_TXSWC 0x05ACC /* Tx Switch Control */
+#define E1000_SCCRL 0x05DB0 /* Storm Control Control */
+#define E1000_BSCTRH 0x05DB8 /* Broadcast Storm Control Threshold */
+#define E1000_MSCTRH 0x05DBC /* Multicast Storm Control Threshold */
/* These act per VF so an array friendly macro is used */
#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
#define E1000_P2VMAILBOX(_n) (0x00C00 + (4 * (_n)))
@@ -474,6 +485,7 @@
#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine
* Filter - RW */
#define E1000_VMVIR(_n) (0x03700 + (4 * (_n)))
+#define E1000_DVMOLR(_n) (0x0C038 + (0x40 * (_n))) /* DMA VM offload */
/* Time Sync */
#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
@@ -537,12 +549,34 @@
#define E1000_DMCTXTH 0x03550 /* Transmit Threshold */
#define E1000_DMCTLX 0x02514 /* Time to Lx Request */
#define E1000_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */
-#define E1000_DMCCNT 0x05DD4 /* Current RX Count */
+#define E1000_DMCCNT 0x05DD4 /* Current Rx Count */
#define E1000_FCRTC 0x02170 /* Flow Control Rx high watermark */
#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */
/* PCIe Parity Status Register */
#define E1000_PCIEERRSTS 0x05BA8
+#define E1000_PROXYS 0x5F64 /* Proxying Status */
+#define E1000_PROXYFC 0x5F60 /* Proxying Filter Control */
+/* Thermal sensor configuration and status registers */
+#define E1000_THMJT 0x08100 /* Junction Temperature */
+#define E1000_THLOWTC 0x08104 /* Low Threshold Control */
+#define E1000_THMIDTC 0x08108 /* Mid Threshold Control */
+#define E1000_THHIGHTC 0x0810C /* High Threshold Control */
+#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
+
+/*Energy Efficient Ethernet "EEE" registers */
+#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */
+#define E1000_LTRC 0x01A0 /* Latency Tolerance Reporting Control */
+#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/
+#define E1000_EEE_SU 0x0E34 /* EEE Setup */
+#define E1000_TLPIC 0x4148 /* EEE Tx LPI Count - TLPIC */
+#define E1000_RLPIC 0x414C /* EEE Rx LPI Count - RLPIC */
+
+/* OS2BMC Registers */
+#define E1000_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */
+#define E1000_B2OGPRC 0x04158 /* BMC2OS packets received by host */
+#define E1000_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
+#define E1000_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
#endif
diff --git a/sys/dev/e1000/e1000_vf.c b/sys/dev/e1000/e1000_vf.c
index b2ee563..3eeda24 100644
--- a/sys/dev/e1000/e1000_vf.c
+++ b/sys/dev/e1000/e1000_vf.c
@@ -532,8 +532,8 @@ static s32 e1000_check_for_link_vf(struct e1000_hw *hw)
* or a virtual function reset
*/
- /* If we were hit with a reset drop the link */
- if (!mbx->ops.check_for_rst(hw, 0))
+ /* If we were hit with a reset or timeout drop the link */
+ if (!mbx->ops.check_for_rst(hw, 0) || !mbx->timeout)
mac->get_link_status = TRUE;
if (!mac->get_link_status)
diff --git a/sys/dev/e1000/e1000_vf.h b/sys/dev/e1000/e1000_vf.h
index b67bed2..0ee73ae 100644
--- a/sys/dev/e1000/e1000_vf.h
+++ b/sys/dev/e1000/e1000_vf.h
@@ -42,6 +42,7 @@
struct e1000_hw;
#define E1000_DEV_ID_82576_VF 0x10CA
+#define E1000_DEV_ID_I350_VF 0x1520
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
@@ -88,9 +89,10 @@ union e1000_adv_rx_desc {
union {
u32 data;
struct {
- u16 pkt_info; /* RSS type, Packet type */
- u16 hdr_info; /* Split Header,
- * header buffer length */
+ /* RSS type, Packet type */
+ u16 pkt_info;
+ /* Split Header, header buffer len */
+ u16 hdr_info;
} hs_rss;
} lo_dword;
union {
@@ -154,6 +156,7 @@ struct e1000_adv_tx_context_desc {
enum e1000_mac_type {
e1000_undefined = 0,
e1000_vfadapt,
+ e1000_vfadapt_i350,
e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
};
@@ -249,8 +252,8 @@ struct e1000_mbx_info {
};
struct e1000_dev_spec_vf {
- u32 vf_number;
- u32 v2p_mailbox;
+ u32 vf_number;
+ u32 v2p_mailbox;
};
struct e1000_hw {
@@ -264,7 +267,7 @@ struct e1000_hw {
struct e1000_mbx_info mbx;
union {
- struct e1000_dev_spec_vf vf;
+ struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 3fff390..53d52ce 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -99,7 +99,7 @@ int igb_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char igb_driver_version[] = "version - 2.0.7";
+char igb_driver_version[] = "version - 2.1.3";
/*********************************************************************
@@ -141,6 +141,14 @@ static igb_vendor_info_t igb_vendor_info_array[] =
PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_DH89XXCC_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_DH89XXCC_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_DH89XXCC_SFP, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_DH89XXCC_BACKPLANE,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_I350_VF, PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -505,7 +513,7 @@ igb_attach(device_t dev)
}
/* Allocate the appropriate stats memory */
- if (adapter->hw.mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
adapter->stats =
(struct e1000_vf_stats *)malloc(sizeof \
(struct e1000_vf_stats), M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -792,11 +800,10 @@ igb_start_locked(struct tx_ring *txr, struct ifnet *ifp)
if (!adapter->link_active)
return;
- /* Call cleanup if number of TX descriptors low */
- if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
- igb_txeof(txr);
-
while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+ /* Cleanup if TX descriptors are low */
+ if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
+ igb_txeof(txr);
if (txr->tx_avail <= IGB_TX_OP_THRESHOLD) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
@@ -891,10 +898,6 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
return (err);
}
- /* Call cleanup if number of TX descriptors low */
- if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
- igb_txeof(txr);
-
enq = 0;
if (m == NULL) {
next = drbr_dequeue(ifp, txr->br);
@@ -907,6 +910,13 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
/* Process the queue */
while (next != NULL) {
+ /* Call cleanup if number of TX descriptors low */
+ if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD)
+ igb_txeof(txr);
+ if (txr->tx_avail <= IGB_TX_OP_THRESHOLD) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
if ((err = igb_xmit(txr, &next)) != 0) {
if (next != NULL)
err = drbr_enqueue(ifp, txr->br, next);
@@ -917,10 +927,6 @@ igb_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
ETHER_BPF_MTAP(ifp, next);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
break;
- if (txr->tx_avail <= IGB_TX_OP_THRESHOLD) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
next = drbr_dequeue(ifp, txr->br);
}
if (enq > 0) {
@@ -1210,18 +1216,9 @@ igb_init_locked(struct adapter *adapter)
}
igb_initialize_receive_units(adapter);
- /* Use real VLAN Filter support? */
- if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
- if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
- /* Use real VLAN Filter support */
- igb_setup_vlan_hw_support(adapter);
- else {
- u32 ctrl;
- ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
- ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- }
- }
+ /* Enable VLAN support */
+ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
+ igb_setup_vlan_hw_support(adapter);
/* Don't lose promiscuous settings */
igb_set_promisc(adapter);
@@ -1286,11 +1283,10 @@ igb_handle_que(void *context, int pending)
if (!drbr_empty(ifp, txr->br))
igb_mq_start_locked(ifp, txr, NULL);
#else
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- igb_start_locked(txr, ifp);
+ igb_start_locked(txr, ifp);
#endif
IGB_TX_UNLOCK(txr);
- if (more) {
+ if (more || (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
taskqueue_enqueue(que->tq, &que->que_task);
return;
}
@@ -1411,8 +1407,7 @@ igb_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
if (!drbr_empty(ifp, txr->br))
igb_mq_start_locked(ifp, txr, NULL);
#else
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- igb_start_locked(txr, ifp);
+ igb_start_locked(txr, ifp);
#endif
IGB_TX_UNLOCK(txr);
return POLL_RETURN_COUNT(rx_done);
@@ -1496,7 +1491,8 @@ igb_msix_que(void *arg)
no_calc:
/* Schedule a clean task if needed*/
- if (more_tx || more_rx)
+ if (more_tx || more_rx ||
+ (adapter->ifp->if_drv_flags & IFF_DRV_OACTIVE))
taskqueue_enqueue(que->tq, &que->que_task);
else
/* Reenable this interrupt */
@@ -1670,19 +1666,6 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
if (m_head->m_flags & M_VLANTAG)
cmd_type_len |= E1000_ADVTXD_DCMD_VLE;
- /*
- * Force a cleanup if number of TX descriptors
- * available hits the threshold
- */
- if (txr->tx_avail <= IGB_TX_CLEANUP_THRESHOLD) {
- igb_txeof(txr);
- /* Now do we at least have a minimal? */
- if (txr->tx_avail <= IGB_TX_OP_THRESHOLD) {
- txr->no_desc_avail++;
- return (ENOBUFS);
- }
- }
-
/*
* Map the packet for DMA.
*
@@ -1830,7 +1813,7 @@ igb_set_promisc(struct adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 reg;
- if (hw->mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
e1000_promisc_set_vf(hw, e1000_promisc_enabled);
return;
}
@@ -1852,7 +1835,7 @@ igb_disable_promisc(struct adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 reg;
- if (hw->mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
e1000_promisc_set_vf(hw, e1000_promisc_disabled);
return;
}
@@ -2106,6 +2089,13 @@ igb_identify_hardware(struct adapter *adapter)
/* Set MAC type early for PCI setup */
e1000_set_mac_type(&adapter->hw);
+
+ /* Are we a VF device? */
+ if ((adapter->hw.mac.type == e1000_vfadapt) ||
+ (adapter->hw.mac.type == e1000_vfadapt_i350))
+ adapter->vf_ifp = 1;
+ else
+ adapter->vf_ifp = 0;
}
static int
@@ -2275,7 +2265,7 @@ igb_configure_queues(struct adapter *adapter)
u32 tmp, ivar = 0, newitr = 0;
/* First turn on RSS capability */
- if (adapter->hw.mac.type > e1000_82575)
+ if (adapter->hw.mac.type != e1000_82575)
E1000_WRITE_REG(hw, E1000_GPIE,
E1000_GPIE_MSIX_MODE | E1000_GPIE_EIAME |
E1000_GPIE_PBA | E1000_GPIE_NSICR);
@@ -2283,7 +2273,9 @@ igb_configure_queues(struct adapter *adapter)
/* Turn on MSIX */
switch (adapter->hw.mac.type) {
case e1000_82580:
+ case e1000_i350:
case e1000_vfadapt:
+ case e1000_vfadapt_i350:
/* RX entries */
for (int i = 0; i < adapter->num_queues; i++) {
u32 index = i >> 1;
@@ -2311,13 +2303,12 @@ igb_configure_queues(struct adapter *adapter)
ivar |= (que->msix | E1000_IVAR_VALID) << 8;
}
E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* And for the link interrupt */
ivar = (adapter->linkvec | E1000_IVAR_VALID) << 8;
adapter->link_mask = 1 << adapter->linkvec;
- adapter->eims_mask |= adapter->link_mask;
E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar);
break;
case e1000_82576:
@@ -2334,7 +2325,7 @@ igb_configure_queues(struct adapter *adapter)
ivar |= (que->msix | E1000_IVAR_VALID) << 16;
}
E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* TX entries */
for (int i = 0; i < adapter->num_queues; i++) {
@@ -2349,13 +2340,12 @@ igb_configure_queues(struct adapter *adapter)
ivar |= (que->msix | E1000_IVAR_VALID) << 24;
}
E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* And for the link interrupt */
ivar = (adapter->linkvec | E1000_IVAR_VALID) << 8;
adapter->link_mask = 1 << adapter->linkvec;
- adapter->eims_mask |= adapter->link_mask;
E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar);
break;
@@ -2376,14 +2366,13 @@ igb_configure_queues(struct adapter *adapter)
que->eims = tmp;
E1000_WRITE_REG_ARRAY(hw, E1000_MSIXBM(0),
i, que->eims);
- adapter->eims_mask |= que->eims;
+ adapter->que_mask |= que->eims;
}
/* Link */
E1000_WRITE_REG(hw, E1000_MSIXBM(adapter->linkvec),
E1000_EIMS_OTHER);
adapter->link_mask |= E1000_EIMS_OTHER;
- adapter->eims_mask |= adapter->link_mask;
default:
break;
}
@@ -2510,8 +2499,8 @@ igb_setup_msix(struct adapter *adapter)
if ((adapter->hw.mac.type == e1000_82575) && (queues > 4))
queues = 4;
- /* Limit the VF adapter to one queue */
- if (adapter->hw.mac.type == e1000_vfadapt)
+ /* Limit the VF devices to one queue */
+ if (adapter->vf_ifp)
queues = 1;
/*
@@ -2572,9 +2561,15 @@ igb_reset(struct adapter *adapter)
break;
case e1000_82576:
case e1000_vfadapt:
- pba = E1000_PBA_64K;
+ pba = E1000_READ_REG(hw, E1000_RXPBS);
+ pba &= E1000_RXPBS_SIZE_MASK_82576;
break;
case e1000_82580:
+ case e1000_i350:
+ case e1000_vfadapt_i350:
+ pba = E1000_READ_REG(hw, E1000_RXPBS);
+ pba = e1000_rxpbs_adjust_82580(pba);
+ break;
pba = E1000_PBA_35K;
default:
break;
@@ -2646,7 +2641,8 @@ igb_reset(struct adapter *adapter)
if (e1000_init_hw(hw) < 0)
device_printf(dev, "Hardware Initialization Failed\n");
- if (hw->mac.type == e1000_82580) {
+ /* Setup DMA Coalescing */
+ if (hw->mac.type == e1000_i350) {
u32 reg;
hwm = (pba << 10) - (2 * adapter->max_frame_size);
@@ -3178,7 +3174,7 @@ igb_initialize_transmit_units(struct adapter *adapter)
E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl);
}
- if (adapter->hw.mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
return;
e1000_config_collision_dist(hw);
@@ -3584,17 +3580,17 @@ igb_txeof(struct tx_ring *txr)
txr->queue_status = IGB_QUEUE_HUNG;
/*
- * If we have enough room, clear IFF_DRV_OACTIVE
+ * If we have a minimum free, clear IFF_DRV_OACTIVE
* to tell the stack that it is OK to send packets.
*/
- if (txr->tx_avail > IGB_TX_CLEANUP_THRESHOLD) {
+ if (txr->tx_avail > IGB_TX_OP_THRESHOLD)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- /* All clean, turn off the watchdog */
- if (txr->tx_avail == adapter->num_tx_desc) {
- txr->queue_status = IGB_QUEUE_IDLE;
- return (FALSE);
- }
- }
+
+ /* All clean, turn off the watchdog */
+ if (txr->tx_avail == adapter->num_tx_desc) {
+ txr->queue_status = IGB_QUEUE_IDLE;
+ return (FALSE);
+ }
return (TRUE);
}
@@ -4563,9 +4559,9 @@ igb_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
bit = vtag & 0x1F;
adapter->shadow_vfta[index] |= (1 << bit);
++adapter->num_vlans;
- /* Re-init to load the changes */
+ /* Change hw filter setting */
if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
- igb_init_locked(adapter);
+ igb_setup_vlan_hw_support(adapter);
IGB_CORE_UNLOCK(adapter);
}
@@ -4590,9 +4586,9 @@ igb_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
bit = vtag & 0x1F;
adapter->shadow_vfta[index] &= ~(1 << bit);
--adapter->num_vlans;
- /* Re-init to load the changes */
+ /* Change hw filter setting */
if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
- igb_init_locked(adapter);
+ igb_setup_vlan_hw_support(adapter);
IGB_CORE_UNLOCK(adapter);
}
@@ -4600,49 +4596,48 @@ static void
igb_setup_vlan_hw_support(struct adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
+ struct ifnet *ifp = adapter->ifp;
u32 reg;
- /*
- ** We get here thru init_locked, meaning
- ** a soft reset, this has already cleared
- ** the VFTA and other state, so if there
- ** have been no vlan's registered do nothing.
- */
- if (adapter->num_vlans == 0)
- return;
+ if (adapter->vf_ifp) {
+ e1000_rlpml_set_vf(hw,
+ adapter->max_frame_size + VLAN_TAG_SIZE);
+ return;
+ }
+ reg = E1000_READ_REG(hw, E1000_CTRL);
+ reg |= E1000_CTRL_VME;
+ E1000_WRITE_REG(hw, E1000_CTRL, reg);
+
+ /* Enable the Filter Table */
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
+ reg = E1000_READ_REG(hw, E1000_RCTL);
+ reg &= ~E1000_RCTL_CFIEN;
+ reg |= E1000_RCTL_VFE;
+ E1000_WRITE_REG(hw, E1000_RCTL, reg);
+ }
+
+ /* Update the frame size */
+ E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
+ adapter->max_frame_size + VLAN_TAG_SIZE);
+
+ /* Don't bother with table if no vlans */
+ if ((adapter->num_vlans == 0) ||
+ ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0))
+ return;
/*
** A soft reset zero's out the VFTA, so
** we need to repopulate it now.
*/
for (int i = 0; i < IGB_VFTA_SIZE; i++)
if (adapter->shadow_vfta[i] != 0) {
- if (hw->mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
e1000_vfta_set_vf(hw,
adapter->shadow_vfta[i], TRUE);
else
E1000_WRITE_REG_ARRAY(hw, E1000_VFTA,
i, adapter->shadow_vfta[i]);
}
-
- if (hw->mac.type == e1000_vfadapt)
- e1000_rlpml_set_vf(hw,
- adapter->max_frame_size + VLAN_TAG_SIZE);
- else {
- reg = E1000_READ_REG(hw, E1000_CTRL);
- reg |= E1000_CTRL_VME;
- E1000_WRITE_REG(hw, E1000_CTRL, reg);
-
- /* Enable the Filter Table */
- reg = E1000_READ_REG(hw, E1000_RCTL);
- reg &= ~E1000_RCTL_CFIEN;
- reg |= E1000_RCTL_VFE;
- E1000_WRITE_REG(hw, E1000_RCTL, reg);
-
- /* Update the frame size */
- E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
- adapter->max_frame_size + VLAN_TAG_SIZE);
- }
}
static void
@@ -4650,12 +4645,10 @@ igb_enable_intr(struct adapter *adapter)
{
/* With RSS set up what to auto clear */
if (adapter->msix_mem) {
- E1000_WRITE_REG(&adapter->hw, E1000_EIAC,
- adapter->eims_mask);
- E1000_WRITE_REG(&adapter->hw, E1000_EIAM,
- adapter->eims_mask);
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS,
- adapter->eims_mask);
+ u32 mask = (adapter->que_mask | adapter->link_mask);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIAC, mask);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIAM, mask);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIMS, mask);
E1000_WRITE_REG(&adapter->hw, E1000_IMS,
E1000_IMS_LSC);
} else {
@@ -4732,7 +4725,7 @@ igb_get_hw_control(struct adapter *adapter)
{
u32 ctrl_ext;
- if (adapter->hw.mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
return;
/* Let firmware know the driver has taken over */
@@ -4752,7 +4745,7 @@ igb_release_hw_control(struct adapter *adapter)
{
u32 ctrl_ext;
- if (adapter->hw.mac.type == e1000_vfadapt)
+ if (adapter->vf_ifp)
return;
/* Let firmware taken over control of h/w */
@@ -4831,7 +4824,7 @@ igb_update_stats_counters(struct adapter *adapter)
** small controlled set of stats, do only
** those and return.
*/
- if (adapter->hw.mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
igb_update_vf_stats_counters(adapter);
return;
}
@@ -5176,7 +5169,7 @@ igb_add_hw_stats(struct adapter *adapter)
** VF adapter has a very limited set of stats
** since its not managing the metal, so to speak.
*/
- if (adapter->hw.mac.type == e1000_vfadapt) {
+ if (adapter->vf_ifp) {
SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_recvd",
CTLFLAG_RD, &stats->gprc,
"Good Packets Received");
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index 15fdceb..d9f1cc3 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -180,8 +180,7 @@
#define IGB_TX_PTHRESH 8
#define IGB_TX_HTHRESH 1
-#define IGB_TX_WTHRESH (((hw->mac.type == e1000_82576 || \
- hw->mac.type == e1000_vfadapt) && \
+#define IGB_TX_WTHRESH ((hw->mac.type != e1000_82575 && \
adapter->msix_mem) ? 1 : 16)
#define MAX_NUM_MULTICAST_ADDRESSES 128
@@ -323,6 +322,7 @@ struct rx_ring {
bool lro_enabled;
bool hdr_split;
bool discard;
+ bool needs_refresh;
struct mtx rx_mtx;
char mtx_name[16];
u32 next_to_refresh;
@@ -361,7 +361,7 @@ struct adapter {
struct resource *msix_mem;
struct resource *res;
void *tag;
- u32 eims_mask;
+ u32 que_mask;
int linkvec;
int link_mask;
@@ -378,6 +378,7 @@ struct adapter {
struct mtx core_mtx;
int igb_insert_vlan_header;
u16 num_queues;
+ u16 vf_ifp; /* a VF interface */
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
OpenPOWER on IntegriCloud