File Index
Files and directories
Sign in
FILE

fbnic_hw_stats.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) Meta Platforms, Inc. and affiliates. */
  3
  4#include <linux/rtnetlink.h>
  5
  6#include "fbnic.h"
  7
  8static void fbnic_hw_stat_rst32(struct fbnic_dev *fbd, u32 reg,
  9				struct fbnic_stat_counter *stat)
 10{
 11	/* We do not touch the "value" field here.
 12	 * It gets zeroed out on fbd structure allocation.
 13	 * After that we want it to grow continuously
 14	 * through device resets and power state changes.
 15	 */
 16	stat->u.old_reg_value_32 = rd32(fbd, reg);
 17}
 18
 19static void fbnic_hw_stat_rd32(struct fbnic_dev *fbd, u32 reg,
 20			       struct fbnic_stat_counter *stat)
 21{
 22	u32 new_reg_value;
 23
 24	new_reg_value = rd32(fbd, reg);
 25	stat->value += new_reg_value - stat->u.old_reg_value_32;
 26	stat->u.old_reg_value_32 = new_reg_value;
 27}
 28
 29u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset)
 30{
 31	u32 prev_upper, upper, lower, diff;
 32
 33	prev_upper = rd32(fbd, reg + offset);
 34	lower = rd32(fbd, reg);
 35	upper = rd32(fbd, reg + offset);
 36
 37	diff = upper - prev_upper;
 38	if (!diff)
 39		return ((u64)upper << 32) | lower;
 40
 41	if (diff > 1)
 42		dev_warn_once(fbd->dev,
 43			      "Stats inconsistent, upper 32b of %#010x updating too quickly\n",
 44			      reg * 4);
 45
 46	/* Return only the upper bits as we cannot guarantee
 47	 * the accuracy of the lower bits. We will add them in
 48	 * when the counter slows down enough that we can get
 49	 * a snapshot with both upper values being the same
 50	 * between reads.
 51	 */
 52	return ((u64)upper << 32);
 53}
 54
 55static void fbnic_hw_stat_rst64(struct fbnic_dev *fbd, u32 reg, s32 offset,
 56				struct fbnic_stat_counter *stat)
 57{
 58	/* Record initial counter values and compute deltas from there to ensure
 59	 * stats start at 0 after reboot/reset. This avoids exposing absolute
 60	 * hardware counter values to userspace.
 61	 */
 62	stat->u.old_reg_value_64 = fbnic_stat_rd64(fbd, reg, offset);
 63}
 64
 65static void fbnic_hw_stat_rd64(struct fbnic_dev *fbd, u32 reg, s32 offset,
 66			       struct fbnic_stat_counter *stat)
 67{
 68	u64 new_reg_value;
 69
 70	new_reg_value = fbnic_stat_rd64(fbd, reg, offset);
 71	stat->value += new_reg_value - stat->u.old_reg_value_64;
 72	stat->u.old_reg_value_64 = new_reg_value;
 73}
 74
 75static void fbnic_reset_tmi_stats(struct fbnic_dev *fbd,
 76				  struct fbnic_tmi_stats *tmi)
 77{
 78	fbnic_hw_stat_rst32(fbd, FBNIC_TMI_DROP_PKTS, &tmi->drop.frames);
 79	fbnic_hw_stat_rst64(fbd, FBNIC_TMI_DROP_BYTE_L, 1, &tmi->drop.bytes);
 80
 81	fbnic_hw_stat_rst32(fbd,
 82			    FBNIC_TMI_ILLEGAL_PTP_REQS,
 83			    &tmi->ptp_illegal_req);
 84	fbnic_hw_stat_rst32(fbd, FBNIC_TMI_GOOD_PTP_TS, &tmi->ptp_good_ts);
 85	fbnic_hw_stat_rst32(fbd, FBNIC_TMI_BAD_PTP_TS, &tmi->ptp_bad_ts);
 86}
 87
 88static void fbnic_get_tmi_stats32(struct fbnic_dev *fbd,
 89				  struct fbnic_tmi_stats *tmi)
 90{
 91	fbnic_hw_stat_rd32(fbd, FBNIC_TMI_DROP_PKTS, &tmi->drop.frames);
 92
 93	fbnic_hw_stat_rd32(fbd,
 94			   FBNIC_TMI_ILLEGAL_PTP_REQS,
 95			   &tmi->ptp_illegal_req);
 96	fbnic_hw_stat_rd32(fbd, FBNIC_TMI_GOOD_PTP_TS, &tmi->ptp_good_ts);
 97	fbnic_hw_stat_rd32(fbd, FBNIC_TMI_BAD_PTP_TS, &tmi->ptp_bad_ts);
 98}
 99
100static void fbnic_get_tmi_stats(struct fbnic_dev *fbd,
101				struct fbnic_tmi_stats *tmi)
102{
103	fbnic_hw_stat_rd64(fbd, FBNIC_TMI_DROP_BYTE_L, 1, &tmi->drop.bytes);
104}
105
106static void fbnic_reset_tti_stats(struct fbnic_dev *fbd,
107				  struct fbnic_tti_stats *tti)
108{
109	fbnic_hw_stat_rst32(fbd,
110			    FBNIC_TCE_TTI_CM_DROP_PKTS,
111			    &tti->cm_drop.frames);
112	fbnic_hw_stat_rst64(fbd,
113			    FBNIC_TCE_TTI_CM_DROP_BYTE_L,
114			    1,
115			    &tti->cm_drop.bytes);
116
117	fbnic_hw_stat_rst32(fbd,
118			    FBNIC_TCE_TTI_FRAME_DROP_PKTS,
119			    &tti->frame_drop.frames);
120	fbnic_hw_stat_rst64(fbd,
121			    FBNIC_TCE_TTI_FRAME_DROP_BYTE_L,
122			    1,
123			    &tti->frame_drop.bytes);
124
125	fbnic_hw_stat_rst32(fbd,
126			    FBNIC_TCE_TBI_DROP_PKTS,
127			    &tti->tbi_drop.frames);
128	fbnic_hw_stat_rst64(fbd,
129			    FBNIC_TCE_TBI_DROP_BYTE_L,
130			    1,
131			    &tti->tbi_drop.bytes);
132}
133
134static void fbnic_get_tti_stats32(struct fbnic_dev *fbd,
135				  struct fbnic_tti_stats *tti)
136{
137	fbnic_hw_stat_rd32(fbd,
138			   FBNIC_TCE_TTI_CM_DROP_PKTS,
139			   &tti->cm_drop.frames);
140
141	fbnic_hw_stat_rd32(fbd,
142			   FBNIC_TCE_TTI_FRAME_DROP_PKTS,
143			   &tti->frame_drop.frames);
144
145	fbnic_hw_stat_rd32(fbd,
146			   FBNIC_TCE_TBI_DROP_PKTS,
147			   &tti->tbi_drop.frames);
148}
149
150static void fbnic_get_tti_stats(struct fbnic_dev *fbd,
151				struct fbnic_tti_stats *tti)
152{
153	fbnic_hw_stat_rd64(fbd,
154			   FBNIC_TCE_TTI_CM_DROP_BYTE_L,
155			   1,
156			   &tti->cm_drop.bytes);
157
158	fbnic_hw_stat_rd64(fbd,
159			   FBNIC_TCE_TTI_FRAME_DROP_BYTE_L,
160			   1,
161			   &tti->frame_drop.bytes);
162
163	fbnic_hw_stat_rd64(fbd,
164			   FBNIC_TCE_TBI_DROP_BYTE_L,
165			   1,
166			   &tti->tbi_drop.bytes);
167}
168
169static void fbnic_reset_rpc_stats(struct fbnic_dev *fbd,
170				  struct fbnic_rpc_stats *rpc)
171{
172	fbnic_hw_stat_rst32(fbd,
173			    FBNIC_RPC_CNTR_UNKN_ETYPE,
174			    &rpc->unkn_etype);
175	fbnic_hw_stat_rst32(fbd,
176			    FBNIC_RPC_CNTR_UNKN_EXT_HDR,
177			    &rpc->unkn_ext_hdr);
178	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV4_FRAG, &rpc->ipv4_frag);
179	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV6_FRAG, &rpc->ipv6_frag);
180	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV4_ESP, &rpc->ipv4_esp);
181	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV6_ESP, &rpc->ipv6_esp);
182	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_TCP_OPT_ERR, &rpc->tcp_opt_err);
183	fbnic_hw_stat_rst32(fbd,
184			    FBNIC_RPC_CNTR_OUT_OF_HDR_ERR,
185			    &rpc->out_of_hdr_err);
186	fbnic_hw_stat_rst32(fbd,
187			    FBNIC_RPC_CNTR_OVR_SIZE_ERR,
188			    &rpc->ovr_size_err);
189}
190
191static void fbnic_get_rpc_stats32(struct fbnic_dev *fbd,
192				  struct fbnic_rpc_stats *rpc)
193{
194	fbnic_hw_stat_rd32(fbd,
195			   FBNIC_RPC_CNTR_UNKN_ETYPE,
196			   &rpc->unkn_etype);
197	fbnic_hw_stat_rd32(fbd,
198			   FBNIC_RPC_CNTR_UNKN_EXT_HDR,
199			   &rpc->unkn_ext_hdr);
200
201	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV4_FRAG, &rpc->ipv4_frag);
202	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV6_FRAG, &rpc->ipv6_frag);
203
204	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV4_ESP, &rpc->ipv4_esp);
205	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV6_ESP, &rpc->ipv6_esp);
206
207	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_TCP_OPT_ERR, &rpc->tcp_opt_err);
208	fbnic_hw_stat_rd32(fbd,
209			   FBNIC_RPC_CNTR_OUT_OF_HDR_ERR,
210			   &rpc->out_of_hdr_err);
211	fbnic_hw_stat_rd32(fbd,
212			   FBNIC_RPC_CNTR_OVR_SIZE_ERR,
213			   &rpc->ovr_size_err);
214}
215
216static void fbnic_reset_rxb_fifo_stats(struct fbnic_dev *fbd, int i,
217				       struct fbnic_rxb_fifo_stats *fifo)
218{
219	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_DROP_FRMS_STS(i),
220			    &fifo->drop.frames);
221	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_DROP_BYTES_STS_L(i), 1,
222			    &fifo->drop.bytes);
223
224	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_TRUN_FRMS_STS(i),
225			    &fifo->trunc.frames);
226	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_TRUN_BYTES_STS_L(i), 1,
227			    &fifo->trunc.bytes);
228
229	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_TRANS_DROP_STS(i),
230			    &fifo->trans_drop);
231	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_TRANS_ECN_STS(i),
232			    &fifo->trans_ecn);
233
234	fifo->level.u.old_reg_value_32 = 0;
235}
236
237static void fbnic_reset_rxb_enq_stats(struct fbnic_dev *fbd, int i,
238				      struct fbnic_rxb_enqueue_stats *enq)
239{
240	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_DRBO_FRM_CNT_SRC(i),
241			    &enq->drbo.frames);
242	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_DRBO_BYTE_CNT_SRC_L(i), 4,
243			    &enq->drbo.bytes);
244
245	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_INTEGRITY_ERR(i),
246			    &enq->integrity_err);
247	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_MAC_ERR(i),
248			    &enq->mac_err);
249	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_PARSER_ERR(i),
250			    &enq->parser_err);
251	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_FRM_ERR(i),
252			    &enq->frm_err);
253}
254
255static void fbnic_reset_rxb_deq_stats(struct fbnic_dev *fbd, int i,
256				      struct fbnic_rxb_dequeue_stats *deq)
257{
258	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_INTF_FRM_CNT_DST(i),
259			    &deq->intf.frames);
260	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_INTF_BYTE_CNT_DST_L(i), 4,
261			    &deq->intf.bytes);
262
263	fbnic_hw_stat_rst32(fbd, FBNIC_RXB_PBUF_FRM_CNT_DST(i),
264			    &deq->pbuf.frames);
265	fbnic_hw_stat_rst64(fbd, FBNIC_RXB_PBUF_BYTE_CNT_DST_L(i), 4,
266			    &deq->pbuf.bytes);
267}
268
269static void fbnic_reset_rxb_stats(struct fbnic_dev *fbd,
270				  struct fbnic_rxb_stats *rxb)
271{
272	int i;
273
274	for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++)
275		fbnic_reset_rxb_fifo_stats(fbd, i, &rxb->fifo[i]);
276
277	for (i = 0; i < FBNIC_RXB_INTF_INDICES; i++) {
278		fbnic_reset_rxb_enq_stats(fbd, i, &rxb->enq[i]);
279		fbnic_reset_rxb_deq_stats(fbd, i, &rxb->deq[i]);
280	}
281}
282
283static void fbnic_get_rxb_fifo_stats32(struct fbnic_dev *fbd, int i,
284				       struct fbnic_rxb_fifo_stats *fifo)
285{
286	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_DROP_FRMS_STS(i),
287			   &fifo->drop.frames);
288	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_TRUN_FRMS_STS(i),
289			   &fifo->trunc.frames);
290
291	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_TRANS_DROP_STS(i),
292			   &fifo->trans_drop);
293	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_TRANS_ECN_STS(i),
294			   &fifo->trans_ecn);
295
296	fifo->level.value = rd32(fbd, FBNIC_RXB_PBUF_FIFO_LEVEL(i));
297}
298
299static void fbnic_get_rxb_fifo_stats(struct fbnic_dev *fbd, int i,
300				     struct fbnic_rxb_fifo_stats *fifo)
301{
302	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_DROP_BYTES_STS_L(i), 1,
303			   &fifo->drop.bytes);
304	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_TRUN_BYTES_STS_L(i), 1,
305			   &fifo->trunc.bytes);
306
307	fbnic_get_rxb_fifo_stats32(fbd, i, fifo);
308}
309
310static void fbnic_get_rxb_enq_stats32(struct fbnic_dev *fbd, int i,
311				      struct fbnic_rxb_enqueue_stats *enq)
312{
313	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_DRBO_FRM_CNT_SRC(i),
314			   &enq->drbo.frames);
315
316	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_INTEGRITY_ERR(i),
317			   &enq->integrity_err);
318	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_MAC_ERR(i),
319			   &enq->mac_err);
320	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_PARSER_ERR(i),
321			   &enq->parser_err);
322	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_FRM_ERR(i),
323			   &enq->frm_err);
324}
325
326static void fbnic_get_rxb_enq_stats(struct fbnic_dev *fbd, int i,
327				    struct fbnic_rxb_enqueue_stats *enq)
328{
329	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_DRBO_BYTE_CNT_SRC_L(i), 4,
330			   &enq->drbo.bytes);
331
332	fbnic_get_rxb_enq_stats32(fbd, i, enq);
333}
334
335static void fbnic_get_rxb_deq_stats32(struct fbnic_dev *fbd, int i,
336				      struct fbnic_rxb_dequeue_stats *deq)
337{
338	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_INTF_FRM_CNT_DST(i),
339			   &deq->intf.frames);
340	fbnic_hw_stat_rd32(fbd, FBNIC_RXB_PBUF_FRM_CNT_DST(i),
341			   &deq->pbuf.frames);
342}
343
344static void fbnic_get_rxb_deq_stats(struct fbnic_dev *fbd, int i,
345				    struct fbnic_rxb_dequeue_stats *deq)
346{
347	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_INTF_BYTE_CNT_DST_L(i), 4,
348			   &deq->intf.bytes);
349	fbnic_hw_stat_rd64(fbd, FBNIC_RXB_PBUF_BYTE_CNT_DST_L(i), 4,
350			   &deq->pbuf.bytes);
351
352	fbnic_get_rxb_deq_stats32(fbd, i, deq);
353}
354
355static void fbnic_get_rxb_stats32(struct fbnic_dev *fbd,
356				  struct fbnic_rxb_stats *rxb)
357{
358	int i;
359
360	for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++)
361		fbnic_get_rxb_fifo_stats32(fbd, i, &rxb->fifo[i]);
362
363	for (i = 0; i < FBNIC_RXB_INTF_INDICES; i++) {
364		fbnic_get_rxb_enq_stats32(fbd, i, &rxb->enq[i]);
365		fbnic_get_rxb_deq_stats32(fbd, i, &rxb->deq[i]);
366	}
367}
368
369static void fbnic_get_rxb_stats(struct fbnic_dev *fbd,
370				struct fbnic_rxb_stats *rxb)
371{
372	int i;
373
374	for (i = 0; i < FBNIC_RXB_FIFO_INDICES; i++)
375		fbnic_get_rxb_fifo_stats(fbd, i, &rxb->fifo[i]);
376
377	for (i = 0; i < FBNIC_RXB_INTF_INDICES; i++) {
378		fbnic_get_rxb_enq_stats(fbd, i, &rxb->enq[i]);
379		fbnic_get_rxb_deq_stats(fbd, i, &rxb->deq[i]);
380	}
381}
382
383static void fbnic_reset_hw_rxq_stats(struct fbnic_dev *fbd,
384				     struct fbnic_hw_q_stats *hw_q)
385{
386	int i;
387
388	for (i = 0; i < fbd->max_num_queues; i++, hw_q++) {
389		u32 base = FBNIC_QUEUE(i);
390
391		fbnic_hw_stat_rst32(fbd,
392				    base + FBNIC_QUEUE_RDE_PKT_ERR_CNT,
393				    &hw_q->rde_pkt_err);
394		fbnic_hw_stat_rst32(fbd,
395				    base + FBNIC_QUEUE_RDE_CQ_DROP_CNT,
396				    &hw_q->rde_pkt_cq_drop);
397		fbnic_hw_stat_rst32(fbd,
398				    base + FBNIC_QUEUE_RDE_BDQ_DROP_CNT,
399				    &hw_q->rde_pkt_bdq_drop);
400	}
401}
402
403static void fbnic_get_hw_rxq_stats32(struct fbnic_dev *fbd,
404				     struct fbnic_hw_q_stats *hw_q)
405{
406	int i;
407
408	for (i = 0; i < fbd->max_num_queues; i++, hw_q++) {
409		u32 base = FBNIC_QUEUE(i);
410
411		fbnic_hw_stat_rd32(fbd,
412				   base + FBNIC_QUEUE_RDE_PKT_ERR_CNT,
413				   &hw_q->rde_pkt_err);
414		fbnic_hw_stat_rd32(fbd,
415				   base + FBNIC_QUEUE_RDE_CQ_DROP_CNT,
416				   &hw_q->rde_pkt_cq_drop);
417		fbnic_hw_stat_rd32(fbd,
418				   base + FBNIC_QUEUE_RDE_BDQ_DROP_CNT,
419				   &hw_q->rde_pkt_bdq_drop);
420	}
421}
422
423void fbnic_get_hw_q_stats(struct fbnic_dev *fbd,
424			  struct fbnic_hw_q_stats *hw_q)
425{
426	spin_lock(&fbd->hw_stats.lock);
427	fbnic_get_hw_rxq_stats32(fbd, hw_q);
428	spin_unlock(&fbd->hw_stats.lock);
429}
430
431static void fbnic_reset_pcie_stats_asic(struct fbnic_dev *fbd,
432					struct fbnic_pcie_stats *pcie)
433{
434	fbnic_hw_stat_rst64(fbd,
435			    FBNIC_PUL_USER_OB_RD_TLP_CNT_31_0,
436			    1,
437			    &pcie->ob_rd_tlp);
438	fbnic_hw_stat_rst64(fbd,
439			    FBNIC_PUL_USER_OB_RD_DWORD_CNT_31_0,
440			    1,
441			    &pcie->ob_rd_dword);
442	fbnic_hw_stat_rst64(fbd,
443			    FBNIC_PUL_USER_OB_CPL_TLP_CNT_31_0,
444			    1,
445			    &pcie->ob_cpl_tlp);
446	fbnic_hw_stat_rst64(fbd,
447			    FBNIC_PUL_USER_OB_CPL_DWORD_CNT_31_0,
448			    1,
449			    &pcie->ob_cpl_dword);
450	fbnic_hw_stat_rst64(fbd,
451			    FBNIC_PUL_USER_OB_WR_TLP_CNT_31_0,
452			    1,
453			    &pcie->ob_wr_tlp);
454	fbnic_hw_stat_rst64(fbd,
455			    FBNIC_PUL_USER_OB_WR_DWORD_CNT_31_0,
456			    1,
457			    &pcie->ob_wr_dword);
458
459	fbnic_hw_stat_rst64(fbd,
460			    FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_31_0,
461			    1,
462			    &pcie->ob_rd_no_tag);
463	fbnic_hw_stat_rst64(fbd,
464			    FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_31_0,
465			    1,
466			    &pcie->ob_rd_no_cpl_cred);
467	fbnic_hw_stat_rst64(fbd,
468			    FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_31_0,
469			    1,
470			    &pcie->ob_rd_no_np_cred);
471}
472
473static void fbnic_get_pcie_stats_asic64(struct fbnic_dev *fbd,
474					struct fbnic_pcie_stats *pcie)
475{
476	fbnic_hw_stat_rd64(fbd,
477			   FBNIC_PUL_USER_OB_RD_TLP_CNT_31_0,
478			   1,
479			   &pcie->ob_rd_tlp);
480	fbnic_hw_stat_rd64(fbd,
481			   FBNIC_PUL_USER_OB_RD_DWORD_CNT_31_0,
482			   1,
483			   &pcie->ob_rd_dword);
484	fbnic_hw_stat_rd64(fbd,
485			   FBNIC_PUL_USER_OB_WR_TLP_CNT_31_0,
486			   1,
487			   &pcie->ob_wr_tlp);
488	fbnic_hw_stat_rd64(fbd,
489			   FBNIC_PUL_USER_OB_WR_DWORD_CNT_31_0,
490			   1,
491			   &pcie->ob_wr_dword);
492	fbnic_hw_stat_rd64(fbd,
493			   FBNIC_PUL_USER_OB_CPL_TLP_CNT_31_0,
494			   1,
495			   &pcie->ob_cpl_tlp);
496	fbnic_hw_stat_rd64(fbd,
497			   FBNIC_PUL_USER_OB_CPL_DWORD_CNT_31_0,
498			   1,
499			   &pcie->ob_cpl_dword);
500
501	fbnic_hw_stat_rd64(fbd,
502			   FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_31_0,
503			   1,
504			   &pcie->ob_rd_no_tag);
505	fbnic_hw_stat_rd64(fbd,
506			   FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_31_0,
507			   1,
508			   &pcie->ob_rd_no_cpl_cred);
509	fbnic_hw_stat_rd64(fbd,
510			   FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_31_0,
511			   1,
512			   &pcie->ob_rd_no_np_cred);
513}
514
515static void fbnic_reset_phy_stats(struct fbnic_dev *fbd,
516				  struct fbnic_phy_stats *phy_stats)
517{
518	const struct fbnic_mac *mac = fbd->mac;
519
520	mac->get_fec_stats(fbd, true, &phy_stats->fec);
521	mac->get_pcs_stats(fbd, true, &phy_stats->pcs);
522}
523
524static void fbnic_get_phy_stats32(struct fbnic_dev *fbd,
525				  struct fbnic_phy_stats *phy_stats)
526{
527	const struct fbnic_mac *mac = fbd->mac;
528
529	mac->get_fec_stats(fbd, false, &phy_stats->fec);
530	mac->get_pcs_stats(fbd, false, &phy_stats->pcs);
531}
532
533static void fbnic_reset_hw_mac_stats(struct fbnic_dev *fbd,
534				     struct fbnic_mac_stats *mac_stats)
535{
536	const struct fbnic_mac *mac = fbd->mac;
537
538	mac->get_eth_mac_stats(fbd, true, &mac_stats->eth_mac);
539	mac->get_pause_stats(fbd, true, &mac_stats->pause);
540	mac->get_eth_ctrl_stats(fbd, true, &mac_stats->eth_ctrl);
541	mac->get_rmon_stats(fbd, true, &mac_stats->rmon);
542}
543
544void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
545{
546	spin_lock(&fbd->hw_stats.lock);
547	fbnic_reset_phy_stats(fbd, &fbd->hw_stats.phy);
548	fbnic_reset_tmi_stats(fbd, &fbd->hw_stats.tmi);
549	fbnic_reset_tti_stats(fbd, &fbd->hw_stats.tti);
550	fbnic_reset_rpc_stats(fbd, &fbd->hw_stats.rpc);
551	fbnic_reset_rxb_stats(fbd, &fbd->hw_stats.rxb);
552	fbnic_reset_hw_rxq_stats(fbd, fbd->hw_stats.hw_q);
553	fbnic_reset_pcie_stats_asic(fbd, &fbd->hw_stats.pcie);
554	spin_unlock(&fbd->hw_stats.lock);
555
556	/* Once registered, the only other access to MAC stats is via the
557	 * ethtool API which is protected by the rtnl_lock. The call to
558	 * fbnic_reset_hw_stats() during PCI recovery is also protected
559	 * by the rtnl_lock hence, we don't need the spinlock to access
560	 * the MAC stats.
561	 */
562	if (fbd->netdev)
563		ASSERT_RTNL();
564	fbnic_reset_hw_mac_stats(fbd, &fbd->hw_stats.mac);
565}
566
567void fbnic_init_hw_stats(struct fbnic_dev *fbd)
568{
569	spin_lock_init(&fbd->hw_stats.lock);
570
571	fbnic_reset_hw_stats(fbd);
572}
573
574static void __fbnic_get_hw_stats32(struct fbnic_dev *fbd)
575{
576	fbnic_get_phy_stats32(fbd, &fbd->hw_stats.phy);
577	fbnic_get_tmi_stats32(fbd, &fbd->hw_stats.tmi);
578	fbnic_get_tti_stats32(fbd, &fbd->hw_stats.tti);
579	fbnic_get_rpc_stats32(fbd, &fbd->hw_stats.rpc);
580	fbnic_get_rxb_stats32(fbd, &fbd->hw_stats.rxb);
581	fbnic_get_hw_rxq_stats32(fbd, fbd->hw_stats.hw_q);
582}
583
584void fbnic_get_hw_stats32(struct fbnic_dev *fbd)
585{
586	spin_lock(&fbd->hw_stats.lock);
587	__fbnic_get_hw_stats32(fbd);
588	spin_unlock(&fbd->hw_stats.lock);
589}
590
591void fbnic_get_hw_stats(struct fbnic_dev *fbd)
592{
593	spin_lock(&fbd->hw_stats.lock);
594	__fbnic_get_hw_stats32(fbd);
595
596	fbnic_get_tmi_stats(fbd, &fbd->hw_stats.tmi);
597	fbnic_get_tti_stats(fbd, &fbd->hw_stats.tti);
598	fbnic_get_rxb_stats(fbd, &fbd->hw_stats.rxb);
599	fbnic_get_pcie_stats_asic64(fbd, &fbd->hw_stats.pcie);
600	spin_unlock(&fbd->hw_stats.lock);
601}
~/ Read-only file preview.