net/mlx5e: Consider aggregated port speed during rate configuration
authorJianbo Liu <jianbol@nvidia.com>
Wed, 30 Aug 2023 01:19:01 +0000 (01:19 +0000)
committerSaeed Mahameed <saeedm@nvidia.com>
Wed, 20 Sep 2023 06:33:07 +0000 (23:33 -0700)
When LAG is configured, functions (PF,VF,SF) can utilize the maximum
aggregated link speed for transmission. Currently the aggregated link
speed is not considered.

Hence, improve it to use the aggregated link speed by referring to the
physical port's upper bonding device when LAG is configured.

Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c

index 1887a24ee414d00c75cbae2222f7a02f6fa52e51..f76c8f0562e9ee898a8ea6c533fd0fdb533d74fc 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
 
 #include "eswitch.h"
+#include "lib/mlx5.h"
 #include "esw/qos.h"
 #include "en/port.h"
 #define CREATE_TRACE_POINTS
@@ -701,6 +702,70 @@ int mlx5_esw_qos_set_vport_rate(struct mlx5_eswitch *esw, struct mlx5_vport *vpo
        return err;
 }
 
+static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev)
+{
+       struct ethtool_link_ksettings lksettings;
+       struct net_device *slave, *master;
+       u32 speed = SPEED_UNKNOWN;
+
+       /* Lock ensures a stable reference to master and slave netdevice
+        * while port speed of master is queried.
+        */
+       ASSERT_RTNL();
+
+       slave = mlx5_uplink_netdev_get(mdev);
+       if (!slave)
+               goto out;
+
+       master = netdev_master_upper_dev_get(slave);
+       if (master && !__ethtool_get_link_ksettings(master, &lksettings))
+               speed = lksettings.base.speed;
+
+out:
+       return speed;
+}
+
+static int mlx5_esw_qos_max_link_speed_get(struct mlx5_core_dev *mdev, u32 *link_speed_max,
+                                          bool hold_rtnl_lock, struct netlink_ext_ack *extack)
+{
+       int err;
+
+       if (!mlx5_lag_is_active(mdev))
+               goto skip_lag;
+
+       if (hold_rtnl_lock)
+               rtnl_lock();
+
+       *link_speed_max = mlx5_esw_qos_lag_link_speed_get_locked(mdev);
+
+       if (hold_rtnl_lock)
+               rtnl_unlock();
+
+       if (*link_speed_max != (u32)SPEED_UNKNOWN)
+               return 0;
+
+skip_lag:
+       err = mlx5_port_max_linkspeed(mdev, link_speed_max);
+       if (err)
+               NL_SET_ERR_MSG_MOD(extack, "Failed to get link maximum speed");
+
+       return err;
+}
+
+static int mlx5_esw_qos_link_speed_verify(struct mlx5_core_dev *mdev,
+                                         const char *name, u32 link_speed_max,
+                                         u64 value, struct netlink_ext_ack *extack)
+{
+       if (value > link_speed_max) {
+               pr_err("%s rate value %lluMbps exceed link maximum speed %u.\n",
+                      name, value, link_speed_max);
+               NL_SET_ERR_MSG_MOD(extack, "TX rate value exceed link maximum speed");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32 rate_mbps)
 {
        u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
@@ -744,12 +809,6 @@ static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char *
        u64 value;
        int err;
 
-       err = mlx5_port_max_linkspeed(mdev, &link_speed_max);
-       if (err) {
-               NL_SET_ERR_MSG_MOD(extack, "Failed to get link maximum speed");
-               return err;
-       }
-
        value = div_u64_rem(*rate, MLX5_LINKSPEED_UNIT, &remainder);
        if (remainder) {
                pr_err("%s rate value %lluBps not in link speed units of 1Mbps.\n",
@@ -758,12 +817,13 @@ static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char *
                return -EINVAL;
        }
 
-       if (value > link_speed_max) {
-               pr_err("%s rate value %lluMbps exceed link maximum speed %u.\n",
-                      name, value, link_speed_max);
-               NL_SET_ERR_MSG_MOD(extack, "TX rate value exceed link maximum speed");
-               return -EINVAL;
-       }
+       err = mlx5_esw_qos_max_link_speed_get(mdev, &link_speed_max, true, extack);
+       if (err)
+               return err;
+
+       err = mlx5_esw_qos_link_speed_verify(mdev, name, link_speed_max, value, extack);
+       if (err)
+               return err;
 
        *rate = value;
        return 0;