net/octeontx2: support flow API flags based extraction
[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 void
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         otx2_mbox_alloc_msg_nix_stats_rst(mbox);
141         otx2_mbox_process(mbox);
142 }
143
144 int
145 otx2_nix_queue_stats_mapping(struct rte_eth_dev *eth_dev, uint16_t queue_id,
146                              uint8_t stat_idx, uint8_t is_rx)
147 {
148         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
149
150         if (is_rx)
151                 dev->rxmap[stat_idx] = ((1U << 31) | queue_id);
152         else
153                 dev->txmap[stat_idx] = ((1U << 31) | queue_id);
154
155         return 0;
156 }
157
158 int
159 otx2_nix_xstats_get(struct rte_eth_dev *eth_dev,
160                     struct rte_eth_xstat *xstats,
161                     unsigned int n)
162 {
163         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
164         unsigned int i, count = 0;
165         uint64_t reg, val;
166
167         if (n < OTX2_NIX_NUM_XSTATS_REG)
168                 return OTX2_NIX_NUM_XSTATS_REG;
169
170         if (xstats == NULL)
171                 return 0;
172
173         for (i = 0; i < OTX2_NIX_NUM_TX_XSTATS; i++) {
174                 xstats[count].value = otx2_read64(dev->base +
175                 NIX_LF_TX_STATX(nix_tx_xstats[i].offset));
176                 xstats[count].id = count;
177                 count++;
178         }
179
180         for (i = 0; i < OTX2_NIX_NUM_RX_XSTATS; i++) {
181                 xstats[count].value = otx2_read64(dev->base +
182                 NIX_LF_RX_STATX(nix_rx_xstats[i].offset));
183                 xstats[count].id = count;
184                 count++;
185         }
186
187         for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
188                 reg = (((uint64_t)i) << 32);
189                 val = otx2_atomic64_add_nosync(reg, (int64_t *)(dev->base +
190                                                nix_q_xstats[0].offset));
191                 if (val & OP_ERR)
192                         val = 0;
193                 xstats[count].value += val;
194         }
195         xstats[count].id = count;
196         count++;
197
198         return count;
199 }
200
201 int
202 otx2_nix_xstats_get_names(struct rte_eth_dev *eth_dev,
203                           struct rte_eth_xstat_name *xstats_names,
204                           unsigned int limit)
205 {
206         unsigned int i, count = 0;
207
208         RTE_SET_USED(eth_dev);
209
210         if (limit < OTX2_NIX_NUM_XSTATS_REG && xstats_names != NULL)
211                 return -ENOMEM;
212
213         if (xstats_names) {
214                 for (i = 0; i < OTX2_NIX_NUM_TX_XSTATS; i++) {
215                         snprintf(xstats_names[count].name,
216                                  sizeof(xstats_names[count].name),
217                                  "%s", nix_tx_xstats[i].name);
218                         count++;
219                 }
220
221                 for (i = 0; i < OTX2_NIX_NUM_RX_XSTATS; i++) {
222                         snprintf(xstats_names[count].name,
223                                  sizeof(xstats_names[count].name),
224                                  "%s", nix_rx_xstats[i].name);
225                         count++;
226                 }
227
228                 for (i = 0; i < OTX2_NIX_NUM_QUEUE_XSTATS; i++) {
229                         snprintf(xstats_names[count].name,
230                                  sizeof(xstats_names[count].name),
231                                  "%s", nix_q_xstats[i].name);
232                         count++;
233                 }
234         }
235
236         return OTX2_NIX_NUM_XSTATS_REG;
237 }
238
239 int
240 otx2_nix_xstats_get_names_by_id(struct rte_eth_dev *eth_dev,
241                                 struct rte_eth_xstat_name *xstats_names,
242                                 const uint64_t *ids, unsigned int limit)
243 {
244         struct rte_eth_xstat_name xstats_names_copy[OTX2_NIX_NUM_XSTATS_REG];
245         uint16_t i;
246
247         if (limit < OTX2_NIX_NUM_XSTATS_REG && ids == NULL)
248                 return OTX2_NIX_NUM_XSTATS_REG;
249
250         if (limit > OTX2_NIX_NUM_XSTATS_REG)
251                 return -EINVAL;
252
253         if (xstats_names == NULL)
254                 return -ENOMEM;
255
256         otx2_nix_xstats_get_names(eth_dev, xstats_names_copy, limit);
257
258         for (i = 0; i < OTX2_NIX_NUM_XSTATS_REG; i++) {
259                 if (ids[i] >= OTX2_NIX_NUM_XSTATS_REG) {
260                         otx2_err("Invalid id value");
261                         return -EINVAL;
262                 }
263                 strncpy(xstats_names[i].name, xstats_names_copy[ids[i]].name,
264                         sizeof(xstats_names[i].name));
265         }
266
267         return limit;
268 }
269
270 int
271 otx2_nix_xstats_get_by_id(struct rte_eth_dev *eth_dev, const uint64_t *ids,
272                           uint64_t *values, unsigned int n)
273 {
274         struct rte_eth_xstat xstats[OTX2_NIX_NUM_XSTATS_REG];
275         uint16_t i;
276
277         if (n < OTX2_NIX_NUM_XSTATS_REG && ids == NULL)
278                 return OTX2_NIX_NUM_XSTATS_REG;
279
280         if (n > OTX2_NIX_NUM_XSTATS_REG)
281                 return -EINVAL;
282
283         if (values == NULL)
284                 return -ENOMEM;
285
286         otx2_nix_xstats_get(eth_dev, xstats, n);
287
288         for (i = 0; i < OTX2_NIX_NUM_XSTATS_REG; i++) {
289                 if (ids[i] >= OTX2_NIX_NUM_XSTATS_REG) {
290                         otx2_err("Invalid id value");
291                         return -EINVAL;
292                 }
293                 values[i] = xstats[ids[i]].value;
294         }
295
296         return n;
297 }
298
299 static void
300 nix_queue_stats_reset(struct rte_eth_dev *eth_dev)
301 {
302         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
303         struct otx2_mbox *mbox = dev->mbox;
304         struct nix_aq_enq_rsp *rsp;
305         struct nix_aq_enq_req *aq;
306         uint32_t i;
307         int rc;
308
309         for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
310                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
311                 aq->qidx = i;
312                 aq->ctype = NIX_AQ_CTYPE_RQ;
313                 aq->op = NIX_AQ_INSTOP_READ;
314                 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
315                 if (rc) {
316                         otx2_err("Failed to read rq context");
317                         return;
318                 }
319                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
320                 aq->qidx = i;
321                 aq->ctype = NIX_AQ_CTYPE_RQ;
322                 aq->op = NIX_AQ_INSTOP_WRITE;
323                 otx2_mbox_memcpy(&aq->rq, &rsp->rq, sizeof(rsp->rq));
324                 otx2_mbox_memset(&aq->rq_mask, 0, sizeof(aq->rq_mask));
325                 aq->rq.octs = 0;
326                 aq->rq.pkts = 0;
327                 aq->rq.drop_octs = 0;
328                 aq->rq.drop_pkts = 0;
329                 aq->rq.re_pkts = 0;
330
331                 aq->rq_mask.octs = ~(aq->rq_mask.octs);
332                 aq->rq_mask.pkts = ~(aq->rq_mask.pkts);
333                 aq->rq_mask.drop_octs = ~(aq->rq_mask.drop_octs);
334                 aq->rq_mask.drop_pkts = ~(aq->rq_mask.drop_pkts);
335                 aq->rq_mask.re_pkts = ~(aq->rq_mask.re_pkts);
336                 rc = otx2_mbox_process(mbox);
337                 if (rc) {
338                         otx2_err("Failed to write rq context");
339                         return;
340                 }
341         }
342
343         for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
344                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
345                 aq->qidx = i;
346                 aq->ctype = NIX_AQ_CTYPE_SQ;
347                 aq->op = NIX_AQ_INSTOP_READ;
348                 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
349                 if (rc) {
350                         otx2_err("Failed to read sq context");
351                         return;
352                 }
353                 aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
354                 aq->qidx = i;
355                 aq->ctype = NIX_AQ_CTYPE_SQ;
356                 aq->op = NIX_AQ_INSTOP_WRITE;
357                 otx2_mbox_memcpy(&aq->sq, &rsp->sq, sizeof(rsp->sq));
358                 otx2_mbox_memset(&aq->sq_mask, 0, sizeof(aq->sq_mask));
359                 aq->sq.octs = 0;
360                 aq->sq.pkts = 0;
361                 aq->sq.drop_octs = 0;
362                 aq->sq.drop_pkts = 0;
363
364                 aq->sq_mask.octs = ~(aq->sq_mask.octs);
365                 aq->sq_mask.pkts = ~(aq->sq_mask.pkts);
366                 aq->sq_mask.drop_octs = ~(aq->sq_mask.drop_octs);
367                 aq->sq_mask.drop_pkts = ~(aq->sq_mask.drop_pkts);
368                 rc = otx2_mbox_process(mbox);
369                 if (rc) {
370                         otx2_err("Failed to write sq context");
371                         return;
372                 }
373         }
374 }
375
376 void
377 otx2_nix_xstats_reset(struct rte_eth_dev *eth_dev)
378 {
379         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
380         struct otx2_mbox *mbox = dev->mbox;
381
382         otx2_mbox_alloc_msg_nix_stats_rst(mbox);
383         otx2_mbox_process(mbox);
384
385         /* Reset queue stats */
386         nix_queue_stats_reset(eth_dev);
387 }