Skip to content

Commit

Permalink
ixgbe: Add X550EM_x dual-speed SFP+ support
Browse files Browse the repository at this point in the history
This patch adds X550EM_x SFP+ dual-speed support. 82599 fiber link
code was moved from ixgbe_82599.c to ixgbe_common.c for use by
X550EM. SFP MAC link code is added to x550EM.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Mark Rustad authored and Jeff Kirsher committed Sep 24, 2015
1 parent 56f6ed1 commit 6d373a1
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 167 deletions.
192 changes: 25 additions & 167 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@
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_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,
ixgbe_link_speed speed,
bool autoneg_wait_to_complete);
Expand Down Expand Up @@ -109,6 +108,9 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
if (hw->phy.multispeed_fiber) {
/* Set up dual speed SFP+ support */
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 {
if ((mac->ops.get_media_type(hw) ==
ixgbe_media_type_backplane) &&
Expand Down Expand Up @@ -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 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);
}

/**
Expand Down
Loading

0 comments on commit 6d373a1

Please sign in to comment.