RDMA/mlx5: Fix Q-counters per vport allocation
authorPatrisious Haddad <phaddad@nvidia.com>
Mon, 5 Jun 2023 10:33:19 +0000 (13:33 +0300)
committerLeon Romanovsky <leon@kernel.org>
Sun, 11 Jun 2023 08:25:39 +0000 (11:25 +0300)
Previously Q-counters data was being allocated over the PF for all of
the available vports, however that isn't necessary.

Since each VF or SF has a Q-counter allocated for itself.

So we only need to allocate two counters data structures, one for the
device counters, and one for all the other vports to expose the
representors, since they only need to read from it in order to
determine mainly counters numbers and names, so they can all share.

This in turn also solves a bug we previously had where we couldn't
switch the device to switchdev mode when there were more than 128 SF/VFs
configured, since that is the maximum amount of Q-counters available for
a single port

Fixes: d22467a71ebe ("RDMA/mlx5: Expand switchdev Q-counters to expose representor statistics")
Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
Reviewed-by: Mark Zhang <markzhang@nvidia.com>
Link: https://lore.kernel.org/r/f54671df16e2227a069b229b33b62cd9ee24c475.1685960567.git.leon@kernel.org
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/mlx5/counters.c

index 1c06920..3d7ef81 100644 (file)
@@ -209,7 +209,8 @@ static const struct mlx5_ib_counters *get_counters(struct mlx5_ib_dev *dev,
             !vport_qcounters_supported(dev)) || !port_num)
                return &dev->port[0].cnts;
 
-       return &dev->port[port_num - 1].cnts;
+       return is_mdev_switchdev_mode(dev->mdev) ?
+              &dev->port[1].cnts : &dev->port[port_num - 1].cnts;
 }
 
 /**
@@ -262,7 +263,7 @@ static struct rdma_hw_stats *
 mlx5_ib_alloc_hw_port_stats(struct ib_device *ibdev, u32 port_num)
 {
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
-       const struct mlx5_ib_counters *cnts = &dev->port[port_num - 1].cnts;
+       const struct mlx5_ib_counters *cnts = get_counters(dev, port_num);
 
        return do_alloc_stats(cnts);
 }
@@ -725,11 +726,11 @@ err:
 static void mlx5_ib_dealloc_counters(struct mlx5_ib_dev *dev)
 {
        u32 in[MLX5_ST_SZ_DW(dealloc_q_counter_in)] = {};
-       int num_cnt_ports;
+       int num_cnt_ports = dev->num_ports;
        int i, j;
 
-       num_cnt_ports = (!is_mdev_switchdev_mode(dev->mdev) ||
-                        vport_qcounters_supported(dev)) ? dev->num_ports : 1;
+       if (is_mdev_switchdev_mode(dev->mdev))
+               num_cnt_ports = min(2, num_cnt_ports);
 
        MLX5_SET(dealloc_q_counter_in, in, opcode,
                 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
@@ -761,15 +762,22 @@ static int mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev)
 {
        u32 out[MLX5_ST_SZ_DW(alloc_q_counter_out)] = {};
        u32 in[MLX5_ST_SZ_DW(alloc_q_counter_in)] = {};
-       int num_cnt_ports;
+       int num_cnt_ports = dev->num_ports;
        int err = 0;
        int i;
        bool is_shared;
 
        MLX5_SET(alloc_q_counter_in, in, opcode, MLX5_CMD_OP_ALLOC_Q_COUNTER);
        is_shared = MLX5_CAP_GEN(dev->mdev, log_max_uctx) != 0;
-       num_cnt_ports = (!is_mdev_switchdev_mode(dev->mdev) ||
-                        vport_qcounters_supported(dev)) ? dev->num_ports : 1;
+
+       /*
+        * In switchdev we need to allocate two ports, one that is used for
+        * the device Q_counters and it is essentially the real Q_counters of
+        * this device, while the other is used as a helper for PF to be able to
+        * query all other vports.
+        */
+       if (is_mdev_switchdev_mode(dev->mdev))
+               num_cnt_ports = min(2, num_cnt_ports);
 
        for (i = 0; i < num_cnt_ports; i++) {
                err = __mlx5_ib_alloc_counters(dev, &dev->port[i].cnts, i);