1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
3 */
4
5 #include <inttypes.h>
6
7 #include "roc_api.h"
8 #include "roc_nix_xstats.h"
9 #include "roc_priv.h"
10
11 #define NIX_RX_STATS(val) plt_read64(nix->base + NIX_LF_RX_STATX(val))
12 #define NIX_TX_STATS(val) plt_read64(nix->base + NIX_LF_TX_STATX(val))
13
14 int
roc_nix_num_xstats_get(struct roc_nix * roc_nix)15 roc_nix_num_xstats_get(struct roc_nix *roc_nix)
16 {
17 if (roc_nix_is_vf_or_sdp(roc_nix))
18 return CNXK_NIX_NUM_XSTATS_REG;
19 else if (roc_model_is_cn9k())
20 return CNXK_NIX_NUM_XSTATS_CGX;
21
22 return CNXK_NIX_NUM_XSTATS_RPM;
23 }
24
25 int
roc_nix_stats_get(struct roc_nix * roc_nix,struct roc_nix_stats * stats)26 roc_nix_stats_get(struct roc_nix *roc_nix, struct roc_nix_stats *stats)
27 {
28 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
29
30 if (stats == NULL)
31 return NIX_ERR_PARAM;
32
33 stats->rx_octs = NIX_RX_STATS(NIX_STAT_LF_RX_RX_OCTS);
34 stats->rx_ucast = NIX_RX_STATS(NIX_STAT_LF_RX_RX_UCAST);
35 stats->rx_bcast = NIX_RX_STATS(NIX_STAT_LF_RX_RX_BCAST);
36 stats->rx_mcast = NIX_RX_STATS(NIX_STAT_LF_RX_RX_MCAST);
37 stats->rx_drop = NIX_RX_STATS(NIX_STAT_LF_RX_RX_DROP);
38 stats->rx_drop_octs = NIX_RX_STATS(NIX_STAT_LF_RX_RX_DROP_OCTS);
39 stats->rx_fcs = NIX_RX_STATS(NIX_STAT_LF_RX_RX_FCS);
40 stats->rx_err = NIX_RX_STATS(NIX_STAT_LF_RX_RX_ERR);
41 stats->rx_drop_bcast = NIX_RX_STATS(NIX_STAT_LF_RX_RX_DRP_BCAST);
42 stats->rx_drop_mcast = NIX_RX_STATS(NIX_STAT_LF_RX_RX_DRP_MCAST);
43 stats->rx_drop_l3_bcast = NIX_RX_STATS(NIX_STAT_LF_RX_RX_DRP_L3BCAST);
44 stats->rx_drop_l3_mcast = NIX_RX_STATS(NIX_STAT_LF_RX_RX_DRP_L3MCAST);
45
46 stats->tx_ucast = NIX_TX_STATS(NIX_STAT_LF_TX_TX_UCAST);
47 stats->tx_bcast = NIX_TX_STATS(NIX_STAT_LF_TX_TX_BCAST);
48 stats->tx_mcast = NIX_TX_STATS(NIX_STAT_LF_TX_TX_MCAST);
49 stats->tx_drop = NIX_TX_STATS(NIX_STAT_LF_TX_TX_DROP);
50 stats->tx_octs = NIX_TX_STATS(NIX_STAT_LF_TX_TX_OCTS);
51 return 0;
52 }
53
54 int
roc_nix_stats_reset(struct roc_nix * roc_nix)55 roc_nix_stats_reset(struct roc_nix *roc_nix)
56 {
57 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
58 struct mbox *mbox = (&nix->dev)->mbox;
59
60 if (mbox_alloc_msg_nix_stats_rst(mbox) == NULL)
61 return -ENOMEM;
62
63 return mbox_process(mbox);
64 }
65
66 static int
queue_is_valid(struct nix * nix,uint16_t qid,bool is_rx)67 queue_is_valid(struct nix *nix, uint16_t qid, bool is_rx)
68 {
69 uint16_t nb_queues;
70
71 if (is_rx)
72 nb_queues = nix->nb_rx_queues;
73 else
74 nb_queues = nix->nb_tx_queues;
75
76 if (qid >= nb_queues)
77 return NIX_ERR_QUEUE_INVALID_RANGE;
78
79 return 0;
80 }
81
82 static uint64_t
qstat_read(struct nix * nix,uint16_t qid,uint32_t off)83 qstat_read(struct nix *nix, uint16_t qid, uint32_t off)
84 {
85 uint64_t reg, val;
86 int64_t *addr;
87
88 addr = (int64_t *)(nix->base + off);
89 reg = (((uint64_t)qid) << 32);
90 val = roc_atomic64_add_nosync(reg, addr);
91 if (val & BIT_ULL(NIX_CQ_OP_STAT_OP_ERR))
92 val = 0;
93 return val;
94 }
95
96 static void
nix_stat_rx_queue_get(struct nix * nix,uint16_t qid,struct roc_nix_stats_queue * qstats)97 nix_stat_rx_queue_get(struct nix *nix, uint16_t qid,
98 struct roc_nix_stats_queue *qstats)
99 {
100 qstats->rx_pkts = qstat_read(nix, qid, NIX_LF_RQ_OP_PKTS);
101 qstats->rx_octs = qstat_read(nix, qid, NIX_LF_RQ_OP_OCTS);
102 qstats->rx_drop_pkts = qstat_read(nix, qid, NIX_LF_RQ_OP_DROP_PKTS);
103 qstats->rx_drop_octs = qstat_read(nix, qid, NIX_LF_RQ_OP_DROP_OCTS);
104 qstats->rx_error_pkts = qstat_read(nix, qid, NIX_LF_RQ_OP_RE_PKTS);
105 }
106
107 static void
nix_stat_tx_queue_get(struct nix * nix,uint16_t qid,struct roc_nix_stats_queue * qstats)108 nix_stat_tx_queue_get(struct nix *nix, uint16_t qid,
109 struct roc_nix_stats_queue *qstats)
110 {
111 qstats->tx_pkts = qstat_read(nix, qid, NIX_LF_SQ_OP_PKTS);
112 qstats->tx_octs = qstat_read(nix, qid, NIX_LF_SQ_OP_OCTS);
113 qstats->tx_drop_pkts = qstat_read(nix, qid, NIX_LF_SQ_OP_DROP_PKTS);
114 qstats->tx_drop_octs = qstat_read(nix, qid, NIX_LF_SQ_OP_DROP_OCTS);
115 }
116
117 static int
nix_stat_rx_queue_reset(struct nix * nix,uint16_t qid)118 nix_stat_rx_queue_reset(struct nix *nix, uint16_t qid)
119 {
120 struct mbox *mbox = (&nix->dev)->mbox;
121 int rc;
122
123 if (roc_model_is_cn9k()) {
124 struct nix_aq_enq_req *aq;
125
126 aq = mbox_alloc_msg_nix_aq_enq(mbox);
127 if (!aq)
128 return -ENOSPC;
129
130 aq->qidx = qid;
131 aq->ctype = NIX_AQ_CTYPE_RQ;
132 aq->op = NIX_AQ_INSTOP_WRITE;
133
134 aq->rq.octs = 0;
135 aq->rq.pkts = 0;
136 aq->rq.drop_octs = 0;
137 aq->rq.drop_pkts = 0;
138 aq->rq.re_pkts = 0;
139
140 aq->rq_mask.octs = ~(aq->rq_mask.octs);
141 aq->rq_mask.pkts = ~(aq->rq_mask.pkts);
142 aq->rq_mask.drop_octs = ~(aq->rq_mask.drop_octs);
143 aq->rq_mask.drop_pkts = ~(aq->rq_mask.drop_pkts);
144 aq->rq_mask.re_pkts = ~(aq->rq_mask.re_pkts);
145 } else {
146 struct nix_cn10k_aq_enq_req *aq;
147
148 aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
149 if (!aq)
150 return -ENOSPC;
151
152 aq->qidx = qid;
153 aq->ctype = NIX_AQ_CTYPE_RQ;
154 aq->op = NIX_AQ_INSTOP_WRITE;
155
156 aq->rq.octs = 0;
157 aq->rq.pkts = 0;
158 aq->rq.drop_octs = 0;
159 aq->rq.drop_pkts = 0;
160 aq->rq.re_pkts = 0;
161
162 aq->rq_mask.octs = ~(aq->rq_mask.octs);
163 aq->rq_mask.pkts = ~(aq->rq_mask.pkts);
164 aq->rq_mask.drop_octs = ~(aq->rq_mask.drop_octs);
165 aq->rq_mask.drop_pkts = ~(aq->rq_mask.drop_pkts);
166 aq->rq_mask.re_pkts = ~(aq->rq_mask.re_pkts);
167 }
168
169 rc = mbox_process(mbox);
170 return rc ? NIX_ERR_AQ_WRITE_FAILED : 0;
171 }
172
173 static int
nix_stat_tx_queue_reset(struct nix * nix,uint16_t qid)174 nix_stat_tx_queue_reset(struct nix *nix, uint16_t qid)
175 {
176 struct mbox *mbox = (&nix->dev)->mbox;
177 int rc;
178
179 if (roc_model_is_cn9k()) {
180 struct nix_aq_enq_req *aq;
181
182 aq = mbox_alloc_msg_nix_aq_enq(mbox);
183 if (!aq)
184 return -ENOSPC;
185
186 aq->qidx = qid;
187 aq->ctype = NIX_AQ_CTYPE_SQ;
188 aq->op = NIX_AQ_INSTOP_WRITE;
189 aq->sq.octs = 0;
190 aq->sq.pkts = 0;
191 aq->sq.drop_octs = 0;
192 aq->sq.drop_pkts = 0;
193
194 aq->sq_mask.octs = ~(aq->sq_mask.octs);
195 aq->sq_mask.pkts = ~(aq->sq_mask.pkts);
196 aq->sq_mask.drop_octs = ~(aq->sq_mask.drop_octs);
197 aq->sq_mask.drop_pkts = ~(aq->sq_mask.drop_pkts);
198 } else {
199 struct nix_cn10k_aq_enq_req *aq;
200
201 aq = mbox_alloc_msg_nix_cn10k_aq_enq(mbox);
202 if (!aq)
203 return -ENOSPC;
204
205 aq->qidx = qid;
206 aq->ctype = NIX_AQ_CTYPE_SQ;
207 aq->op = NIX_AQ_INSTOP_WRITE;
208 aq->sq.octs = 0;
209 aq->sq.pkts = 0;
210 aq->sq.drop_octs = 0;
211 aq->sq.drop_pkts = 0;
212
213 aq->sq_mask.octs = ~(aq->sq_mask.octs);
214 aq->sq_mask.pkts = ~(aq->sq_mask.pkts);
215 aq->sq_mask.drop_octs = ~(aq->sq_mask.drop_octs);
216 aq->sq_mask.drop_pkts = ~(aq->sq_mask.drop_pkts);
217 }
218
219 rc = mbox_process(mbox);
220 return rc ? NIX_ERR_AQ_WRITE_FAILED : 0;
221 }
222
223 int
roc_nix_stats_queue_get(struct roc_nix * roc_nix,uint16_t qid,bool is_rx,struct roc_nix_stats_queue * qstats)224 roc_nix_stats_queue_get(struct roc_nix *roc_nix, uint16_t qid, bool is_rx,
225 struct roc_nix_stats_queue *qstats)
226 {
227 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
228 int rc;
229
230 if (qstats == NULL)
231 return NIX_ERR_PARAM;
232
233 rc = queue_is_valid(nix, qid, is_rx);
234 if (rc)
235 goto fail;
236
237 if (is_rx)
238 nix_stat_rx_queue_get(nix, qid, qstats);
239 else
240 nix_stat_tx_queue_get(nix, qid, qstats);
241
242 fail:
243 return rc;
244 }
245
246 int
roc_nix_stats_queue_reset(struct roc_nix * roc_nix,uint16_t qid,bool is_rx)247 roc_nix_stats_queue_reset(struct roc_nix *roc_nix, uint16_t qid, bool is_rx)
248 {
249 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
250 int rc;
251
252 rc = queue_is_valid(nix, qid, is_rx);
253 if (rc)
254 goto fail;
255
256 if (is_rx)
257 rc = nix_stat_rx_queue_reset(nix, qid);
258 else
259 rc = nix_stat_tx_queue_reset(nix, qid);
260
261 fail:
262 return rc;
263 }
264
265 int
roc_nix_xstats_get(struct roc_nix * roc_nix,struct roc_nix_xstat * xstats,unsigned int n)266 roc_nix_xstats_get(struct roc_nix *roc_nix, struct roc_nix_xstat *xstats,
267 unsigned int n)
268 {
269 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
270 struct mbox *mbox = (&nix->dev)->mbox;
271 struct cgx_stats_rsp *cgx_resp;
272 struct rpm_stats_rsp *rpm_resp;
273 uint64_t i, count = 0;
274 struct msg_req *req;
275 uint32_t xstat_cnt;
276 int rc;
277
278 xstat_cnt = roc_nix_num_xstats_get(roc_nix);
279 if (n < xstat_cnt)
280 return xstat_cnt;
281
282 if (xstats == NULL)
283 return -EINVAL;
284
285 memset(xstats, 0, (xstat_cnt * sizeof(*xstats)));
286 for (i = 0; i < CNXK_NIX_NUM_TX_XSTATS; i++) {
287 xstats[count].value = NIX_TX_STATS(nix_tx_xstats[i].offset);
288 xstats[count].id = count;
289 count++;
290 }
291
292 for (i = 0; i < CNXK_NIX_NUM_RX_XSTATS; i++) {
293 xstats[count].value = NIX_RX_STATS(nix_rx_xstats[i].offset);
294 xstats[count].id = count;
295 count++;
296 }
297
298 for (i = 0; i < nix->nb_rx_queues; i++)
299 xstats[count].value +=
300 qstat_read(nix, i, nix_q_xstats[0].offset);
301
302 xstats[count].id = count;
303 count++;
304
305 if (roc_nix_is_vf_or_sdp(roc_nix))
306 return count;
307
308 if (roc_model_is_cn9k()) {
309 req = mbox_alloc_msg_cgx_stats(mbox);
310 if (!req)
311 return -ENOSPC;
312
313 req->hdr.pcifunc = roc_nix_get_pf_func(roc_nix);
314
315 rc = mbox_process_msg(mbox, (void *)&cgx_resp);
316 if (rc)
317 return rc;
318
319 for (i = 0; i < roc_nix_num_rx_xstats(); i++) {
320 xstats[count].value =
321 cgx_resp->rx_stats[nix_rx_xstats_cgx[i].offset];
322 xstats[count].id = count;
323 count++;
324 }
325
326 for (i = 0; i < roc_nix_num_tx_xstats(); i++) {
327 xstats[count].value =
328 cgx_resp->tx_stats[nix_tx_xstats_cgx[i].offset];
329 xstats[count].id = count;
330 count++;
331 }
332 } else {
333 req = mbox_alloc_msg_rpm_stats(mbox);
334 if (!req)
335 return -ENOSPC;
336
337 req->hdr.pcifunc = roc_nix_get_pf_func(roc_nix);
338
339 rc = mbox_process_msg(mbox, (void *)&rpm_resp);
340 if (rc)
341 return rc;
342
343 for (i = 0; i < roc_nix_num_rx_xstats(); i++) {
344 xstats[count].value =
345 rpm_resp->rx_stats[nix_rx_xstats_rpm[i].offset];
346 xstats[count].id = count;
347 count++;
348 }
349
350 for (i = 0; i < roc_nix_num_tx_xstats(); i++) {
351 xstats[count].value =
352 rpm_resp->tx_stats[nix_tx_xstats_rpm[i].offset];
353 xstats[count].id = count;
354 count++;
355 }
356
357 for (i = 0; i < CNXK_NIX_NUM_CN10K_RX_XSTATS; i++) {
358 xstats[count].value =
359 NIX_RX_STATS(nix_cn10k_rx_xstats[i].offset);
360 xstats[count].id = count;
361 count++;
362 }
363 }
364
365 return count;
366 }
367
368 int
roc_nix_xstats_names_get(struct roc_nix * roc_nix,struct roc_nix_xstat_name * xstats_names,unsigned int limit)369 roc_nix_xstats_names_get(struct roc_nix *roc_nix,
370 struct roc_nix_xstat_name *xstats_names,
371 unsigned int limit)
372 {
373 uint64_t i, count = 0;
374 uint32_t xstat_cnt;
375
376 xstat_cnt = roc_nix_num_xstats_get(roc_nix);
377 if (limit < xstat_cnt && xstats_names != NULL)
378 return -ENOMEM;
379
380 if (xstats_names) {
381 for (i = 0; i < CNXK_NIX_NUM_TX_XSTATS; i++) {
382 snprintf(xstats_names[count].name,
383 sizeof(xstats_names[count].name), "%s",
384 nix_tx_xstats[i].name);
385 count++;
386 }
387
388 for (i = 0; i < CNXK_NIX_NUM_RX_XSTATS; i++) {
389 snprintf(xstats_names[count].name,
390 sizeof(xstats_names[count].name), "%s",
391 nix_rx_xstats[i].name);
392 count++;
393 }
394 for (i = 0; i < CNXK_NIX_NUM_QUEUE_XSTATS; i++) {
395 snprintf(xstats_names[count].name,
396 sizeof(xstats_names[count].name), "%s",
397 nix_q_xstats[i].name);
398 count++;
399 }
400
401 if (roc_nix_is_vf_or_sdp(roc_nix))
402 return count;
403
404 if (roc_model_is_cn9k()) {
405 for (i = 0; i < roc_nix_num_rx_xstats(); i++) {
406 snprintf(xstats_names[count].name,
407 sizeof(xstats_names[count].name), "%s",
408 nix_rx_xstats_cgx[i].name);
409 count++;
410 }
411
412 for (i = 0; i < roc_nix_num_tx_xstats(); i++) {
413 snprintf(xstats_names[count].name,
414 sizeof(xstats_names[count].name), "%s",
415 nix_tx_xstats_cgx[i].name);
416 count++;
417 }
418 } else {
419 for (i = 0; i < roc_nix_num_rx_xstats(); i++) {
420 snprintf(xstats_names[count].name,
421 sizeof(xstats_names[count].name), "%s",
422 nix_rx_xstats_rpm[i].name);
423 count++;
424 }
425
426 for (i = 0; i < roc_nix_num_tx_xstats(); i++) {
427 snprintf(xstats_names[count].name,
428 sizeof(xstats_names[count].name), "%s",
429 nix_tx_xstats_rpm[i].name);
430 count++;
431 }
432
433 for (i = 0; i < CNXK_NIX_NUM_CN10K_RX_XSTATS; i++) {
434 snprintf(xstats_names[count].name,
435 sizeof(xstats_names[count].name), "%s",
436 nix_cn10k_rx_xstats[i].name);
437 count++;
438 }
439 }
440 }
441
442 return xstat_cnt;
443 }
444