Switch to new ethtool api in preparation for support of advertising
2.5GBaseT and 5GBaseT.

Fixes a bug introduced in 9a799d7, which sets 1000baseT supported
flags instead of 100baseT flag.

Signed-off-by: Ryan Schaefer <ryanschaefe...@gmail.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 237 ++++++++++++++---------
 include/linux/ethtool.h                          |  34 ++++
 2 files changed, 178 insertions(+), 93 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index fd192bf..89afc48 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -158,29 +158,41 @@ static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] 
= {
 
 #define ixgbe_isbackplane(type) ((type) == ixgbe_media_type_backplane)
 
-static u32 ixgbe_get_supported_10gtypes(struct ixgbe_hw *hw)
+static void ixgbe_set_supported_10gtypes(struct ixgbe_hw *hw,
+                                        struct ethtool_link_ksettings *cmd)
 {
-       if (!ixgbe_isbackplane(hw->phy.media_type))
-               return SUPPORTED_10000baseT_Full;
+       if (!ixgbe_isbackplane(hw->phy.media_type)) {
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    10000baseT_Full);
+               return;
+       }
 
        switch (hw->device_id) {
        case IXGBE_DEV_ID_82598:
        case IXGBE_DEV_ID_82599_KX4:
        case IXGBE_DEV_ID_82599_KX4_MEZZ:
        case IXGBE_DEV_ID_X550EM_X_KX4:
-               return SUPPORTED_10000baseKX4_Full;
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    10000baseKX4_Full);
+               break;
        case IXGBE_DEV_ID_82598_BX:
        case IXGBE_DEV_ID_82599_KR:
        case IXGBE_DEV_ID_X550EM_X_KR:
-               return SUPPORTED_10000baseKR_Full;
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    10000baseKR_Full);
+               break;
        default:
-               return SUPPORTED_10000baseKX4_Full |
-                      SUPPORTED_10000baseKR_Full;
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    10000baseKX4_Full);
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    10000baseKR_Full);
+               break;
        }
+       return;
 }
 
-static int ixgbe_get_settings(struct net_device *netdev,
-                             struct ethtool_cmd *ecmd)
+static int ixgbe_get_link_ksettings(struct net_device *netdev,
+                                   struct ethtool_link_ksettings *cmd)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_hw *hw = &adapter->hw;
@@ -191,46 +203,66 @@ static int ixgbe_get_settings(struct net_device *netdev,
 
        /* set the supported link speeds */
        if (supported_link & IXGBE_LINK_SPEED_10GB_FULL)
-               ecmd->supported |= ixgbe_get_supported_10gtypes(hw);
-       if (supported_link & IXGBE_LINK_SPEED_1GB_FULL)
-               ecmd->supported |= (ixgbe_isbackplane(hw->phy.media_type)) ?
-                                  SUPPORTED_1000baseKX_Full :
-                                  SUPPORTED_1000baseT_Full;
+               ixgbe_set_supported_10gtypes(hw, cmd);
+       if (supported_link & IXGBE_LINK_SPEED_1GB_FULL) {
+               if (ixgbe_isbackplane(hw->phy.media_type))
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            1000baseKX_Full);
+               else
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            1000baseT_Full);
+       }
        if (supported_link & IXGBE_LINK_SPEED_100_FULL)
-               ecmd->supported |= ixgbe_isbackplane(hw->phy.media_type) ?
-                                  SUPPORTED_1000baseKX_Full :
-                                  SUPPORTED_1000baseT_Full;
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    100baseT_Full);
 
        /* default advertised speed if phy.autoneg_advertised isn't set */
-       ecmd->advertising = ecmd->supported;
+       ethtool_link_ksettings_copy_link_mode(cmd, advertising, supported);
        /* set the advertised speeds */
        if (hw->phy.autoneg_advertised) {
-               ecmd->advertising = 0;
+               ethtool_link_ksettings_zero_link_mode(cmd, advertising);
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
-                       ecmd->advertising |= ADVERTISED_100baseT_Full;
-               if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
-                       ecmd->advertising |= ecmd->supported & ADVRTSD_MSK_10G;
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            100baseT_Full);
+               if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) {
+                       if (ethtool_link_ksettings_test_link_mode(cmd,
+                                               supported, 10000baseT_Full))
+                               ethtool_link_ksettings_add_link_mode(cmd,
+                                               advertising, 10000baseT_Full);
+
+                       if (ethtool_link_ksettings_test_link_mode(cmd,
+                                               supported, 10000baseKX4_Full))
+                               ethtool_link_ksettings_add_link_mode(cmd,
+                                               advertising, 10000baseKX4_Full);
+
+                       if (ethtool_link_ksettings_test_link_mode(cmd,
+                                               supported, 10000baseKR_Full))
+                               ethtool_link_ksettings_add_link_mode(cmd,
+                                               advertising, 10000baseKR_Full);
+               }
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) {
-                       if (ecmd->supported & SUPPORTED_1000baseKX_Full)
-                               ecmd->advertising |= ADVERTISED_1000baseKX_Full;
+                       if (ethtool_link_ksettings_test_link_mode(cmd,
+                                               supported, 1000baseKX_Full))
+                               ethtool_link_ksettings_add_link_mode(cmd,
+                                               advertising, 1000baseKX_Full);
                        else
-                               ecmd->advertising |= ADVERTISED_1000baseT_Full;
+                               ethtool_link_ksettings_add_link_mode(cmd,
+                                               advertising, 1000baseT_Full);
                }
        } else {
                if (hw->phy.multispeed_fiber && !autoneg) {
                        if (supported_link & IXGBE_LINK_SPEED_10GB_FULL)
-                               ecmd->advertising = ADVERTISED_10000baseT_Full;
+                               ethtool_link_ksettings_add_link_mode(cmd,
+                                               advertising, 1000baseT_Full);
                }
        }
 
        if (autoneg) {
-               ecmd->supported |= SUPPORTED_Autoneg;
-               ecmd->advertising |= ADVERTISED_Autoneg;
-               ecmd->autoneg = AUTONEG_ENABLE;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
+               cmd->base.autoneg = AUTONEG_ENABLE;
        } else
-               ecmd->autoneg = AUTONEG_DISABLE;
-
-       ecmd->transceiver = XCVR_EXTERNAL;
+               cmd->base.autoneg = AUTONEG_DISABLE;
 
        /* Determine the remaining settings based on the PHY type. */
        switch (adapter->hw.phy.type) {
@@ -238,14 +270,14 @@ static int ixgbe_get_settings(struct net_device *netdev,
        case ixgbe_phy_aq:
        case ixgbe_phy_x550em_ext_t:
        case ixgbe_phy_cu_unknown:
-               ecmd->supported |= SUPPORTED_TP;
-               ecmd->advertising |= ADVERTISED_TP;
-               ecmd->port = PORT_TP;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
+               cmd->base.port = PORT_TP;
                break;
        case ixgbe_phy_qt:
-               ecmd->supported |= SUPPORTED_FIBRE;
-               ecmd->advertising |= ADVERTISED_FIBRE;
-               ecmd->port = PORT_FIBRE;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
+               cmd->base.port = PORT_FIBRE;
                break;
        case ixgbe_phy_nl:
        case ixgbe_phy_sfp_passive_tyco:
@@ -263,9 +295,11 @@ static int ixgbe_get_settings(struct net_device *netdev,
                case ixgbe_sfp_type_da_cu:
                case ixgbe_sfp_type_da_cu_core0:
                case ixgbe_sfp_type_da_cu_core1:
-                       ecmd->supported |= SUPPORTED_FIBRE;
-                       ecmd->advertising |= ADVERTISED_FIBRE;
-                       ecmd->port = PORT_DA;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
+                       cmd->base.port = PORT_DA;
                        break;
                case ixgbe_sfp_type_sr:
                case ixgbe_sfp_type_lr:
@@ -275,91 +309,103 @@ static int ixgbe_get_settings(struct net_device *netdev,
                case ixgbe_sfp_type_1g_sx_core1:
                case ixgbe_sfp_type_1g_lx_core0:
                case ixgbe_sfp_type_1g_lx_core1:
-                       ecmd->supported |= SUPPORTED_FIBRE;
-                       ecmd->advertising |= ADVERTISED_FIBRE;
-                       ecmd->port = PORT_FIBRE;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
+                       cmd->base.port = PORT_FIBRE;
                        break;
                case ixgbe_sfp_type_not_present:
-                       ecmd->supported |= SUPPORTED_FIBRE;
-                       ecmd->advertising |= ADVERTISED_FIBRE;
-                       ecmd->port = PORT_NONE;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
+                       cmd->base.port = PORT_NONE;
                        break;
                case ixgbe_sfp_type_1g_cu_core0:
                case ixgbe_sfp_type_1g_cu_core1:
-                       ecmd->supported |= SUPPORTED_TP;
-                       ecmd->advertising |= ADVERTISED_TP;
-                       ecmd->port = PORT_TP;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            TP);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            TP);
+                       cmd->base.port = PORT_TP;
                        break;
                case ixgbe_sfp_type_unknown:
                default:
-                       ecmd->supported |= SUPPORTED_FIBRE;
-                       ecmd->advertising |= ADVERTISED_FIBRE;
-                       ecmd->port = PORT_OTHER;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
+                       cmd->base.port = PORT_OTHER;
                        break;
                }
                break;
        case ixgbe_phy_xaui:
-               ecmd->supported |= SUPPORTED_FIBRE;
-               ecmd->advertising |= ADVERTISED_FIBRE;
-               ecmd->port = PORT_NONE;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
+               cmd->base.port = PORT_NONE;
                break;
        case ixgbe_phy_unknown:
        case ixgbe_phy_generic:
        case ixgbe_phy_sfp_unsupported:
        default:
-               ecmd->supported |= SUPPORTED_FIBRE;
-               ecmd->advertising |= ADVERTISED_FIBRE;
-               ecmd->port = PORT_OTHER;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
+               cmd->base.port = PORT_OTHER;
                break;
        }
 
        /* Indicate pause support */
-       ecmd->supported |= SUPPORTED_Pause;
+       ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
 
        switch (hw->fc.requested_mode) {
        case ixgbe_fc_full:
-               ecmd->advertising |= ADVERTISED_Pause;
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
                break;
        case ixgbe_fc_rx_pause:
-               ecmd->advertising |= ADVERTISED_Pause |
-                                    ADVERTISED_Asym_Pause;
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    Asym_Pause);
                break;
        case ixgbe_fc_tx_pause:
-               ecmd->advertising |= ADVERTISED_Asym_Pause;
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    Asym_Pause);
                break;
        default:
-               ecmd->advertising &= ~(ADVERTISED_Pause |
-                                      ADVERTISED_Asym_Pause);
+               ethtool_link_ksettings_remove_link_mode(cmd, advertising,
+                                                       Pause);
+               ethtool_link_ksettings_remove_link_mode(cmd, advertising,
+                                                       Asym_Pause);
        }
 
        if (netif_carrier_ok(netdev)) {
                switch (adapter->link_speed) {
                case IXGBE_LINK_SPEED_10GB_FULL:
-                       ethtool_cmd_speed_set(ecmd, SPEED_10000);
+                       cmd->base.speed = SPEED_10000;
                        break;
                case IXGBE_LINK_SPEED_2_5GB_FULL:
-                       ethtool_cmd_speed_set(ecmd, SPEED_2500);
+                       cmd->base.speed = SPEED_2500;
                        break;
                case IXGBE_LINK_SPEED_1GB_FULL:
-                       ethtool_cmd_speed_set(ecmd, SPEED_1000);
+                       cmd->base.speed = SPEED_1000;
                        break;
                case IXGBE_LINK_SPEED_100_FULL:
-                       ethtool_cmd_speed_set(ecmd, SPEED_100);
+                       cmd->base.speed = SPEED_100;
                        break;
                default:
                        break;
                }
-               ecmd->duplex = DUPLEX_FULL;
+               cmd->base.duplex = DUPLEX_FULL;
        } else {
-               ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
-               ecmd->duplex = DUPLEX_UNKNOWN;
+               cmd->base.speed = SPEED_UNKNOWN;
+               cmd->base.duplex = DUPLEX_UNKNOWN;
        }
 
        return 0;
 }
 
-static int ixgbe_set_settings(struct net_device *netdev,
-                             struct ethtool_cmd *ecmd)
+static int ixgbe_set_link_ksettings(struct net_device *netdev,
+                                   const struct ethtool_link_ksettings *cmd)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_hw *hw = &adapter->hw;
@@ -372,30 +418,34 @@ static int ixgbe_set_settings(struct net_device *netdev,
                 * this function does not support duplex forcing, but can
                 * limit the advertising of the adapter to the specified speed
                 */
-               if (ecmd->advertising & ~ecmd->supported)
+               if (!ethtool_link_ksettings_subset_link_mode(cmd, advertising,
+                                                            supported))
                        return -EINVAL;
 
                /* only allow one speed at a time if no autoneg */
-               if (!ecmd->autoneg && hw->phy.multispeed_fiber) {
-                       if (ecmd->advertising ==
-                           (ADVERTISED_10000baseT_Full |
-                            ADVERTISED_1000baseT_Full))
+               if (!cmd->base.autoneg && hw->phy.multispeed_fiber)
+                       if (ethtool_link_ksettings_test_link_mode(cmd,
+                                               advertising, 10000baseT_Full) ||
+                           ethtool_link_ksettings_test_link_mode(cmd,
+                                               advertising, 1000baseT_Full))
                                return -EINVAL;
-               }
 
                old = hw->phy.autoneg_advertised;
                advertised = 0;
-               if (ecmd->advertising & ADVERTISED_10000baseT_Full)
+               if (ethtool_link_ksettings_test_link_mode(cmd,
+                                       advertising, 10000baseT_Full))
                        advertised |= IXGBE_LINK_SPEED_10GB_FULL;
-
-               if (ecmd->advertising & ADVERTISED_1000baseT_Full)
+               if (ethtool_link_ksettings_test_link_mode(cmd,
+                                                         advertising,
+                                                         1000baseT_Full))
                        advertised |= IXGBE_LINK_SPEED_1GB_FULL;
-
-               if (ecmd->advertising & ADVERTISED_100baseT_Full)
+               if (ethtool_link_ksettings_test_link_mode(cmd,
+                                                         advertising,
+                                                         100baseT_Full))
                        advertised |= IXGBE_LINK_SPEED_100_FULL;
-
                if (old == advertised)
                        return err;
+
                /* this sets the link speed and restarts auto-neg */
                while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
                        usleep_range(1000, 2000);
@@ -409,10 +459,11 @@ static int ixgbe_set_settings(struct net_device *netdev,
                clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
        } else {
                /* in this case we currently only support 10Gb/FULL */
-               u32 speed = ethtool_cmd_speed(ecmd);
-               if ((ecmd->autoneg == AUTONEG_ENABLE) ||
-                   (ecmd->advertising != ADVERTISED_10000baseT_Full) ||
-                   (speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL))
+               u32 speed = cmd->base.speed;
+               if ((cmd->base.autoneg == AUTONEG_ENABLE) ||
+                   (!ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                           10000baseT_Full)) ||
+                   (speed + cmd->base.duplex != SPEED_10000 + DUPLEX_FULL))
                        return -EINVAL;
        }
 
@@ -3238,8 +3289,8 @@ static int ixgbe_get_module_eeprom(struct net_device *dev,
 }
 
 static const struct ethtool_ops ixgbe_ethtool_ops = {
-       .get_settings           = ixgbe_get_settings,
-       .set_settings           = ixgbe_set_settings,
+       .get_link_ksettings     = ixgbe_get_link_ksettings,
+       .set_link_ksettings     = ixgbe_set_link_ksettings,
        .get_drvinfo            = ixgbe_get_drvinfo,
        .get_regs_len           = ixgbe_get_regs_len,
        .get_regs               = ixgbe_get_regs,
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 9ded8c6..94434a6 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -124,6 +124,29 @@ struct ethtool_link_ksettings {
        bitmap_zero((ptr)->link_modes.name, __ETHTOOL_LINK_MODE_MASK_NBITS)
 
 /**
+ * ethtool_link_ksettings_subset_link_mode - check if link mode mask
+ * modes are a subset of one another
+ *   @ptr : pointer to struct ethtool_link_ksettings
+ *   @src1 : one of supported/advertising/lp_advertising
+ *   @src2 : one of supported/advertising/lp_advertising
+ *
+ * Returns true/false
+ */
+#define ethtool_link_ksettings_subset_link_mode(ptr, src1, src2)       \
+       bitmap_subset((ptr)->link_modes.src1, (ptr)->link_modes.src2,   \
+       __ETHTOOL_LINK_MODE_MASK_NBITS)
+
+/**
+ * ethtool_link_ksettings_copy_link_mode - mask ksettings mask
+ *   @ptr : pointer to struct ethtool_link_ksettings
+ *   @dst : one of supported/advertising/lp_advertising
+ *   @src : one of supported/advertising/lp_advertising
+ */
+#define ethtool_link_ksettings_copy_link_mode(ptr, dst, src)   \
+       bitmap_copy((ptr)->link_modes.dst, (ptr)->link_modes.src,       \
+        __ETHTOOL_LINK_MODE_MASK_NBITS)                                \
+
+/**
  * ethtool_link_ksettings_add_link_mode - set bit in link_ksettings
  * link mode mask
  *   @ptr : pointer to struct ethtool_link_ksettings
@@ -135,6 +158,17 @@ struct ethtool_link_ksettings {
        __set_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
 
 /**
+ * ethtool_link_ksettings_remove_link_mode - set bit in link_ksettings
+ * link mode mask
+ *   @ptr : pointer to struct ethtool_link_ksettings
+ *   @name : one of supported/advertising/lp_advertising
+ *   @mode : one of the ETHTOOL_LINK_MODE_*_BIT
+ * (not atomic, no bound checking)
+ */
+#define ethtool_link_ksettings_remove_link_mode(ptr, name, mode)       \
+       __clear_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
+
+/**
  * ethtool_link_ksettings_test_link_mode - test bit in ksettings link mode mask
  *   @ptr : pointer to struct ethtool_link_ksettings
  *   @name : one of supported/advertising/lp_advertising
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel&#174; Ethernet, visit 
http://communities.intel.com/community/wired

Reply via email to