Mercurial > illumos > illumos-gate
changeset 11155:1d6534291026
6874779 Solaris igb driver needs to support Intel 82580 Barton Hills
6901478 igb is not lint clean after the integration of CR6708291
author | zhefeng xu - Sun Microsystems - Beijing China <Jason.Xu@Sun.COM> |
---|---|
date | Mon, 23 Nov 2009 14:27:01 +0800 |
parents | cec14087b5a4 |
children | fa5f12909da7 |
files | usr/src/pkgdefs/SUNWigb/postinstall usr/src/uts/common/io/igb/igb_82575.c usr/src/uts/common/io/igb/igb_82575.h usr/src/uts/common/io/igb/igb_api.c usr/src/uts/common/io/igb/igb_api.h usr/src/uts/common/io/igb/igb_defines.h usr/src/uts/common/io/igb/igb_hw.h usr/src/uts/common/io/igb/igb_mac.c usr/src/uts/common/io/igb/igb_mac.h usr/src/uts/common/io/igb/igb_main.c usr/src/uts/common/io/igb/igb_manage.c usr/src/uts/common/io/igb/igb_manage.h usr/src/uts/common/io/igb/igb_nvm.c usr/src/uts/common/io/igb/igb_nvm.h usr/src/uts/common/io/igb/igb_osdep.h usr/src/uts/common/io/igb/igb_phy.c usr/src/uts/common/io/igb/igb_phy.h usr/src/uts/common/io/igb/igb_regs.h usr/src/uts/common/io/igb/igb_sw.h usr/src/uts/common/io/igb/igb_tx.c |
diffstat | 20 files changed, 1452 insertions(+), 474 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/pkgdefs/SUNWigb/postinstall Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/pkgdefs/SUNWigb/postinstall Mon Nov 23 14:27:01 2009 +0800 @@ -135,5 +135,11 @@ "pciex8086,10e7" "pciex8086,10e8" "pciex8086,150a" - "pciex8086,150d"' \ + "pciex8086,150d" + "pciex8086,150e" + "pciex8086,150f" + "pciex8086,1510" + "pciex8086,1511" + "pciex8086,1516" + "pciex8086,1518"' \ -b "$BASEDIR" igb
--- a/usr/src/uts/common/io/igb/igb_82575.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_82575.c Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.123 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.143 scm_100809_154340 */ /* * 82575EB Gigabit Network Connection @@ -54,16 +54,20 @@ 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, u32 offset, + u16 *data); +static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, + u16 data); 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); -static s32 e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw); +static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw); static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data); static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data); static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw); static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask); -static s32 e1000_configure_pcs_link_82575(struct e1000_hw *hw); static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, u16 *duplex); static s32 e1000_get_phy_id_82575(struct e1000_hw *hw); @@ -72,9 +76,14 @@ static s32 e1000_reset_init_script_82575(struct e1000_hw *hw); static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw); static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw); -void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw); +static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw); static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw); +static const u16 e1000_82580_rxpbs_table[] = + {36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140}; +#define E1000_82580_RXPBS_TABLE_SIZE \ + (sizeof (e1000_82580_rxpbs_table)/sizeof (u16)) + /* * e1000_init_phy_params_82575 - Init PHY func ptrs. * @hw: pointer to the HW structure @@ -90,11 +99,11 @@ if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; - } else { - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_82575; } + phy->ops.power_up = e1000_power_up_phy_copper; + phy->ops.power_down = e1000_power_down_phy_copper_82575; + phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->reset_delay_us = 100; @@ -108,6 +117,10 @@ phy->ops.reset = e1000_phy_hw_reset_sgmii_82575; phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; + } else if (hw->mac.type == e1000_82580) { + phy->ops.reset = e1000_phy_hw_reset_generic; + phy->ops.read_reg = e1000_read_phy_reg_82580; + phy->ops.write_reg = e1000_write_phy_reg_82580; } else { phy->ops.reset = e1000_phy_hw_reset_generic; phy->ops.read_reg = e1000_read_phy_reg_igp; @@ -136,6 +149,14 @@ phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; break; + case I82580_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; + break; default: ret_val = -E1000_ERR_PHY; goto out; @@ -228,24 +249,33 @@ dev_spec->sgmii_active = false; ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); - if ((ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) == - E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES) { + switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { + case E1000_CTRL_EXT_LINK_MODE_SGMII: + dev_spec->sgmii_active = true; + ctrl_ext |= E1000_CTRL_I2C_ENA; + break; + case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: + case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: hw->phy.media_type = e1000_media_type_internal_serdes; ctrl_ext |= E1000_CTRL_I2C_ENA; - } else if (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_SGMII) { - dev_spec->sgmii_active = true; - ctrl_ext |= E1000_CTRL_I2C_ENA; - } else { + break; + default: ctrl_ext &= ~E1000_CTRL_I2C_ENA; + break; } + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); /* Set mta register count */ mac->mta_reg_count = 128; + /* Set uta register count */ + mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; /* Set rar entry count */ mac->rar_entry_count = E1000_RAR_ENTRIES_82575; if (mac->type == e1000_82576) mac->rar_entry_count = E1000_RAR_ENTRIES_82576; + if (mac->type == e1000_82580) + mac->rar_entry_count = E1000_RAR_ENTRIES_82580; /* Set if part includes ASF firmware */ mac->asf_firmware_present = true; /* Set if manageability features are enabled. */ @@ -258,7 +288,10 @@ /* bus type/speed/width */ mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; /* reset */ - mac->ops.reset_hw = e1000_reset_hw_82575; + if (mac->type == e1000_82580) + mac->ops.reset_hw = e1000_reset_hw_82580; + else + mac->ops.reset_hw = e1000_reset_hw_82575; /* hw initialization */ mac->ops.init_hw = e1000_init_hw_82575; /* link setup */ @@ -267,9 +300,9 @@ mac->ops.setup_physical_interface = (hw->phy.media_type == e1000_media_type_copper) ? e1000_setup_copper_link_82575 - : e1000_setup_fiber_serdes_link_82575; + : e1000_setup_serdes_link_82575; /* physical interface shutdown */ - mac->ops.shutdown_serdes = e1000_shutdown_fiber_serdes_link_82575; + mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_82575; /* receive address register setting */ @@ -300,6 +333,9 @@ /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_82575; + /* set lan id for port to determine which phy lock to use */ + hw->mac.ops.set_lan_id(hw); + return (E1000_SUCCESS); } @@ -334,6 +370,10 @@ if (hw->bus.func == E1000_FUNC_1) mask = E1000_SWFW_PHY1_SM; + else if (hw->bus.func == E1000_FUNC_2) + mask = E1000_SWFW_PHY2_SM; + else if (hw->bus.func == E1000_FUNC_3) + mask = E1000_SWFW_PHY3_SM; return (e1000_acquire_swfw_sync_82575(hw, mask)); } @@ -353,6 +393,10 @@ if (hw->bus.func == E1000_FUNC_1) mask = E1000_SWFW_PHY1_SM; + else if (hw->bus.func == E1000_FUNC_2) + mask = E1000_SWFW_PHY2_SM; + else if (hw->bus.func == E1000_FUNC_3) + mask = E1000_SWFW_PHY3_SM; e1000_release_swfw_sync_82575(hw, mask); } @@ -369,47 +413,25 @@ static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 *data) { - struct e1000_phy_info *phy = &hw->phy; - u32 i, i2ccmd = 0; + s32 ret_val = -E1000_ERR_PARAM; DEBUGFUNC("e1000_read_phy_reg_sgmii_82575"); if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { DEBUGOUT1("PHY Address %u is out of range\n", offset); - return (-E1000_ERR_PARAM); + goto out; } - /* - * Set up Op-code, Phy Address, and register address in the I2CCMD - * register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | - (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | - (E1000_I2CCMD_OPCODE_READ)); - - E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; - /* Poll the ready bit to see if the I2C read completed */ - for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { - usec_delay(50); - i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); - if (i2ccmd & E1000_I2CCMD_READY) - break; - } - if (!(i2ccmd & E1000_I2CCMD_READY)) { - DEBUGOUT("I2CCMD Read did not complete\n"); - return (-E1000_ERR_PHY); - } - if (i2ccmd & E1000_I2CCMD_ERROR) { - DEBUGOUT("I2CCMD Error bit set\n"); - return (-E1000_ERR_PHY); - } + ret_val = e1000_read_phy_reg_i2c(hw, offset, data); - /* Need to byte-swap the 16-bit value. */ - *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); + hw->phy.ops.release(hw); - return (E1000_SUCCESS); +out: + return (ret_val); } /* @@ -424,49 +446,25 @@ static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, u16 data) { - struct e1000_phy_info *phy = &hw->phy; - u32 i, i2ccmd = 0; - u16 phy_data_swapped; + s32 ret_val = -E1000_ERR_PARAM; DEBUGFUNC("e1000_write_phy_reg_sgmii_82575"); if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { DEBUGOUT1("PHY Address %d is out of range\n", offset); - return (-E1000_ERR_PARAM); + goto out; } - /* Swap the data bytes for the I2C interface */ - phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); - - /* - * Set up Op-code, Phy Address, and register address in the I2CCMD - * register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | - (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | - E1000_I2CCMD_OPCODE_WRITE | - phy_data_swapped); - - E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; - /* Poll the ready bit to see if the I2C read completed */ - for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { - usec_delay(50); - i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); - if (i2ccmd & E1000_I2CCMD_READY) - break; - } - if (!(i2ccmd & E1000_I2CCMD_READY)) { - DEBUGOUT("I2CCMD Write did not complete\n"); - return (-E1000_ERR_PHY); - } - if (i2ccmd & E1000_I2CCMD_ERROR) { - DEBUGOUT("I2CCMD Error bit set\n"); - return (-E1000_ERR_PHY); - } + ret_val = e1000_write_phy_reg_i2c(hw, offset, data); - return (E1000_SUCCESS); + hw->phy.ops.release(hw); + +out: + return (ret_val); } /* @@ -482,6 +480,7 @@ struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_id; + u32 ctrl_ext; DEBUGFUNC("e1000_get_phy_id_82575"); @@ -492,12 +491,19 @@ * work. The result of this function should mean phy->phy_addr * and phy->id are set correctly. */ - if (!(e1000_sgmii_active_82575(hw))) { + if (!e1000_sgmii_active_82575(hw)) { phy->addr = 1; ret_val = e1000_get_phy_id(hw); goto out; } + /* Power on sgmii phy if it is disabled */ + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, + ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); + E1000_WRITE_FLUSH(hw); + msec_delay(300); + /* * The address field in the I2CCMD register is 3 bits and 0 is invalid. * Therefore, we need to test 1-7 @@ -524,10 +530,12 @@ if (phy->addr == 8) { phy->addr = 0; ret_val = -E1000_ERR_PHY; - goto out; + } else { + ret_val = e1000_get_phy_id(hw); } - ret_val = e1000_get_phy_id(hw); + /* restore previous sfp cage power state */ + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); out: return (ret_val); @@ -806,6 +814,10 @@ if (hw->bus.func == E1000_FUNC_1) mask = E1000_NVM_CFG_DONE_PORT_1; + else if (hw->bus.func == E1000_FUNC_2) + mask = E1000_NVM_CFG_DONE_PORT_2; + else if (hw->bus.func == E1000_FUNC_3) + mask = E1000_NVM_CFG_DONE_PORT_3; while (timeout) { if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) @@ -813,15 +825,14 @@ msec_delay(1); timeout--; } - if (!timeout) { + if (!timeout) DEBUGOUT("MNG configuration cycle has not completed.\n"); - } /* If EEPROM is not marked present, init the PHY manually */ if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && - (hw->phy.type == e1000_phy_igp_3)) { + (hw->phy.type == e1000_phy_igp_3)) (void) e1000_phy_init_script_igp3(hw); - } + return (ret_val); } @@ -842,14 +853,12 @@ DEBUGFUNC("e1000_get_link_up_info_82575"); - if (hw->phy.media_type != e1000_media_type_copper || - e1000_sgmii_active_82575(hw)) { + if (hw->phy.media_type != e1000_media_type_copper) ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed, duplex); - } else { + else ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex); - } return (ret_val); } @@ -870,8 +879,7 @@ DEBUGFUNC("e1000_check_for_link_82575"); /* SGMII link check is done through the PCS register. */ - if ((hw->phy.media_type != e1000_media_type_copper) || - (e1000_sgmii_active_82575(hw))) { + if (hw->phy.media_type != e1000_media_type_copper) { ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed, &duplex); /* @@ -946,23 +954,28 @@ } /* - * e1000_shutdown_fiber_serdes_link_82575 - Remove link during power down + * e1000_shutdown_serdes_link_82575 - Remove link during power down * @hw: pointer to the HW structure * - * In the case of fiber serdes shut down optics and PCS on driver unload + * In the case of serdes shut down sfp and PCS on driver unload * when management pass thru is not enabled. */ void -e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw) +e1000_shutdown_serdes_link_82575(struct e1000_hw *hw) { u32 reg; u16 eeprom_data = 0; - if (hw->phy.media_type != e1000_media_type_internal_serdes) + if ((hw->phy.media_type != e1000_media_type_internal_serdes) && + !e1000_sgmii_active_82575(hw)) return; if (hw->bus.func == E1000_FUNC_0) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + else if (hw->mac.type == e1000_82580) + hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + + NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, + &eeprom_data); else if (hw->bus.func == E1000_FUNC_1) hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); @@ -979,58 +992,16 @@ /* shutdown the laser */ reg = E1000_READ_REG(hw, E1000_CTRL_EXT); - reg |= E1000_CTRL_EXT_SDP7_DATA; + reg |= E1000_CTRL_EXT_SDP3_DATA; E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); - /* flush the write to verfiy completion */ + /* flush the write to verify completion */ E1000_WRITE_FLUSH(hw); msec_delay(1); } } /* - * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback - * @hw: pointer to the HW structure - * @enable: state to enter, either enabled or disabled - * - * enables/disables L2 switch loopback functionality - */ -void -e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) -{ - u32 reg; - - reg = E1000_READ_REG(hw, E1000_DTXSWC); - if (enable) - reg |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; - else - reg &= ~(E1000_DTXSWC_VMDQ_LOOPBACK_EN); - - E1000_WRITE_REG(hw, E1000_DTXSWC, reg); -} - -/* - * e1000_vmdq_set_replication_pf - enable or disable vmdq replication - * @hw: pointer to the HW structure - * @enable: state to enter, either enabled or disabled - * - * enables/disables replication of packets across multiple pools - */ -void -e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) -{ - u32 reg; - - reg = E1000_READ_REG(hw, E1000_VT_CTL); - if (enable) - reg |= E1000_VT_CTL_VM_REPL_EN; - else - reg &= ~(E1000_VT_CTL_VM_REPL_EN); - - E1000_WRITE_REG(hw, E1000_VT_CTL, reg); -} - -/* * e1000_reset_hw_82575 - Reset hardware * @hw: pointer to the HW structure * @@ -1130,6 +1101,11 @@ for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); + /* Zero out the Unicast HASH table */ + DEBUGOUT("Zeroing the UTA\n"); + for (i = 0; i < mac->uta_reg_count; i++) + E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); + /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); @@ -1157,7 +1133,6 @@ { u32 ctrl; s32 ret_val; - bool link; DEBUGFUNC("e1000_setup_copper_link_82575"); @@ -1166,6 +1141,17 @@ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + ret_val = e1000_setup_serdes_link_82575(hw); + if (ret_val) + goto out; + + if (e1000_sgmii_active_82575(hw) && !hw->phy.reset_disable) { + ret_val = hw->phy.ops.reset(hw); + if (ret_val) { + DEBUGOUT("Error resetting the PHY.\n"); + goto out; + } + } switch (hw->phy.type) { case e1000_phy_m88: ret_val = e1000_copper_link_setup_m88(hw); @@ -1173,6 +1159,9 @@ case e1000_phy_igp_3: ret_val = e1000_copper_link_setup_igp(hw); break; + case e1000_phy_82580: + ret_val = e1000_copper_link_setup_82577(hw); + break; default: ret_val = -E1000_ERR_PHY; break; @@ -1181,67 +1170,30 @@ if (ret_val) goto out; - if (hw->mac.autoneg) { - /* - * Setup autoneg and flow control advertisement - * and perform autonegotiation. - */ - ret_val = e1000_copper_link_autoneg(hw); - if (ret_val) - goto out; - } else { - /* - * PHY will be set to 10H, 10F, 100H or 100F - * depending on user settings. - */ - DEBUGOUT("Forcing Speed and Duplex\n"); - ret_val = hw->phy.ops.force_speed_duplex(hw); - if (ret_val) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - goto out; - } - } - - ret_val = e1000_configure_pcs_link_82575(hw); - if (ret_val) - goto out; - - /* - * Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - ret_val = e1000_phy_has_link_generic(hw, - COPPER_LINK_UP_LIMIT, - 10, - &link); - if (ret_val) - goto out; - - if (link) { - DEBUGOUT("Valid link established!!!\n"); - /* Config the MAC and PHY after link is up */ - e1000_config_collision_dist_generic(hw); - ret_val = e1000_config_fc_after_link_up_generic(hw); - } else { - DEBUGOUT("Unable to establish link!!!\n"); - } - + ret_val = e1000_setup_copper_link_generic(hw); out: return (ret_val); } /* - * e1000_setup_fiber_serdes_link_82575 - Setup link for fiber/serdes + * e1000_setup_serdes_link_82575 - Setup link for serdes * @hw: pointer to the HW structure * - * Configures speed and duplex for fiber and serdes links. + * Configure the physical coding sub-layer (PCS) link. The PCS link is + * used on copper connections where the serialized gigabit media independent + * interface (sgmii), or serdes fiber is being used. Configures the link + * for auto-negotiation or forces speed/duplex. */ static s32 -e1000_setup_fiber_serdes_link_82575(struct e1000_hw *hw) +e1000_setup_serdes_link_82575(struct e1000_hw *hw) { - u32 reg; + u32 ctrl_reg, reg; + + DEBUGFUNC("e1000_setup_serdes_link_82575"); - DEBUGFUNC("e1000_setup_fiber_serdes_link_82575"); + if ((hw->phy.media_type != e1000_media_type_internal_serdes) && + !e1000_sgmii_active_82575(hw)) + return (E1000_SUCCESS); /* * On the 82575, SerDes loopback mode persists until it is @@ -1251,26 +1203,38 @@ */ E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - /* Force link up, set 1gb */ - reg = E1000_READ_REG(hw, E1000_CTRL); - reg |= E1000_CTRL_SLU | E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD; + /* power on the sfp cage if present */ + reg = E1000_READ_REG(hw, E1000_CTRL_EXT); + reg &= ~E1000_CTRL_EXT_SDP3_DATA; + E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + + ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); + ctrl_reg |= E1000_CTRL_SLU; + if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) { /* set both sw defined pins */ - reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; - } - E1000_WRITE_REG(hw, E1000_CTRL, reg); + ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; - /* Power on phy for 82576 fiber adapters */ - if (hw->mac.type == e1000_82576) { - reg = E1000_READ_REG(hw, E1000_CTRL_EXT); - reg &= ~E1000_CTRL_EXT_SDP7_DATA; - E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); + /* Set switch control to serdes energy detect */ + reg = E1000_READ_REG(hw, E1000_CONNSW); + reg |= E1000_CONNSW_ENRGSRC; + E1000_WRITE_REG(hw, E1000_CONNSW, reg); } - /* Set switch control to serdes energy detect */ - reg = E1000_READ_REG(hw, E1000_CONNSW); - reg |= E1000_CONNSW_ENRGSRC; - E1000_WRITE_REG(hw, E1000_CONNSW, reg); + reg = E1000_READ_REG(hw, E1000_PCS_LCTL); + + if (e1000_sgmii_active_82575(hw)) { + /* allow time for SFP cage to power up phy */ + msec_delay(300); + + /* AN time out should be disabled for SGMII mode */ + reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); + } else { + ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | + E1000_CTRL_FD | E1000_CTRL_FRCDPX; + } + + E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); /* * New SerDes mode allows for forcing speed or autonegotiating speed @@ -1278,35 +1242,54 @@ * mode that will be compatible with older link partners and switches. * However, both are supported by the hardware and some drivers/tools. */ - reg = E1000_READ_REG(hw, E1000_PCS_LCTL); reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - if (hw->mac.autoneg) { + /* + * We force flow control to prevent the CTRL register values from being + * overwritten by the autonegotiated flow control values + */ + reg |= E1000_PCS_LCTL_FORCE_FCTRL; + + /* + * we always set sgmii to autoneg since it is the phy that will be + * forcing the link and the serdes is just a go-between + */ + if (hw->mac.autoneg || e1000_sgmii_active_82575(hw)) { /* Set PCS register for autoneg */ - reg |= E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ - E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ - E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ - E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ - DEBUGOUT1("Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg); + reg |= E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ + E1000_PCS_LCTL_FDV_FULL | /* SerDes Full dplx */ + E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ + E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ + DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); } else { - /* Set PCS register for forced speed */ - reg |= E1000_PCS_LCTL_FLV_LINK_UP | /* Force link up */ - E1000_PCS_LCTL_FSV_1000 | /* Force 1000 */ - E1000_PCS_LCTL_FDV_FULL | /* SerDes Full duplex */ - E1000_PCS_LCTL_FSD | /* Force Speed */ - E1000_PCS_LCTL_FORCE_LINK; /* Force Link */ - DEBUGOUT1("Configuring Forced Link; PCS_LCTL = 0x%08X\n", reg); - } + /* Check for duplex first */ + if (hw->mac.forced_speed_duplex & E1000_ALL_FULL_DUPLEX) + reg |= E1000_PCS_LCTL_FDV_FULL; + + /* + * No need to check for 1000/full since the spec states that + * it requires autoneg to be enabled + */ - if (hw->mac.type == e1000_82576) { - reg |= E1000_PCS_LCTL_FORCE_FCTRL; - e1000_force_mac_fc_generic(hw); + /* Now set speed */ + if (hw->mac.forced_speed_duplex & E1000_ALL_100_SPEED) + reg |= E1000_PCS_LCTL_FSV_100; + + /* Force speed and force link */ + reg |= E1000_PCS_LCTL_FSD | + E1000_PCS_LCTL_FORCE_LINK | + E1000_PCS_LCTL_FLV_LINK_UP; + + DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); } E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); + if (!e1000_sgmii_active_82575(hw)) + (void) e1000_force_mac_fc_generic(hw); + return (E1000_SUCCESS); } @@ -1347,73 +1330,6 @@ } /* - * e1000_configure_pcs_link_82575 - Configure PCS link - * @hw: pointer to the HW structure - * - * Configure the physical coding sub-layer (PCS) link. The PCS link is - * only used on copper connections where the serialized gigabit media - * independent interface (sgmii) is being used. Configures the link - * for auto-negotiation or forces speed/duplex. - */ -static s32 -e1000_configure_pcs_link_82575(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg = 0; - - DEBUGFUNC("e1000_configure_pcs_link_82575"); - - if (hw->phy.media_type != e1000_media_type_copper || - !(e1000_sgmii_active_82575(hw))) - goto out; - - /* For SGMII, we need to issue a PCS autoneg restart */ - reg = E1000_READ_REG(hw, E1000_PCS_LCTL); - - /* AN time out should be disabled for SGMII mode */ - reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); - - if (mac->autoneg) { - /* Make sure forced speed and force link are not set */ - reg &= ~(E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); - - /* - * The PHY should be setup prior to calling this function. - * All we need to do is restart autoneg and enable autoneg. - */ - reg |= E1000_PCS_LCTL_AN_RESTART | E1000_PCS_LCTL_AN_ENABLE; - } else { - /* Set PCS register for forced speed */ - - /* Turn off bits for full duplex, speed, and autoneg */ - reg &= ~(E1000_PCS_LCTL_FSV_1000 | - E1000_PCS_LCTL_FSV_100 | - E1000_PCS_LCTL_FDV_FULL | - E1000_PCS_LCTL_AN_ENABLE); - - /* Check for duplex first */ - if (mac->forced_speed_duplex & E1000_ALL_FULL_DUPLEX) - reg |= E1000_PCS_LCTL_FDV_FULL; - - /* Now set speed */ - if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) - reg |= E1000_PCS_LCTL_FSV_100; - - /* Force speed and force link */ - reg |= E1000_PCS_LCTL_FSD | - E1000_PCS_LCTL_FORCE_LINK | - E1000_PCS_LCTL_FLV_LINK_UP; - - DEBUGOUT1("Wrote 0x%08X to PCS_LCTL to configure forced link\n", - reg); - } - E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); - -out: - return (E1000_SUCCESS); -} - -/* * e1000_sgmii_active_82575 - Return sgmii state * @hw: pointer to the HW structure * @@ -1588,7 +1504,8 @@ (void) E1000_READ_REG(hw, E1000_LENERRS); /* This register should not be read in copper configurations */ - if (hw->phy.media_type == e1000_media_type_internal_serdes) + if ((hw->phy.media_type == e1000_media_type_internal_serdes) || + e1000_sgmii_active_82575(hw)) (void) E1000_READ_REG(hw, E1000_SCVPC); } @@ -1720,3 +1637,226 @@ E1000_WRITE_REG(hw, E1000_GCR, gcr); return (ret_val); } + +/* + * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback + * @hw: pointer to the hardware struct + * @enable: state to enter, either enabled or disabled + * + * enables/disables L2 switch loopback functionality. + */ +void +e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) +{ + u32 dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); + + if (enable) + dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; + else + dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; + + E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); +} + +/* + * e1000_vmdq_set_replication_pf - enable or disable vmdq replication + * @hw: pointer to the hardware struct + * @enable: state to enter, either enabled or disabled + * + * enables/disables replication of packets across multiple pools. + */ +void +e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) +{ + u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); + + if (enable) + vt_ctl |= E1000_VT_CTL_VM_REPL_EN; + else + vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; + + E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); +} + +/* + * e1000_read_phy_reg_82580 - Read 82580 MDI control register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the MDI control register in the PHY at offset and stores the + * information read to data. + */ +static s32 +e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) +{ + u32 mdicnfg = 0; + s32 ret_val; + + DEBUGFUNC("e1000_read_phy_reg_82580"); + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + /* + * We config the phy address in MDICNFG register now. Same bits + * as before. The values in MDIC can be written but will be + * ignored. This allows us to call the old function after + * configuring the PHY address in the new register + */ + mdicnfg = (hw->phy.addr << E1000_MDIC_PHY_SHIFT); + E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); + + ret_val = e1000_read_phy_reg_mdic(hw, offset, data); + + hw->phy.ops.release(hw); + +out: + return (ret_val); +} + +/* + * e1000_write_phy_reg_82580 - Write 82580 MDI control register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write to register at offset + * + * Writes data to MDI control register in the PHY at offset. + */ +static s32 +e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data) +{ + u32 mdicnfg = 0; + s32 ret_val; + + DEBUGFUNC("e1000_write_phy_reg_82580"); + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + + /* + * We config the phy address in MDICNFG register now. Same bits + * as before. The values in MDIC can be written but will be + * ignored. This allows us to call the old function after + * configuring the PHY address in the new register + */ + mdicnfg = (hw->phy.addr << E1000_MDIC_PHY_SHIFT); + E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); + + ret_val = e1000_write_phy_reg_mdic(hw, offset, data); + + hw->phy.ops.release(hw); + +out: + return (ret_val); +} + +/* + * e1000_reset_hw_82580 - Reset hardware + * @hw: pointer to the HW structure + * + * This resets function or entire device (all ports, etc.) + * to a known state. + */ +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; + bool global_device_reset = hw->dev_spec._82575.global_device_reset; + + DEBUGFUNC("e1000_reset_hw_82580"); + + hw->dev_spec._82575.global_device_reset = false; + + /* Get current control state. */ + ctrl = E1000_READ_REG(hw, E1000_CTRL); + + /* + * Prevent the PCI-E bus from sticking if there is no TLP connection + * on the last TLP read/write transaction when MAC is reset. + */ + ret_val = e1000_disable_pcie_master_generic(hw); + if (ret_val) + DEBUGOUT("PCI-E Master disable polling has failed.\n"); + + DEBUGOUT("Masking off all interrupts\n"); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + E1000_WRITE_REG(hw, E1000_RCTL, 0); + E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); + E1000_WRITE_FLUSH(hw); + + msec_delay(10); + + /* Determine whether or not a global dev reset is requested */ + if (global_device_reset && + e1000_acquire_swfw_sync_82575(hw, swmbsw_mask)) + global_device_reset = false; + + if (global_device_reset && + !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STAT_DEV_RST_SET)) + ctrl |= E1000_CTRL_DEV_RST; + else + ctrl |= E1000_CTRL_RST; + + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + + /* Add delay to insure DEV_RST has time to complete */ + if (global_device_reset) + msec_delay(5); + + ret_val = e1000_get_auto_rd_done_generic(hw); + if (ret_val) { + /* + * When auto config read does not complete, do not + * return with an error. This can happen in situations + * where there is no eeprom and prevents getting link. + */ + DEBUGOUT("Auto Read Done did not complete\n"); + } + + /* If EEPROM is not present, run manual init scripts */ + if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) + e1000_reset_init_script_82575(hw); + + /* clear global device reset status bit */ + E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); + + /* Clear any pending interrupt events. */ + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); + (void) E1000_READ_REG(hw, E1000_ICR); + + /* Install any alternate MAC address into RAR0 */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + + /* Release semaphore */ + if (global_device_reset) + e1000_release_swfw_sync_82575(hw, swmbsw_mask); + + return (ret_val); +} + +/* + * 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. + * This function converts the retrieved value into the correct table value + * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 + * 0x0 36 72 144 1 2 4 8 16 + * 0x8 35 70 140 rsv rsv rsv rsv rsv + */ +u16 +e1000_rxpbs_adjust_82580(u32 data) +{ + u16 ret_val = 0; + + if (data < E1000_82580_RXPBS_TABLE_SIZE) + ret_val = e1000_82580_rxpbs_table[data]; + + return (ret_val); +}
--- a/usr/src/uts/common/io/igb/igb_82575.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_82575.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.77 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.85 scm_100809_154340 */ #ifndef _IGB_82575_H #define _IGB_82575_H @@ -52,10 +52,14 @@ */ #define E1000_RAR_ENTRIES_82575 16 #define E1000_RAR_ENTRIES_82576 24 +#define E1000_RAR_ENTRIES_82580 24 +#define E1000_SW_SYNCH_MB 0x00000100 +#define E1000_STAT_DEV_RST_SET 0x00100000 +#define E1000_CTRL_DEV_RST 0x20000000 #ifdef E1000_BIT_FIELDS struct e1000_adv_data_desc { - u64 buffer_addr; /* Address of the descriptor's data buffer */ + __le64 buffer_addr; /* Address of the descriptor's data buffer */ union { u32 data; struct { @@ -129,6 +133,7 @@ #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000 #define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 #define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000 +#define E1000_SRRCTL_TIMESTAMP 0x40000000 #define E1000_SRRCTL_DROP_EN 0x80000000 #define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F @@ -143,6 +148,7 @@ #define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000 #define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000 +#define E1000_MRQC_ENABLE_RSS_8Q 0x00000002 #define E1000_VMRCTL_MIRROR_PORT_SHIFT 8 #define E1000_VMRCTL_MIRROR_DSTPORT_MASK (7 << E1000_VMRCTL_MIRROR_PORT_SHIFT) @@ -186,32 +192,32 @@ /* Receive Descriptor - Advanced */ union e1000_adv_rx_desc { struct { - u64 pkt_addr; /* Packet buffer address */ - u64 hdr_addr; /* Header buffer address */ + __le64 pkt_addr; /* Packet buffer address */ + __le64 hdr_addr; /* Header buffer address */ } read; struct { struct { union { - u32 data; + __le32 data; struct { /* RSS type, Packet type */ - u16 pkt_info; + __le16 pkt_info; /* Split Header, header buffer length */ - u16 hdr_info; + __le16 hdr_info; } hs_rss; } lo_dword; union { - u32 rss; /* RSS Hash */ + __le32 rss; /* RSS Hash */ struct { - u16 ip_id; /* IP id */ - u16 csum; /* Packet Checksum */ + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ } csum_ip; } hi_dword; } lower; struct { - u32 status_error; /* ext status/error */ - u16 length; /* Packet length */ - u16 vlan; /* VLAN tag */ + __le32 status_error; /* ext status/error */ + __le16 length; /* Packet length */ + __le16 vlan; /* VLAN tag */ } upper; } wb; /* writeback */ }; @@ -222,6 +228,8 @@ #define E1000_RXDADV_HDRBUFLEN_SHIFT 5 #define E1000_RXDADV_SPLITHEADER_EN 0x00001000 #define E1000_RXDADV_SPH 0x8000 +#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */ +#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */ #define E1000_RXDADV_ERR_HBO 0x00800000 /* RSS Hash results */ @@ -271,14 +279,14 @@ /* Transmit Descriptor - Advanced */ union e1000_adv_tx_desc { struct { - u64 buffer_addr; /* Address of descriptor's data buf */ - u32 cmd_type_len; - u32 olinfo_status; + __le64 buffer_addr; /* Address of descriptor's data buf */ + __le32 cmd_type_len; + __le32 olinfo_status; } read; struct { - u64 rsvd; /* Reserved */ - u32 nxtseq_seed; - u32 status; + __le64 rsvd; /* Reserved */ + __le32 nxtseq_seed; + __le32 status; } wb; }; @@ -306,10 +314,10 @@ /* Context descriptors */ struct e1000_adv_tx_context_desc { - u32 vlan_macip_lens; - u32 seqnum_seed; - u32 type_tucmd_mlhl; - u32 mss_l4len_idx; + __le32 vlan_macip_lens; + __le32 seqnum_seed; + __le32 type_tucmd_mlhl; + __le32 mss_l4len_idx; }; #define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ @@ -386,6 +394,14 @@ */ #define E1000_ETQF_FILTER_EAPOL 0 +#define E1000_FTQF_VF_BP 0x00008000 +#define E1000_FTQF_1588_TIME_STAMP 0x08000000 +#define E1000_FTQF_MASK 0xF0000000 +#define E1000_FTQF_MASK_PROTO_BP 0x10000000 +#define E1000_FTQF_MASK_SOURCE_ADDR_BP 0x20000000 +#define E1000_FTQF_MASK_DEST_ADDR_BP 0x40000000 +#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000 + #define E1000_NVM_APME_82575 0x0400 #define MAX_NUM_VFS 8 @@ -432,11 +448,21 @@ #define E1000_IOVCTL_REUSE_VFQ 0x00000001 #define E1000_RPLOLR_STRVLAN 0x40000000 +#define E1000_RPLOLR_STRCRC 0x80000000 + +#define E1000_DTXCTL_8023LL 0x0004 +#define E1000_DTXCTL_VLAN_ADDED 0x0008 +#define E1000_DTXCTL_OOS_ENABLE 0x0010 +#define E1000_DTXCTL_MDP_EN 0x0020 +#define E1000_DTXCTL_SPOOF_INT 0x0040 #define ALL_QUEUES 0xFFFF +/* 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_replication_pf(struct e1000_hw *hw, bool enable); +u16 e1000_rxpbs_adjust_82580(u32 data); #ifdef __cplusplus }
--- a/usr/src/uts/common/io/igb/igb_api.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_api.c Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.122 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.128 scm_100809_154340 */ #include "igb_api.h" @@ -139,9 +139,17 @@ case E1000_DEV_ID_82576_SERDES: case E1000_DEV_ID_82576_QUAD_COPPER: case E1000_DEV_ID_82576_NS: + case E1000_DEV_ID_82576_NS_SERDES: case E1000_DEV_ID_82576_SERDES_QUAD: mac->type = e1000_82576; break; + case E1000_DEV_ID_82580_COPPER: + case E1000_DEV_ID_82580_FIBER: + case E1000_DEV_ID_82580_SERDES: + case E1000_DEV_ID_82580_SGMII: + case E1000_DEV_ID_82580_COPPER_DUAL: + mac->type = e1000_82580; + break; default: /* Should never have loaded on this device */ ret_val = -E1000_ERR_MAC_INIT; @@ -197,6 +205,7 @@ switch (hw->mac.type) { case e1000_82575: case e1000_82576: + case e1000_82580: e1000_init_function_pointers_82575(hw); break; default:
--- a/usr/src/uts/common/io/igb/igb_api.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_api.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.52 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.53 scm_100809_154340 */ #ifndef _IGB_API_H #define _IGB_API_H
--- a/usr/src/uts/common/io/igb/igb_defines.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_defines.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.111 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.119 scm_100809_154340 */ #ifndef _IGB_DEFINES_H #define _IGB_DEFINES_H @@ -118,12 +118,12 @@ #define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Definable Pin 5 */ #define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA #define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Definable Pin 6 */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */ +#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */ /* SDP 4/5 (bits 8,9) are reserved in >= 82575 */ #define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ #define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ #define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ -#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ +#define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */ #define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ #define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ @@ -134,6 +134,8 @@ /* DMA Dynamic Clock Gating */ #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 +#define E1000_CTRL_EXT_LINK_MODE_82580_MASK 0x01C00000 /* 82580 bit 24:22 */ +#define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX 0x00400000 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 #define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 #define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 @@ -353,6 +355,8 @@ #define E1000_SWFW_PHY0_SM 0x2 #define E1000_SWFW_PHY1_SM 0x4 #define E1000_SWFW_CSR_SM 0x8 +#define E1000_SWFW_PHY2_SM 0x20 +#define E1000_SWFW_PHY3_SM 0x40 /* FACTPS Definitions */ #define E1000_FACTPS_LFS 0x40000000 /* LAN Function Select */ @@ -654,6 +658,7 @@ /* Extended Configuration Control and Size */ #define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 +#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 @@ -727,6 +732,7 @@ #define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ #define E1000_ICR_MNG 0x00040000 /* Manageability event */ #define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ +#define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */ /* If this bit asserted, the driver should claim the interrupt */ #define E1000_ICR_INT_ASSERTED 0x80000000 #define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* Q0 Rx desc FIFO parity error */ @@ -742,6 +748,7 @@ #define E1000_ICR_PHYINT 0x00001000 #define E1000_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */ #define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ +#define E1000_ICR_FER 0x00400000 /* Fatal Error */ /* Extended Interrupt Cause Read */ #define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ @@ -806,6 +813,7 @@ #define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_IMS_DRSTA E1000_ICR_DRSTA /* Device Reset Asserted */ /* queue 0 Rx descriptor FIFO parity error */ #define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ @@ -822,6 +830,7 @@ #define E1000_IMS_PHYINT E1000_ICR_PHYINT #define E1000_IMS_DOUTSYNC E1000_ICR_DOUTSYNC /* NIC DMA out of sync */ #define E1000_IMS_EPRST E1000_ICR_EPRST +#define E1000_IMS_FER E1000_ICR_FER /* Fatal Error */ /* Extended Interrupt Mask Set */ #define E1000_EIMS_RX_QUEUE0 E1000_EICR_RX_QUEUE0 /* Rx Queue 0 Interrupt */ @@ -854,6 +863,7 @@ #define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ #define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ #define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ +#define E1000_ICS_DRSTA E1000_ICR_DRSTA /* Device Reset Aserted */ /* queue 0 Rx descriptor FIFO parity error */ #define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ @@ -977,6 +987,25 @@ #define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ #define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ +/* TUPLE Filtering Configuration */ +#define E1000_TTQF_DISABLE_MASK 0xF0008000 /* TTQF Disable Mask */ +#define E1000_TTQF_QUEUE_ENABLE 0x100 /* TTQF Queue Enable Bit */ +#define E1000_TTQF_PROTOCOL_MASK 0xFF /* TTQF Protocol Mask */ +/* TTQF TCP Bit, shift with E1000_TTQF_PROTOCOL SHIFT */ +#define E1000_TTQF_PROTOCOL_TCP 0x0 +/* TTQF UDP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */ +#define E1000_TTQF_PROTOCOL_UDP 0x1 +/* TTQF SCTP Bit, shift with E1000_TTQF_PROTOCOL_SHIFT */ +#define E1000_TTQF_PROTOCOL_SCTP 0x2 +#define E1000_TTQF_PROTOCOL_SHIFT 5 /* TTQF Protocol Shift */ +#define E1000_TTQF_QUEUE_SHIFT 16 /* TTQF Queue Shfit */ +#define E1000_TTQF_RX_QUEUE_MASK 0x70000 /* TTQF Queue Mask */ +#define E1000_TTQF_MASK_ENABLE 0x10000000 /* TTQF Mask Enable Bit */ +#define E1000_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */ +#define E1000_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */ +#define E1000_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */ +#define E1000_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */ + /* PCI Express Control */ #define E1000_GCR_RXD_NO_SNOOP 0x00000001 #define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 @@ -1167,6 +1196,10 @@ #define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */ #define E1000_NVM_CFG_DONE_PORT_1 0x80000 /* ...for second port */ +#define E1000_NVM_CFG_DONE_PORT_2 0x100000 /* ...for third port */ +#define E1000_NVM_CFG_DONE_PORT_3 0x200000 /* ...for fourth port */ + +#define NVM_82580_LAN_FUNC_OFFSET(a) (a ? (0x40 + (0x40 * a)) : 0) /* Mask bits for fields in Word 0x0f of the NVM */ #define NVM_WORD0F_PAUSE_MASK 0x3000 @@ -1272,6 +1305,7 @@ #define IFE_E_PHY_ID 0x02A80330 #define IFE_PLUS_E_PHY_ID 0x02A80320 #define IFE_C_E_PHY_ID 0x02A80310 +#define I82580_I_PHY_ID 0x015403A0 #define IGP04E1000_E_PHY_ID 0x02A80391 #define M88_VENDOR 0x0141 @@ -1494,6 +1528,34 @@ #define E1000_LSECRXCTRL_RP 0x00000080 #define E1000_LSECRXCTRL_RSV_MASK 0xFFFFFF33 +/* DMA Coalescing register fields */ + +/* DMA Coalescing Watchdog Timer */ +#define E1000_DMACR_DMACWT_MASK 0x00003FFF +/* DMA Coalescing Receive Threshold */ +#define E1000_DMACR_DMACTHR_MASK 0x00FF0000 +#define E1000_DMACR_DMACTHR_SHIFT 16 +/* Lx when no PCIe transactions */ +#define E1000_DMACR_DMAC_LX_MASK 0x30000000 +#define E1000_DMACR_DMAC_LX_SHIFT 28 +/* Enable DMA Coalescing */ +#define E1000_DMACR_DMAC_EN 0x80000000 +/* DMA Coalescing Transmit Threshold */ +#define E1000_DMCTXTH_DMCTTHR_MASK 0x00000FFF +/* Time to LX request */ +#define E1000_DMCTLX_TTLX_MASK 0x00000FFF +/* Receive Traffic Rate Threshold */ +#define E1000_DMCRTRH_UTRESH_MASK 0x0007FFFF +/* Rcv packet rate in current window */ +#define E1000_DMCRTRH_LRPRCW 0x80000000 +/* DMA Coal Rcv Traffic Current Cnt */ +#define E1000_DMCCNT_CCOUNT_MASK 0x01FFFFFF +/* Flow ctrl Rcv Threshold High val */ +#define E1000_FCRTC_RTH_COAL_MASK 0x0003FFF0 +#define E1000_FCRTC_RTH_COAL_SHIFT 4 +/* Lx power decision based on DMA coal */ +#define E1000_PCIEMISC_LX_DECISION 0x00000080 + #ifdef __cplusplus } #endif
--- a/usr/src/uts/common/io/igb/igb_hw.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_hw.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.398 v2008-10-7 */ +/* IntelVersion: 1.444 scm_100809_154340 */ #ifndef _IGB_HW_H #define _IGB_HW_H @@ -46,10 +46,16 @@ #define E1000_DEV_ID_82576_SERDES 0x10E7 #define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 #define E1000_DEV_ID_82576_NS 0x150A +#define E1000_DEV_ID_82576_NS_SERDES 0x1518 #define E1000_DEV_ID_82576_SERDES_QUAD 0x150D #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 +#define E1000_DEV_ID_82580_COPPER 0x150E +#define E1000_DEV_ID_82580_FIBER 0x150F +#define E1000_DEV_ID_82580_SERDES 0x1510 +#define E1000_DEV_ID_82580_SGMII 0x1511 +#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516 #define E1000_REVISION_0 0 #define E1000_REVISION_1 1 @@ -59,13 +65,19 @@ #define E1000_FUNC_0 0 #define E1000_FUNC_1 1 +#define E1000_FUNC_2 2 +#define E1000_FUNC_3 3 + #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 #define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 +#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6 +#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9 enum e1000_mac_type { e1000_undefined = 0, e1000_82575, e1000_82576, + e1000_82580, e1000_num_macs /* List is 1-based, so subtract 1 for true count. */ }; @@ -103,6 +115,7 @@ e1000_phy_gg82563, e1000_phy_igp_3, e1000_phy_ife, + e1000_phy_82580, e1000_phy_vf }; @@ -490,11 +503,13 @@ s32 (*get_cable_length)(struct e1000_hw *); s32 (*get_info)(struct e1000_hw *); s32 (*read_reg)(struct e1000_hw *, u32, u16 *); + s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); void (*release)(struct e1000_hw *); s32 (*reset)(struct e1000_hw *); s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); s32 (*write_reg)(struct e1000_hw *, u32, u16); + s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); void (*power_up)(struct e1000_hw *); void (*power_down)(struct e1000_hw *); }; @@ -532,6 +547,7 @@ u16 ifs_ratio; u16 ifs_step_size; u16 mta_reg_count; + u16 uta_reg_count; /* Maximum size of the MTA register table in all supported adapters */ #define MAX_MTA_REG 128
--- a/usr/src/uts/common/io/igb/igb_mac.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_mac.c Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.104 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.108 scm_100809_154340 */ #include "igb_api.h" @@ -346,6 +346,10 @@ if (hw->bus.func == E1000_FUNC_1) nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; + if (hw->bus.func == E1000_FUNC_2) + nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN2; + if (hw->bus.func == E1000_FUNC_3) + nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN3; for (i = 0; i < ETH_ADDR_LEN; i += 2) { offset = nvm_alt_mac_addr_offset + (i >> 1); ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); @@ -2074,7 +2078,7 @@ * Verify that when not using auto-negotiation that MDI/MDIx is correctly * set, which is forced to MDI mode only. */ -s32 +static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw) { s32 ret_val = E1000_SUCCESS;
--- a/usr/src/uts/common/io/igb/igb_mac.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_mac.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.32 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.32 scm_100809_154340 */ #ifndef _IGB_MAC_H #define _IGB_MAC_H
--- a/usr/src/uts/common/io/igb/igb_main.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_main.c Mon Nov 23 14:27:01 2009 +0800 @@ -29,7 +29,7 @@ #include "igb_sw.h" static char ident[] = "Intel 1Gb Ethernet"; -static char igb_version[] = "igb 1.1.8"; +static char igb_version[] = "igb 1.1.9"; /* * Local function protoypes @@ -74,6 +74,7 @@ static void igb_disable_adapter_interrupts(igb_t *); static void igb_enable_adapter_interrupts_82575(igb_t *); static void igb_enable_adapter_interrupts_82576(igb_t *); +static void igb_enable_adapter_interrupts_82580(igb_t *); static boolean_t is_valid_mac_addr(uint8_t *); static boolean_t igb_stall_check(igb_t *); static boolean_t igb_set_loopback_mode(igb_t *, uint32_t); @@ -91,6 +92,7 @@ static int igb_disable_intrs(igb_t *); static void igb_setup_msix_82575(igb_t *); static void igb_setup_msix_82576(igb_t *); +static void igb_setup_msix_82580(igb_t *); static uint_t igb_intr_legacy(void *, void *); static uint_t igb_intr_msi(void *, void *); static uint_t igb_intr_rx(void *, void *); @@ -233,6 +235,30 @@ 0xffe00000 /* mask for RXDCTL register */ }; +static adapter_info_t igb_82580_cap = { + /* limits */ + 8, /* maximum number of rx queues */ + 1, /* minimum number of rx queues */ + 4, /* default number of rx queues */ + 8, /* maximum number of tx queues */ + 1, /* minimum number of tx queues */ + 4, /* default number of tx queues */ + 65535, /* maximum interrupt throttle rate */ + 0, /* minimum interrupt throttle rate */ + 200, /* default interrupt throttle rate */ + + /* function pointers */ + igb_enable_adapter_interrupts_82580, + igb_setup_msix_82580, + + /* capabilities */ + (IGB_FLAG_HAS_DCA | /* capability flags */ + IGB_FLAG_VMDQ_POOL | + IGB_FLAG_NEED_CTX_IDX), + + 0xffe00000 /* mask for RXDCTL register */ +}; + /* * Module Initialization Functions */ @@ -812,6 +838,9 @@ case e1000_82576: igb->capab = &igb_82576_cap; break; + case e1000_82580: + igb->capab = &igb_82580_cap; + break; default: return (IGB_FAILURE); } @@ -1257,7 +1286,7 @@ hw->fc.pause_time = E1000_FC_PAUSE_TIME; hw->fc.send_xon = B_TRUE; - e1000_validate_mdi_setting(hw); + (void) e1000_validate_mdi_setting(hw); /* * Reset the chipset hardware the second time to put PBA settings @@ -1915,31 +1944,15 @@ * wakeup but leave this here for completeness. */ rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - - switch (hw->mac.type) { - case e1000_82575: - rctl |= (E1000_RCTL_EN | /* Enable Receive Unit */ - E1000_RCTL_BAM | /* Accept Broadcast Packets */ - E1000_RCTL_LPE | /* Large Packet Enable */ - /* Multicast filter offset */ - (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) | - E1000_RCTL_RDMTS_HALF | /* rx descriptor threshold */ - E1000_RCTL_SECRC); /* Strip Ethernet CRC */ - break; - - case e1000_82576: - rctl |= (E1000_RCTL_EN | /* Enable Receive Unit */ - E1000_RCTL_BAM | /* Accept Broadcast Packets */ - E1000_RCTL_LPE | /* Large Packet Enable */ - /* Multicast filter offset */ - (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) | - E1000_RCTL_SECRC); /* Strip Ethernet CRC */ - break; - - default: - igb_log(igb, "unsupported MAC type: %d", hw->mac.type); - return; /* should never come here; this will cause rx failure */ - } + rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); + + rctl |= (E1000_RCTL_EN | /* Enable Receive Unit */ + E1000_RCTL_BAM | /* Accept Broadcast Packets */ + E1000_RCTL_LPE | /* Large Packet Enable */ + /* Multicast filter offset */ + (hw->mac.mc_filter_type << E1000_RCTL_MO_SHIFT) | + E1000_RCTL_RDMTS_HALF | /* rx descriptor threshold */ + E1000_RCTL_SECRC); /* Strip Ethernet CRC */ for (i = 0; i < igb->num_rx_groups; i++) { rx_group = &igb->rx_groups[i]; @@ -2175,7 +2188,7 @@ /* Setup the Redirection Table */ if (hw->mac.type == e1000_82576) { - shift = 0; + shift = 3; } else if (hw->mac.type == e1000_82575) { shift = 6; } @@ -2683,10 +2696,10 @@ igb->num_rx_groups = igb_get_prop(igb, PROP_RX_GROUP_NUM, MIN_RX_GROUP_NUM, MAX_RX_GROUP_NUM, DEFAULT_RX_GROUP_NUM); /* - * Currently we do not support VMDq for 82576. + * Currently we do not support VMDq for 82576 and 82580. * If it is e1000_82576, set num_rx_groups to 1. */ - if (hw->mac.type == e1000_82576) + if (hw->mac.type >= e1000_82576) igb->num_rx_groups = 1; if (igb->mr_enable) { @@ -2998,8 +3011,8 @@ /* * igb_local_timer - driver watchdog function * - * This function will handle the transmit stall check, link status check and - * other routines. + * This function will handle the hardware stall check, link status + * check and other routines. */ static void igb_local_timer(void *arg) @@ -3007,10 +3020,14 @@ igb_t *igb = (igb_t *)arg; boolean_t link_changed = B_FALSE; - if (igb_stall_check(igb)) { + if (igb_stall_check(igb)) + igb->igb_state |= IGB_STALL; + + if (igb->igb_state & IGB_STALL) { igb_fm_ereport(igb, DDI_FM_DEVICE_STALL); ddi_fm_service_impact(igb->dip, DDI_SERVICE_LOST); igb->reset_count++; + igb->igb_state &= ~IGB_STALL; if (igb_reset(igb) == IGB_SUCCESS) ddi_fm_service_impact(igb->dip, DDI_SERVICE_RESTORED); @@ -3045,6 +3062,7 @@ igb_stall_check(igb_t *igb) { igb_tx_ring_t *tx_ring; + struct e1000_hw *hw = &igb->hw; boolean_t result; int i; @@ -3065,6 +3083,10 @@ if (tx_ring->stall_watchdog >= STALL_WATCHDOG_TIMEOUT) { result = B_TRUE; + if (hw->mac.type == e1000_82580) { + hw->dev_spec._82575.global_device_reset + = B_TRUE; + } break; } } @@ -3307,6 +3329,38 @@ } /* + * igb_enable_adapter_interrupts_82580 - Enable NIC interrupts for 82580 + */ +static void +igb_enable_adapter_interrupts_82580(igb_t *igb) +{ + struct e1000_hw *hw = &igb->hw; + + /* Clear any pending interrupts */ + (void) E1000_READ_REG(hw, E1000_ICR); + igb->ims_mask |= E1000_IMS_DRSTA; + + if (igb->intr_type == DDI_INTR_TYPE_MSIX) { + + /* Interrupt enabling for MSI-X */ + E1000_WRITE_REG(hw, E1000_EIMS, igb->eims_mask); + E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask); + igb->ims_mask = (E1000_IMS_LSC | E1000_IMS_DRSTA); + E1000_WRITE_REG(hw, E1000_IMS, igb->ims_mask); + } else { /* Interrupt enabling for MSI and legacy */ + E1000_WRITE_REG(hw, E1000_IVAR0, E1000_IVAR_VALID); + igb->ims_mask = IMS_ENABLE_MASK | E1000_IMS_TXQE; + igb->ims_mask |= E1000_IMS_DRSTA; + E1000_WRITE_REG(hw, E1000_IMS, igb->ims_mask); + } + + /* Disable auto-mask for ICR interrupt bits */ + E1000_WRITE_REG(hw, E1000_IAM, 0); + + E1000_WRITE_FLUSH(hw); +} + +/* * igb_enable_adapter_interrupts_82576 - Enable NIC interrupts for 82576 */ static void @@ -3816,6 +3870,11 @@ igb_get_phy_state(igb); } + if (icr & E1000_ICR_DRSTA) { + /* 82580 Full Device Reset needed */ + igb->igb_state |= IGB_STALL; + } + result = DDI_INTR_CLAIMED; } else { /* @@ -3880,6 +3939,11 @@ igb_intr_link_work(igb); } + if (icr & E1000_ICR_DRSTA) { + /* 82580 Full Device Reset needed */ + igb->igb_state |= IGB_STALL; + } + return (DDI_INTR_CLAIMED); } @@ -3961,6 +4025,11 @@ IGB_STAT(igb->dout_sync); } + if (icr & E1000_ICR_DRSTA) { + /* 82580 Full Device Reset needed */ + igb->igb_state |= IGB_STALL; + } + return (DDI_INTR_CLAIMED); } @@ -4481,6 +4550,96 @@ } /* + * igb_setup_msix_82580 - setup 82580 adapter to use MSI-X interrupts + * + * 82580 uses same table approach at 82576 but has fewer entries. Each + * queue has a single entry in the table to which we write a vector number + * along with a "valid" bit. Vectors take a different position in the + * register depending on * whether * they are numbered above or below 4. + */ +static void +igb_setup_msix_82580(igb_t *igb) +{ + struct e1000_hw *hw = &igb->hw; + uint32_t ivar, index, vector; + int i; + + /* must enable msi-x capability before IVAR settings */ + E1000_WRITE_REG(hw, E1000_GPIE, (E1000_GPIE_MSIX_MODE | + E1000_GPIE_PBA | E1000_GPIE_NSICR | E1000_GPIE_EIAME)); + /* + * Set vector for tx ring 0 and other causes. + * NOTE assumption that it is vector 0. + * This is also interdependent with installation of interrupt service + * routines in igb_add_intr_handlers(). + */ + + /* assign "other" causes to vector 0 */ + vector = 0; + ivar = ((vector | E1000_IVAR_VALID) << 8); + E1000_WRITE_REG(hw, E1000_IVAR_MISC, ivar); + + /* assign tx ring 0 to vector 0 */ + ivar = ((vector | E1000_IVAR_VALID) << 8); + E1000_WRITE_REG(hw, E1000_IVAR0, ivar); + + /* prepare to enable tx & other interrupt causes */ + igb->eims_mask = (1 << vector); + + vector ++; + + for (i = 0; i < igb->num_rx_rings; i++) { + /* + * Set vector for each rx ring + */ + index = (i >> 1); + ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index); + + if (i & 1) { + /* vector goes into third byte of register */ + ivar = ivar & 0xFF00FFFF; + ivar |= ((vector | E1000_IVAR_VALID) << 16); + } else { + /* vector goes into low byte of register */ + ivar = ivar & 0xFFFFFF00; + ivar |= (vector | E1000_IVAR_VALID); + } + E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar); + + /* Accumulate interrupt-cause bits to enable */ + igb->eims_mask |= (1 << vector); + + vector ++; + } + + for (i = 1; i < igb->num_tx_rings; i++) { + /* + * Set vector for each tx ring from 2nd tx ring. + * Note assumption that tx vectors numericall follow rx vectors. + */ + index = (i >> 1); + ivar = E1000_READ_REG_ARRAY(hw, E1000_IVAR0, index); + + if (i & 1) { + /* vector goes into high byte of register */ + ivar = ivar & 0x00FFFFFF; + ivar |= ((vector | E1000_IVAR_VALID) << 24); + } else { + /* vector goes into second byte of register */ + ivar = ivar & 0xFFFF00FF; + ivar |= (vector | E1000_IVAR_VALID) << 8; + } + E1000_WRITE_REG_ARRAY(hw, E1000_IVAR0, index, ivar); + + /* Accumulate interrupt-cause bits to enable */ + igb->eims_mask |= (1 << vector); + + vector ++; + } + ASSERT(vector == igb->intr_cnt); +} + +/* * igb_rem_intr_handlers - remove the interrupt handlers */ static void
--- a/usr/src/uts/common/io/igb/igb_manage.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_manage.c Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.27 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.27 scm_100809_154340 */ #include "igb_api.h"
--- a/usr/src/uts/common/io/igb/igb_manage.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_manage.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.18 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.18 scm_100809_154340 */ #ifndef _IGB_MANAGE_H #define _IGB_MANAGE_H
--- a/usr/src/uts/common/io/igb/igb_nvm.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_nvm.c Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.49 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.49 scm_100809_154340 */ #include "igb_api.h"
--- a/usr/src/uts/common/io/igb/igb_nvm.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_nvm.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.18 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.18 scm_100809_154340 */ #ifndef _IGB_NVM_H #define _IGB_NVM_H
--- a/usr/src/uts/common/io/igb/igb_osdep.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_osdep.h Mon Nov 23 14:27:01 2009 +0800 @@ -69,7 +69,7 @@ #define DEBUGOUT3(S, A, B, C) #endif -#define DEBUGFUNC(F) +#define DEBUGFUNC(f) #define OS_DEP(hw) ((struct igb_osdep *)((hw)->back))
--- a/usr/src/uts/common/io/igb/igb_phy.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_phy.c Mon Nov 23 14:27:01 2009 +0800 @@ -26,10 +26,11 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.140 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.155 scm_100809_154340 */ #include "igb_api.h" +static s32 e1000_copper_link_autoneg(struct e1000_hw *hw); static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); /* Cable length tables */ @@ -77,11 +78,13 @@ phy->ops.get_cable_length = e1000_null_ops_generic; phy->ops.get_info = e1000_null_ops_generic; phy->ops.read_reg = e1000_null_read_reg; + phy->ops.read_reg_locked = e1000_null_read_reg; phy->ops.release = e1000_null_phy_generic; phy->ops.reset = e1000_null_ops_generic; phy->ops.set_d0_lplu_state = e1000_null_lplu_state; phy->ops.set_d3_lplu_state = e1000_null_lplu_state; phy->ops.write_reg = e1000_null_write_reg; + phy->ops.write_reg_locked = e1000_null_write_reg; phy->ops.power_up = e1000_null_phy_generic; phy->ops.power_down = e1000_null_phy_generic; } @@ -328,6 +331,107 @@ } /* + * e1000_read_phy_reg_i2c - Read PHY register using i2c + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the PHY register at offset using the i2c interface and stores the + * retrieved information in data. + */ +s32 +e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 i, i2ccmd = 0; + + DEBUGFUNC("e1000_read_phy_reg_i2c"); + + /* + * Set up Op-code, Phy Address, and register address in the I2CCMD + * register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | + (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | + (E1000_I2CCMD_OPCODE_READ)); + + E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); + + /* Poll the ready bit to see if the I2C read completed */ + for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { + usec_delay(50); + i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); + if (i2ccmd & E1000_I2CCMD_READY) + break; + } + if (!(i2ccmd & E1000_I2CCMD_READY)) { + DEBUGOUT("I2CCMD Read did not complete\n"); + return (-E1000_ERR_PHY); + } + if (i2ccmd & E1000_I2CCMD_ERROR) { + DEBUGOUT("I2CCMD Error bit set\n"); + return (-E1000_ERR_PHY); + } + + /* Need to byte-swap the 16-bit value. */ + *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00); + + return (E1000_SUCCESS); +} + +/* + * e1000_write_phy_reg_i2c - Write PHY register using i2c + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Writes the data to PHY register at the offset using the i2c interface. + */ +s32 +e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data) +{ + struct e1000_phy_info *phy = &hw->phy; + u32 i, i2ccmd = 0; + u16 phy_data_swapped; + + DEBUGFUNC("e1000_write_phy_reg_i2c"); + + /* Swap the data bytes for the I2C interface */ + phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00); + + /* + * Set up Op-code, Phy Address, and register address in the I2CCMD + * register. The MAC will take care of interfacing with the + * PHY to retrieve the desired data. + */ + i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) | + (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) | + E1000_I2CCMD_OPCODE_WRITE | + phy_data_swapped); + + E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd); + + /* Poll the ready bit to see if the I2C read completed */ + for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) { + usec_delay(50); + i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD); + if (i2ccmd & E1000_I2CCMD_READY) + break; + } + if (!(i2ccmd & E1000_I2CCMD_READY)) { + DEBUGOUT("I2CCMD Write did not complete\n"); + return (-E1000_ERR_PHY); + } + if (i2ccmd & E1000_I2CCMD_ERROR) { + DEBUGOUT("I2CCMD Error bit set\n"); + return (-E1000_ERR_PHY); + } + + return (E1000_SUCCESS); +} + +/* * e1000_read_phy_reg_m88 - Read m88 PHY register * @hw: pointer to the HW structure * @offset: register offset to be read @@ -393,42 +497,122 @@ } /* + * __e1000_read_phy_reg_igp - Read igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * @locked: semaphore has already been acquired or not + * + * Acquires semaphore, if necessary, then reads the PHY register at offset + * and stores the retrieved information in data. Release any acquired + * semaphores before exiting. + */ +static s32 +__e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, + bool locked) +{ + s32 ret_val = E1000_SUCCESS; + + DEBUGFUNC("__e1000_read_phy_reg_igp"); + + if (!locked) { + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + } + + if (offset > MAX_PHY_MULTI_PAGE_REG) { + ret_val = e1000_write_phy_reg_mdic(hw, + IGP01E1000_PHY_PAGE_SELECT, (u16)offset); + if (ret_val) + goto release; + } + + ret_val = e1000_read_phy_reg_mdic(hw, + MAX_PHY_REG_ADDRESS & offset, data); + +release: + if (!locked) + hw->phy.ops.release(hw); + +out: + return (ret_val); +} + +/* * e1000_read_phy_reg_igp - Read igp PHY register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. + * Acquires semaphore then reads the PHY register at offset and stores the + * retrieved information in data. + * Release the acquired semaphore before exiting. */ s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) { + return (__e1000_read_phy_reg_igp(hw, offset, data, false)); +} + +/* + * e1000_read_phy_reg_igp_locked - Read igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the PHY register at offset and stores the retrieved information + * in data. Assumes semaphore already acquired. + */ +s32 +e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return (__e1000_read_phy_reg_igp(hw, offset, data, true)); +} + +/* + * __e1000_write_phy_reg_igp - Write igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * @locked: semaphore has already been acquired or not + * + * Acquires semaphore, if necessary, then writes the data to PHY register + * at the offset. Release any acquired semaphores before exiting. + */ +static s32 +__e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, + bool locked) +{ s32 ret_val = E1000_SUCCESS; - DEBUGFUNC("e1000_read_phy_reg_igp"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; + DEBUGFUNC("__e1000_write_phy_reg_igp"); + + if (!locked) { + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + } if (offset > MAX_PHY_MULTI_PAGE_REG) { ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, (u16)offset); - if (ret_val) { - hw->phy.ops.release(hw); - goto out; - } + if (ret_val) + goto release; } - ret_val = e1000_read_phy_reg_mdic(hw, + ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); - hw->phy.ops.release(hw); +release: + if (!locked) + hw->phy.ops.release(hw); out: return (ret_val); @@ -440,65 +624,57 @@ * @offset: register offset to write to * @data: data to write at register offset * - * Acquires semaphore, if necessary, then writes the data to PHY register + * Acquires semaphore then writes the data to PHY register * at the offset. Release any acquired semaphores before exiting. */ s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) { - s32 ret_val = E1000_SUCCESS; - - DEBUGFUNC("e1000_write_phy_reg_igp"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - ret_val = e1000_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, (u16)offset); - if (ret_val) { - hw->phy.ops.release(hw); - goto out; - } - } - - ret_val = e1000_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, data); - - hw->phy.ops.release(hw); - -out: - return (ret_val); + return (__e1000_write_phy_reg_igp(hw, offset, data, false)); } /* - * e1000_read_kmrn_reg_generic - Read kumeran register + * e1000_write_phy_reg_igp_locked - Write igp PHY register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Writes the data to PHY register at the offset. + * Assumes semaphore already acquired. + */ +s32 +e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) +{ + return (__e1000_write_phy_reg_igp(hw, offset, data, true)); +} + +/* + * __e1000_read_kmrn_reg - Read kumeran register * @hw: pointer to the HW structure * @offset: register offset to be read * @data: pointer to the read data + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then reads the PHY register at offset * using the kumeran interface. The information retrieved is stored in data. * Release any acquired semaphores before exiting. */ -s32 -e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) +static s32 +__e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, bool locked) { u32 kmrnctrlsta; s32 ret_val = E1000_SUCCESS; - DEBUGFUNC("e1000_read_kmrn_reg_generic"); - - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; + DEBUGFUNC("__e1000_read_kmrn_reg_generic"); + + if (!locked) { + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; @@ -509,43 +685,164 @@ kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); *data = (u16)kmrnctrlsta; - hw->phy.ops.release(hw); + if (!locked) + hw->phy.ops.release(hw); out: return (ret_val); } /* - * e1000_write_kmrn_reg_generic - Write kumeran register + * e1000_read_kmrn_reg_generic - Read kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Acquires semaphore then reads the PHY register at offset using the + * kumeran interface. The information retrieved is stored in data. + * Release the acquired semaphore before exiting. + */ +s32 +e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return (__e1000_read_kmrn_reg(hw, offset, data, false)); +} + +/* + * e1000_read_kmrn_reg_locked - Read kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to be read + * @data: pointer to the read data + * + * Reads the PHY register at offset using the kumeran interface. The + * information retrieved is stored in data. + * Assumes semaphore already acquired. + */ +s32 +e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) +{ + return (__e1000_read_kmrn_reg(hw, offset, data, true)); +} + +/* + * __e1000_write_kmrn_reg - Write kumeran register * @hw: pointer to the HW structure * @offset: register offset to write to * @data: data to write at register offset + * @locked: semaphore has already been acquired or not * * Acquires semaphore, if necessary. Then write the data to PHY register * at the offset using the kumeran interface. Release any acquired semaphores * before exiting. */ -s32 -e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) +static s32 +__e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, bool locked) { u32 kmrnctrlsta; s32 ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_write_kmrn_reg_generic"); - if (!(hw->phy.ops.acquire)) - goto out; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; + if (!locked) { + if (!(hw->phy.ops.acquire)) + goto out; + + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + } kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & E1000_KMRNCTRLSTA_OFFSET) | data; E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); usec_delay(2); - hw->phy.ops.release(hw); + + if (!locked) + hw->phy.ops.release(hw); + +out: + return (ret_val); +} + +/* + * e1000_write_kmrn_reg_generic - Write kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Acquires semaphore then writes the data to the PHY register at the offset + * using the kumeran interface. Release the acquired semaphore before exiting. + */ +s32 +e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) +{ + return (__e1000_write_kmrn_reg(hw, offset, data, false)); +} + +/* + * e1000_write_kmrn_reg_locked - Write kumeran register + * @hw: pointer to the HW structure + * @offset: register offset to write to + * @data: data to write at register offset + * + * Write the data to PHY register at the offset using the kumeran interface. + * Assumes semaphore already acquired. + */ +s32 +e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) +{ + return (__e1000_write_kmrn_reg(hw, offset, data, true)); +} + +/* + * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link + * @hw: pointer to the HW structure + * + * Sets up Carrier-sense on Transmit and downshift values. + */ +s32 +e1000_copper_link_setup_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + + DEBUGFUNC("e1000_copper_link_setup_82577"); + + if (phy->reset_disable) { + ret_val = E1000_SUCCESS; + goto out; + } + + if (phy->type == e1000_phy_82580) { + ret_val = hw->phy.ops.reset(hw); + if (ret_val) { + DEBUGOUT("Error resetting the PHY.\n"); + goto out; + } + } + + /* Enable CRS on TX. This must be set for half-duplex operation. */ + ret_val = phy->ops.read_reg(hw, I82577_CFG_REG, &phy_data); + if (ret_val) + goto out; + + phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; + + /* Enable downshift */ + phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; + + ret_val = phy->ops.write_reg(hw, I82577_CFG_REG, phy_data); + if (ret_val) + goto out; + + /* Set number of link attempts before downshift */ + ret_val = phy->ops.read_reg(hw, I82577_CTRL_REG, &phy_data); + if (ret_val) + goto out; + phy_data &= ~I82577_CTRL_DOWNSHIFT_MASK; + ret_val = phy->ops.write_reg(hw, I82577_CTRL_REG, phy_data); out: return (ret_val); @@ -811,7 +1108,7 @@ * and restart the negotiation process between the link partner. If * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. */ -s32 +static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; @@ -1743,9 +2040,8 @@ * see if they have relinquished the resources yet. */ usec_delay(usec_interval); - ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, - &phy_status); } + ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); if (ret_val) break; if (phy_status & MII_SR_LINK_STATUS) @@ -1791,13 +2087,13 @@ 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; + 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->max_cable_length = e1000_m88_cable_length_table[index + 1]; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; @@ -1901,7 +2197,7 @@ DEBUGFUNC("e1000_get_phy_info_m88"); - if (hw->phy.media_type != e1000_media_type_copper) { + if (phy->media_type != e1000_media_type_copper) { DEBUGOUT("Phy info is only valid for copper media\n"); ret_val = -E1000_ERR_CONFIG; goto out; @@ -2004,7 +2300,7 @@ if ((data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = hw->phy.ops.get_cable_length(hw); + ret_val = phy->ops.get_cable_length(hw); if (ret_val) goto out; @@ -2245,6 +2541,9 @@ case IFE_C_E_PHY_ID: phy_type = e1000_phy_ife; break; + case I82580_I_PHY_ID: + phy_type = e1000_phy_82580; + break; default: phy_type = e1000_phy_unknown; break; @@ -2275,7 +2574,7 @@ i = 0; do { - e1000_get_phy_id(hw); + (void) e1000_get_phy_id(hw); phy_type = e1000_get_phy_type_from_id(hw->phy.id); /* @@ -2332,3 +2631,204 @@ (void) hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); msec_delay(1); } + +/* + * e1000_check_polarity_82577 - Checks the polarity. + * @hw: pointer to the HW structure + * + * Success returns 0, Failure returns -E1000_ERR_PHY (-2) + * + * Polarity is determined based on the PHY specific status register. + */ +s32 +e1000_check_polarity_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + + DEBUGFUNC("e1000_check_polarity_82577"); + + ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); + + if (!ret_val) + phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY) + ? e1000_rev_polarity_reversed + : e1000_rev_polarity_normal; + + return (ret_val); +} + +/* + * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY + * @hw: pointer to the HW structure + * + * Calls the PHY setup function to force speed and duplex. Clears the + * auto-crossover to force MDI manually. Waits for link and returns + * successful if link up is successful, else -E1000_ERR_PHY (-2). + */ +s32 +e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data; + bool link; + + DEBUGFUNC("e1000_phy_force_speed_duplex_82577"); + + ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); + if (ret_val) + goto out; + + e1000_phy_force_speed_duplex_setup(hw, &phy_data); + + ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); + if (ret_val) + goto out; + + /* + * Clear Auto-Crossover to force MDI manually. 82577 requires MDI + * forced whenever speed and duplex are forced. + */ + ret_val = phy->ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX; + phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX; + + ret_val = phy->ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data); + if (ret_val) + goto out; + + DEBUGOUT1("I82577_PHY_CTRL_2: %X\n", phy_data); + + usec_delay(1); + + if (phy->autoneg_wait_to_complete) { + DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n"); + + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + + if (!link) + DEBUGOUT("Link taking longer than expected.\n"); + + /* Try once more */ + ret_val = e1000_phy_has_link_generic(hw, + PHY_FORCE_LIMIT, + 100000, + &link); + if (ret_val) + goto out; + } + +out: + return (ret_val); +} + +/* + * e1000_get_phy_info_82577 - Retrieve I82577 PHY information + * @hw: pointer to the HW structure + * + * Read PHY status to determine if link is up. If link is up, then + * set/determine 10base-T extended distance and polarity correction. Read + * PHY port status to determine MDI/MDIx and speed. Based on the speed, + * determine on the cable length, local and remote receiver. + */ +s32 +e1000_get_phy_info_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 data; + bool link; + + DEBUGFUNC("e1000_get_phy_info_82577"); + + ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); + if (ret_val) + goto out; + + if (!link) { + DEBUGOUT("Phy info is only valid if link is up\n"); + ret_val = -E1000_ERR_CONFIG; + goto out; + } + + phy->polarity_correction = true; + + ret_val = e1000_check_polarity_82577(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); + if (ret_val) + goto out; + + phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false; + + if ((data & I82577_PHY_STATUS2_SPEED_MASK) == + I82577_PHY_STATUS2_SPEED_1000MBPS) { + ret_val = hw->phy.ops.get_cable_length(hw); + if (ret_val) + goto out; + + ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); + if (ret_val) + goto out; + + phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + + phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) + ? e1000_1000t_rx_status_ok + : e1000_1000t_rx_status_not_ok; + } else { + phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; + phy->local_rx = e1000_1000t_rx_status_undefined; + phy->remote_rx = e1000_1000t_rx_status_undefined; + } + +out: + return (ret_val); +} + +/* + * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY + * @hw: pointer to the HW structure + * + * Reads the diagnostic status register and verifies result is valid before + * placing it in the phy_cable_length field. + */ +s32 +e1000_get_cable_length_82577(struct e1000_hw *hw) +{ + struct e1000_phy_info *phy = &hw->phy; + s32 ret_val; + u16 phy_data, length; + + DEBUGFUNC("e1000_get_cable_length_82577"); + + ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data); + if (ret_val) + goto out; + + length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >> + I82577_DSTATUS_CABLE_LENGTH_SHIFT; + + if (length == E1000_CABLE_LENGTH_UNDEFINED) + ret_val = -E1000_ERR_PHY; + + phy->cable_length = length; + +out: + + return (ret_val); +}
--- a/usr/src/uts/common/io/igb/igb_phy.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_phy.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.69 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.76 scm_100809_154340 */ #ifndef _IGB_PHY_H #define _IGB_PHY_H @@ -45,7 +45,6 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw); s32 e1000_check_polarity_ife(struct e1000_hw *hw); s32 e1000_check_reset_block_generic(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_phy_force_speed_duplex_igp(struct e1000_hw *hw); @@ -62,13 +61,17 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw); s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw); s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active); s32 e1000_setup_copper_link_generic(struct e1000_hw *hw); s32 e1000_wait_autoneg_generic(struct e1000_hw *hw); s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); s32 e1000_phy_reset_dsp(struct e1000_hw *hw); s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, @@ -80,6 +83,13 @@ void e1000_power_down_phy_copper(struct e1000_hw *hw); s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); +s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data); +s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); +s32 e1000_check_polarity_82577(struct e1000_hw *hw); +s32 e1000_get_phy_info_82577(struct e1000_hw *hw); +s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); +s32 e1000_get_cable_length_82577(struct e1000_hw *hw); #define E1000_MAX_PHY_ADDR 4 @@ -96,6 +106,36 @@ #define IGP_PAGE_SHIFT 5 #define PHY_REG_MASK 0x1F +#define HV_INTC_FC_PAGE_START 768 +#define I82578_ADDR_REG 29 +#define I82577_ADDR_REG 16 +#define I82577_CFG_REG 22 +#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) +#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */ +#define I82577_CTRL_REG 23 +#define I82577_CTRL_DOWNSHIFT_MASK (7 << 10) + +/* 82577 specific PHY registers */ +#define I82577_PHY_CTRL_2 18 +#define I82577_PHY_LBK_CTRL 19 +#define I82577_PHY_STATUS_2 26 +#define I82577_PHY_DIAG_STATUS 31 + +/* I82577 PHY Status 2 */ +#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 +#define I82577_PHY_STATUS2_MDIX 0x0800 +#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 +#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 +#define I82577_PHY_STATUS2_SPEED_100MBPS 0x0100 + +/* I82577 PHY Control 2 */ +#define I82577_PHY_CTRL2_AUTO_MDIX 0x0400 +#define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200 + +/* I82577 PHY Diagnostics Status */ +#define I82577_DSTATUS_CABLE_LENGTH 0x03FC +#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 + #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 #define IGP01E1000_PHY_POLARITY_MASK 0x0078
--- a/usr/src/uts/common/io/igb/igb_regs.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_regs.h Mon Nov 23 14:27:01 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms of the CDDL. */ -/* IntelVersion: 1.70 v2-9-8_2009-6-12 */ +/* IntelVersion: 1.78 scm_100809_154340 */ #ifndef _IGB_REGS_H #define _IGB_REGS_H @@ -43,6 +43,12 @@ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ #define E1000_FLA 0x0001C /* Flash Access - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ +#define E1000_MDICNFG 0x00E04 /* MDI Config - RW */ +#define E1000_REGISTER_SET_SIZE 0x20000 /* CSR Size */ +#define E1000_EEPROM_INIT_CTRL_WORD_2 0x0F /* EEPROM Init Ctrl Word 2 */ +#define E1000_BARCTRL 0x5BBC /* BAR ctrl reg */ +#define E1000_BARCTRL_FLSIZE 0x0700 /* BAR ctrl Flsize */ +#define E1000_BARCTRL_CSRSIZE 0x2000 /* BAR ctrl CSR size */ #define E1000_SCTL 0x00024 /* SerDes Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ @@ -91,17 +97,19 @@ #define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ #define E1000_FLOP 0x0103C /* FLASH Opcode Register */ #define E1000_I2CCMD 0x01028 /* SFPI2C Command Register - RW */ -#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ +#define E1000_I2CPARAMS 0x0102C /* SFPI2C Parameters Register - RW */ #define E1000_WDSTP 0x01040 /* Watchdog Setup - RW */ #define E1000_SWDSTS 0x01044 /* SW Device Status - RW */ #define E1000_FRTIMER 0x01048 /* Free Running Timer - RW */ #define E1000_TCPTIMER 0x0104C /* TCP Timer - RW */ #define E1000_VPDDIAG 0x01060 /* VPD Diagnostic - RO */ -#define E1000_ICR_V2 0x01500 /* Interrupt Cause - new location - RC */ -#define E1000_ICS_V2 0x01504 /* Interrupt Cause Set - new location - WO */ -#define E1000_IMS_V2 0x01508 /* Interrupt Mask Set/Read - new location - RW */ -#define E1000_IMC_V2 0x0150C /* Interrupt Mask Clear - new location - WO */ -#define E1000_IAM_V2 0x01510 /* Interrupt Ack Auto Mask - new location - RW */ +#define E1000_ICR_V2 0x01500 /* Interrupt Cause - new location - RC */ +#define E1000_ICS_V2 0x01504 /* Interrupt Cause Set - new location - WO */ +/* Interrupt Mask Set/Read - new location - RW */ +#define E1000_IMS_V2 0x01508 +#define E1000_IMC_V2 0x0150C /* Interrupt Mask Clear - new location - WO */ +/* Interrupt Ack Auto Mask - new location - RW */ +#define E1000_IAM_V2 0x01510 #define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ #define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ #define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ @@ -117,11 +125,8 @@ #define E1000_RDPUCTL 0x025DC /* DMA Rx Descriptor uC Control - RW */ #define E1000_PBDIAG 0x02458 /* Packet Buffer Diagnostic - RW */ #define E1000_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */ -#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n))) -#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n))) -#define E1000_TXCTL(_n) (0x0E014 + (0x40 * (_n))) -#define E1000_RXCTL(_n) (0x0C014 + (0x40 * (_n))) -#define E1000_RQDPC(_n) (0x0C030 + (0x40 * (_n))) +/* Same as RXPBS, renamed for newer adapters - RW */ +#define E1000_IRPBS 0x02404 #define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ #define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ /* @@ -147,12 +152,19 @@ #define E1000_RDH(_n) ((_n) < 4 ? \ (0x02810 + ((_n) * 0x100)) : \ (0x0C010 + ((_n) * 0x40))) +#define E1000_RXCTL(_n) ((_n) < 4 ? \ + (0x02814 + ((_n) * 0x100)) : \ + (0x0C014 + ((_n) * 0x40))) +#define E1000_DCA_RXCTRL(_n) E1000_RXCTL(_n) #define E1000_RDT(_n) ((_n) < 4 ? \ (0x02818 + ((_n) * 0x100)) : \ (0x0C018 + ((_n) * 0x40))) #define E1000_RXDCTL(_n) ((_n) < 4 ? \ (0x02828 + ((_n) * 0x100)) : \ (0x0C028 + ((_n) * 0x40))) +#define E1000_RQDPC(_n) ((_n) < 4 ? \ + (0x02830 + ((_n) * 0x100)) : \ + (0x0C030 + ((_n) * 0x40))) #define E1000_TDBAL(_n) ((_n) < 4 ? \ (0x03800 + ((_n) * 0x100)) : \ (0x0E000 + ((_n) * 0x40))) @@ -165,21 +177,23 @@ #define E1000_TDH(_n) ((_n) < 4 ? \ (0x03810 + ((_n) * 0x100)) : \ (0x0E010 + ((_n) * 0x40))) +#define E1000_TXCTL(_n) ((_n) < 4 ? \ + (0x03814 + ((_n) * 0x100)) : \ + (0x0E014 + ((_n) * 0x40))) +#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n) #define E1000_TDT(_n) ((_n) < 4 ? \ (0x03818 + ((_n) * 0x100)) : \ (0x0E018 + ((_n) * 0x40))) #define E1000_TXDCTL(_n) ((_n) < 4 ? \ (0x03828 + ((_n) * 0x100)) : \ (0x0E028 + ((_n) * 0x40))) -#define E1000_TARC(_n) (0x03840 + (_n << 8)) -#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) -#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) #define E1000_TDWBAL(_n) ((_n) < 4 ? \ (0x03838 + ((_n) * 0x100)) : \ (0x0E038 + ((_n) * 0x40))) #define E1000_TDWBAH(_n) ((_n) < 4 ? \ (0x0383C + ((_n) * 0x100)) : \ (0x0E03C + ((_n) * 0x40))) +#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) #define E1000_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */ #define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ #define E1000_TXDMAC 0x03000 /* Tx DMA Control - RW */ @@ -201,6 +215,8 @@ /* Packet Buffer DWORD (_n) */ #define E1000_PBSLAD(_n) (0x03110 + (0x4 * (_n))) #define E1000_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */ +/* Same as TXPBS, renamed for newer adpaters - RW */ +#define E1000_ITPBS 0x03404 #define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ #define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ #define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ @@ -539,6 +555,15 @@ #define E1000_RTTBCNACH 0x0B214 /* Tx BCN Control High */ #define E1000_RTTBCNACL 0x0B210 /* Tx BCN Control Low */ +/* DMA Coalescing registers */ +#define E1000_DMACR 0x02508 /* Control Register */ +#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_FCRTC 0x02170 /* Flow Control Rx high watermark */ +#define E1000_PCIEMISC 0x05BB8 /* PCIE misc config register */ + #ifdef __cplusplus } #endif
--- a/usr/src/uts/common/io/igb/igb_sw.h Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_sw.h Mon Nov 23 14:27:01 2009 +0800 @@ -81,6 +81,7 @@ #define IGB_INITIALIZED 0x01 #define IGB_STARTED 0x02 #define IGB_SUSPENDED 0x04 +#define IGB_STALL 0x08 #define IGB_INTR_NONE 0 #define IGB_INTR_MSIX 1 @@ -114,10 +115,6 @@ #define MAX_MTU 9000 #define MAX_RX_LIMIT_PER_INTR 4096 -#define MAX_RX_INTR_DELAY 65535 -#define MAX_RX_INTR_ABS_DELAY 65535 -#define MAX_TX_INTR_DELAY 65535 -#define MAX_TX_INTR_ABS_DELAY 65535 #define MAX_RX_COPY_THRESHOLD 9216 #define MAX_TX_COPY_THRESHOLD 9216 @@ -135,10 +132,7 @@ #define MIN_MTU ETHERMIN #define MIN_RX_LIMIT_PER_INTR 16 -#define MIN_RX_INTR_DELAY 0 -#define MIN_RX_INTR_ABS_DELAY 0 -#define MIN_TX_INTR_DELAY 0 -#define MIN_TX_INTR_ABS_DELAY 0 + #define MIN_RX_COPY_THRESHOLD 0 #define MIN_TX_COPY_THRESHOLD 0 #define MIN_TX_RECYCLE_THRESHOLD MIN_NUM_TX_DESC @@ -155,10 +149,7 @@ #define DEFAULT_MTU ETHERMTU #define DEFAULT_RX_LIMIT_PER_INTR 256 -#define DEFAULT_RX_INTR_DELAY 0 -#define DEFAULT_RX_INTR_ABS_DELAY 0 -#define DEFAULT_TX_INTR_DELAY 300 -#define DEFAULT_TX_INTR_ABS_DELAY 0 + #define DEFAULT_RX_COPY_THRESHOLD 128 #define DEFAULT_TX_COPY_THRESHOLD 512 #define DEFAULT_TX_RECYCLE_THRESHOLD (MAX_COOKIE + 1) @@ -834,8 +825,8 @@ void e1000_read_pci_cfg(struct e1000_hw *, uint32_t, uint16_t *); int32_t e1000_read_pcie_cap_reg(struct e1000_hw *, uint32_t, uint16_t *); int32_t e1000_write_pcie_cap_reg(struct e1000_hw *, uint32_t, uint16_t *); -void e1000_rar_clear(struct e1000_hw *hw, uint32_t); -void e1000_rar_set_vmdq(struct e1000_hw *hw, const uint8_t *, uint32_t, +void e1000_rar_clear(struct e1000_hw *, uint32_t); +void e1000_rar_set_vmdq(struct e1000_hw *, const uint8_t *, uint32_t, uint32_t, uint8_t); /*
--- a/usr/src/uts/common/io/igb/igb_tx.c Mon Nov 23 12:45:18 2009 +0800 +++ b/usr/src/uts/common/io/igb/igb_tx.c Mon Nov 23 14:27:01 2009 +0800 @@ -957,7 +957,7 @@ (mbsize - ctx->mac_hdr_len - ctx->ip_hdr_len - ctx->l4_hdr_len) << E1000_ADVTXD_PAYLEN_SHIFT; } else { - if (hw->mac.type == e1000_82576) { + if (hw->mac.type >= e1000_82576) { first_tbd->read.olinfo_status |= (mbsize << E1000_ADVTXD_PAYLEN_SHIFT); }