xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_hw_stats.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3 
4 #include "fbnic.h"
5 
6 static void fbnic_hw_stat_rst32(struct fbnic_dev *fbd, u32 reg,
7 				struct fbnic_stat_counter *stat)
8 {
9 	/* We do not touch the "value" field here.
10 	 * It gets zeroed out on fbd structure allocation.
11 	 * After that we want it to grow continuously
12 	 * through device resets and power state changes.
13 	 */
14 	stat->u.old_reg_value_32 = rd32(fbd, reg);
15 }
16 
17 static void fbnic_hw_stat_rd32(struct fbnic_dev *fbd, u32 reg,
18 			       struct fbnic_stat_counter *stat)
19 {
20 	u32 new_reg_value;
21 
22 	new_reg_value = rd32(fbd, reg);
23 	stat->value += new_reg_value - stat->u.old_reg_value_32;
24 	stat->u.old_reg_value_32 = new_reg_value;
25 }
26 
27 u64 fbnic_stat_rd64(struct fbnic_dev *fbd, u32 reg, u32 offset)
28 {
29 	u32 prev_upper, upper, lower, diff;
30 
31 	prev_upper = rd32(fbd, reg + offset);
32 	lower = rd32(fbd, reg);
33 	upper = rd32(fbd, reg + offset);
34 
35 	diff = upper - prev_upper;
36 	if (!diff)
37 		return ((u64)upper << 32) | lower;
38 
39 	if (diff > 1)
40 		dev_warn_once(fbd->dev,
41 			      "Stats inconsistent, upper 32b of %#010x updating too quickly\n",
42 			      reg * 4);
43 
44 	/* Return only the upper bits as we cannot guarantee
45 	 * the accuracy of the lower bits. We will add them in
46 	 * when the counter slows down enough that we can get
47 	 * a snapshot with both upper values being the same
48 	 * between reads.
49 	 */
50 	return ((u64)upper << 32);
51 }
52 
53 static void fbnic_hw_stat_rst64(struct fbnic_dev *fbd, u32 reg, s32 offset,
54 				struct fbnic_stat_counter *stat)
55 {
56 	/* Record initial counter values and compute deltas from there to ensure
57 	 * stats start at 0 after reboot/reset. This avoids exposing absolute
58 	 * hardware counter values to userspace.
59 	 */
60 	stat->u.old_reg_value_64 = fbnic_stat_rd64(fbd, reg, offset);
61 }
62 
63 static void fbnic_hw_stat_rd64(struct fbnic_dev *fbd, u32 reg, s32 offset,
64 			       struct fbnic_stat_counter *stat)
65 {
66 	u64 new_reg_value;
67 
68 	new_reg_value = fbnic_stat_rd64(fbd, reg, offset);
69 	stat->value += new_reg_value - stat->u.old_reg_value_64;
70 	stat->u.old_reg_value_64 = new_reg_value;
71 }
72 
73 static void fbnic_reset_rpc_stats(struct fbnic_dev *fbd,
74 				  struct fbnic_rpc_stats *rpc)
75 {
76 	fbnic_hw_stat_rst32(fbd,
77 			    FBNIC_RPC_CNTR_UNKN_ETYPE,
78 			    &rpc->unkn_etype);
79 	fbnic_hw_stat_rst32(fbd,
80 			    FBNIC_RPC_CNTR_UNKN_EXT_HDR,
81 			    &rpc->unkn_ext_hdr);
82 	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV4_FRAG, &rpc->ipv4_frag);
83 	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV6_FRAG, &rpc->ipv6_frag);
84 	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV4_ESP, &rpc->ipv4_esp);
85 	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_IPV6_ESP, &rpc->ipv6_esp);
86 	fbnic_hw_stat_rst32(fbd, FBNIC_RPC_CNTR_TCP_OPT_ERR, &rpc->tcp_opt_err);
87 	fbnic_hw_stat_rst32(fbd,
88 			    FBNIC_RPC_CNTR_OUT_OF_HDR_ERR,
89 			    &rpc->out_of_hdr_err);
90 	fbnic_hw_stat_rst32(fbd,
91 			    FBNIC_RPC_CNTR_OVR_SIZE_ERR,
92 			    &rpc->ovr_size_err);
93 }
94 
95 static void fbnic_get_rpc_stats32(struct fbnic_dev *fbd,
96 				  struct fbnic_rpc_stats *rpc)
97 {
98 	fbnic_hw_stat_rd32(fbd,
99 			   FBNIC_RPC_CNTR_UNKN_ETYPE,
100 			   &rpc->unkn_etype);
101 	fbnic_hw_stat_rd32(fbd,
102 			   FBNIC_RPC_CNTR_UNKN_EXT_HDR,
103 			   &rpc->unkn_ext_hdr);
104 
105 	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV4_FRAG, &rpc->ipv4_frag);
106 	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV6_FRAG, &rpc->ipv6_frag);
107 
108 	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV4_ESP, &rpc->ipv4_esp);
109 	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_IPV6_ESP, &rpc->ipv6_esp);
110 
111 	fbnic_hw_stat_rd32(fbd, FBNIC_RPC_CNTR_TCP_OPT_ERR, &rpc->tcp_opt_err);
112 	fbnic_hw_stat_rd32(fbd,
113 			   FBNIC_RPC_CNTR_OUT_OF_HDR_ERR,
114 			   &rpc->out_of_hdr_err);
115 	fbnic_hw_stat_rd32(fbd,
116 			   FBNIC_RPC_CNTR_OVR_SIZE_ERR,
117 			   &rpc->ovr_size_err);
118 }
119 
120 static void fbnic_reset_pcie_stats_asic(struct fbnic_dev *fbd,
121 					struct fbnic_pcie_stats *pcie)
122 {
123 	fbnic_hw_stat_rst64(fbd,
124 			    FBNIC_PUL_USER_OB_RD_TLP_CNT_31_0,
125 			    1,
126 			    &pcie->ob_rd_tlp);
127 	fbnic_hw_stat_rst64(fbd,
128 			    FBNIC_PUL_USER_OB_RD_DWORD_CNT_31_0,
129 			    1,
130 			    &pcie->ob_rd_dword);
131 	fbnic_hw_stat_rst64(fbd,
132 			    FBNIC_PUL_USER_OB_CPL_TLP_CNT_31_0,
133 			    1,
134 			    &pcie->ob_cpl_tlp);
135 	fbnic_hw_stat_rst64(fbd,
136 			    FBNIC_PUL_USER_OB_CPL_DWORD_CNT_31_0,
137 			    1,
138 			    &pcie->ob_cpl_dword);
139 	fbnic_hw_stat_rst64(fbd,
140 			    FBNIC_PUL_USER_OB_WR_TLP_CNT_31_0,
141 			    1,
142 			    &pcie->ob_wr_tlp);
143 	fbnic_hw_stat_rst64(fbd,
144 			    FBNIC_PUL_USER_OB_WR_DWORD_CNT_31_0,
145 			    1,
146 			    &pcie->ob_wr_dword);
147 
148 	fbnic_hw_stat_rst64(fbd,
149 			    FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_31_0,
150 			    1,
151 			    &pcie->ob_rd_no_tag);
152 	fbnic_hw_stat_rst64(fbd,
153 			    FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_31_0,
154 			    1,
155 			    &pcie->ob_rd_no_cpl_cred);
156 	fbnic_hw_stat_rst64(fbd,
157 			    FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_31_0,
158 			    1,
159 			    &pcie->ob_rd_no_np_cred);
160 }
161 
162 static void fbnic_get_pcie_stats_asic64(struct fbnic_dev *fbd,
163 					struct fbnic_pcie_stats *pcie)
164 {
165 	fbnic_hw_stat_rd64(fbd,
166 			   FBNIC_PUL_USER_OB_RD_TLP_CNT_31_0,
167 			   1,
168 			   &pcie->ob_rd_tlp);
169 	fbnic_hw_stat_rd64(fbd,
170 			   FBNIC_PUL_USER_OB_RD_DWORD_CNT_31_0,
171 			   1,
172 			   &pcie->ob_rd_dword);
173 	fbnic_hw_stat_rd64(fbd,
174 			   FBNIC_PUL_USER_OB_WR_TLP_CNT_31_0,
175 			   1,
176 			   &pcie->ob_wr_tlp);
177 	fbnic_hw_stat_rd64(fbd,
178 			   FBNIC_PUL_USER_OB_WR_DWORD_CNT_31_0,
179 			   1,
180 			   &pcie->ob_wr_dword);
181 	fbnic_hw_stat_rd64(fbd,
182 			   FBNIC_PUL_USER_OB_CPL_TLP_CNT_31_0,
183 			   1,
184 			   &pcie->ob_cpl_tlp);
185 	fbnic_hw_stat_rd64(fbd,
186 			   FBNIC_PUL_USER_OB_CPL_DWORD_CNT_31_0,
187 			   1,
188 			   &pcie->ob_cpl_dword);
189 
190 	fbnic_hw_stat_rd64(fbd,
191 			   FBNIC_PUL_USER_OB_RD_DBG_CNT_TAG_31_0,
192 			   1,
193 			   &pcie->ob_rd_no_tag);
194 	fbnic_hw_stat_rd64(fbd,
195 			   FBNIC_PUL_USER_OB_RD_DBG_CNT_CPL_CRED_31_0,
196 			   1,
197 			   &pcie->ob_rd_no_cpl_cred);
198 	fbnic_hw_stat_rd64(fbd,
199 			   FBNIC_PUL_USER_OB_RD_DBG_CNT_NP_CRED_31_0,
200 			   1,
201 			   &pcie->ob_rd_no_np_cred);
202 }
203 
204 void fbnic_reset_hw_stats(struct fbnic_dev *fbd)
205 {
206 	fbnic_reset_rpc_stats(fbd, &fbd->hw_stats.rpc);
207 	fbnic_reset_pcie_stats_asic(fbd, &fbd->hw_stats.pcie);
208 }
209 
210 void fbnic_get_hw_stats32(struct fbnic_dev *fbd)
211 {
212 	fbnic_get_rpc_stats32(fbd, &fbd->hw_stats.rpc);
213 }
214 
215 void fbnic_get_hw_stats(struct fbnic_dev *fbd)
216 {
217 	fbnic_get_hw_stats32(fbd);
218 
219 	fbnic_get_pcie_stats_asic64(fbd, &fbd->hw_stats.pcie);
220 }
221