Commit 986c63a0 authored by Mohsin Bashir's avatar Mohsin Bashir Committed by Paolo Abeni
Browse files

eth: fbnic: add coverage for RXB stats



This patch provides coverage to the RXB (RX Buffer) stats. RXB stats
are divided into 3 sections: RXB enqueue, RXB FIFO, and RXB dequeue
stats.

The RXB enqueue/dequeue stats are indexed from 0-3 and cater for the
input/output counters whereas, the RXB fifo stats are indexed from 0-7.

The RXB also supports pause frame stats counters which we are leaving
for a later patch.

ethtool -S eth0 | grep rxb
     rxb_integrity_err0: 0
     rxb_mac_err0: 0
     rxb_parser_err0: 0
     rxb_frm_err0: 0
     rxb_drbo0_frames: 1433543
     rxb_drbo0_bytes: 775949081
     ---
     ---
     rxb_intf3_frames: 1195711
     rxb_intf3_bytes: 739650210
     rxb_pbuf3_frames: 1195711
     rxb_pbuf3_bytes: 765948092

Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarMohsin Bashir <mohsin.bashr@gmail.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250410070859.4160768-4-mohsin.bashr@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 8f20a2bf
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -31,6 +31,32 @@ separate entry.
Statistics
----------

RXB (RX Buffer) Enqueue
~~~~~~~~~~~~~~~~~~~~~~~

 - ``rxb_integrity_err[i]``: frames enqueued with integrity errors (e.g., multi-bit ECC errors) on RXB input i
 - ``rxb_mac_err[i]``: frames enqueued with MAC end-of-frame errors (e.g., bad FCS) on RXB input i
 - ``rxb_parser_err[i]``: frames experienced RPC parser errors
 - ``rxb_frm_err[i]``: frames experienced signaling errors (e.g., missing end-of-packet/start-of-packet) on RXB input i
 - ``rxb_drbo[i]_frames``: frames received at RXB input i
 - ``rxb_drbo[i]_bytes``: bytes received at RXB input i

RXB (RX Buffer) FIFO
~~~~~~~~~~~~~~~~~~~~

 - ``rxb_fifo[i]_drop``: transitions into the drop state on RXB pool i
 - ``rxb_fifo[i]_dropped_frames``: frames dropped on RXB pool i
 - ``rxb_fifo[i]_ecn``: transitions into the ECN mark state on RXB pool i
 - ``rxb_fifo[i]_level``: current occupancy of RXB pool i

RXB (RX Buffer) Dequeue
~~~~~~~~~~~~~~~~~~~~~~~

   - ``rxb_intf[i]_frames``: frames sent to the output i
   - ``rxb_intf[i]_bytes``: bytes sent to the output i
   - ``rxb_pbuf[i]_frames``: frames sent to output i from the perspective of internal packet buffer
   - ``rxb_pbuf[i]_bytes``: bytes sent to output i from the perspective of internal packet buffer

RPC (Rx parser)
~~~~~~~~~~~~~~~

+8 −0
Original line number Diff line number Diff line
@@ -485,6 +485,14 @@ enum {
	FBNIC_RXB_FIFO_INDICES		= 8
};

enum {
	FBNIC_RXB_INTF_NET = 0,
	FBNIC_RXB_INTF_RBT = 1,
	/* Unused */
	/* Unused */
	FBNIC_RXB_INTF_INDICES	= 4
};

#define FBNIC_RXB_CT_SIZE(n)		(0x08000 + (n))	/* 0x20000 + 4*n */
#define FBNIC_RXB_CT_SIZE_CNT			8
#define FBNIC_RXB_CT_SIZE_HEADER		CSR_GENMASK(5, 0)
+110 −0
Original line number Diff line number Diff line
@@ -40,6 +40,47 @@ static const struct fbnic_stat fbnic_gstrings_hw_stats[] = {

#define FBNIC_HW_FIXED_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_stats)

#define FBNIC_RXB_ENQUEUE_STAT(name, stat) \
	FBNIC_STAT_FIELDS(fbnic_rxb_enqueue_stats, name, stat)

static const struct fbnic_stat fbnic_gstrings_rxb_enqueue_stats[] = {
	FBNIC_RXB_ENQUEUE_STAT("rxb_integrity_err%u", integrity_err),
	FBNIC_RXB_ENQUEUE_STAT("rxb_mac_err%u", mac_err),
	FBNIC_RXB_ENQUEUE_STAT("rxb_parser_err%u", parser_err),
	FBNIC_RXB_ENQUEUE_STAT("rxb_frm_err%u", frm_err),

	FBNIC_RXB_ENQUEUE_STAT("rxb_drbo%u_frames", drbo.frames),
	FBNIC_RXB_ENQUEUE_STAT("rxb_drbo%u_bytes", drbo.bytes),
};

#define FBNIC_HW_RXB_ENQUEUE_STATS_LEN \
	ARRAY_SIZE(fbnic_gstrings_rxb_enqueue_stats)

#define FBNIC_RXB_FIFO_STAT(name, stat) \
	FBNIC_STAT_FIELDS(fbnic_rxb_fifo_stats, name, stat)

static const struct fbnic_stat fbnic_gstrings_rxb_fifo_stats[] = {
	FBNIC_RXB_FIFO_STAT("rxb_fifo%u_drop", trans_drop),
	FBNIC_RXB_FIFO_STAT("rxb_fifo%u_dropped_frames", drop.frames),
	FBNIC_RXB_FIFO_STAT("rxb_fifo%u_ecn", trans_ecn),
	FBNIC_RXB_FIFO_STAT("rxb_fifo%u_level", level),
};

#define FBNIC_HW_RXB_FIFO_STATS_LEN ARRAY_SIZE(fbnic_gstrings_rxb_fifo_stats)

#define FBNIC_RXB_DEQUEUE_STAT(name, stat) \
	FBNIC_STAT_FIELDS(fbnic_rxb_dequeue_stats, name, stat)

static const struct fbnic_stat fbnic_gstrings_rxb_dequeue_stats[] = {
	FBNIC_RXB_DEQUEUE_STAT("rxb_intf%u_frames", intf.frames),
	FBNIC_RXB_DEQUEUE_STAT("rxb_intf%u_bytes", intf.bytes),
	FBNIC_RXB_DEQUEUE_STAT("rxb_pbuf%u_frames", pbuf.frames),
	FBNIC_RXB_DEQUEUE_STAT("rxb_pbuf%u_bytes", pbuf.bytes),
};

#define FBNIC_HW_RXB_DEQUEUE_STATS_LEN \
	ARRAY_SIZE(fbnic_gstrings_rxb_dequeue_stats)

#define FBNIC_HW_Q_STAT(name, stat) \
	FBNIC_STAT_FIELDS(fbnic_hw_q_stats, name, stat.value)

@@ -52,6 +93,9 @@ static const struct fbnic_stat fbnic_gstrings_hw_q_stats[] = {
#define FBNIC_HW_Q_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_q_stats)
#define FBNIC_HW_STATS_LEN \
	(FBNIC_HW_FIXED_STATS_LEN + \
	 FBNIC_HW_RXB_ENQUEUE_STATS_LEN * FBNIC_RXB_ENQUEUE_INDICES + \
	 FBNIC_HW_RXB_FIFO_STATS_LEN * FBNIC_RXB_FIFO_INDICES + \
	 FBNIC_HW_RXB_DEQUEUE_STATS_LEN * FBNIC_RXB_DEQUEUE_INDICES + \
	 FBNIC_HW_Q_STATS_LEN * FBNIC_MAX_QUEUES)

static void
@@ -311,6 +355,36 @@ fbnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
	return err;
}

static void fbnic_get_rxb_enqueue_strings(u8 **data, unsigned int idx)
{
	const struct fbnic_stat *stat;
	int i;

	stat = fbnic_gstrings_rxb_enqueue_stats;
	for (i = 0; i < FBNIC_HW_RXB_ENQUEUE_STATS_LEN; i++, stat++)
		ethtool_sprintf(data, stat->string, idx);
}

static void fbnic_get_rxb_fifo_strings(u8 **data, unsigned int idx)
{
	const struct fbnic_stat *stat;
	int i;

	stat = fbnic_gstrings_rxb_fifo_stats;
	for (i = 0; i < FBNIC_HW_RXB_FIFO_STATS_LEN; i++, stat++)
		ethtool_sprintf(data, stat->string, idx);
}

static void fbnic_get_rxb_dequeue_strings(u8 **data, unsigned int idx)
{
	const struct fbnic_stat *stat;
	int i;

	stat = fbnic_gstrings_rxb_dequeue_stats;
	for (i = 0; i < FBNIC_HW_RXB_DEQUEUE_STATS_LEN; i++, stat++)
		ethtool_sprintf(data, stat->string, idx);
}

static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
{
	const struct fbnic_stat *stat;
@@ -321,6 +395,15 @@ static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
		for (i = 0; i < FBNIC_HW_FIXED_STATS_LEN; i++)
			ethtool_puts(&data, fbnic_gstrings_hw_stats[i].string);

		for (i = 0; i < FBNIC_RXB_ENQUEUE_INDICES; i++)
			fbnic_get_rxb_enqueue_strings(&data, i);

		for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++)
			fbnic_get_rxb_fifo_strings(&data, i);

		for (i = 0; i < FBNIC_RXB_DEQUEUE_INDICES; i++)
			fbnic_get_rxb_dequeue_strings(&data, i);

		for (idx = 0; idx < FBNIC_MAX_QUEUES; idx++) {
			stat = fbnic_gstrings_hw_q_stats;

@@ -357,6 +440,33 @@ static void fbnic_get_ethtool_stats(struct net_device *dev,
	fbnic_report_hw_stats(fbnic_gstrings_hw_stats, &fbd->hw_stats,
			      FBNIC_HW_FIXED_STATS_LEN, &data);

	for (i = 0; i < FBNIC_RXB_ENQUEUE_INDICES; i++) {
		const struct fbnic_rxb_enqueue_stats *enq;

		enq = &fbd->hw_stats.rxb.enq[i];
		fbnic_report_hw_stats(fbnic_gstrings_rxb_enqueue_stats,
				      enq, FBNIC_HW_RXB_ENQUEUE_STATS_LEN,
				      &data);
	}

	for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++) {
		const struct fbnic_rxb_fifo_stats *fifo;

		fifo = &fbd->hw_stats.rxb.fifo[i];
		fbnic_report_hw_stats(fbnic_gstrings_rxb_fifo_stats,
				      fifo, FBNIC_HW_RXB_FIFO_STATS_LEN,
				      &data);
	}

	for (i = 0; i < FBNIC_RXB_DEQUEUE_INDICES; i++) {
		const struct fbnic_rxb_dequeue_stats *deq;

		deq = &fbd->hw_stats.rxb.deq[i];
		fbnic_report_hw_stats(fbnic_gstrings_rxb_dequeue_stats,
				      deq, FBNIC_HW_RXB_DEQUEUE_STATS_LEN,
				      &data);
	}

	for (i  = 0; i < FBNIC_MAX_QUEUES; i++) {
		const struct fbnic_hw_q_stats *hw_q = &fbd->hw_stats.hw_q[i];

+171 −0
Original line number Diff line number Diff line
@@ -117,6 +117,173 @@ static void fbnic_get_rpc_stats32(struct fbnic_dev *fbd,
			   &rpc->ovr_size_err);
}

static void fbnic_reset_rxb_fifo_stats(struct fbnic_dev *fbd, int i,
				       struct fbnic_rxb_fifo_stats *fifo)
{
	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_DROP_FRMS_STS(i),
			    &fifo->drop.frames);
	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_DROP_BYTES_STS_L(i), 1,
			    &fifo->drop.bytes);

	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_TRUN_FRMS_STS(i),
			    &fifo->trunc.frames);
	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_TRUN_BYTES_STS_L(i), 1,
			    &fifo->trunc.bytes);

	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_TRANS_DROP_STS(i),
			    &fifo->trans_drop);
	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_TRANS_ECN_STS(i),
			    &fifo->trans_ecn);

	fifo->level.u.old_reg_value_32 = 0;
}

static void fbnic_reset_rxb_enq_stats(struct fbnic_dev *fbd, int i,
				      struct fbnic_rxb_enqueue_stats *enq)
{
	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_DRBO_FRM_CNT_SRC(i),
			    &enq->drbo.frames);
	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_DRBO_BYTE_CNT_SRC_L(i), 4,
			    &enq->drbo.bytes);

	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_INTEGRITY_ERR(i),
			    &enq->integrity_err);
	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_MAC_ERR(i),
			    &enq->mac_err);
	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_PARSER_ERR(i),
			    &enq->parser_err);
	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_FRM_ERR(i),
			    &enq->frm_err);
}

static void fbnic_reset_rxb_deq_stats(struct fbnic_dev *fbd, int i,
				      struct fbnic_rxb_dequeue_stats *deq)
{
	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_INTF_FRM_CNT_DST(i),
			    &deq->intf.frames);
	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_INTF_BYTE_CNT_DST_L(i), 4,
			    &deq->intf.bytes);

	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_PBUF_FRM_CNT_DST(i),
			    &deq->pbuf.frames);
	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_PBUF_BYTE_CNT_DST_L(i), 4,
			    &deq->pbuf.bytes);
}

static void fbnic_reset_rxb_stats(struct fbnic_dev *fbd,
				  struct fbnic_rxb_stats *rxb)
{
	int i;

	for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++)
		fbnic_reset_rxb_fifo_stats(fbd, i, &rxb->fifo[i]);

	for (i = 0; i < FBNIC_RXB_INTF_INDICES; i++) {
		fbnic_reset_rxb_enq_stats(fbd, i, &rxb->enq[i]);
		fbnic_reset_rxb_deq_stats(fbd, i, &rxb->deq[i]);
	}
}

static void fbnic_get_rxb_fifo_stats32(struct fbnic_dev *fbd, int i,
				       struct fbnic_rxb_fifo_stats *fifo)
{
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_DROP_FRMS_STS(i),
			   &fifo->drop.frames);
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_TRUN_FRMS_STS(i),
			   &fifo->trunc.frames);

	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_TRANS_DROP_STS(i),
			   &fifo->trans_drop);
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_TRANS_ECN_STS(i),
			   &fifo->trans_ecn);

	fifo->level.value = rd32(fbd, FBNIC_RXB_PBUF_FIFO_LEVEL(i));
}

static void fbnic_get_rxb_fifo_stats(struct fbnic_dev *fbd, int i,
				     struct fbnic_rxb_fifo_stats *fifo)
{
	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_DROP_BYTES_STS_L(i), 1,
			   &fifo->drop.bytes);
	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_TRUN_BYTES_STS_L(i), 1,
			   &fifo->trunc.bytes);

	fbnic_get_rxb_fifo_stats32(fbd, i, fifo);
}

static void fbnic_get_rxb_enq_stats32(struct fbnic_dev *fbd, int i,
				      struct fbnic_rxb_enqueue_stats *enq)
{
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_DRBO_FRM_CNT_SRC(i),
			   &enq->drbo.frames);

	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_INTEGRITY_ERR(i),
			   &enq->integrity_err);
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_MAC_ERR(i),
			   &enq->mac_err);
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_PARSER_ERR(i),
			   &enq->parser_err);
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_FRM_ERR(i),
			   &enq->frm_err);
}

static void fbnic_get_rxb_enq_stats(struct fbnic_dev *fbd, int i,
				    struct fbnic_rxb_enqueue_stats *enq)
{
	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_DRBO_BYTE_CNT_SRC_L(i), 4,
			   &enq->drbo.bytes);

	fbnic_get_rxb_enq_stats32(fbd, i, enq);
}

static void fbnic_get_rxb_deq_stats32(struct fbnic_dev *fbd, int i,
				      struct fbnic_rxb_dequeue_stats *deq)
{
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_INTF_FRM_CNT_DST(i),
			   &deq->intf.frames);
	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_PBUF_FRM_CNT_DST(i),
			   &deq->pbuf.frames);
}

static void fbnic_get_rxb_deq_stats(struct fbnic_dev *fbd, int i,
				    struct fbnic_rxb_dequeue_stats *deq)
{
	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_INTF_BYTE_CNT_DST_L(i), 4,
			   &deq->intf.bytes);
	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_PBUF_BYTE_CNT_DST_L(i), 4,
			   &deq->pbuf.bytes);

	fbnic_get_rxb_deq_stats32(fbd, i, deq);
}

static void fbnic_get_rxb_stats32(struct fbnic_dev *fbd,
				  struct fbnic_rxb_stats *rxb)
{
	int i;

	for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++)
		fbnic_get_rxb_fifo_stats32(fbd, i, &rxb->fifo[i]);

	for (i = 0; i < FBNIC_RXB_INTF_INDICES; i++) {
		fbnic_get_rxb_enq_stats32(fbd, i, &rxb->enq[i]);
		fbnic_get_rxb_deq_stats32(fbd, i, &rxb->deq[i]);
	}
}

static void fbnic_get_rxb_stats(struct fbnic_dev *fbd,
				struct fbnic_rxb_stats *rxb)
{
	int i;

	for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++)
		fbnic_get_rxb_fifo_stats(fbd, i, &rxb->fifo[i]);

	for (i = 0; i < FBNIC_RXB_INTF_INDICES; i++) {
		fbnic_get_rxb_enq_stats(fbd, i, &rxb->enq[i]);
		fbnic_get_rxb_deq_stats(fbd, i, &rxb->deq[i]);
	}
}

static void fbnic_reset_hw_rxq_stats(struct fbnic_dev *fbd,
				     struct fbnic_hw_q_stats *hw_q)
{
@@ -253,6 +420,7 @@ void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
{
	spin_lock(&fbd->hw_stats_lock);
	fbnic_reset_rpc_stats(fbd, &fbd->hw_stats.rpc);
	fbnic_reset_rxb_stats(fbd, &fbd->hw_stats.rxb);
	fbnic_reset_hw_rxq_stats(fbd, fbd->hw_stats.hw_q);
	fbnic_reset_pcie_stats_asic(fbd, &fbd->hw_stats.pcie);
	spin_unlock(&fbd->hw_stats_lock);
@@ -261,6 +429,7 @@ void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
static void __fbnic_get_hw_stats32(struct fbnic_dev *fbd)
{
	fbnic_get_rpc_stats32(fbd, &fbd->hw_stats.rpc);
	fbnic_get_rxb_stats32(fbd, &fbd->hw_stats.rxb);
	fbnic_get_hw_rxq_stats32(fbd, fbd->hw_stats.hw_q);
}

@@ -275,6 +444,8 @@ void fbnic_get_hw_stats(struct fbnic_dev *fbd)
{
	spin_lock(&fbd->hw_stats_lock);
	__fbnic_get_hw_stats32(fbd);

	fbnic_get_rxb_stats(fbd, &fbd->hw_stats.rxb);
	fbnic_get_pcie_stats_asic64(fbd, &fbd->hw_stats.pcie);
	spin_unlock(&fbd->hw_stats_lock);
}
+28 −0
Original line number Diff line number Diff line
@@ -17,6 +17,11 @@ struct fbnic_stat_counter {
	bool reported;
};

struct fbnic_hw_stat {
	struct fbnic_stat_counter frames;
	struct fbnic_stat_counter bytes;
};

struct fbnic_eth_mac_stats {
	struct fbnic_stat_counter FramesTransmittedOK;
	struct fbnic_stat_counter FramesReceivedOK;
@@ -43,6 +48,28 @@ struct fbnic_rpc_stats {
	struct fbnic_stat_counter tcp_opt_err, out_of_hdr_err, ovr_size_err;
};

struct fbnic_rxb_enqueue_stats {
	struct fbnic_hw_stat drbo;
	struct fbnic_stat_counter integrity_err, mac_err;
	struct fbnic_stat_counter parser_err, frm_err;
};

struct fbnic_rxb_fifo_stats {
	struct fbnic_hw_stat drop, trunc;
	struct fbnic_stat_counter trans_drop, trans_ecn;
	struct fbnic_stat_counter level;
};

struct fbnic_rxb_dequeue_stats {
	struct fbnic_hw_stat intf, pbuf;
};

struct fbnic_rxb_stats {
	struct fbnic_rxb_enqueue_stats enq[FBNIC_RXB_ENQUEUE_INDICES];
	struct fbnic_rxb_fifo_stats fifo[FBNIC_RXB_FIFO_INDICES];
	struct fbnic_rxb_dequeue_stats deq[FBNIC_RXB_DEQUEUE_INDICES];
};

struct fbnic_hw_q_stats {
	struct fbnic_stat_counter rde_pkt_err;
	struct fbnic_stat_counter rde_pkt_cq_drop;
@@ -62,6 +89,7 @@ struct fbnic_pcie_stats {
struct fbnic_hw_stats {
	struct fbnic_mac_stats mac;
	struct fbnic_rpc_stats rpc;
	struct fbnic_rxb_stats rxb;
	struct fbnic_hw_q_stats hw_q[FBNIC_MAX_QUEUES];
	struct fbnic_pcie_stats pcie;
};
Loading