1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3
4 #include "fbnic.h"
5
fbnic_hw_stat_rst32(struct fbnic_dev * fbd,u32 reg,struct fbnic_stat_counter * stat)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
fbnic_hw_stat_rd32(struct fbnic_dev * fbd,u32 reg,struct fbnic_stat_counter * stat)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
fbnic_stat_rd64(struct fbnic_dev * fbd,u32 reg,u32 offset)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
fbnic_hw_stat_rst64(struct fbnic_dev * fbd,u32 reg,s32 offset,struct fbnic_stat_counter * stat)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
fbnic_hw_stat_rd64(struct fbnic_dev * fbd,u32 reg,s32 offset,struct fbnic_stat_counter * stat)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
fbnic_reset_rpc_stats(struct fbnic_dev * fbd,struct fbnic_rpc_stats * rpc)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
fbnic_get_rpc_stats32(struct fbnic_dev * fbd,struct fbnic_rpc_stats * rpc)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
fbnic_reset_pcie_stats_asic(struct fbnic_dev * fbd,struct fbnic_pcie_stats * pcie)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
fbnic_get_pcie_stats_asic64(struct fbnic_dev * fbd,struct fbnic_pcie_stats * pcie)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
fbnic_reset_hw_stats(struct fbnic_dev * fbd)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
fbnic_get_hw_stats32(struct fbnic_dev * fbd)210 void fbnic_get_hw_stats32(struct fbnic_dev *fbd)
211 {
212 fbnic_get_rpc_stats32(fbd, &fbd->hw_stats.rpc);
213 }
214
fbnic_get_hw_stats(struct fbnic_dev * fbd)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