Thomas Bogendoerfer 0dd93d
From: Aharon Landau <aharonl@nvidia.com>
Thomas Bogendoerfer 0dd93d
Date: Fri, 8 Oct 2021 15:24:39 +0300
Thomas Bogendoerfer 0dd93d
Subject: RDMA/mlx5: Add optional counter support in get_hw_stats callback
Thomas Bogendoerfer 0dd93d
Patch-mainline: v5.16-rc1
Thomas Bogendoerfer 0dd93d
Git-commit: a020094090e5293abd5c2ecdcec96a275f56c4ef
Thomas Bogendoerfer 0dd93d
References: jsc#SLE-19249
Thomas Bogendoerfer 0dd93d
Thomas Bogendoerfer 0dd93d
When get_hw_stats is called, query and return the optional counter
Thomas Bogendoerfer 0dd93d
statistic as well.
Thomas Bogendoerfer 0dd93d
Thomas Bogendoerfer 0dd93d
Link: https://lore.kernel.org/r/20211008122439.166063-14-markzhang@nvidia.com
Thomas Bogendoerfer 0dd93d
Signed-off-by: Aharon Landau <aharonl@nvidia.com>
Thomas Bogendoerfer 0dd93d
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Thomas Bogendoerfer 0dd93d
Signed-off-by: Mark Zhang <markzhang@nvidia.com>
Thomas Bogendoerfer 0dd93d
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Thomas Bogendoerfer 0dd93d
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Thomas Bogendoerfer 0dd93d
---
Thomas Bogendoerfer 0dd93d
 drivers/infiniband/hw/mlx5/counters.c |   88 ++++++++++++++++++++++++++++++++--
Thomas Bogendoerfer 0dd93d
 1 file changed, 85 insertions(+), 3 deletions(-)
Thomas Bogendoerfer 0dd93d
Thomas Bogendoerfer 0dd93d
--- a/drivers/infiniband/hw/mlx5/counters.c
Thomas Bogendoerfer 0dd93d
+++ b/drivers/infiniband/hw/mlx5/counters.c
Thomas Bogendoerfer 0dd93d
@@ -270,9 +270,9 @@ free:
Thomas Bogendoerfer 0dd93d
 	return ret;
Thomas Bogendoerfer 0dd93d
 }
Thomas Bogendoerfer 0dd93d
 
Thomas Bogendoerfer 0dd93d
-static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
Thomas Bogendoerfer 0dd93d
-				struct rdma_hw_stats *stats,
Thomas Bogendoerfer 0dd93d
-				u32 port_num, int index)
Thomas Bogendoerfer 0dd93d
+static int do_get_hw_stats(struct ib_device *ibdev,
Thomas Bogendoerfer 0dd93d
+			   struct rdma_hw_stats *stats,
Thomas Bogendoerfer 0dd93d
+			   u32 port_num, int index)
Thomas Bogendoerfer 0dd93d
 {
Thomas Bogendoerfer 0dd93d
 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
Thomas Bogendoerfer 0dd93d
 	const struct mlx5_ib_counters *cnts = get_counters(dev, port_num - 1);
Thomas Bogendoerfer 0dd93d
@@ -324,6 +324,88 @@ done:
Thomas Bogendoerfer 0dd93d
 	return num_counters;
Thomas Bogendoerfer 0dd93d
 }
Thomas Bogendoerfer 0dd93d
 
Thomas Bogendoerfer 0dd93d
+static int do_get_op_stat(struct ib_device *ibdev,
Thomas Bogendoerfer 0dd93d
+			  struct rdma_hw_stats *stats,
Thomas Bogendoerfer 0dd93d
+			  u32 port_num, int index)
Thomas Bogendoerfer 0dd93d
+{
Thomas Bogendoerfer 0dd93d
+	struct mlx5_ib_dev *dev = to_mdev(ibdev);
Thomas Bogendoerfer 0dd93d
+	const struct mlx5_ib_counters *cnts;
Thomas Bogendoerfer 0dd93d
+	const struct mlx5_ib_op_fc *opfcs;
Thomas Bogendoerfer 0dd93d
+	u64 packets = 0, bytes;
Thomas Bogendoerfer 0dd93d
+	u32 type;
Thomas Bogendoerfer 0dd93d
+	int ret;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	cnts = get_counters(dev, port_num - 1);
Thomas Bogendoerfer 0dd93d
+	opfcs = cnts->opfcs;
Thomas Bogendoerfer 0dd93d
+	type = *(u32 *)cnts->descs[index].priv;
Thomas Bogendoerfer 0dd93d
+	if (type >= MLX5_IB_OPCOUNTER_MAX)
Thomas Bogendoerfer 0dd93d
+		return -EINVAL;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	if (!opfcs[type].fc)
Thomas Bogendoerfer 0dd93d
+		goto out;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	ret = mlx5_fc_query(dev->mdev, opfcs[type].fc,
Thomas Bogendoerfer 0dd93d
+			    &packets, &bytes);
Thomas Bogendoerfer 0dd93d
+	if (ret)
Thomas Bogendoerfer 0dd93d
+		return ret;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+out:
Thomas Bogendoerfer 0dd93d
+	stats->value[index] = packets;
Thomas Bogendoerfer 0dd93d
+	return index;
Thomas Bogendoerfer 0dd93d
+}
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+static int do_get_op_stats(struct ib_device *ibdev,
Thomas Bogendoerfer 0dd93d
+			   struct rdma_hw_stats *stats,
Thomas Bogendoerfer 0dd93d
+			   u32 port_num)
Thomas Bogendoerfer 0dd93d
+{
Thomas Bogendoerfer 0dd93d
+	struct mlx5_ib_dev *dev = to_mdev(ibdev);
Thomas Bogendoerfer 0dd93d
+	const struct mlx5_ib_counters *cnts;
Thomas Bogendoerfer 0dd93d
+	int index, ret, num_hw_counters;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	cnts = get_counters(dev, port_num - 1);
Thomas Bogendoerfer 0dd93d
+	num_hw_counters = cnts->num_q_counters + cnts->num_cong_counters +
Thomas Bogendoerfer 0dd93d
+			  cnts->num_ext_ppcnt_counters;
Thomas Bogendoerfer 0dd93d
+	for (index = num_hw_counters;
Thomas Bogendoerfer 0dd93d
+	     index < (num_hw_counters + cnts->num_op_counters); index++) {
Thomas Bogendoerfer 0dd93d
+		ret = do_get_op_stat(ibdev, stats, port_num, index);
Thomas Bogendoerfer 0dd93d
+		if (ret != index)
Thomas Bogendoerfer 0dd93d
+			return ret;
Thomas Bogendoerfer 0dd93d
+	}
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	return cnts->num_op_counters;
Thomas Bogendoerfer 0dd93d
+}
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
Thomas Bogendoerfer 0dd93d
+				struct rdma_hw_stats *stats,
Thomas Bogendoerfer 0dd93d
+				u32 port_num, int index)
Thomas Bogendoerfer 0dd93d
+{
Thomas Bogendoerfer 0dd93d
+	int num_counters, num_hw_counters, num_op_counters;
Thomas Bogendoerfer 0dd93d
+	struct mlx5_ib_dev *dev = to_mdev(ibdev);
Thomas Bogendoerfer 0dd93d
+	const struct mlx5_ib_counters *cnts;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	cnts = get_counters(dev, port_num - 1);
Thomas Bogendoerfer 0dd93d
+	num_hw_counters = cnts->num_q_counters + cnts->num_cong_counters +
Thomas Bogendoerfer 0dd93d
+		cnts->num_ext_ppcnt_counters;
Thomas Bogendoerfer 0dd93d
+	num_counters = num_hw_counters + cnts->num_op_counters;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	if (index < 0 || index > num_counters)
Thomas Bogendoerfer 0dd93d
+		return -EINVAL;
Thomas Bogendoerfer 0dd93d
+	else if (index > 0 && index < num_hw_counters)
Thomas Bogendoerfer 0dd93d
+		return do_get_hw_stats(ibdev, stats, port_num, index);
Thomas Bogendoerfer 0dd93d
+	else if (index >= num_hw_counters && index < num_counters)
Thomas Bogendoerfer 0dd93d
+		return do_get_op_stat(ibdev, stats, port_num, index);
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	num_hw_counters = do_get_hw_stats(ibdev, stats, port_num, index);
Thomas Bogendoerfer 0dd93d
+	if (num_hw_counters < 0)
Thomas Bogendoerfer 0dd93d
+		return num_hw_counters;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	num_op_counters = do_get_op_stats(ibdev, stats, port_num);
Thomas Bogendoerfer 0dd93d
+	if (num_op_counters < 0)
Thomas Bogendoerfer 0dd93d
+		return num_op_counters;
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
+	return num_hw_counters + num_op_counters;
Thomas Bogendoerfer 0dd93d
+}
Thomas Bogendoerfer 0dd93d
+
Thomas Bogendoerfer 0dd93d
 static struct rdma_hw_stats *
Thomas Bogendoerfer 0dd93d
 mlx5_ib_counter_alloc_stats(struct rdma_counter *counter)
Thomas Bogendoerfer 0dd93d
 {