8aaf270a7ca369edef5c184b4c298537cce1bf9d
[dpdk.git] / drivers / net / octeontx2 / otx2_stats.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <inttypes.h>
6
7 #include "otx2_ethdev.h"
8
9 struct otx2_nix_xstats_name {
10         char name[RTE_ETH_XSTATS_NAME_SIZE];
11         uint32_t offset;
12 };
13
14 static const struct otx2_nix_xstats_name nix_tx_xstats[] = {
15         {"tx_ucast", NIX_STAT_LF_TX_TX_UCAST},
16         {"tx_bcast", NIX_STAT_LF_TX_TX_BCAST},
17         {"tx_mcast", NIX_STAT_LF_TX_TX_MCAST},
18         {"tx_drop", NIX_STAT_LF_TX_TX_DROP},
19         {"tx_octs", NIX_STAT_LF_TX_TX_OCTS},
20 };
21
22 static const struct otx2_nix_xstats_name nix_rx_xstats[] = {
23         {"rx_octs", NIX_STAT_LF_RX_RX_OCTS},
24         {"rx_ucast", NIX_STAT_LF_RX_RX_UCAST},
25         {"rx_bcast", NIX_STAT_LF_RX_RX_BCAST},
26         {"rx_mcast", NIX_STAT_LF_RX_RX_MCAST},
27         {"rx_drop", NIX_STAT_LF_RX_RX_DROP},
28         {"rx_drop_octs", NIX_STAT_LF_RX_RX_DROP_OCTS},
29         {"rx_fcs", NIX_STAT_LF_RX_RX_FCS},
30         {"rx_err", NIX_STAT_LF_RX_RX_ERR},
31         {"rx_drp_bcast", NIX_STAT_LF_RX_RX_DRP_BCAST},
32         {"rx_drp_mcast", NIX_STAT_LF_RX_RX_DRP_MCAST},
33         {"rx_drp_l3bcast", NIX_STAT_LF_RX_RX_DRP_L3BCAST},
34         {"rx_drp_l3mcast", NIX_STAT_LF_RX_RX_DRP_L3MCAST},
35 };
36
37 static const struct otx2_nix_xstats_name nix_q_xstats[] = {
38         {"rq_op_re_pkts", NIX_LF_RQ_OP_RE_PKTS},
39 };
40
41 #define OTX2_NIX_NUM_RX_XSTATS RTE_DIM(nix_rx_xstats)
42 #define OTX2_NIX_NUM_TX_XSTATS RTE_DIM(nix_tx_xstats)
43 #define OTX2_NIX_NUM_QUEUE_XSTATS RTE_DIM(nix_q_xstats)
44
45 #define OTX2_NIX_NUM_XSTATS_REG (OTX2_NIX_NUM_RX_XSTATS + \
46                 OTX2_NIX_NUM_TX_XSTATS + OTX2_NIX_NUM_QUEUE_XSTATS)
47
48 int
49 otx2_nix_dev_stats_get(struct rte_eth_dev *eth_dev,
50                        struct rte_eth_stats *stats)
51 {
52         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
53         uint64_t reg, val;
54         uint32_t qidx, i;
55         int64_t *addr;
56
57         stats->opackets = otx2_read64(dev->base +
58                         NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_UCAST));
59         stats->opackets += otx2_read64(dev->base +
60                         NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_MCAST));
61         stats->opackets += otx2_read64(dev->base +
62                         NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_BCAST));
63         stats->oerrors = otx2_read64(dev->base +
64                         NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_DROP));
65         stats->obytes = otx2_read64(dev->base +
66                         NIX_LF_TX_STATX(NIX_STAT_LF_TX_TX_OCTS));
67
68         stats->ipackets = otx2_read64(dev->base +
69                         NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_UCAST));
70         stats->ipackets += otx2_read64(dev->base +
71                         NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_MCAST));
72         stats->ipackets += otx2_read64(dev->base +
73                         NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_BCAST));
74         stats->imissed = otx2_read64(dev->base +
75                         NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_DROP));
76         stats->ibytes = otx2_read64(dev->base +
77                         NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_OCTS));
78         stats->ierrors = otx2_read64(dev->base +
79                         NIX_LF_RX_STATX(NIX_STAT_LF_RX_RX_ERR));
80
81         for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
82                 if (dev->txmap[i] & (1U << 31)) {
83                         qidx = dev->txmap[i] & 0xFFFF;
84                         reg = (((uint64_t)qidx) << 32);
85
86                         addr = (int64_t *)(dev->base + NIX_LF_SQ_OP_PKTS);
87                         val = otx2_atomic64_add_nosync(reg, addr);
88                         if (val & OP_ERR)
89                                 val = 0;
90                         stats->q_opackets[i] = val;
91
92                         addr = (int64_t *)(dev->base + NIX_LF_SQ_OP_OCTS);
93                         val = otx2_atomic64_add_nosync(reg, addr);
94                         if (val & OP_ERR)
95                                 val = 0;
96                         stats->q_obytes[i] = val;
97
98                         addr = (int64_t *)(dev->base + NIX_LF_SQ_OP_DROP_PKTS);
99                         val = otx2_atomic64_add_nosync(reg, addr);
100                         if (val & OP_ERR)
101                                 val = 0;
102                         stats->q_errors[i] = val;
103                 }
104         }
105
106         for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
107                 if (dev->rxmap[i] & (1U << 31)) {
108                         qidx = dev->rxmap[i] & 0xFFFF;
109                         reg = (((uint64_t)qidx) << 32);
110
111                         addr = (int64_t *)(dev->base + NIX_LF_RQ_OP_PKTS);
112                         val = otx2_atomic64_add_nosync(reg, addr);
113                         if (val & OP_ERR)
114                                 val = 0;
115                         stats->q_ipackets[i] = val;
116
117                         addr = (int64_t *)(dev->base + NIX_LF_RQ_OP_OCTS);
118                         val = otx2_atomic64_add_nosync(reg, addr);
119                         if (val & OP_ERR)
120                                 val = 0;
121                         stats->q_ibytes[i] = val;
122
123                         addr = (int64_t *)(dev->base + NIX_LF_RQ_OP_DROP_PKTS);
124                         val = otx2_atomic64_add_nosync(reg, addr);
125                         if (val & OP_ERR)
126                                 val = 0;
127                         stats->q_errors[i] += val;
128                 }
129         }
130
131         return 0;
132 }
133
134 int
135 otx2_nix_dev_stats_reset(struct rte_eth_dev *eth_dev)
136 {
137         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
138         struct otx2_mbox *mbox = dev->mbox;
139
140         if (otx2_mbox_alloc_msg_nix_stats_rst(mbox) == NULL)
141                 return -ENOMEM;
142
143         return otx2_mbox_process(mbox);
144 }
145
146 int
147 otx2_nix_queue_stats_mapping(struct rte_eth_dev *eth_dev, uint16_t queue_id,
148                              uint8_t stat_idx, uint8_t is_rx)
149 {
150         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
151
152         if (is_rx)
153                 dev->rxmap[stat_idx] = ((1U << 31) | queue_id);
154         else
155                 dev->txmap[stat_idx] = ((1U << 31) | queue_id);
156
157         return 0;
158 }
159
160 int
161 otx2_nix_xstats_get(struct rte_eth_dev *eth_dev,
162                     struct rte_eth_xstat *xstats,
163                     unsigned int n)
164 {
165         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
166         unsigned int i, count = 0;
167         uint64_t reg, val;
168
169         if (n < OTX2_NIX_NUM_XSTATS_REG)
170                 return OTX2_NIX_NUM_XSTATS_REG;
171
172         if (xstats == NULL)
173                 return 0;
174
175         for (i = 0; i < OTX2_NIX_NUM_TX_XSTATS; i++) {
176                 xstats[count].value = otx2_read64(dev->base +
177                 NIX_LF_TX_STATX(nix_tx_xstats[i].offset));
178                 xstats[count].id = count;
179                 count++;
180         }
181
182         for (i = 0; i < OTX2_NIX_NUM_RX_XSTATS; i++) {
183                 xstats[count].value = otx2_read64(dev->base +
184                 NIX_LF_RX_STATX(nix_rx_xstats[i].offset));
185                 xstats[count].id = count;
186                 count++;
187         }
188
189         for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
190                 reg = (((uint64_t)i) << 32);
191                 val = otx2_atomic64_add_nosync(reg, (int64_t *)(dev->base +
192                                                nix_q_xstats[0].offset));
193                 if (val & OP_ERR)
194                         val = 0;
195                 xstats[count].value += val;
196         }
197         xstats[count].id = count;
198         count++;
199
200         return count;
201 }
202
203 int
204 otx2_nix_xstats_get_names(struct rte_eth_dev *eth_dev,
205                           struct rte_eth_xstat_name *xstats_names,
206                           unsigned int limit)
207 {
208         unsigned int i, count = 0;
209
210         RTE_SET_USED(eth_dev);
211
212         if (limit < OTX2_NIX_NUM_XSTATS_REG && xstats_names != NULL)
213                 return -ENOMEM;
214
215         if (xstats_names) {
216                 for (i = 0; i < OTX2_NIX_NUM_TX_XSTATS; i++) {
217                         snprintf(xstats_names[count].name,
218                                  sizeof(xstats_names[count].name),
219                                  "%s", nix_tx_xstats[i].name);
220                         count++;
221                 }
222
223                 for (i = 0; i < OTX2_NIX_NUM_RX_XSTATS; i++) {
224                         snprintf(xstats_names[count].name,
225                                  sizeof(xstats_names[count].name),
226                                  "%s", nix_rx_xstats[i].name);
227                         count++;
228                 }
229
230                 for (i = 0; i < OTX2_NIX_NUM_QUEUE_XSTATS; i++) {
231                         snprintf(xstats_names[count].name,
232                                  sizeof(xstats_names[count].name),
233                                  "%s", nix_q_xstats[i].name);
234                         count++;
235                 }
236         }
237
238         return OTX2_NIX_NUM_XSTATS_REG;
239 }
240
241 int
242 otx2_nix_xstats_get_names_by_id(struct rte_eth_dev *eth_dev,
243                                 struct rte_eth_xstat_name *xstats_names,
244                                 const uint64_t *ids, unsigned int limit)
245 {
246         struct rte_eth_xstat_name xstats_names_copy[OTX2_NIX_NUM_XSTATS_REG];
247         uint16_t i;
248
249         if (limit < OTX2_NIX_NUM_XSTATS_REG && ids == NULL)
250                 return OTX2_NIX_NUM_XSTATS_REG;
251
252         if (limit > OTX2_NIX_NUM_XSTATS_REG)
253                 return -EINVAL;
254
255         if (xstats_names == NULL)
256                 return -ENOMEM;
257
258         otx2_nix_xstats_get_names(eth_dev, xstats_names_copy, limit);
259
260         for (i = 0; i < OTX2_NIX_NUM_XSTATS_REG; i++) {
261                 if (ids[i] >= OTX2_NIX_NUM_XSTATS_REG) {
262                         otx2_err("Invalid id value");
263                         return -EINVAL;
264                 }
265                 strncpy(xstats_names[i].name, xstats_names_copy[ids[i]].name,
266                         sizeof(xstats_names[i].name));
267         }
268
269         return limit;
270 }
271
272 int
273 otx2_nix_xstats_get_by_id(struct rte_eth_dev *eth_dev, const uint64_t *ids,
274                           uint64_t *values, unsigned int n)
275 {
276         struct rte_eth_xstat xstats[OTX2_NIX_NUM_XSTATS_REG];
277         uint16_t i;
278
279         if (n < OTX2_NIX_NUM_XSTATS_REG && ids == NULL)
280                 return OTX2_NIX_NUM_XSTATS_REG;
281
282         if (n > OTX2_NIX_NUM_XSTATS_REG)
283                 return -EINVAL;
284
285         if (values == NULL)
286                 return -ENOMEM;
287
288         otx2_nix_xstats_get(eth_dev, xstats, n);
289
290         for (i = 0; i < OTX2_NIX_NUM_XSTATS_REG; i++) {
291                 if (ids[i] >= OTX2_NIX_NUM_XSTATS_REG) {
292                         otx2_err("Invalid id value");
293                         return -EINVAL;
294                 }
295                 values[i] = xstats[ids[i]].value;
296         }
297
298         return n;
299 }
300
301 static int
302 nix_queue_stats_reset(struct rte_eth_dev *eth_dev)
303 {
304         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
305         struct otx2_mbox *mbox = dev->mbox;
306         struct nix_aq_enq_rsp *rsp;
307         struct nix_aq_enq_req *aq;
308         uint32_t i;
309         int rc;
310
311         for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
312                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
313                 aq->qidx = i;
314                 aq->ctype = NIX_AQ_CTYPE_RQ;
315                 aq->op = NIX_AQ_INSTOP_READ;
316                 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
317                 if (rc) {
318                         otx2_err("Failed to read rq context");
319                         return rc;
320                 }
321                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
322                 aq->qidx = i;
323                 aq->ctype = NIX_AQ_CTYPE_RQ;
324                 aq->op = NIX_AQ_INSTOP_WRITE;
325                 otx2_mbox_memcpy(&aq->rq, &rsp->rq, sizeof(rsp->rq));
326                 otx2_mbox_memset(&aq->rq_mask, 0, sizeof(aq->rq_mask));
327                 aq->rq.octs = 0;
328                 aq->rq.pkts = 0;
329                 aq->rq.drop_octs = 0;
330                 aq->rq.drop_pkts = 0;
331                 aq->rq.re_pkts = 0;
332
333                 aq->rq_mask.octs = ~(aq->rq_mask.octs);
334                 aq->rq_mask.pkts = ~(aq->rq_mask.pkts);
335                 aq->rq_mask.drop_octs = ~(aq->rq_mask.drop_octs);
336                 aq->rq_mask.drop_pkts = ~(aq->rq_mask.drop_pkts);
337                 aq->rq_mask.re_pkts = ~(aq->rq_mask.re_pkts);
338                 rc = otx2_mbox_process(mbox);
339                 if (rc) {
340                         otx2_err("Failed to write rq context");
341                         return rc;
342                 }
343         }
344
345         for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
346                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
347                 aq->qidx = i;
348                 aq->ctype = NIX_AQ_CTYPE_SQ;
349                 aq->op = NIX_AQ_INSTOP_READ;
350                 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
351                 if (rc) {
352                         otx2_err("Failed to read sq context");
353                         return rc;
354                 }
355                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
356                 aq->qidx = i;
357                 aq->ctype = NIX_AQ_CTYPE_SQ;
358                 aq->op = NIX_AQ_INSTOP_WRITE;
359                 otx2_mbox_memcpy(&aq->sq, &rsp->sq, sizeof(rsp->sq));
360                 otx2_mbox_memset(&aq->sq_mask, 0, sizeof(aq->sq_mask));
361                 aq->sq.octs = 0;
362                 aq->sq.pkts = 0;
363                 aq->sq.drop_octs = 0;
364                 aq->sq.drop_pkts = 0;
365
366                 aq->sq_mask.octs = ~(aq->sq_mask.octs);
367                 aq->sq_mask.pkts = ~(aq->sq_mask.pkts);
368                 aq->sq_mask.drop_octs = ~(aq->sq_mask.drop_octs);
369                 aq->sq_mask.drop_pkts = ~(aq->sq_mask.drop_pkts);
370                 rc = otx2_mbox_process(mbox);
371                 if (rc) {
372                         otx2_err("Failed to write sq context");
373                         return rc;
374                 }
375         }
376
377         return 0;
378 }
379
380 int
381 otx2_nix_xstats_reset(struct rte_eth_dev *eth_dev)
382 {
383         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
384         struct otx2_mbox *mbox = dev->mbox;
385         int ret;
386
387         if (otx2_mbox_alloc_msg_nix_stats_rst(mbox) == NULL)
388                 return -ENOMEM;
389
390         ret = otx2_mbox_process(mbox);
391         if (ret != 0)
392                 return ret;
393
394         /* Reset queue stats */
395         return nix_queue_stats_reset(eth_dev);
396 }