]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ixgbe/ixgbe_82599.c
ixgbe: Fix KR to KX fail over for Mezzanine cards
[karo-tx-linux.git] / drivers / net / ixgbe / ixgbe_82599.c
index ecb753b33d2656eb208e4c731586e43c6451a6a5..ae27c41222e300f0f1967032acba0e9e77029957 100644 (file)
@@ -42,6 +42,10 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                                           ixgbe_link_speed speed,
                                           bool autoneg,
                                           bool autoneg_wait_to_complete);
+static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
+                                           ixgbe_link_speed speed,
+                                           bool autoneg,
+                                           bool autoneg_wait_to_complete);
 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,
@@ -64,7 +68,13 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
                /* Set up dual speed SFP+ support */
                mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
        } else {
-               mac->ops.setup_link = &ixgbe_setup_mac_link_82599;
+               if ((mac->ops.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;
        }
 }
 
@@ -480,7 +490,12 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                        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 */
                        msleep(100);
@@ -567,6 +582,111 @@ out:
        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.
+ **/
+static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
+                                    ixgbe_link_speed speed, bool autoneg,
+                                    bool autoneg_wait_to_complete)
+{
+       s32 status = 0;
+       ixgbe_link_speed link_speed;
+       s32 i, j;
+       bool link_up = false;
+       u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+       hw_dbg(hw, "ixgbe_setup_mac_link_smartspeed.\n");
+
+        /* 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)
+                       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++) {
+                       mdelay(100);
+
+                       /* If we have link, just jump out */
+                       hw->mac.ops.check_link(hw, &link_speed,
+                                              &link_up, false);
+                       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)
+               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++) {
+               mdelay(100);
+
+               /* If we have link, just jump out */
+               hw->mac.ops.check_link(hw, &link_speed,
+                                      &link_up, false);
+               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
@@ -670,7 +790,8 @@ s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
                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;