xref: /dpdk/drivers/common/cnxk/roc_nix_stats.c (revision 8fbad405)
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