Commit a0200940 authored by Aharon Landau's avatar Aharon Landau Committed by Jason Gunthorpe
Browse files

RDMA/mlx5: Add optional counter support in get_hw_stats callback

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: default avatarAharon Landau <aharonl@nvidia.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarMark Zhang <markzhang@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent a29b934c
Loading
Loading
Loading
Loading
+85 −3
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ static int mlx5_ib_query_ext_ppcnt_counters(struct mlx5_ib_dev *dev,
	return ret;
}

static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
static int do_get_hw_stats(struct ib_device *ibdev,
			   struct rdma_hw_stats *stats,
			   u32 port_num, int index)
{
@@ -324,6 +324,88 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
	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)
{