Commit 9a381f7e authored by Selvin Xavier's avatar Selvin Xavier Committed by Jason Gunthorpe
Browse files

RDMA/bnxt_re: Add extended statistics counters

Implement extended statistics counters for newer adapters. Check if the FW
support for this command and issue the FW command only if is
supported. Includes code re-organization to handle extended stats. Also,
add AH and PD software counters.

Link: https://lore.kernel.org/r/1631709163-2287-2-git-send-email-selvin.xavier@broadcom.com


Reviewed-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarSelvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent ad17bbef
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@

#ifndef __BNXT_RE_H__
#define __BNXT_RE_H__
#include "hw_counters.h"
#define ROCE_DRV_MODULE_NAME		"bnxt_re"

#define BNXT_RE_DESC	"Broadcom NetXtreme-C/E RoCE Driver"
@@ -177,15 +178,17 @@ struct bnxt_re_dev {
	atomic_t			srq_count;
	atomic_t			mr_count;
	atomic_t			mw_count;
	atomic_t			ah_count;
	atomic_t			pd_count;
	/* Max of 2 lossless traffic class supported per port */
	u16				cosq[2];

	/* QP for for handling QP1 packets */
	struct bnxt_re_gsi_context	gsi_ctx;
	struct bnxt_re_stats		stats;
	atomic_t nq_alloc_cnt;
	u32 is_virtfn;
	u32 num_vfs;
	struct bnxt_qplib_roce_stats	stats;
};

#define to_bnxt_re_dev(ptr, member)	\
+178 −95
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@
#include "hw_counters.h"

static const char * const bnxt_re_stat_name[] = {
	[BNXT_RE_ACTIVE_PD]		=  "active_pds",
	[BNXT_RE_ACTIVE_AH]		=  "active_ahs",
	[BNXT_RE_ACTIVE_QP]		=  "active_qps",
	[BNXT_RE_ACTIVE_SRQ]		=  "active_srqs",
	[BNXT_RE_ACTIVE_CQ]		=  "active_cqs",
@@ -109,137 +111,218 @@ static const char * const bnxt_re_stat_name[] = {
	[BNXT_RE_RES_SRQ_LOAD_ERR]      = "res_srq_load_err",
	[BNXT_RE_RES_TX_PCI_ERR]        = "res_tx_pci_err",
	[BNXT_RE_RES_RX_PCI_ERR]        = "res_rx_pci_err",
	[BNXT_RE_OUT_OF_SEQ_ERR]        = "oos_drop_count"
	[BNXT_RE_OUT_OF_SEQ_ERR]        = "oos_drop_count",
	[BNXT_RE_TX_ATOMIC_REQ]		= "tx_atomic_req",
	[BNXT_RE_TX_READ_REQ]		= "tx_read_req",
	[BNXT_RE_TX_READ_RES]		= "tx_read_resp",
	[BNXT_RE_TX_WRITE_REQ]		= "tx_write_req",
	[BNXT_RE_TX_SEND_REQ]		= "tx_send_req",
	[BNXT_RE_RX_ATOMIC_REQ]		= "rx_atomic_req",
	[BNXT_RE_RX_READ_REQ]		= "rx_read_req",
	[BNXT_RE_RX_READ_RESP]		= "rx_read_resp",
	[BNXT_RE_RX_WRITE_REQ]		= "rx_write_req",
	[BNXT_RE_RX_SEND_REQ]		= "rx_send_req",
	[BNXT_RE_RX_ROCE_GOOD_PKTS]	= "rx_roce_good_pkts",
	[BNXT_RE_RX_ROCE_GOOD_BYTES]	= "rx_roce_good_bytes",
	[BNXT_RE_OOB]			= "rx_out_of_buffer"
};

int bnxt_re_ib_get_hw_stats(struct ib_device *ibdev,
static void bnxt_re_copy_ext_stats(struct bnxt_re_dev *rdev,
				   struct rdma_hw_stats *stats,
			    u32 port, int index)
				   struct bnxt_qplib_ext_stat *s)
{
	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
	struct ctx_hw_stats *bnxt_re_stats = rdev->qplib_ctx.stats.dma;
	int rc  = 0;
	stats->value[BNXT_RE_TX_ATOMIC_REQ] = s->tx_atomic_req;
	stats->value[BNXT_RE_TX_READ_REQ]   = s->tx_read_req;
	stats->value[BNXT_RE_TX_READ_RES]   = s->tx_read_res;
	stats->value[BNXT_RE_TX_WRITE_REQ]  = s->tx_write_req;
	stats->value[BNXT_RE_TX_SEND_REQ]   = s->tx_send_req;
	stats->value[BNXT_RE_RX_ATOMIC_REQ] = s->rx_atomic_req;
	stats->value[BNXT_RE_RX_READ_REQ]   = s->rx_read_req;
	stats->value[BNXT_RE_RX_READ_RESP]  = s->rx_read_res;
	stats->value[BNXT_RE_RX_WRITE_REQ]  = s->rx_write_req;
	stats->value[BNXT_RE_RX_SEND_REQ]   = s->rx_send_req;
	stats->value[BNXT_RE_RX_ROCE_GOOD_PKTS] = s->rx_roce_good_pkts;
	stats->value[BNXT_RE_RX_ROCE_GOOD_BYTES] = s->rx_roce_good_bytes;
	stats->value[BNXT_RE_OOB] = s->rx_out_of_buffer;
}

	if (!port || !stats)
		return -EINVAL;
static int bnxt_re_get_ext_stat(struct bnxt_re_dev *rdev,
				struct rdma_hw_stats *stats)
{
	struct bnxt_qplib_ext_stat *estat = &rdev->stats.rstat.ext_stat;
	u32 fid;
	int rc;

	stats->value[BNXT_RE_ACTIVE_QP] = atomic_read(&rdev->qp_count);
	stats->value[BNXT_RE_ACTIVE_SRQ] = atomic_read(&rdev->srq_count);
	stats->value[BNXT_RE_ACTIVE_CQ] = atomic_read(&rdev->cq_count);
	stats->value[BNXT_RE_ACTIVE_MR] = atomic_read(&rdev->mr_count);
	stats->value[BNXT_RE_ACTIVE_MW] = atomic_read(&rdev->mw_count);
	if (bnxt_re_stats) {
		stats->value[BNXT_RE_RECOVERABLE_ERRORS] =
			le64_to_cpu(bnxt_re_stats->tx_bcast_pkts);
		stats->value[BNXT_RE_RX_DROPS] =
			le64_to_cpu(bnxt_re_stats->rx_error_pkts);
		stats->value[BNXT_RE_RX_DISCARDS] =
			le64_to_cpu(bnxt_re_stats->rx_discard_pkts);
		stats->value[BNXT_RE_RX_PKTS] =
			le64_to_cpu(bnxt_re_stats->rx_ucast_pkts);
		stats->value[BNXT_RE_RX_BYTES] =
			le64_to_cpu(bnxt_re_stats->rx_ucast_bytes);
		stats->value[BNXT_RE_TX_PKTS] =
			le64_to_cpu(bnxt_re_stats->tx_ucast_pkts);
		stats->value[BNXT_RE_TX_BYTES] =
			le64_to_cpu(bnxt_re_stats->tx_ucast_bytes);
	}
	if (test_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags)) {
		rc = bnxt_qplib_get_roce_stats(&rdev->rcfw, &rdev->stats);
	fid = PCI_FUNC(rdev->en_dev->pdev->devfn);
	rc = bnxt_qplib_qext_stat(&rdev->rcfw, fid, estat);
	if (rc)
			clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS,
				  &rdev->flags);
		goto done;
	bnxt_re_copy_ext_stats(rdev, stats, estat);

done:
	return rc;
}

static void bnxt_re_copy_err_stats(struct bnxt_re_dev *rdev,
				   struct rdma_hw_stats *stats,
				   struct bnxt_qplib_roce_stats *err_s)
{
	stats->value[BNXT_RE_TO_RETRANSMITS] =
					rdev->stats.to_retransmits;
				err_s->to_retransmits;
	stats->value[BNXT_RE_SEQ_ERR_NAKS_RCVD] =
					rdev->stats.seq_err_naks_rcvd;
				err_s->seq_err_naks_rcvd;
	stats->value[BNXT_RE_MAX_RETRY_EXCEEDED] =
					rdev->stats.max_retry_exceeded;
				err_s->max_retry_exceeded;
	stats->value[BNXT_RE_RNR_NAKS_RCVD] =
					rdev->stats.rnr_naks_rcvd;
				err_s->rnr_naks_rcvd;
	stats->value[BNXT_RE_MISSING_RESP] =
					rdev->stats.missing_resp;
				err_s->missing_resp;
	stats->value[BNXT_RE_UNRECOVERABLE_ERR] =
					rdev->stats.unrecoverable_err;
				err_s->unrecoverable_err;
	stats->value[BNXT_RE_BAD_RESP_ERR] =
					rdev->stats.bad_resp_err;
				err_s->bad_resp_err;
	stats->value[BNXT_RE_LOCAL_QP_OP_ERR]	=
				rdev->stats.local_qp_op_err;
			err_s->local_qp_op_err;
	stats->value[BNXT_RE_LOCAL_PROTECTION_ERR] =
				rdev->stats.local_protection_err;
			err_s->local_protection_err;
	stats->value[BNXT_RE_MEM_MGMT_OP_ERR] =
				rdev->stats.mem_mgmt_op_err;
			err_s->mem_mgmt_op_err;
	stats->value[BNXT_RE_REMOTE_INVALID_REQ_ERR] =
				rdev->stats.remote_invalid_req_err;
			err_s->remote_invalid_req_err;
	stats->value[BNXT_RE_REMOTE_ACCESS_ERR] =
				rdev->stats.remote_access_err;
			err_s->remote_access_err;
	stats->value[BNXT_RE_REMOTE_OP_ERR] =
				rdev->stats.remote_op_err;
			err_s->remote_op_err;
	stats->value[BNXT_RE_DUP_REQ] =
				rdev->stats.dup_req;
			err_s->dup_req;
	stats->value[BNXT_RE_RES_EXCEED_MAX] =
				rdev->stats.res_exceed_max;
			err_s->res_exceed_max;
	stats->value[BNXT_RE_RES_LENGTH_MISMATCH] =
				rdev->stats.res_length_mismatch;
			err_s->res_length_mismatch;
	stats->value[BNXT_RE_RES_EXCEEDS_WQE] =
				rdev->stats.res_exceeds_wqe;
			err_s->res_exceeds_wqe;
	stats->value[BNXT_RE_RES_OPCODE_ERR] =
				rdev->stats.res_opcode_err;
			err_s->res_opcode_err;
	stats->value[BNXT_RE_RES_RX_INVALID_RKEY] =
				rdev->stats.res_rx_invalid_rkey;
			err_s->res_rx_invalid_rkey;
	stats->value[BNXT_RE_RES_RX_DOMAIN_ERR] =
				rdev->stats.res_rx_domain_err;
			err_s->res_rx_domain_err;
	stats->value[BNXT_RE_RES_RX_NO_PERM] =
				rdev->stats.res_rx_no_perm;
			err_s->res_rx_no_perm;
	stats->value[BNXT_RE_RES_RX_RANGE_ERR]  =
				rdev->stats.res_rx_range_err;
			err_s->res_rx_range_err;
	stats->value[BNXT_RE_RES_TX_INVALID_RKEY] =
				rdev->stats.res_tx_invalid_rkey;
			err_s->res_tx_invalid_rkey;
	stats->value[BNXT_RE_RES_TX_DOMAIN_ERR] =
				rdev->stats.res_tx_domain_err;
			err_s->res_tx_domain_err;
	stats->value[BNXT_RE_RES_TX_NO_PERM] =
				rdev->stats.res_tx_no_perm;
			err_s->res_tx_no_perm;
	stats->value[BNXT_RE_RES_TX_RANGE_ERR]  =
				rdev->stats.res_tx_range_err;
			err_s->res_tx_range_err;
	stats->value[BNXT_RE_RES_IRRQ_OFLOW] =
				rdev->stats.res_irrq_oflow;
			err_s->res_irrq_oflow;
	stats->value[BNXT_RE_RES_UNSUP_OPCODE]  =
				rdev->stats.res_unsup_opcode;
			err_s->res_unsup_opcode;
	stats->value[BNXT_RE_RES_UNALIGNED_ATOMIC] =
				rdev->stats.res_unaligned_atomic;
			err_s->res_unaligned_atomic;
	stats->value[BNXT_RE_RES_REM_INV_ERR]   =
				rdev->stats.res_rem_inv_err;
			err_s->res_rem_inv_err;
	stats->value[BNXT_RE_RES_MEM_ERROR] =
				rdev->stats.res_mem_error;
			err_s->res_mem_error;
	stats->value[BNXT_RE_RES_SRQ_ERR] =
				rdev->stats.res_srq_err;
			err_s->res_srq_err;
	stats->value[BNXT_RE_RES_CMP_ERR] =
				rdev->stats.res_cmp_err;
			err_s->res_cmp_err;
	stats->value[BNXT_RE_RES_INVALID_DUP_RKEY] =
				rdev->stats.res_invalid_dup_rkey;
			err_s->res_invalid_dup_rkey;
	stats->value[BNXT_RE_RES_WQE_FORMAT_ERR] =
				rdev->stats.res_wqe_format_err;
			err_s->res_wqe_format_err;
	stats->value[BNXT_RE_RES_CQ_LOAD_ERR]   =
				rdev->stats.res_cq_load_err;
			err_s->res_cq_load_err;
	stats->value[BNXT_RE_RES_SRQ_LOAD_ERR]  =
				rdev->stats.res_srq_load_err;
			err_s->res_srq_load_err;
	stats->value[BNXT_RE_RES_TX_PCI_ERR]    =
				rdev->stats.res_tx_pci_err;
			err_s->res_tx_pci_err;
	stats->value[BNXT_RE_RES_RX_PCI_ERR]    =
				rdev->stats.res_rx_pci_err;
			err_s->res_rx_pci_err;
	stats->value[BNXT_RE_OUT_OF_SEQ_ERR]    =
				rdev->stats.res_oos_drop_count;
			err_s->res_oos_drop_count;
}

	return ARRAY_SIZE(bnxt_re_stat_name);
int bnxt_re_ib_get_hw_stats(struct ib_device *ibdev,
			    struct rdma_hw_stats *stats,
			    u32 port, int index)
{
	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
	struct ctx_hw_stats *hw_stats = NULL;
	struct bnxt_qplib_roce_stats *err_s = NULL;
	int rc  = 0;

	hw_stats = rdev->qplib_ctx.stats.dma;
	if (!port || !stats)
		return -EINVAL;

	stats->value[BNXT_RE_ACTIVE_QP] = atomic_read(&rdev->qp_count);
	stats->value[BNXT_RE_ACTIVE_SRQ] = atomic_read(&rdev->srq_count);
	stats->value[BNXT_RE_ACTIVE_CQ] = atomic_read(&rdev->cq_count);
	stats->value[BNXT_RE_ACTIVE_MR] = atomic_read(&rdev->mr_count);
	stats->value[BNXT_RE_ACTIVE_MW] = atomic_read(&rdev->mw_count);
	stats->value[BNXT_RE_ACTIVE_PD] = atomic_read(&rdev->pd_count);
	stats->value[BNXT_RE_ACTIVE_AH] = atomic_read(&rdev->ah_count);

	if (hw_stats) {
		stats->value[BNXT_RE_RECOVERABLE_ERRORS] =
			le64_to_cpu(hw_stats->tx_bcast_pkts);
		stats->value[BNXT_RE_RX_DROPS] =
			le64_to_cpu(hw_stats->rx_error_pkts);
		stats->value[BNXT_RE_RX_DISCARDS] =
			le64_to_cpu(hw_stats->rx_discard_pkts);
		stats->value[BNXT_RE_RX_PKTS] =
			le64_to_cpu(hw_stats->rx_ucast_pkts);
		stats->value[BNXT_RE_RX_BYTES] =
			le64_to_cpu(hw_stats->rx_ucast_bytes);
		stats->value[BNXT_RE_TX_PKTS] =
			le64_to_cpu(hw_stats->tx_ucast_pkts);
		stats->value[BNXT_RE_TX_BYTES] =
			le64_to_cpu(hw_stats->tx_ucast_bytes);
	}
	err_s = &rdev->stats.rstat.errs;
	if (test_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags)) {
		rc = bnxt_qplib_get_roce_stats(&rdev->rcfw, err_s);
		if (rc) {
			clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS,
				  &rdev->flags);
			goto done;
		}
		if (_is_ext_stats_supported(rdev->dev_attr.dev_cap_flags) &&
		    !rdev->is_virtfn) {
			rc = bnxt_re_get_ext_stat(rdev, stats);
			if (rc) {
				clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS,
					  &rdev->flags);
				goto done;
			}
		}
		bnxt_re_copy_err_stats(rdev, stats, err_s);
	}

done:
	return bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx) ?
		BNXT_RE_NUM_EXT_COUNTERS : BNXT_RE_NUM_STD_COUNTERS;
}

struct rdma_hw_stats *bnxt_re_ib_alloc_hw_port_stats(struct ib_device *ibdev,
						     u32 port_num)
{
	BUILD_BUG_ON(ARRAY_SIZE(bnxt_re_stat_name) != BNXT_RE_NUM_COUNTERS);
	struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
	int num_counters = 0;

	if (bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx))
		num_counters = BNXT_RE_NUM_EXT_COUNTERS;
	else
		num_counters = BNXT_RE_NUM_STD_COUNTERS;

	return rdma_alloc_hw_stats_struct(bnxt_re_stat_name,
					  ARRAY_SIZE(bnxt_re_stat_name),
					  num_counters,
					  RDMA_HW_STATS_DEFAULT_LIFESPAN);
}
+27 −1
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@
#define __BNXT_RE_HW_STATS_H__

enum bnxt_re_hw_stats {
	BNXT_RE_ACTIVE_PD,
	BNXT_RE_ACTIVE_AH,
	BNXT_RE_ACTIVE_QP,
	BNXT_RE_ACTIVE_SRQ,
	BNXT_RE_ACTIVE_CQ,
@@ -93,7 +95,31 @@ enum bnxt_re_hw_stats {
	BNXT_RE_RES_TX_PCI_ERR,
	BNXT_RE_RES_RX_PCI_ERR,
	BNXT_RE_OUT_OF_SEQ_ERR,
	BNXT_RE_NUM_COUNTERS
	BNXT_RE_TX_ATOMIC_REQ,
	BNXT_RE_TX_READ_REQ,
	BNXT_RE_TX_READ_RES,
	BNXT_RE_TX_WRITE_REQ,
	BNXT_RE_TX_SEND_REQ,
	BNXT_RE_RX_ATOMIC_REQ,
	BNXT_RE_RX_READ_REQ,
	BNXT_RE_RX_READ_RESP,
	BNXT_RE_RX_WRITE_REQ,
	BNXT_RE_RX_SEND_REQ,
	BNXT_RE_RX_ROCE_GOOD_PKTS,
	BNXT_RE_RX_ROCE_GOOD_BYTES,
	BNXT_RE_OOB,
	BNXT_RE_NUM_EXT_COUNTERS
};

#define BNXT_RE_NUM_STD_COUNTERS (BNXT_RE_OUT_OF_SEQ_ERR + 1)

struct bnxt_re_rstat {
	struct bnxt_qplib_roce_stats    errs;
	struct bnxt_qplib_ext_stat      ext_stat;
};

struct bnxt_re_stats {
	struct bnxt_re_rstat            rstat;
};

struct rdma_hw_stats *bnxt_re_ib_alloc_hw_port_stats(struct ib_device *ibdev,
+13 −3
Original line number Diff line number Diff line
@@ -541,9 +541,12 @@ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd, struct ib_udata *udata)

	bnxt_re_destroy_fence_mr(pd);

	if (pd->qplib_pd.id)
		bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
				      &pd->qplib_pd);
	if (pd->qplib_pd.id) {
		if (!bnxt_qplib_dealloc_pd(&rdev->qplib_res,
					   &rdev->qplib_res.pd_tbl,
					   &pd->qplib_pd))
			atomic_dec(&rdev->pd_count);
	}
	return 0;
}

@@ -595,6 +598,8 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
		if (bnxt_re_create_fence_mr(pd))
			ibdev_warn(&rdev->ibdev,
				   "Failed to create Fence-MR\n");
	atomic_inc(&rdev->pd_count);

	return 0;
dbfail:
	bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
@@ -611,6 +616,8 @@ int bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags)

	bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah,
			      !(flags & RDMA_DESTROY_AH_SLEEPABLE));
	atomic_dec(&rdev->ah_count);

	return 0;
}

@@ -695,6 +702,7 @@ int bnxt_re_create_ah(struct ib_ah *ib_ah, struct rdma_ah_init_attr *init_attr,
		wmb(); /* make sure cache is updated. */
		spin_unlock_irqrestore(&uctx->sh_lock, flag);
	}
	atomic_inc(&rdev->ah_count);

	return 0;
}
@@ -760,6 +768,7 @@ static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
	bnxt_qplib_destroy_ah(&rdev->qplib_res,
			      &gsi_sah->qplib_ah,
			      true);
	atomic_dec(&rdev->ah_count);
	bnxt_qplib_clean_qp(&qp->qplib_qp);

	ibdev_dbg(&rdev->ibdev, "Destroy the shadow QP\n");
@@ -1006,6 +1015,7 @@ static struct bnxt_re_ah *bnxt_re_create_shadow_qp_ah
			  "Failed to allocate HW AH for Shadow QP");
		goto fail;
	}
	atomic_inc(&rdev->ah_count);

	return ah;

+4 −0
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode)

	rdev->qplib_res.cctx = rdev->chip_ctx;
	rdev->rcfw.res = &rdev->qplib_res;
	rdev->qplib_res.dattr = &rdev->dev_attr;
	rdev->qplib_res.is_vf = BNXT_VF(bp);

	bnxt_re_set_drv_mode(rdev, wqe_mode);
	if (bnxt_qplib_determine_atomics(en_dev->pdev))
@@ -777,6 +779,8 @@ static struct bnxt_re_dev *bnxt_re_dev_add(struct net_device *netdev,
	atomic_set(&rdev->srq_count, 0);
	atomic_set(&rdev->mr_count, 0);
	atomic_set(&rdev->mw_count, 0);
	atomic_set(&rdev->ah_count, 0);
	atomic_set(&rdev->pd_count, 0);
	rdev->cosq[0] = 0xFFFF;
	rdev->cosq[1] = 0xFFFF;

Loading