#define TXGBE_ISCSI_BOOT_CONFIG 0x07
#define TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1
+#define TXGBE_FW_LESM_PARAMETERS_PTR 0x2
+#define TXGBE_FW_LESM_STATE_1 0x1
+#define TXGBE_FW_LESM_STATE_ENABLED 0x8000 /* LESM Enable bit */
s32 txgbe_init_eeprom_params(struct txgbe_hw *hw);
s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw);
#define TXGBE_RAPTOR_MAX_RX_QUEUES 128
#define TXGBE_RAPTOR_RAR_ENTRIES 128
+static s32 txgbe_setup_copper_link_raptor(struct txgbe_hw *hw,
+ u32 speed,
+ bool autoneg_wait_to_complete);
+
/**
* txgbe_init_hw - Generic hardware initialization
* @hw: pointer to hardware structure
return status;
}
+/**
+ * txgbe_need_crosstalk_fix - Determine if we need to do cross talk fix
+ * @hw: pointer to hardware structure
+ *
+ * Contains the logic to identify if we need to verify link for the
+ * crosstalk fix
+ **/
+static bool txgbe_need_crosstalk_fix(struct txgbe_hw *hw)
+{
+ /* Does FW say we need the fix */
+ if (!hw->need_crosstalk_fix)
+ return false;
+
+ /* Only consider SFP+ PHYs i.e. media type fiber */
+ switch (hw->phy.media_type) {
+ case txgbe_media_type_fiber:
+ case txgbe_media_type_fiber_qsfp:
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * txgbe_check_mac_link - 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 txgbe_check_mac_link(struct txgbe_hw *hw, u32 *speed,
+ bool *link_up, bool link_up_wait_to_complete)
+{
+ u32 links_reg, links_orig;
+ u32 i;
+
+ DEBUGFUNC("txgbe_check_mac_link");
+
+ /* If Crosstalk fix enabled do the sanity check of making sure
+ * the SFP+ cage is full.
+ */
+ if (txgbe_need_crosstalk_fix(hw)) {
+ u32 sfp_cage_full;
+
+ switch (hw->mac.type) {
+ case txgbe_mac_raptor:
+ sfp_cage_full = !rd32m(hw, TXGBE_GPIODATA,
+ TXGBE_GPIOBIT_2);
+ break;
+ default:
+ /* sanity check - No SFP+ devices here */
+ sfp_cage_full = false;
+ break;
+ }
+
+ if (!sfp_cage_full) {
+ *link_up = false;
+ *speed = TXGBE_LINK_SPEED_UNKNOWN;
+ return 0;
+ }
+ }
+
+ /* clear the old state */
+ links_orig = rd32(hw, TXGBE_PORTSTAT);
+
+ links_reg = rd32(hw, TXGBE_PORTSTAT);
+
+ if (links_orig != links_reg) {
+ DEBUGOUT("LINKS changed from %08X to %08X\n",
+ links_orig, links_reg);
+ }
+
+ if (link_up_wait_to_complete) {
+ for (i = 0; i < hw->mac.max_link_up_time; i++) {
+ if (!(links_reg & TXGBE_PORTSTAT_UP)) {
+ *link_up = false;
+ } else {
+ *link_up = true;
+ break;
+ }
+ msec_delay(100);
+ links_reg = rd32(hw, TXGBE_PORTSTAT);
+ }
+ } else {
+ if (links_reg & TXGBE_PORTSTAT_UP)
+ *link_up = true;
+ else
+ *link_up = false;
+ }
+
+ switch (links_reg & TXGBE_PORTSTAT_BW_MASK) {
+ case TXGBE_PORTSTAT_BW_10G:
+ *speed = TXGBE_LINK_SPEED_10GB_FULL;
+ break;
+ case TXGBE_PORTSTAT_BW_1G:
+ *speed = TXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ case TXGBE_PORTSTAT_BW_100M:
+ *speed = TXGBE_LINK_SPEED_100M_FULL;
+ break;
+ default:
+ *speed = TXGBE_LINK_SPEED_UNKNOWN;
+ }
+
+ return 0;
+}
+
/**
* txgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo
* @hw: pointer to the hardware structure
struct txgbe_mac_info *mac = &hw->mac;
DEBUGFUNC("txgbe_init_mac_link_ops");
- RTE_SET_USED(mac);
+
+ mac->setup_link = txgbe_setup_mac_link;
}
/**
**/
s32 txgbe_init_phy_raptor(struct txgbe_hw *hw)
{
+ struct txgbe_mac_info *mac = &hw->mac;
struct txgbe_phy_info *phy = &hw->phy;
s32 err = 0;
/* Setup function pointers based on detected SFP module and speeds */
txgbe_init_mac_link_ops(hw);
+ /* If copper media, overwrite with copper function pointers */
+ if (phy->media_type == txgbe_media_type_copper) {
+ mac->setup_link = txgbe_setup_copper_link_raptor;
+ mac->get_link_capabilities =
+ txgbe_get_copper_link_capabilities;
+ }
+
+ /* Set necessary function pointers based on PHY type */
+ switch (hw->phy.type) {
+ case txgbe_phy_tn:
+ phy->setup_link = txgbe_setup_phy_link_tnx;
+ phy->check_link = txgbe_check_phy_link_tnx;
+ break;
+ default:
+ break;
+ }
+
init_phy_ops_out:
return err;
}
phy->write_reg = txgbe_write_phy_reg;
phy->read_reg_mdi = txgbe_read_phy_reg_mdi;
phy->write_reg_mdi = txgbe_write_phy_reg_mdi;
+ phy->setup_link = txgbe_setup_phy_link;
+ phy->setup_link_speed = txgbe_setup_phy_link_speed;
phy->read_i2c_byte = txgbe_read_i2c_byte;
phy->write_i2c_byte = txgbe_write_i2c_byte;
phy->read_i2c_eeprom = txgbe_read_i2c_eeprom;
mac->init_hw = txgbe_init_hw;
mac->reset_hw = txgbe_reset_hw;
+ /* Link */
+ mac->get_link_capabilities = txgbe_get_link_capabilities_raptor;
+ mac->check_link = txgbe_check_mac_link;
+
/* EEPROM */
rom->init_params = txgbe_init_eeprom_params;
rom->read16 = txgbe_ee_read16;
return 0;
}
+/**
+ * txgbe_get_link_capabilities_raptor - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: true when autoneg or autotry is enabled
+ *
+ * Determines the link capabilities by reading the AUTOC register.
+ **/
+s32 txgbe_get_link_capabilities_raptor(struct txgbe_hw *hw,
+ u32 *speed,
+ bool *autoneg)
+{
+ s32 status = 0;
+ u32 autoc = 0;
+
+ DEBUGFUNC("txgbe_get_link_capabilities_raptor");
+
+ /* Check if 1G SFP module. */
+ if (hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core0 ||
+ hw->phy.sfp_type == txgbe_sfp_type_1g_cu_core1 ||
+ hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core0 ||
+ hw->phy.sfp_type == txgbe_sfp_type_1g_lx_core1 ||
+ hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 ||
+ hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1) {
+ *speed = TXGBE_LINK_SPEED_1GB_FULL;
+ *autoneg = true;
+ return 0;
+ }
+
+ /*
+ * Determine link capabilities based on the stored value of AUTOC,
+ * which represents EEPROM defaults. If AUTOC value has not
+ * been stored, use the current register values.
+ */
+ if (hw->mac.orig_link_settings_stored)
+ autoc = hw->mac.orig_autoc;
+ else
+ autoc = hw->mac.autoc_read(hw);
+
+ switch (autoc & TXGBE_AUTOC_LMS_MASK) {
+ case TXGBE_AUTOC_LMS_1G_LINK_NO_AN:
+ *speed = TXGBE_LINK_SPEED_1GB_FULL;
+ *autoneg = false;
+ break;
+
+ case TXGBE_AUTOC_LMS_10G_LINK_NO_AN:
+ *speed = TXGBE_LINK_SPEED_10GB_FULL;
+ *autoneg = false;
+ break;
+
+ case TXGBE_AUTOC_LMS_1G_AN:
+ *speed = TXGBE_LINK_SPEED_1GB_FULL;
+ *autoneg = true;
+ break;
+
+ case TXGBE_AUTOC_LMS_10G:
+ *speed = TXGBE_LINK_SPEED_10GB_FULL;
+ *autoneg = false;
+ break;
+
+ case TXGBE_AUTOC_LMS_KX4_KX_KR:
+ case TXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
+ *speed = TXGBE_LINK_SPEED_UNKNOWN;
+ if (autoc & TXGBE_AUTOC_KR_SUPP)
+ *speed |= TXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & TXGBE_AUTOC_KX4_SUPP)
+ *speed |= TXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & TXGBE_AUTOC_KX_SUPP)
+ *speed |= TXGBE_LINK_SPEED_1GB_FULL;
+ *autoneg = true;
+ break;
+
+ case TXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
+ *speed = TXGBE_LINK_SPEED_100M_FULL;
+ if (autoc & TXGBE_AUTOC_KR_SUPP)
+ *speed |= TXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & TXGBE_AUTOC_KX4_SUPP)
+ *speed |= TXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & TXGBE_AUTOC_KX_SUPP)
+ *speed |= TXGBE_LINK_SPEED_1GB_FULL;
+ *autoneg = true;
+ break;
+
+ case TXGBE_AUTOC_LMS_SGMII_1G_100M:
+ *speed = TXGBE_LINK_SPEED_1GB_FULL |
+ TXGBE_LINK_SPEED_100M_FULL |
+ TXGBE_LINK_SPEED_10M_FULL;
+ *autoneg = false;
+ break;
+
+ default:
+ return TXGBE_ERR_LINK_SETUP;
+ }
+
+ return status;
+}
+
+/**
+ * txgbe_start_mac_link_raptor - Setup MAC link settings
+ * @hw: pointer to hardware structure
+ * @autoneg_wait_to_complete: true when waiting for completion is needed
+ *
+ * Configures link settings based on values in the txgbe_hw struct.
+ * Restarts the link. Performs autonegotiation if needed.
+ **/
+s32 txgbe_start_mac_link_raptor(struct txgbe_hw *hw,
+ bool autoneg_wait_to_complete)
+{
+ s32 status = 0;
+ bool got_lock = false;
+
+ DEBUGFUNC("txgbe_start_mac_link_raptor");
+
+ UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+
+ /* reset_pipeline requires us to hold this lock as it writes to
+ * AUTOC.
+ */
+ if (txgbe_verify_lesm_fw_enabled_raptor(hw)) {
+ status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY);
+ if (status != 0)
+ goto out;
+
+ got_lock = true;
+ }
+
+ /* Restart link */
+ txgbe_reset_pipeline_raptor(hw);
+
+ if (got_lock)
+ hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY);
+
+ /* Add delay to filter out noises during initial link setup */
+ msec_delay(50);
+
+out:
+ return status;
+}
+
+/**
+ * txgbe_setup_mac_link - Set MAC link speed
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait_to_complete: true when waiting for completion is needed
+ *
+ * Set the link speed in the AUTOC register and restarts link.
+ **/
+s32 txgbe_setup_mac_link(struct txgbe_hw *hw,
+ u32 speed,
+ bool autoneg_wait_to_complete)
+{
+ bool autoneg = false;
+ s32 status = 0;
+
+ u64 autoc = hw->mac.autoc_read(hw);
+ u64 pma_pmd_10gs = autoc & TXGBE_AUTOC_10GS_PMA_PMD_MASK;
+ u64 pma_pmd_1g = autoc & TXGBE_AUTOC_1G_PMA_PMD_MASK;
+ u64 link_mode = autoc & TXGBE_AUTOC_LMS_MASK;
+ u64 current_autoc = autoc;
+ u64 orig_autoc = 0;
+ u32 links_reg;
+ u32 i;
+ u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN;
+
+ DEBUGFUNC("txgbe_setup_mac_link");
+
+ /* Check to see if speed passed in is supported. */
+ status = hw->mac.get_link_capabilities(hw,
+ &link_capabilities, &autoneg);
+ if (status)
+ return status;
+
+ speed &= link_capabilities;
+ if (speed == TXGBE_LINK_SPEED_UNKNOWN)
+ return TXGBE_ERR_LINK_SETUP;
+
+ /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
+ if (hw->mac.orig_link_settings_stored)
+ orig_autoc = hw->mac.orig_autoc;
+ else
+ orig_autoc = autoc;
+
+ link_mode = autoc & TXGBE_AUTOC_LMS_MASK;
+ pma_pmd_1g = autoc & TXGBE_AUTOC_1G_PMA_PMD_MASK;
+
+ if (link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR ||
+ link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
+ link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
+ /* Set KX4/KX/KR support according to speed requested */
+ autoc &= ~(TXGBE_AUTOC_KX_SUPP |
+ TXGBE_AUTOC_KX4_SUPP |
+ TXGBE_AUTOC_KR_SUPP);
+ if (speed & TXGBE_LINK_SPEED_10GB_FULL) {
+ if (orig_autoc & TXGBE_AUTOC_KX4_SUPP)
+ autoc |= TXGBE_AUTOC_KX4_SUPP;
+ if ((orig_autoc & TXGBE_AUTOC_KR_SUPP) &&
+ !hw->phy.smart_speed_active)
+ autoc |= TXGBE_AUTOC_KR_SUPP;
+ }
+ if (speed & TXGBE_LINK_SPEED_1GB_FULL)
+ autoc |= TXGBE_AUTOC_KX_SUPP;
+ } else if ((pma_pmd_1g == TXGBE_AUTOC_1G_SFI) &&
+ (link_mode == TXGBE_AUTOC_LMS_1G_LINK_NO_AN ||
+ link_mode == TXGBE_AUTOC_LMS_1G_AN)) {
+ /* Switch from 1G SFI to 10G SFI if requested */
+ if (speed == TXGBE_LINK_SPEED_10GB_FULL &&
+ pma_pmd_10gs == TXGBE_AUTOC_10GS_SFI) {
+ autoc &= ~TXGBE_AUTOC_LMS_MASK;
+ autoc |= TXGBE_AUTOC_LMS_10G;
+ }
+ } else if ((pma_pmd_10gs == TXGBE_AUTOC_10GS_SFI) &&
+ (link_mode == TXGBE_AUTOC_LMS_10G)) {
+ /* Switch from 10G SFI to 1G SFI if requested */
+ if (speed == TXGBE_LINK_SPEED_1GB_FULL &&
+ pma_pmd_1g == TXGBE_AUTOC_1G_SFI) {
+ autoc &= ~TXGBE_AUTOC_LMS_MASK;
+ if (autoneg || hw->phy.type == txgbe_phy_qsfp_intel)
+ autoc |= TXGBE_AUTOC_LMS_1G_AN;
+ else
+ autoc |= TXGBE_AUTOC_LMS_1G_LINK_NO_AN;
+ }
+ }
+
+ if (autoc == current_autoc)
+ return status;
+
+ autoc &= ~TXGBE_AUTOC_SPEED_MASK;
+ autoc |= TXGBE_AUTOC_SPEED(speed);
+ autoc |= (autoneg ? TXGBE_AUTOC_AUTONEG : 0);
+
+ /* Restart link */
+ hw->mac.autoc_write(hw, autoc);
+
+ /* Only poll for autoneg to complete if specified to do so */
+ if (autoneg_wait_to_complete) {
+ if (link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR ||
+ link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
+ link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
+ links_reg = 0; /*Just in case Autoneg time=0*/
+ for (i = 0; i < TXGBE_AUTO_NEG_TIME; i++) {
+ links_reg = rd32(hw, TXGBE_PORTSTAT);
+ if (links_reg & TXGBE_PORTSTAT_UP)
+ break;
+ msec_delay(100);
+ }
+ if (!(links_reg & TXGBE_PORTSTAT_UP)) {
+ status = TXGBE_ERR_AUTONEG_NOT_COMPLETE;
+ DEBUGOUT("Autoneg did not complete.\n");
+ }
+ }
+ }
+
+ /* Add delay to filter out noises during initial link setup */
+ msec_delay(50);
+
+ return status;
+}
+
+/**
+ * txgbe_setup_copper_link_raptor - Set the PHY autoneg advertised field
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait_to_complete: true if waiting is needed to complete
+ *
+ * Restarts link on PHY and MAC based on settings passed in.
+ **/
+static s32 txgbe_setup_copper_link_raptor(struct txgbe_hw *hw,
+ u32 speed,
+ bool autoneg_wait_to_complete)
+{
+ s32 status;
+
+ DEBUGFUNC("txgbe_setup_copper_link_raptor");
+
+ /* Setup the PHY according to input speed */
+ status = hw->phy.setup_link_speed(hw, speed,
+ autoneg_wait_to_complete);
+ /* Set up MAC */
+ txgbe_start_mac_link_raptor(hw, autoneg_wait_to_complete);
+
+ return status;
+}
+
static int
txgbe_check_flash_load(struct txgbe_hw *hw, u32 check_bit)
{
return status;
}
+/**
+ * txgbe_verify_lesm_fw_enabled_raptor - Checks LESM FW module state.
+ * @hw: pointer to hardware structure
+ *
+ * Returns true if the LESM FW module is present and enabled. Otherwise
+ * returns false. Smart Speed must be disabled if LESM FW module is enabled.
+ **/
+bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw)
+{
+ bool lesm_enabled = false;
+ u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
+ s32 status;
+
+ DEBUGFUNC("txgbe_verify_lesm_fw_enabled_raptor");
+
+ /* get the offset to the Firmware Module block */
+ status = hw->rom.read16(hw, TXGBE_FW_PTR, &fw_offset);
+
+ if (status != 0 || fw_offset == 0 || fw_offset == 0xFFFF)
+ goto out;
+
+ /* get the offset to the LESM Parameters block */
+ status = hw->rom.read16(hw, (fw_offset +
+ TXGBE_FW_LESM_PARAMETERS_PTR),
+ &fw_lesm_param_offset);
+
+ if (status != 0 ||
+ fw_lesm_param_offset == 0 || fw_lesm_param_offset == 0xFFFF)
+ goto out;
+
+ /* get the LESM state word */
+ status = hw->rom.read16(hw, (fw_lesm_param_offset +
+ TXGBE_FW_LESM_STATE_1),
+ &fw_lesm_state);
+
+ if (status == 0 && (fw_lesm_state & TXGBE_FW_LESM_STATE_ENABLED))
+ lesm_enabled = true;
+
+out:
+ lesm_enabled = false;
+ return lesm_enabled;
+}
+
+/**
+ * txgbe_reset_pipeline_raptor - perform pipeline reset
+ *
+ * @hw: pointer to hardware structure
+ *
+ * Reset pipeline by asserting Restart_AN together with LMS change to ensure
+ * full pipeline reset. This function assumes the SW/FW lock is held.
+ **/
+s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw)
+{
+ s32 err = 0;
+ u64 autoc;
+
+ autoc = hw->mac.autoc_read(hw);
+
+ /* Enable link if disabled in NVM */
+ if (autoc & TXGBE_AUTOC_LINK_DIA_MASK)
+ autoc &= ~TXGBE_AUTOC_LINK_DIA_MASK;
+
+ autoc |= TXGBE_AUTOC_AN_RESTART;
+ /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
+ hw->mac.autoc_write(hw, autoc ^ TXGBE_AUTOC_LMS_AN);
+
+ /* Write AUTOC register with original LMS field and Restart_AN */
+ hw->mac.autoc_write(hw, autoc);
+ txgbe_flush(hw);
+
+ return err;
+}
+
void txgbe_set_lan_id_multi_port(struct txgbe_hw *hw);
s32 txgbe_validate_mac_addr(u8 *mac_addr);
+
+s32 txgbe_check_mac_link(struct txgbe_hw *hw,
+ u32 *speed,
+ bool *link_up, bool link_up_wait_to_complete);
+
void txgbe_clear_tx_pending(struct txgbe_hw *hw);
+
+s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw);
+
s32 txgbe_init_shared_code(struct txgbe_hw *hw);
s32 txgbe_set_mac_type(struct txgbe_hw *hw);
s32 txgbe_init_ops_pf(struct txgbe_hw *hw);
+s32 txgbe_get_link_capabilities_raptor(struct txgbe_hw *hw,
+ u32 *speed, bool *autoneg);
+s32 txgbe_start_mac_link_raptor(struct txgbe_hw *hw,
+ bool autoneg_wait_to_complete);
+s32 txgbe_setup_mac_link(struct txgbe_hw *hw, u32 speed,
+ bool autoneg_wait_to_complete);
void txgbe_init_mac_link_ops(struct txgbe_hw *hw);
s32 txgbe_reset_hw(struct txgbe_hw *hw);
s32 txgbe_init_phy_raptor(struct txgbe_hw *hw);
+bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw);
#endif /* _TXGBE_HW_H_ */
return err;
}
+
+/**
+ * txgbe_setup_phy_link - Set and restart auto-neg
+ * @hw: pointer to hardware structure
+ *
+ * Restart auto-negotiation and PHY and waits for completion.
+ **/
+s32 txgbe_setup_phy_link(struct txgbe_hw *hw)
+{
+ s32 err = 0;
+ u16 autoneg_reg = TXGBE_MII_AUTONEG_REG;
+ bool autoneg = false;
+ u32 speed;
+
+ DEBUGFUNC("txgbe_setup_phy_link");
+
+ txgbe_get_copper_link_capabilities(hw, &speed, &autoneg);
+
+ /* Set or unset auto-negotiation 10G advertisement */
+ hw->phy.read_reg(hw, TXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &autoneg_reg);
+
+ autoneg_reg &= ~TXGBE_MII_10GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & TXGBE_LINK_SPEED_10GB_FULL) &&
+ (speed & TXGBE_LINK_SPEED_10GB_FULL))
+ autoneg_reg |= TXGBE_MII_10GBASE_T_ADVERTISE;
+
+ hw->phy.write_reg(hw, TXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ autoneg_reg);
+
+ hw->phy.read_reg(hw, TXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &autoneg_reg);
+
+ /* Set or unset auto-negotiation 5G advertisement */
+ autoneg_reg &= ~TXGBE_MII_5GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & TXGBE_LINK_SPEED_5GB_FULL) &&
+ (speed & TXGBE_LINK_SPEED_5GB_FULL))
+ autoneg_reg |= TXGBE_MII_5GBASE_T_ADVERTISE;
+
+ /* Set or unset auto-negotiation 2.5G advertisement */
+ autoneg_reg &= ~TXGBE_MII_2_5GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised &
+ TXGBE_LINK_SPEED_2_5GB_FULL) &&
+ (speed & TXGBE_LINK_SPEED_2_5GB_FULL))
+ autoneg_reg |= TXGBE_MII_2_5GBASE_T_ADVERTISE;
+ /* Set or unset auto-negotiation 1G advertisement */
+ autoneg_reg &= ~TXGBE_MII_1GBASE_T_ADVERTISE;
+ if ((hw->phy.autoneg_advertised & TXGBE_LINK_SPEED_1GB_FULL) &&
+ (speed & TXGBE_LINK_SPEED_1GB_FULL))
+ autoneg_reg |= TXGBE_MII_1GBASE_T_ADVERTISE;
+
+ hw->phy.write_reg(hw, TXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ autoneg_reg);
+
+ /* Set or unset auto-negotiation 100M advertisement */
+ hw->phy.read_reg(hw, TXGBE_MII_AUTONEG_ADVERTISE_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &autoneg_reg);
+
+ autoneg_reg &= ~(TXGBE_MII_100BASE_T_ADVERTISE |
+ TXGBE_MII_100BASE_T_ADVERTISE_HALF);
+ if ((hw->phy.autoneg_advertised & TXGBE_LINK_SPEED_100M_FULL) &&
+ (speed & TXGBE_LINK_SPEED_100M_FULL))
+ autoneg_reg |= TXGBE_MII_100BASE_T_ADVERTISE;
+
+ hw->phy.write_reg(hw, TXGBE_MII_AUTONEG_ADVERTISE_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ autoneg_reg);
+
+ /* Blocked by MNG FW so don't reset PHY */
+ if (txgbe_check_reset_blocked(hw))
+ return err;
+
+ /* Restart PHY auto-negotiation. */
+ hw->phy.read_reg(hw, TXGBE_MD_AUTO_NEG_CONTROL,
+ TXGBE_MD_DEV_AUTO_NEG, &autoneg_reg);
+
+ autoneg_reg |= TXGBE_MII_RESTART;
+
+ hw->phy.write_reg(hw, TXGBE_MD_AUTO_NEG_CONTROL,
+ TXGBE_MD_DEV_AUTO_NEG, autoneg_reg);
+
+ return err;
+}
+
+/**
+ * txgbe_setup_phy_link_speed - Sets the auto advertised capabilities
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait_to_complete: unused
+ **/
+s32 txgbe_setup_phy_link_speed(struct txgbe_hw *hw,
+ u32 speed,
+ bool autoneg_wait_to_complete)
+{
+ UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
+
+ DEBUGFUNC("txgbe_setup_phy_link_speed");
+
+ /*
+ * Clear autoneg_advertised and set new values based on input link
+ * speed.
+ */
+ hw->phy.autoneg_advertised = 0;
+
+ if (speed & TXGBE_LINK_SPEED_10GB_FULL)
+ hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10GB_FULL;
+
+ if (speed & TXGBE_LINK_SPEED_5GB_FULL)
+ hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_5GB_FULL;
+
+ if (speed & TXGBE_LINK_SPEED_2_5GB_FULL)
+ hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_2_5GB_FULL;
+
+ if (speed & TXGBE_LINK_SPEED_1GB_FULL)
+ hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_1GB_FULL;
+
+ if (speed & TXGBE_LINK_SPEED_100M_FULL)
+ hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_100M_FULL;
+
+ if (speed & TXGBE_LINK_SPEED_10M_FULL)
+ hw->phy.autoneg_advertised |= TXGBE_LINK_SPEED_10M_FULL;
+
+ /* Setup link based on the new speed settings */
+ hw->phy.setup_link(hw);
+
+ return 0;
+}
+
+/**
+ * txgbe_get_copper_speeds_supported - Get copper link speeds from phy
+ * @hw: pointer to hardware structure
+ *
+ * Determines the supported link capabilities by reading the PHY auto
+ * negotiation register.
+ **/
+static s32 txgbe_get_copper_speeds_supported(struct txgbe_hw *hw)
+{
+ s32 err;
+ u16 speed_ability;
+
+ err = hw->phy.read_reg(hw, TXGBE_MD_PHY_SPEED_ABILITY,
+ TXGBE_MD_DEV_PMA_PMD,
+ &speed_ability);
+ if (err)
+ return err;
+
+ if (speed_ability & TXGBE_MD_PHY_SPEED_10G)
+ hw->phy.speeds_supported |= TXGBE_LINK_SPEED_10GB_FULL;
+ if (speed_ability & TXGBE_MD_PHY_SPEED_1G)
+ hw->phy.speeds_supported |= TXGBE_LINK_SPEED_1GB_FULL;
+ if (speed_ability & TXGBE_MD_PHY_SPEED_100M)
+ hw->phy.speeds_supported |= TXGBE_LINK_SPEED_100M_FULL;
+
+ return err;
+}
+
+/**
+ * txgbe_get_copper_link_capabilities - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: boolean auto-negotiation value
+ **/
+s32 txgbe_get_copper_link_capabilities(struct txgbe_hw *hw,
+ u32 *speed,
+ bool *autoneg)
+{
+ s32 err = 0;
+
+ DEBUGFUNC("txgbe_get_copper_link_capabilities");
+
+ *autoneg = true;
+ if (!hw->phy.speeds_supported)
+ err = txgbe_get_copper_speeds_supported(hw);
+
+ *speed = hw->phy.speeds_supported;
+ return err;
+}
+
+/**
+ * txgbe_check_phy_link_tnx - Determine link and speed status
+ * @hw: pointer to hardware structure
+ * @speed: current link speed
+ * @link_up: true is link is up, false otherwise
+ *
+ * Reads the VS1 register to determine if link is up and the current speed for
+ * the PHY.
+ **/
+s32 txgbe_check_phy_link_tnx(struct txgbe_hw *hw, u32 *speed,
+ bool *link_up)
+{
+ s32 err = 0;
+ u32 time_out;
+ u32 max_time_out = 10;
+ u16 phy_link = 0;
+ u16 phy_speed = 0;
+ u16 phy_data = 0;
+
+ DEBUGFUNC("txgbe_check_phy_link_tnx");
+
+ /* Initialize speed and link to default case */
+ *link_up = false;
+ *speed = TXGBE_LINK_SPEED_10GB_FULL;
+
+ /*
+ * Check current speed and link status of the PHY register.
+ * This is a vendor specific register and may have to
+ * be changed for other copper PHYs.
+ */
+ for (time_out = 0; time_out < max_time_out; time_out++) {
+ usec_delay(10);
+ err = hw->phy.read_reg(hw,
+ TXGBE_MD_VENDOR_SPECIFIC_1_STATUS,
+ TXGBE_MD_DEV_VENDOR_1,
+ &phy_data);
+ phy_link = phy_data & TXGBE_MD_VENDOR_SPECIFIC_1_LINK_STATUS;
+ phy_speed = phy_data &
+ TXGBE_MD_VENDOR_SPECIFIC_1_SPEED_STATUS;
+ if (phy_link == TXGBE_MD_VENDOR_SPECIFIC_1_LINK_STATUS) {
+ *link_up = true;
+ if (phy_speed ==
+ TXGBE_MD_VENDOR_SPECIFIC_1_SPEED_STATUS)
+ *speed = TXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ }
+ }
+
+ return err;
+}
+
+/**
+ * txgbe_setup_phy_link_tnx - Set and restart auto-neg
+ * @hw: pointer to hardware structure
+ *
+ * Restart auto-negotiation and PHY and waits for completion.
+ **/
+s32 txgbe_setup_phy_link_tnx(struct txgbe_hw *hw)
+{
+ s32 err = 0;
+ u16 autoneg_reg = TXGBE_MII_AUTONEG_REG;
+ bool autoneg = false;
+ u32 speed;
+
+ DEBUGFUNC("txgbe_setup_phy_link_tnx");
+
+ txgbe_get_copper_link_capabilities(hw, &speed, &autoneg);
+
+ if (speed & TXGBE_LINK_SPEED_10GB_FULL) {
+ /* Set or unset auto-negotiation 10G advertisement */
+ hw->phy.read_reg(hw, TXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &autoneg_reg);
+
+ autoneg_reg &= ~TXGBE_MII_10GBASE_T_ADVERTISE;
+ if (hw->phy.autoneg_advertised & TXGBE_LINK_SPEED_10GB_FULL)
+ autoneg_reg |= TXGBE_MII_10GBASE_T_ADVERTISE;
+
+ hw->phy.write_reg(hw, TXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ autoneg_reg);
+ }
+
+ if (speed & TXGBE_LINK_SPEED_1GB_FULL) {
+ /* Set or unset auto-negotiation 1G advertisement */
+ hw->phy.read_reg(hw, TXGBE_MII_AUTONEG_XNP_TX_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &autoneg_reg);
+
+ autoneg_reg &= ~TXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+ if (hw->phy.autoneg_advertised & TXGBE_LINK_SPEED_1GB_FULL)
+ autoneg_reg |= TXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+
+ hw->phy.write_reg(hw, TXGBE_MII_AUTONEG_XNP_TX_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ autoneg_reg);
+ }
+
+ if (speed & TXGBE_LINK_SPEED_100M_FULL) {
+ /* Set or unset auto-negotiation 100M advertisement */
+ hw->phy.read_reg(hw, TXGBE_MII_AUTONEG_ADVERTISE_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &autoneg_reg);
+
+ autoneg_reg &= ~TXGBE_MII_100BASE_T_ADVERTISE;
+ if (hw->phy.autoneg_advertised & TXGBE_LINK_SPEED_100M_FULL)
+ autoneg_reg |= TXGBE_MII_100BASE_T_ADVERTISE;
+
+ hw->phy.write_reg(hw, TXGBE_MII_AUTONEG_ADVERTISE_REG,
+ TXGBE_MD_DEV_AUTO_NEG,
+ autoneg_reg);
+ }
+
+ /* Blocked by MNG FW so don't reset PHY */
+ if (txgbe_check_reset_blocked(hw))
+ return err;
+
+ /* Restart PHY auto-negotiation. */
+ hw->phy.read_reg(hw, TXGBE_MD_AUTO_NEG_CONTROL,
+ TXGBE_MD_DEV_AUTO_NEG, &autoneg_reg);
+
+ autoneg_reg |= TXGBE_MII_RESTART;
+
+ hw->phy.write_reg(hw, TXGBE_MD_AUTO_NEG_CONTROL,
+ TXGBE_MD_DEV_AUTO_NEG, autoneg_reg);
+
+ return err;
+}
+
/**
* txgbe_identify_module - Identifies module type
* @hw: pointer to hardware structure
u32 device_type, u16 *phy_data);
s32 txgbe_write_phy_reg(struct txgbe_hw *hw, u32 reg_addr,
u32 device_type, u16 phy_data);
+s32 txgbe_setup_phy_link(struct txgbe_hw *hw);
+s32 txgbe_setup_phy_link_speed(struct txgbe_hw *hw,
+ u32 speed,
+ bool autoneg_wait_to_complete);
+s32 txgbe_get_copper_link_capabilities(struct txgbe_hw *hw,
+ u32 *speed,
+ bool *autoneg);
s32 txgbe_check_reset_blocked(struct txgbe_hw *hw);
/* PHY specific */
+s32 txgbe_check_phy_link_tnx(struct txgbe_hw *hw,
+ u32 *speed,
+ bool *link_up);
+s32 txgbe_setup_phy_link_tnx(struct txgbe_hw *hw);
+
s32 txgbe_identify_module(struct txgbe_hw *hw);
s32 txgbe_identify_sfp_module(struct txgbe_hw *hw);
s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw);
#define TXGBE_AUTOC_1G_KX_BX LS64(1, 9, 0x7)
#define TXGBE_AUTOC_AN_RESTART MS64(12, 0x1)
#define TXGBE_AUTOC_LMS_MASK MS64(13, 0x7)
-#define TXGBE_AUTOC_LMS_10Gs LS64(3, 13, 0x7)
+#define TXGBE_AUTOC_LMS_10G LS64(3, 13, 0x7)
#define TXGBE_AUTOC_LMS_KX4_KX_KR LS64(4, 13, 0x7)
#define TXGBE_AUTOC_LMS_SGMII_1G_100M LS64(5, 13, 0x7)
#define TXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN LS64(6, 13, 0x7)
#define TXGBE_AUTOC_KX_SUPP MS64(30, 0x1)
#define TXGBE_AUTOC_KX4_SUPP MS64(31, 0x1)
-#define TXGBE_AUTOC_10Gs_PMA_PMD_MASK MS64(48, 0x3) /* serial */
-#define TXGBE_AUTOC_10Gs_KR LS64(0, 48, 0x3)
-#define TXGBE_AUTOC_10Gs_XFI LS64(1, 48, 0x3)
-#define TXGBE_AUTOC_10Gs_SFI LS64(2, 48, 0x3)
+#define TXGBE_AUTOC_10GS_PMA_PMD_MASK MS64(48, 0x3) /* serial */
+#define TXGBE_AUTOC_10GS_KR LS64(0, 48, 0x3)
+#define TXGBE_AUTOC_10GS_XFI LS64(1, 48, 0x3)
+#define TXGBE_AUTOC_10GS_SFI LS64(2, 48, 0x3)
#define TXGBE_AUTOC_LINK_DIA_MASK MS64(60, 0x7)
#define TXGBE_AUTOC_LINK_DIA_D3_MASK LS64(5, 60, 0x7)
#define _TXGBE_TYPE_H_
#define TXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
+#define TXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
#define TXGBE_ALIGN 128 /* as intel did */
txgbe_media_type_virtual
};
+
+/* Smart Speed Settings */
+#define TXGBE_SMARTSPEED_MAX_RETRIES 3
+enum txgbe_smart_speed {
+ txgbe_smart_speed_auto = 0,
+ txgbe_smart_speed_on,
+ txgbe_smart_speed_off
+};
+
/* PCI bus types */
enum txgbe_bus_type {
txgbe_bus_type_unknown = 0,
u32 max_rx_queues;
u8 san_mac_rar_index;
+ bool get_link_status;
u64 orig_autoc; /* cached value of AUTOC */
bool orig_link_settings_stored;
bool autotry_restart;
u32 media_type;
u32 phy_semaphore_mask;
bool reset_disable;
+ u32 autoneg_advertised;
+ u32 speeds_supported;
+ enum txgbe_smart_speed smart_speed;
+ bool smart_speed_active;
bool multispeed_fiber;
bool qsfp_shared_i2c_bus;
u32 nw_mng_if_sel;
u16 subsystem_vendor_id;
bool allow_unsupported_sfp;
+ bool need_crosstalk_fix;
uint64_t isb_dma;
void IOMEM *isb_mem;
+ enum txgbe_link_status {
+ TXGBE_LINK_STATUS_NONE = 0,
+ TXGBE_LINK_STATUS_KX,
+ TXGBE_LINK_STATUS_KX4
+ } link_status;
enum txgbe_reset_type {
TXGBE_LAN_RESET = 0,
TXGBE_SW_RESET,
#include "txgbe_ethdev.h"
#include "txgbe_rxtx.h"
+static int txgbe_dev_set_link_up(struct rte_eth_dev *dev);
+static int txgbe_dev_set_link_down(struct rte_eth_dev *dev);
static int txgbe_dev_close(struct rte_eth_dev *dev);
+static int txgbe_dev_link_update(struct rte_eth_dev *dev,
+ int wait_to_complete);
static void txgbe_dev_link_status_print(struct rte_eth_dev *dev);
static int txgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on);
intr->mask_misc |= TXGBE_ICRMISC_GPIO;
}
+/*
+ * Set device link up: enable tx.
+ */
+static int
+txgbe_dev_set_link_up(struct rte_eth_dev *dev)
+{
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+
+ if (hw->phy.media_type == txgbe_media_type_copper) {
+ /* Turn on the copper */
+ hw->phy.set_phy_power(hw, true);
+ } else {
+ /* Turn on the laser */
+ hw->mac.enable_tx_laser(hw);
+ txgbe_dev_link_update(dev, 0);
+ }
+
+ return 0;
+}
+
+/*
+ * Set device link down: disable tx.
+ */
+static int
+txgbe_dev_set_link_down(struct rte_eth_dev *dev)
+{
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+
+ if (hw->phy.media_type == txgbe_media_type_copper) {
+ /* Turn off the copper */
+ hw->phy.set_phy_power(hw, false);
+ } else {
+ /* Turn off the laser */
+ hw->mac.disable_tx_laser(hw);
+ txgbe_dev_link_update(dev, 0);
+ }
+
+ return 0;
+}
+
/*
* Reset and stop device.
*/
return 0;
}
+void
+txgbe_dev_setup_link_alarm_handler(void *param)
+{
+ struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+ struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+ u32 speed;
+ bool autoneg = false;
+
+ speed = hw->phy.autoneg_advertised;
+ if (!speed)
+ hw->mac.get_link_capabilities(hw, &speed, &autoneg);
+
+ hw->mac.setup_link(hw, speed, true);
+
+ intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG;
+}
+
+/* return 0 means link status changed, -1 means not changed */
+int
+txgbe_dev_link_update_share(struct rte_eth_dev *dev,
+ int wait_to_complete)
+{
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+ struct rte_eth_link link;
+ u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
+ struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+ bool link_up;
+ int err;
+ int wait = 1;
+
+ memset(&link, 0, sizeof(link));
+ link.link_status = ETH_LINK_DOWN;
+ link.link_speed = ETH_SPEED_NUM_NONE;
+ link.link_duplex = ETH_LINK_HALF_DUPLEX;
+ link.link_autoneg = ETH_LINK_AUTONEG;
+
+ hw->mac.get_link_status = true;
+
+ if (intr->flags & TXGBE_FLAG_NEED_LINK_CONFIG)
+ return rte_eth_linkstatus_set(dev, &link);
+
+ /* check if it needs to wait to complete, if lsc interrupt is enabled */
+ if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0)
+ wait = 0;
+
+ err = hw->mac.check_link(hw, &link_speed, &link_up, wait);
+
+ if (err != 0) {
+ link.link_speed = ETH_SPEED_NUM_100M;
+ link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ return rte_eth_linkstatus_set(dev, &link);
+ }
+
+ if (link_up == 0) {
+ if (hw->phy.media_type == txgbe_media_type_fiber) {
+ intr->flags |= TXGBE_FLAG_NEED_LINK_CONFIG;
+ rte_eal_alarm_set(10,
+ txgbe_dev_setup_link_alarm_handler, dev);
+ }
+ return rte_eth_linkstatus_set(dev, &link);
+ }
+
+ intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG;
+ link.link_status = ETH_LINK_UP;
+ link.link_duplex = ETH_LINK_FULL_DUPLEX;
+
+ switch (link_speed) {
+ default:
+ case TXGBE_LINK_SPEED_UNKNOWN:
+ link.link_duplex = ETH_LINK_FULL_DUPLEX;
+ link.link_speed = ETH_SPEED_NUM_100M;
+ break;
+
+ case TXGBE_LINK_SPEED_100M_FULL:
+ link.link_speed = ETH_SPEED_NUM_100M;
+ break;
+
+ case TXGBE_LINK_SPEED_1GB_FULL:
+ link.link_speed = ETH_SPEED_NUM_1G;
+ break;
+
+ case TXGBE_LINK_SPEED_2_5GB_FULL:
+ link.link_speed = ETH_SPEED_NUM_2_5G;
+ break;
+
+ case TXGBE_LINK_SPEED_5GB_FULL:
+ link.link_speed = ETH_SPEED_NUM_5G;
+ break;
+
+ case TXGBE_LINK_SPEED_10GB_FULL:
+ link.link_speed = ETH_SPEED_NUM_10G;
+ break;
+ }
+
+ return rte_eth_linkstatus_set(dev, &link);
+}
+
static int
txgbe_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete)
{
- RTE_SET_USED(dev);
- RTE_SET_USED(wait_to_complete);
- return 0;
+ return txgbe_dev_link_update_share(dev, wait_to_complete);
}
/**
static const struct eth_dev_ops txgbe_eth_dev_ops = {
.dev_configure = txgbe_dev_configure,
.dev_infos_get = txgbe_dev_info_get,
+ .dev_set_link_up = txgbe_dev_set_link_up,
+ .dev_set_link_down = txgbe_dev_set_link_down,
};
RTE_PMD_REGISTER_PCI(net_txgbe, rte_txgbe_pmd);
};
#define TXGBE_DEV_ADAPTER(dev) \
- ((struct txgbe_adapter *)(dev)->data->dev_private)
+ ((struct txgbe_adapter *)(dev)->data->dev_private)
#define TXGBE_DEV_HW(dev) \
(&((struct txgbe_adapter *)(dev)->data->dev_private)->hw)
void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction,
uint8_t queue, uint8_t msix_vector);
+int
+txgbe_dev_link_update_share(struct rte_eth_dev *dev,
+ int wait_to_complete);
+
#define TXGBE_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */
#define TXGBE_LINK_UP_CHECK_TIMEOUT 1000 /* ms */
#define TXGBE_VMDQ_NUM_UC_MAC 4096 /* Maximum nb. of UC MAC addr. */
#define TXGBE_DEFAULT_TX_HTHRESH 0
#define TXGBE_DEFAULT_TX_WTHRESH 0
+void txgbe_dev_setup_link_alarm_handler(void *param);
+
#endif /* _TXGBE_ETHDEV_H_ */