From: Danielle Ratson <daniel...@nvidia.com>

Currently, the driver does not expose how many lanes are used when the
link is up.

Extract the lanes information from the device and expose it to ethtool.

Signed-off-by: Danielle Ratson <daniel...@nvidia.com>
Reviewed-by: Jiri Pirko <j...@nvidia.com>
Signed-off-by: Ido Schimmel <ido...@nvidia.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  6 +-
 .../mellanox/mlxsw/spectrum_ethtool.c         | 83 ++++++++++++++++---
 2 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index b8e91792ac08..84aee7d08ab4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -329,9 +329,9 @@ struct mlxsw_sp_port_type_speed_ops {
        void (*from_ptys_link)(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
                               unsigned long *mode);
        u32 (*from_ptys_speed)(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto);
-       void (*from_ptys_speed_duplex)(struct mlxsw_sp *mlxsw_sp,
-                                      bool carrier_ok, u32 ptys_eth_proto,
-                                      struct ethtool_link_ksettings *cmd);
+       void (*from_ptys_speed_lanes_duplex)(struct mlxsw_sp *mlxsw_sp,
+                                            bool carrier_ok, u32 
ptys_eth_proto,
+                                            struct ethtool_link_ksettings 
*cmd);
        int (*ptys_max_speed)(struct mlxsw_sp_port *mlxsw_sp_port, u32 
*p_max_speed);
        u32 (*to_ptys_advert_link)(struct mlxsw_sp *mlxsw_sp,
                                   const struct ethtool_link_ksettings *cmd);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
index 8a1b5d437822..6675d5e0d9d4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
@@ -966,8 +966,8 @@ static int mlxsw_sp_port_get_link_ksettings(struct 
net_device *dev,
 
        cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
        cmd->base.port = mlxsw_sp_port_connector_port(connector_type);
-       ops->from_ptys_speed_duplex(mlxsw_sp, netif_carrier_ok(dev),
-                                   eth_proto_oper, cmd);
+       ops->from_ptys_speed_lanes_duplex(mlxsw_sp, netif_carrier_ok(dev),
+                                         eth_proto_oper, cmd);
 
        return 0;
 }
@@ -1081,6 +1081,7 @@ struct mlxsw_sp1_port_link_mode {
        enum ethtool_link_mode_bit_indices mask_ethtool;
        u32 mask;
        u32 speed;
+       u32 width;
 };
 
 static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
@@ -1089,12 +1090,14 @@ static const struct mlxsw_sp1_port_link_mode 
mlxsw_sp1_port_link_mode[] = {
                                  MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
                .mask_ethtool   = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
                .speed          = SPEED_1000,
+               .width          = ETHTOOL_LANES_1,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
                                  MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
                .speed          = SPEED_10000,
+               .width          = ETHTOOL_LANES_4,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
@@ -1103,71 +1106,85 @@ static const struct mlxsw_sp1_port_link_mode 
mlxsw_sp1_port_link_mode[] = {
                                  MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
                .mask_ethtool   = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
                .speed          = SPEED_10000,
+               .width          = ETHTOOL_LANES_1,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
                .speed          = SPEED_40000,
+               .width          = ETHTOOL_LANES_4,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
                .speed          = SPEED_40000,
+               .width          = ETHTOOL_LANES_4,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
                .speed          = SPEED_40000,
+               .width          = ETHTOOL_LANES_4,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
                .speed          = SPEED_40000,
+               .width          = ETHTOOL_LANES_4,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR,
                .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
                .speed          = SPEED_25000,
+               .width          = ETHTOOL_LANES_1,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR,
                .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
                .speed          = SPEED_25000,
+               .width          = ETHTOOL_LANES_1,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
                .mask_ethtool   = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
                .speed          = SPEED_25000,
+               .width          = ETHTOOL_LANES_1,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
                .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
                .speed          = SPEED_50000,
+               .width          = ETHTOOL_LANES_2,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
                .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
                .speed          = SPEED_50000,
+               .width          = ETHTOOL_LANES_2,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2,
                .mask_ethtool   = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
                .speed          = SPEED_50000,
+               .width          = ETHTOOL_LANES_2,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
                .speed          = SPEED_100000,
+               .width          = ETHTOOL_LANES_4,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
                .speed          = SPEED_100000,
+               .width          = ETHTOOL_LANES_4,
        },
        {
                .mask           = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
                .mask_ethtool   = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
                .speed          = SPEED_100000,
+               .width          = ETHTOOL_LANES_4,
        },
 };
 
@@ -1220,20 +1237,36 @@ mlxsw_sp1_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, 
u32 ptys_eth_proto)
        return SPEED_UNKNOWN;
 }
 
+static u32
+mlxsw_sp1_from_ptys_lanes(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
+{
+       int i;
+
+       for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
+               if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
+                       return mlxsw_sp1_port_link_mode[i].width;
+       }
+
+       return ETHTOOL_LANES_UNKNOWN;
+}
+
 static void
-mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
-                                u32 ptys_eth_proto,
-                                struct ethtool_link_ksettings *cmd)
+mlxsw_sp1_from_ptys_speed_lanes_duplex(struct mlxsw_sp *mlxsw_sp, bool 
carrier_ok,
+                                      u32 ptys_eth_proto,
+                                      struct ethtool_link_ksettings *cmd)
 {
        cmd->base.speed = SPEED_UNKNOWN;
+       cmd->lanes = ETHTOOL_LANES_UNKNOWN;
        cmd->base.duplex = DUPLEX_UNKNOWN;
 
        if (!carrier_ok)
                return;
 
        cmd->base.speed = mlxsw_sp1_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
-       if (cmd->base.speed != SPEED_UNKNOWN)
+       if (cmd->base.speed != SPEED_UNKNOWN) {
+               cmd->lanes = mlxsw_sp1_from_ptys_lanes(mlxsw_sp, 
ptys_eth_proto);
                cmd->base.duplex = DUPLEX_FULL;
+       }
 }
 
 static int mlxsw_sp1_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 
*p_max_speed)
@@ -1308,7 +1341,7 @@ const struct mlxsw_sp_port_type_speed_ops 
mlxsw_sp1_port_type_speed_ops = {
        .from_ptys_supported_port       = mlxsw_sp1_from_ptys_supported_port,
        .from_ptys_link                 = mlxsw_sp1_from_ptys_link,
        .from_ptys_speed                = mlxsw_sp1_from_ptys_speed,
-       .from_ptys_speed_duplex         = mlxsw_sp1_from_ptys_speed_duplex,
+       .from_ptys_speed_lanes_duplex   = 
mlxsw_sp1_from_ptys_speed_lanes_duplex,
        .ptys_max_speed                 = mlxsw_sp1_ptys_max_speed,
        .to_ptys_advert_link            = mlxsw_sp1_to_ptys_advert_link,
        .to_ptys_speed_lanes            = mlxsw_sp1_to_ptys_speed_lanes,
@@ -1629,20 +1662,46 @@ mlxsw_sp2_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, 
u32 ptys_eth_proto)
        return SPEED_UNKNOWN;
 }
 
+static u32
+mlxsw_sp2_from_ptys_lanes(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
+{
+       u8 width;
+       int i;
+
+       for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
+               if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) {
+                       width = mlxsw_sp2_port_link_mode[i].mask_width;
+                       if (width & MLXSW_SP_PORT_MASK_WIDTH_1X)
+                               return ETHTOOL_LANES_1;
+                       else if (width & MLXSW_SP_PORT_MASK_WIDTH_2X)
+                               return ETHTOOL_LANES_2;
+                       else if (width & MLXSW_SP_PORT_MASK_WIDTH_4X)
+                               return ETHTOOL_LANES_4;
+                       else if (width & MLXSW_SP_PORT_MASK_WIDTH_8X)
+                               return ETHTOOL_LANES_8;
+               }
+       }
+
+       return ETHTOOL_LANES_UNKNOWN;
+}
+
 static void
-mlxsw_sp2_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
-                                u32 ptys_eth_proto,
-                                struct ethtool_link_ksettings *cmd)
+mlxsw_sp2_from_ptys_speed_lanes_duplex(struct mlxsw_sp *mlxsw_sp, bool 
carrier_ok,
+                                      u32 ptys_eth_proto,
+                                      struct ethtool_link_ksettings *cmd)
 {
        cmd->base.speed = SPEED_UNKNOWN;
+       cmd->lanes = ETHTOOL_LANES_UNKNOWN;
        cmd->base.duplex = DUPLEX_UNKNOWN;
 
        if (!carrier_ok)
                return;
 
        cmd->base.speed = mlxsw_sp2_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
-       if (cmd->base.speed != SPEED_UNKNOWN)
+       if (cmd->base.speed != SPEED_UNKNOWN) {
+               cmd->lanes = mlxsw_sp2_from_ptys_lanes(mlxsw_sp, 
ptys_eth_proto);
                cmd->base.duplex = DUPLEX_FULL;
+       }
 }
 
 static int mlxsw_sp2_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 
*p_max_speed)
@@ -1744,7 +1803,7 @@ const struct mlxsw_sp_port_type_speed_ops 
mlxsw_sp2_port_type_speed_ops = {
        .from_ptys_supported_port       = mlxsw_sp2_from_ptys_supported_port,
        .from_ptys_link                 = mlxsw_sp2_from_ptys_link,
        .from_ptys_speed                = mlxsw_sp2_from_ptys_speed,
-       .from_ptys_speed_duplex         = mlxsw_sp2_from_ptys_speed_duplex,
+       .from_ptys_speed_lanes_duplex   = 
mlxsw_sp2_from_ptys_speed_lanes_duplex,
        .ptys_max_speed                 = mlxsw_sp2_ptys_max_speed,
        .to_ptys_advert_link            = mlxsw_sp2_to_ptys_advert_link,
        .to_ptys_speed_lanes            = mlxsw_sp2_to_ptys_speed_lanes,
-- 
2.26.2

Reply via email to