|
@@ -44,9 +44,8 @@
|
|
static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
|
|
static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
|
|
static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
|
|
static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
|
|
static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
|
|
static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw);
|
|
-static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
|
|
|
|
- ixgbe_link_speed speed,
|
|
|
|
- bool autoneg_wait_to_complete);
|
|
|
|
|
|
+static void
|
|
|
|
+ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *, ixgbe_link_speed);
|
|
static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
|
|
static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
|
|
ixgbe_link_speed speed,
|
|
ixgbe_link_speed speed,
|
|
bool autoneg_wait_to_complete);
|
|
bool autoneg_wait_to_complete);
|
|
@@ -109,6 +108,9 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
|
|
if (hw->phy.multispeed_fiber) {
|
|
if (hw->phy.multispeed_fiber) {
|
|
/* Set up dual speed SFP+ support */
|
|
/* Set up dual speed SFP+ support */
|
|
mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
|
|
mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber;
|
|
|
|
+ mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599;
|
|
|
|
+ mac->ops.set_rate_select_speed =
|
|
|
|
+ ixgbe_set_hard_rate_select_speed;
|
|
} else {
|
|
} else {
|
|
if ((mac->ops.get_media_type(hw) ==
|
|
if ((mac->ops.get_media_type(hw) ==
|
|
ixgbe_media_type_backplane) &&
|
|
ixgbe_media_type_backplane) &&
|
|
@@ -646,176 +648,32 @@ static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed
|
|
|
|
- * @hw: pointer to hardware structure
|
|
|
|
- * @speed: new link speed
|
|
|
|
- * @autoneg_wait_to_complete: true when waiting for completion is needed
|
|
|
|
|
|
+ * ixgbe_set_hard_rate_select_speed - Set module link speed
|
|
|
|
+ * @hw: pointer to hardware structure
|
|
|
|
+ * @speed: link speed to set
|
|
*
|
|
*
|
|
- * Set the link speed in the AUTOC register and restarts link.
|
|
|
|
- **/
|
|
|
|
-static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
|
|
|
|
- ixgbe_link_speed speed,
|
|
|
|
- bool autoneg_wait_to_complete)
|
|
|
|
|
|
+ * Set module link speed via RS0/RS1 rate select pins.
|
|
|
|
+ */
|
|
|
|
+static void
|
|
|
|
+ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed)
|
|
{
|
|
{
|
|
- s32 status = 0;
|
|
|
|
- ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
|
|
|
|
- ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
|
|
|
|
- u32 speedcnt = 0;
|
|
|
|
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
|
|
- u32 i = 0;
|
|
|
|
- bool link_up = false;
|
|
|
|
- bool autoneg = false;
|
|
|
|
|
|
|
|
- /* Mask off requested but non-supported speeds */
|
|
|
|
- status = hw->mac.ops.get_link_capabilities(hw, &link_speed,
|
|
|
|
- &autoneg);
|
|
|
|
- if (status != 0)
|
|
|
|
- return status;
|
|
|
|
-
|
|
|
|
- speed &= link_speed;
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Try each speed one by one, highest priority first. We do this in
|
|
|
|
- * software because 10gb fiber doesn't support speed autonegotiation.
|
|
|
|
- */
|
|
|
|
- if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
|
|
|
|
- speedcnt++;
|
|
|
|
- highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
|
|
|
|
-
|
|
|
|
- /* If we already have link at this speed, just jump out */
|
|
|
|
- status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
|
|
|
|
- false);
|
|
|
|
- if (status != 0)
|
|
|
|
- return status;
|
|
|
|
-
|
|
|
|
- if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
- /* Set the module link speed */
|
|
|
|
- switch (hw->phy.media_type) {
|
|
|
|
- case ixgbe_media_type_fiber:
|
|
|
|
- esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
|
|
|
|
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
|
|
|
|
- IXGBE_WRITE_FLUSH(hw);
|
|
|
|
- break;
|
|
|
|
- case ixgbe_media_type_fiber_qsfp:
|
|
|
|
- /* QSFP module automatically detects MAC link speed */
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- hw_dbg(hw, "Unexpected media type.\n");
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Allow module to change analog characteristics (1G->10G) */
|
|
|
|
- msleep(40);
|
|
|
|
-
|
|
|
|
- status = ixgbe_setup_mac_link_82599(hw,
|
|
|
|
- IXGBE_LINK_SPEED_10GB_FULL,
|
|
|
|
- autoneg_wait_to_complete);
|
|
|
|
- if (status != 0)
|
|
|
|
- return status;
|
|
|
|
-
|
|
|
|
- /* Flap the tx laser if it has not already been done */
|
|
|
|
- if (hw->mac.ops.flap_tx_laser)
|
|
|
|
- hw->mac.ops.flap_tx_laser(hw);
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * 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);
|
|
|
|
-
|
|
|
|
- /* If we have link, just jump out */
|
|
|
|
- status = hw->mac.ops.check_link(hw, &link_speed,
|
|
|
|
- &link_up, false);
|
|
|
|
- if (status != 0)
|
|
|
|
- return status;
|
|
|
|
-
|
|
|
|
- if (link_up)
|
|
|
|
- goto out;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
|
|
|
|
- speedcnt++;
|
|
|
|
- if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
|
|
|
|
- highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
|
|
|
|
-
|
|
|
|
- /* If we already have link at this speed, just jump out */
|
|
|
|
- status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
|
|
|
|
- false);
|
|
|
|
- if (status != 0)
|
|
|
|
- return status;
|
|
|
|
-
|
|
|
|
- if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
|
|
|
|
- goto out;
|
|
|
|
-
|
|
|
|
- /* Set the module link speed */
|
|
|
|
- switch (hw->phy.media_type) {
|
|
|
|
- case ixgbe_media_type_fiber:
|
|
|
|
- esdp_reg &= ~IXGBE_ESDP_SDP5;
|
|
|
|
- esdp_reg |= IXGBE_ESDP_SDP5_DIR;
|
|
|
|
- IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
|
|
|
|
- IXGBE_WRITE_FLUSH(hw);
|
|
|
|
- break;
|
|
|
|
- case ixgbe_media_type_fiber_qsfp:
|
|
|
|
- /* QSFP module automatically detects MAC link speed */
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- hw_dbg(hw, "Unexpected media type.\n");
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Allow module to change analog characteristics (10G->1G) */
|
|
|
|
- msleep(40);
|
|
|
|
-
|
|
|
|
- status = ixgbe_setup_mac_link_82599(hw,
|
|
|
|
- IXGBE_LINK_SPEED_1GB_FULL,
|
|
|
|
- autoneg_wait_to_complete);
|
|
|
|
- if (status != 0)
|
|
|
|
- return status;
|
|
|
|
-
|
|
|
|
- /* Flap the tx laser if it has not already been done */
|
|
|
|
- if (hw->mac.ops.flap_tx_laser)
|
|
|
|
- hw->mac.ops.flap_tx_laser(hw);
|
|
|
|
-
|
|
|
|
- /* Wait for the link partner to also set speed */
|
|
|
|
- msleep(100);
|
|
|
|
-
|
|
|
|
- /* If we have link, just jump out */
|
|
|
|
- status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
|
|
|
|
- false);
|
|
|
|
- if (status != 0)
|
|
|
|
- return status;
|
|
|
|
-
|
|
|
|
- if (link_up)
|
|
|
|
- goto out;
|
|
|
|
|
|
+ switch (speed) {
|
|
|
|
+ case IXGBE_LINK_SPEED_10GB_FULL:
|
|
|
|
+ esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
|
|
|
|
+ break;
|
|
|
|
+ case IXGBE_LINK_SPEED_1GB_FULL:
|
|
|
|
+ esdp_reg &= ~IXGBE_ESDP_SDP5;
|
|
|
|
+ esdp_reg |= IXGBE_ESDP_SDP5_DIR;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ hw_dbg(hw, "Invalid fixed module speed\n");
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * We didn't get link. Configure back to the highest speed we tried,
|
|
|
|
- * (if there was more than one). We call ourselves back with just the
|
|
|
|
- * single highest speed that the user requested.
|
|
|
|
- */
|
|
|
|
- if (speedcnt > 1)
|
|
|
|
- status = ixgbe_setup_mac_link_multispeed_fiber(hw,
|
|
|
|
- highest_link_speed,
|
|
|
|
- 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_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
|
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|