rawdev: add private data size to info query
[dpdk.git] / drivers / raw / skeleton / skeleton_rawdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017 NXP
3  */
4
5 #include <assert.h>
6 #include <stdio.h>
7 #include <stdbool.h>
8 #include <errno.h>
9 #include <stdint.h>
10 #include <inttypes.h>
11 #include <string.h>
12
13 #include <rte_byteorder.h>
14 #include <rte_common.h>
15 #include <rte_debug.h>
16 #include <rte_dev.h>
17 #include <rte_eal.h>
18 #include <rte_kvargs.h>
19 #include <rte_log.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>
25
26 #include <rte_rawdev.h>
27 #include <rte_rawdev_pmd.h>
28
29 #include "skeleton_rawdev.h"
30
31 /* Count of instances */
32 static uint16_t skeldev_init_once;
33
34 /**< Rawdev Skeleton dummy driver name */
35 #define SKELETON_PMD_RAWDEV_NAME rawdev_skeleton
36
37 struct queue_buffers {
38         void *bufs[SKELETON_QUEUE_MAX_DEPTH];
39 };
40
41 static struct queue_buffers queue_buf[SKELETON_MAX_QUEUES] = {};
42 static void clear_queue_bufs(int queue_id);
43
44 static void skeleton_rawdev_info_get(struct rte_rawdev *dev,
45                                      rte_rawdev_obj_t dev_info,
46                                      size_t dev_info_size)
47 {
48         struct skeleton_rawdev *skeldev;
49         struct skeleton_rawdev_conf *skeldev_conf;
50
51         SKELETON_PMD_FUNC_TRACE();
52
53         if (!dev_info || dev_info_size != sizeof(*skeldev_conf)) {
54                 SKELETON_PMD_ERR("Invalid request");
55                 return;
56         }
57
58         skeldev = skeleton_rawdev_get_priv(dev);
59
60         skeldev_conf = dev_info;
61
62         skeldev_conf->num_queues = skeldev->num_queues;
63         skeldev_conf->capabilities = skeldev->capabilities;
64         skeldev_conf->device_state = skeldev->device_state;
65         skeldev_conf->firmware_state = skeldev->fw.firmware_state;
66 }
67
68 static int skeleton_rawdev_configure(const struct rte_rawdev *dev,
69                                      rte_rawdev_obj_t config)
70 {
71         struct skeleton_rawdev *skeldev;
72         struct skeleton_rawdev_conf *skeldev_conf;
73
74         SKELETON_PMD_FUNC_TRACE();
75
76         RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
77
78         if (!config) {
79                 SKELETON_PMD_ERR("Invalid configuration");
80                 return -EINVAL;
81         }
82
83         skeldev_conf = config;
84         skeldev = skeleton_rawdev_get_priv(dev);
85
86         if (skeldev_conf->num_queues <= SKELETON_MAX_QUEUES)
87                 skeldev->num_queues = skeldev_conf->num_queues;
88         else
89                 return -EINVAL;
90
91         skeldev->capabilities = skeldev_conf->capabilities;
92         skeldev->num_queues = skeldev_conf->num_queues;
93
94         return 0;
95 }
96
97 static int skeleton_rawdev_start(struct rte_rawdev *dev)
98 {
99         int ret = 0;
100         struct skeleton_rawdev *skeldev;
101         enum skeleton_firmware_state fw_state;
102         enum skeleton_device_state device_state;
103
104         SKELETON_PMD_FUNC_TRACE();
105
106         RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
107
108         skeldev = skeleton_rawdev_get_priv(dev);
109
110         fw_state = skeldev->fw.firmware_state;
111         device_state = skeldev->device_state;
112
113         if (fw_state == SKELETON_FW_LOADED &&
114                 device_state == SKELETON_DEV_STOPPED) {
115                 skeldev->device_state = SKELETON_DEV_RUNNING;
116         } else {
117                 SKELETON_PMD_ERR("Device not ready for starting");
118                 ret = -EINVAL;
119         }
120
121         return ret;
122 }
123
124 static void skeleton_rawdev_stop(struct rte_rawdev *dev)
125 {
126         struct skeleton_rawdev *skeldev;
127
128         SKELETON_PMD_FUNC_TRACE();
129
130         if (dev) {
131                 skeldev = skeleton_rawdev_get_priv(dev);
132                 skeldev->device_state = SKELETON_DEV_STOPPED;
133         }
134 }
135
136 static void
137 reset_queues(struct skeleton_rawdev *skeldev)
138 {
139         int i;
140
141         for (i = 0; i < SKELETON_MAX_QUEUES; i++) {
142                 skeldev->queues[i].depth = SKELETON_QUEUE_DEF_DEPTH;
143                 skeldev->queues[i].state = SKELETON_QUEUE_DETACH;
144         }
145 }
146
147 static void
148 reset_attribute_table(struct skeleton_rawdev *skeldev)
149 {
150         int i;
151
152         for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
153                 if (skeldev->attr[i].name) {
154                         free(skeldev->attr[i].name);
155                         skeldev->attr[i].name = NULL;
156                 }
157         }
158 }
159
160 static int skeleton_rawdev_close(struct rte_rawdev *dev)
161 {
162         int ret = 0, i;
163         struct skeleton_rawdev *skeldev;
164         enum skeleton_firmware_state fw_state;
165         enum skeleton_device_state device_state;
166
167         SKELETON_PMD_FUNC_TRACE();
168
169         RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
170
171         skeldev = skeleton_rawdev_get_priv(dev);
172
173         fw_state = skeldev->fw.firmware_state;
174         device_state = skeldev->device_state;
175
176         reset_queues(skeldev);
177         reset_attribute_table(skeldev);
178
179         switch (fw_state) {
180         case SKELETON_FW_LOADED:
181                 if (device_state == SKELETON_DEV_RUNNING) {
182                         SKELETON_PMD_ERR("Cannot close running device");
183                         ret = -EINVAL;
184                 } else {
185                         /* Probably call fw reset here */
186                         skeldev->fw.firmware_state = SKELETON_FW_READY;
187                 }
188                 break;
189         case SKELETON_FW_READY:
190         case SKELETON_FW_ERROR:
191         default:
192                 SKELETON_PMD_DEBUG("Device already in stopped state");
193                 ret = -EINVAL;
194                 break;
195         }
196
197         /* Clear all allocated queues */
198         for (i = 0; i < SKELETON_MAX_QUEUES; i++)
199                 clear_queue_bufs(i);
200
201         return ret;
202 }
203
204 static int skeleton_rawdev_reset(struct rte_rawdev *dev)
205 {
206         struct skeleton_rawdev *skeldev;
207
208         SKELETON_PMD_FUNC_TRACE();
209
210         RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
211
212         skeldev = skeleton_rawdev_get_priv(dev);
213
214         SKELETON_PMD_DEBUG("Resetting device");
215         skeldev->fw.firmware_state = SKELETON_FW_READY;
216
217         return 0;
218 }
219
220 static void skeleton_rawdev_queue_def_conf(struct rte_rawdev *dev,
221                                            uint16_t queue_id,
222                                            rte_rawdev_obj_t queue_conf)
223 {
224         struct skeleton_rawdev *skeldev;
225         struct skeleton_rawdev_queue *skelq;
226
227         SKELETON_PMD_FUNC_TRACE();
228
229         if (!dev || !queue_conf)
230                 return;
231
232         skeldev = skeleton_rawdev_get_priv(dev);
233         skelq = &skeldev->queues[queue_id];
234
235         if (queue_id < SKELETON_MAX_QUEUES)
236                 rte_memcpy(queue_conf, skelq,
237                         sizeof(struct skeleton_rawdev_queue));
238 }
239
240 static void
241 clear_queue_bufs(int queue_id)
242 {
243         int i;
244
245         /* Clear buffers for queue_id */
246         for (i = 0; i < SKELETON_QUEUE_MAX_DEPTH; i++)
247                 queue_buf[queue_id].bufs[i] = NULL;
248 }
249
250 static int skeleton_rawdev_queue_setup(struct rte_rawdev *dev,
251                                        uint16_t queue_id,
252                                        rte_rawdev_obj_t queue_conf)
253 {
254         int ret = 0;
255         struct skeleton_rawdev *skeldev;
256         struct skeleton_rawdev_queue *q;
257
258         SKELETON_PMD_FUNC_TRACE();
259
260         if (!dev || !queue_conf)
261                 return -EINVAL;
262
263         skeldev = skeleton_rawdev_get_priv(dev);
264         q = &skeldev->queues[queue_id];
265
266         if (skeldev->num_queues > queue_id &&
267             q->depth < SKELETON_QUEUE_MAX_DEPTH) {
268                 rte_memcpy(q, queue_conf,
269                            sizeof(struct skeleton_rawdev_queue));
270                 clear_queue_bufs(queue_id);
271         } else {
272                 SKELETON_PMD_ERR("Invalid queue configuration");
273                 ret = -EINVAL;
274         }
275
276         return ret;
277 }
278
279 static int skeleton_rawdev_queue_release(struct rte_rawdev *dev,
280                                          uint16_t queue_id)
281 {
282         int ret = 0;
283         struct skeleton_rawdev *skeldev;
284
285         SKELETON_PMD_FUNC_TRACE();
286
287         RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
288
289         skeldev = skeleton_rawdev_get_priv(dev);
290
291         if (skeldev->num_queues > queue_id) {
292                 skeldev->queues[queue_id].state = SKELETON_QUEUE_DETACH;
293                 skeldev->queues[queue_id].depth = SKELETON_QUEUE_DEF_DEPTH;
294                 clear_queue_bufs(queue_id);
295         } else {
296                 SKELETON_PMD_ERR("Invalid queue configuration");
297                 ret = -EINVAL;
298         }
299
300         return ret;
301 }
302
303 static uint16_t skeleton_rawdev_queue_count(struct rte_rawdev *dev)
304 {
305         struct skeleton_rawdev *skeldev;
306
307         SKELETON_PMD_FUNC_TRACE();
308
309         RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
310
311         skeldev = skeleton_rawdev_get_priv(dev);
312         return skeldev->num_queues;
313 }
314
315 static int skeleton_rawdev_get_attr(struct rte_rawdev *dev,
316                                     const char *attr_name,
317                                     uint64_t *attr_value)
318 {
319         int i;
320         uint8_t done = 0;
321         struct skeleton_rawdev *skeldev;
322
323         SKELETON_PMD_FUNC_TRACE();
324
325         if (!dev || !attr_name || !attr_value) {
326                 SKELETON_PMD_ERR("Invalid arguments for getting attributes");
327                 return -EINVAL;
328         }
329
330         skeldev = skeleton_rawdev_get_priv(dev);
331
332         for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
333                 if (!skeldev->attr[i].name)
334                         continue;
335
336                 if (!strncmp(skeldev->attr[i].name, attr_name,
337                             SKELETON_ATTRIBUTE_NAME_MAX)) {
338                         *attr_value = skeldev->attr[i].value;
339                         done = 1;
340                         SKELETON_PMD_DEBUG("Attribute (%s) Value (%" PRIu64 ")",
341                                            attr_name, *attr_value);
342                         break;
343                 }
344         }
345
346         if (done)
347                 return 0;
348
349         /* Attribute not found */
350         return -EINVAL;
351 }
352
353 static int skeleton_rawdev_set_attr(struct rte_rawdev *dev,
354                                      const char *attr_name,
355                                      const uint64_t attr_value)
356 {
357         int i;
358         uint8_t done = 0;
359         struct skeleton_rawdev *skeldev;
360
361         SKELETON_PMD_FUNC_TRACE();
362
363         if (!dev || !attr_name) {
364                 SKELETON_PMD_ERR("Invalid arguments for setting attributes");
365                 return -EINVAL;
366         }
367
368         skeldev = skeleton_rawdev_get_priv(dev);
369
370         /* Check if attribute already exists */
371         for (i = 0; i < SKELETON_MAX_ATTRIBUTES; i++) {
372                 if (!skeldev->attr[i].name)
373                         break;
374
375                 if (!strncmp(skeldev->attr[i].name, attr_name,
376                              SKELETON_ATTRIBUTE_NAME_MAX)) {
377                         /* Update value */
378                         skeldev->attr[i].value = attr_value;
379                         done = 1;
380                         break;
381                 }
382         }
383
384         if (!done) {
385                 if (i < (SKELETON_MAX_ATTRIBUTES - 1)) {
386                         /* There is still space to insert one more */
387                         skeldev->attr[i].name = strdup(attr_name);
388                         if (!skeldev->attr[i].name)
389                                 return -ENOMEM;
390
391                         skeldev->attr[i].value = attr_value;
392                         return 0;
393                 }
394         }
395
396         return -EINVAL;
397 }
398
399 static int skeleton_rawdev_enqueue_bufs(struct rte_rawdev *dev,
400                                         struct rte_rawdev_buf **buffers,
401                                         unsigned int count,
402                                         rte_rawdev_obj_t context)
403 {
404         unsigned int i;
405         uint16_t q_id;
406         RTE_SET_USED(dev);
407
408         /* context is essentially the queue_id which is
409          * transferred as opaque object through the library layer. This can
410          * help in complex implementation which require more information than
411          * just an integer - for example, a queue-pair.
412          */
413         q_id = *((int *)context);
414
415         for (i = 0; i < count; i++)
416                 queue_buf[q_id].bufs[i] = buffers[i]->buf_addr;
417
418         return i;
419 }
420
421 static int skeleton_rawdev_dequeue_bufs(struct rte_rawdev *dev,
422                                         struct rte_rawdev_buf **buffers,
423                                         unsigned int count,
424                                         rte_rawdev_obj_t context)
425 {
426         unsigned int i;
427         uint16_t q_id;
428         RTE_SET_USED(dev);
429
430         /* context is essentially the queue_id which is
431          * transferred as opaque object through the library layer. This can
432          * help in complex implementation which require more information than
433          * just an integer - for example, a queue-pair.
434          */
435         q_id = *((int *)context);
436
437         for (i = 0; i < count; i++)
438                 buffers[i]->buf_addr = queue_buf[q_id].bufs[i];
439
440         return i;
441 }
442
443 static int skeleton_rawdev_dump(struct rte_rawdev *dev, FILE *f)
444 {
445         RTE_SET_USED(dev);
446         RTE_SET_USED(f);
447
448         return 0;
449 }
450
451 static int skeleton_rawdev_firmware_status_get(struct rte_rawdev *dev,
452                                                rte_rawdev_obj_t status_info)
453 {
454         struct skeleton_rawdev *skeldev;
455
456         SKELETON_PMD_FUNC_TRACE();
457
458         skeldev = skeleton_rawdev_get_priv(dev);
459
460         RTE_FUNC_PTR_OR_ERR_RET(dev, -EINVAL);
461
462         if (status_info)
463                 memcpy(status_info, &skeldev->fw.firmware_state,
464                         sizeof(enum skeleton_firmware_state));
465
466         return 0;
467 }
468
469
470 static int skeleton_rawdev_firmware_version_get(
471                                         struct rte_rawdev *dev,
472                                         rte_rawdev_obj_t version_info)
473 {
474         struct skeleton_rawdev *skeldev;
475         struct skeleton_firmware_version_info *vi;
476
477         SKELETON_PMD_FUNC_TRACE();
478
479         skeldev = skeleton_rawdev_get_priv(dev);
480         vi = version_info;
481
482         vi->major = skeldev->fw.firmware_version.major;
483         vi->minor = skeldev->fw.firmware_version.minor;
484         vi->subrel = skeldev->fw.firmware_version.subrel;
485
486         return 0;
487 }
488
489 static int skeleton_rawdev_firmware_load(struct rte_rawdev *dev,
490                                          rte_rawdev_obj_t firmware_buf)
491 {
492         struct skeleton_rawdev *skeldev;
493
494         SKELETON_PMD_FUNC_TRACE();
495
496         skeldev = skeleton_rawdev_get_priv(dev);
497
498         /* firmware_buf is a mmaped, possibly DMA'able area, buffer. Being
499          * dummy, all this does is check if firmware_buf is not NULL and
500          * sets the state of the firmware.
501          */
502         if (!firmware_buf)
503                 return -EINVAL;
504
505         skeldev->fw.firmware_state = SKELETON_FW_LOADED;
506
507         return 0;
508 }
509
510 static int skeleton_rawdev_firmware_unload(struct rte_rawdev *dev)
511 {
512         struct skeleton_rawdev *skeldev;
513
514         SKELETON_PMD_FUNC_TRACE();
515
516         skeldev = skeleton_rawdev_get_priv(dev);
517
518         skeldev->fw.firmware_state = SKELETON_FW_READY;
519
520         return 0;
521 }
522
523 static const struct rte_rawdev_ops skeleton_rawdev_ops = {
524         .dev_info_get = skeleton_rawdev_info_get,
525         .dev_configure = skeleton_rawdev_configure,
526         .dev_start = skeleton_rawdev_start,
527         .dev_stop = skeleton_rawdev_stop,
528         .dev_close = skeleton_rawdev_close,
529         .dev_reset = skeleton_rawdev_reset,
530
531         .queue_def_conf = skeleton_rawdev_queue_def_conf,
532         .queue_setup = skeleton_rawdev_queue_setup,
533         .queue_release = skeleton_rawdev_queue_release,
534         .queue_count = skeleton_rawdev_queue_count,
535
536         .attr_get = skeleton_rawdev_get_attr,
537         .attr_set = skeleton_rawdev_set_attr,
538
539         .enqueue_bufs = skeleton_rawdev_enqueue_bufs,
540         .dequeue_bufs = skeleton_rawdev_dequeue_bufs,
541
542         .dump = skeleton_rawdev_dump,
543
544         .xstats_get = NULL,
545         .xstats_get_names = NULL,
546         .xstats_get_by_name = NULL,
547         .xstats_reset = NULL,
548
549         .firmware_status_get = skeleton_rawdev_firmware_status_get,
550         .firmware_version_get = skeleton_rawdev_firmware_version_get,
551         .firmware_load = skeleton_rawdev_firmware_load,
552         .firmware_unload = skeleton_rawdev_firmware_unload,
553
554         .dev_selftest = test_rawdev_skeldev,
555 };
556
557 static int
558 skeleton_rawdev_create(const char *name,
559                        struct rte_vdev_device *vdev,
560                        int socket_id)
561 {
562         int ret = 0, i;
563         struct rte_rawdev *rawdev = NULL;
564         struct skeleton_rawdev *skeldev = NULL;
565
566         if (!name) {
567                 SKELETON_PMD_ERR("Invalid name of the device!");
568                 ret = -EINVAL;
569                 goto cleanup;
570         }
571
572         /* Allocate device structure */
573         rawdev = rte_rawdev_pmd_allocate(name, sizeof(struct skeleton_rawdev),
574                                          socket_id);
575         if (rawdev == NULL) {
576                 SKELETON_PMD_ERR("Unable to allocate rawdevice");
577                 ret = -EINVAL;
578                 goto cleanup;
579         }
580
581         ret = rawdev->dev_id; /* return the rawdev id of new device */
582
583         rawdev->dev_ops = &skeleton_rawdev_ops;
584         rawdev->device = &vdev->device;
585
586         skeldev = skeleton_rawdev_get_priv(rawdev);
587
588         skeldev->device_id = SKELETON_DEVICE_ID;
589         skeldev->vendor_id = SKELETON_VENDOR_ID;
590         skeldev->capabilities = SKELETON_DEFAULT_CAPA;
591
592         memset(&skeldev->fw, 0, sizeof(struct skeleton_firmware));
593
594         skeldev->fw.firmware_state = SKELETON_FW_READY;
595         skeldev->fw.firmware_version.major = SKELETON_MAJOR_VER;
596         skeldev->fw.firmware_version.minor = SKELETON_MINOR_VER;
597         skeldev->fw.firmware_version.subrel = SKELETON_SUB_VER;
598
599         skeldev->device_state = SKELETON_DEV_STOPPED;
600
601         /* Reset/set to default queue configuration for this device */
602         for (i = 0; i < SKELETON_MAX_QUEUES; i++) {
603                 skeldev->queues[i].state = SKELETON_QUEUE_DETACH;
604                 skeldev->queues[i].depth = SKELETON_QUEUE_DEF_DEPTH;
605         }
606
607         /* Clear all allocated queue buffers */
608         for (i = 0; i < SKELETON_MAX_QUEUES; i++)
609                 clear_queue_bufs(i);
610
611         return ret;
612
613 cleanup:
614         if (rawdev)
615                 rte_rawdev_pmd_release(rawdev);
616
617         return ret;
618 }
619
620 static int
621 skeleton_rawdev_destroy(const char *name)
622 {
623         int ret;
624         struct rte_rawdev *rdev;
625
626         if (!name) {
627                 SKELETON_PMD_ERR("Invalid device name");
628                 return -EINVAL;
629         }
630
631         rdev = rte_rawdev_pmd_get_named_dev(name);
632         if (!rdev) {
633                 SKELETON_PMD_ERR("Invalid device name (%s)", name);
634                 return -EINVAL;
635         }
636
637         /* rte_rawdev_close is called by pmd_release */
638         ret = rte_rawdev_pmd_release(rdev);
639         if (ret)
640                 SKELETON_PMD_DEBUG("Device cleanup failed");
641
642         return 0;
643 }
644
645 static int
646 skeldev_get_selftest(const char *key __rte_unused,
647                      const char *value,
648                      void *opaque)
649 {
650         int *flag = opaque;
651         *flag = atoi(value);
652         return 0;
653 }
654
655 static int
656 skeldev_parse_vdev_args(struct rte_vdev_device *vdev)
657 {
658         int selftest = 0;
659         const char *name;
660         const char *params;
661
662         static const char *const args[] = {
663                 SKELETON_SELFTEST_ARG,
664                 NULL
665         };
666
667         name = rte_vdev_device_name(vdev);
668
669         params = rte_vdev_device_args(vdev);
670         if (params != NULL && params[0] != '\0') {
671                 struct rte_kvargs *kvlist = rte_kvargs_parse(params, args);
672
673                 if (!kvlist) {
674                         SKELETON_PMD_INFO(
675                                 "Ignoring unsupported params supplied '%s'",
676                                 name);
677                 } else {
678                         int ret = rte_kvargs_process(kvlist,
679                                         SKELETON_SELFTEST_ARG,
680                                         skeldev_get_selftest, &selftest);
681                         if (ret != 0 || (selftest < 0 || selftest > 1)) {
682                                 SKELETON_PMD_ERR("%s: Error in parsing args",
683                                                  name);
684                                 rte_kvargs_free(kvlist);
685                                 ret = -1; /* enforce if selftest is invalid */
686                                 return ret;
687                         }
688                 }
689
690                 rte_kvargs_free(kvlist);
691         }
692
693         return selftest;
694 }
695
696 static int
697 skeleton_rawdev_probe(struct rte_vdev_device *vdev)
698 {
699         const char *name;
700         int selftest = 0, ret = 0;
701
702
703         name = rte_vdev_device_name(vdev);
704         if (name == NULL)
705                 return -EINVAL;
706
707         /* More than one instance is not supported */
708         if (skeldev_init_once) {
709                 SKELETON_PMD_ERR("Multiple instance not supported for %s",
710                                  name);
711                 return -EINVAL;
712         }
713
714         SKELETON_PMD_INFO("Init %s on NUMA node %d", name, rte_socket_id());
715
716         selftest = skeldev_parse_vdev_args(vdev);
717         /* In case of invalid argument, selftest != 1; ignore other values */
718
719         ret = skeleton_rawdev_create(name, vdev, rte_socket_id());
720         if (ret >= 0) {
721                 /* In case command line argument for 'selftest' was passed;
722                  * if invalid arguments were passed, execution continues but
723                  * without selftest.
724                  */
725                 if (selftest == 1)
726                         test_rawdev_skeldev(ret);
727         }
728
729         /* Device instance created; Second instance not possible */
730         skeldev_init_once = 1;
731
732         return ret < 0 ? ret : 0;
733 }
734
735 static int
736 skeleton_rawdev_remove(struct rte_vdev_device *vdev)
737 {
738         const char *name;
739         int ret;
740
741         name = rte_vdev_device_name(vdev);
742         if (name == NULL)
743                 return -1;
744
745         SKELETON_PMD_INFO("Closing %s on NUMA node %d", name, rte_socket_id());
746
747         ret = skeleton_rawdev_destroy(name);
748         if (!ret)
749                 skeldev_init_once = 0;
750
751         return ret;
752 }
753
754 static struct rte_vdev_driver skeleton_pmd_drv = {
755         .probe = skeleton_rawdev_probe,
756         .remove = skeleton_rawdev_remove
757 };
758
759 RTE_PMD_REGISTER_VDEV(SKELETON_PMD_RAWDEV_NAME, skeleton_pmd_drv);
760 RTE_LOG_REGISTER(skeleton_pmd_logtype, rawdev.skeleton, INFO);