📄 ixgbe_82598.c
字号:
else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg)) hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_LINK_NO_AN; else if (autoneg) { /* BX mode - Autonegotiate 1G */ if (!(hw->mac.link_attach_type & IXGBE_AUTOC_1G_PMA_PMD)) hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_AN; else /* KX/KX4 mode */ hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN_1G_AN; } else { status = IXGBE_ERR_LINK_SETUP; } if (status == 0) { hw->phy.autoneg_wait_to_complete = autoneg_wait_to_complete; hw->mac.link_settings_loaded = true; /* * 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 */ hw->phy.ops.setup(hw); } 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; u32 speed = 0; bool link_up = false; /* Set up MAC */ hw->phy.ops.setup(hw); /* Restart autonegotiation on PHY */ status = hw->phy.ops.setup(hw); /* Synchronize MAC to PHY speed */ if (status == 0) status = hw->phy.ops.check(hw, &speed, &link_up); return status;}/** * ixgbe_check_copper_link_82598 - Syncs MAC & PHY link settings * @hw: pointer to hardware structure * @speed: pointer to link speed * @link_up: true if link is up, false otherwise * * Reads the mac link, phy link, and synchronizes the MAC to PHY. **/static s32 ixgbe_check_copper_link_82598(struct ixgbe_hw *hw, u32 *speed, bool *link_up){ s32 status; u32 phy_speed = 0; bool phy_link = false; /* This is the speed and link the MAC is set at */ hw->phy.ops.check(hw, speed, link_up); /* * 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. */ status = hw->phy.ops.check(hw, &phy_speed, &phy_link); if ((status == 0) && (phy_link)) { /* * Check current link status of the MACs link's register * matches that of the speed in the PHY register */ if (*speed != phy_speed) { /* * The copper PHY requires 82598 attach type to be XAUI * for 10G and BX for 1G */ hw->mac.link_attach_type = (IXGBE_AUTOC_10G_XAUI | IXGBE_AUTOC_1G_BX); /* Synchronize the MAC speed to the PHY speed */ status = hw->phy.ops.setup_speed(hw, phy_speed, false, false); if (status == 0) hw->phy.ops.check(hw, speed, link_up); else status = IXGBE_ERR_LINK_SETUP; } } else { *link_up = phy_link; } return status;}/** * ixgbe_setup_copper_link_speed_82598 - Set the PHY autoneg advertised field * @hw: pointer to hardware structure * @speed: new link speed * @autoneg: true if autonegotiation enabled * @autoneg_wait_to_complete: true if waiting is needed to complete * * 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, u32 speed, bool autoneg, bool autoneg_wait_to_complete){ s32 status; bool link_up = 0; /* Setup the PHY according to input speed */ status = hw->phy.ops.setup_speed(hw, speed, autoneg, autoneg_wait_to_complete); /* Synchronize MAC to PHY speed */ if (status == 0) status = hw->phy.ops.check(hw, &speed, &link_up); return status;}/** * ixgbe_reset_hw_82598 - Performs hardware reset * @hw: pointer to hardware structure * * Resets the hardware by reseting the transmit and receive units, masks and * clears all interrupts, performing a PHY reset, and performing a link (MAC) * reset. **/static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw){ s32 status = 0; u32 ctrl; u32 gheccr; u32 i; u32 autoc; u8 analog_val; /* Call adapter stop to disable tx/rx and clear interrupts */ ixgbe_stop_adapter(hw); /* * Power up the Atlas TX lanes if they are currently powered down. * Atlas TX lanes are powered down for MAC loopback tests, but * they are not automatically restored on reset. */ ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); if (analog_val & IXGBE_ATLAS_PDN_TX_REG_EN) { /* Enable TX Atlas so packets can be transmitted again */ ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_REG_EN; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_LPBK, analog_val); ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_10G_QL_ALL; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_10G, analog_val); ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_1G_QL_ALL; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_1G, analog_val); ixgbe_read_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, &analog_val); analog_val &= ~IXGBE_ATLAS_PDN_TX_AN_QL_ALL; ixgbe_write_analog_reg8(hw, IXGBE_ATLAS_PDN_AN, analog_val); } /* Reset PHY */ ixgbe_reset_phy(hw); /* * Prevent the PCI-E bus from from hanging by disabling PCI-E master * access and verify no pending requests before reset */ if (ixgbe_disable_pcie_master(hw) != 0) { status = IXGBE_ERR_MASTER_REQUESTS_PENDING; hw_dbg(hw, "PCI-E Master disable polling has failed.\n"); } /* * Issue global reset to the MAC. This needs to be a SW reset. * If link reset is used, it might reset the MAC when mng is using it */ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST)); IXGBE_WRITE_FLUSH(hw); /* Poll for reset bit to self-clear indicating reset is complete */ for (i = 0; i < 10; i++) { udelay(1); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); if (!(ctrl & IXGBE_CTRL_RST)) break; } if (ctrl & IXGBE_CTRL_RST) { status = IXGBE_ERR_RESET_FAILED; hw_dbg(hw, "Reset polling failed to complete.\n"); } msleep(50); gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); /* * AUTOC register which stores link settings gets cleared * and reloaded from EEPROM after reset. We need to restore * our stored value from init in case SW changed the attach * type or speed. If this is the first time and link settings * have not been stored, store default settings from AUTOC. */ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC); if (hw->mac.link_settings_loaded) { autoc &= ~(IXGBE_AUTOC_LMS_ATTACH_TYPE); autoc &= ~(IXGBE_AUTOC_LMS_MASK); autoc |= hw->mac.link_attach_type; autoc |= hw->mac.link_mode_select; IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); } else { hw->mac.link_attach_type = (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE); hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK); hw->mac.link_settings_loaded = true; } /* Store the permanent mac address */ ixgbe_get_mac_addr(hw, hw->mac.perm_addr); return status;}static struct ixgbe_mac_operations mac_ops_82598 = { .reset = &ixgbe_reset_hw_82598, .get_media_type = &ixgbe_get_media_type_82598,};static struct ixgbe_phy_operations phy_ops_82598EB = { .setup = &ixgbe_setup_copper_link_82598, .check = &ixgbe_check_copper_link_82598, .setup_speed = &ixgbe_setup_copper_link_speed_82598, .get_settings = &ixgbe_get_copper_link_settings_82598,};struct ixgbe_info ixgbe_82598EB_info = { .mac = ixgbe_mac_82598EB, .get_invariants = &ixgbe_get_invariants_82598, .mac_ops = &mac_ops_82598, .phy_ops = &phy_ops_82598EB,};static struct ixgbe_phy_operations phy_ops_82598AT = { .setup = &ixgbe_setup_tnx_phy_link, .check = &ixgbe_check_tnx_phy_link, .setup_speed = &ixgbe_setup_tnx_phy_link_speed, .get_settings = &ixgbe_get_copper_link_settings_82598,};struct ixgbe_info ixgbe_82598AT_info = { .mac = ixgbe_mac_82598EB, .get_invariants = &ixgbe_get_invariants_82598, .mac_ops = &mac_ops_82598, .phy_ops = &phy_ops_82598AT,};static struct ixgbe_phy_operations phy_ops_82598AF = { .setup = &ixgbe_setup_mac_link_82598, .check = &ixgbe_check_mac_link_82598, .setup_speed = &ixgbe_setup_mac_link_speed_82598, .get_settings = &ixgbe_get_link_settings_82598,};struct ixgbe_info ixgbe_82598AF_info = { .mac = ixgbe_mac_82598EB, .get_invariants = &ixgbe_get_invariants_82598, .mac_ops = &mac_ops_82598, .phy_ops = &phy_ops_82598AF,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -