RDMA/mlx5: Add optional counter support in get_hw_stats callback
authorAharon Landau <aharonl@nvidia.com>
Fri, 8 Oct 2021 12:24:39 +0000 (15:24 +0300)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 12 Oct 2021 15:48:07 +0000 (12:48 -0300)
When get_hw_stats is called, query and return the optional counter
statistic as well.

Link: https://lore.kernel.org/r/20211008122439.166063-14-markzhang@nvidia.com
Signed-off-by: Aharon Landau <aharonl@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Mark Zhang <markzhang@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/hw/mlx5/counters.c

index 6ee340c63b20023a560dfd18c03c94d4a71b3b97..6f1c4b57110ec762c6f819cdf25a42f61d869707 100644 (file)
@@ -270,9 +270,9 @@ free:
        return ret;
 }
 
-static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
-                               struct rdma_hw_stats *stats,
-                               u32 port_num, int index)
+static int do_get_hw_stats(struct ib_device *ibdev,
+                          struct rdma_hw_stats *stats,
+                          u32 port_num, int index)
 {
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
        const struct mlx5_ib_counters *cnts = get_counters(dev, port_num - 1);
@@ -324,6 +324,88 @@ done:
        return num_counters;
 }
 
+static int do_get_op_stat(struct ib_device *ibdev,
+                         struct rdma_hw_stats *stats,
+                         u32 port_num, int index)
+{
+       struct mlx5_ib_dev *dev = to_mdev(ibdev);
+       const struct mlx5_ib_counters *cnts;
+       const struct mlx5_ib_op_fc *opfcs;
+       u64 packets = 0, bytes;
+       u32 type;
+       int ret;
+
+       cnts = get_counters(dev, port_num - 1);
+       opfcs = cnts->opfcs;
+       type = *(u32 *)cnts->descs[index].priv;
+       if (type >= MLX5_IB_OPCOUNTER_MAX)
+               return -EINVAL;
+
+       if (!opfcs[type].fc)
+               goto out;
+
+       ret = mlx5_fc_query(dev->mdev, opfcs[type].fc,
+                           &packets, &bytes);
+       if (ret)
+               return ret;
+
+out:
+       stats->value[index] = packets;
+       return index;
+}
+
+static int do_get_op_stats(struct ib_device *ibdev,
+                          struct rdma_hw_stats *stats,
+                          u32 port_num)
+{
+       struct mlx5_ib_dev *dev = to_mdev(ibdev);
+       const struct mlx5_ib_counters *cnts;
+       int index, ret, num_hw_counters;
+
+       cnts = get_counters(dev, port_num - 1);
+       num_hw_counters = cnts->num_q_counters + cnts->num_cong_counters +
+                         cnts->num_ext_ppcnt_counters;
+       for (index = num_hw_counters;
+            index < (num_hw_counters + cnts->num_op_counters); index++) {
+               ret = do_get_op_stat(ibdev, stats, port_num, index);
+               if (ret != index)
+                       return ret;
+       }
+
+       return cnts->num_op_counters;
+}
+
+static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
+                               struct rdma_hw_stats *stats,
+                               u32 port_num, int index)
+{
+       int num_counters, num_hw_counters, num_op_counters;
+       struct mlx5_ib_dev *dev = to_mdev(ibdev);
+       const struct mlx5_ib_counters *cnts;
+
+       cnts = get_counters(dev, port_num - 1);
+       num_hw_counters = cnts->num_q_counters + cnts->num_cong_counters +
+               cnts->num_ext_ppcnt_counters;
+       num_counters = num_hw_counters + cnts->num_op_counters;
+
+       if (index < 0 || index > num_counters)
+               return -EINVAL;
+       else if (index > 0 && index < num_hw_counters)
+               return do_get_hw_stats(ibdev, stats, port_num, index);
+       else if (index >= num_hw_counters && index < num_counters)
+               return do_get_op_stat(ibdev, stats, port_num, index);
+
+       num_hw_counters = do_get_hw_stats(ibdev, stats, port_num, index);
+       if (num_hw_counters < 0)
+               return num_hw_counters;
+
+       num_op_counters = do_get_op_stats(ibdev, stats, port_num);
+       if (num_op_counters < 0)
+               return num_op_counters;
+
+       return num_hw_counters + num_op_counters;
+}
+
 static struct rdma_hw_stats *
 mlx5_ib_counter_alloc_stats(struct rdma_counter *counter)
 {