Ensure link is still up after getting the speed, to ensure that the
speed read is valid.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu at intel.com>
---
 drivers/net/ixgbe/base/ixgbe_x550.c | 79 ++++++++++++++++++++++++++-----------
 1 file changed, 57 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ixgbe/base/ixgbe_x550.c 
b/drivers/net/ixgbe/base/ixgbe_x550.c
index 2a7046c..a7e95d9 100644
--- a/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -1860,6 +1860,38 @@ STATIC s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, 
ixgbe_link_speed *speed)
 }

 /**
+ * ixgbe_ext_phy_t_x550em_get_link - Get ext phy link status
+ * @hw: address of hardware structure
+ * @link_up: address of boolean to indicate link status
+ *
+ * Returns error code if unable to get link status.
+ */
+STATIC s32 ixgbe_ext_phy_t_x550em_get_link(struct ixgbe_hw *hw, bool *link_up)
+{
+       u32 ret;
+       u16 autoneg_status;
+
+       *link_up = false;
+
+       /* read this twice back to back to indicate current status */
+       ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+                                  IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                  &autoneg_status);
+       if (ret != IXGBE_SUCCESS)
+               return ret;
+
+       ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
+                                  IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+                                  &autoneg_status);
+       if (ret != IXGBE_SUCCESS)
+               return ret;
+
+       *link_up = !!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS);
+
+       return IXGBE_SUCCESS;
+}
+
+/**
  *  ixgbe_setup_mac_link_sfp_x550em - Setup internal/external the PHY for SFP
  *  @hw: pointer to hardware structure
  *
@@ -1936,33 +1968,34 @@ s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
  */
 s32 ixgbe_setup_internal_phy_t_x550em(struct ixgbe_hw *hw)
 {
-       u32 status;
-       u16 autoneg_status, speed;
        ixgbe_link_speed force_speed;
+       bool link_up;
+       u32 status;
+       u16 speed;

        if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
                return IXGBE_ERR_CONFIG;

-       /* read this twice back to back to indicate current status */
-       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                     &autoneg_status);
-       if (status != IXGBE_SUCCESS)
-               return status;
-
-       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                     &autoneg_status);
+       /* If link is not up, then there is no setup necessary so return  */
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
        if (status != IXGBE_SUCCESS)
                return status;

-       /* If link is not up, then there is no setup necessary so return  */
-       if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
+       if (!link_up)
                return IXGBE_SUCCESS;

        status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
                                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
                                      &speed);
+       if (status != IXGBE_SUCCESS)
+               return status;
+
+       /* If link is not still up, then no setup is necessary so return */
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
+       if (status != IXGBE_SUCCESS)
+               return status;
+       if (!link_up)
+               return IXGBE_SUCCESS;

        /* clear everything but the speed and duplex bits */
        speed &= IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_MASK;
@@ -2687,19 +2720,17 @@ void ixgbe_disable_rx_x550(struct ixgbe_hw *hw)
  **/
 s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
 {
-       u16 autoneg_status, an_10g_cntl_reg, autoneg_reg, speed;
+       u16 an_10g_cntl_reg, autoneg_reg, speed;
        s32 status;
        ixgbe_link_speed lcd_speed;
        u32 save_autoneg;
+       bool link_up;

        /* If blocked by MNG FW, then don't restart AN */
        if (ixgbe_check_reset_blocked(hw))
                return IXGBE_SUCCESS;

-       status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-                                     IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                     &autoneg_status);
-
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
        if (status != IXGBE_SUCCESS)
                return status;

@@ -2711,8 +2742,7 @@ s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
        /* If link is down, LPLU disabled in NVM, WoL disabled, or manageability
         * disabled, then force link down by entering low power mode.
         */
-       if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS) ||
-           !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
+       if (!link_up || !(hw->eeprom.ctrl_word_3 & NVM_INIT_CTRL_3_LPLU) ||
            !(hw->wol_enabled || ixgbe_mng_present(hw)))
                return ixgbe_set_copper_phy_power(hw, FALSE);

@@ -2733,6 +2763,11 @@ s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
        if (status != IXGBE_SUCCESS)
                return status;

+       /* If no link now, speed is invalid so take link down */
+       status = ixgbe_ext_phy_t_x550em_get_link(hw, &link_up);
+       if (status != IXGBE_SUCCESS)
+               return ixgbe_set_copper_phy_power(hw, false);
+
        /* clear everything but the speed bits */
        speed &= IXGBE_MDIO_AUTO_NEG_VEN_STAT_SPEED_MASK;

@@ -2746,7 +2781,7 @@ s32 ixgbe_enter_lplu_t_x550em(struct ixgbe_hw *hw)
        /* Clear AN completed indication */
        status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
                                      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-                                     &autoneg_status);
+                                     &autoneg_reg);

        if (status != IXGBE_SUCCESS)
                return status;
-- 
1.9.3

Reply via email to