xref: /dpdk/lib/rawdev/rte_rawdev.c (revision 37ff33833b6b8932bfbc8e149d386ef23ccdc54e)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017 NXP
3  */
4 
5 #include <ctype.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <stdint.h>
11 #include <inttypes.h>
12 
13 #include <rte_string_fns.h>
14 #include <rte_log.h>
15 #include <dev_driver.h>
16 #include <rte_common.h>
17 #include <rte_malloc.h>
18 #include <rte_telemetry.h>
19 
20 #include "rte_rawdev.h"
21 #include "rte_rawdev_pmd.h"
22 
23 static struct rte_rawdev rte_rawdevices[RTE_RAWDEV_MAX_DEVS];
24 
25 struct rte_rawdev *rte_rawdevs = rte_rawdevices;
26 
27 static struct rte_rawdev_global rawdev_globals = {
28 	.nb_devs		= 0
29 };
30 
31 /* Raw device, northbound API implementation */
32 uint8_t
rte_rawdev_count(void)33 rte_rawdev_count(void)
34 {
35 	return rawdev_globals.nb_devs;
36 }
37 
38 uint16_t
rte_rawdev_get_dev_id(const char * name)39 rte_rawdev_get_dev_id(const char *name)
40 {
41 	uint16_t i;
42 
43 	if (!name)
44 		return -EINVAL;
45 
46 	for (i = 0; i < rawdev_globals.nb_devs; i++)
47 		if ((strcmp(rte_rawdevices[i].name, name)
48 				== 0) &&
49 				(rte_rawdevices[i].attached ==
50 						RTE_RAWDEV_ATTACHED))
51 			return i;
52 	return -ENODEV;
53 }
54 
55 int
rte_rawdev_socket_id(uint16_t dev_id)56 rte_rawdev_socket_id(uint16_t dev_id)
57 {
58 	struct rte_rawdev *dev;
59 
60 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
61 	dev = &rte_rawdevs[dev_id];
62 
63 	return dev->socket_id;
64 }
65 
66 int
rte_rawdev_info_get(uint16_t dev_id,struct rte_rawdev_info * dev_info,size_t dev_private_size)67 rte_rawdev_info_get(uint16_t dev_id, struct rte_rawdev_info *dev_info,
68 		size_t dev_private_size)
69 {
70 	struct rte_rawdev *rawdev;
71 	int ret = 0;
72 
73 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
74 	if (dev_info == NULL)
75 		return -EINVAL;
76 
77 	rawdev = &rte_rawdevs[dev_id];
78 
79 	if (dev_info->dev_private != NULL) {
80 		if (*rawdev->dev_ops->dev_info_get == NULL)
81 			return -ENOTSUP;
82 		ret = (*rawdev->dev_ops->dev_info_get)(rawdev,
83 				dev_info->dev_private,
84 				dev_private_size);
85 	}
86 
87 	dev_info->driver_name = rawdev->driver_name;
88 	dev_info->device = rawdev->device;
89 	dev_info->socket_id = rawdev->socket_id;
90 
91 	return ret;
92 }
93 
94 int
rte_rawdev_configure(uint16_t dev_id,struct rte_rawdev_info * dev_conf,size_t dev_private_size)95 rte_rawdev_configure(uint16_t dev_id, struct rte_rawdev_info *dev_conf,
96 		size_t dev_private_size)
97 {
98 	struct rte_rawdev *dev;
99 	int diag;
100 
101 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
102 	if (dev_conf == NULL)
103 		return -EINVAL;
104 
105 	dev = &rte_rawdevs[dev_id];
106 
107 	if (*dev->dev_ops->dev_configure == NULL)
108 		return -ENOTSUP;
109 
110 	if (dev->started) {
111 		RTE_RDEV_ERR(
112 		   "device %d must be stopped to allow configuration", dev_id);
113 		return -EBUSY;
114 	}
115 
116 	/* Configure the device */
117 	diag = (*dev->dev_ops->dev_configure)(dev, dev_conf->dev_private,
118 			dev_private_size);
119 	if (diag != 0)
120 		RTE_RDEV_ERR("dev%d dev_configure = %d", dev_id, diag);
121 	else
122 		dev->attached = 1;
123 
124 	return diag;
125 }
126 
127 int
rte_rawdev_queue_conf_get(uint16_t dev_id,uint16_t queue_id,rte_rawdev_obj_t queue_conf,size_t queue_conf_size)128 rte_rawdev_queue_conf_get(uint16_t dev_id,
129 			  uint16_t queue_id,
130 			  rte_rawdev_obj_t queue_conf,
131 			  size_t queue_conf_size)
132 {
133 	struct rte_rawdev *dev;
134 
135 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
136 	dev = &rte_rawdevs[dev_id];
137 
138 	if (*dev->dev_ops->queue_def_conf == NULL)
139 		return -ENOTSUP;
140 	return (*dev->dev_ops->queue_def_conf)(dev, queue_id, queue_conf,
141 			queue_conf_size);
142 }
143 
144 int
rte_rawdev_queue_setup(uint16_t dev_id,uint16_t queue_id,rte_rawdev_obj_t queue_conf,size_t queue_conf_size)145 rte_rawdev_queue_setup(uint16_t dev_id,
146 		       uint16_t queue_id,
147 		       rte_rawdev_obj_t queue_conf,
148 		       size_t queue_conf_size)
149 {
150 	struct rte_rawdev *dev;
151 
152 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
153 	dev = &rte_rawdevs[dev_id];
154 
155 	if (*dev->dev_ops->queue_setup == NULL)
156 		return -ENOTSUP;
157 	return (*dev->dev_ops->queue_setup)(dev, queue_id, queue_conf,
158 			queue_conf_size);
159 }
160 
161 int
rte_rawdev_queue_release(uint16_t dev_id,uint16_t queue_id)162 rte_rawdev_queue_release(uint16_t dev_id, uint16_t queue_id)
163 {
164 	struct rte_rawdev *dev;
165 
166 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
167 	dev = &rte_rawdevs[dev_id];
168 
169 	if (*dev->dev_ops->queue_release == NULL)
170 		return -ENOTSUP;
171 	return (*dev->dev_ops->queue_release)(dev, queue_id);
172 }
173 
174 uint16_t
rte_rawdev_queue_count(uint16_t dev_id)175 rte_rawdev_queue_count(uint16_t dev_id)
176 {
177 	struct rte_rawdev *dev;
178 
179 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
180 	dev = &rte_rawdevs[dev_id];
181 
182 	if (*dev->dev_ops->queue_count == NULL)
183 		return -ENOTSUP;
184 	return (*dev->dev_ops->queue_count)(dev);
185 }
186 
187 int
rte_rawdev_get_attr(uint16_t dev_id,const char * attr_name,uint64_t * attr_value)188 rte_rawdev_get_attr(uint16_t dev_id,
189 		    const char *attr_name,
190 		    uint64_t *attr_value)
191 {
192 	struct rte_rawdev *dev;
193 
194 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
195 	dev = &rte_rawdevs[dev_id];
196 
197 	if (*dev->dev_ops->attr_get == NULL)
198 		return -ENOTSUP;
199 	return (*dev->dev_ops->attr_get)(dev, attr_name, attr_value);
200 }
201 
202 int
rte_rawdev_set_attr(uint16_t dev_id,const char * attr_name,const uint64_t attr_value)203 rte_rawdev_set_attr(uint16_t dev_id,
204 		    const char *attr_name,
205 		    const uint64_t attr_value)
206 {
207 	struct rte_rawdev *dev;
208 
209 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
210 	dev = &rte_rawdevs[dev_id];
211 
212 	if (*dev->dev_ops->attr_set == NULL)
213 		return -ENOTSUP;
214 	return (*dev->dev_ops->attr_set)(dev, attr_name, attr_value);
215 }
216 
217 int
rte_rawdev_enqueue_buffers(uint16_t dev_id,struct rte_rawdev_buf ** buffers,unsigned int count,rte_rawdev_obj_t context)218 rte_rawdev_enqueue_buffers(uint16_t dev_id,
219 			   struct rte_rawdev_buf **buffers,
220 			   unsigned int count,
221 			   rte_rawdev_obj_t context)
222 {
223 	struct rte_rawdev *dev;
224 
225 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
226 	dev = &rte_rawdevs[dev_id];
227 
228 	if (*dev->dev_ops->enqueue_bufs == NULL)
229 		return -ENOTSUP;
230 	return (*dev->dev_ops->enqueue_bufs)(dev, buffers, count, context);
231 }
232 
233 int
rte_rawdev_dequeue_buffers(uint16_t dev_id,struct rte_rawdev_buf ** buffers,unsigned int count,rte_rawdev_obj_t context)234 rte_rawdev_dequeue_buffers(uint16_t dev_id,
235 			   struct rte_rawdev_buf **buffers,
236 			   unsigned int count,
237 			   rte_rawdev_obj_t context)
238 {
239 	struct rte_rawdev *dev;
240 
241 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
242 	dev = &rte_rawdevs[dev_id];
243 
244 	if (*dev->dev_ops->dequeue_bufs == NULL)
245 		return -ENOTSUP;
246 	return (*dev->dev_ops->dequeue_bufs)(dev, buffers, count, context);
247 }
248 
249 int
rte_rawdev_dump(uint16_t dev_id,FILE * f)250 rte_rawdev_dump(uint16_t dev_id, FILE *f)
251 {
252 	struct rte_rawdev *dev;
253 
254 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
255 	dev = &rte_rawdevs[dev_id];
256 
257 	if (*dev->dev_ops->dump == NULL)
258 		return -ENOTSUP;
259 	return (*dev->dev_ops->dump)(dev, f);
260 }
261 
262 static int
xstats_get_count(uint16_t dev_id)263 xstats_get_count(uint16_t dev_id)
264 {
265 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
266 
267 	if (*dev->dev_ops->xstats_get_names == NULL)
268 		return -ENOTSUP;
269 	return (*dev->dev_ops->xstats_get_names)(dev, NULL, 0);
270 }
271 
272 int
rte_rawdev_xstats_names_get(uint16_t dev_id,struct rte_rawdev_xstats_name * xstats_names,unsigned int size)273 rte_rawdev_xstats_names_get(uint16_t dev_id,
274 		struct rte_rawdev_xstats_name *xstats_names,
275 		unsigned int size)
276 {
277 	const struct rte_rawdev *dev;
278 	int cnt_expected_entries;
279 
280 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -ENODEV);
281 
282 	cnt_expected_entries = xstats_get_count(dev_id);
283 
284 	if (xstats_names == NULL || cnt_expected_entries < 0 ||
285 	    (int)size < cnt_expected_entries || size <= 0)
286 		return cnt_expected_entries;
287 
288 	dev = &rte_rawdevs[dev_id];
289 
290 	if (*dev->dev_ops->xstats_get_names == NULL)
291 		return -ENOTSUP;
292 	return (*dev->dev_ops->xstats_get_names)(dev, xstats_names, size);
293 }
294 
295 /* retrieve rawdev extended statistics */
296 int
rte_rawdev_xstats_get(uint16_t dev_id,const unsigned int ids[],uint64_t values[],unsigned int n)297 rte_rawdev_xstats_get(uint16_t dev_id,
298 		      const unsigned int ids[],
299 		      uint64_t values[],
300 		      unsigned int n)
301 {
302 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -ENODEV);
303 	const struct rte_rawdev *dev = &rte_rawdevs[dev_id];
304 
305 	if (*dev->dev_ops->xstats_get == NULL)
306 		return -ENOTSUP;
307 	return (*dev->dev_ops->xstats_get)(dev, ids, values, n);
308 }
309 
310 uint64_t
rte_rawdev_xstats_by_name_get(uint16_t dev_id,const char * name,unsigned int * id)311 rte_rawdev_xstats_by_name_get(uint16_t dev_id,
312 			      const char *name,
313 			      unsigned int *id)
314 {
315 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, 0);
316 	const struct rte_rawdev *dev = &rte_rawdevs[dev_id];
317 	unsigned int temp = -1;
318 
319 	if (id != NULL)
320 		*id = (unsigned int)-1;
321 	else
322 		id = &temp; /* driver never gets a NULL value */
323 
324 	/* implemented by driver */
325 	if (*dev->dev_ops->xstats_get_by_name == NULL)
326 		return -ENOTSUP;
327 	return (*dev->dev_ops->xstats_get_by_name)(dev, name, id);
328 }
329 
330 int
rte_rawdev_xstats_reset(uint16_t dev_id,const uint32_t ids[],uint32_t nb_ids)331 rte_rawdev_xstats_reset(uint16_t dev_id,
332 			const uint32_t ids[], uint32_t nb_ids)
333 {
334 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
335 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
336 
337 	if (*dev->dev_ops->xstats_reset == NULL)
338 		return -ENOTSUP;
339 	return (*dev->dev_ops->xstats_reset)(dev, ids, nb_ids);
340 }
341 
342 int
rte_rawdev_firmware_status_get(uint16_t dev_id,rte_rawdev_obj_t status_info)343 rte_rawdev_firmware_status_get(uint16_t dev_id, rte_rawdev_obj_t status_info)
344 {
345 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
346 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
347 
348 	if (*dev->dev_ops->firmware_status_get == NULL)
349 		return -ENOTSUP;
350 	return (*dev->dev_ops->firmware_status_get)(dev, status_info);
351 }
352 
353 int
rte_rawdev_firmware_version_get(uint16_t dev_id,rte_rawdev_obj_t version_info)354 rte_rawdev_firmware_version_get(uint16_t dev_id, rte_rawdev_obj_t version_info)
355 {
356 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
357 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
358 
359 	if (*dev->dev_ops->firmware_version_get == NULL)
360 		return -ENOTSUP;
361 	return (*dev->dev_ops->firmware_version_get)(dev, version_info);
362 }
363 
364 int
rte_rawdev_firmware_load(uint16_t dev_id,rte_rawdev_obj_t firmware_image)365 rte_rawdev_firmware_load(uint16_t dev_id, rte_rawdev_obj_t firmware_image)
366 {
367 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
368 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
369 
370 	if (!firmware_image)
371 		return -EINVAL;
372 
373 	if (*dev->dev_ops->firmware_load == NULL)
374 		return -ENOTSUP;
375 	return (*dev->dev_ops->firmware_load)(dev, firmware_image);
376 }
377 
378 int
rte_rawdev_firmware_unload(uint16_t dev_id)379 rte_rawdev_firmware_unload(uint16_t dev_id)
380 {
381 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
382 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
383 
384 	if (*dev->dev_ops->firmware_load == NULL)
385 		return -ENOTSUP;
386 	return (*dev->dev_ops->firmware_unload)(dev);
387 }
388 
389 int
rte_rawdev_selftest(uint16_t dev_id)390 rte_rawdev_selftest(uint16_t dev_id)
391 {
392 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
393 	struct rte_rawdev *dev = &rte_rawdevs[dev_id];
394 
395 	if (*dev->dev_ops->dev_selftest == NULL)
396 		return -ENOTSUP;
397 	return (*dev->dev_ops->dev_selftest)(dev_id);
398 }
399 
400 int
rte_rawdev_start(uint16_t dev_id)401 rte_rawdev_start(uint16_t dev_id)
402 {
403 	struct rte_rawdev *dev;
404 	int diag;
405 
406 	RTE_RDEV_DEBUG("Start dev_id=%" PRIu8, dev_id);
407 
408 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
409 	dev = &rte_rawdevs[dev_id];
410 	if (dev->started != 0) {
411 		RTE_RDEV_ERR("Device with dev_id=%" PRIu8 "already started",
412 			     dev_id);
413 		return 0;
414 	}
415 
416 	if (dev->dev_ops->dev_start == NULL)
417 		goto mark_started;
418 
419 	diag = (*dev->dev_ops->dev_start)(dev);
420 	if (diag != 0)
421 		return diag;
422 
423 mark_started:
424 	dev->started = 1;
425 	return 0;
426 }
427 
428 void
rte_rawdev_stop(uint16_t dev_id)429 rte_rawdev_stop(uint16_t dev_id)
430 {
431 	struct rte_rawdev *dev;
432 
433 	RTE_RDEV_DEBUG("Stop dev_id=%" PRIu8, dev_id);
434 
435 	RTE_RAWDEV_VALID_DEVID_OR_RET(dev_id);
436 	dev = &rte_rawdevs[dev_id];
437 
438 	if (dev->started == 0) {
439 		RTE_RDEV_ERR("Device with dev_id=%" PRIu8 "already stopped",
440 			dev_id);
441 		return;
442 	}
443 
444 	if (dev->dev_ops->dev_stop == NULL)
445 		goto mark_stopped;
446 
447 	(*dev->dev_ops->dev_stop)(dev);
448 
449 mark_stopped:
450 	dev->started = 0;
451 }
452 
453 int
rte_rawdev_close(uint16_t dev_id)454 rte_rawdev_close(uint16_t dev_id)
455 {
456 	struct rte_rawdev *dev;
457 
458 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
459 	dev = &rte_rawdevs[dev_id];
460 
461 	if (*dev->dev_ops->dev_close == NULL)
462 		return -ENOTSUP;
463 	/* Device must be stopped before it can be closed */
464 	if (dev->started == 1) {
465 		RTE_RDEV_ERR("Device %u must be stopped before closing",
466 			     dev_id);
467 		return -EBUSY;
468 	}
469 
470 	return (*dev->dev_ops->dev_close)(dev);
471 }
472 
473 int
rte_rawdev_reset(uint16_t dev_id)474 rte_rawdev_reset(uint16_t dev_id)
475 {
476 	struct rte_rawdev *dev;
477 
478 	RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
479 	dev = &rte_rawdevs[dev_id];
480 
481 	if (*dev->dev_ops->dev_reset == NULL)
482 		return -ENOTSUP;
483 	/* Reset is not dependent on state of the device */
484 	return (*dev->dev_ops->dev_reset)(dev);
485 }
486 
487 static inline uint8_t
rte_rawdev_find_free_device_index(void)488 rte_rawdev_find_free_device_index(void)
489 {
490 	uint16_t dev_id;
491 
492 	for (dev_id = 0; dev_id < RTE_RAWDEV_MAX_DEVS; dev_id++) {
493 		if (rte_rawdevs[dev_id].attached ==
494 				RTE_RAWDEV_DETACHED)
495 			return dev_id;
496 	}
497 
498 	return RTE_RAWDEV_MAX_DEVS;
499 }
500 
501 struct rte_rawdev *
rte_rawdev_pmd_allocate(const char * name,size_t dev_priv_size,int socket_id)502 rte_rawdev_pmd_allocate(const char *name, size_t dev_priv_size, int socket_id)
503 {
504 	struct rte_rawdev *rawdev;
505 	uint16_t dev_id;
506 
507 	if (rte_rawdev_pmd_get_named_dev(name) != NULL) {
508 		RTE_RDEV_ERR("Raw device with name %s already allocated!", name);
509 		return NULL;
510 	}
511 
512 	dev_id = rte_rawdev_find_free_device_index();
513 	if (dev_id == RTE_RAWDEV_MAX_DEVS) {
514 		RTE_RDEV_ERR("Reached maximum number of raw devices");
515 		return NULL;
516 	}
517 
518 	rawdev = &rte_rawdevs[dev_id];
519 
520 	if (dev_priv_size > 0) {
521 		rawdev->dev_private = rte_zmalloc_socket("rawdev private",
522 				     dev_priv_size,
523 				     RTE_CACHE_LINE_SIZE,
524 				     socket_id);
525 		if (!rawdev->dev_private) {
526 			RTE_RDEV_ERR("Unable to allocate memory for rawdev");
527 			return NULL;
528 		}
529 	}
530 
531 	rawdev->dev_id = dev_id;
532 	rawdev->socket_id = socket_id;
533 	rawdev->started = 0;
534 	strlcpy(rawdev->name, name, RTE_RAWDEV_NAME_MAX_LEN);
535 
536 	rawdev->attached = RTE_RAWDEV_ATTACHED;
537 	rawdev_globals.nb_devs++;
538 
539 	return rawdev;
540 }
541 
542 int
rte_rawdev_pmd_release(struct rte_rawdev * rawdev)543 rte_rawdev_pmd_release(struct rte_rawdev *rawdev)
544 {
545 	int ret;
546 
547 	if (rawdev == NULL)
548 		return -EINVAL;
549 
550 	ret = rte_rawdev_close(rawdev->dev_id);
551 	if (ret < 0)
552 		return ret;
553 
554 	rawdev->attached = RTE_RAWDEV_DETACHED;
555 	rawdev_globals.nb_devs--;
556 
557 	rawdev->dev_id = 0;
558 	rawdev->socket_id = 0;
559 	rawdev->dev_ops = NULL;
560 	if (rawdev->dev_private) {
561 		rte_free(rawdev->dev_private);
562 		rawdev->dev_private = NULL;
563 	}
564 
565 	return 0;
566 }
567 
568 static int
handle_dev_list(const char * cmd __rte_unused,const char * params __rte_unused,struct rte_tel_data * d)569 handle_dev_list(const char *cmd __rte_unused,
570 		const char *params __rte_unused,
571 		struct rte_tel_data *d)
572 {
573 	int i;
574 
575 	rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
576 	for (i = 0; i < rawdev_globals.nb_devs; i++)
577 		if (rte_rawdevices[i].attached == RTE_RAWDEV_ATTACHED)
578 			rte_tel_data_add_array_int(d, i);
579 	return 0;
580 }
581 
582 static int
handle_dev_xstats(const char * cmd __rte_unused,const char * params,struct rte_tel_data * d)583 handle_dev_xstats(const char *cmd __rte_unused,
584 		const char *params,
585 		struct rte_tel_data *d)
586 {
587 	uint64_t *rawdev_xstats;
588 	struct rte_rawdev_xstats_name *xstat_names;
589 	int dev_id, num_xstats, i, ret;
590 	unsigned int *ids;
591 	char *end_param;
592 
593 	if (params == NULL || strlen(params) == 0 || !isdigit(*params))
594 		return -1;
595 
596 	dev_id = strtoul(params, &end_param, 0);
597 	if (*end_param != '\0')
598 		RTE_RDEV_LOG(NOTICE,
599 			"Extra parameters passed to rawdev telemetry command, ignoring");
600 	if (!rte_rawdev_pmd_is_valid_dev(dev_id))
601 		return -1;
602 
603 	num_xstats = xstats_get_count(dev_id);
604 	if (num_xstats < 0)
605 		return -1;
606 
607 	/* use one malloc for names, stats and ids */
608 	rawdev_xstats = malloc((sizeof(uint64_t) +
609 			sizeof(struct rte_rawdev_xstats_name) +
610 			sizeof(unsigned int)) * num_xstats);
611 	if (rawdev_xstats == NULL)
612 		return -1;
613 	xstat_names = (void *)&rawdev_xstats[num_xstats];
614 	ids = (void *)&xstat_names[num_xstats];
615 
616 	ret = rte_rawdev_xstats_names_get(dev_id, xstat_names, num_xstats);
617 	if (ret < 0 || ret > num_xstats) {
618 		free(rawdev_xstats);
619 		return -1;
620 	}
621 
622 	for (i = 0; i < num_xstats; i++)
623 		ids[i] = i;
624 
625 	ret = rte_rawdev_xstats_get(dev_id, ids, rawdev_xstats, num_xstats);
626 	if (ret < 0 || ret > num_xstats) {
627 		free(rawdev_xstats);
628 		return -1;
629 	}
630 
631 	rte_tel_data_start_dict(d);
632 	for (i = 0; i < num_xstats; i++)
633 		rte_tel_data_add_dict_uint(d, xstat_names[i].name,
634 					   rawdev_xstats[i]);
635 
636 	free(rawdev_xstats);
637 	return 0;
638 }
639 
640 static int
handle_dev_dump(const char * cmd __rte_unused,const char * params,struct rte_tel_data * d)641 handle_dev_dump(const char *cmd __rte_unused,
642 		const char *params,
643 		struct rte_tel_data *d)
644 {
645 	char *buf, *end_param;
646 	int dev_id, ret;
647 	FILE *f;
648 
649 	if (params == NULL || strlen(params) == 0 || !isdigit(*params))
650 		return -EINVAL;
651 
652 	dev_id = strtoul(params, &end_param, 0);
653 	if (*end_param != '\0')
654 		RTE_RDEV_LOG(NOTICE,
655 			"Extra parameters passed to rawdev telemetry command, ignoring");
656 	if (!rte_rawdev_pmd_is_valid_dev(dev_id))
657 		return -EINVAL;
658 
659 	buf = calloc(RTE_TEL_MAX_SINGLE_STRING_LEN, sizeof(char));
660 	if (buf == NULL)
661 		return -ENOMEM;
662 
663 	f = fmemopen(buf, RTE_TEL_MAX_SINGLE_STRING_LEN - 1, "w+");
664 	if (f == NULL) {
665 		free(buf);
666 		return -EINVAL;
667 	}
668 
669 	ret = rte_rawdev_dump(dev_id, f);
670 	fclose(f);
671 	if (ret == 0) {
672 		rte_tel_data_start_dict(d);
673 		rte_tel_data_string(d, buf);
674 	}
675 
676 	free(buf);
677 	return 0;
678 }
679 
680 RTE_LOG_REGISTER_DEFAULT(librawdev_logtype, INFO);
681 
RTE_INIT(librawdev_init_telemetry)682 RTE_INIT(librawdev_init_telemetry)
683 {
684 	rte_telemetry_register_cmd("/rawdev/list", handle_dev_list,
685 			"Returns list of available rawdev ports. Takes no parameters");
686 	rte_telemetry_register_cmd("/rawdev/xstats", handle_dev_xstats,
687 			"Returns the xstats for a rawdev port. Parameters: int port_id");
688 	rte_telemetry_register_cmd("/rawdev/dump", handle_dev_dump,
689 			"Returns dump information for a rawdev port. Parameters: int port_id");
690 }
691