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