2017-12-19 15:49:01 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
* Copyright(c) 2010-2015 Intel Corporation
|
2013-11-08 02:00:00 +00:00
|
|
|
*/
|
|
|
|
|
2015-05-15 15:56:53 +00:00
|
|
|
#include "base/ixgbe_type.h"
|
|
|
|
#include "base/ixgbe_82599.h"
|
|
|
|
#include "base/ixgbe_api.h"
|
|
|
|
#include "base/ixgbe_common.h"
|
|
|
|
#include "base/ixgbe_phy.h"
|
2013-11-08 02:00:00 +00:00
|
|
|
#include "ixgbe_bypass_defines.h"
|
|
|
|
#include "ixgbe_bypass.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ixgbe_set_fiber_fixed_speed - Set module link speed for fixed fiber
|
|
|
|
* @hw: pointer to hardware structure
|
|
|
|
* @speed: link speed to set
|
|
|
|
*
|
|
|
|
* We set the module speed differently for fixed fiber. For other
|
|
|
|
* multi-speed devices we don't have an error value so here if we
|
|
|
|
* detect an error we just log it and exit.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed)
|
|
|
|
{
|
|
|
|
s32 status;
|
|
|
|
u8 rs, eeprom_data;
|
|
|
|
|
|
|
|
switch (speed) {
|
|
|
|
case IXGBE_LINK_SPEED_10GB_FULL:
|
|
|
|
/* one bit mask same as setting on */
|
|
|
|
rs = IXGBE_SFF_SOFT_RS_SELECT_10G;
|
|
|
|
break;
|
|
|
|
case IXGBE_LINK_SPEED_1GB_FULL:
|
|
|
|
rs = IXGBE_SFF_SOFT_RS_SELECT_1G;
|
|
|
|
break;
|
|
|
|
default:
|
2014-10-01 22:27:25 +00:00
|
|
|
PMD_DRV_LOG(ERR, "Invalid fixed module speed");
|
2013-11-08 02:00:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set RS0 */
|
|
|
|
status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
|
|
|
|
IXGBE_I2C_EEPROM_DEV_ADDR2,
|
|
|
|
&eeprom_data);
|
|
|
|
if (status) {
|
2014-10-01 22:27:25 +00:00
|
|
|
PMD_DRV_LOG(ERR, "Failed to read Rx Rate Select RS0");
|
2013-11-08 02:00:00 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
|
|
|
|
|
|
|
|
status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB,
|
|
|
|
IXGBE_I2C_EEPROM_DEV_ADDR2,
|
|
|
|
eeprom_data);
|
|
|
|
if (status) {
|
2014-10-01 22:27:25 +00:00
|
|
|
PMD_DRV_LOG(ERR, "Failed to write Rx Rate Select RS0");
|
2013-11-08 02:00:00 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set RS1 */
|
|
|
|
status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
|
|
|
|
IXGBE_I2C_EEPROM_DEV_ADDR2,
|
|
|
|
&eeprom_data);
|
|
|
|
if (status) {
|
2014-10-01 22:27:25 +00:00
|
|
|
PMD_DRV_LOG(ERR, "Failed to read Rx Rate Select RS1");
|
2013-11-08 02:00:00 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs;
|
|
|
|
|
|
|
|
status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB,
|
|
|
|
IXGBE_I2C_EEPROM_DEV_ADDR2,
|
|
|
|
eeprom_data);
|
|
|
|
if (status) {
|
2014-10-01 22:27:25 +00:00
|
|
|
PMD_DRV_LOG(ERR, "Failed to write Rx Rate Select RS1");
|
2013-11-08 02:00:00 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ixgbe_setup_mac_link_multispeed_fixed_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
|
|
|
|
*
|
|
|
|
* Set the link speed in the AUTOC register and restarts link.
|
|
|
|
**/
|
|
|
|
static s32
|
|
|
|
ixgbe_setup_mac_link_multispeed_fixed_fiber(struct ixgbe_hw *hw,
|
2014-06-18 13:46:07 +00:00
|
|
|
ixgbe_link_speed speed,
|
2013-11-08 02:00:00 +00:00
|
|
|
bool autoneg_wait_to_complete)
|
|
|
|
{
|
|
|
|
s32 status = IXGBE_SUCCESS;
|
|
|
|
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 negotiation;
|
|
|
|
|
2014-09-17 13:46:33 +00:00
|
|
|
PMD_INIT_FUNC_TRACE();
|
2013-11-08 02:00:00 +00:00
|
|
|
|
|
|
|
/* Mask off requested but non-supported speeds */
|
|
|
|
status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation);
|
|
|
|
if (status != IXGBE_SUCCESS)
|
|
|
|
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 = ixgbe_check_link(hw, &link_speed, &link_up, false);
|
|
|
|
if (status != IXGBE_SUCCESS)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
|
|
|
|
goto out;
|
|
|
|
/* Set the module link speed */
|
|
|
|
ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_10GB_FULL);
|
2014-06-03 23:42:50 +00:00
|
|
|
|
2013-11-08 02:00:00 +00:00
|
|
|
/* Set the module link speed */
|
|
|
|
esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
|
|
|
|
IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
|
|
|
|
IXGBE_WRITE_FLUSH(hw);
|
|
|
|
|
|
|
|
/* Allow module to change analog characteristics (1G->10G) */
|
|
|
|
msec_delay(40);
|
|
|
|
|
|
|
|
status = ixgbe_setup_mac_link_82599(hw,
|
|
|
|
IXGBE_LINK_SPEED_10GB_FULL,
|
|
|
|
autoneg_wait_to_complete);
|
|
|
|
if (status != IXGBE_SUCCESS)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
/* Flap the tx laser if it has not already been done */
|
|
|
|
ixgbe_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 */
|
|
|
|
msec_delay(100);
|
|
|
|
|
|
|
|
/* If we have link, just jump out */
|
|
|
|
status = ixgbe_check_link(hw, &link_speed,
|
|
|
|
&link_up, false);
|
|
|
|
if (status != IXGBE_SUCCESS)
|
|
|
|
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 = ixgbe_check_link(hw, &link_speed, &link_up, false);
|
|
|
|
if (status != IXGBE_SUCCESS)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Set the module link speed */
|
|
|
|
ixgbe_set_fiber_fixed_speed(hw, IXGBE_LINK_SPEED_1GB_FULL);
|
2014-06-03 23:42:50 +00:00
|
|
|
|
2013-11-08 02:00:00 +00:00
|
|
|
/* Allow module to change analog characteristics (10G->1G) */
|
|
|
|
msec_delay(40);
|
|
|
|
|
|
|
|
status = ixgbe_setup_mac_link_82599(hw,
|
|
|
|
IXGBE_LINK_SPEED_1GB_FULL,
|
|
|
|
autoneg_wait_to_complete);
|
|
|
|
if (status != IXGBE_SUCCESS)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
/* Flap the tx laser if it has not already been done */
|
|
|
|
ixgbe_flap_tx_laser(hw);
|
|
|
|
|
|
|
|
/* Wait for the link partner to also set speed */
|
|
|
|
msec_delay(100);
|
|
|
|
|
|
|
|
/* If we have link, just jump out */
|
|
|
|
status = ixgbe_check_link(hw, &link_speed, &link_up, false);
|
|
|
|
if (status != IXGBE_SUCCESS)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
if (link_up)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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_fixed_fiber(hw,
|
2014-06-18 13:46:07 +00:00
|
|
|
highest_link_speed, autoneg_wait_to_complete);
|
2013-11-08 02:00:00 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum ixgbe_media_type
|
|
|
|
ixgbe_bypass_get_media_type(struct ixgbe_hw *hw)
|
|
|
|
{
|
|
|
|
enum ixgbe_media_type media_type;
|
|
|
|
|
2014-09-17 13:46:33 +00:00
|
|
|
PMD_INIT_FUNC_TRACE();
|
2013-11-08 02:00:00 +00:00
|
|
|
|
|
|
|
if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
|
|
|
|
media_type = ixgbe_media_type_fiber;
|
|
|
|
} else {
|
|
|
|
media_type = ixgbe_get_media_type_82599(hw);
|
|
|
|
}
|
2016-01-27 13:58:30 +00:00
|
|
|
return media_type;
|
2013-11-08 02:00:00 +00:00
|
|
|
}
|
|
|
|
|
2014-06-24 14:41:29 +00:00
|
|
|
/*
|
|
|
|
* Wrapper around shared code (base driver) to support BYPASS nic.
|
|
|
|
*/
|
|
|
|
s32
|
|
|
|
ixgbe_bypass_init_shared_code(struct ixgbe_hw *hw)
|
|
|
|
{
|
|
|
|
s32 ret_val;
|
|
|
|
|
|
|
|
if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
|
|
|
|
hw->mac.type = ixgbe_mac_82599EB;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret_val = ixgbe_init_shared_code(hw);
|
|
|
|
if (hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
|
|
|
|
hw->mac.ops.get_media_type = &ixgbe_bypass_get_media_type;
|
|
|
|
ixgbe_init_mac_link_ops_82599(hw);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
2013-11-08 02:00:00 +00:00
|
|
|
s32
|
|
|
|
ixgbe_bypass_init_hw(struct ixgbe_hw *hw)
|
|
|
|
{
|
|
|
|
int rc;
|
2014-06-03 23:42:50 +00:00
|
|
|
|
2016-04-07 23:45:28 +00:00
|
|
|
rc = ixgbe_init_hw(hw);
|
|
|
|
if (rc == 0 && hw->device_id == IXGBE_DEV_ID_82599_BYPASS) {
|
2013-11-08 02:00:00 +00:00
|
|
|
|
|
|
|
hw->mac.ops.setup_link =
|
|
|
|
&ixgbe_setup_mac_link_multispeed_fixed_fiber;
|
|
|
|
|
|
|
|
hw->mac.ops.get_media_type = &ixgbe_bypass_get_media_type;
|
|
|
|
|
|
|
|
hw->mac.ops.disable_tx_laser = NULL;
|
2016-04-07 23:45:28 +00:00
|
|
|
hw->mac.ops.enable_tx_laser = NULL;
|
|
|
|
hw->mac.ops.flap_tx_laser = NULL;
|
2013-11-08 02:00:00 +00:00
|
|
|
}
|
|
|
|
|
2016-01-27 13:58:30 +00:00
|
|
|
return rc;
|
2013-11-08 02:00:00 +00:00
|
|
|
}
|