1 /* SPDX-License-Identifier: BSD-3-Clause
13 #include <rte_byteorder.h>
14 #include <rte_common.h>
15 #include <rte_debug.h>
18 #include <rte_kvargs.h>
20 #include <rte_malloc.h>
21 #include <rte_memory.h>
22 #include <rte_memcpy.h>
23 #include <rte_lcore.h>
24 #include <rte_bus_vdev.h>
26 #include <rte_rawdev.h>
27 #include <rte_rawdev_pmd.h>
29 #include "skeleton_rawdev.h"
31 /* Count of instances */
32 static uint16_t skeldev_init_once;
34 /**< Rawdev Skeleton dummy driver name */
35 #define SKELETON_PMD_RAWDEV_NAME rawdev_skeleton
37 struct queue_buffers {
38 void *bufs[SKELETON_QUEUE_MAX_DEPTH];
41 static struct queue_buffers queue_buf[SKELETON_MAX_QUEUES] = {};
42 static void clear_queue_bufs(int queue_id);
44 static void skeleton_rawdev_info_get(struct rte_rawdev *dev,
45 rte_rawdev_obj_t dev_info)
47 struct skeleton_rawdev *skeldev;
48 struct skeleton_rawdev_conf *skeldev_conf;
50 SKELETON_PMD_FUNC_TRACE();
53 SKELETON_PMD_ERR("Invalid request");
57 skeldev = skeleton_rawdev_get_priv(dev);
59 skeldev_conf = dev_info;
61 skeldev_conf->num_queues = skeldev->num_queues;
62 skeldev_conf->capabilities = skeldev->capabilities;
63 skeldev_conf->device_state = skeldev->device_state;
64 skeldev_conf->firmware_state = skeldev->fw.firmware_state;
67 static int skeleton_rawdev_configure(const struct rte_rawdev *dev,
68 rte_rawdev_obj_t config)
70 struct skeleton_rawdev *skeldev;
71 struct skeleton_rawdev_conf *skeldev_conf;
73 SKELETON_PMD_FUNC_TRACE();
75 RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
78 SKELETON_PMD_ERR("Invalid configuration");
82 skeldev_conf = config;
83 skeldev = skeleton_rawdev_get_priv(dev);
85 if (skeldev_conf->num_queues <= SKELETON_MAX_QUEUES)
86 skeldev->num_queues = skeldev_conf->num_queues;
90 skeldev->capabilities = skeldev_conf->capabilities;
91 skeldev->num_queues = skeldev_conf->num_queues;
96 static int skeleton_rawdev_start(struct rte_rawdev *dev)
99 struct skeleton_rawdev *skeldev;
100 enum skeleton_firmware_state fw_state;
101 enum skeleton_device_state device_state;
103 SKELETON_PMD_FUNC_TRACE();
105 RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
107 skeldev = skeleton_rawdev_get_priv(dev);
109 fw_state = skeldev->fw.firmware_state;
110 device_state = skeldev->device_state;
112 if (fw_state == SKELETON_FW_LOADED &&
113 device_state == SKELETON_DEV_STOPPED) {
114 skeldev->device_state = SKELETON_DEV_RUNNING;
116 SKELETON_PMD_ERR("Device not ready for starting");
123 static void skeleton_rawdev_stop(struct rte_rawdev *dev)
125 struct skeleton_rawdev *skeldev;
127 SKELETON_PMD_FUNC_TRACE();
130 skeldev = skeleton_rawdev_get_priv(dev);
131 skeldev->device_state = SKELETON_DEV_STOPPED;
136 reset_queues(struct skeleton_rawdev *skeldev)
140 for (i = 0; i < SKELETON_MAX_QUEUES; i++) {
141 skeldev->queues[i].depth = SKELETON_QUEUE_DEF_DEPTH;
142 skeldev->queues[i].state = SKELETON_QUEUE_DETACH;
147 reset_attribute_table(struct skeleton_rawdev *skeldev)
151 for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
152 if (skeldev->attr[i].name) {
153 free(skeldev->attr[i].name);
154 skeldev->attr[i].name = NULL;
159 static int skeleton_rawdev_close(struct rte_rawdev *dev)
162 struct skeleton_rawdev *skeldev;
163 enum skeleton_firmware_state fw_state;
164 enum skeleton_device_state device_state;
166 SKELETON_PMD_FUNC_TRACE();
168 RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
170 skeldev = skeleton_rawdev_get_priv(dev);
172 fw_state = skeldev->fw.firmware_state;
173 device_state = skeldev->device_state;
175 reset_queues(skeldev);
176 reset_attribute_table(skeldev);
179 case SKELETON_FW_LOADED:
180 if (device_state == SKELETON_DEV_RUNNING) {
181 SKELETON_PMD_ERR("Cannot close running device");
184 /* Probably call fw reset here */
185 skeldev->fw.firmware_state = SKELETON_FW_READY;
188 case SKELETON_FW_READY:
189 case SKELETON_FW_ERROR:
191 SKELETON_PMD_DEBUG("Device already in stopped state");
196 /* Clear all allocated queues */
197 for (i = 0; i < SKELETON_MAX_QUEUES; i++)
203 static int skeleton_rawdev_reset(struct rte_rawdev *dev)
205 struct skeleton_rawdev *skeldev;
207 SKELETON_PMD_FUNC_TRACE();
209 RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
211 skeldev = skeleton_rawdev_get_priv(dev);
213 SKELETON_PMD_DEBUG("Resetting device");
214 skeldev->fw.firmware_state = SKELETON_FW_READY;
219 static void skeleton_rawdev_queue_def_conf(struct rte_rawdev *dev,
221 rte_rawdev_obj_t queue_conf)
223 struct skeleton_rawdev *skeldev;
224 struct skeleton_rawdev_queue *skelq;
226 SKELETON_PMD_FUNC_TRACE();
228 if (!dev || !queue_conf)
231 skeldev = skeleton_rawdev_get_priv(dev);
232 skelq = &skeldev->queues[queue_id];
234 if (queue_id < SKELETON_MAX_QUEUES)
235 rte_memcpy(queue_conf, skelq,
236 sizeof(struct skeleton_rawdev_queue));
240 clear_queue_bufs(int queue_id)
244 /* Clear buffers for queue_id */
245 for (i = 0; i < SKELETON_QUEUE_MAX_DEPTH; i++)
246 queue_buf[queue_id].bufs[i] = NULL;
249 static int skeleton_rawdev_queue_setup(struct rte_rawdev *dev,
251 rte_rawdev_obj_t queue_conf)
254 struct skeleton_rawdev *skeldev;
255 struct skeleton_rawdev_queue *q;
257 SKELETON_PMD_FUNC_TRACE();
259 if (!dev || !queue_conf)
262 skeldev = skeleton_rawdev_get_priv(dev);
263 q = &skeldev->queues[queue_id];
265 if (skeldev->num_queues > queue_id &&
266 q->depth < SKELETON_QUEUE_MAX_DEPTH) {
267 rte_memcpy(q, queue_conf,
268 sizeof(struct skeleton_rawdev_queue));
269 clear_queue_bufs(queue_id);
271 SKELETON_PMD_ERR("Invalid queue configuration");
278 static int skeleton_rawdev_queue_release(struct rte_rawdev *dev,
282 struct skeleton_rawdev *skeldev;
284 SKELETON_PMD_FUNC_TRACE();
286 RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
288 skeldev = skeleton_rawdev_get_priv(dev);
290 if (skeldev->num_queues > queue_id) {
291 skeldev->queues[queue_id].state = SKELETON_QUEUE_DETACH;
292 skeldev->queues[queue_id].depth = SKELETON_QUEUE_DEF_DEPTH;
293 clear_queue_bufs(queue_id);
295 SKELETON_PMD_ERR("Invalid queue configuration");
302 static uint16_t skeleton_rawdev_queue_count(struct rte_rawdev *dev)
304 struct skeleton_rawdev *skeldev;
306 SKELETON_PMD_FUNC_TRACE();
308 RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
310 skeldev = skeleton_rawdev_get_priv(dev);
311 return skeldev->num_queues;
314 static int skeleton_rawdev_get_attr(struct rte_rawdev *dev,
315 const char *attr_name,
316 uint64_t *attr_value)
320 struct skeleton_rawdev *skeldev;
322 SKELETON_PMD_FUNC_TRACE();
324 if (!dev || !attr_name || !attr_value) {
325 SKELETON_PMD_ERR("Invalid arguments for getting attributes");
329 skeldev = skeleton_rawdev_get_priv(dev);
331 for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
332 if (!skeldev->attr[i].name)
335 if (!strncmp(skeldev->attr[i].name, attr_name,
336 SKELETON_ATTRIBUTE_NAME_MAX)) {
337 *attr_value = skeldev->attr[i].value;
339 SKELETON_PMD_DEBUG("Attribute (%s) Value (%" PRIu64 ")",
340 attr_name, *attr_value);
348 /* Attribute not found */
352 static int skeleton_rawdev_set_attr(struct rte_rawdev *dev,
353 const char *attr_name,
354 const uint64_t attr_value)
358 struct skeleton_rawdev *skeldev;
360 SKELETON_PMD_FUNC_TRACE();
362 if (!dev || !attr_name) {
363 SKELETON_PMD_ERR("Invalid arguments for setting attributes");
367 skeldev = skeleton_rawdev_get_priv(dev);
369 /* Check if attribute already exists */
370 for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
371 if (!skeldev->attr[i].name)
374 if (!strncmp(skeldev->attr[i].name, attr_name,
375 SKELETON_ATTRIBUTE_NAME_MAX)) {
377 skeldev->attr[i].value = attr_value;
384 if (i < (SKELETON_MAX_ATTRIBUTES - 1)) {
385 /* There is still space to insert one more */
386 skeldev->attr[i].name = strdup(attr_name);
387 if (!skeldev->attr[i].name)
390 skeldev->attr[i].value = attr_value;
398 static int skeleton_rawdev_enqueue_bufs(struct rte_rawdev *dev,
399 struct rte_rawdev_buf **buffers,
401 rte_rawdev_obj_t context)
407 /* context is essentially the queue_id which is
408 * transferred as opaque object through the library layer. This can
409 * help in complex implementation which require more information than
410 * just an integer - for example, a queue-pair.
412 q_id = *((int *)context);
414 for (i = 0; i < count; i++)
415 queue_buf[q_id].bufs[i] = buffers[i]->buf_addr;
420 static int skeleton_rawdev_dequeue_bufs(struct rte_rawdev *dev,
421 struct rte_rawdev_buf **buffers,
423 rte_rawdev_obj_t context)
429 /* context is essentially the queue_id which is
430 * transferred as opaque object through the library layer. This can
431 * help in complex implementation which require more information than
432 * just an integer - for example, a queue-pair.
434 q_id = *((int *)context);
436 for (i = 0; i < count; i++)
437 buffers[i]->buf_addr = queue_buf[q_id].bufs[i];
442 static int skeleton_rawdev_dump(struct rte_rawdev *dev, FILE *f)
450 static int skeleton_rawdev_firmware_status_get(struct rte_rawdev *dev,
451 rte_rawdev_obj_t status_info)
453 struct skeleton_rawdev *skeldev;
455 SKELETON_PMD_FUNC_TRACE();
457 skeldev = skeleton_rawdev_get_priv(dev);
459 RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
462 memcpy(status_info, &skeldev->fw.firmware_state,
463 sizeof(enum skeleton_firmware_state));
469 static int skeleton_rawdev_firmware_version_get(
470 struct rte_rawdev *dev,
471 rte_rawdev_obj_t version_info)
473 struct skeleton_rawdev *skeldev;
474 struct skeleton_firmware_version_info *vi;
476 SKELETON_PMD_FUNC_TRACE();
478 skeldev = skeleton_rawdev_get_priv(dev);
481 vi->major = skeldev->fw.firmware_version.major;
482 vi->minor = skeldev->fw.firmware_version.minor;
483 vi->subrel = skeldev->fw.firmware_version.subrel;
488 static int skeleton_rawdev_firmware_load(struct rte_rawdev *dev,
489 rte_rawdev_obj_t firmware_buf)
491 struct skeleton_rawdev *skeldev;
493 SKELETON_PMD_FUNC_TRACE();
495 skeldev = skeleton_rawdev_get_priv(dev);
497 /* firmware_buf is a mmaped, possibly DMA'able area, buffer. Being
498 * dummy, all this does is check if firmware_buf is not NULL and
499 * sets the state of the firmware.
504 skeldev->fw.firmware_state = SKELETON_FW_LOADED;
509 static int skeleton_rawdev_firmware_unload(struct rte_rawdev *dev)
511 struct skeleton_rawdev *skeldev;
513 SKELETON_PMD_FUNC_TRACE();
515 skeldev = skeleton_rawdev_get_priv(dev);
517 skeldev->fw.firmware_state = SKELETON_FW_READY;
522 static const struct rte_rawdev_ops skeleton_rawdev_ops = {
523 .dev_info_get = skeleton_rawdev_info_get,
524 .dev_configure = skeleton_rawdev_configure,
525 .dev_start = skeleton_rawdev_start,
526 .dev_stop = skeleton_rawdev_stop,
527 .dev_close = skeleton_rawdev_close,
528 .dev_reset = skeleton_rawdev_reset,
530 .queue_def_conf = skeleton_rawdev_queue_def_conf,
531 .queue_setup = skeleton_rawdev_queue_setup,
532 .queue_release = skeleton_rawdev_queue_release,
533 .queue_count = skeleton_rawdev_queue_count,
535 .attr_get = skeleton_rawdev_get_attr,
536 .attr_set = skeleton_rawdev_set_attr,
538 .enqueue_bufs = skeleton_rawdev_enqueue_bufs,
539 .dequeue_bufs = skeleton_rawdev_dequeue_bufs,
541 .dump = skeleton_rawdev_dump,
544 .xstats_get_names = NULL,
545 .xstats_get_by_name = NULL,
546 .xstats_reset = NULL,
548 .firmware_status_get = skeleton_rawdev_firmware_status_get,
549 .firmware_version_get = skeleton_rawdev_firmware_version_get,
550 .firmware_load = skeleton_rawdev_firmware_load,
551 .firmware_unload = skeleton_rawdev_firmware_unload,
553 .dev_selftest = test_rawdev_skeldev,
557 skeleton_rawdev_create(const char *name,
558 struct rte_vdev_device *vdev,
562 struct rte_rawdev *rawdev = NULL;
563 struct skeleton_rawdev *skeldev = NULL;
566 SKELETON_PMD_ERR("Invalid name of the device!");
571 /* Allocate device structure */
572 rawdev = rte_rawdev_pmd_allocate(name, sizeof(struct skeleton_rawdev),
574 if (rawdev == NULL) {
575 SKELETON_PMD_ERR("Unable to allocate rawdevice");
580 ret = rawdev->dev_id; /* return the rawdev id of new device */
582 rawdev->dev_ops = &skeleton_rawdev_ops;
583 rawdev->device = &vdev->device;
585 skeldev = skeleton_rawdev_get_priv(rawdev);
587 skeldev->device_id = SKELETON_DEVICE_ID;
588 skeldev->vendor_id = SKELETON_VENDOR_ID;
589 skeldev->capabilities = SKELETON_DEFAULT_CAPA;
591 memset(&skeldev->fw, 0, sizeof(struct skeleton_firmware));
593 skeldev->fw.firmware_state = SKELETON_FW_READY;
594 skeldev->fw.firmware_version.major = SKELETON_MAJOR_VER;
595 skeldev->fw.firmware_version.minor = SKELETON_MINOR_VER;
596 skeldev->fw.firmware_version.subrel = SKELETON_SUB_VER;
598 skeldev->device_state = SKELETON_DEV_STOPPED;
600 /* Reset/set to default queue configuration for this device */
601 for (i = 0; i < SKELETON_MAX_QUEUES; i++) {
602 skeldev->queues[i].state = SKELETON_QUEUE_DETACH;
603 skeldev->queues[i].depth = SKELETON_QUEUE_DEF_DEPTH;
606 /* Clear all allocated queue buffers */
607 for (i = 0; i < SKELETON_MAX_QUEUES; i++)
614 rte_rawdev_pmd_release(rawdev);
620 skeleton_rawdev_destroy(const char *name)
623 struct rte_rawdev *rdev;
626 SKELETON_PMD_ERR("Invalid device name");
630 rdev = rte_rawdev_pmd_get_named_dev(name);
632 SKELETON_PMD_ERR("Invalid device name (%s)", name);
636 /* rte_rawdev_close is called by pmd_release */
637 ret = rte_rawdev_pmd_release(rdev);
639 SKELETON_PMD_DEBUG("Device cleanup failed");
645 skeldev_get_selftest(const char *key __rte_unused,
655 skeldev_parse_vdev_args(struct rte_vdev_device *vdev)
661 static const char *const args[] = {
662 SKELETON_SELFTEST_ARG,
666 name = rte_vdev_device_name(vdev);
668 params = rte_vdev_device_args(vdev);
669 if (params != NULL && params[0] != '\0') {
670 struct rte_kvargs *kvlist = rte_kvargs_parse(params, args);
674 "Ignoring unsupported params supplied '%s'",
677 int ret = rte_kvargs_process(kvlist,
678 SKELETON_SELFTEST_ARG,
679 skeldev_get_selftest, &selftest);
680 if (ret != 0 || (selftest < 0 || selftest > 1)) {
681 SKELETON_PMD_ERR("%s: Error in parsing args",
683 rte_kvargs_free(kvlist);
684 ret = -1; /* enforce if selftest is invalid */
689 rte_kvargs_free(kvlist);
696 skeleton_rawdev_probe(struct rte_vdev_device *vdev)
699 int selftest = 0, ret = 0;
702 name = rte_vdev_device_name(vdev);
706 /* More than one instance is not supported */
707 if (skeldev_init_once) {
708 SKELETON_PMD_ERR("Multiple instance not supported for %s",
713 SKELETON_PMD_INFO("Init %s on NUMA node %d", name, rte_socket_id());
715 selftest = skeldev_parse_vdev_args(vdev);
716 /* In case of invalid argument, selftest != 1; ignore other values */
718 ret = skeleton_rawdev_create(name, vdev, rte_socket_id());
720 /* In case command line argument for 'selftest' was passed;
721 * if invalid arguments were passed, execution continues but
725 test_rawdev_skeldev(ret);
728 /* Device instance created; Second instance not possible */
729 skeldev_init_once = 1;
731 return ret < 0 ? ret : 0;
735 skeleton_rawdev_remove(struct rte_vdev_device *vdev)
740 name = rte_vdev_device_name(vdev);
744 SKELETON_PMD_INFO("Closing %s on NUMA node %d", name, rte_socket_id());
746 ret = skeleton_rawdev_destroy(name);
748 skeldev_init_once = 0;
753 static struct rte_vdev_driver skeleton_pmd_drv = {
754 .probe = skeleton_rawdev_probe,
755 .remove = skeleton_rawdev_remove
758 RTE_PMD_REGISTER_VDEV(SKELETON_PMD_RAWDEV_NAME, skeleton_pmd_drv);
759 RTE_LOG_REGISTER(skeleton_pmd_logtype, rawdev.skeleton, INFO);