Commit 0f2be576 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'eth-fbnic-extend-hardware-stats-coverage'

Mohsin Bashir says:

====================
eth: fbnic: extend hardware stats coverage

This patch series extends the coverage for hardware stats reported via
`ethtool -S`, queue API, and rtnl link stats. The patchset is organized
as follow:

- The first patch adds locking support to protect hardware stats.
- The second patch provides coverage to the hardware queue stats.
- The third patch covers the RX buffer related stats.
- The fourth patch covers the TMI (TX MAC Interface) stats.
- The last patch cover the TTI (TX TEI Interface) stats.
====================

Link: https://patch.msgid.link/20250410070859.4160768-1-mohsin.bashr@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 24e31e47 f2957147
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -31,6 +31,46 @@ separate entry.
Statistics
----------

TX MAC Interface
~~~~~~~~~~~~~~~~

 - ``ptp_illegal_req``: packets sent to the NIC with PTP request bit set but routed to BMC/FW
 - ``ptp_good_ts``: packets successfully routed to MAC with PTP request bit set
 - ``ptp_bad_ts``: packets destined for MAC with PTP request bit set but aborted because of some error (e.g., DMA read error)

TX Extension (TEI) Interface (TTI)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 - ``tti_cm_drop``: control messages dropped at the TX Extension (TEI) Interface because of credit starvation
 - ``tti_frame_drop``: packets dropped at the TX Extension (TEI) Interface because of credit starvation
 - ``tti_tbi_drop``: packets dropped at the TX BMC Interface (TBI) because of credit starvation

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)
~~~~~~~~~~~~~~~

@@ -44,6 +84,15 @@ RPC (Rx parser)
 - ``rpc_out_of_hdr_err``: frames where header was larger than parsable region
 - ``ovr_size_err``: oversized frames

Hardware Queues
~~~~~~~~~~~~~~~

1. RX DMA Engine:

 - ``rde_[i]_pkt_err``: packets with MAC EOP, RPC parser, RXB truncation, or RDE frame truncation errors. These error are flagged in the packet metadata because of cut-through support but the actual drop happens once PCIE/RDE is reached.
 - ``rde_[i]_pkt_cq_drop``: packets dropped because RCQ is full
 - ``rde_[i]_pkt_bdq_drop``: packets dropped because HPQ or PPQ ran out of host buffer

PCIe
~~~~

+3 −0
Original line number Diff line number Diff line
@@ -81,6 +81,9 @@ struct fbnic_dev {

	/* Local copy of hardware statistics */
	struct fbnic_hw_stats hw_stats;

	/* Lock protecting access to hw_stats */
	spinlock_t hw_stats_lock;
};

/* Reserve entry 0 in the MSI-X "others" array until we have filled all
+34 −0
Original line number Diff line number Diff line
@@ -397,6 +397,15 @@ enum {
#define FBNIC_TCE_DROP_CTRL_TTI_FRM_DROP_EN	CSR_BIT(1)
#define FBNIC_TCE_DROP_CTRL_TTI_TBI_DROP_EN	CSR_BIT(2)

#define FBNIC_TCE_TTI_CM_DROP_PKTS	0x0403e		/* 0x100f8 */
#define FBNIC_TCE_TTI_CM_DROP_BYTE_L	0x0403f		/* 0x100fc */
#define FBNIC_TCE_TTI_CM_DROP_BYTE_H	0x04040		/* 0x10100 */
#define FBNIC_TCE_TTI_FRAME_DROP_PKTS	0x04041		/* 0x10104 */
#define FBNIC_TCE_TTI_FRAME_DROP_BYTE_L	0x04042		/* 0x10108 */
#define FBNIC_TCE_TTI_FRAME_DROP_BYTE_H	0x04043		/* 0x1010c */
#define FBNIC_TCE_TBI_DROP_PKTS		0x04044		/* 0x10110 */
#define FBNIC_TCE_TBI_DROP_BYTE_L	0x04045		/* 0x10114 */

#define FBNIC_TCE_TCAM_IDX2DEST_MAP	0x0404A		/* 0x10128 */
#define FBNIC_TCE_TCAM_IDX2DEST_MAP_DEST_ID_0	CSR_GENMASK(3, 0)
enum {
@@ -432,6 +441,11 @@ enum {
#define FBNIC_TMI_SOP_PROT_CTRL		0x04400		/* 0x11000 */
#define FBNIC_TMI_DROP_CTRL		0x04401		/* 0x11004 */
#define FBNIC_TMI_DROP_CTRL_EN			CSR_BIT(0)
#define FBNIC_TMI_DROP_PKTS		0x04402		/* 0x11008 */
#define FBNIC_TMI_DROP_BYTE_L		0x04403		/* 0x1100c */
#define FBNIC_TMI_ILLEGAL_PTP_REQS	0x04409		/* 0x11024 */
#define FBNIC_TMI_GOOD_PTP_TS		0x0440a		/* 0x11028 */
#define FBNIC_TMI_BAD_PTP_TS		0x0440b		/* 0x1102c */
#define FBNIC_CSR_END_TMI		0x0443f	/* CSR section delimiter */

/* Precision Time Protocol Registers */
@@ -485,6 +499,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)
@@ -864,6 +886,12 @@ enum {
#define FBNIC_QUEUE_TWQ1_BAL		0x022		/* 0x088 */
#define FBNIC_QUEUE_TWQ1_BAH		0x023		/* 0x08c */

/* Tx Work Queue Statistics Registers */
#define FBNIC_QUEUE_TWQ0_PKT_CNT	0x062		/* 0x188 */
#define FBNIC_QUEUE_TWQ0_ERR_CNT	0x063		/* 0x18c */
#define FBNIC_QUEUE_TWQ1_PKT_CNT	0x072		/* 0x1c8 */
#define FBNIC_QUEUE_TWQ1_ERR_CNT	0x073		/* 0x1cc */

/* Tx Completion Queue Registers */
#define FBNIC_QUEUE_TCQ_CTL		0x080		/* 0x200 */
#define FBNIC_QUEUE_TCQ_CTL_RESET		CSR_BIT(0)
@@ -953,6 +981,12 @@ enum {
	FBNIC_QUEUE_RDE_CTL1_PAYLD_PACK_RSS	= 2,
};

/* Rx Per CQ Statistics Counters */
#define FBNIC_QUEUE_RDE_PKT_CNT		0x2a2		/* 0xa88 */
#define FBNIC_QUEUE_RDE_PKT_ERR_CNT	0x2a3		/* 0xa8c */
#define FBNIC_QUEUE_RDE_CQ_DROP_CNT	0x2a4		/* 0xa90 */
#define FBNIC_QUEUE_RDE_BDQ_DROP_CNT	0x2a5		/* 0xa94 */

/* Rx Interrupt Manager Registers */
#define FBNIC_QUEUE_RIM_CTL		0x2c0		/* 0xb00 */
#define FBNIC_QUEUE_RIM_CTL_MSIX_MASK		CSR_GENMASK(7, 0)
+171 −7
Original line number Diff line number Diff line
@@ -27,6 +27,19 @@ struct fbnic_stat {
	FBNIC_STAT_FIELDS(fbnic_hw_stats, name, stat)

static const struct fbnic_stat fbnic_gstrings_hw_stats[] = {
	/* TTI */
	FBNIC_HW_STAT("tti_cm_drop_frames", tti.cm_drop.frames),
	FBNIC_HW_STAT("tti_cm_drop_bytes", tti.cm_drop.bytes),
	FBNIC_HW_STAT("tti_frame_drop_frames", tti.frame_drop.frames),
	FBNIC_HW_STAT("tti_frame_drop_bytes", tti.frame_drop.bytes),
	FBNIC_HW_STAT("tti_tbi_drop_frames", tti.tbi_drop.frames),
	FBNIC_HW_STAT("tti_tbi_drop_bytes", tti.tbi_drop.bytes),

	/* TMI */
	FBNIC_HW_STAT("ptp_illegal_req", tmi.ptp_illegal_req),
	FBNIC_HW_STAT("ptp_good_ts", tmi.ptp_good_ts),
	FBNIC_HW_STAT("ptp_bad_ts", tmi.ptp_bad_ts),

	/* RPC */
	FBNIC_HW_STAT("rpc_unkn_etype", rpc.unkn_etype),
	FBNIC_HW_STAT("rpc_unkn_ext_hdr", rpc.unkn_ext_hdr),
@@ -39,7 +52,64 @@ static const struct fbnic_stat fbnic_gstrings_hw_stats[] = {
};

#define FBNIC_HW_FIXED_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_stats)
#define FBNIC_HW_STATS_LEN	FBNIC_HW_FIXED_STATS_LEN

#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)

static const struct fbnic_stat fbnic_gstrings_hw_q_stats[] = {
	FBNIC_HW_Q_STAT("rde_%u_pkt_err", rde_pkt_err),
	FBNIC_HW_Q_STAT("rde_%u_pkt_cq_drop", rde_pkt_cq_drop),
	FBNIC_HW_Q_STAT("rde_%u_pkt_bdq_drop", rde_pkt_bdq_drop),
};

#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
fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
@@ -298,31 +368,125 @@ fbnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
	return err;
}

static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
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;
	int i, idx;

	switch (sset) {
	case ETH_SS_STATS:
		for (i = 0; i < FBNIC_HW_STATS_LEN; i++)
		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;

			for (i = 0; i < FBNIC_HW_Q_STATS_LEN; i++, stat++)
				ethtool_sprintf(&data, stat->string, idx);
		}
		break;
	}
}

static void fbnic_report_hw_stats(const struct fbnic_stat *stat,
				  const void *base, int len, u64 **data)
{
	while (len--) {
		u8 *curr = (u8 *)base + stat->offset;

		**data = *(u64 *)curr;

		stat++;
		(*data)++;
	}
}

static void fbnic_get_ethtool_stats(struct net_device *dev,
				    struct ethtool_stats *stats, u64 *data)
{
	struct fbnic_net *fbn = netdev_priv(dev);
	const struct fbnic_stat *stat;
	struct fbnic_dev *fbd = fbn->fbd;
	int i;

	fbnic_get_hw_stats(fbn->fbd);

	for (i = 0; i < FBNIC_HW_STATS_LEN; i++) {
		stat = &fbnic_gstrings_hw_stats[i];
		data[i] = *(u64 *)((u8 *)&fbn->fbd->hw_stats + stat->offset);
	spin_lock(&fbd->hw_stats_lock);
	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];

		fbnic_report_hw_stats(fbnic_gstrings_hw_q_stats, hw_q,
				      FBNIC_HW_Q_STATS_LEN, &data);
	}
	spin_unlock(&fbd->hw_stats_lock);
}

static int fbnic_get_sset_count(struct net_device *dev, int sset)
+333 −2
Original line number Diff line number Diff line
@@ -70,6 +70,100 @@ static void fbnic_hw_stat_rd64(struct fbnic_dev *fbd, u32 reg, s32 offset,
	stat->u.old_reg_value_64 = new_reg_value;
}

static void fbnic_reset_tmi_stats(struct fbnic_dev *fbd,
				  struct fbnic_tmi_stats *tmi)
{
	fbnic_hw_stat_rst32(fbd, FBNIC_TMI_DROP_PKTS, &tmi->drop.frames);
	fbnic_hw_stat_rst64(fbd, FBNIC_TMI_DROP_BYTE_L, 1, &tmi->drop.bytes);

	fbnic_hw_stat_rst32(fbd,
			    FBNIC_TMI_ILLEGAL_PTP_REQS,
			    &tmi->ptp_illegal_req);
	fbnic_hw_stat_rst32(fbd, FBNIC_TMI_GOOD_PTP_TS, &tmi->ptp_good_ts);
	fbnic_hw_stat_rst32(fbd, FBNIC_TMI_BAD_PTP_TS, &tmi->ptp_bad_ts);
}

static void fbnic_get_tmi_stats32(struct fbnic_dev *fbd,
				  struct fbnic_tmi_stats *tmi)
{
	fbnic_hw_stat_rd32(fbd, FBNIC_TMI_DROP_PKTS, &tmi->drop.frames);

	fbnic_hw_stat_rd32(fbd,
			   FBNIC_TMI_ILLEGAL_PTP_REQS,
			   &tmi->ptp_illegal_req);
	fbnic_hw_stat_rd32(fbd, FBNIC_TMI_GOOD_PTP_TS, &tmi->ptp_good_ts);
	fbnic_hw_stat_rd32(fbd, FBNIC_TMI_BAD_PTP_TS, &tmi->ptp_bad_ts);
}

static void fbnic_get_tmi_stats(struct fbnic_dev *fbd,
				struct fbnic_tmi_stats *tmi)
{
	fbnic_hw_stat_rd64(fbd, FBNIC_TMI_DROP_BYTE_L, 1, &tmi->drop.bytes);
}

static void fbnic_reset_tti_stats(struct fbnic_dev *fbd,
				  struct fbnic_tti_stats *tti)
{
	fbnic_hw_stat_rst32(fbd,
			    FBNIC_TCE_TTI_CM_DROP_PKTS,
			    &tti->cm_drop.frames);
	fbnic_hw_stat_rst64(fbd,
			    FBNIC_TCE_TTI_CM_DROP_BYTE_L,
			    1,
			    &tti->cm_drop.bytes);

	fbnic_hw_stat_rst32(fbd,
			    FBNIC_TCE_TTI_FRAME_DROP_PKTS,
			    &tti->frame_drop.frames);
	fbnic_hw_stat_rst64(fbd,
			    FBNIC_TCE_TTI_FRAME_DROP_BYTE_L,
			    1,
			    &tti->frame_drop.bytes);

	fbnic_hw_stat_rst32(fbd,
			    FBNIC_TCE_TBI_DROP_PKTS,
			    &tti->tbi_drop.frames);
	fbnic_hw_stat_rst64(fbd,
			    FBNIC_TCE_TBI_DROP_BYTE_L,
			    1,
			    &tti->tbi_drop.bytes);
}

static void fbnic_get_tti_stats32(struct fbnic_dev *fbd,
				  struct fbnic_tti_stats *tti)
{
	fbnic_hw_stat_rd32(fbd,
			   FBNIC_TCE_TTI_CM_DROP_PKTS,
			   &tti->cm_drop.frames);

	fbnic_hw_stat_rd32(fbd,
			   FBNIC_TCE_TTI_FRAME_DROP_PKTS,
			   &tti->frame_drop.frames);

	fbnic_hw_stat_rd32(fbd,
			   FBNIC_TCE_TBI_DROP_PKTS,
			   &tti->tbi_drop.frames);
}

static void fbnic_get_tti_stats(struct fbnic_dev *fbd,
				struct fbnic_tti_stats *tti)
{
	fbnic_hw_stat_rd64(fbd,
			   FBNIC_TCE_TTI_CM_DROP_BYTE_L,
			   1,
			   &tti->cm_drop.bytes);

	fbnic_hw_stat_rd64(fbd,
			   FBNIC_TCE_TTI_FRAME_DROP_BYTE_L,
			   1,
			   &tti->frame_drop.bytes);

	fbnic_hw_stat_rd64(fbd,
			   FBNIC_TCE_TBI_DROP_BYTE_L,
			   1,
			   &tti->tbi_drop.bytes);
}

static void fbnic_reset_rpc_stats(struct fbnic_dev *fbd,
				  struct fbnic_rpc_stats *rpc)
{
@@ -117,6 +211,221 @@ 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)
{
	int i;

	for (i = 0; i < fbd->max_num_queues; i++, hw_q++) {
		u32 base = FBNIC_QUEUE(i);

		fbnic_hw_stat_rst32(fbd,
				    base + FBNIC_QUEUE_RDE_PKT_ERR_CNT,
				    &hw_q->rde_pkt_err);
		fbnic_hw_stat_rst32(fbd,
				    base + FBNIC_QUEUE_RDE_CQ_DROP_CNT,
				    &hw_q->rde_pkt_cq_drop);
		fbnic_hw_stat_rst32(fbd,
				    base + FBNIC_QUEUE_RDE_BDQ_DROP_CNT,
				    &hw_q->rde_pkt_bdq_drop);
	}
}

static void fbnic_get_hw_rxq_stats32(struct fbnic_dev *fbd,
				     struct fbnic_hw_q_stats *hw_q)
{
	int i;

	for (i = 0; i < fbd->max_num_queues; i++, hw_q++) {
		u32 base = FBNIC_QUEUE(i);

		fbnic_hw_stat_rd32(fbd,
				   base + FBNIC_QUEUE_RDE_PKT_ERR_CNT,
				   &hw_q->rde_pkt_err);
		fbnic_hw_stat_rd32(fbd,
				   base + FBNIC_QUEUE_RDE_CQ_DROP_CNT,
				   &hw_q->rde_pkt_cq_drop);
		fbnic_hw_stat_rd32(fbd,
				   base + FBNIC_QUEUE_RDE_BDQ_DROP_CNT,
				   &hw_q->rde_pkt_bdq_drop);
	}
}

void fbnic_get_hw_q_stats(struct fbnic_dev *fbd,
			  struct fbnic_hw_q_stats *hw_q)
{
	spin_lock(&fbd->hw_stats_lock);
	fbnic_get_hw_rxq_stats32(fbd, hw_q);
	spin_unlock(&fbd->hw_stats_lock);
}

static void fbnic_reset_pcie_stats_asic(struct fbnic_dev *fbd,
					struct fbnic_pcie_stats *pcie)
{
@@ -203,18 +512,40 @@ static void fbnic_get_pcie_stats_asic64(struct fbnic_dev *fbd,

void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
{
	spin_lock(&fbd->hw_stats_lock);
	fbnic_reset_tmi_stats(fbd, &fbd->hw_stats.tmi);
	fbnic_reset_tti_stats(fbd, &fbd->hw_stats.tti);
	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);
}

void fbnic_get_hw_stats32(struct fbnic_dev *fbd)
static void __fbnic_get_hw_stats32(struct fbnic_dev *fbd)
{
	fbnic_get_tmi_stats32(fbd, &fbd->hw_stats.tmi);
	fbnic_get_tti_stats32(fbd, &fbd->hw_stats.tti);
	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);
}

void fbnic_get_hw_stats32(struct fbnic_dev *fbd)
{
	spin_lock(&fbd->hw_stats_lock);
	__fbnic_get_hw_stats32(fbd);
	spin_unlock(&fbd->hw_stats_lock);
}

void fbnic_get_hw_stats(struct fbnic_dev *fbd)
{
	fbnic_get_hw_stats32(fbd);
	spin_lock(&fbd->hw_stats_lock);
	__fbnic_get_hw_stats32(fbd);

	fbnic_get_tmi_stats(fbd, &fbd->hw_stats.tmi);
	fbnic_get_tti_stats(fbd, &fbd->hw_stats.tti);
	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);
}
Loading