Commit 56503d55 authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller

amd-xgbe: Fix SFP PHY supported/advertised settings

When using SFPs, the supported and advertised settings should be initially
based on the SFP that has been detected.  The code currently indicates the
overall support of the device as opposed to what the SFP is capable of.
Update the code to change the supported link modes, auto-negotiation, etc.
to be based on the installed SFP.
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 549b32af
...@@ -711,23 +711,39 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) ...@@ -711,23 +711,39 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
{ {
struct xgbe_phy_data *phy_data = pdata->phy_data; struct xgbe_phy_data *phy_data = pdata->phy_data;
if (!phy_data->sfp_mod_absent && !phy_data->sfp_changed)
return;
pdata->phy.supported &= ~SUPPORTED_Autoneg;
pdata->phy.supported &= ~(SUPPORTED_Pause | SUPPORTED_Asym_Pause);
pdata->phy.supported &= ~SUPPORTED_TP;
pdata->phy.supported &= ~SUPPORTED_FIBRE;
pdata->phy.supported &= ~SUPPORTED_100baseT_Full;
pdata->phy.supported &= ~SUPPORTED_1000baseT_Full;
pdata->phy.supported &= ~SUPPORTED_10000baseT_Full;
if (phy_data->sfp_mod_absent) { if (phy_data->sfp_mod_absent) {
pdata->phy.speed = SPEED_UNKNOWN; pdata->phy.speed = SPEED_UNKNOWN;
pdata->phy.duplex = DUPLEX_UNKNOWN; pdata->phy.duplex = DUPLEX_UNKNOWN;
pdata->phy.autoneg = AUTONEG_ENABLE; pdata->phy.autoneg = AUTONEG_ENABLE;
pdata->phy.pause_autoneg = AUTONEG_ENABLE;
pdata->phy.supported |= SUPPORTED_Autoneg;
pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
pdata->phy.supported |= SUPPORTED_TP;
pdata->phy.supported |= SUPPORTED_FIBRE;
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
pdata->phy.supported |= SUPPORTED_100baseT_Full;
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
pdata->phy.supported |= SUPPORTED_1000baseT_Full;
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
pdata->phy.supported |= SUPPORTED_10000baseT_Full;
pdata->phy.advertising = pdata->phy.supported; pdata->phy.advertising = pdata->phy.supported;
return; return;
} }
pdata->phy.advertising &= ~ADVERTISED_Autoneg;
pdata->phy.advertising &= ~ADVERTISED_TP;
pdata->phy.advertising &= ~ADVERTISED_FIBRE;
pdata->phy.advertising &= ~ADVERTISED_100baseT_Full;
pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full;
pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full;
pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC;
switch (phy_data->sfp_base) { switch (phy_data->sfp_base) {
case XGBE_SFP_BASE_1000_T: case XGBE_SFP_BASE_1000_T:
case XGBE_SFP_BASE_1000_SX: case XGBE_SFP_BASE_1000_SX:
...@@ -736,17 +752,25 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) ...@@ -736,17 +752,25 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
pdata->phy.speed = SPEED_UNKNOWN; pdata->phy.speed = SPEED_UNKNOWN;
pdata->phy.duplex = DUPLEX_UNKNOWN; pdata->phy.duplex = DUPLEX_UNKNOWN;
pdata->phy.autoneg = AUTONEG_ENABLE; pdata->phy.autoneg = AUTONEG_ENABLE;
pdata->phy.advertising |= ADVERTISED_Autoneg; pdata->phy.pause_autoneg = AUTONEG_ENABLE;
pdata->phy.supported |= SUPPORTED_Autoneg;
pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
break; break;
case XGBE_SFP_BASE_10000_SR: case XGBE_SFP_BASE_10000_SR:
case XGBE_SFP_BASE_10000_LR: case XGBE_SFP_BASE_10000_LR:
case XGBE_SFP_BASE_10000_LRM: case XGBE_SFP_BASE_10000_LRM:
case XGBE_SFP_BASE_10000_ER: case XGBE_SFP_BASE_10000_ER:
case XGBE_SFP_BASE_10000_CR: case XGBE_SFP_BASE_10000_CR:
default:
pdata->phy.speed = SPEED_10000; pdata->phy.speed = SPEED_10000;
pdata->phy.duplex = DUPLEX_FULL; pdata->phy.duplex = DUPLEX_FULL;
pdata->phy.autoneg = AUTONEG_DISABLE; pdata->phy.autoneg = AUTONEG_DISABLE;
pdata->phy.pause_autoneg = AUTONEG_DISABLE;
break;
default:
pdata->phy.speed = SPEED_UNKNOWN;
pdata->phy.duplex = DUPLEX_UNKNOWN;
pdata->phy.autoneg = AUTONEG_DISABLE;
pdata->phy.pause_autoneg = AUTONEG_DISABLE;
break; break;
} }
...@@ -754,36 +778,38 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) ...@@ -754,36 +778,38 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
case XGBE_SFP_BASE_1000_T: case XGBE_SFP_BASE_1000_T:
case XGBE_SFP_BASE_1000_CX: case XGBE_SFP_BASE_1000_CX:
case XGBE_SFP_BASE_10000_CR: case XGBE_SFP_BASE_10000_CR:
pdata->phy.advertising |= ADVERTISED_TP; pdata->phy.supported |= SUPPORTED_TP;
break; break;
default: default:
pdata->phy.advertising |= ADVERTISED_FIBRE; pdata->phy.supported |= SUPPORTED_FIBRE;
} }
switch (phy_data->sfp_speed) { switch (phy_data->sfp_speed) {
case XGBE_SFP_SPEED_100_1000: case XGBE_SFP_SPEED_100_1000:
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
pdata->phy.advertising |= ADVERTISED_100baseT_Full; pdata->phy.supported |= SUPPORTED_100baseT_Full;
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
pdata->phy.advertising |= ADVERTISED_1000baseT_Full; pdata->phy.supported |= SUPPORTED_1000baseT_Full;
break; break;
case XGBE_SFP_SPEED_1000: case XGBE_SFP_SPEED_1000:
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
pdata->phy.advertising |= ADVERTISED_1000baseT_Full; pdata->phy.supported |= SUPPORTED_1000baseT_Full;
break; break;
case XGBE_SFP_SPEED_10000: case XGBE_SFP_SPEED_10000:
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
pdata->phy.advertising |= ADVERTISED_10000baseT_Full; pdata->phy.supported |= SUPPORTED_10000baseT_Full;
break; break;
default: default:
/* Choose the fastest supported speed */ /* Choose the fastest supported speed */
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
pdata->phy.advertising |= ADVERTISED_10000baseT_Full; pdata->phy.supported |= SUPPORTED_10000baseT_Full;
else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
pdata->phy.advertising |= ADVERTISED_1000baseT_Full; pdata->phy.supported |= SUPPORTED_1000baseT_Full;
else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
pdata->phy.advertising |= ADVERTISED_100baseT_Full; pdata->phy.supported |= SUPPORTED_100baseT_Full;
} }
pdata->phy.advertising = pdata->phy.supported;
} }
static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom,
...@@ -2113,6 +2139,8 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata, ...@@ -2113,6 +2139,8 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
return xgbe_phy_check_mode(pdata, mode, return xgbe_phy_check_mode(pdata, mode,
ADVERTISED_1000baseT_Full); ADVERTISED_1000baseT_Full);
case XGBE_MODE_SFI: case XGBE_MODE_SFI:
if (phy_data->sfp_mod_absent)
return true;
return xgbe_phy_check_mode(pdata, mode, return xgbe_phy_check_mode(pdata, mode,
ADVERTISED_10000baseT_Full); ADVERTISED_10000baseT_Full);
default: default:
...@@ -2916,9 +2944,6 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata) ...@@ -2916,9 +2944,6 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) { if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
pdata->phy.supported |= SUPPORTED_10000baseT_Full; pdata->phy.supported |= SUPPORTED_10000baseT_Full;
phy_data->start_mode = XGBE_MODE_SFI; phy_data->start_mode = XGBE_MODE_SFI;
if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
pdata->phy.supported |=
SUPPORTED_10000baseR_FEC;
} }
phy_data->phydev_mode = XGBE_MDIO_MODE_CL22; phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment