net/sfc: fix missing const of SW stats descriptions
[dpdk.git] / drivers / net / sfc / sfc_sw_stats.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2021 Xilinx, Inc.
4  */
5 #include <rte_dev.h>
6 #include <rte_bitmap.h>
7
8 #include "sfc.h"
9 #include "sfc_rx.h"
10 #include "sfc_tx.h"
11 #include "sfc_sw_stats.h"
12
13 enum sfc_sw_stats_type {
14         SFC_SW_STATS_RX,
15         SFC_SW_STATS_TX,
16 };
17
18 typedef uint64_t sfc_get_sw_stat_val_t(struct sfc_adapter *sa, uint16_t qid);
19
20 struct sfc_sw_stat_descr {
21         const char *name;
22         enum sfc_sw_stats_type type;
23         sfc_get_sw_stat_val_t *get_val;
24 };
25
26 static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_rx_dbells;
27 static uint64_t
28 sfc_get_sw_stat_val_rx_dbells(struct sfc_adapter *sa, uint16_t qid)
29 {
30         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
31         struct sfc_rxq_info *rxq_info;
32
33         rxq_info = sfc_rxq_info_by_ethdev_qid(sas, qid);
34         if (rxq_info->state & SFC_RXQ_INITIALIZED)
35                 return rxq_info->dp->dpq.rx_dbells;
36         return 0;
37 }
38
39 static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_tx_dbells;
40 static uint64_t
41 sfc_get_sw_stat_val_tx_dbells(struct sfc_adapter *sa, uint16_t qid)
42 {
43         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
44         struct sfc_txq_info *txq_info;
45
46         txq_info = sfc_txq_info_by_ethdev_qid(sas, qid);
47         if (txq_info->state & SFC_TXQ_INITIALIZED)
48                 return txq_info->dp->dpq.tx_dbells;
49         return 0;
50 }
51
52 const struct sfc_sw_stat_descr sfc_sw_stats_descr[] = {
53         {
54                 .name = "dbells",
55                 .type = SFC_SW_STATS_RX,
56                 .get_val  = sfc_get_sw_stat_val_rx_dbells,
57         },
58         {
59                 .name = "dbells",
60                 .type = SFC_SW_STATS_TX,
61                 .get_val  = sfc_get_sw_stat_val_tx_dbells,
62         }
63 };
64
65 static int
66 sfc_sw_stat_get_name(struct sfc_adapter *sa,
67                      const struct sfc_sw_stat_descr *sw_stat, char *name,
68                      size_t name_size, unsigned int id_off)
69 {
70         const char *prefix;
71         int ret;
72
73         switch (sw_stat->type) {
74         case SFC_SW_STATS_RX:
75                 prefix = "rx";
76                 break;
77         case SFC_SW_STATS_TX:
78                 prefix = "tx";
79                 break;
80         default:
81                 sfc_err(sa, "%s: unknown software statistics type %d",
82                         __func__, sw_stat->type);
83                 return -EINVAL;
84         }
85
86         if (id_off == 0) {
87                 ret = snprintf(name, name_size, "%s_%s", prefix,
88                                                          sw_stat->name);
89                 if (ret < 0 || ret >= (int)name_size) {
90                         sfc_err(sa, "%s: failed to fill xstat name %s_%s, err %d",
91                                 __func__, prefix, sw_stat->name, ret);
92                         return ret > 0 ? -EINVAL : ret;
93                 }
94         } else {
95                 uint16_t qid = id_off - 1;
96                 ret = snprintf(name, name_size, "%s_q%u_%s", prefix, qid,
97                                                         sw_stat->name);
98                 if (ret < 0 || ret >= (int)name_size) {
99                         sfc_err(sa, "%s: failed to fill xstat name %s_q%u_%s, err %d",
100                                 __func__, prefix, qid, sw_stat->name, ret);
101                         return ret > 0 ? -EINVAL : ret;
102                 }
103         }
104
105         return 0;
106 }
107
108 static unsigned int
109 sfc_sw_stat_get_queue_count(struct sfc_adapter *sa,
110                             const struct sfc_sw_stat_descr *sw_stat)
111 {
112         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
113
114         switch (sw_stat->type) {
115         case SFC_SW_STATS_RX:
116                 return sas->ethdev_rxq_count;
117         case SFC_SW_STATS_TX:
118                 return sas->ethdev_txq_count;
119         default:
120                 sfc_err(sa, "%s: unknown software statistics type %d",
121                         __func__, sw_stat->type);
122                 return 0;
123         }
124 }
125
126 static unsigned int
127 sfc_sw_xstat_per_queue_get_count(unsigned int nb_queues)
128 {
129         /* Take into account the total xstat of all queues */
130         return nb_queues > 0 ? 1 + nb_queues : 0;
131 }
132
133 static unsigned int
134 sfc_sw_xstat_get_nb_supported(struct sfc_adapter *sa,
135                               const struct sfc_sw_stat_descr *sw_stat)
136 {
137         unsigned int nb_queues;
138
139         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
140         return sfc_sw_xstat_per_queue_get_count(nb_queues);
141 }
142
143 static int
144 sfc_sw_stat_get_names(struct sfc_adapter *sa,
145                       const struct sfc_sw_stat_descr *sw_stat,
146                       struct rte_eth_xstat_name *xstats_names,
147                       unsigned int xstats_names_sz,
148                       unsigned int *nb_written,
149                       unsigned int *nb_supported)
150 {
151         const size_t name_size = sizeof(xstats_names[0].name);
152         unsigned int id_base = *nb_supported;
153         unsigned int nb_queues;
154         unsigned int qid;
155         int rc;
156
157         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
158         if (nb_queues == 0)
159                 return 0;
160         *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues);
161
162         /*
163          * The order of each software xstat type is the total xstat
164          * followed by per-queue xstats.
165          */
166         if (*nb_written < xstats_names_sz) {
167                 rc = sfc_sw_stat_get_name(sa, sw_stat,
168                                           xstats_names[*nb_written].name,
169                                           name_size, *nb_written - id_base);
170                 if (rc != 0)
171                         return rc;
172                 (*nb_written)++;
173         }
174
175         for (qid = 0; qid < nb_queues; ++qid) {
176                 if (*nb_written < xstats_names_sz) {
177                         rc = sfc_sw_stat_get_name(sa, sw_stat,
178                                               xstats_names[*nb_written].name,
179                                               name_size, *nb_written - id_base);
180                         if (rc != 0)
181                                 return rc;
182                         (*nb_written)++;
183                 }
184         }
185
186         return 0;
187 }
188
189 static int
190 sfc_sw_xstat_get_names_by_id(struct sfc_adapter *sa,
191                              const struct sfc_sw_stat_descr *sw_stat,
192                              const uint64_t *ids,
193                              struct rte_eth_xstat_name *xstats_names,
194                              unsigned int size,
195                              unsigned int *nb_supported)
196 {
197         const size_t name_size = sizeof(xstats_names[0].name);
198         unsigned int id_base = *nb_supported;
199         unsigned int nb_queues;
200         unsigned int i;
201         int rc;
202
203         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
204         if (nb_queues == 0)
205                 return 0;
206         *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues);
207
208         /*
209          * The order of each software xstat type is the total xstat
210          * followed by per-queue xstats.
211          */
212         for (i = 0; i < size; i++) {
213                 if (id_base <= ids[i] && ids[i] <= id_base + nb_queues) {
214                         rc = sfc_sw_stat_get_name(sa, sw_stat,
215                                                   xstats_names[i].name,
216                                                   name_size, ids[i] - id_base);
217                         if (rc != 0)
218                                 return rc;
219                 }
220         }
221
222         return 0;
223 }
224
225 static void
226 sfc_sw_xstat_get_values(struct sfc_adapter *sa,
227                         const struct sfc_sw_stat_descr *sw_stat,
228                         struct rte_eth_xstat *xstats,
229                         unsigned int xstats_size,
230                         unsigned int *nb_written,
231                         unsigned int *nb_supported)
232 {
233         unsigned int qid;
234         uint64_t value;
235         struct rte_eth_xstat *total_xstat;
236         bool count_total_value = false;
237         unsigned int nb_queues;
238
239         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
240         if (nb_queues == 0)
241                 return;
242         *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues);
243
244         /*
245          * The order of each software xstat type is the total xstat
246          * followed by per-queue xstats.
247          */
248         if (*nb_written < xstats_size) {
249                 count_total_value = true;
250                 total_xstat = &xstats[*nb_written];
251                 xstats[*nb_written].id = *nb_written;
252                 xstats[*nb_written].value = 0;
253                 (*nb_written)++;
254         }
255
256         for (qid = 0; qid < nb_queues; ++qid) {
257                 value = sw_stat->get_val(sa, qid);
258
259                 if (*nb_written < xstats_size) {
260                         xstats[*nb_written].id = *nb_written;
261                         xstats[*nb_written].value = value;
262                         (*nb_written)++;
263                 }
264
265                 if (count_total_value)
266                         total_xstat->value += value;
267         }
268 }
269
270 static void
271 sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa,
272                               const struct sfc_sw_stat_descr *sw_stat,
273                               const uint64_t *ids,
274                               uint64_t *values,
275                               unsigned int ids_size,
276                               unsigned int *nb_supported)
277 {
278         rte_spinlock_t *bmp_lock = &sa->sw_stats.queues_bitmap_lock;
279         struct rte_bitmap *bmp = sa->sw_stats.queues_bitmap;
280         unsigned int id_base = *nb_supported;
281         bool count_total_value = false;
282         unsigned int total_value_idx;
283         uint64_t total_value = 0;
284         unsigned int i, qid;
285         unsigned int nb_queues;
286
287
288         rte_spinlock_lock(bmp_lock);
289         rte_bitmap_reset(bmp);
290
291         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
292         if (nb_queues == 0)
293                 goto unlock;
294         *nb_supported += sfc_sw_xstat_per_queue_get_count(nb_queues);
295
296         /*
297          * The order of each software xstat type is the total xstat
298          * followed by per-queue xstats.
299          */
300         for (i = 0; i < ids_size; i++) {
301                 if (id_base <= ids[i] && ids[i] <= (id_base + nb_queues)) {
302                         if (ids[i] == id_base) { /* Accumulative value */
303                                 count_total_value = true;
304                                 total_value_idx = i;
305                                 continue;
306                         }
307                         qid = ids[i] - id_base - 1;
308                         values[i] = sw_stat->get_val(sa, qid);
309                         total_value += values[i];
310
311                         rte_bitmap_set(bmp, qid);
312                 }
313         }
314
315         if (count_total_value) {
316                 values[total_value_idx] = 0;
317                 for (qid = 0; qid < nb_queues; ++qid) {
318                         if (rte_bitmap_get(bmp, qid) != 0)
319                                 continue;
320                         values[total_value_idx] += sw_stat->get_val(sa, qid);
321                 }
322                 values[total_value_idx] += total_value;
323         }
324
325 unlock:
326         rte_spinlock_unlock(bmp_lock);
327 }
328
329 unsigned int
330 sfc_sw_xstats_get_nb_supported(struct sfc_adapter *sa)
331 {
332         unsigned int nb_supported = 0;
333         unsigned int i;
334
335         SFC_ASSERT(sfc_adapter_is_locked(sa));
336
337         for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) {
338                 nb_supported += sfc_sw_xstat_get_nb_supported(sa,
339                                                         &sfc_sw_stats_descr[i]);
340         }
341
342         return nb_supported;
343 }
344
345 void
346 sfc_sw_xstats_get_vals(struct sfc_adapter *sa,
347                        struct rte_eth_xstat *xstats,
348                        unsigned int xstats_count,
349                        unsigned int *nb_written,
350                        unsigned int *nb_supported)
351 {
352         uint64_t *reset_vals = sa->sw_stats.reset_vals;
353         unsigned int sw_xstats_offset;
354         unsigned int i;
355
356         sfc_adapter_lock(sa);
357
358         sw_xstats_offset = *nb_supported;
359
360         for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) {
361                 sfc_sw_xstat_get_values(sa, &sfc_sw_stats_descr[i], xstats,
362                                         xstats_count, nb_written, nb_supported);
363         }
364
365         for (i = sw_xstats_offset; i < *nb_written; i++)
366                 xstats[i].value -= reset_vals[i - sw_xstats_offset];
367
368         sfc_adapter_unlock(sa);
369 }
370
371 int
372 sfc_sw_xstats_get_names(struct sfc_adapter *sa,
373                         struct rte_eth_xstat_name *xstats_names,
374                         unsigned int xstats_count,
375                         unsigned int *nb_written,
376                         unsigned int *nb_supported)
377 {
378         unsigned int i;
379         int ret;
380
381         sfc_adapter_lock(sa);
382
383         for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) {
384                 ret = sfc_sw_stat_get_names(sa, &sfc_sw_stats_descr[i],
385                                             xstats_names, xstats_count,
386                                             nb_written, nb_supported);
387                 if (ret != 0) {
388                         sfc_adapter_unlock(sa);
389                         return ret;
390                 }
391         }
392
393         sfc_adapter_unlock(sa);
394
395         return 0;
396 }
397
398 void
399 sfc_sw_xstats_get_vals_by_id(struct sfc_adapter *sa,
400                              const uint64_t *ids,
401                              uint64_t *values,
402                              unsigned int n,
403                              unsigned int *nb_supported)
404 {
405         uint64_t *reset_vals = sa->sw_stats.reset_vals;
406         unsigned int sw_xstats_offset;
407         unsigned int i;
408
409         sfc_adapter_lock(sa);
410
411         sw_xstats_offset = *nb_supported;
412
413         for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) {
414                 sfc_sw_xstat_get_values_by_id(sa, &sfc_sw_stats_descr[i], ids,
415                                               values, n, nb_supported);
416         }
417
418         for (i = 0; i < n; i++) {
419                 if (sw_xstats_offset <= ids[i] && ids[i] < *nb_supported)
420                         values[i] -= reset_vals[ids[i] - sw_xstats_offset];
421         }
422
423         sfc_adapter_unlock(sa);
424 }
425
426 int
427 sfc_sw_xstats_get_names_by_id(struct sfc_adapter *sa,
428                               const uint64_t *ids,
429                               struct rte_eth_xstat_name *xstats_names,
430                               unsigned int size,
431                               unsigned int *nb_supported)
432 {
433         unsigned int i;
434         int ret;
435
436         sfc_adapter_lock(sa);
437
438         for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) {
439                 ret = sfc_sw_xstat_get_names_by_id(sa, &sfc_sw_stats_descr[i],
440                                                    ids, xstats_names, size,
441                                                    nb_supported);
442                 if (ret != 0) {
443                         sfc_adapter_unlock(sa);
444                         SFC_ASSERT(ret < 0);
445                         return ret;
446                 }
447         }
448
449         sfc_adapter_unlock(sa);
450
451         return 0;
452 }
453
454 static void
455 sfc_sw_xstat_reset(struct sfc_adapter *sa,
456                    const struct sfc_sw_stat_descr *sw_stat,
457                    uint64_t *reset_vals)
458 {
459         unsigned int nb_queues;
460         unsigned int qid;
461         uint64_t *total_xstat_reset;
462
463         SFC_ASSERT(sfc_adapter_is_locked(sa));
464
465         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
466         if (nb_queues == 0)
467                 return;
468
469         /*
470          * The order of each software xstat type is the total xstat
471          * followed by per-queue xstats.
472          */
473         total_xstat_reset = reset_vals;
474         *total_xstat_reset = 0;
475         reset_vals++;
476
477         for (qid = 0; qid < nb_queues; ++qid) {
478                 reset_vals[qid] = sw_stat->get_val(sa, qid);
479                 *total_xstat_reset += reset_vals[qid];
480         }
481 }
482
483 void
484 sfc_sw_xstats_reset(struct sfc_adapter *sa)
485 {
486         uint64_t *reset_vals = sa->sw_stats.reset_vals;
487         const struct sfc_sw_stat_descr *sw_stat;
488         unsigned int i;
489
490         SFC_ASSERT(sfc_adapter_is_locked(sa));
491
492         for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++) {
493                 sw_stat = &sfc_sw_stats_descr[i];
494                 sfc_sw_xstat_reset(sa, sw_stat, reset_vals);
495                 reset_vals += sfc_sw_xstat_get_nb_supported(sa, sw_stat);
496         }
497 }
498
499 int
500 sfc_sw_xstats_configure(struct sfc_adapter *sa)
501 {
502         uint64_t **reset_vals = &sa->sw_stats.reset_vals;
503         size_t nb_supported = 0;
504         unsigned int i;
505
506         for (i = 0; i < RTE_DIM(sfc_sw_stats_descr); i++)
507                 nb_supported += sfc_sw_xstat_get_nb_supported(sa,
508                                                         &sfc_sw_stats_descr[i]);
509
510         *reset_vals = rte_realloc(*reset_vals,
511                                   nb_supported * sizeof(**reset_vals), 0);
512         if (*reset_vals == NULL)
513                 return ENOMEM;
514
515         memset(*reset_vals, 0, nb_supported * sizeof(**reset_vals));
516
517         return 0;
518 }
519
520 static void
521 sfc_sw_xstats_free_queues_bitmap(struct sfc_adapter *sa)
522 {
523         rte_bitmap_free(sa->sw_stats.queues_bitmap);
524         rte_free(sa->sw_stats.queues_bitmap_mem);
525 }
526
527 static int
528 sfc_sw_xstats_alloc_queues_bitmap(struct sfc_adapter *sa)
529 {
530         struct rte_bitmap **queues_bitmap = &sa->sw_stats.queues_bitmap;
531         void **queues_bitmap_mem = &sa->sw_stats.queues_bitmap_mem;
532         uint32_t bmp_size;
533         int rc;
534
535         bmp_size = rte_bitmap_get_memory_footprint(RTE_MAX_QUEUES_PER_PORT);
536         *queues_bitmap_mem = NULL;
537         *queues_bitmap = NULL;
538
539         *queues_bitmap_mem = rte_calloc_socket("bitmap_mem", bmp_size, 1, 0,
540                                                sa->socket_id);
541         if (*queues_bitmap_mem == NULL)
542                 return ENOMEM;
543
544         *queues_bitmap = rte_bitmap_init(RTE_MAX_QUEUES_PER_PORT,
545                                          *queues_bitmap_mem, bmp_size);
546         if (*queues_bitmap == NULL) {
547                 rc = EINVAL;
548                 goto fail;
549         }
550
551         rte_spinlock_init(&sa->sw_stats.queues_bitmap_lock);
552         return 0;
553
554 fail:
555         sfc_sw_xstats_free_queues_bitmap(sa);
556         return rc;
557 }
558
559 int
560 sfc_sw_xstats_init(struct sfc_adapter *sa)
561 {
562         sa->sw_stats.reset_vals = NULL;
563
564         return sfc_sw_xstats_alloc_queues_bitmap(sa);
565 }
566
567 void
568 sfc_sw_xstats_close(struct sfc_adapter *sa)
569 {
570         sfc_sw_xstats_free_queues_bitmap(sa);
571         rte_free(sa->sw_stats.reset_vals);
572         sa->sw_stats.reset_vals = NULL;
573 }