New upstream version 17.11-rc3
[deb_dpdk.git] / drivers / event / sw / sw_evdev_xstats.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Intel Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <rte_event_ring.h>
34 #include "sw_evdev.h"
35 #include "iq_ring.h"
36
37 enum xstats_type {
38         /* common stats */
39         rx,
40         tx,
41         dropped,
42         inflight,
43         calls,
44         credits,
45         /* device instance specific */
46         no_iq_enq,
47         no_cq_enq,
48         /* port_specific */
49         rx_used,
50         rx_free,
51         tx_used,
52         tx_free,
53         pkt_cycles,
54         poll_return, /* for zero-count and used also for port bucket loop */
55         /* qid_specific */
56         iq_size,
57         iq_used,
58         /* qid port mapping specific */
59         pinned,
60         pkts, /* note: qid-to-port pkts */
61 };
62
63 typedef uint64_t (*xstats_fn)(const struct sw_evdev *dev,
64                 uint16_t obj_idx, /* port or queue id */
65                 enum xstats_type stat, int extra_arg);
66
67 struct sw_xstats_entry {
68         struct rte_event_dev_xstats_name name;
69         xstats_fn fn;
70         uint16_t obj_idx;
71         enum xstats_type stat;
72         enum rte_event_dev_xstats_mode mode;
73         int extra_arg;
74         uint8_t reset_allowed; /* when set, this value can be reset */
75         uint64_t reset_value; /* an offset to be taken away to emulate resets */
76 };
77
78 static uint64_t
79 get_dev_stat(const struct sw_evdev *sw, uint16_t obj_idx __rte_unused,
80                 enum xstats_type type, int extra_arg __rte_unused)
81 {
82         switch (type) {
83         case rx: return sw->stats.rx_pkts;
84         case tx: return sw->stats.tx_pkts;
85         case dropped: return sw->stats.rx_dropped;
86         case calls: return sw->sched_called;
87         case no_iq_enq: return sw->sched_no_iq_enqueues;
88         case no_cq_enq: return sw->sched_no_cq_enqueues;
89         default: return -1;
90         }
91 }
92
93 static uint64_t
94 get_port_stat(const struct sw_evdev *sw, uint16_t obj_idx,
95                 enum xstats_type type, int extra_arg __rte_unused)
96 {
97         const struct sw_port *p = &sw->ports[obj_idx];
98
99         switch (type) {
100         case rx: return p->stats.rx_pkts;
101         case tx: return p->stats.tx_pkts;
102         case dropped: return p->stats.rx_dropped;
103         case inflight: return p->inflights;
104         case pkt_cycles: return p->avg_pkt_ticks;
105         case calls: return p->total_polls;
106         case credits: return p->inflight_credits;
107         case poll_return: return p->zero_polls;
108         case rx_used: return rte_event_ring_count(p->rx_worker_ring);
109         case rx_free: return rte_event_ring_free_count(p->rx_worker_ring);
110         case tx_used: return rte_event_ring_count(p->cq_worker_ring);
111         case tx_free: return rte_event_ring_free_count(p->cq_worker_ring);
112         default: return -1;
113         }
114 }
115
116 static uint64_t
117 get_port_bucket_stat(const struct sw_evdev *sw, uint16_t obj_idx,
118                 enum xstats_type type, int extra_arg)
119 {
120         const struct sw_port *p = &sw->ports[obj_idx];
121
122         switch (type) {
123         case poll_return: return p->poll_buckets[extra_arg];
124         default: return -1;
125         }
126 }
127
128 static uint64_t
129 get_qid_stat(const struct sw_evdev *sw, uint16_t obj_idx,
130                 enum xstats_type type, int extra_arg __rte_unused)
131 {
132         const struct sw_qid *qid = &sw->qids[obj_idx];
133
134         switch (type) {
135         case rx: return qid->stats.rx_pkts;
136         case tx: return qid->stats.tx_pkts;
137         case dropped: return qid->stats.rx_dropped;
138         case inflight:
139                 do {
140                         uint64_t infl = 0;
141                         unsigned int i;
142                         for (i = 0; i < RTE_DIM(qid->fids); i++)
143                                 infl += qid->fids[i].pcount;
144                         return infl;
145                 } while (0);
146                 break;
147         case iq_size: return RTE_DIM(qid->iq[0]->ring);
148         default: return -1;
149         }
150 }
151
152 static uint64_t
153 get_qid_iq_stat(const struct sw_evdev *sw, uint16_t obj_idx,
154                 enum xstats_type type, int extra_arg)
155 {
156         const struct sw_qid *qid = &sw->qids[obj_idx];
157         const int iq_idx = extra_arg;
158
159         switch (type) {
160         case iq_used: return iq_ring_count(qid->iq[iq_idx]);
161         default: return -1;
162         }
163 }
164
165 static uint64_t
166 get_qid_port_stat(const struct sw_evdev *sw, uint16_t obj_idx,
167                 enum xstats_type type, int extra_arg)
168 {
169         const struct sw_qid *qid = &sw->qids[obj_idx];
170         uint16_t port = extra_arg;
171
172         switch (type) {
173         case pinned:
174                 do {
175                         uint64_t pin = 0;
176                         unsigned int i;
177                         for (i = 0; i < RTE_DIM(qid->fids); i++)
178                                 if (qid->fids[i].cq == port)
179                                         pin++;
180                         return pin;
181                 } while (0);
182                 break;
183         case pkts:
184                 return qid->to_port[port];
185         default: return -1;
186         }
187 }
188
189 int
190 sw_xstats_init(struct sw_evdev *sw)
191 {
192         /*
193          * define the stats names and types. Used to build up the device
194          * xstats array
195          * There are multiple set of stats:
196          *   - device-level,
197          *   - per-port,
198          *   - per-port-dequeue-burst-sizes
199          *   - per-qid,
200          *   - per-iq
201          *   - per-port-per-qid
202          *
203          * For each of these sets, we have three parallel arrays, one for the
204          * names, the other for the stat type parameter to be passed in the fn
205          * call to get that stat. The third array allows resetting or not.
206          * All these arrays must be kept in sync
207          */
208         static const char * const dev_stats[] = { "rx", "tx", "drop",
209                         "sched_calls", "sched_no_iq_enq", "sched_no_cq_enq",
210         };
211         static const enum xstats_type dev_types[] = { rx, tx, dropped,
212                         calls, no_iq_enq, no_cq_enq,
213         };
214         /* all device stats are allowed to be reset */
215
216         static const char * const port_stats[] = {"rx", "tx", "drop",
217                         "inflight", "avg_pkt_cycles", "credits",
218                         "rx_ring_used", "rx_ring_free",
219                         "cq_ring_used", "cq_ring_free",
220                         "dequeue_calls", "dequeues_returning_0",
221         };
222         static const enum xstats_type port_types[] = { rx, tx, dropped,
223                         inflight, pkt_cycles, credits,
224                         rx_used, rx_free, tx_used, tx_free,
225                         calls, poll_return,
226         };
227         static const uint8_t port_reset_allowed[] = {1, 1, 1,
228                         0, 1, 0,
229                         0, 0, 0, 0,
230                         1, 1,
231         };
232
233         static const char * const port_bucket_stats[] = {
234                         "dequeues_returning" };
235         static const enum xstats_type port_bucket_types[] = { poll_return };
236         /* all bucket dequeues are allowed to be reset, handled in loop below */
237
238         static const char * const qid_stats[] = {"rx", "tx", "drop",
239                         "inflight", "iq_size"
240         };
241         static const enum xstats_type qid_types[] = { rx, tx, dropped,
242                         inflight, iq_size
243         };
244         static const uint8_t qid_reset_allowed[] = {1, 1, 1,
245                         0, 0
246         };
247
248         static const char * const qid_iq_stats[] = { "used" };
249         static const enum xstats_type qid_iq_types[] = { iq_used };
250         /* reset allowed */
251
252         static const char * const qid_port_stats[] = { "pinned_flows",
253                 "packets"
254         };
255         static const enum xstats_type qid_port_types[] = { pinned, pkts };
256         static const uint8_t qid_port_reset_allowed[] = {0, 1};
257         /* reset allowed */
258         /* ---- end of stat definitions ---- */
259
260         /* check sizes, since a missed comma can lead to strings being
261          * joined by the compiler.
262          */
263         RTE_BUILD_BUG_ON(RTE_DIM(dev_stats) != RTE_DIM(dev_types));
264         RTE_BUILD_BUG_ON(RTE_DIM(port_stats) != RTE_DIM(port_types));
265         RTE_BUILD_BUG_ON(RTE_DIM(qid_stats) != RTE_DIM(qid_types));
266         RTE_BUILD_BUG_ON(RTE_DIM(qid_iq_stats) != RTE_DIM(qid_iq_types));
267         RTE_BUILD_BUG_ON(RTE_DIM(qid_port_stats) != RTE_DIM(qid_port_types));
268         RTE_BUILD_BUG_ON(RTE_DIM(port_bucket_stats) !=
269                         RTE_DIM(port_bucket_types));
270
271         RTE_BUILD_BUG_ON(RTE_DIM(port_stats) != RTE_DIM(port_reset_allowed));
272         RTE_BUILD_BUG_ON(RTE_DIM(qid_stats) != RTE_DIM(qid_reset_allowed));
273
274         /* other vars */
275         const uint32_t cons_bkt_shift =
276                 (MAX_SW_CONS_Q_DEPTH >> SW_DEQ_STAT_BUCKET_SHIFT);
277         const unsigned int count = RTE_DIM(dev_stats) +
278                         sw->port_count * RTE_DIM(port_stats) +
279                         sw->port_count * RTE_DIM(port_bucket_stats) *
280                                 (cons_bkt_shift + 1) +
281                         sw->qid_count * RTE_DIM(qid_stats) +
282                         sw->qid_count * SW_IQS_MAX * RTE_DIM(qid_iq_stats) +
283                         sw->qid_count * sw->port_count *
284                                 RTE_DIM(qid_port_stats);
285         unsigned int i, port, qid, iq, bkt, stat = 0;
286
287         sw->xstats = rte_zmalloc_socket(NULL, sizeof(sw->xstats[0]) * count, 0,
288                         sw->data->socket_id);
289         if (sw->xstats == NULL)
290                 return -ENOMEM;
291
292 #define sname sw->xstats[stat].name.name
293         for (i = 0; i < RTE_DIM(dev_stats); i++, stat++) {
294                 sw->xstats[stat] = (struct sw_xstats_entry){
295                         .fn = get_dev_stat,
296                         .stat = dev_types[i],
297                         .mode = RTE_EVENT_DEV_XSTATS_DEVICE,
298                         .reset_allowed = 1,
299                 };
300                 snprintf(sname, sizeof(sname), "dev_%s", dev_stats[i]);
301         }
302         sw->xstats_count_mode_dev = stat;
303
304         for (port = 0; port < sw->port_count; port++) {
305                 sw->xstats_offset_for_port[port] = stat;
306
307                 uint32_t count_offset = stat;
308
309                 for (i = 0; i < RTE_DIM(port_stats); i++, stat++) {
310                         sw->xstats[stat] = (struct sw_xstats_entry){
311                                 .fn = get_port_stat,
312                                 .obj_idx = port,
313                                 .stat = port_types[i],
314                                 .mode = RTE_EVENT_DEV_XSTATS_PORT,
315                                 .reset_allowed = port_reset_allowed[i],
316                         };
317                         snprintf(sname, sizeof(sname), "port_%u_%s",
318                                         port, port_stats[i]);
319                 }
320
321                 for (bkt = 0; bkt < (rte_event_ring_get_capacity(
322                                 sw->ports[port].cq_worker_ring) >>
323                                         SW_DEQ_STAT_BUCKET_SHIFT) + 1; bkt++) {
324                         for (i = 0; i < RTE_DIM(port_bucket_stats); i++) {
325                                 sw->xstats[stat] = (struct sw_xstats_entry){
326                                         .fn = get_port_bucket_stat,
327                                         .obj_idx = port,
328                                         .stat = port_bucket_types[i],
329                                         .mode = RTE_EVENT_DEV_XSTATS_PORT,
330                                         .extra_arg = bkt,
331                                         .reset_allowed = 1,
332                                 };
333                                 snprintf(sname, sizeof(sname),
334                                         "port_%u_%s_%u-%u",
335                                         port, port_bucket_stats[i],
336                                         (bkt << SW_DEQ_STAT_BUCKET_SHIFT) + 1,
337                                         (bkt + 1) << SW_DEQ_STAT_BUCKET_SHIFT);
338                                 stat++;
339                         }
340                 }
341
342                 sw->xstats_count_per_port[port] = stat - count_offset;
343         }
344
345         sw->xstats_count_mode_port = stat - sw->xstats_count_mode_dev;
346
347         for (qid = 0; qid < sw->qid_count; qid++) {
348                 uint32_t count_offset = stat;
349                 sw->xstats_offset_for_qid[qid] = stat;
350
351                 for (i = 0; i < RTE_DIM(qid_stats); i++, stat++) {
352                         sw->xstats[stat] = (struct sw_xstats_entry){
353                                 .fn = get_qid_stat,
354                                 .obj_idx = qid,
355                                 .stat = qid_types[i],
356                                 .mode = RTE_EVENT_DEV_XSTATS_QUEUE,
357                                 .reset_allowed = qid_reset_allowed[i],
358                         };
359                         snprintf(sname, sizeof(sname), "qid_%u_%s",
360                                         qid, qid_stats[i]);
361                 }
362                 for (iq = 0; iq < SW_IQS_MAX; iq++)
363                         for (i = 0; i < RTE_DIM(qid_iq_stats); i++, stat++) {
364                                 sw->xstats[stat] = (struct sw_xstats_entry){
365                                         .fn = get_qid_iq_stat,
366                                         .obj_idx = qid,
367                                         .stat = qid_iq_types[i],
368                                         .mode = RTE_EVENT_DEV_XSTATS_QUEUE,
369                                         .extra_arg = iq,
370                                         .reset_allowed = 0,
371                                 };
372                                 snprintf(sname, sizeof(sname),
373                                                 "qid_%u_iq_%u_%s",
374                                                 qid, iq,
375                                                 qid_iq_stats[i]);
376                         }
377
378                 for (port = 0; port < sw->port_count; port++)
379                         for (i = 0; i < RTE_DIM(qid_port_stats); i++, stat++) {
380                                 sw->xstats[stat] = (struct sw_xstats_entry){
381                                         .fn = get_qid_port_stat,
382                                         .obj_idx = qid,
383                                         .stat = qid_port_types[i],
384                                         .mode = RTE_EVENT_DEV_XSTATS_QUEUE,
385                                         .extra_arg = port,
386                                         .reset_allowed =
387                                                 qid_port_reset_allowed[i],
388                                 };
389                                 snprintf(sname, sizeof(sname),
390                                                 "qid_%u_port_%u_%s",
391                                                 qid, port,
392                                                 qid_port_stats[i]);
393                         }
394
395                 sw->xstats_count_per_qid[qid] = stat - count_offset;
396         }
397
398         sw->xstats_count_mode_queue = stat -
399                 (sw->xstats_count_mode_dev + sw->xstats_count_mode_port);
400 #undef sname
401
402         sw->xstats_count = stat;
403
404         return stat;
405 }
406
407 int
408 sw_xstats_uninit(struct sw_evdev *sw)
409 {
410         rte_free(sw->xstats);
411         sw->xstats_count = 0;
412         return 0;
413 }
414
415 int
416 sw_xstats_get_names(const struct rte_eventdev *dev,
417                 enum rte_event_dev_xstats_mode mode, uint8_t queue_port_id,
418                 struct rte_event_dev_xstats_name *xstats_names,
419                 unsigned int *ids, unsigned int size)
420 {
421         const struct sw_evdev *sw = sw_pmd_priv_const(dev);
422         unsigned int i;
423         unsigned int xidx = 0;
424         RTE_SET_USED(mode);
425         RTE_SET_USED(queue_port_id);
426
427         uint32_t xstats_mode_count = 0;
428         uint32_t start_offset = 0;
429
430         switch (mode) {
431         case RTE_EVENT_DEV_XSTATS_DEVICE:
432                 xstats_mode_count = sw->xstats_count_mode_dev;
433                 break;
434         case RTE_EVENT_DEV_XSTATS_PORT:
435                 if (queue_port_id >= (signed int)sw->port_count)
436                         break;
437                 xstats_mode_count = sw->xstats_count_per_port[queue_port_id];
438                 start_offset = sw->xstats_offset_for_port[queue_port_id];
439                 break;
440         case RTE_EVENT_DEV_XSTATS_QUEUE:
441                 if (queue_port_id >= (signed int)sw->qid_count)
442                         break;
443                 xstats_mode_count = sw->xstats_count_per_qid[queue_port_id];
444                 start_offset = sw->xstats_offset_for_qid[queue_port_id];
445                 break;
446         default:
447                 SW_LOG_ERR("Invalid mode received in sw_xstats_get_names()\n");
448                 return -EINVAL;
449         };
450
451         if (xstats_mode_count > size || !ids || !xstats_names)
452                 return xstats_mode_count;
453
454         for (i = 0; i < sw->xstats_count && xidx < size; i++) {
455                 if (sw->xstats[i].mode != mode)
456                         continue;
457
458                 if (mode != RTE_EVENT_DEV_XSTATS_DEVICE &&
459                                 queue_port_id != sw->xstats[i].obj_idx)
460                         continue;
461
462                 xstats_names[xidx] = sw->xstats[i].name;
463                 if (ids)
464                         ids[xidx] = start_offset + xidx;
465                 xidx++;
466         }
467         return xidx;
468 }
469
470 static int
471 sw_xstats_update(struct sw_evdev *sw, enum rte_event_dev_xstats_mode mode,
472                 uint8_t queue_port_id, const unsigned int ids[],
473                 uint64_t values[], unsigned int n, const uint32_t reset,
474                 const uint32_t ret_if_n_lt_nstats)
475 {
476         unsigned int i;
477         unsigned int xidx = 0;
478         RTE_SET_USED(mode);
479         RTE_SET_USED(queue_port_id);
480
481         uint32_t xstats_mode_count = 0;
482
483         switch (mode) {
484         case RTE_EVENT_DEV_XSTATS_DEVICE:
485                 xstats_mode_count = sw->xstats_count_mode_dev;
486                 break;
487         case RTE_EVENT_DEV_XSTATS_PORT:
488                 if (queue_port_id >= (signed int)sw->port_count)
489                         goto invalid_value;
490                 xstats_mode_count = sw->xstats_count_per_port[queue_port_id];
491                 break;
492         case RTE_EVENT_DEV_XSTATS_QUEUE:
493                 if (queue_port_id >= (signed int)sw->qid_count)
494                         goto invalid_value;
495                 xstats_mode_count = sw->xstats_count_per_qid[queue_port_id];
496                 break;
497         default:
498                 SW_LOG_ERR("Invalid mode received in sw_xstats_get()\n");
499                 goto invalid_value;
500         };
501
502         /* this function can check num stats and return them (xstats_get() style
503          * behaviour) or ignore n for reset() of a single stat style behaviour.
504          */
505         if (ret_if_n_lt_nstats && xstats_mode_count > n)
506                 return xstats_mode_count;
507
508         for (i = 0; i < n && xidx < xstats_mode_count; i++) {
509                 struct sw_xstats_entry *xs = &sw->xstats[ids[i]];
510                 if (ids[i] > sw->xstats_count || xs->mode != mode)
511                         continue;
512
513                 if (mode != RTE_EVENT_DEV_XSTATS_DEVICE &&
514                                 queue_port_id != xs->obj_idx)
515                         continue;
516
517                 uint64_t val = xs->fn(sw, xs->obj_idx, xs->stat, xs->extra_arg)
518                                         - xs->reset_value;
519
520                 if (values)
521                         values[xidx] = val;
522
523                 if (xs->reset_allowed && reset)
524                         xs->reset_value = val;
525
526                 xidx++;
527         }
528
529         return xidx;
530 invalid_value:
531         return -EINVAL;
532 }
533
534 int
535 sw_xstats_get(const struct rte_eventdev *dev,
536                 enum rte_event_dev_xstats_mode mode, uint8_t queue_port_id,
537                 const unsigned int ids[], uint64_t values[], unsigned int n)
538 {
539         struct sw_evdev *sw = sw_pmd_priv(dev);
540         const uint32_t reset = 0;
541         const uint32_t ret_n_lt_stats = 0;
542         return sw_xstats_update(sw, mode, queue_port_id, ids, values, n,
543                                 reset, ret_n_lt_stats);
544 }
545
546 uint64_t
547 sw_xstats_get_by_name(const struct rte_eventdev *dev,
548                 const char *name, unsigned int *id)
549 {
550         const struct sw_evdev *sw = sw_pmd_priv_const(dev);
551         unsigned int i;
552
553         for (i = 0; i < sw->xstats_count; i++) {
554                 struct sw_xstats_entry *xs = &sw->xstats[i];
555                 if (strncmp(xs->name.name, name,
556                                 RTE_EVENT_DEV_XSTATS_NAME_SIZE) == 0){
557                         if (id != NULL)
558                                 *id = i;
559                         return xs->fn(sw, xs->obj_idx, xs->stat, xs->extra_arg)
560                                         - xs->reset_value;
561                 }
562         }
563         if (id != NULL)
564                 *id = (uint32_t)-1;
565         return (uint64_t)-1;
566 }
567
568 static void
569 sw_xstats_reset_range(struct sw_evdev *sw, uint32_t start, uint32_t num)
570 {
571         uint32_t i;
572         for (i = start; i < start + num; i++) {
573                 struct sw_xstats_entry *xs = &sw->xstats[i];
574                 if (!xs->reset_allowed)
575                         continue;
576
577                 uint64_t val = xs->fn(sw, xs->obj_idx, xs->stat, xs->extra_arg)
578                                         - xs->reset_value;
579                 xs->reset_value = val;
580         }
581 }
582
583 static int
584 sw_xstats_reset_queue(struct sw_evdev *sw, uint8_t queue_id,
585                 const uint32_t ids[], uint32_t nb_ids)
586 {
587         const uint32_t reset = 1;
588         const uint32_t ret_n_lt_stats = 0;
589         if (ids) {
590                 uint32_t nb_reset = sw_xstats_update(sw,
591                                         RTE_EVENT_DEV_XSTATS_QUEUE,
592                                         queue_id, ids, NULL, nb_ids,
593                                         reset, ret_n_lt_stats);
594                 return nb_reset == nb_ids ? 0 : -EINVAL;
595         }
596
597         if (ids == NULL)
598                 sw_xstats_reset_range(sw, sw->xstats_offset_for_qid[queue_id],
599                                       sw->xstats_count_per_qid[queue_id]);
600
601         return 0;
602 }
603
604 static int
605 sw_xstats_reset_port(struct sw_evdev *sw, uint8_t port_id,
606                 const uint32_t ids[], uint32_t nb_ids)
607 {
608         const uint32_t reset = 1;
609         const uint32_t ret_n_lt_stats = 0;
610         int offset = sw->xstats_offset_for_port[port_id];
611         int nb_stat = sw->xstats_count_per_port[port_id];
612
613         if (ids) {
614                 uint32_t nb_reset = sw_xstats_update(sw,
615                                         RTE_EVENT_DEV_XSTATS_PORT, port_id,
616                                         ids, NULL, nb_ids,
617                                         reset, ret_n_lt_stats);
618                 return nb_reset == nb_ids ? 0 : -EINVAL;
619         }
620
621         sw_xstats_reset_range(sw, offset, nb_stat);
622         return 0;
623 }
624
625 static int
626 sw_xstats_reset_dev(struct sw_evdev *sw, const uint32_t ids[], uint32_t nb_ids)
627 {
628         uint32_t i;
629         if (ids) {
630                 for (i = 0; i < nb_ids; i++) {
631                         uint32_t id = ids[i];
632                         if (id >= sw->xstats_count_mode_dev)
633                                 return -EINVAL;
634                         sw_xstats_reset_range(sw, id, 1);
635                 }
636         } else {
637                 for (i = 0; i < sw->xstats_count_mode_dev; i++)
638                         sw_xstats_reset_range(sw, i, 1);
639         }
640
641         return 0;
642 }
643
644 int
645 sw_xstats_reset(struct rte_eventdev *dev,
646                 enum rte_event_dev_xstats_mode mode,
647                 int16_t queue_port_id,
648                 const uint32_t ids[],
649                 uint32_t nb_ids)
650 {
651         struct sw_evdev *sw = sw_pmd_priv(dev);
652         uint32_t i, err;
653
654         /* handle -1 for queue_port_id here, looping over all ports/queues */
655         switch (mode) {
656         case RTE_EVENT_DEV_XSTATS_DEVICE:
657                 sw_xstats_reset_dev(sw, ids, nb_ids);
658                 break;
659         case RTE_EVENT_DEV_XSTATS_PORT:
660                 if (queue_port_id == -1) {
661                         for (i = 0; i < sw->port_count; i++) {
662                                 err = sw_xstats_reset_port(sw, i, ids, nb_ids);
663                                 if (err)
664                                         return -EINVAL;
665                         }
666                 } else if (queue_port_id < (int16_t)sw->port_count)
667                         sw_xstats_reset_port(sw, queue_port_id, ids, nb_ids);
668                 break;
669         case RTE_EVENT_DEV_XSTATS_QUEUE:
670                 if (queue_port_id == -1) {
671                         for (i = 0; i < sw->qid_count; i++) {
672                                 err = sw_xstats_reset_queue(sw, i, ids, nb_ids);
673                                 if (err)
674                                         return -EINVAL;
675                         }
676                 } else if (queue_port_id < (int16_t)sw->qid_count)
677                         sw_xstats_reset_queue(sw, queue_port_id, ids, nb_ids);
678                 break;
679         };
680
681         return 0;
682 }