Mercurial > illumos > illumos-gate
changeset 10998:fa3b21f3b03c
6873301 ixgbe shared code update (version 3.1.9)
author | chenlu chen - Sun Microsystems - Beijing China <Chenlu.Chen@Sun.COM> |
---|---|
date | Sun, 08 Nov 2009 15:49:56 +0800 |
parents | 2ff33cc68aa6 |
children | 1e3c6bd245c1 |
files | usr/src/pkgdefs/SUNWixgbe/postinstall usr/src/uts/common/io/ixgbe/ixgbe_82598.c usr/src/uts/common/io/ixgbe/ixgbe_82599.c usr/src/uts/common/io/ixgbe/ixgbe_api.c usr/src/uts/common/io/ixgbe/ixgbe_api.h usr/src/uts/common/io/ixgbe/ixgbe_common.c usr/src/uts/common/io/ixgbe/ixgbe_common.h usr/src/uts/common/io/ixgbe/ixgbe_gld.c usr/src/uts/common/io/ixgbe/ixgbe_main.c usr/src/uts/common/io/ixgbe/ixgbe_phy.c usr/src/uts/common/io/ixgbe/ixgbe_phy.h usr/src/uts/common/io/ixgbe/ixgbe_stat.c usr/src/uts/common/io/ixgbe/ixgbe_type.h |
diffstat | 13 files changed, 1692 insertions(+), 880 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/pkgdefs/SUNWixgbe/postinstall Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/pkgdefs/SUNWixgbe/postinstall Sun Nov 08 15:49:56 2009 +0800 @@ -139,10 +139,12 @@ "pciex8086,10f1" "pciex8086,10f4" "pciex8086,10f7" + "pciex8086,10f8" "pciex8086,10f9" "pciex8086,10fb" "pciex8086,10fc" "pciex8086,1507" "pciex8086,1508" + "pciex8086,150b" "pciex8086,1514"' \ -b "$BASEDIR" ixgbe
--- a/usr/src/uts/common/io/ixgbe/ixgbe_82598.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_82598.c Sun Nov 08 15:49:56 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.144 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.155 scm_100309_002210 */ #include "ixgbe_type.h" #include "ixgbe_api.h" @@ -39,16 +39,17 @@ ixgbe_link_speed *speed, bool *autoneg); static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw); s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num); -static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw); +static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, + bool autoneg_wait_to_complete); static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); -static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, +static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw); -static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, +static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); +s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw); s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq); s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, @@ -61,6 +62,50 @@ u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw); s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw); void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw); +void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw); + +/* + * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout + * @hw: pointer to the HW structure + * + * The defaults for 82598 should be in the range of 50us to 50ms, + * however the hardware default for these parts is 500us to 1ms which is less + * than the 10ms recommended by the pci-e spec. To address this we need to + * increase the value to either 10ms to 250ms for capability version 1 config, + * or 16ms to 55ms for version 2. + */ +void +ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw) +{ + u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR); + u16 pcie_devctl2; + + /* only take action if timeout value is defaulted to 0 */ + if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK) + goto out; + + /* + * if capababilities version is type 1 we can write the + * timeout of 10ms to 250ms through the GCR register + */ + if (!(gcr & IXGBE_GCR_CAP_VER2)) { + gcr |= IXGBE_GCR_CMPL_TMOUT_10ms; + goto out; + } + + /* + * for version 2 capabilities we need to write the config space + * directly in order to set the completion timeout value for + * 16ms to 55ms + */ + pcie_devctl2 = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2); + pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms; + IXGBE_WRITE_PCIE_WORD(hw, IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2); +out: + /* disable completion timeout resend */ + gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND; + IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr); +} /* * ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count @@ -74,6 +119,8 @@ { u32 msix_count = 18; + DEBUGFUNC("ixgbe_get_pcie_msix_count_82598"); + if (hw->mac.msix_vectors_from_pcie) { msix_count = IXGBE_READ_PCIE_WORD(hw, IXGBE_PCIE_MSIX_82598_CAPS); @@ -102,6 +149,8 @@ struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val; + DEBUGFUNC("ixgbe_init_ops_82598"); + ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); @@ -109,6 +158,7 @@ phy->ops.init = &ixgbe_init_phy_ops_82598; /* MAC */ + mac->ops.start_hw = &ixgbe_start_hw_82598; mac->ops.reset_hw = &ixgbe_reset_hw_82598; mac->ops.get_media_type = &ixgbe_get_media_type_82598; mac->ops.get_supported_physical_layer = @@ -139,7 +189,6 @@ /* Link */ mac->ops.check_link = &ixgbe_check_mac_link_82598; mac->ops.setup_link = &ixgbe_setup_mac_link_82598; - mac->ops.setup_link_speed = &ixgbe_setup_mac_link_speed_82598; mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82598; @@ -163,27 +212,28 @@ s32 ret_val = IXGBE_SUCCESS; u16 list_offset, data_offset; + DEBUGFUNC("ixgbe_init_phy_ops_82598"); + /* Identify the PHY */ phy->ops.identify(hw); /* Overwrite the link function pointers if copper PHY */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82598; - mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82598; mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic; } switch (hw->phy.type) { case ixgbe_phy_tn: + phy->ops.setup_link = &ixgbe_setup_phy_link_tnx; phy->ops.check_link = &ixgbe_check_phy_link_tnx; phy->ops.get_firmware_version = &ixgbe_get_phy_firmware_version_tnx; break; case ixgbe_phy_aq: phy->ops.get_firmware_version = - &ixgbe_get_phy_firmware_version_aq; + &ixgbe_get_phy_firmware_version_generic; break; case ixgbe_phy_nl: phy->ops.reset = &ixgbe_reset_phy_nl; @@ -213,6 +263,29 @@ } /* + * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx + * @hw: pointer to hardware structure + * + * Starts the hardware using the generic start_hw function. + * Then set pcie completion timeout + */ +s32 +ixgbe_start_hw_82598(struct ixgbe_hw *hw) +{ + s32 ret_val = IXGBE_SUCCESS; + + DEBUGFUNC("ixgbe_start_hw_82598"); + + ret_val = ixgbe_start_hw_generic(hw); + + /* set the completion timeout for interface */ + if (ret_val == IXGBE_SUCCESS) + ixgbe_set_pcie_completion_timeout(hw); + + return (ret_val); +} + +/* * ixgbe_get_link_capabilities_82598 - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed @@ -227,6 +300,8 @@ s32 status = IXGBE_SUCCESS; u32 autoc = 0; + DEBUGFUNC("ixgbe_get_link_capabilities_82598"); + /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not been @@ -282,6 +357,8 @@ { enum ixgbe_media_type media_type; + DEBUGFUNC("ixgbe_get_media_type_82598"); + /* Detect if there is a copper PHY attached. */ if (hw->phy.type == ixgbe_phy_cu_unknown || hw->phy.type == ixgbe_phy_tn || @@ -299,15 +376,18 @@ break; case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: - case IXGBE_DEV_ID_82598EB_CX4: - case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: case IXGBE_DEV_ID_82598EB_XF_LR: case IXGBE_DEV_ID_82598EB_SFP_LOM: media_type = ixgbe_media_type_fiber; break; + case IXGBE_DEV_ID_82598EB_CX4: + case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: + media_type = ixgbe_media_type_cx4; + break; case IXGBE_DEV_ID_82598AT: + case IXGBE_DEV_ID_82598AT2: media_type = ixgbe_media_type_copper; break; default: @@ -389,7 +469,7 @@ break; default: DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -IXGBE_ERR_CONFIG; + ret_val = IXGBE_ERR_CONFIG; goto out; } @@ -427,27 +507,29 @@ } /* - * ixgbe_setup_mac_link_82598 - Configures MAC link settings + * ixgbe_start_mac_link_82598 - Configures MAC link settings * @hw: pointer to hardware structure * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. */ static s32 -ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw) +ixgbe_start_mac_link_82598(struct ixgbe_hw *hw, bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; u32 i; s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_start_mac_link_82598"); + /* Restart link */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ - if (hw->phy.autoneg_wait_to_complete) { + if (autoneg_wait_to_complete) { if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_AN || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == @@ -489,6 +571,8 @@ u32 i; u16 link_reg, adapt_comp_reg; + DEBUGFUNC("ixgbe_check_mac_link_82598"); + /* * SERDES PHY requires us to read link status from undocumented * register 0xC79F. Bit 0 set indicates link is up/ready; clear @@ -561,7 +645,7 @@ } /* - * ixgbe_setup_mac_link_speed_82598 - Set MAC link speed + * ixgbe_setup_mac_link_82598 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled @@ -570,7 +654,7 @@ * Set the link speed in the AUTOC register and restarts link. */ static s32 -ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw, +ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { @@ -580,6 +664,8 @@ u32 autoc = curr_autoc; u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK; + DEBUGFUNC("ixgbe_setup_mac_link_82598"); + /* Check to see if speed passed in is supported. */ (void) ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); speed &= link_capabilities; @@ -599,45 +685,20 @@ } if (status == IXGBE_SUCCESS) { - hw->phy.autoneg_wait_to_complete = autoneg_wait_to_complete; - /* * Setup and restart the link based on the new values in * ixgbe_hw This will write the AUTOC register based on the new * stored values */ - status = ixgbe_setup_mac_link_82598(hw); + status = ixgbe_start_mac_link_82598(hw, + autoneg_wait_to_complete); } return (status); } - /* - * ixgbe_setup_copper_link_82598 - Setup copper link settings - * @hw: pointer to hardware structure - * - * Configures link settings based on values in the ixgbe_hw struct. - * Restarts the link. Performs autonegotiation if needed. Restart - * phy and wait for autonegotiate to finish. Then synchronize the - * MAC and PHY. - */ -static s32 -ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw) -{ - s32 status; - - /* Restart autonegotiation on PHY */ - status = hw->phy.ops.setup_link(hw); - - /* Set up MAC */ - (void) ixgbe_setup_mac_link_82598(hw); - - return (status); -} - -/* - * ixgbe_setup_copper_link_speed_82598 - Set the PHY autoneg advertised field + * ixgbe_setup_copper_link_82598 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled @@ -646,19 +707,21 @@ * Sets the link speed in the AUTOC register in the MAC and restarts link. */ static s32 -ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw, +ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status; + DEBUGFUNC("ixgbe_setup_copper_link_82598"); + /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); /* Set up MAC */ - (void) ixgbe_setup_mac_link_82598(hw); + (void) ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete); return (status); } @@ -682,6 +745,8 @@ u32 autoc; u8 analog_val; + DEBUGFUNC("ixgbe_reset_hw_82598"); + /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); @@ -809,6 +874,8 @@ { u32 rar_high; + DEBUGFUNC("ixgbe_set_vmdq_82598"); + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); rar_high &= ~IXGBE_RAH_VIND_MASK; rar_high |= ((vmdq << IXGBE_RAH_VIND_SHIFT) & IXGBE_RAH_VIND_MASK); @@ -860,6 +927,8 @@ u32 bits; u32 vftabyte; + DEBUGFUNC("ixgbe_set_vfta_82598"); + if (vlan > 4095) return (IXGBE_ERR_PARAM); @@ -903,6 +972,8 @@ u32 offset; u32 vlanbyte; + DEBUGFUNC("ixgbe_clear_vfta_82598"); + for (offset = 0; offset < hw->mac.vft_size; offset++) IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); @@ -927,6 +998,8 @@ { u32 atlas_ctl; + DEBUGFUNC("ixgbe_read_analog_reg8_82598"); + IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, IXGBE_ATLASCTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); @@ -950,6 +1023,8 @@ { u32 atlas_ctl; + DEBUGFUNC("ixgbe_write_analog_reg8_82598"); + atlas_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_ATLASCTL, atlas_ctl); IXGBE_WRITE_FLUSH(hw); @@ -976,6 +1051,8 @@ u16 sfp_stat = 0; u32 i; + DEBUGFUNC("ixgbe_read_i2c_eeprom_82598"); + if (hw->phy.type == ixgbe_phy_nl) { /* * NetLogic phy SDA/SCL registers are at addresses 0xC30A to @@ -1033,6 +1110,8 @@ u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; u16 ext_ability = 0; + DEBUGFUNC("ixgbe_get_supported_physical_layer_82598"); + hw->phy.ops.identify(hw); /* @@ -1132,6 +1211,8 @@ struct ixgbe_bus_info *bus = &hw->bus; u16 pci_gen, pci_ctrl2; + DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie_82598"); + ixgbe_set_lan_id_multi_port_pcie(hw); /* check if LAN0 is disabled */
--- a/usr/src/uts/common/io/ixgbe/ixgbe_82599.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_82599.c Sun Nov 08 15:49:56 2009 +0800 @@ -26,42 +26,32 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.176 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.197 scm_100309_002210 */ #include "ixgbe_type.h" #include "ixgbe_api.h" #include "ixgbe_common.h" #include "ixgbe_phy.h" -u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw); s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw); s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw); -s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw); -s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, +s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); +s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw); -s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, - ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete); -s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, +s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, + bool autoneg_wait_to_complete); +s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw); -static s32 ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw, +static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw); -s32 ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq); -s32 ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq); -s32 ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); -s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, - u32 vind, bool vlan_on); -s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw); -s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw); s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val); s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw); @@ -69,10 +59,6 @@ s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw); u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval); -s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw, - u16 *san_mac_offset); -s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr); -s32 ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr); s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps); static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); @@ -85,15 +71,14 @@ if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ - mac->ops.setup_link = - &ixgbe_setup_mac_link_multispeed_fiber; - mac->ops.setup_link_speed = - &ixgbe_setup_mac_link_speed_multispeed_fiber; + mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; } else { - mac->ops.setup_link = - &ixgbe_setup_mac_link_82599; - mac->ops.setup_link_speed = - &ixgbe_setup_mac_link_speed_82599; + if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) && + (hw->phy.smart_speed == ixgbe_smart_speed_auto || + hw->phy.smart_speed == ixgbe_smart_speed_on)) + mac->ops.setup_link = &ixgbe_setup_mac_link_smartspeed; + else + mac->ops.setup_link = &ixgbe_setup_mac_link_82599; } } @@ -128,8 +113,6 @@ /* If copper media, overwrite with copper function pointers */ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) { mac->ops.setup_link = &ixgbe_setup_copper_link_82599; - mac->ops.setup_link_speed = - &ixgbe_setup_copper_link_speed_82599; mac->ops.get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic; } @@ -143,7 +126,7 @@ break; case ixgbe_phy_aq: phy->ops.get_firmware_version = - &ixgbe_get_phy_firmware_version_aq; + &ixgbe_get_phy_firmware_version_generic; break; default: break; @@ -200,33 +183,6 @@ } /* - * ixgbe_get_pcie_msix_count_82599 - Gets MSI-X vector count - * @hw: pointer to hardware structure - * - * Read PCIe configuration space, and get the MSI-X vector count from - * the capabilities table. - */ -u32 -ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw) -{ - u32 msix_count = 64; - - if (hw->mac.msix_vectors_from_pcie) { - msix_count = IXGBE_READ_PCIE_WORD(hw, - IXGBE_PCIE_MSIX_82599_CAPS); - msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; - - /* - * MSI-X count is zero-based in HW, so increment to give - * proper value - */ - msix_count++; - } - - return (msix_count); -} - -/* * ixgbe_init_ops_82599 - Inits func ptrs and MAC type * @hw: pointer to hardware structure * @@ -241,6 +197,8 @@ struct ixgbe_phy_info *phy = &hw->phy; s32 ret_val; + DEBUGFUNC("ixgbe_init_ops_82599"); + ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); @@ -257,23 +215,24 @@ mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82599; mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82599; mac->ops.start_hw = &ixgbe_start_hw_rev_1_82599; - mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_82599; - mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_82599; + mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_generic; + mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_generic; mac->ops.get_device_caps = &ixgbe_get_device_caps_82599; + mac->ops.get_wwn_prefix = &ixgbe_get_wwn_prefix_generic; /* RAR, Multicast, VLAN */ - mac->ops.set_vmdq = &ixgbe_set_vmdq_82599; - mac->ops.clear_vmdq = &ixgbe_clear_vmdq_82599; - mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_82599; + mac->ops.set_vmdq = &ixgbe_set_vmdq_generic; + mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic; + mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic; mac->rar_highwater = 1; - mac->ops.set_vfta = &ixgbe_set_vfta_82599; - mac->ops.clear_vfta = &ixgbe_clear_vfta_82599; - mac->ops.init_uta_tables = &ixgbe_init_uta_tables_82599; + mac->ops.set_vfta = &ixgbe_set_vfta_generic; + mac->ops.clear_vfta = &ixgbe_clear_vfta_generic; + mac->ops.init_uta_tables = &ixgbe_init_uta_tables_generic; mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_82599; /* Link */ mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599; - mac->ops.check_link = &ixgbe_check_mac_link_82599; + mac->ops.check_link = &ixgbe_check_mac_link_generic; ixgbe_init_mac_link_ops_82599(hw); mac->mcft_size = 128; @@ -281,7 +240,7 @@ mac->num_rar_entries = 128; mac->max_tx_queues = 128; mac->max_rx_queues = 128; - mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw); + mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw); return (ret_val); } @@ -301,6 +260,8 @@ s32 status = IXGBE_SUCCESS; u32 autoc = 0; + DEBUGFUNC("ixgbe_get_link_capabilities_82599"); + /* * Determine link capabilities based on the stored value of AUTOC, * which represents EEPROM defaults. If AUTOC value has not @@ -386,6 +347,8 @@ { enum ixgbe_media_type media_type; + DEBUGFUNC("ixgbe_get_media_type_82599"); + /* Detect if there is a copper PHY attached. */ if (hw->phy.type == ixgbe_phy_cu_unknown || hw->phy.type == ixgbe_phy_tn || @@ -396,17 +359,18 @@ switch (hw->device_id) { case IXGBE_DEV_ID_82599_KX4: - case IXGBE_DEV_ID_82599_KX4_SIK: + case IXGBE_DEV_ID_82599_KX4_MEZZ: + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; break; case IXGBE_DEV_ID_82599_SFP: - case IXGBE_DEV_ID_82599_SPW: + case IXGBE_DEV_ID_82599_SFP_EM: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82599_CX4: - media_type = ixgbe_media_type_fiber; + media_type = ixgbe_media_type_cx4; break; default: media_type = ixgbe_media_type_unknown; @@ -417,27 +381,29 @@ } /* - * ixgbe_setup_mac_link_82599 - Setup MAC link settings + * ixgbe_start_mac_link_82599 - Setup MAC link settings * @hw: pointer to hardware structure * * Configures link settings based on values in the ixgbe_hw struct. * Restarts the link. Performs autonegotiation if needed. */ s32 -ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw) +ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete) { u32 autoc_reg; u32 links_reg; u32 i; s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_start_mac_link_82599"); + /* Restart link */ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); /* Only poll for autoneg to complete if specified to do so */ - if (hw->phy.autoneg_wait_to_complete) { + if (autoneg_wait_to_complete) { if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) == IXGBE_AUTOC_LMS_KX4_KX_KR || (autoc_reg & IXGBE_AUTOC_LMS_MASK) == @@ -465,28 +431,7 @@ } /* - * ixgbe_setup_mac_link_multispeed_fiber - Setup MAC link settings - * @hw: pointer to hardware structure - * - * Configures link settings based on values in the ixgbe_hw struct. - * Restarts the link for multi-speed fiber at 1G speed, if link - * fails at 10G. - * Performs autonegotiation if needed. - */ -s32 -ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw) -{ - s32 status = IXGBE_SUCCESS; - ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_82599_AUTONEG; - DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); - - status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw, - link_speed, true, true); - return (status); -} - -/* - * ixgbe_setup_mac_link_speed_multispeed_fiber - Set MAC link speed + * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled @@ -495,7 +440,7 @@ * Set the link speed in the AUTOC register and restarts link. */ s32 -ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw, +ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = IXGBE_SUCCESS; @@ -507,22 +452,15 @@ bool link_up = false; bool negotiation; + DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); + /* Mask off requested but non-supported speeds */ status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation); if (status != IXGBE_SUCCESS) - goto out; + return (status); speed &= link_speed; - /* Set autoneg_advertised value based on input link speed */ - hw->phy.autoneg_advertised = 0; - - if (speed & IXGBE_LINK_SPEED_10GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; - - if (speed & IXGBE_LINK_SPEED_1GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; - /* * When the driver changes the link speeds that it can support, * it sets autotry_restart to true to indicate that we need to @@ -544,7 +482,7 @@ /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) - goto out; + return (status); if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) goto out; @@ -556,11 +494,11 @@ /* Allow module to change analog characteristics (1G->10G) */ msec_delay(40); - status = ixgbe_setup_mac_link_speed_82599( + status = ixgbe_setup_mac_link_82599( hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) - goto out; + return (status); /* Flap the tx laser if it has not already been done */ if (hw->mac.autotry_restart) { @@ -577,7 +515,11 @@ hw->mac.autotry_restart = false; } - /* The controller may take up to 500ms at 10g to acquire link */ + /* + * Wait for the controller to acquire link. Per IEEE 802.3ap, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted. 82599 uses the same timing for 10g SFI. + */ for (i = 0; i < 5; i++) { /* Wait for the link partner to also set speed */ msec_delay(100); @@ -586,7 +528,7 @@ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) - goto out; + return (status); if (link_up) goto out; @@ -601,7 +543,7 @@ /* If we already have link at this speed, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) - goto out; + return (status); if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) goto out; @@ -614,11 +556,11 @@ /* Allow module to change analog characteristics (10G->1G) */ msec_delay(40); - status = ixgbe_setup_mac_link_speed_82599( + status = ixgbe_setup_mac_link_82599( hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg, autoneg_wait_to_complete); if (status != IXGBE_SUCCESS) - goto out; + return (status); /* Flap the tx laser if it has not already been done */ if (hw->mac.autotry_restart) { @@ -641,7 +583,7 @@ /* If we have link, just jump out */ status = ixgbe_check_link(hw, &link_speed, &link_up, false); if (status != IXGBE_SUCCESS) - goto out; + return (status); if (link_up) goto out; @@ -653,68 +595,134 @@ * single highest speed that the user requested. */ if (speedcnt > 1) - status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw, + status = ixgbe_setup_mac_link_multispeed_fiber(hw, highest_link_speed, autoneg, autoneg_wait_to_complete); out: + /* Set autoneg_advertised value based on input link speed */ + hw->phy.autoneg_advertised = 0; + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + return (status); +} + +/* + * ixgbe_setup_mac_link_smartspeed - Set MAC link speed using SmartSpeed + * @hw: pointer to hardware structure + * @speed: new link speed + * @autoneg: true if autonegotiation enabled + * @autoneg_wait_to_complete: true when waiting for completion is needed + * + * Implements the Intel SmartSpeed algorithm. + */ +s32 +ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, + ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) +{ + s32 status = IXGBE_SUCCESS; + ixgbe_link_speed link_speed; + s32 i, j; + bool link_up = false; + u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + DEBUGFUNC("ixgbe_setup_mac_link_smartspeed"); + + /* Set autoneg_advertised value based on input link speed */ + hw->phy.autoneg_advertised = 0; + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + if (speed & IXGBE_LINK_SPEED_100_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; + + /* + * Implement Intel SmartSpeed algorithm. SmartSpeed will reduce the + * autoneg advertisement if link is unable to be established at the + * highest negotiated rate. This can sometimes happen due to integrity + * issues with the physical media connection. + */ + + /* First, try to get link with full advertisement */ + hw->phy.smart_speed_active = false; + for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) { + status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, + autoneg_wait_to_complete); + if (status != IXGBE_SUCCESS) + goto out; + + /* + * Wait for the controller to acquire link. Per IEEE 802.3ap, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted, or 200ms if KX/KX4/BX/BX4 is attempted, per + * Table 9 in the AN MAS. + */ + for (i = 0; i < 5; i++) { + msec_delay(100); + + /* If we have link, just jump out */ + status = ixgbe_check_link(hw, &link_speed, &link_up, + false); + if (status != IXGBE_SUCCESS) + goto out; + + if (link_up) + goto out; + } + } + + /* + * We didn't get link. If we advertised KR plus one of KX4/KX + * (or BX4/BX), then disable KR and try again. + */ + if (((autoc_reg & IXGBE_AUTOC_KR_SUPP) == 0) || + ((autoc_reg & IXGBE_AUTOC_KX4_KX_SUPP_MASK) == 0)) + goto out; + + /* Turn SmartSpeed on to disable KR support */ + hw->phy.smart_speed_active = true; + status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, + autoneg_wait_to_complete); + if (status != IXGBE_SUCCESS) + goto out; + + /* + * Wait for the controller to acquire link. 600ms will allow for + * the AN link_fail_inhibit_timer as well for multiple cycles of + * parallel detect, both 10g and 1g. This allows for the maximum + * connect attempts as defined in the AN MAS table 73-7. + */ + for (i = 0; i < 6; i++) { + msec_delay(100); + + /* If we have link, just jump out */ + status = ixgbe_check_link(hw, &link_speed, &link_up, false); + if (status != IXGBE_SUCCESS) + goto out; + + if (link_up) + goto out; + } + + /* We didn't get link. Turn SmartSpeed back off. */ + hw->phy.smart_speed_active = false; + status = ixgbe_setup_mac_link_82599(hw, speed, autoneg, + autoneg_wait_to_complete); + +out: return (status); } /* - * ixgbe_check_mac_link_82599 - Determine link and speed status - * @hw: pointer to hardware structure - * @speed: pointer to link speed - * @link_up: true when link is up - * @link_up_wait_to_complete: bool used to wait for link up or not - * - * Reads the links register to determine if link is up and the current speed - */ -s32 -ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete) -{ - u32 links_reg; - u32 i; - - links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); - if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { - if (links_reg & IXGBE_LINKS_UP) { - *link_up = true; - break; - } else { - *link_up = false; - } - msec_delay(100); - links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); - } - } else { - if (links_reg & IXGBE_LINKS_UP) - *link_up = true; - else - *link_up = false; - } - - if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_10G_82599) - *speed = IXGBE_LINK_SPEED_10GB_FULL; - else if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_1G_82599) - *speed = IXGBE_LINK_SPEED_1GB_FULL; - else - *speed = IXGBE_LINK_SPEED_100_FULL; - - /* if link is down, zero out the current_mode */ - if (*link_up == false) { - hw->fc.current_mode = ixgbe_fc_none; - hw->fc.fc_was_autonegged = false; - } - - return (IXGBE_SUCCESS); -} - -/* - * ixgbe_setup_mac_link_speed_82599 - Set MAC link speed + * ixgbe_setup_mac_link_82599 - Set MAC link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled @@ -723,7 +731,7 @@ * Set the link speed in the AUTOC register and restarts link. */ s32 -ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw, +ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status = IXGBE_SUCCESS; @@ -738,6 +746,8 @@ u32 i; ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN; + DEBUGFUNC("ixgbe_setup_mac_link_82599"); + /* Check to see if speed passed in is supported. */ status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg); if (status != IXGBE_SUCCESS) @@ -766,7 +776,8 @@ if (speed & IXGBE_LINK_SPEED_10GB_FULL) if (orig_autoc & IXGBE_AUTOC_KX4_SUPP) autoc |= IXGBE_AUTOC_KX4_SUPP; - if (orig_autoc & IXGBE_AUTOC_KR_SUPP) + if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) && + (hw->phy.smart_speed_active == false)) autoc |= IXGBE_AUTOC_KR_SUPP; if (speed & IXGBE_LINK_SPEED_1GB_FULL) autoc |= IXGBE_AUTOC_KX_SUPP; @@ -827,27 +838,7 @@ } /* - * ixgbe_setup_copper_link_82599 - Setup copper link settings - * @hw: pointer to hardware structure - * - * Restarts the link on PHY and then MAC. Performs autonegotiation if needed. - */ -static s32 -ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw) -{ - s32 status; - - /* Restart autonegotiation on PHY */ - status = hw->phy.ops.setup_link(hw); - - /* Set up MAC */ - (void) ixgbe_setup_mac_link_82599(hw); - - return (status); -} - -/* - * ixgbe_setup_copper_link_speed_82599 - Set the PHY autoneg advertised field + * ixgbe_setup_copper_link_82599 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled @@ -856,16 +847,18 @@ * Restarts link on PHY and MAC based on settings passed in. */ static s32 -ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw, +ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { s32 status; + DEBUGFUNC("ixgbe_setup_copper_link_82599"); + /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg, autoneg_wait_to_complete); /* Set up MAC */ - (void) ixgbe_setup_mac_link_82599(hw); + (void) ixgbe_start_mac_link_82599(hw, autoneg_wait_to_complete); return (status); } @@ -886,6 +879,8 @@ u32 autoc; u32 autoc2; + DEBUGFUNC("ixgbe_reset_hw_82599"); + /* Call adapter stop to disable tx/rx and clear interrupts */ hw->mac.ops.stop_adapter(hw); @@ -997,319 +992,15 @@ hw->mac.num_rar_entries--; } + /* Store the alternative WWNN/WWPN prefix */ + hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix, + &hw->mac.wwpn_prefix); + reset_hw_out: return (status); } /* - * ixgbe_insert_mac_addr_82599 - Find a RAR for this mac address - * @hw: pointer to hardware structure - * @addr: Address to put into receive address register - * @vmdq: VMDq pool to assign - * - * Puts an ethernet address into a receive address register, or - * finds the rar that it is aleady in; adds to the pool list - */ -s32 -ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) -{ - static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; - u32 first_empty_rar = NO_EMPTY_RAR_FOUND; - u32 rar; - u32 rar_low, rar_high; - u32 addr_low, addr_high; - - /* swap bytes for HW little endian */ - addr_low = addr[0] | (addr[1] << 8) - | (addr[2] << 16) - | (addr[3] << 24); - addr_high = addr[4] | (addr[5] << 8); - - /* - * Either find the mac_id in rar or find the first empty space. - * rar_highwater points to just after the highest currently used - * rar in order to shorten the search. It grows when we add a new - * rar to the top. - */ - for (rar = 0; rar < hw->mac.rar_highwater; rar++) { - rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); - - if (((IXGBE_RAH_AV & rar_high) == 0) && - first_empty_rar == NO_EMPTY_RAR_FOUND) { - first_empty_rar = rar; - } else if ((rar_high & 0xFFFF) == addr_high) { - rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); - if (rar_low == addr_low) - break; /* found it already in the rars */ - } - } - - if (rar < hw->mac.rar_highwater) { - /* already there so just add to the pool bits */ - (void) ixgbe_set_vmdq(hw, rar, vmdq); - } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { - /* stick it into first empty RAR slot we found */ - rar = first_empty_rar; - (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); - } else if (rar == hw->mac.rar_highwater) { - /* add it to the top of the list and inc the highwater mark */ - (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); - hw->mac.rar_highwater++; - } else if (rar >= hw->mac.num_rar_entries) { - return (IXGBE_ERR_INVALID_MAC_ADDR); - } - - /* - * If we found rar[0], make sure the default pool bit (we use pool 0) - * remains cleared to be sure default pool packets will get delivered - */ - if (rar == 0) - (void) ixgbe_clear_vmdq(hw, rar, 0); - - return (rar); -} - -/* - * ixgbe_clear_vmdq_82599 - Disassociate a VMDq pool index from a rx address - * @hw: pointer to hardware struct - * @rar: receive address register index to disassociate - * @vmdq: VMDq pool index to remove from the rar - */ -s32 -ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq) -{ - u32 mpsar_lo, mpsar_hi; - u32 rar_entries = hw->mac.num_rar_entries; - - if (rar < rar_entries) { - mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); - mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); - - if (!mpsar_lo && !mpsar_hi) { - goto done; - } - - if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { - if (mpsar_lo) { - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); - mpsar_lo = 0; - } - if (mpsar_hi) { - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); - mpsar_hi = 0; - } - } else if (vmdq < 32) { - mpsar_lo &= ~(1 << vmdq); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); - } else { - mpsar_hi &= ~(1 << (vmdq - 32)); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); - } - - /* was that the last pool using this rar? */ - if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) { - hw->mac.ops.clear_rar(hw, rar); - } - } else { - DEBUGOUT1("RAR index %d is out of range.\n", rar); - return (IXGBE_ERR_PARAM); - } -done: - return (IXGBE_SUCCESS); -} - -/* - * ixgbe_set_vmdq_82599 - Associate a VMDq pool index with a rx address - * @hw: pointer to hardware struct - * @rar: receive address register index to associate with a VMDq index - * @vmdq: VMDq pool index - */ -s32 -ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq) -{ - u32 mpsar; - u32 rar_entries = hw->mac.num_rar_entries; - - if (rar < rar_entries) { - if (vmdq < 32) { - mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); - mpsar |= 1 << vmdq; - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); - } else { - mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); - mpsar |= 1 << (vmdq - 32); - IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); - } - } else { - DEBUGOUT1("RAR index %d is out of range.\n", rar); - return (IXGBE_ERR_PARAM); - } - - return (IXGBE_SUCCESS); -} - -/* - * ixgbe_set_vfta_82599 - Set VLAN filter table - * @hw: pointer to hardware structure - * @vlan: VLAN id to write to VLAN filter - * @vind: VMDq output index that maps queue to VLAN id in VFVFB - * @vlan_on: boolean flag to turn on/off VLAN in VFVF - * - * Turn on/off specified VLAN in the VLAN filter table. - */ -s32 -ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) -{ - u32 regindex; - u32 bitindex; - u32 bits; - u32 first_empty_slot; - - if (vlan > 4095) { - return (IXGBE_ERR_PARAM); - } - - /* - * this is a 2 part operation - first the VFTA, then the - * VLVF and VLVFB if vind is set - */ - - /* - * Part 1 - * The VFTA is a bitstring made up of 128 32-bit registers - * that enable the particular VLAN id, much like the MTA: - * bits[11-5]: which register - * bits[4-0]: which bit in the register - */ - regindex = (vlan >> 5) & 0x7F; - bitindex = vlan & 0x1F; - bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); - if (vlan_on) { - bits |= (1 << bitindex); - } else { - bits &= ~(1 << bitindex); - } - IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); - - - /* - * Part 2 - * If the vind is set - * Either vlan_on - * make sure the vlan is in VLVF - * set the vind bit in the matching VLVFB - * Or !vlan_on - * clear the pool bit and possibly the vind - */ - if (vind) { - /* find the vlanid or the first empty slot */ - first_empty_slot = 0; - - for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { - bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); - if (!bits && !first_empty_slot) - first_empty_slot = regindex; - else if ((bits & 0x0FFF) == vlan) - break; - } - - if (regindex >= IXGBE_VLVF_ENTRIES) { - if (first_empty_slot) - regindex = first_empty_slot; - else { - DEBUGOUT("No space in VLVF.\n"); - goto out; - } - } - - - if (vlan_on) { - /* set the pool bit */ - if (vind < 32) { - bits = - IXGBE_READ_REG(hw, IXGBE_VLVFB(regindex*2)); - bits |= (1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex*2), bits); - } else { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - bits |= (1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex*2)+1), bits); - } - } else { - /* clear the pool bit */ - if (vind < 32) { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); - bits &= ~(1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex*2), bits); - bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - } else { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex*2)+1)); - bits &= ~(1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex*2)+1), bits); - bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex*2)); - } - } - - if (bits) - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), - (IXGBE_VLVF_VIEN | vlan)); - else - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0); - } - -out: - return (IXGBE_SUCCESS); -} - -/* - * ixgbe_clear_vfta_82599 - Clear VLAN filter table - * @hw: pointer to hardware structure - * - * Clears the VLAN filer table, and the VMDq index associated with the filter - */ -s32 -ixgbe_clear_vfta_82599(struct ixgbe_hw *hw) -{ - u32 offset; - - for (offset = 0; offset < hw->mac.vft_size; offset++) - IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); - - for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { - IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); - IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0); - IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0); - } - - return (IXGBE_SUCCESS); -} - -/* - * ixgbe_init_uta_tables_82599 - Initialize the Unicast Table Array - * @hw: pointer to hardware structure - */ -s32 -ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw) -{ - int i; - DEBUGOUT(" Clearing UTA\n"); - - for (i = 0; i < 128; i++) - IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); - - return (IXGBE_SUCCESS); -} - -/* * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables. * @hw: pointer to hardware structure */ @@ -1320,6 +1011,8 @@ u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE; + DEBUGFUNC("ixgbe_reinit_fdir_tables_82599"); + /* * Before starting reinitialization process, * FDIRCMD.CMD must be zero. @@ -1397,6 +1090,8 @@ u32 pbsize; int i; + DEBUGFUNC("ixgbe_init_fdir_signature_82599"); + /* * Before enabling Flow Director, the Rx Packet Buffer size * must be reduced. The new value is the current size minus @@ -1489,6 +1184,8 @@ u32 pbsize; int i; + DEBUGFUNC("ixgbe_init_fdir_perfect_82599"); + /* * Before enabling Flow Director, the Rx Packet Buffer size * must be reduced. The new value is the current size minus @@ -1626,6 +1323,8 @@ u16 hash_result = 0; int i, j, k, h; + DEBUGFUNC("ixgbe_atr_compute_hash_82599"); + /* * Initialize the fill member to prevent warnings * on some compilers @@ -1704,6 +1403,8 @@ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) { + DEBUGFUNC("ixgbe_atr_set_vlan_id_82599"); + input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8; input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff; @@ -1718,6 +1419,8 @@ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) { + DEBUGFUNC("ixgbe_atr_set_src_ipv4_82599"); + input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24; input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] = (src_addr >> 16) & 0xff; @@ -1736,6 +1439,8 @@ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr) { + DEBUGFUNC("ixgbe_atr_set_dst_ipv4_82599"); + input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24; input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] = (dst_addr >> 16) & 0xff; @@ -1758,6 +1463,8 @@ ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, u32 src_addr_1, u32 src_addr_2, u32 src_addr_3, u32 src_addr_4) { + DEBUGFUNC("ixgbe_atr_set_src_ipv6_82599"); + input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff; input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] = (src_addr_4 >> 8) & 0xff; @@ -1801,6 +1508,8 @@ ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, u32 dst_addr_1, u32 dst_addr_2, u32 dst_addr_3, u32 dst_addr_4) { + DEBUGFUNC("ixgbe_atr_set_dst_ipv6_82599"); + input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff; input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] = (dst_addr_4 >> 8) & 0xff; @@ -1840,6 +1549,8 @@ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) { + DEBUGFUNC("ixgbe_atr_set_src_port_82599"); + input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8; input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff; @@ -1854,6 +1565,8 @@ s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port) { + DEBUGFUNC("ixgbe_atr_set_dst_port_82599"); + input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8; input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff; @@ -1868,6 +1581,8 @@ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte) { + DEBUGFUNC("ixgbe_atr_set_flex_byte_82599"); + input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8; input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff; @@ -1882,6 +1597,8 @@ s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool) { + DEBUGFUNC("ixgbe_atr_set_vm_pool_82599"); + input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool; return (IXGBE_SUCCESS); @@ -1895,6 +1612,8 @@ s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type) { + DEBUGFUNC("ixgbe_atr_set_l4type_82599"); + input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type; return (IXGBE_SUCCESS); @@ -1908,6 +1627,8 @@ s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan) { + DEBUGFUNC("ixgbe_atr_get_vlan_id_82599"); + *vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET]; *vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8; @@ -1922,6 +1643,8 @@ s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr) { + DEBUGFUNC("ixgbe_atr_get_src_ipv4_82599"); + *src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET]; *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8; *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16; @@ -1938,6 +1661,8 @@ s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr) { + DEBUGFUNC("ixgbe_atr_get_dst_ipv4_82599"); + *dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET]; *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8; *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16; @@ -1958,6 +1683,8 @@ ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input, u32 *src_addr_1, u32 *src_addr_2, u32 *src_addr_3, u32 *src_addr_4) { + DEBUGFUNC("ixgbe_atr_get_src_ipv6_82599"); + *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12]; *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8; *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16; @@ -1993,6 +1720,8 @@ ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, u32 *dst_addr_1, u32 *dst_addr_2, u32 *dst_addr_3, u32 *dst_addr_4) { + DEBUGFUNC("ixgbe_atr_get_dst_ipv6_82599"); + *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12]; *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8; *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16; @@ -2029,6 +1758,8 @@ s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port) { + DEBUGFUNC("ixgbe_atr_get_src_port_82599"); + *src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8; *src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1]; @@ -2048,6 +1779,8 @@ s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port) { + DEBUGFUNC("ixgbe_atr_get_dst_port_82599"); + *dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8; *dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1]; @@ -2062,6 +1795,8 @@ s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte) { + DEBUGFUNC("ixgbe_atr_get_flex_byte_82599"); + *flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET]; *flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8; @@ -2076,6 +1811,8 @@ s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool) { + DEBUGFUNC("ixgbe_atr_get_vm_pool_82599"); + *vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET]; return (IXGBE_SUCCESS); @@ -2089,6 +1826,8 @@ s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type) { + DEBUGFUNC("ixgbe_atr_get_l4type__82599"); + *l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET]; return (IXGBE_SUCCESS); @@ -2110,6 +1849,8 @@ u16 bucket_hash, sig_hash; u8 l4type; + DEBUGFUNC("ixgbe_fdir_add_signature_filter_82599"); + bucket_hash = ixgbe_atr_compute_hash_82599(input, IXGBE_ATR_BUCKET_HASH_KEY); @@ -2180,6 +1921,8 @@ u16 bucket_hash; u8 l4type; + DEBUGFUNC("ixgbe_fdir_add_perfect_filter_82599"); + /* Get our input values */ (void) ixgbe_atr_get_l4type_82599(input, &l4type); @@ -2269,6 +2012,8 @@ { u32 core_ctl; + DEBUGFUNC("ixgbe_read_analog_reg8_82599"); + IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD | (reg << 8)); IXGBE_WRITE_FLUSH(hw); @@ -2292,6 +2037,8 @@ { u32 core_ctl; + DEBUGFUNC("ixgbe_write_analog_reg8_82599"); + core_ctl = (reg << 8) | val; IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl); IXGBE_WRITE_FLUSH(hw); @@ -2311,14 +2058,16 @@ s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw) { - u32 q_num; + u32 i; s32 ret_val = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_start_hw_rev_1__82599"); + ret_val = ixgbe_start_hw_generic(hw); /* Clear the rate limiters */ - for (q_num = 0; q_num < hw->mac.max_tx_queues; q_num++) { - IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, q_num); + for (i = 0; i < hw->mac.max_tx_queues; i++) { + IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, i); IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0); } IXGBE_WRITE_FLUSH(hw); @@ -2345,6 +2094,8 @@ { s32 status = IXGBE_ERR_PHY_ADDR_INVALID; + DEBUGFUNC("ixgbe_identify_phy_82599"); + /* Detect PHY if not unknown - returns success if already detected. */ status = ixgbe_identify_phy_generic(hw); if (status != IXGBE_SUCCESS) @@ -2380,10 +2131,12 @@ u16 ext_ability = 0; u8 comp_codes_10g = 0; + DEBUGFUNC("ixgbe_get_support_physical_layer_82599"); + hw->phy.ops.identify(hw); if (hw->phy.type == ixgbe_phy_tn || - hw->phy.type == ixgbe_phy_tn || + hw->phy.type == ixgbe_phy_aq || hw->phy.type == ixgbe_phy_cu_unknown) { hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability); @@ -2483,6 +2236,8 @@ int i; int secrxreg; + DEBUGFUNC("ixgbe_enable_rx_dma_82599"); + /* * Workaround for 82599 silicon errata when enabling the Rx datapath. * If traffic is incoming before we enable the Rx unit, it could hang @@ -2526,121 +2281,14 @@ s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps) { + DEBUGFUNC("ixgbe_get_device_caps_82599"); + hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps); return (IXGBE_SUCCESS); } /* - * ixgbe_get_san_mac_addr_offset_82599 - SAN MAC address offset for 82599 - * @hw: pointer to hardware structure - * @san_mac_offset: SAN MAC address offset - * - * This function will read the EEPROM location for the SAN MAC address - * pointer, and returns the value at that location. This is used in both - * get and set mac_addr routines. - */ -s32 -ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw, u16 *san_mac_offset) -{ - /* - * First read the EEPROM pointer to see if the MAC addresses are - * available. - */ - hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); - - return (IXGBE_SUCCESS); -} - -/* - * ixgbe_get_san_mac_addr_82599 - SAN MAC address retrieval for 82599 - * @hw: pointer to hardware structure - * @san_mac_addr: SAN MAC address - * - * Reads the SAN MAC address from the EEPROM, if it's available. This is - * per-port, so set_lan_id() must be called before reading the addresses. - * set_lan_id() is called by identify_sfp(), but this cannot be relied - * upon for non-SFP connections, so we must call it here. - */ -s32 -ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr) -{ - u16 san_mac_data, san_mac_offset; - u8 i; - - /* - * First read the EEPROM pointer to see if the MAC addresses are - * available. If they're not, no point in calling set_lan_id() here. - */ - (void) ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset); - - if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { - /* - * No addresses available in this EEPROM. It's not an - * error though, so just wipe the local address and return. - */ - for (i = 0; i < 6; i++) - san_mac_addr[i] = 0xFF; - - goto san_mac_addr_out; - } - - /* make sure we know which port we need to program */ - hw->mac.ops.set_lan_id(hw); - /* apply the port offset to the address offset */ - (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : - (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); - for (i = 0; i < 3; i++) { - hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); - san_mac_addr[i * 2] = (u8)(san_mac_data); - san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); - san_mac_offset++; - } - -san_mac_addr_out: - return (IXGBE_SUCCESS); -} - -/* - * ixgbe_set_san_mac_addr_82599 - Write the SAN MAC address to the EEPROM - * @hw: pointer to hardware structure - * @san_mac_addr: SAN MAC address - * - * Write a SAN MAC address to the EEPROM. - */ -s32 -ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr) -{ - s32 status = IXGBE_SUCCESS; - u16 san_mac_data, san_mac_offset; - u8 i; - - /* Look for SAN mac address pointer. If not defined, return */ - (void) ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset); - - if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { - status = IXGBE_ERR_NO_SAN_ADDR_PTR; - goto san_mac_addr_out; - } - - /* Make sure we know which port we need to write */ - hw->mac.ops.set_lan_id(hw); - /* Apply the port offset to the address offset */ - (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : - (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); - - for (i = 0; i < 3; i++) { - san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); - san_mac_data |= (u16)(san_mac_addr[i * 2]); - hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); - san_mac_offset++; - } - -san_mac_addr_out: - return (status); -} - -/* * ixgbe_verify_fw_version_82599 - verify fw version for 82599 * @hw: pointer to hardware structure * @@ -2657,6 +2305,8 @@ u16 fw_offset, fw_ptp_cfg_offset; u16 fw_version = 0; + DEBUGFUNC("ixgbe_verify_fw_version_82599"); + /* firmware check is only necessary for SFI devices */ if (hw->phy.media_type != ixgbe_media_type_fiber) { status = IXGBE_SUCCESS;
--- a/usr/src/uts/common/io/ixgbe/ixgbe_api.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_api.c Sun Nov 08 15:49:56 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.120 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.131 scm_100309_002210 */ #include "ixgbe_api.h" #include "ixgbe_common.h" @@ -51,6 +51,8 @@ { s32 status; + DEBUGFUNC("ixgbe_init_shared_code"); + /* * Set the mac type */ @@ -92,6 +94,7 @@ case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AT: + case IXGBE_DEV_ID_82598AT2: case IXGBE_DEV_ID_82598EB_CX4: case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: case IXGBE_DEV_ID_82598_DA_DUAL_PORT: @@ -101,10 +104,11 @@ hw->mac.type = ixgbe_mac_82598EB; break; case IXGBE_DEV_ID_82599_KX4: - case IXGBE_DEV_ID_82599_KX4_SIK: + case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_XAUI_LOM: + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_SFP: - case IXGBE_DEV_ID_82599_SPW: + case IXGBE_DEV_ID_82599_SFP_EM: case IXGBE_DEV_ID_82599_CX4: hw->mac.type = ixgbe_mac_82599EB; break; @@ -254,6 +258,22 @@ } /* + * ixgbe_get_wwn_prefix - Get alternative WWNN/WWPN prefix from the EEPROM + * @hw: pointer to hardware structure + * @wwnn_prefix: the alternative WWNN prefix + * @wwpn_prefix: the alternative WWPN prefix + * + * This function will read the EEPROM from the alternative SAN MAC address + * block to check the support for the alternative WWNN/WWPN prefix support. + */ +s32 +ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, u16 *wwpn_prefix) +{ + return ixgbe_call_func(hw, hw->mac.ops.get_wwn_prefix, + (hw, wwnn_prefix, wwpn_prefix), IXGBE_NOT_IMPLEMENTED); +} + +/* * ixgbe_get_bus_info - Set PCI bus info * @hw: pointer to hardware structure * @@ -460,20 +480,6 @@ } /* - * ixgbe_setup_link - Configure link settings - * @hw: pointer to hardware structure - * - * Configures link settings based on values in the ixgbe_hw struct. - * Restarts the link. Performs autonegotiation if needed. - */ -s32 -ixgbe_setup_link(struct ixgbe_hw *hw) -{ - return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw), - IXGBE_NOT_IMPLEMENTED); -} - -/* * ixgbe_check_link - Get link and speed status * @hw: pointer to hardware structure * @@ -488,18 +494,19 @@ } /* - * ixgbe_setup_link_speed - Set link speed + * ixgbe_setup_link - Set link speed * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * - * Set the link speed and restarts the link. + * Configures link settings. Restarts the link. + * Performs autonegotiation if needed. */ -s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, +s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) { - return ixgbe_call_func(hw, hw->mac.ops.setup_link_speed, (hw, speed, + return ixgbe_call_func(hw, hw->mac.ops.setup_link, (hw, speed, autoneg, autoneg_wait_to_complete), IXGBE_NOT_IMPLEMENTED); }
--- a/usr/src/uts/common/io/ixgbe/ixgbe_api.h Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_api.h Sun Nov 08 15:49:56 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.74 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.77 scm_100309_002210 */ #ifndef _IXGBE_API_H #define _IXGBE_API_H @@ -60,8 +60,7 @@ ixgbe_link_speed *speed, bool *link_up); s32 ixgbe_setup_phy_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); -s32 ixgbe_setup_link(struct ixgbe_hw *hw); -s32 ixgbe_setup_link_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed, +s32 ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete); s32 ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); @@ -90,6 +89,7 @@ u32 addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_update_mc_addr_list(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func); +void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr_list, u32 vmdq); s32 ixgbe_enable_mc(struct ixgbe_hw *hw); s32 ixgbe_disable_mc(struct ixgbe_hw *hw); s32 ixgbe_clear_vfta(struct ixgbe_hw *hw); @@ -149,5 +149,7 @@ s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps); s32 ixgbe_acquire_swfw_semaphore(struct ixgbe_hw *hw, u16 mask); void ixgbe_release_swfw_semaphore(struct ixgbe_hw *hw, u16 mask); +s32 ixgbe_get_wwn_prefix(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix); #endif /* _IXGBE_API_H */
--- a/usr/src/uts/common/io/ixgbe/ixgbe_common.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_common.c Sun Nov 08 15:49:56 2009 +0800 @@ -25,12 +25,11 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.206 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.218 scm_100309_002210 */ #include "ixgbe_common.h" #include "ixgbe_api.h" -static s32 ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw); static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw); static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw); static void ixgbe_release_eeprom_semaphore(struct ixgbe_hw *hw); @@ -45,6 +44,9 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); +static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, + u16 *san_mac_offset); +s32 ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan); /* * ixgbe_init_ops_generic - Inits function ptrs @@ -59,11 +61,13 @@ struct ixgbe_mac_info *mac = &hw->mac; u32 eec = IXGBE_READ_REG(hw, IXGBE_EEC); + DEBUGFUNC("ixgbe_init_ops_generic"); + /* EEPROM */ eeprom->ops.init_params = &ixgbe_init_eeprom_params_generic; /* If EEPROM is valid (bit 8 = 1), use EERD otherwise use bit bang */ if (eec & (1 << 8)) - eeprom->ops.read = &ixgbe_read_eeprom_generic; + eeprom->ops.read = &ixgbe_read_eerd_generic; else eeprom->ops.read = &ixgbe_read_eeprom_bit_bang_generic; eeprom->ops.write = &ixgbe_write_eeprom_generic; @@ -113,7 +117,6 @@ /* Link */ mac->ops.get_link_capabilities = NULL; mac->ops.setup_link = NULL; - mac->ops.setup_link_speed = NULL; mac->ops.check_link = NULL; return (IXGBE_SUCCESS); @@ -133,6 +136,8 @@ { u32 ctrl_ext; + DEBUGFUNC("ixgbe_start_hw_generic"); + /* Set the media type */ hw->phy.media_type = hw->mac.ops.get_media_type(hw); @@ -174,6 +179,8 @@ { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_init_hw_generic"); + /* Reset the hardware */ status = hw->mac.ops.reset_hw(hw); @@ -197,6 +204,8 @@ { u16 i = 0; + DEBUGFUNC("ixgbe_clear_hw_cntrs_generic"); + (void) IXGBE_READ_REG(hw, IXGBE_CRCERRS); (void) IXGBE_READ_REG(hw, IXGBE_ILLERRC); (void) IXGBE_READ_REG(hw, IXGBE_ERRBC); @@ -330,6 +339,8 @@ u32 rar_low; u16 i; + DEBUGFUNC("ixgbe_get_mac_addr_generic"); + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(0)); rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(0)); @@ -354,6 +365,8 @@ struct ixgbe_mac_info *mac = &hw->mac; u16 link_status; + DEBUGFUNC("ixgbe_get_bus_info_generic"); + hw->bus.type = ixgbe_bus_type_pci_express; /* Get the negotiated link width and speed from PCI config space */ @@ -408,6 +421,8 @@ struct ixgbe_bus_info *bus = &hw->bus; u32 reg; + DEBUGFUNC("ixgbe_set_lan_id_multi_port_pcie"); + reg = IXGBE_READ_REG(hw, IXGBE_STATUS); bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT; bus->lan_id = bus->func; @@ -434,6 +449,8 @@ u32 reg_val; u16 i; + DEBUGFUNC("ixgbe_stop_adapter_generic"); + /* * Set the adapter_stopped flag so other driver functions stop touching * the hardware @@ -484,6 +501,8 @@ { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_led_on_generic"); + /* To turn on the LED, set mode to ON. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_ON << IXGBE_LED_MODE_SHIFT(index); @@ -503,6 +522,8 @@ { u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_led_off_generic"); + /* To turn off the LED, set mode to OFF. */ led_reg &= ~IXGBE_LED_MODE_MASK(index); led_reg |= IXGBE_LED_OFF << IXGBE_LED_MODE_SHIFT(index); @@ -526,6 +547,8 @@ u32 eec; u16 eeprom_size; + DEBUGFUNC("ixgbe_init_eeprom_params_generic"); + if (eeprom->type == ixgbe_eeprom_uninitialized) { eeprom->type = ixgbe_eeprom_none; /* @@ -549,7 +572,7 @@ eeprom_size = (u16)((eec & IXGBE_EEC_SIZE) >> IXGBE_EEC_SIZE_SHIFT); eeprom->word_size = 1 << (eeprom_size + - IXGBE_EEPROM_WORD_SIZE_SHIFT); + IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT); } if (eec & IXGBE_EEC_ADDR_SIZE) @@ -579,6 +602,8 @@ s32 status; u8 write_opcode = IXGBE_EEPROM_WRITE_OPCODE_SPI; + DEBUGFUNC("ixgbe_write_eeprom_generic"); + hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { @@ -647,6 +672,8 @@ u16 word_in; u8 read_opcode = IXGBE_EEPROM_READ_OPCODE_SPI; + DEBUGFUNC("ixgbe_read_eeprom_bit_bang_generic"); + hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { @@ -693,7 +720,7 @@ } /* - * ixgbe_read_eeprom_generic - Read EEPROM word using EERD + * ixgbe_read_eerd_generic - Read EEPROM word using EERD * @hw: pointer to hardware structure * @offset: offset of word in the EEPROM to read * @data: word read from the EEPROM @@ -701,11 +728,13 @@ * Reads a 16 bit word from the EEPROM using the EERD register. */ s32 -ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) +ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data) { u32 eerd; s32 status; + DEBUGFUNC("ixgbe_read_eerd_generic"); + hw->eeprom.ops.init_params(hw); if (offset >= hw->eeprom.word_size) { @@ -713,39 +742,46 @@ goto out; } - eerd = (offset << IXGBE_EEPROM_READ_ADDR_SHIFT) + - IXGBE_EEPROM_READ_REG_START; + eerd = (offset << IXGBE_EEPROM_RW_ADDR_SHIFT) + + IXGBE_EEPROM_RW_REG_START; IXGBE_WRITE_REG(hw, IXGBE_EERD, eerd); - status = ixgbe_poll_eeprom_eerd_done(hw); - - if (status == IXGBE_SUCCESS) { + status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_READ); + + if (status == IXGBE_SUCCESS) *data = (IXGBE_READ_REG(hw, IXGBE_EERD) >> - IXGBE_EEPROM_READ_REG_DATA); - } else { + IXGBE_EEPROM_RW_REG_DATA); + else DEBUGOUT("Eeprom read timed out\n"); - } out: return (status); } /* - * ixgbe_poll_eeprom_eerd_done - Poll EERD status + * ixgbe_poll_eerd_eewr_done - Poll EERD read or EEWR write status * @hw: pointer to hardware structure + * @ee_reg: EEPROM flag for polling * - * Polls the status bit (bit 1) of the EERD to determine when the read is done. + * Polls the status bit (bit 1) of the EERD or EEWR to determine when the + * read or write is done respectively. */ -static s32 -ixgbe_poll_eeprom_eerd_done(struct ixgbe_hw *hw) +s32 +ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg) { u32 i; u32 reg; s32 status = IXGBE_ERR_EEPROM; - for (i = 0; i < IXGBE_EERD_ATTEMPTS; i++) { - reg = IXGBE_READ_REG(hw, IXGBE_EERD); - if (reg & IXGBE_EEPROM_READ_REG_DONE) { + DEBUGFUNC("ixgbe_poll_eerd_eewr_done"); + + for (i = 0; i < IXGBE_EERD_EEWR_ATTEMPTS; i++) { + if (ee_reg == IXGBE_NVM_POLL_READ) + reg = IXGBE_READ_REG(hw, IXGBE_EERD); + else + reg = IXGBE_READ_REG(hw, IXGBE_EEWR); + + if (reg & IXGBE_EEPROM_RW_REG_DONE) { status = IXGBE_SUCCESS; break; } @@ -768,6 +804,8 @@ u32 eec; u32 i; + DEBUGFUNC("ixgbe_acquire_eeprom"); + if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS) status = IXGBE_ERR_SWFW_SYNC; @@ -821,6 +859,8 @@ u32 i; u32 swsm; + DEBUGFUNC("ixgbe_get_eeprom_semaphore"); + /* Get SMBI software semaphore between device drivers first */ for (i = 0; i < timeout; i++) { /* @@ -884,6 +924,8 @@ { u32 swsm; + DEBUGFUNC("ixgbe_release_eeprom_semaphore"); + swsm = IXGBE_READ_REG(hw, IXGBE_SWSM); /* Release both semaphores by writing 0 to the bits SWESMBI and SMBI */ @@ -903,6 +945,8 @@ u16 i; u8 spi_stat_reg; + DEBUGFUNC("ixgbe_ready_eeprom"); + /* * Read "Status Register" repeatedly until the LSB is cleared. The * EEPROM will signal that the command has been completed by clearing @@ -941,6 +985,8 @@ { u32 eec; + DEBUGFUNC("ixgbe_standby_eeprom"); + eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* Toggle CS to flush commands */ @@ -968,6 +1014,8 @@ u32 mask; u32 i; + DEBUGFUNC("ixgbe_shift_out_eeprom_bits"); + eec = IXGBE_READ_REG(hw, IXGBE_EEC); /* @@ -1021,6 +1069,8 @@ u32 i; u16 data = 0; + DEBUGFUNC("ixgbe_shift_in_eeprom_bits"); + /* * In order to read a register from the EEPROM, we need to shift * 'count' bits in from the EEPROM. Bits are "shifted in" by raising @@ -1056,6 +1106,8 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { + DEBUGFUNC("ixgbe_raise_eeprom_clk"); + /* * Raise the clock input to the EEPROM * (setting the SK bit), then delay @@ -1074,6 +1126,8 @@ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec) { + DEBUGFUNC("ixgbe_lower_eeprom_clk"); + /* * Lower the clock input to the EEPROM (clearing the SK bit), then * delay @@ -1093,6 +1147,8 @@ { u32 eec; + DEBUGFUNC("ixgbe_release_eeprom"); + eec = IXGBE_READ_REG(hw, IXGBE_EEC); eec |= IXGBE_EEC_CS; /* Pull CS high */ @@ -1127,6 +1183,8 @@ u16 pointer = 0; u16 word = 0; + DEBUGFUNC("ixgbe_calc_eeprom_checksum"); + /* Include 0x0-0x3F in the checksum */ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) { if (hw->eeprom.ops.read(hw, i, &word) != IXGBE_SUCCESS) { @@ -1174,6 +1232,8 @@ u16 checksum; u16 read_checksum = 0; + DEBUGFUNC("ixgbe_validate_eeprom_checksum_generic"); + /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every @@ -1213,6 +1273,8 @@ s32 status; u16 checksum; + DEBUGFUNC("ixgbe_update_eeprom_checksum_generic"); + /* * Read the first word from the EEPROM. If this times out or fails, do * not continue or we could be in for a very long wait while every @@ -1242,6 +1304,8 @@ { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_validate_mac_addr"); + /* Make sure it is not a multicast address */ if (IXGBE_IS_MULTICAST(mac_addr)) { DEBUGOUT("MAC address is multicast\n"); @@ -1276,6 +1340,8 @@ u32 rar_low, rar_high; u32 rar_entries = hw->mac.num_rar_entries; + DEBUGFUNC("ixgbe_set_rar_generic"); + /* setup VMDq pool selection before this RAR gets enabled */ hw->mac.ops.set_vmdq(hw, index, vmdq); @@ -1323,6 +1389,8 @@ u32 rar_high; u32 rar_entries = hw->mac.num_rar_entries; + DEBUGFUNC("ixgbe_clear_rar_generic"); + /* Make sure we are using a valid rar index range */ if (index < rar_entries) { /* @@ -1359,6 +1427,8 @@ u32 i; u32 rar_entries = hw->mac.num_rar_entries; + DEBUGFUNC("ixgbe_init_rx_addrs_generic"); + /* * If the current mac address is valid, assume it is a software override * to the permanent address. @@ -1423,6 +1493,8 @@ u32 rar_entries = hw->mac.num_rar_entries; u32 rar; + DEBUGFUNC("ixgbe_add_uc_addr"); + DEBUGOUT6(" UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); @@ -1467,6 +1539,8 @@ u32 fctrl; u32 vmdq; + DEBUGFUNC("ixgbe_update_uc_addr_list_generic"); + /* * Clear accounting of old secondary address list, * don't count RAR[0] @@ -1528,6 +1602,8 @@ { u32 vector = 0; + DEBUGFUNC("ixgbe_mta_vector"); + switch (hw->mac.mc_filter_type) { case 0: /* use bits [47:36] of the address */ vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); @@ -1567,6 +1643,8 @@ u32 vector_reg; u32 mta_reg; + DEBUGFUNC("ixgbe_set_mta"); + hw->addr_ctrl.mta_in_use++; vector = ixgbe_mta_vector(hw, mc_addr); @@ -1607,6 +1685,8 @@ u32 i; u32 vmdq; + DEBUGFUNC("ixgbe_update_mc_addr_list_generic"); + /* * Set the new number of MC addresses that we are being requested to * use. @@ -1645,6 +1725,8 @@ { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; + DEBUGFUNC("ixgbe_enable_mc_generic"); + if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type); @@ -1663,6 +1745,8 @@ { struct ixgbe_addr_filter_info *a = &hw->addr_ctrl; + DEBUGFUNC("ixgbe_disable_mc_generic"); + if (a->mta_in_use > 0) IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type); @@ -1740,7 +1824,7 @@ break; default: DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -IXGBE_ERR_CONFIG; + ret_val = IXGBE_ERR_CONFIG; goto out; } @@ -1810,6 +1894,7 @@ s32 ret_val = IXGBE_SUCCESS; ixgbe_link_speed speed; u32 pcs_anadv_reg, pcs_lpab_reg, linkstat; + u32 links2, anlp1_reg, autoc_reg, links; bool link_up; DEBUGFUNC("ixgbe_fc_autoneg"); @@ -1818,27 +1903,61 @@ * AN should have completed when the cable was plugged in. * Look for reasons to bail out. Bail out if: * - FC autoneg is disabled, or if - * - we don't have multispeed fiber, or if - * - we're not running at 1G, or if - * - link is not up, or if - * - link is up but AN did not complete, or if - * - link is up and AN completed but timed out + * - link is not up. * - * Since we're being called from an LSC, link is already know to be up. + * Since we're being called from an LSC, link is already known to be up. * So use link_up_wait_to_complete=false. */ hw->mac.ops.check_link(hw, &speed, &link_up, false); - linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); - - if (hw->fc.disable_fc_autoneg || - !hw->phy.multispeed_fiber || - (speed != IXGBE_LINK_SPEED_1GB_FULL) || - !link_up || - ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || - ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { + + if (hw->fc.disable_fc_autoneg || (!link_up)) { hw->fc.fc_was_autonegged = false; hw->fc.current_mode = hw->fc.requested_mode; - DEBUGOUT("Autoneg FC was skipped.\n"); + goto out; + } + + /* + * On backplane, bail out if + * - backplane autoneg was not completed, or if + * - link partner is not AN enabled + */ + if (hw->phy.media_type == ixgbe_media_type_backplane) { + links = IXGBE_READ_REG(hw, IXGBE_LINKS); + links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2); + if (((links & IXGBE_LINKS_KX_AN_COMP) == 0) || + ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)) { + hw->fc.fc_was_autonegged = false; + hw->fc.current_mode = hw->fc.requested_mode; + goto out; + } + } + + /* + * On multispeed fiber at 1g, bail out if + * - link is up but AN did not complete, or if + * - link is up and AN completed but timed out + */ + if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) { + linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA); + if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) || + ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) { + hw->fc.fc_was_autonegged = false; + hw->fc.current_mode = hw->fc.requested_mode; + goto out; + } + } + + /* + * Bail out on + * - copper or CX4 adapters + * - fiber adapters running at 10gig + */ + if ((hw->phy.media_type == ixgbe_media_type_copper) || + (hw->phy.media_type == ixgbe_media_type_cx4) || + ((hw->phy.media_type == ixgbe_media_type_fiber) && + (speed == IXGBE_LINK_SPEED_10GB_FULL))) { + hw->fc.fc_was_autonegged = false; + hw->fc.current_mode = hw->fc.requested_mode; goto out; } @@ -1846,41 +1965,85 @@ * Read the AN advertisement and LP ability registers and resolve * local flow control settings accordingly */ - pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); - pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); - if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { - /* - * Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise RX - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == ixgbe_fc_full) { - hw->fc.current_mode = ixgbe_fc_full; - DEBUGOUT("Flow Control = FULL.\n"); - } else { + if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && + (hw->phy.media_type != ixgbe_media_type_backplane)) { + pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); + pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP); + if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) { + /* + * Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == ixgbe_fc_full) { + hw->fc.current_mode = ixgbe_fc_full; + DEBUGOUT("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control=RX PAUSE frames only\n"); + } + } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_tx_pause; + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); + } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && + !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && + (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { hw->fc.current_mode = ixgbe_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); } - } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { - hw->fc.current_mode = ixgbe_fc_tx_pause; - DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); - } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) && - !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) && - (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) { - hw->fc.current_mode = ixgbe_fc_rx_pause; - DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); - } else { - hw->fc.current_mode = ixgbe_fc_none; - DEBUGOUT("Flow Control = NONE.\n"); } + if (hw->phy.media_type == ixgbe_media_type_backplane) { + /* + * Read the 10g AN autoc and LP ability registers and resolve + * local flow control settings accordingly + */ + autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1); + + if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) { + /* + * Now we need to check if the user selected Rx ONLY + * of pause frames. In this case, we had to advertise + * FULL flow control because we could not advertise RX + * ONLY. Hence, we must now check to see if we need to + * turn OFF the TRANSMISSION of PAUSE frames. + */ + if (hw->fc.requested_mode == ixgbe_fc_full) { + hw->fc.current_mode = ixgbe_fc_full; + DEBUGOUT("Flow Control = FULL.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control=RX PAUSE frames only\n"); + } + } else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && + (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_tx_pause; + DEBUGOUT("Flow Control = TX PAUSE frames only.\n"); + } else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) && + (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) && + !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) && + (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) { + hw->fc.current_mode = ixgbe_fc_rx_pause; + DEBUGOUT("Flow Control = RX PAUSE frames only.\n"); + } else { + hw->fc.current_mode = ixgbe_fc_none; + DEBUGOUT("Flow Control = NONE.\n"); + } + } /* Record that current_mode is the result of a successful autoneg */ hw->fc.fc_was_autonegged = true; @@ -1900,6 +2063,8 @@ s32 ret_val = IXGBE_SUCCESS; u32 reg; + DEBUGFUNC("ixgbe_setup_fc"); + /* Validate the packetbuf configuration */ if (packetbuf_num < 0 || packetbuf_num > 7) { DEBUGOUT1("Invalid packet buffer number [%d], expected range is" @@ -1982,16 +2147,13 @@ break; default: DEBUGOUT("Flow control param set incorrectly\n"); - ret_val = -IXGBE_ERR_CONFIG; + ret_val = IXGBE_ERR_CONFIG; goto out; } IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg); reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL); - /* Enable and restart autoneg to inform the link partner */ - reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART; - /* Disable AN timeout */ if (hw->fc.strict_ieee) reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN; @@ -1999,6 +2161,64 @@ IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg); DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg); + /* + * Set up the 10G flow control advertisement registers so the HW + * can do fc autoneg once the cable is plugged in. If we end up + * using 1g instead, this is harmless. + */ + reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); + + /* + * The possible values of fc.requested_mode are: + * 0: Flow control is completely disabled + * 1: Rx flow control is enabled (we can receive pause frames, + * but not send pause frames). + * 2: Tx flow control is enabled (we can send pause frames but + * we do not support receiving pause frames). + * 3: Both Rx and Tx flow control (symmetric) are enabled. + * other: Invalid. + */ + switch (hw->fc.requested_mode) { + case ixgbe_fc_none: + /* Flow control completely disabled by software override. */ + reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); + break; + case ixgbe_fc_rx_pause: + /* + * Rx Flow control is enabled and Tx Flow control is + * disabled by software override. Since there really + * isn't a way to advertise that we are capable of RX + * Pause ONLY, we will advertise that we support both + * symmetric and asymmetric Rx PAUSE. Later, we will + * disable the adapter's ability to send PAUSE frames. + */ + reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); + break; + case ixgbe_fc_tx_pause: + /* + * Tx Flow control is enabled, and Rx Flow control is + * disabled by software override. + */ + reg |= (IXGBE_AUTOC_ASM_PAUSE); + reg &= ~(IXGBE_AUTOC_SYM_PAUSE); + break; + case ixgbe_fc_full: + /* Flow control (both Rx and Tx) is enabled by SW override. */ + reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE); + break; + default: + DEBUGOUT("Flow control param set incorrectly\n"); + ret_val = IXGBE_ERR_CONFIG; + goto out; + } + /* + * AUTOC restart handles negotiation of 1G and 10G. There is + * no need to set the PCS1GCTL register. + */ + reg |= IXGBE_AUTOC_AN_RESTART; + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg); + DEBUGOUT1("Set up FC; IXGBE_AUTOC = 0x%08X\n", reg); + out: return (ret_val); } @@ -2020,6 +2240,8 @@ u32 number_of_queues; s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING; + DEBUGFUNC("ixgbe_disable_pcie_master"); + /* Disable the receive unit by stopping each queue */ number_of_queues = hw->mac.max_rx_queues; for (i = 0; i < number_of_queues; i++) { @@ -2061,13 +2283,15 @@ u32 fwmask = mask << 5; s32 timeout = 200; + DEBUGFUNC("ixgbe_acquire_swfw_sync"); + while (timeout) { /* * SW EEPROM semaphore bit is used for access to all * SW_FW_SYNC/GSSR bits (not just EEPROM) */ if (ixgbe_get_eeprom_semaphore(hw)) - return (-IXGBE_ERR_SWFW_SYNC); + return (IXGBE_ERR_SWFW_SYNC); gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); if (!(gssr & (fwmask | swmask))) @@ -2084,7 +2308,7 @@ if (!timeout) { DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); - return (-IXGBE_ERR_SWFW_SYNC); + return (IXGBE_ERR_SWFW_SYNC); } gssr |= swmask; @@ -2108,6 +2332,8 @@ u32 gssr; u32 swmask = mask; + DEBUGFUNC("ixgbe_release_swfw_sync"); + (void) ixgbe_get_eeprom_semaphore(hw); gssr = IXGBE_READ_REG(hw, IXGBE_GSSR); @@ -2127,6 +2353,8 @@ s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval) { + DEBUGFUNC("ixgbe_enable_rx_dma_generic"); + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); return (IXGBE_SUCCESS); @@ -2145,6 +2373,8 @@ u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_blink_led_start_generic"); + /* * Link must be up to auto-blink the LEDs; * Force it if link is down. @@ -2177,6 +2407,8 @@ u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC); u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + DEBUGFUNC("ixgbe_blink_led_stop_generic"); + autoc_reg &= ~IXGBE_AUTOC_FLU; autoc_reg |= IXGBE_AUTOC_AN_RESTART; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg); @@ -2189,3 +2421,598 @@ return (IXGBE_SUCCESS); } + +/* + * ixgbe_get_san_mac_addr_offset - Get SAN MAC address offset from the EEPROM + * @hw: pointer to hardware structure + * @san_mac_offset: SAN MAC address offset + * + * This function will read the EEPROM location for the SAN MAC address + * pointer, and returns the value at that location. This is used in both + * get and set mac_addr routines. + */ +static s32 +ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw, u16 *san_mac_offset) +{ + DEBUGFUNC("ixgbe_get_san_mac_addr_offset"); + + /* + * First read the EEPROM pointer to see if the MAC addresses are + * available. + */ + hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset); + + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_get_san_mac_addr_generic - SAN MAC address retrieval from the EEPROM + * @hw: pointer to hardware structure + * @san_mac_addr: SAN MAC address + * + * Reads the SAN MAC address from the EEPROM, if it's available. This is + * per-port, so set_lan_id() must be called before reading the addresses. + * set_lan_id() is called by identify_sfp(), but this cannot be relied + * upon for non-SFP connections, so we must call it here. + */ +s32 +ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) +{ + u16 san_mac_data, san_mac_offset; + u8 i; + + DEBUGFUNC("ixgbe_get_san_mac_addr_generic"); + + /* + * First read the EEPROM pointer to see if the MAC addresses are + * available. If they're not, no point in calling set_lan_id() here. + */ + (void) ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); + + if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { + /* + * No addresses available in this EEPROM. It's not an + * error though, so just wipe the local address and return. + */ + for (i = 0; i < 6; i++) + san_mac_addr[i] = 0xFF; + + goto san_mac_addr_out; + } + + /* make sure we know which port we need to program */ + hw->mac.ops.set_lan_id(hw); + /* apply the port offset to the address offset */ + (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : + (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); + for (i = 0; i < 3; i++) { + hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data); + san_mac_addr[i * 2] = (u8)(san_mac_data); + san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8); + san_mac_offset++; + } + +san_mac_addr_out: + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_set_san_mac_addr_generic - Write the SAN MAC address to the EEPROM + * @hw: pointer to hardware structure + * @san_mac_addr: SAN MAC address + * + * Write a SAN MAC address to the EEPROM. + */ +s32 +ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr) +{ + s32 status = IXGBE_SUCCESS; + u16 san_mac_data, san_mac_offset; + u8 i; + + DEBUGFUNC("ixgbe_set_san_mac_addr_generic"); + + /* Look for SAN mac address pointer. If not defined, return */ + (void) ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset); + + if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) { + status = IXGBE_ERR_NO_SAN_ADDR_PTR; + goto san_mac_addr_out; + } + + /* Make sure we know which port we need to write */ + hw->mac.ops.set_lan_id(hw); + /* Apply the port offset to the address offset */ + (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) : + (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET); + + for (i = 0; i < 3; i++) { + san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8); + san_mac_data |= (u16)(san_mac_addr[i * 2]); + hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data); + san_mac_offset++; + } + +san_mac_addr_out: + return (status); +} + +/* + * ixgbe_get_pcie_msix_count_generic - Gets MSI-X vector count + * @hw: pointer to hardware structure + * + * Read PCIe configuration space, and get the MSI-X vector count from + * the capabilities table. + */ +u32 +ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) +{ + u32 msix_count = 64; + + DEBUGFUNC("ixgbe_get_pcie_msix_count_generic"); + if (hw->mac.msix_vectors_from_pcie) { + msix_count = IXGBE_READ_PCIE_WORD(hw, + IXGBE_PCIE_MSIX_82599_CAPS); + msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK; + + /* + * MSI-X count is zero-based in HW, so increment to give + * proper value. + */ + msix_count++; + } + + return (msix_count); +} + +/* + * ixgbe_insert_mac_addr_generic - Find a RAR for this mac address + * @hw: pointer to hardware structure + * @addr: Address to put into receive address register + * @vmdq: VMDq pool to assign + * + * Puts an ethernet address into a receive address register, or + * finds the rar that it is aleady in; adds to the pool list + */ +s32 +ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) +{ + static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF; + u32 first_empty_rar = NO_EMPTY_RAR_FOUND; + u32 rar; + u32 rar_low, rar_high; + u32 addr_low, addr_high; + + DEBUGFUNC("ixgbe_insert_mac_addr_generic"); + + /* swap bytes for HW little endian */ + addr_low = addr[0] | (addr[1] << 8) + | (addr[2] << 16) + | (addr[3] << 24); + addr_high = addr[4] | (addr[5] << 8); + + /* + * Either find the mac_id in rar or find the first empty space. + * rar_highwater points to just after the highest currently used + * rar in order to shorten the search. It grows when we add a new + * rar to the top. + */ + for (rar = 0; rar < hw->mac.rar_highwater; rar++) { + rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); + + if (((IXGBE_RAH_AV & rar_high) == 0) && + first_empty_rar == NO_EMPTY_RAR_FOUND) { + first_empty_rar = rar; + } else if ((rar_high & 0xFFFF) == addr_high) { + rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar)); + if (rar_low == addr_low) + break; /* found it already in the rars */ + } + } + + if (rar < hw->mac.rar_highwater) { + /* already there so just add to the pool bits */ + (void) ixgbe_set_vmdq(hw, rar, vmdq); + } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) { + /* stick it into first empty RAR slot we found */ + rar = first_empty_rar; + (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); + } else if (rar == hw->mac.rar_highwater) { + /* add it to the top of the list and inc the highwater mark */ + (void) ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV); + hw->mac.rar_highwater++; + } else if (rar >= hw->mac.num_rar_entries) { + return (IXGBE_ERR_INVALID_MAC_ADDR); + } + + /* + * If we found rar[0], make sure the default pool bit (we use pool 0) + * remains cleared to be sure default pool packets will get delivered + */ + if (rar == 0) + (void) ixgbe_clear_vmdq(hw, rar, 0); + + return (rar); +} + +/* + * ixgbe_clear_vmdq_generic - Disassociate a VMDq pool index from a rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to disassociate + * @vmdq: VMDq pool index to remove from the rar + */ +s32 +ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 mpsar_lo, mpsar_hi; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ixgbe_clear_vmdq_generic"); + + if (rar < rar_entries) { + mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); + mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); + + if (!mpsar_lo && !mpsar_hi) + goto done; + + if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { + if (mpsar_lo) { + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0); + mpsar_lo = 0; + } + if (mpsar_hi) { + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0); + mpsar_hi = 0; + } + } else if (vmdq < 32) { + mpsar_lo &= ~(1 << vmdq); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo); + } else { + mpsar_hi &= ~(1 << (vmdq - 32)); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi); + } + + /* was that the last pool using this rar? */ + if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) + hw->mac.ops.clear_rar(hw, rar); + } else { + DEBUGOUT1("RAR index %d is out of range.\n", rar); + } + +done: + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_set_vmdq_generic - Associate a VMDq pool index with a rx address + * @hw: pointer to hardware struct + * @rar: receive address register index to associate with a VMDq index + * @vmdq: VMDq pool index + */ +s32 +ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) +{ + u32 mpsar; + u32 rar_entries = hw->mac.num_rar_entries; + + DEBUGFUNC("ixgbe_set_vmdq_generic"); + + if (rar < rar_entries) { + if (vmdq < 32) { + mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); + mpsar |= 1 << vmdq; + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar); + } else { + mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); + mpsar |= 1 << (vmdq - 32); + IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar); + } + } else { + DEBUGOUT1("RAR index %d is out of range.\n", rar); + } + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_init_uta_tables_generic - Initialize the Unicast Table Array + * @hw: pointer to hardware structure + */ +s32 +ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw) +{ + int i; + + DEBUGFUNC("ixgbe_init_uta_tables_generic"); + DEBUGOUT(" Clearing UTA\n"); + + for (i = 0; i < 128; i++) + IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0); + + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_find_vlvf_slot - find the vlanid or the first empty slot + * @hw: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * + * return the VLVF index where this VLAN id should be placed + * + */ +s32 +ixgbe_find_vlvf_slot(struct ixgbe_hw *hw, u32 vlan) +{ + u32 bits = 0; + u32 first_empty_slot = 0; + s32 regindex; + + /* + * Search for the vlan id in the VLVF entries. Save off the first empty + * slot found along the way + */ + for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { + bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); + if (!bits && !(first_empty_slot)) + first_empty_slot = regindex; + else if ((bits & 0x0FFF) == vlan) + break; + } + + /* + * If regindex is less than IXGBE_VLVF_ENTRIES, then we found the vlan + * in the VLVF. Else use the first empty VLVF register for this + * vlan id. + */ + if (regindex >= IXGBE_VLVF_ENTRIES) { + if (first_empty_slot) + regindex = first_empty_slot; + else { + DEBUGOUT("No space in VLVF.\n"); + regindex = -1; + } + } + + return (regindex); +} + +/* + * ixgbe_set_vfta_generic - Set VLAN filter table + * @hw: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * @vind: VMDq output index that maps queue to VLAN id in VFVFB + * @vlan_on: boolean flag to turn on/off VLAN in VFVF + * + * Turn on/off specified VLAN in the VLAN filter table. + */ +s32 +ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) +{ + s32 regindex; + u32 bitindex; + u32 bits; + u32 vt; + + DEBUGFUNC("ixgbe_set_vfta_generic"); + + if (vlan > 4095) + return (IXGBE_ERR_PARAM); + + /* + * this is a 2 part operation - first the VFTA, then the + * VLVF and VLVFB if VT Mode is set + */ + + /* + * Part 1 + * The VFTA is a bitstring made up of 128 32-bit registers + * that enable the particular VLAN id, much like the MTA: + * bits[11-5]: which register + * bits[4-0]: which bit in the register + */ + regindex = (vlan >> 5) & 0x7F; + bitindex = vlan & 0x1F; + bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); + if (vlan_on) + bits |= (1 << bitindex); + else + bits &= ~(1 << bitindex); + IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); + + + /* + * Part 2 + * If VT Mode is set + * Either vlan_on + * make sure the vlan is in VLVF + * set the vind bit in the matching VLVFB + * Or !vlan_on + * clear the pool bit and possibly the vind + */ + vt = IXGBE_READ_REG(hw, IXGBE_VT_CTL); + if (vt & IXGBE_VT_CTL_VT_ENABLE) { + if (vlan == 0) { + regindex = 0; + } else { + regindex = ixgbe_find_vlvf_slot(hw, vlan); + if (regindex < 0) + goto out; + } + + if (vlan_on) { + /* set the pool bit */ + if (vind < 32) { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB(regindex*2)); + bits |= (1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB(regindex*2), + bits); + } else { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB((regindex*2)+1)); + bits |= (1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB((regindex*2)+1), + bits); + } + } else { + /* clear the pool bit */ + if (vind < 32) { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB(regindex*2)); + bits &= ~(1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB(regindex*2), + bits); + bits |= IXGBE_READ_REG(hw, + IXGBE_VLVFB((regindex*2)+1)); + } else { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB((regindex*2)+1)); + bits &= ~(1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB((regindex*2)+1), + bits); + bits |= IXGBE_READ_REG(hw, + IXGBE_VLVFB(regindex*2)); + } + } + + if (bits) + IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), + (IXGBE_VLVF_VIEN | vlan)); + else + IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0); + } +out: + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_clear_vfta_generic - Clear VLAN filter table + * @hw: pointer to hardware structure + * + * Clears the VLAN filer table, and the VMDq index associated with the filter + */ +s32 +ixgbe_clear_vfta_generic(struct ixgbe_hw *hw) +{ + u32 offset; + + DEBUGFUNC("ixgbe_clear_vfta_generic"); + + for (offset = 0; offset < hw->mac.vft_size; offset++) + IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0); + + for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) { + IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0); + IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0); + IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0); + } + + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_check_mac_link_generic - Determine link and speed status + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: true when link is up + * @link_up_wait_to_complete: bool used to wait for link up or not + * + * Reads the links register to determine if link is up and the current speed + */ +s32 +ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, + bool *link_up, bool link_up_wait_to_complete) +{ + u32 links_reg; + u32 i; + + DEBUGFUNC("ixgbe_check_mac_link_generic"); + + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + if (link_up_wait_to_complete) { + for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + if (links_reg & IXGBE_LINKS_UP) { + *link_up = true; + break; + } else { + *link_up = false; + } + msec_delay(100); + links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); + } + } else { + if (links_reg & IXGBE_LINKS_UP) + *link_up = true; + else + *link_up = false; + } + + if ((links_reg & IXGBE_LINKS_SPEED_82599) == + IXGBE_LINKS_SPEED_10G_82599) + *speed = IXGBE_LINK_SPEED_10GB_FULL; + else if ((links_reg & IXGBE_LINKS_SPEED_82599) == + IXGBE_LINKS_SPEED_1G_82599) + *speed = IXGBE_LINK_SPEED_1GB_FULL; + else + *speed = IXGBE_LINK_SPEED_100_FULL; + + /* if link is down, zero out the current_mode */ + if (*link_up == false) { + hw->fc.current_mode = ixgbe_fc_none; + hw->fc.fc_was_autonegged = false; + } + + return (IXGBE_SUCCESS); +} + +/* + * ixgbe_get_wwn_prefix_generic - Get alternative WWNN/WWPN prefix from + * the EEPROM + * @hw: pointer to hardware structure + * @wwnn_prefix: the alternative WWNN prefix + * @wwpn_prefix: the alternative WWPN prefix + * + * This function will read the EEPROM from the alternative SAN MAC address + * block to check the support for the alternative WWNN/WWPN prefix support. + */ +s32 +ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix) +{ + u16 offset, caps; + u16 alt_san_mac_blk_offset; + + DEBUGFUNC("ixgbe_get_wwn_prefix_generic"); + + /* clear output first */ + *wwnn_prefix = 0xFFFF; + *wwpn_prefix = 0xFFFF; + + /* check if alternative SAN MAC is supported */ + hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR, + &alt_san_mac_blk_offset); + + if ((alt_san_mac_blk_offset == 0) || + (alt_san_mac_blk_offset == 0xFFFF)) + goto wwn_prefix_out; + + /* check capability in alternative san mac address block */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET; + hw->eeprom.ops.read(hw, offset, &caps); + if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN)) + goto wwn_prefix_out; + + /* get the corresponding prefix for WWNN/WWPN */ + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwnn_prefix); + + offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET; + hw->eeprom.ops.read(hw, offset, wwpn_prefix); + +wwn_prefix_out: + return (IXGBE_SUCCESS); +}
--- a/usr/src/uts/common/io/ixgbe/ixgbe_common.h Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_common.h Sun Nov 08 15:49:56 2009 +0800 @@ -26,13 +26,15 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.90 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.93 scm_100309_002210 */ #ifndef _IXGBE_COMMON_H #define _IXGBE_COMMON_H #include "ixgbe_type.h" +u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw); + s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw); s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw); s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw); @@ -48,12 +50,13 @@ s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw); s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data); -s32 ixgbe_read_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); +s32 ixgbe_read_eerd_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_read_eeprom_bit_bang_generic(struct ixgbe_hw *hw, u16 offset, u16 *data); s32 ixgbe_validate_eeprom_checksum_generic(struct ixgbe_hw *hw, u16 *checksum_val); s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw); +s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg); s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, u32 enable_addr); @@ -64,7 +67,6 @@ ixgbe_mc_addr_itr func); s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, u32 addr_count, ixgbe_mc_addr_itr func); -void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); @@ -78,9 +80,24 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask); s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw); -s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val); -s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val); s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index); s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); +s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); +s32 ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr); + +s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); +s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq); +s32 ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); +s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw); +s32 ixgbe_set_vfta_generic(struct ixgbe_hw *hw, u32 vlan, + u32 vind, bool vlan_on); +s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw); + +s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); + +s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix, + u16 *wwpn_prefix); + #endif /* _IXGBE_COMMON_H */
--- a/usr/src/uts/common/io/ixgbe/ixgbe_gld.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_gld.c Sun Nov 08 15:49:56 2009 +0800 @@ -276,8 +276,9 @@ break; case ETHER_STAT_LINK_AUTONEG: - *val = hw->mac.autoneg; + *val = ixgbe->param_adv_autoneg_cap; break; + case ETHER_STAT_LINK_DUPLEX: *val = LINK_DUPLEX_FULL; break;
--- a/usr/src/uts/common/io/ixgbe/ixgbe_main.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_main.c Sun Nov 08 15:49:56 2009 +0800 @@ -27,7 +27,8 @@ #include "ixgbe_sw.h" -static char ident[] = "Intel 10Gb Ethernet 1.1.0"; +static char ident[] = "Intel 10Gb Ethernet"; +static char ixgbe_version[] = "ixgbe 1.1.1"; /* * Local function protoypes @@ -505,6 +506,7 @@ } ixgbe->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR; + ixgbe_log(ixgbe, "%s", ixgbe_version); ixgbe->ixgbe_state |= IXGBE_INITIALIZED; return (DDI_SUCCESS); @@ -1108,11 +1110,6 @@ hw->fc.send_xon = B_TRUE; /* - * Don't wait for auto-negotiation to complete - */ - hw->phy.autoneg_wait_to_complete = B_FALSE; - - /* * Initialize link settings */ (void) ixgbe_driver_setup_link(ixgbe, B_FALSE); @@ -2504,44 +2501,32 @@ int ixgbe_driver_setup_link(ixgbe_t *ixgbe, boolean_t setup_hw) { - struct ixgbe_mac_info *mac; - struct ixgbe_phy_info *phy; - boolean_t invalid; - - mac = &ixgbe->hw.mac; - phy = &ixgbe->hw.phy; - invalid = B_FALSE; - - if (ixgbe->param_adv_autoneg_cap == 1) { - mac->autoneg = B_TRUE; - phy->autoneg_advertised = 0; - - /* - * No half duplex support with 10Gb parts - */ - if (ixgbe->param_adv_10000fdx_cap == 1) - phy->autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; - - if (ixgbe->param_adv_1000fdx_cap == 1) - phy->autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; - - if (ixgbe->param_adv_100fdx_cap == 1) - phy->autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; - - if (phy->autoneg_advertised == 0) - invalid = B_TRUE; - } else { - ixgbe->hw.mac.autoneg = B_FALSE; - } - - if (invalid) { - ixgbe_notice(ixgbe, "Invalid link settings. Setup link to " - "autonegotiation with full link capabilities."); - ixgbe->hw.mac.autoneg = B_TRUE; + u32 autoneg_advertised = 0; + + /* + * No half duplex support with 10Gb parts + */ + if (ixgbe->param_adv_10000fdx_cap == 1) + autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (ixgbe->param_adv_1000fdx_cap == 1) + autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + if (ixgbe->param_adv_100fdx_cap == 1) + autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; + + if (ixgbe->param_adv_autoneg_cap == 1 && autoneg_advertised == 0) { + ixgbe_notice(ixgbe, "Invalid link settings. Setup link " + "to autonegotiation with full link capabilities."); + + autoneg_advertised = IXGBE_LINK_SPEED_10GB_FULL | + IXGBE_LINK_SPEED_1GB_FULL | + IXGBE_LINK_SPEED_100_FULL; } if (setup_hw) { - if (ixgbe_setup_link(&ixgbe->hw) != IXGBE_SUCCESS) { + if (ixgbe_setup_link(&ixgbe->hw, autoneg_advertised, + ixgbe->param_adv_autoneg_cap, B_TRUE) != IXGBE_SUCCESS) { ixgbe_notice(ixgbe, "Setup link failed on this " "device."); return (IXGBE_FAILURE); @@ -2636,16 +2621,14 @@ ixgbe_t *ixgbe = (ixgbe_t *)arg; uint32_t eicr = ixgbe->eicr; struct ixgbe_hw *hw = &ixgbe->hw; - uint32_t autoneg; if (eicr & IXGBE_EICR_GPI_SDP1) { /* clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1); /* if link up, do multispeed fiber setup */ - (void) ixgbe_get_link_capabilities(hw, &autoneg, - &hw->mac.autoneg); - (void) ixgbe_setup_link_speed(hw, autoneg, B_TRUE, B_TRUE); + (void) ixgbe_setup_link(hw, IXGBE_LINK_SPEED_82599_AUTONEG, + B_TRUE, B_TRUE); ixgbe_driver_link_check(ixgbe); } else if (eicr & IXGBE_EICR_GPI_SDP2) { /* clear the interrupt */ @@ -2655,9 +2638,8 @@ (void) hw->mac.ops.setup_sfp(hw); /* do multispeed fiber setup */ - (void) ixgbe_get_link_capabilities(hw, &autoneg, - &hw->mac.autoneg); - (void) ixgbe_setup_link_speed(hw, autoneg, B_TRUE, B_TRUE); + (void) ixgbe_setup_link(hw, IXGBE_LINK_SPEED_82599_AUTONEG, + B_TRUE, B_TRUE); ixgbe_driver_link_check(ixgbe); } } @@ -3096,22 +3078,16 @@ static boolean_t ixgbe_set_loopback_mode(ixgbe_t *ixgbe, uint32_t mode) { - struct ixgbe_hw *hw; - if (mode == ixgbe->loopback_mode) return (B_TRUE); - hw = &ixgbe->hw; - ixgbe->loopback_mode = mode; if (mode == IXGBE_LB_NONE) { /* * Reset the chip */ - hw->phy.autoneg_wait_to_complete = B_TRUE; (void) ixgbe_reset(ixgbe); - hw->phy.autoneg_wait_to_complete = B_FALSE; return (B_TRUE); }
--- a/usr/src/uts/common/io/ixgbe/ixgbe_phy.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_phy.c Sun Nov 08 15:49:56 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.94 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.98 scm_100309_002210 */ #include "ixgbe_api.h" #include "ixgbe_common.h" @@ -56,6 +56,8 @@ { struct ixgbe_phy_info *phy = &hw->phy; + DEBUGFUNC("ixgbe_init_phy_ops_generic"); + /* PHY */ phy->ops.identify = &ixgbe_identify_phy_generic; phy->ops.reset = &ixgbe_reset_phy_generic; @@ -64,7 +66,7 @@ phy->ops.setup_link = &ixgbe_setup_phy_link_generic; phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic; phy->ops.check_link = NULL; - phy->ops.get_firmware_version = NULL; + phy->ops.get_firmware_version = ixgbe_get_phy_firmware_version_generic; phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_generic; phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_generic; phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic; @@ -89,6 +91,8 @@ u32 phy_addr; u16 ext_ability = 0; + DEBUGFUNC("ixgbe_identify_phy_generic"); + if (hw->phy.type == ixgbe_phy_unknown) { for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) { if (ixgbe_validate_phy_addr(hw, phy_addr)) { @@ -137,6 +141,8 @@ u16 phy_id = 0; bool valid = false; + DEBUGFUNC("ixgbe_validate_phy_addr"); + hw->phy.addr = phy_addr; hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id); @@ -159,6 +165,8 @@ u16 phy_id_high = 0; u16 phy_id_low = 0; + DEBUGFUNC("ixgbe_get_phy_id"); + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_ID_HIGH, IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id_high); @@ -185,6 +193,8 @@ { enum ixgbe_phy_type phy_type; + DEBUGFUNC("ixgbe_get_phy_type_from_id"); + switch (phy_id) { case TN1010_PHY_ID: phy_type = ixgbe_phy_tn; @@ -219,6 +229,8 @@ u16 ctrl = 0; s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_reset_phy_generic"); + if (hw->phy.type == ixgbe_phy_unknown) status = ixgbe_identify_phy_generic(hw); @@ -267,6 +279,8 @@ s32 status = IXGBE_SUCCESS; u16 gssr; + DEBUGFUNC("ixgbe_read_phy_reg_generic"); + if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) gssr = IXGBE_GSSR_PHY1_SM; else @@ -365,6 +379,8 @@ s32 status = IXGBE_SUCCESS; u16 gssr; + DEBUGFUNC("ixgbe_write_phy_reg_generic"); + if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1) gssr = IXGBE_GSSR_PHY1_SM; else @@ -457,23 +473,59 @@ u32 time_out; u32 max_time_out = 10; u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; + bool autoneg = false; + ixgbe_link_speed speed; - /* - * Set advertisement settings in PHY based on autoneg_advertised - * settings. If autoneg_advertised = 0, then advertise default values - * tnx devices cannot be "forced" to a autoneg 10G and fail. But can - * for a 1G. - */ - hw->phy.ops.read_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + DEBUGFUNC("ixgbe_setup_phy_link_generic"); + + (void) ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { + /* Set or unset auto-negotiation 10G advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) + autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } - if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL) - autoneg_reg &= 0xEFFF; /* 0 in bit 12 is 1G operation */ - else - autoneg_reg |= 0x1000; /* 1 in bit 12 is 10G/1G operation */ + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { + /* Set or unset auto-negotiation 1G advertisement */ + hw->phy.ops.read_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) + autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; - hw->phy.ops.write_reg(hw, IXGBE_MII_SPEED_SELECTION_REG, - IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + hw->phy.ops.write_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_100_FULL) { + /* Set or unset auto-negotiation 100M advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) + autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } /* Restart PHY autonegotiation and wait for completion */ hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, @@ -498,8 +550,10 @@ } } - if (time_out == max_time_out) + if (time_out == max_time_out) { status = IXGBE_ERR_LINK_SETUP; + DEBUGOUT("ixgbe_setup_phy_link_generic: time out"); + } return (status); } @@ -510,7 +564,8 @@ * @speed: new link speed * @autoneg: true if autonegotiation enabled */ -s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, +s32 +ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg, bool autoneg_wait_to_complete) @@ -518,6 +573,8 @@ UNREFERENCED_PARAMETER(autoneg); UNREFERENCED_PARAMETER(autoneg_wait_to_complete); + DEBUGFUNC("ixgbe_setup_phy_link_speed_generic"); + /* * Clear autoneg_advertised and set new values based on input link * speed. @@ -549,12 +606,15 @@ * * Determines the link capabilities by reading the AUTOC register. */ -s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, +s32 +ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg) { s32 status = IXGBE_ERR_LINK_SETUP; u16 speed_ability; + DEBUGFUNC("ixgbe_get_copper_link_capabilities_generic"); + *speed = 0; *autoneg = true; @@ -591,6 +651,8 @@ u16 phy_speed = 0; u16 phy_data = 0; + DEBUGFUNC("ixgbe_check_phy_link_tnx"); + /* Initialize speed and link to default case */ *link_up = false; *speed = IXGBE_LINK_SPEED_10GB_FULL; @@ -623,6 +685,102 @@ } /* + * ixgbe_setup_phy_link_tnx - Set and restart autoneg + * @hw: pointer to hardware structure + * + * Restart autonegotiation and PHY and waits for completion. + */ +s32 +ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) +{ + s32 status = IXGBE_SUCCESS; + u32 time_out; + u32 max_time_out = 10; + u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; + bool autoneg = false; + ixgbe_link_speed speed; + + DEBUGFUNC("ixgbe_setup_phy_link_tnx"); + + (void) ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { + /* Set or unset auto-negotiation 10G advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_10GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) + autoneg_reg |= IXGBE_MII_10GBASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { + /* Set or unset auto-negotiation 1G advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) + autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; + + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_100_FULL) { + /* Set or unset auto-negotiation 100M advertisement */ + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) + autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_ADVERTISE_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + /* Restart PHY autonegotiation and wait for completion */ + hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg); + + autoneg_reg |= IXGBE_MII_RESTART; + + hw->phy.ops.write_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, autoneg_reg); + + /* Wait for autonegotiation to finish */ + for (time_out = 0; time_out < max_time_out; time_out++) { + usec_delay(10); + /* Restart PHY autonegotiation and wait for completion */ + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= IXGBE_MII_AUTONEG_COMPLETE; + if (autoneg_reg == IXGBE_MII_AUTONEG_COMPLETE) { + break; + } + } + + if (time_out == max_time_out) { + status = IXGBE_ERR_LINK_SETUP; + DEBUGOUT("ixgbe_setup_phy_link_tnx: time out"); + } + + return (status); +} + +/* * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version @@ -632,6 +790,8 @@ { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_get_phy_firmware_version_tnx"); + status = hw->phy.ops.read_reg(hw, TNX_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); @@ -639,15 +799,18 @@ } /* - * ixgbe_get_phy_firmware_version_aq - Gets the PHY Firmware Version + * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version * @hw: pointer to hardware structure * @firmware_version: pointer to the PHY Firmware Version */ s32 -ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw, u16 *firmware_version) +ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, + u16 *firmware_version) { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_get_phy_firmware_version_generic"); + status = hw->phy.ops.read_reg(hw, AQ_FW_REV, IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, firmware_version); @@ -668,6 +831,8 @@ s32 ret_val = IXGBE_SUCCESS; u32 i; + DEBUGFUNC("ixgbe_reset_phy_nl"); + hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL, IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data); @@ -770,6 +935,8 @@ u8 cable_tech = 0; u16 enforce_sfp = 0; + DEBUGFUNC("ixgbe_identify_sfp_module_generic"); + if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) { hw->phy.sfp_type = ixgbe_sfp_type_not_present; status = IXGBE_ERR_SFP_NOT_PRESENT; @@ -952,6 +1119,8 @@ { u16 sfp_id; + DEBUGFUNC("ixgbe_get_sfp_init_sequence_offsets"); + if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) return (IXGBE_ERR_SFP_NOT_SUPPORTED); @@ -1384,6 +1553,8 @@ s32 status; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + DEBUGFUNC("ixgbe_clock_in_i2c_bit"); + status = ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ @@ -1413,6 +1584,8 @@ s32 status; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL); + DEBUGFUNC("ixgbe_clock_out_i2c_bit"); + status = ixgbe_set_i2c_data(hw, &i2cctl, data); if (status == IXGBE_SUCCESS) { status = ixgbe_raise_i2c_clk(hw, &i2cctl); @@ -1447,6 +1620,8 @@ { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_raise_i2c_clk"); + *i2cctl |= IXGBE_I2C_CLK_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); @@ -1467,6 +1642,8 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { + DEBUGFUNC("ixgbe_lower_i2c_clk"); + *i2cctl &= ~IXGBE_I2C_CLK_OUT; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl); @@ -1488,6 +1665,8 @@ { s32 status = IXGBE_SUCCESS; + DEBUGFUNC("ixgbe_set_i2c_data"); + if (data) *i2cctl |= IXGBE_I2C_DATA_OUT; else @@ -1520,6 +1699,8 @@ { bool data; + DEBUGFUNC("ixgbe_get_i2c_data"); + if (*i2cctl & IXGBE_I2C_DATA_IN) data = 1; else
--- a/usr/src/uts/common/io/ixgbe/ixgbe_phy.h Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_phy.h Sun Nov 08 15:49:56 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.34 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.36 scm_100309_002210 */ #ifndef _IXGBE_PHY_H #define _IXGBE_PHY_H @@ -100,9 +100,10 @@ /* PHY specific */ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up); +s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw); s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, u16 *firmware_version); -s32 ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw, +s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, u16 *firmware_version); s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
--- a/usr/src/uts/common/io/ixgbe/ixgbe_stat.c Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_stat.c Sun Nov 08 15:49:56 2009 +0800 @@ -51,10 +51,9 @@ * Basic information */ ixgbe_ks->link_speed.value.ui64 = ixgbe->link_speed; + ixgbe_ks->reset_count.value.ui64 = ixgbe->reset_count; #ifdef IXGBE_DEBUG - ixgbe_ks->reset_count.value.ui64 = ixgbe->reset_count; - ixgbe_ks->rx_frame_error.value.ui64 = 0; ixgbe_ks->rx_cksum_error.value.ui64 = 0; ixgbe_ks->rx_exceed_pkt.value.ui64 = 0; @@ -207,10 +206,10 @@ */ kstat_named_init(&ixgbe_ks->link_speed, "link_speed", KSTAT_DATA_UINT64); + kstat_named_init(&ixgbe_ks->reset_count, "reset_count", + KSTAT_DATA_UINT64); #ifdef IXGBE_DEBUG - kstat_named_init(&ixgbe_ks->reset_count, "reset_count", - KSTAT_DATA_UINT64); kstat_named_init(&ixgbe_ks->rx_frame_error, "rx_frame_error", KSTAT_DATA_UINT64); kstat_named_init(&ixgbe_ks->rx_cksum_error, "rx_cksum_error",
--- a/usr/src/uts/common/io/ixgbe/ixgbe_type.h Sat Nov 07 09:32:37 2009 -0800 +++ b/usr/src/uts/common/io/ixgbe/ixgbe_type.h Sun Nov 08 15:49:56 2009 +0800 @@ -26,7 +26,7 @@ * Use is subject to license terms. */ -/* IntelVersion: 1.338 v2-9-1-1_2009-6-10_NSW1 */ +/* IntelVersion: 1.360 scm_100309_002210 */ #ifndef _IXGBE_TYPE_H #define _IXGBE_TYPE_H @@ -42,6 +42,7 @@ #define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6 #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598AT 0x10C8 +#define IXGBE_DEV_ID_82598AT2 0x150B #define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB #define IXGBE_DEV_ID_82598EB_CX4 0x10DD #define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC @@ -49,10 +50,11 @@ #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 -#define IXGBE_DEV_ID_82599_KX4_SIK 0x1514 +#define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 +#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB -#define IXGBE_DEV_ID_82599_SPW 0x1507 +#define IXGBE_DEV_ID_82599_SFP_EM 0x1507 #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC /* General Registers */ @@ -71,6 +73,7 @@ /* NVM Registers */ #define IXGBE_EEC 0x10010 #define IXGBE_EERD 0x10014 +#define IXGBE_EEWR 0x10018 #define IXGBE_FLA 0x1001C #define IXGBE_EEMNGCTL 0x10110 #define IXGBE_EEMNGDATA 0x10114 @@ -685,6 +688,7 @@ #define IXGBE_MREVID 0x11064 #define IXGBE_DCA_ID 0x11070 #define IXGBE_DCA_CTRL 0x11074 +#define IXGBE_SWFW_SYNC IXGBE_GSSR /* PCI-E registers 82599-Specific */ #define IXGBE_GCR_EXT 0x11050 @@ -698,14 +702,6 @@ #define IXGBE_PBACLR_82599 0x11068 #define IXGBE_CIAA_82599 0x11088 #define IXGBE_CIAD_82599 0x1108C -#define IXGBE_PCIE_DIAG_0_82599 0x11090 -#define IXGBE_PCIE_DIAG_1_82599 0x11094 -#define IXGBE_PCIE_DIAG_2_82599 0x11098 -#define IXGBE_PCIE_DIAG_3_82599 0x1109C -#define IXGBE_PCIE_DIAG_4_82599 0x110A0 -#define IXGBE_PCIE_DIAG_5_82599 0x110A4 -#define IXGBE_PCIE_DIAG_6_82599 0x110A8 -#define IXGBE_PCIE_DIAG_7_82599 0x110C0 #define IXGBE_INTRPT_CSR_82599 0x110B0 #define IXGBE_INTRPT_MASK_82599 0x110B8 #define IXGBE_CDQ_MBR_82599 0x110B4 @@ -715,6 +711,12 @@ #define IXGBE_ECC_STATUS_82599 0x110E0 #define IXGBE_BAR_CTRL_82599 0x110F4 +/* PCI Express Control */ +#define IXGBE_GCR_CMPL_TMOUT_MASK 0x0000F000 +#define IXGBE_GCR_CMPL_TMOUT_10ms 0x00001000 +#define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000 +#define IXGBE_GCR_CAP_VER2 0x00040000 + /* Time Sync Registers */ #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */ #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */ @@ -772,10 +774,20 @@ #define IXGBE_TXDATARDPTR(_i) (0x0C720 + ((_i) * 4)) /* 8 of these C720-C72C */ #define IXGBE_TXDESCRDPTR(_i) (0x0C730 + ((_i) * 4)) /* 8 of these C730-C73C */ #define IXGBE_PCIEECCCTL 0x1106C +#define IXGBE_RXWRPTR(_i) (0x03100 + ((_i) * 4)) /* 8 of these 3100-310C */ +#define IXGBE_RXUSED(_i) (0x03120 + ((_i) * 4)) /* 8 of these 3120-312C */ +#define IXGBE_RXRDPTR(_i) (0x03140 + ((_i) * 4)) /* 8 of these 3140-314C */ +#define IXGBE_RXRDWRPTR(_i) (0x03160 + ((_i) * 4)) /* 8 of these 3160-310C */ +#define IXGBE_TXWRPTR(_i) (0x0C100 + ((_i) * 4)) /* 8 of these C100-C10C */ +#define IXGBE_TXUSED(_i) (0x0C120 + ((_i) * 4)) /* 8 of these C120-C12C */ +#define IXGBE_TXRDPTR(_i) (0x0C140 + ((_i) * 4)) /* 8 of these C140-C14C */ +#define IXGBE_TXRDWRPTR(_i) (0x0C160 + ((_i) * 4)) /* 8 of these C160-C10C */ #define IXGBE_PCIEECCCTL0 0x11100 #define IXGBE_PCIEECCCTL1 0x11104 #define IXGBE_RXDBUECC 0x03F70 #define IXGBE_TXDBUECC 0x0CF70 +#define IXGBE_RXDBUEST 0x03F74 +#define IXGBE_TXDBUEST 0x0CF74 #define IXGBE_PBTXECC 0x0C300 #define IXGBE_PBRXECC 0x03300 #define IXGBE_GHECCR 0x110B0 @@ -833,6 +845,7 @@ /* BARCTRL */ #define IXGBE_BARCTRL 0x110F4 #define IXGBE_BARCTRL_FLSIZE 0x0700 +#define IXGBE_BARCTRL_FLSIZE_SHIFT 8 #define IXGBE_BARCTRL_CSRSIZE 0x2000 /* RSCCTL Bit Masks */ @@ -999,9 +1012,17 @@ /* MII clause 22/28 definitions */ #define IXGBE_MDIO_PHY_LOW_POWER_MODE 0x0800 -#define IXGBE_MII_SPEED_SELECTION_REG 0x10 +#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG 0x20 /* 10G Control Reg */ +#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */ +#define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */ +#define IXGBE_MII_AUTONEG_ADVERTISE_REG 0x10 /* 100M Advertisement */ +#define IXGBE_MII_10GBASE_T_ADVERTISE 0x1000 /* full duplex, bit:12 */ +#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14 */ +#define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15 */ +#define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */ #define IXGBE_MII_RESTART 0x200 #define IXGBE_MII_AUTONEG_COMPLETE 0x20 +#define IXGBE_MII_AUTONEG_LINK_UP 0x04 #define IXGBE_MII_AUTONEG_REG 0x0 #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 @@ -1345,6 +1366,7 @@ /* VLAN pool filtering masks */ #define IXGBE_VLVF_VIEN 0x80000000 /* filter is valid */ #define IXGBE_VLVF_ENTRIES 64 +#define IXGBE_VLVF_VLANID_MASK 0x00000FFF #define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */ @@ -1392,6 +1414,8 @@ #define IXGBE_AUTOC_KX4_SUPP 0x80000000 #define IXGBE_AUTOC_KX_SUPP 0x40000000 #define IXGBE_AUTOC_PAUSE 0x30000000 +#define IXGBE_AUTOC_ASM_PAUSE 0x20000000 +#define IXGBE_AUTOC_SYM_PAUSE 0x10000000 #define IXGBE_AUTOC_RF 0x08000000 #define IXGBE_AUTOC_PD_TMR 0x06000000 #define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000 @@ -1460,6 +1484,8 @@ #define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */ #define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */ +#define IXGBE_LINKS2_AN_SUPPORTED 0x00000040 + /* PCS1GLSTA Bit Masks */ #define IXGBE_PCS1GLSTA_LINK_OK 1 #define IXGBE_PCS1GLSTA_SYNK_OK 0x10 @@ -1480,12 +1506,18 @@ #define IXGBE_PCS1GLCTL_AN_ENABLE 0x10000 #define IXGBE_PCS1GLCTL_AN_RESTART 0x20000 +/* ANLP1 Bit Masks */ +#define IXGBE_ANLP1_PAUSE 0x0C00 +#define IXGBE_ANLP1_SYM_PAUSE 0x0400 +#define IXGBE_ANLP1_ASM_PAUSE 0x0800 + /* SW Semaphore Register bitmasks */ #define IXGBE_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define IXGBE_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ #define IXGBE_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ +#define IXGBE_SWFW_REGSMP 0x80000000 /* Register Semaphore bit 31 */ -/* GSSR definitions */ +/* SW_FW_SYNC/GSSR definitions */ #define IXGBE_GSSR_EEP_SM 0x0001 #define IXGBE_GSSR_PHY0_SM 0x0002 #define IXGBE_GSSR_PHY1_SM 0x0004 @@ -1505,13 +1537,15 @@ #define IXGBE_EEC_GNT 0x00000080 /* EEPROM Access Grant */ #define IXGBE_EEC_PRES 0x00000100 /* EEPROM Present */ #define IXGBE_EEC_ARD 0x00000200 /* EEPROM Auto Read Done */ +#define IXGBE_EEC_FLUP 0x00800000 /* Flash update command */ +#define IXGBE_EEC_FLUDONE 0x04000000 /* Flash update done */ /* EEPROM Addressing bits based on type (0-small, 1-large) */ #define IXGBE_EEC_ADDR_SIZE 0x00000400 #define IXGBE_EEC_SIZE 0x00007800 /* EEPROM Size */ -#define IXGBE_EEC_SIZE_SHIFT 11 -#define IXGBE_EEPROM_WORD_SIZE_SHIFT 6 -#define IXGBE_EEPROM_OPCODE_BITS 8 +#define IXGBE_EEC_SIZE_SHIFT 11 +#define IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT 6 +#define IXGBE_EEPROM_OPCODE_BITS 8 /* Checksum and EEPROM pointers */ #define IXGBE_EEPROM_CHECKSUM 0x3F @@ -1561,10 +1595,12 @@ #define IXGBE_EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */ /* EEPROM Read Register */ -#define IXGBE_EEPROM_READ_REG_DATA 16 /* data offset in EEPROM read reg */ -#define IXGBE_EEPROM_READ_REG_DONE 2 /* Offset to READ done bit */ -#define IXGBE_EEPROM_READ_REG_START 1 /* First bit to start operation */ -#define IXGBE_EEPROM_READ_ADDR_SHIFT 2 /* Shift to the address bits */ +#define IXGBE_EEPROM_RW_REG_DATA 16 /* data offset in EEPROM read reg */ +#define IXGBE_EEPROM_RW_REG_DONE 2 /* Offset to READ done bit */ +#define IXGBE_EEPROM_RW_REG_START 1 /* First bit to start operation */ +#define IXGBE_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ +#define IXGBE_NVM_POLL_WRITE 1 /* Flag for polling for write complete */ +#define IXGBE_NVM_POLL_READ 0 /* Flag for polling for read complete */ #define IXGBE_ETH_LENGTH_OF_ADDRESS 6 @@ -1572,9 +1608,17 @@ #define IXGBE_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ #endif -#ifndef IXGBE_EERD_ATTEMPTS -/* Number of 5 microseconds we wait for EERD read to complete */ -#define IXGBE_EERD_ATTEMPTS 100000 +#ifndef IXGBE_EERD_EEWR_ATTEMPTS +/* + * Number of 5 microseconds we wait for EERD read and + * EERW write to complete + */ +#define IXGBE_EERD_EEWR_ATTEMPTS 100000 +#endif + +#ifndef IXGBE_FLUDONE_ATTEMPTS +/* # attempts we wait for flush update to complete */ +#define IXGBE_FLUDONE_ATTEMPTS 20000 #endif #define IXGBE_PCIE_CTRL2 0x5 /* PCIe Control 2 Offset */ @@ -1588,9 +1632,18 @@ #define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2 #define IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR 0x4 #define IXGBE_FW_PATCH_VERSION_4 0x7 +#define IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR 0x27 /* Alt. SAN MAC block */ +#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET 0x0 /* Alt. SAN MAC capability */ +#define IXGBE_ALT_SAN_MAC_ADDR_PORT0_OFFSET 0x1 /* Alt. SAN MAC 0 offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_PORT1_OFFSET 0x4 /* Alt. SAN MAC 1 offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET 0x7 /* Alt. WWNN prefix offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET 0x8 /* Alt. WWPN prefix offset */ +#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_SANMAC 0x0 /* Alt. SAN MAC exists */ +#define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN 0x1 /* Alt. WWN base exists */ /* PCI Bus Info */ #define IXGBE_PCI_LINK_STATUS 0xB2 +#define IXGBE_PCI_DEVICE_CONTROL2 0xC8 #define IXGBE_PCI_LINK_WIDTH 0x3F0 #define IXGBE_PCI_LINK_WIDTH_1 0x10 #define IXGBE_PCI_LINK_WIDTH_2 0x20 @@ -1601,6 +1654,7 @@ #define IXGBE_PCI_LINK_SPEED_5000 0x2 #define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80 +#define IXGBE_PCI_DEVICE_CONTROL2_16ms 0x0005 /* Number of 100 microseconds we wait for PCI Express master disable */ #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800 @@ -1640,6 +1694,7 @@ /* Transmit Config masks */ #define IXGBE_TXDCTL_ENABLE 0x02000000 /* Enable specific Tx Queue */ #define IXGBE_TXDCTL_SWFLSH 0x04000000 /* Tx Desc. write-back flushing */ +#define IXGBE_TXDCTL_WTHRESH_SHIFT 16 /* shift to WTHRESH bits */ /* Enable short packet padding to 64 bytes */ #define IXGBE_TX_PAD_ENABLE 0x00000400 #define IXGBE_JUMBO_FRAME_ENABLE 0x00000004 /* Allow jumbo frames */ @@ -1882,6 +1937,7 @@ #define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600)) #define IXGBE_VFLREC(_i) (0x00700 + (_i * 4)) +/* Translated register #defines */ #ifndef __le16 /* Little Endian defines */ #define __le16 u16 @@ -2187,6 +2243,7 @@ enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, ixgbe_eeprom_spi, + ixgbe_flash, ixgbe_eeprom_none /* No NVM support */ }; @@ -2246,6 +2303,7 @@ ixgbe_media_type_fiber, ixgbe_media_type_copper, ixgbe_media_type_backplane, + ixgbe_media_type_cx4, ixgbe_media_type_virtual }; @@ -2258,6 +2316,14 @@ ixgbe_fc_default }; +/* Smart Speed Settings */ +#define IXGBE_SMARTSPEED_MAX_RETRIES 3 +enum ixgbe_smart_speed { + ixgbe_smart_speed_auto = 0, + ixgbe_smart_speed_on, + ixgbe_smart_speed_off +}; + /* PCI bus types */ enum ixgbe_bus_type { ixgbe_bus_type_unknown = 0, @@ -2424,6 +2490,7 @@ s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*set_san_mac_addr)(struct ixgbe_hw *, u8 *); s32 (*get_device_caps)(struct ixgbe_hw *, u16 *); + s32 (*get_wwn_prefix)(struct ixgbe_hw *, u16 *, u16 *); s32 (*stop_adapter)(struct ixgbe_hw *); s32 (*get_bus_info)(struct ixgbe_hw *); void (*set_lan_id)(struct ixgbe_hw *); @@ -2435,9 +2502,7 @@ void (*release_swfw_sync)(struct ixgbe_hw *, u16); /* Link */ - s32 (*setup_link)(struct ixgbe_hw *); - s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool, - bool); + s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool); s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); @@ -2502,6 +2567,10 @@ u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; u8 san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS]; + /* prefix for World Wide Node Name (WWNN) */ + u16 wwnn_prefix; + /* prefix for World Wide Port Name (WWPN) */ + u16 wwpn_prefix; s32 mc_filter_type; u32 mcft_size; u32 vft_size; @@ -2514,8 +2583,6 @@ u32 orig_autoc; u32 orig_autoc2; bool orig_link_settings_stored; - bool autoneg; - bool autoneg_succeeded; bool autotry_restart; }; @@ -2530,7 +2597,8 @@ enum ixgbe_media_type media_type; bool reset_disable; ixgbe_autoneg_advertised autoneg_advertised; - bool autoneg_wait_to_complete; + enum ixgbe_smart_speed smart_speed; + bool smart_speed_active; bool multispeed_fiber; };