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