i40e/i40evf: Refactor PHY structure and add phy_capabilities enum
[deliverable/linux.git] / drivers / net / ethernet / intel / i40e / i40e_ethtool.c
index 46019e9c489e5b375d89843f730e42ddc2d562bc..831f97125c8f6d5578d522161f4f135f1050f347 100644 (file)
@@ -273,36 +273,12 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
        case I40E_PHY_TYPE_40GBASE_AOC:
                ecmd->supported = SUPPORTED_40000baseCR4_Full;
                break;
-       case I40E_PHY_TYPE_40GBASE_KR4:
-               ecmd->supported = SUPPORTED_Autoneg |
-                                 SUPPORTED_40000baseKR4_Full;
-               ecmd->advertising = ADVERTISED_Autoneg |
-                                   ADVERTISED_40000baseKR4_Full;
-               break;
        case I40E_PHY_TYPE_40GBASE_SR4:
                ecmd->supported = SUPPORTED_40000baseSR4_Full;
                break;
        case I40E_PHY_TYPE_40GBASE_LR4:
                ecmd->supported = SUPPORTED_40000baseLR4_Full;
                break;
-       case I40E_PHY_TYPE_20GBASE_KR2:
-               ecmd->supported = SUPPORTED_Autoneg |
-                                 SUPPORTED_20000baseKR2_Full;
-               ecmd->advertising = ADVERTISED_Autoneg |
-                                   ADVERTISED_20000baseKR2_Full;
-               break;
-       case I40E_PHY_TYPE_10GBASE_KX4:
-               ecmd->supported = SUPPORTED_Autoneg |
-                                 SUPPORTED_10000baseKX4_Full;
-               ecmd->advertising = ADVERTISED_Autoneg |
-                                   ADVERTISED_10000baseKX4_Full;
-               break;
-       case I40E_PHY_TYPE_10GBASE_KR:
-               ecmd->supported = SUPPORTED_Autoneg |
-                                 SUPPORTED_10000baseKR_Full;
-               ecmd->advertising = ADVERTISED_Autoneg |
-                                   ADVERTISED_10000baseKR_Full;
-               break;
        case I40E_PHY_TYPE_10GBASE_SR:
        case I40E_PHY_TYPE_10GBASE_LR:
        case I40E_PHY_TYPE_1000BASE_SX:
@@ -320,12 +296,6 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
                if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
                        ecmd->advertising |= ADVERTISED_10000baseT_Full;
                break;
-       case I40E_PHY_TYPE_1000BASE_KX:
-               ecmd->supported = SUPPORTED_Autoneg |
-                                 SUPPORTED_1000baseKX_Full;
-               ecmd->advertising = ADVERTISED_Autoneg |
-                                   ADVERTISED_1000baseKX_Full;
-               break;
        case I40E_PHY_TYPE_10GBASE_T:
        case I40E_PHY_TYPE_1000BASE_T:
        case I40E_PHY_TYPE_100BASE_TX:
@@ -364,6 +334,15 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
                if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB)
                        ecmd->advertising |= ADVERTISED_100baseT_Full;
                break;
+       /* Backplane is set based on supported phy types in get_settings
+        * so don't set anything here but don't warn either
+        */
+       case I40E_PHY_TYPE_40GBASE_KR4:
+       case I40E_PHY_TYPE_20GBASE_KR2:
+       case I40E_PHY_TYPE_10GBASE_KR:
+       case I40E_PHY_TYPE_10GBASE_KX4:
+       case I40E_PHY_TYPE_1000BASE_KX:
+               break;
        default:
                /* if we got here and link is up something bad is afoot */
                netdev_info(netdev, "WARNING: Link is up but PHY type 0x%x is not recognized.\n",
@@ -403,64 +382,67 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
 static void i40e_get_settings_link_down(struct i40e_hw *hw,
                                        struct ethtool_cmd *ecmd)
 {
-       struct i40e_link_status *hw_link_info = &hw->phy.link_info;
+       enum i40e_aq_capabilities_phy_type phy_types = hw->phy.phy_types;
 
        /* link is down and the driver needs to fall back on
-        * device ID to determine what kinds of info to display,
-        * it's mostly a guess that may change when link is up
+        * supported phy types to figure out what info to display
         */
-       switch (hw->device_id) {
-       case I40E_DEV_ID_QSFP_A:
-       case I40E_DEV_ID_QSFP_B:
-       case I40E_DEV_ID_QSFP_C:
-               /* pluggable QSFP */
-               ecmd->supported = SUPPORTED_40000baseSR4_Full |
-                                 SUPPORTED_40000baseCR4_Full |
-                                 SUPPORTED_40000baseLR4_Full;
-               ecmd->advertising = ADVERTISED_40000baseSR4_Full |
-                                   ADVERTISED_40000baseCR4_Full |
-                                   ADVERTISED_40000baseLR4_Full;
-               break;
-       case I40E_DEV_ID_KX_B:
-               /* backplane 40G */
-               ecmd->supported = SUPPORTED_40000baseKR4_Full;
-               ecmd->advertising = ADVERTISED_40000baseKR4_Full;
-               break;
-       case I40E_DEV_ID_KX_C:
-               /* backplane 10G */
-               ecmd->supported = SUPPORTED_10000baseKR_Full;
-               ecmd->advertising = ADVERTISED_10000baseKR_Full;
-               break;
-       case I40E_DEV_ID_10G_BASE_T:
-       case I40E_DEV_ID_10G_BASE_T4:
-               ecmd->supported = SUPPORTED_10000baseT_Full |
-                                 SUPPORTED_1000baseT_Full |
-                                 SUPPORTED_100baseT_Full;
-               /* Figure out what has been requested */
-               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
-                       ecmd->advertising |= ADVERTISED_10000baseT_Full;
-               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
-                       ecmd->advertising |= ADVERTISED_1000baseT_Full;
-               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB)
-                       ecmd->advertising |= ADVERTISED_100baseT_Full;
-               break;
-       case I40E_DEV_ID_20G_KR2:
-       case I40E_DEV_ID_20G_KR2_A:
-               /* backplane 20G */
-               ecmd->supported = SUPPORTED_20000baseKR2_Full;
-               ecmd->advertising = ADVERTISED_20000baseKR2_Full;
-               break;
-       default:
-               /* all the rest are 10G/1G */
-               ecmd->supported = SUPPORTED_10000baseT_Full |
-                                 SUPPORTED_1000baseT_Full;
-               /* Figure out what has been requested */
-               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
-                       ecmd->advertising |= ADVERTISED_10000baseT_Full;
-               if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
-                       ecmd->advertising |= ADVERTISED_1000baseT_Full;
-               break;
+       ecmd->supported = 0x0;
+       ecmd->advertising = 0x0;
+       if (phy_types & I40E_CAP_PHY_TYPE_SGMII) {
+               ecmd->supported |= SUPPORTED_Autoneg |
+                                  SUPPORTED_1000baseT_Full |
+                                  SUPPORTED_100baseT_Full;
+               ecmd->advertising |= ADVERTISED_Autoneg |
+                                    ADVERTISED_1000baseT_Full |
+                                    ADVERTISED_100baseT_Full;
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_XAUI ||
+           phy_types & I40E_CAP_PHY_TYPE_XFI ||
+           phy_types & I40E_CAP_PHY_TYPE_SFI ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_AOC)
+               ecmd->supported |= SUPPORTED_10000baseT_Full;
+       if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_T ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR ||
+           phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) {
+               ecmd->supported |= SUPPORTED_Autoneg |
+                                  SUPPORTED_10000baseT_Full;
+               ecmd->advertising |= ADVERTISED_Autoneg |
+                                    ADVERTISED_10000baseT_Full;
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_XLAUI ||
+           phy_types & I40E_CAP_PHY_TYPE_XLPPI ||
+           phy_types & I40E_CAP_PHY_TYPE_40GBASE_AOC)
+               ecmd->supported |= SUPPORTED_40000baseCR4_Full;
+       if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4_CU ||
+           phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4) {
+               ecmd->supported |= SUPPORTED_Autoneg |
+                                 SUPPORTED_40000baseCR4_Full;
+               ecmd->advertising |= ADVERTISED_Autoneg |
+                                   ADVERTISED_40000baseCR4_Full;
        }
+       if (phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) {
+               ecmd->supported |= SUPPORTED_Autoneg |
+                                  SUPPORTED_100baseT_Full;
+               ecmd->advertising |= ADVERTISED_Autoneg |
+                                    ADVERTISED_100baseT_Full;
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_T ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX ||
+           phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) {
+               ecmd->supported |= SUPPORTED_Autoneg |
+                                  SUPPORTED_1000baseT_Full;
+               ecmd->advertising |= ADVERTISED_Autoneg |
+                                    ADVERTISED_1000baseT_Full;
+       }
+       if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_SR4)
+               ecmd->supported |= SUPPORTED_40000baseSR4_Full;
+       if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4)
+               ecmd->supported |= SUPPORTED_40000baseLR4_Full;
 
        /* With no link speed and duplex are unknown */
        ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
@@ -490,6 +472,37 @@ static int i40e_get_settings(struct net_device *netdev,
 
        /* Now set the settings that don't rely on link being up/down */
 
+       /* For backplane, supported and advertised are only reliant on the
+        * phy types the NVM specifies are supported.
+        */
+       if (hw->device_id == I40E_DEV_ID_KX_B ||
+           hw->device_id == I40E_DEV_ID_KX_C ||
+           hw->device_id == I40E_DEV_ID_20G_KR2 ||
+           hw->device_id ==  I40E_DEV_ID_20G_KR2_A) {
+               ecmd->supported = SUPPORTED_Autoneg;
+               ecmd->advertising = ADVERTISED_Autoneg;
+               if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) {
+                       ecmd->supported |= SUPPORTED_40000baseKR4_Full;
+                       ecmd->advertising |= ADVERTISED_40000baseKR4_Full;
+               }
+               if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2) {
+                       ecmd->supported |= SUPPORTED_20000baseKR2_Full;
+                       ecmd->advertising |= ADVERTISED_20000baseKR2_Full;
+               }
+               if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) {
+                       ecmd->supported |= SUPPORTED_10000baseKR_Full;
+                       ecmd->advertising |= ADVERTISED_10000baseKR_Full;
+               }
+               if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) {
+                       ecmd->supported |= SUPPORTED_10000baseKX4_Full;
+                       ecmd->advertising |= ADVERTISED_10000baseKX4_Full;
+               }
+               if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) {
+                       ecmd->supported |= SUPPORTED_1000baseKX_Full;
+                       ecmd->advertising |= ADVERTISED_1000baseKX_Full;
+               }
+       }
+
        /* Set autoneg settings */
        ecmd->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ?
                          AUTONEG_ENABLE : AUTONEG_DISABLE);
@@ -589,6 +602,14 @@ static int i40e_set_settings(struct net_device *netdev,
            hw->phy.link_info.link_info & I40E_AQ_LINK_UP)
                return -EOPNOTSUPP;
 
+       if (hw->device_id == I40E_DEV_ID_KX_B ||
+           hw->device_id == I40E_DEV_ID_KX_C ||
+           hw->device_id == I40E_DEV_ID_20G_KR2 ||
+           hw->device_id == I40E_DEV_ID_20G_KR2_A) {
+               netdev_info(netdev, "Changing settings is not supported on backplane.\n");
+               return -EOPNOTSUPP;
+       }
+
        /* get our own copy of the bits to check against */
        memset(&safe_ecmd, 0, sizeof(struct ethtool_cmd));
        i40e_get_settings(netdev, &safe_ecmd);
This page took 0.02714 seconds and 5 git commands to generate.