81bd531a17ee09858923d5cf4f4bcc5e2fdc1556
[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 #define SFC_SW_STAT_INVALID             UINT64_MAX
14
15 #define SFC_SW_STATS_GROUP_SIZE_MAX     1U
16
17 enum sfc_sw_stats_type {
18         SFC_SW_STATS_RX,
19         SFC_SW_STATS_TX,
20 };
21
22 typedef void sfc_get_sw_stat_val_t(struct sfc_adapter *sa, uint16_t qid,
23                                    uint64_t *values, unsigned int values_count);
24
25 struct sfc_sw_stat_descr {
26         const char *name;
27         enum sfc_sw_stats_type type;
28         sfc_get_sw_stat_val_t *get_val;
29         bool provide_total;
30 };
31
32 static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_rx_dbells;
33 static void
34 sfc_get_sw_stat_val_rx_dbells(struct sfc_adapter *sa, uint16_t qid,
35                                uint64_t *values, unsigned int values_count)
36 {
37         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
38         struct sfc_rxq_info *rxq_info;
39
40         RTE_SET_USED(values_count);
41         SFC_ASSERT(values_count == 1);
42         rxq_info = sfc_rxq_info_by_ethdev_qid(sas, qid);
43         values[0] = rxq_info->state & SFC_RXQ_INITIALIZED ?
44                     rxq_info->dp->dpq.rx_dbells : 0;
45 }
46
47 static sfc_get_sw_stat_val_t sfc_get_sw_stat_val_tx_dbells;
48 static void
49 sfc_get_sw_stat_val_tx_dbells(struct sfc_adapter *sa, uint16_t qid,
50                                uint64_t *values, unsigned int values_count)
51 {
52         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
53         struct sfc_txq_info *txq_info;
54
55         RTE_SET_USED(values_count);
56         SFC_ASSERT(values_count == 1);
57         txq_info = sfc_txq_info_by_ethdev_qid(sas, qid);
58         values[0] = txq_info->state & SFC_TXQ_INITIALIZED ?
59                     txq_info->dp->dpq.tx_dbells : 0;
60 }
61
62 /*
63  * SW stats can be grouped together. When stats are grouped the corresponding
64  * stats values for each queue are obtained during calling one get value
65  * callback. Stats of the same group are contiguous in the structure below.
66  * The start of the group is denoted by stat implementing get value callback.
67  */
68 const struct sfc_sw_stat_descr sfc_sw_stats_descr[] = {
69         {
70                 .name = "dbells",
71                 .type = SFC_SW_STATS_RX,
72                 .get_val  = sfc_get_sw_stat_val_rx_dbells,
73                 .provide_total = true,
74         },
75         {
76                 .name = "dbells",
77                 .type = SFC_SW_STATS_TX,
78                 .get_val  = sfc_get_sw_stat_val_tx_dbells,
79                 .provide_total = true,
80         }
81 };
82
83 static int
84 sfc_sw_stat_get_name(struct sfc_adapter *sa,
85                      const struct sfc_sw_stat_descr *sw_stat, char *name,
86                      size_t name_size, unsigned int id_off)
87 {
88         const char *prefix;
89         int ret;
90
91         switch (sw_stat->type) {
92         case SFC_SW_STATS_RX:
93                 prefix = "rx";
94                 break;
95         case SFC_SW_STATS_TX:
96                 prefix = "tx";
97                 break;
98         default:
99                 sfc_err(sa, "%s: unknown software statistics type %d",
100                         __func__, sw_stat->type);
101                 return -EINVAL;
102         }
103
104         if (sw_stat->provide_total && id_off == 0) {
105                 ret = snprintf(name, name_size, "%s_%s", prefix,
106                                                          sw_stat->name);
107                 if (ret < 0 || ret >= (int)name_size) {
108                         sfc_err(sa, "%s: failed to fill xstat name %s_%s, err %d",
109                                 __func__, prefix, sw_stat->name, ret);
110                         return ret > 0 ? -EINVAL : ret;
111                 }
112         } else {
113                 uint16_t qid = id_off - sw_stat->provide_total;
114                 ret = snprintf(name, name_size, "%s_q%u_%s", prefix, qid,
115                                                         sw_stat->name);
116                 if (ret < 0 || ret >= (int)name_size) {
117                         sfc_err(sa, "%s: failed to fill xstat name %s_q%u_%s, err %d",
118                                 __func__, prefix, qid, sw_stat->name, ret);
119                         return ret > 0 ? -EINVAL : ret;
120                 }
121         }
122
123         return 0;
124 }
125
126 static unsigned int
127 sfc_sw_stat_get_queue_count(struct sfc_adapter *sa,
128                             const struct sfc_sw_stat_descr *sw_stat)
129 {
130         struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
131
132         switch (sw_stat->type) {
133         case SFC_SW_STATS_RX:
134                 return sas->ethdev_rxq_count;
135         case SFC_SW_STATS_TX:
136                 return sas->ethdev_txq_count;
137         default:
138                 sfc_err(sa, "%s: unknown software statistics type %d",
139                         __func__, sw_stat->type);
140                 return 0;
141         }
142 }
143
144 static unsigned int
145 sfc_sw_xstat_per_queue_get_count(const struct sfc_sw_stat_descr *sw_stat,
146                                  unsigned int nb_queues)
147 {
148         /* Take into account the total xstat of all queues */
149         return nb_queues > 0 ? sw_stat->provide_total + nb_queues : 0;
150 }
151
152 static unsigned int
153 sfc_sw_xstat_get_nb_supported(struct sfc_adapter *sa,
154                               const struct sfc_sw_stat_descr *sw_stat)
155 {
156         unsigned int nb_queues;
157
158         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
159         return sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues);
160 }
161
162 static int
163 sfc_sw_stat_get_names(struct sfc_adapter *sa,
164                       const struct sfc_sw_stat_descr *sw_stat,
165                       struct rte_eth_xstat_name *xstats_names,
166                       unsigned int xstats_names_sz,
167                       unsigned int *nb_written,
168                       unsigned int *nb_supported)
169 {
170         const size_t name_size = sizeof(xstats_names[0].name);
171         unsigned int id_base = *nb_supported;
172         unsigned int nb_queues;
173         unsigned int qid;
174         int rc;
175
176         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
177         if (nb_queues == 0)
178                 return 0;
179         *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues);
180
181         /*
182          * The order of each software xstat type is the total xstat
183          * followed by per-queue xstats.
184          */
185         if (*nb_written < xstats_names_sz && sw_stat->provide_total) {
186                 rc = sfc_sw_stat_get_name(sa, sw_stat,
187                                           xstats_names[*nb_written].name,
188                                           name_size, *nb_written - id_base);
189                 if (rc != 0)
190                         return rc;
191                 (*nb_written)++;
192         }
193
194         for (qid = 0; qid < nb_queues; ++qid) {
195                 if (*nb_written < xstats_names_sz) {
196                         rc = sfc_sw_stat_get_name(sa, sw_stat,
197                                               xstats_names[*nb_written].name,
198                                               name_size, *nb_written - id_base);
199                         if (rc != 0)
200                                 return rc;
201                         (*nb_written)++;
202                 }
203         }
204
205         return 0;
206 }
207
208 static int
209 sfc_sw_xstat_get_names_by_id(struct sfc_adapter *sa,
210                              const struct sfc_sw_stat_descr *sw_stat,
211                              const uint64_t *ids,
212                              struct rte_eth_xstat_name *xstats_names,
213                              unsigned int size,
214                              unsigned int *nb_supported)
215 {
216         const size_t name_size = sizeof(xstats_names[0].name);
217         unsigned int id_base = *nb_supported;
218         unsigned int id_end;
219         unsigned int nb_queues;
220         unsigned int i;
221         int rc;
222
223         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
224         if (nb_queues == 0)
225                 return 0;
226         *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues);
227
228         /*
229          * The order of each software xstat type is the total xstat
230          * followed by per-queue xstats.
231          */
232         id_end = id_base + sw_stat->provide_total + nb_queues;
233         for (i = 0; i < size; i++) {
234                 if (id_base <= ids[i] && ids[i] < id_end) {
235                         rc = sfc_sw_stat_get_name(sa, sw_stat,
236                                                   xstats_names[i].name,
237                                                   name_size, ids[i] - id_base);
238                         if (rc != 0)
239                                 return rc;
240                 }
241         }
242
243         return 0;
244 }
245
246 static uint64_t
247 sfc_sw_stat_get_val(struct sfc_adapter *sa,
248                     unsigned int sw_stat_idx, uint16_t qid)
249 {
250         struct sfc_sw_stats *sw_stats = &sa->sw_stats;
251         uint64_t *res = &sw_stats->supp[sw_stat_idx].cache[qid];
252         uint64_t values[SFC_SW_STATS_GROUP_SIZE_MAX];
253         unsigned int group_start_idx;
254         unsigned int group_size;
255         unsigned int i;
256
257         if (*res != SFC_SW_STAT_INVALID)
258                 return *res;
259
260         /*
261          * Search for the group start, i.e. the stat that implements
262          * get value callback.
263          */
264         group_start_idx = sw_stat_idx;
265         while (sw_stats->supp[group_start_idx].descr->get_val == NULL)
266                 group_start_idx--;
267
268         /*
269          * Calculate number of elements in the group with loop till the next
270          * group start or the list end.
271          */
272         group_size = 1;
273         for (i = sw_stat_idx + 1; i < sw_stats->supp_count; i++) {
274                 if (sw_stats->supp[i].descr->get_val != NULL)
275                         break;
276                 group_size++;
277         }
278         group_size += sw_stat_idx - group_start_idx;
279
280         SFC_ASSERT(group_size <= SFC_SW_STATS_GROUP_SIZE_MAX);
281         sw_stats->supp[group_start_idx].descr->get_val(sa, qid, values,
282                                                        group_size);
283         for (i = group_start_idx; i < (group_start_idx + group_size); i++)
284                 sw_stats->supp[i].cache[qid] = values[i - group_start_idx];
285
286         return *res;
287 }
288
289 static void
290 sfc_sw_xstat_get_values(struct sfc_adapter *sa,
291                         const struct sfc_sw_stat_descr *sw_stat,
292                         unsigned int sw_stat_idx,
293                         struct rte_eth_xstat *xstats,
294                         unsigned int xstats_size,
295                         unsigned int *nb_written,
296                         unsigned int *nb_supported)
297 {
298         unsigned int qid;
299         uint64_t value;
300         struct rte_eth_xstat *total_xstat;
301         bool count_total_value = false;
302         unsigned int nb_queues;
303
304         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
305         if (nb_queues == 0)
306                 return;
307         *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues);
308
309         /*
310          * The order of each software xstat type is the total xstat
311          * followed by per-queue xstats.
312          */
313         if (*nb_written < xstats_size && sw_stat->provide_total) {
314                 count_total_value = true;
315                 total_xstat = &xstats[*nb_written];
316                 xstats[*nb_written].id = *nb_written;
317                 xstats[*nb_written].value = 0;
318                 (*nb_written)++;
319         }
320
321         for (qid = 0; qid < nb_queues; ++qid) {
322                 value = sfc_sw_stat_get_val(sa, sw_stat_idx, qid);
323
324                 if (*nb_written < xstats_size) {
325                         xstats[*nb_written].id = *nb_written;
326                         xstats[*nb_written].value = value;
327                         (*nb_written)++;
328                 }
329
330                 if (count_total_value)
331                         total_xstat->value += value;
332         }
333 }
334
335 static void
336 sfc_sw_xstat_get_values_by_id(struct sfc_adapter *sa,
337                               const struct sfc_sw_stat_descr *sw_stat,
338                               unsigned int sw_stat_idx,
339                               const uint64_t *ids,
340                               uint64_t *values,
341                               unsigned int ids_size,
342                               unsigned int *nb_supported)
343 {
344         rte_spinlock_t *bmp_lock = &sa->sw_stats.queues_bitmap_lock;
345         struct rte_bitmap *bmp = sa->sw_stats.queues_bitmap;
346         unsigned int id_base = *nb_supported;
347         unsigned int id_base_q;
348         unsigned int id_end;
349         bool count_total_value = false;
350         unsigned int total_value_idx;
351         uint64_t total_value = 0;
352         unsigned int i, qid;
353         unsigned int nb_queues;
354
355
356         rte_spinlock_lock(bmp_lock);
357         rte_bitmap_reset(bmp);
358
359         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
360         if (nb_queues == 0)
361                 goto unlock;
362         *nb_supported += sfc_sw_xstat_per_queue_get_count(sw_stat, nb_queues);
363
364         /*
365          * The order of each software xstat type is the total xstat
366          * followed by per-queue xstats.
367          */
368         id_end = id_base + sw_stat->provide_total + nb_queues;
369         for (i = 0; i < ids_size; i++) {
370                 if (id_base <= ids[i] && ids[i] < id_end) {
371                         if (sw_stat->provide_total && ids[i] == id_base) {
372                                 /* Accumulative value */
373                                 count_total_value = true;
374                                 total_value_idx = i;
375                                 continue;
376                         }
377                         id_base_q = id_base + sw_stat->provide_total;
378                         qid = ids[i] - id_base_q;
379                         values[i] = sfc_sw_stat_get_val(sa, sw_stat_idx, qid);
380                         total_value += values[i];
381
382                         rte_bitmap_set(bmp, qid);
383                 }
384         }
385
386         if (count_total_value) {
387                 values[total_value_idx] = 0;
388                 for (qid = 0; qid < nb_queues; ++qid) {
389                         if (rte_bitmap_get(bmp, qid) != 0)
390                                 continue;
391                         values[total_value_idx] += sfc_sw_stat_get_val(sa,
392                                                                     sw_stat_idx,
393                                                                     qid);
394                 }
395                 values[total_value_idx] += total_value;
396         }
397
398 unlock:
399         rte_spinlock_unlock(bmp_lock);
400 }
401
402 unsigned int
403 sfc_sw_xstats_get_nb_supported(struct sfc_adapter *sa)
404 {
405         SFC_ASSERT(sfc_adapter_is_locked(sa));
406         return sa->sw_stats.xstats_count;
407 }
408
409 static void
410 sfc_sw_stats_clear_cache(struct sfc_adapter *sa)
411 {
412         unsigned int cache_count = sa->sw_stats.cache_count;
413         uint64_t *cache = sa->sw_stats.cache;
414
415         RTE_BUILD_BUG_ON(UINT64_C(0xffffffffffffffff) != SFC_SW_STAT_INVALID);
416         memset(cache, 0xff, cache_count * sizeof(*cache));
417 }
418
419 void
420 sfc_sw_xstats_get_vals(struct sfc_adapter *sa,
421                        struct rte_eth_xstat *xstats,
422                        unsigned int xstats_count,
423                        unsigned int *nb_written,
424                        unsigned int *nb_supported)
425 {
426         uint64_t *reset_vals = sa->sw_stats.reset_vals;
427         struct sfc_sw_stats *sw_stats = &sa->sw_stats;
428         unsigned int sw_xstats_offset;
429         unsigned int i;
430
431         sfc_adapter_lock(sa);
432
433         sfc_sw_stats_clear_cache(sa);
434
435         sw_xstats_offset = *nb_supported;
436
437         for (i = 0; i < sw_stats->supp_count; i++) {
438                 sfc_sw_xstat_get_values(sa, sw_stats->supp[i].descr, i,
439                                 xstats, xstats_count, nb_written, nb_supported);
440         }
441
442         for (i = sw_xstats_offset; i < *nb_written; i++)
443                 xstats[i].value -= reset_vals[i - sw_xstats_offset];
444
445         sfc_adapter_unlock(sa);
446 }
447
448 int
449 sfc_sw_xstats_get_names(struct sfc_adapter *sa,
450                         struct rte_eth_xstat_name *xstats_names,
451                         unsigned int xstats_count,
452                         unsigned int *nb_written,
453                         unsigned int *nb_supported)
454 {
455         struct sfc_sw_stats *sw_stats = &sa->sw_stats;
456         unsigned int i;
457         int ret;
458
459         sfc_adapter_lock(sa);
460
461         for (i = 0; i < sw_stats->supp_count; i++) {
462                 ret = sfc_sw_stat_get_names(sa, sw_stats->supp[i].descr,
463                                             xstats_names, xstats_count,
464                                             nb_written, nb_supported);
465                 if (ret != 0) {
466                         sfc_adapter_unlock(sa);
467                         return ret;
468                 }
469         }
470
471         sfc_adapter_unlock(sa);
472
473         return 0;
474 }
475
476 void
477 sfc_sw_xstats_get_vals_by_id(struct sfc_adapter *sa,
478                              const uint64_t *ids,
479                              uint64_t *values,
480                              unsigned int n,
481                              unsigned int *nb_supported)
482 {
483         uint64_t *reset_vals = sa->sw_stats.reset_vals;
484         struct sfc_sw_stats *sw_stats = &sa->sw_stats;
485         unsigned int sw_xstats_offset;
486         unsigned int i;
487
488         sfc_adapter_lock(sa);
489
490         sfc_sw_stats_clear_cache(sa);
491
492         sw_xstats_offset = *nb_supported;
493
494         for (i = 0; i < sw_stats->supp_count; i++) {
495                 sfc_sw_xstat_get_values_by_id(sa, sw_stats->supp[i].descr, i,
496                                               ids, values, n, nb_supported);
497         }
498
499         for (i = 0; i < n; i++) {
500                 if (sw_xstats_offset <= ids[i] && ids[i] < *nb_supported)
501                         values[i] -= reset_vals[ids[i] - sw_xstats_offset];
502         }
503
504         sfc_adapter_unlock(sa);
505 }
506
507 int
508 sfc_sw_xstats_get_names_by_id(struct sfc_adapter *sa,
509                               const uint64_t *ids,
510                               struct rte_eth_xstat_name *xstats_names,
511                               unsigned int size,
512                               unsigned int *nb_supported)
513 {
514         struct sfc_sw_stats *sw_stats = &sa->sw_stats;
515         unsigned int i;
516         int ret;
517
518         sfc_adapter_lock(sa);
519
520         for (i = 0; i < sw_stats->supp_count; i++) {
521                 ret = sfc_sw_xstat_get_names_by_id(sa, sw_stats->supp[i].descr,
522                                                    ids, xstats_names, size,
523                                                    nb_supported);
524                 if (ret != 0) {
525                         sfc_adapter_unlock(sa);
526                         SFC_ASSERT(ret < 0);
527                         return ret;
528                 }
529         }
530
531         sfc_adapter_unlock(sa);
532
533         return 0;
534 }
535
536 static void
537 sfc_sw_xstat_reset(struct sfc_adapter *sa,
538                    const struct sfc_sw_stat_descr *sw_stat,
539                    unsigned int sw_stat_idx,
540                    uint64_t *reset_vals)
541 {
542         unsigned int nb_queues;
543         unsigned int qid;
544         uint64_t *total_xstat_reset = NULL;
545
546         SFC_ASSERT(sfc_adapter_is_locked(sa));
547
548         nb_queues = sfc_sw_stat_get_queue_count(sa, sw_stat);
549         if (nb_queues == 0)
550                 return;
551
552         /*
553          * The order of each software xstat type is the total xstat
554          * followed by per-queue xstats.
555          */
556         if (sw_stat->provide_total) {
557                 total_xstat_reset = reset_vals;
558                 *total_xstat_reset = 0;
559                 reset_vals++;
560         }
561
562         for (qid = 0; qid < nb_queues; ++qid) {
563                 reset_vals[qid] = sfc_sw_stat_get_val(sa, sw_stat_idx, qid);
564                 if (sw_stat->provide_total)
565                         *total_xstat_reset += reset_vals[qid];
566         }
567 }
568
569 void
570 sfc_sw_xstats_reset(struct sfc_adapter *sa)
571 {
572         uint64_t *reset_vals = sa->sw_stats.reset_vals;
573         struct sfc_sw_stats *sw_stats = &sa->sw_stats;
574         unsigned int i;
575
576         SFC_ASSERT(sfc_adapter_is_locked(sa));
577
578         sfc_sw_stats_clear_cache(sa);
579
580         for (i = 0; i < sw_stats->supp_count; i++) {
581                 sfc_sw_xstat_reset(sa, sw_stats->supp[i].descr, i, reset_vals);
582                 reset_vals += sfc_sw_xstat_get_nb_supported(sa,
583                                                        sw_stats->supp[i].descr);
584         }
585 }
586
587 int
588 sfc_sw_xstats_configure(struct sfc_adapter *sa)
589 {
590         uint64_t **reset_vals = &sa->sw_stats.reset_vals;
591         struct sfc_sw_stats *sw_stats = &sa->sw_stats;
592         unsigned int cache_count = 0;
593         uint64_t **cache =  &sa->sw_stats.cache;
594         uint64_t *stat_cache;
595         size_t nb_supported = 0;
596         unsigned int i;
597         int rc;
598
599         sw_stats->supp_count = RTE_DIM(sfc_sw_stats_descr);
600         if (sw_stats->supp == NULL) {
601                 sw_stats->supp = rte_malloc(NULL, sw_stats->supp_count *
602                                             sizeof(*sw_stats->supp), 0);
603                 if (sw_stats->supp == NULL)
604                         return -ENOMEM;
605         }
606         for (i = 0; i < sw_stats->supp_count; i++)
607                 sw_stats->supp[i].descr = &sfc_sw_stats_descr[i];
608
609         for (i = 0; i < sw_stats->supp_count; i++) {
610                 nb_supported += sfc_sw_xstat_get_nb_supported(sa,
611                                                        sw_stats->supp[i].descr);
612                 cache_count += sfc_sw_stat_get_queue_count(sa,
613                                                        sw_stats->supp[i].descr);
614         }
615         sa->sw_stats.xstats_count = nb_supported;
616
617         *reset_vals = rte_realloc(*reset_vals,
618                                   nb_supported * sizeof(**reset_vals), 0);
619         if (*reset_vals == NULL) {
620                 rc = -ENOMEM;
621                 goto fail_reset_vals;
622         }
623
624         memset(*reset_vals, 0, nb_supported * sizeof(**reset_vals));
625
626         *cache = rte_realloc(*cache, cache_count * sizeof(*cache), 0);
627         if (*cache == NULL) {
628                 rc = ENOMEM;
629                 goto fail_cache;
630         }
631         sa->sw_stats.cache_count = cache_count;
632         stat_cache = *cache;
633
634         for (i = 0; i < sw_stats->supp_count; i++) {
635                 sw_stats->supp[i].cache = stat_cache;
636                 stat_cache += sfc_sw_stat_get_queue_count(sa,
637                                                        sw_stats->supp[i].descr);
638         }
639
640         return 0;
641
642 fail_cache:
643         rte_free(*reset_vals);
644         *reset_vals = NULL;
645 fail_reset_vals:
646         sa->sw_stats.xstats_count = 0;
647         rte_free(sw_stats->supp);
648         sw_stats->supp = NULL;
649         sw_stats->supp_count = 0;
650
651         return rc;
652 }
653
654 static void
655 sfc_sw_xstats_free_queues_bitmap(struct sfc_adapter *sa)
656 {
657         rte_bitmap_free(sa->sw_stats.queues_bitmap);
658         rte_free(sa->sw_stats.queues_bitmap_mem);
659 }
660
661 static int
662 sfc_sw_xstats_alloc_queues_bitmap(struct sfc_adapter *sa)
663 {
664         struct rte_bitmap **queues_bitmap = &sa->sw_stats.queues_bitmap;
665         void **queues_bitmap_mem = &sa->sw_stats.queues_bitmap_mem;
666         uint32_t bmp_size;
667         int rc;
668
669         bmp_size = rte_bitmap_get_memory_footprint(RTE_MAX_QUEUES_PER_PORT);
670         *queues_bitmap_mem = NULL;
671         *queues_bitmap = NULL;
672
673         *queues_bitmap_mem = rte_calloc_socket("bitmap_mem", bmp_size, 1, 0,
674                                                sa->socket_id);
675         if (*queues_bitmap_mem == NULL)
676                 return ENOMEM;
677
678         *queues_bitmap = rte_bitmap_init(RTE_MAX_QUEUES_PER_PORT,
679                                          *queues_bitmap_mem, bmp_size);
680         if (*queues_bitmap == NULL) {
681                 rc = EINVAL;
682                 goto fail;
683         }
684
685         rte_spinlock_init(&sa->sw_stats.queues_bitmap_lock);
686         return 0;
687
688 fail:
689         sfc_sw_xstats_free_queues_bitmap(sa);
690         return rc;
691 }
692
693 int
694 sfc_sw_xstats_init(struct sfc_adapter *sa)
695 {
696         sa->sw_stats.xstats_count = 0;
697         sa->sw_stats.supp = NULL;
698         sa->sw_stats.supp_count = 0;
699         sa->sw_stats.cache = NULL;
700         sa->sw_stats.cache_count = 0;
701         sa->sw_stats.reset_vals = NULL;
702
703         return sfc_sw_xstats_alloc_queues_bitmap(sa);
704 }
705
706 void
707 sfc_sw_xstats_close(struct sfc_adapter *sa)
708 {
709         sfc_sw_xstats_free_queues_bitmap(sa);
710         sa->sw_stats.reset_vals = NULL;
711         rte_free(sa->sw_stats.cache);
712         sa->sw_stats.cache = NULL;
713         sa->sw_stats.cache_count = 0;
714         rte_free(sa->sw_stats.reset_vals);
715         rte_free(sa->sw_stats.supp);
716         sa->sw_stats.supp = NULL;
717         sa->sw_stats.supp_count = 0;
718         sa->sw_stats.xstats_count = 0;
719 }