amd-xgbe: Fix SFP PHY supported/advertised settings
authorLendacky, Thomas <Thomas.Lendacky@amd.com>
Wed, 28 Jun 2017 18:41:40 +0000 (13:41 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 29 Jun 2017 19:14:15 +0000 (15:14 -0400)
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: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c

index 04298401c1337e5440dfc60bfa2eb1ff547ef418..756e1165a318c703325cd1f8c294dbebc588c78d 100644 (file)
@@ -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;
 
+       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) {
                pdata->phy.speed = SPEED_UNKNOWN;
                pdata->phy.duplex = DUPLEX_UNKNOWN;
                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;
 
                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) {
        case XGBE_SFP_BASE_1000_T:
        case XGBE_SFP_BASE_1000_SX:
@@ -736,17 +752,25 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
                pdata->phy.speed = SPEED_UNKNOWN;
                pdata->phy.duplex = DUPLEX_UNKNOWN;
                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;
        case XGBE_SFP_BASE_10000_SR:
        case XGBE_SFP_BASE_10000_LR:
        case XGBE_SFP_BASE_10000_LRM:
        case XGBE_SFP_BASE_10000_ER:
        case XGBE_SFP_BASE_10000_CR:
-       default:
                pdata->phy.speed = SPEED_10000;
                pdata->phy.duplex = DUPLEX_FULL;
                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;
        }
 
@@ -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_CX:
        case XGBE_SFP_BASE_10000_CR:
-               pdata->phy.advertising |= ADVERTISED_TP;
+               pdata->phy.supported |= SUPPORTED_TP;
                break;
        default:
-               pdata->phy.advertising |= ADVERTISED_FIBRE;
+               pdata->phy.supported |= SUPPORTED_FIBRE;
        }
 
        switch (phy_data->sfp_speed) {
        case XGBE_SFP_SPEED_100_1000:
                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)
-                       pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+                       pdata->phy.supported |= SUPPORTED_1000baseT_Full;
                break;
        case XGBE_SFP_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;
        case XGBE_SFP_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;
        default:
                /* Choose the fastest supported speed */
                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)
-                       pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+                       pdata->phy.supported |= SUPPORTED_1000baseT_Full;
                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,
@@ -2113,6 +2139,8 @@ static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
                return xgbe_phy_check_mode(pdata, mode,
                                           ADVERTISED_1000baseT_Full);
        case XGBE_MODE_SFI:
+               if (phy_data->sfp_mod_absent)
+                       return true;
                return xgbe_phy_check_mode(pdata, mode,
                                           ADVERTISED_10000baseT_Full);
        default:
@@ -2916,9 +2944,6 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
                if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
                        pdata->phy.supported |= SUPPORTED_10000baseT_Full;
                        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;