1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation. 3 * Copyright(c) 2014 6WIND S.A. 4 */ 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <sys/queue.h> 10 11 #include <bus_driver.h> 12 #include <rte_class.h> 13 #include <dev_driver.h> 14 #include <rte_devargs.h> 15 #include <rte_errno.h> 16 #include <rte_log.h> 17 #include <rte_spinlock.h> 18 #include <rte_string_fns.h> 19 20 #include "eal_private.h" 21 #include "hotplug_mp.h" 22 23 const char * 24 rte_driver_name(const struct rte_driver *driver) 25 { 26 return driver->name; 27 } 28 29 const struct rte_bus * 30 rte_dev_bus(const struct rte_device *dev) 31 { 32 return dev->bus; 33 } 34 35 const char * 36 rte_dev_bus_info(const struct rte_device *dev) 37 { 38 return dev->bus_info; 39 } 40 41 const struct rte_devargs * 42 rte_dev_devargs(const struct rte_device *dev) 43 { 44 return dev->devargs; 45 } 46 47 const struct rte_driver * 48 rte_dev_driver(const struct rte_device *dev) 49 { 50 return dev->driver; 51 } 52 53 const char * 54 rte_dev_name(const struct rte_device *dev) 55 { 56 return dev->name; 57 } 58 59 int 60 rte_dev_numa_node(const struct rte_device *dev) 61 { 62 return dev->numa_node; 63 } 64 65 /** 66 * The device event callback description. 67 * 68 * It contains callback address to be registered by user application, 69 * the pointer to the parameters for callback, and the device name. 70 */ 71 struct dev_event_callback { 72 TAILQ_ENTRY(dev_event_callback) next; /**< Callbacks list */ 73 rte_dev_event_cb_fn cb_fn; /**< Callback address */ 74 void *cb_arg; /**< Callback parameter */ 75 char *dev_name; /**< Callback device name, NULL is for all device */ 76 uint32_t active; /**< Callback is executing */ 77 }; 78 79 /** @internal Structure to keep track of registered callbacks */ 80 TAILQ_HEAD(dev_event_cb_list, dev_event_callback); 81 82 /* The device event callback list for all registered callbacks. */ 83 static struct dev_event_cb_list dev_event_cbs; 84 85 /* spinlock for device callbacks */ 86 static rte_spinlock_t dev_event_lock = RTE_SPINLOCK_INITIALIZER; 87 88 struct dev_next_ctx { 89 struct rte_dev_iterator *it; 90 const char *bus_str; 91 const char *cls_str; 92 }; 93 94 #define CTX(it, bus_str, cls_str) \ 95 (&(const struct dev_next_ctx){ \ 96 .it = it, \ 97 .bus_str = bus_str, \ 98 .cls_str = cls_str, \ 99 }) 100 101 #define ITCTX(ptr) \ 102 (((struct dev_next_ctx *)(intptr_t)ptr)->it) 103 104 #define BUSCTX(ptr) \ 105 (((struct dev_next_ctx *)(intptr_t)ptr)->bus_str) 106 107 #define CLSCTX(ptr) \ 108 (((struct dev_next_ctx *)(intptr_t)ptr)->cls_str) 109 110 static int cmp_dev_name(const struct rte_device *dev, const void *_name) 111 { 112 const char *name = _name; 113 114 return strcmp(dev->name, name); 115 } 116 117 int 118 rte_dev_is_probed(const struct rte_device *dev) 119 { 120 /* The field driver should be set only when the probe is successful. */ 121 return dev->driver != NULL; 122 } 123 124 /* helper function to build devargs, caller should free the memory */ 125 static int 126 build_devargs(const char *busname, const char *devname, 127 const char *drvargs, char **devargs) 128 { 129 int length; 130 131 length = snprintf(NULL, 0, "%s:%s,%s", busname, devname, drvargs); 132 if (length < 0) 133 return -EINVAL; 134 135 *devargs = malloc(length + 1); 136 if (*devargs == NULL) 137 return -ENOMEM; 138 139 length = snprintf(*devargs, length + 1, "%s:%s,%s", 140 busname, devname, drvargs); 141 if (length < 0) { 142 free(*devargs); 143 return -EINVAL; 144 } 145 146 return 0; 147 } 148 149 int 150 rte_eal_hotplug_add(const char *busname, const char *devname, 151 const char *drvargs) 152 { 153 154 char *devargs; 155 int ret; 156 157 ret = build_devargs(busname, devname, drvargs, &devargs); 158 if (ret != 0) 159 return ret; 160 161 ret = rte_dev_probe(devargs); 162 free(devargs); 163 164 return ret; 165 } 166 167 /* probe device at local process. */ 168 int 169 local_dev_probe(const char *devargs, struct rte_device **new_dev) 170 { 171 struct rte_device *dev; 172 struct rte_devargs *da; 173 int ret; 174 175 *new_dev = NULL; 176 da = calloc(1, sizeof(*da)); 177 if (da == NULL) 178 return -ENOMEM; 179 180 ret = rte_devargs_parse(da, devargs); 181 if (ret) 182 goto err_devarg; 183 184 if (da->bus->plug == NULL) { 185 EAL_LOG(ERR, "Function plug not supported by bus (%s)", 186 da->bus->name); 187 ret = -ENOTSUP; 188 goto err_devarg; 189 } 190 191 ret = rte_devargs_insert(&da); 192 if (ret) 193 goto err_devarg; 194 195 /* the rte_devargs will be referenced in the matching rte_device */ 196 ret = da->bus->scan(); 197 if (ret) 198 goto err_devarg; 199 200 dev = da->bus->find_device(NULL, cmp_dev_name, da->name); 201 if (dev == NULL) { 202 EAL_LOG(ERR, "Cannot find device (%s)", 203 da->name); 204 ret = -ENODEV; 205 goto err_devarg; 206 } 207 /* Since there is a matching device, it is now its responsibility 208 * to manage the devargs we've just inserted. From this point 209 * those devargs shouldn't be removed manually anymore. 210 */ 211 212 ret = dev->bus->plug(dev); 213 if (ret > 0) 214 ret = -ENOTSUP; 215 216 if (ret && !rte_dev_is_probed(dev)) { /* if hasn't ever succeeded */ 217 EAL_LOG(ERR, "Driver cannot attach the device (%s)", 218 dev->name); 219 return ret; 220 } 221 222 *new_dev = dev; 223 return ret; 224 225 err_devarg: 226 if (rte_devargs_remove(da) != 0) { 227 rte_devargs_reset(da); 228 free(da); 229 } 230 return ret; 231 } 232 233 int 234 rte_dev_probe(const char *devargs) 235 { 236 struct eal_dev_mp_req req; 237 struct rte_device *dev; 238 int ret; 239 240 memset(&req, 0, sizeof(req)); 241 req.t = EAL_DEV_REQ_TYPE_ATTACH; 242 strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN); 243 244 if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 245 /** 246 * If in secondary process, just send IPC request to 247 * primary process. 248 */ 249 ret = eal_dev_hotplug_request_to_primary(&req); 250 if (ret != 0) { 251 EAL_LOG(ERR, 252 "Failed to send hotplug request to primary"); 253 return -ENOMSG; 254 } 255 if (req.result != 0) 256 EAL_LOG(ERR, 257 "Failed to hotplug add device"); 258 return req.result; 259 } 260 261 /* attach a shared device from primary start from here: */ 262 263 /* primary attach the new device itself. */ 264 ret = local_dev_probe(devargs, &dev); 265 266 if (ret != 0) { 267 EAL_LOG(ERR, 268 "Failed to attach device on primary process"); 269 270 /** 271 * it is possible that secondary process failed to attached a 272 * device that primary process have during initialization, 273 * so for -EEXIST case, we still need to sync with secondary 274 * process. 275 */ 276 if (ret != -EEXIST) 277 return ret; 278 } 279 280 /* primary send attach sync request to secondary. */ 281 ret = eal_dev_hotplug_request_to_secondary(&req); 282 283 /* if any communication error, we need to rollback. */ 284 if (ret != 0) { 285 EAL_LOG(ERR, 286 "Failed to send hotplug add request to secondary"); 287 ret = -ENOMSG; 288 goto rollback; 289 } 290 291 /** 292 * if any secondary failed to attach, we need to consider if rollback 293 * is necessary. 294 */ 295 if (req.result != 0) { 296 EAL_LOG(ERR, 297 "Failed to attach device on secondary process"); 298 ret = req.result; 299 300 /* for -EEXIST, we don't need to rollback. */ 301 if (ret == -EEXIST) 302 return ret; 303 goto rollback; 304 } 305 306 return 0; 307 308 rollback: 309 req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK; 310 311 /* primary send rollback request to secondary. */ 312 if (eal_dev_hotplug_request_to_secondary(&req) != 0) 313 EAL_LOG(WARNING, 314 "Failed to rollback device attach on secondary." 315 "Devices in secondary may not sync with primary"); 316 317 /* primary rollback itself. */ 318 if (local_dev_remove(dev) != 0) 319 EAL_LOG(WARNING, 320 "Failed to rollback device attach on primary." 321 "Devices in secondary may not sync with primary"); 322 323 return ret; 324 } 325 326 int 327 rte_eal_hotplug_remove(const char *busname, const char *devname) 328 { 329 struct rte_device *dev; 330 struct rte_bus *bus; 331 332 bus = rte_bus_find_by_name(busname); 333 if (bus == NULL) { 334 EAL_LOG(ERR, "Cannot find bus (%s)", busname); 335 return -ENOENT; 336 } 337 338 dev = bus->find_device(NULL, cmp_dev_name, devname); 339 if (dev == NULL) { 340 EAL_LOG(ERR, "Cannot find plugged device (%s)", devname); 341 return -EINVAL; 342 } 343 344 return rte_dev_remove(dev); 345 } 346 347 /* remove device at local process. */ 348 int 349 local_dev_remove(struct rte_device *dev) 350 { 351 int ret; 352 353 if (dev->bus->unplug == NULL) { 354 EAL_LOG(ERR, "Function unplug not supported by bus (%s)", 355 dev->bus->name); 356 return -ENOTSUP; 357 } 358 359 ret = dev->bus->unplug(dev); 360 if (ret) { 361 EAL_LOG(ERR, "Driver cannot detach the device (%s)", 362 dev->name); 363 return (ret < 0) ? ret : -ENOENT; 364 } 365 366 return 0; 367 } 368 369 int 370 rte_dev_remove(struct rte_device *dev) 371 { 372 struct eal_dev_mp_req req; 373 char *devargs; 374 int ret; 375 376 if (!rte_dev_is_probed(dev)) { 377 EAL_LOG(ERR, "Device is not probed"); 378 return -ENOENT; 379 } 380 381 ret = build_devargs(dev->bus->name, dev->name, "", &devargs); 382 if (ret != 0) 383 return ret; 384 385 memset(&req, 0, sizeof(req)); 386 req.t = EAL_DEV_REQ_TYPE_DETACH; 387 strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN); 388 free(devargs); 389 390 if (rte_eal_process_type() != RTE_PROC_PRIMARY) { 391 /** 392 * If in secondary process, just send IPC request to 393 * primary process. 394 */ 395 ret = eal_dev_hotplug_request_to_primary(&req); 396 if (ret != 0) { 397 EAL_LOG(ERR, 398 "Failed to send hotplug request to primary"); 399 return -ENOMSG; 400 } 401 if (req.result != 0) 402 EAL_LOG(ERR, 403 "Failed to hotplug remove device"); 404 return req.result; 405 } 406 407 /* detach a device from primary start from here: */ 408 409 /* primary send detach sync request to secondary */ 410 ret = eal_dev_hotplug_request_to_secondary(&req); 411 412 /** 413 * if communication error, we need to rollback, because it is possible 414 * part of the secondary processes still detached it successfully. 415 */ 416 if (ret != 0) { 417 EAL_LOG(ERR, 418 "Failed to send device detach request to secondary"); 419 ret = -ENOMSG; 420 goto rollback; 421 } 422 423 /** 424 * if any secondary failed to detach, we need to consider if rollback 425 * is necessary. 426 */ 427 if (req.result != 0) { 428 EAL_LOG(ERR, 429 "Failed to detach device on secondary process"); 430 ret = req.result; 431 /** 432 * if -ENOENT, we don't need to rollback, since devices is 433 * already detached on secondary process. 434 */ 435 if (ret != -ENOENT) 436 goto rollback; 437 } 438 439 /* primary detach the device itself. */ 440 ret = local_dev_remove(dev); 441 442 /* if primary failed, still need to consider if rollback is necessary */ 443 if (ret != 0) { 444 EAL_LOG(ERR, 445 "Failed to detach device on primary process"); 446 /* if -ENOENT, we don't need to rollback */ 447 if (ret == -ENOENT) 448 return ret; 449 goto rollback; 450 } 451 452 return 0; 453 454 rollback: 455 req.t = EAL_DEV_REQ_TYPE_DETACH_ROLLBACK; 456 457 /* primary send rollback request to secondary. */ 458 if (eal_dev_hotplug_request_to_secondary(&req) != 0) 459 EAL_LOG(WARNING, 460 "Failed to rollback device detach on secondary." 461 "Devices in secondary may not sync with primary"); 462 463 return ret; 464 } 465 466 int 467 rte_dev_event_callback_register(const char *device_name, 468 rte_dev_event_cb_fn cb_fn, 469 void *cb_arg) 470 { 471 struct dev_event_callback *event_cb; 472 int ret; 473 474 if (!cb_fn) 475 return -EINVAL; 476 477 rte_spinlock_lock(&dev_event_lock); 478 479 if (TAILQ_EMPTY(&dev_event_cbs)) 480 TAILQ_INIT(&dev_event_cbs); 481 482 TAILQ_FOREACH(event_cb, &dev_event_cbs, next) { 483 if (event_cb->cb_fn == cb_fn && event_cb->cb_arg == cb_arg) { 484 if (device_name == NULL && event_cb->dev_name == NULL) 485 break; 486 if (device_name == NULL || event_cb->dev_name == NULL) 487 continue; 488 if (!strcmp(event_cb->dev_name, device_name)) 489 break; 490 } 491 } 492 493 /* create a new callback. */ 494 if (event_cb == NULL) { 495 event_cb = malloc(sizeof(struct dev_event_callback)); 496 if (event_cb != NULL) { 497 event_cb->cb_fn = cb_fn; 498 event_cb->cb_arg = cb_arg; 499 event_cb->active = 0; 500 if (!device_name) { 501 event_cb->dev_name = NULL; 502 } else { 503 event_cb->dev_name = strdup(device_name); 504 if (event_cb->dev_name == NULL) { 505 ret = -ENOMEM; 506 goto error; 507 } 508 } 509 TAILQ_INSERT_TAIL(&dev_event_cbs, event_cb, next); 510 } else { 511 EAL_LOG(ERR, 512 "Failed to allocate memory for device " 513 "event callback."); 514 ret = -ENOMEM; 515 goto error; 516 } 517 } else { 518 EAL_LOG(ERR, 519 "The callback is already exist, no need " 520 "to register again."); 521 event_cb = NULL; 522 ret = -EEXIST; 523 goto error; 524 } 525 526 rte_spinlock_unlock(&dev_event_lock); 527 return 0; 528 error: 529 free(event_cb); 530 rte_spinlock_unlock(&dev_event_lock); 531 return ret; 532 } 533 534 int 535 rte_dev_event_callback_unregister(const char *device_name, 536 rte_dev_event_cb_fn cb_fn, 537 void *cb_arg) 538 { 539 int ret = 0; 540 struct dev_event_callback *event_cb, *next; 541 542 if (!cb_fn) 543 return -EINVAL; 544 545 rte_spinlock_lock(&dev_event_lock); 546 /*walk through the callbacks and remove all that match. */ 547 for (event_cb = TAILQ_FIRST(&dev_event_cbs); event_cb != NULL; 548 event_cb = next) { 549 550 next = TAILQ_NEXT(event_cb, next); 551 552 if (device_name != NULL && event_cb->dev_name != NULL) { 553 if (strcmp(event_cb->dev_name, device_name)) 554 continue; 555 } else if (device_name != NULL) { 556 continue; 557 } 558 559 /* Remove only matching callback with arg */ 560 if (event_cb->cb_fn != cb_fn || 561 (cb_arg != (void *)-1 && event_cb->cb_arg != cb_arg)) 562 continue; 563 564 /* 565 * if this callback is not executing right now, 566 * then remove it. 567 */ 568 if (event_cb->active == 0) { 569 TAILQ_REMOVE(&dev_event_cbs, event_cb, next); 570 free(event_cb->dev_name); 571 free(event_cb); 572 ret++; 573 } else { 574 ret = -EAGAIN; 575 break; 576 } 577 } 578 579 /* this callback is not be registered */ 580 if (ret == 0) 581 ret = -ENOENT; 582 583 rte_spinlock_unlock(&dev_event_lock); 584 return ret; 585 } 586 587 void 588 rte_dev_event_callback_process(const char *device_name, 589 enum rte_dev_event_type event) 590 { 591 struct dev_event_callback *cb_lst; 592 593 if (device_name == NULL) 594 return; 595 596 rte_spinlock_lock(&dev_event_lock); 597 598 TAILQ_FOREACH(cb_lst, &dev_event_cbs, next) { 599 if (cb_lst->dev_name) { 600 if (strcmp(cb_lst->dev_name, device_name)) 601 continue; 602 } 603 cb_lst->active = 1; 604 rte_spinlock_unlock(&dev_event_lock); 605 cb_lst->cb_fn(device_name, event, 606 cb_lst->cb_arg); 607 rte_spinlock_lock(&dev_event_lock); 608 cb_lst->active = 0; 609 } 610 rte_spinlock_unlock(&dev_event_lock); 611 } 612 613 int 614 rte_dev_iterator_init(struct rte_dev_iterator *it, 615 const char *dev_str) 616 { 617 struct rte_devargs devargs = { .bus = NULL }; 618 struct rte_class *cls = NULL; 619 struct rte_bus *bus = NULL; 620 621 /* Having both bus_str and cls_str NULL is illegal, 622 * marking this iterator as invalid unless 623 * everything goes well. 624 */ 625 it->bus_str = NULL; 626 it->cls_str = NULL; 627 628 /* Setting data field implies no malloc in parsing. */ 629 devargs.data = (void *)(intptr_t)dev_str; 630 if (rte_devargs_layers_parse(&devargs, dev_str)) 631 goto get_out; 632 633 bus = devargs.bus; 634 cls = devargs.cls; 635 /* The string should have at least 636 * one layer specified. 637 */ 638 if (bus == NULL && cls == NULL) { 639 EAL_LOG(DEBUG, "Either bus or class must be specified."); 640 rte_errno = EINVAL; 641 goto get_out; 642 } 643 if (bus != NULL && bus->dev_iterate == NULL) { 644 EAL_LOG(DEBUG, "Bus %s not supported", bus->name); 645 rte_errno = ENOTSUP; 646 goto get_out; 647 } 648 if (cls != NULL && cls->dev_iterate == NULL) { 649 EAL_LOG(DEBUG, "Class %s not supported", cls->name); 650 rte_errno = ENOTSUP; 651 goto get_out; 652 } 653 it->bus_str = devargs.bus_str; 654 it->cls_str = devargs.cls_str; 655 it->dev_str = dev_str; 656 it->bus = bus; 657 it->cls = cls; 658 it->device = NULL; 659 it->class_device = NULL; 660 get_out: 661 return -rte_errno; 662 } 663 664 static char * 665 dev_str_sane_copy(const char *str) 666 { 667 size_t end; 668 char *copy; 669 670 end = strcspn(str, ",/"); 671 if (str[end] == ',') { 672 copy = strdup(&str[end + 1]); 673 } else { 674 /* '/' or '\0' */ 675 copy = strdup(""); 676 } 677 if (copy == NULL) { 678 rte_errno = ENOMEM; 679 } else { 680 char *slash; 681 682 slash = strchr(copy, '/'); 683 if (slash != NULL) 684 slash[0] = '\0'; 685 } 686 return copy; 687 } 688 689 static int 690 class_next_dev_cmp(const struct rte_class *cls, 691 const void *ctx) 692 { 693 struct rte_dev_iterator *it; 694 const char *cls_str = NULL; 695 void *dev; 696 697 if (cls->dev_iterate == NULL) 698 return 1; 699 it = ITCTX(ctx); 700 cls_str = CLSCTX(ctx); 701 dev = it->class_device; 702 /* it->cls_str != NULL means a class 703 * was specified in the devstr. 704 */ 705 if (it->cls_str != NULL && cls != it->cls) 706 return 1; 707 /* If an error occurred previously, 708 * no need to test further. 709 */ 710 if (rte_errno != 0) 711 return -1; 712 dev = cls->dev_iterate(dev, cls_str, it); 713 it->class_device = dev; 714 return dev == NULL; 715 } 716 717 static int 718 bus_next_dev_cmp(const struct rte_bus *bus, 719 const void *ctx) 720 { 721 struct rte_device *dev = NULL; 722 struct rte_class *cls = NULL; 723 struct rte_dev_iterator *it; 724 const char *bus_str = NULL; 725 726 if (bus->dev_iterate == NULL) 727 return 1; 728 it = ITCTX(ctx); 729 bus_str = BUSCTX(ctx); 730 dev = it->device; 731 /* it->bus_str != NULL means a bus 732 * was specified in the devstr. 733 */ 734 if (it->bus_str != NULL && bus != it->bus) 735 return 1; 736 /* If an error occurred previously, 737 * no need to test further. 738 */ 739 if (rte_errno != 0) 740 return -1; 741 if (it->cls_str == NULL) { 742 dev = bus->dev_iterate(dev, bus_str, it); 743 goto end; 744 } 745 /* cls_str != NULL */ 746 if (dev == NULL) { 747 next_dev_on_bus: 748 dev = bus->dev_iterate(dev, bus_str, it); 749 it->device = dev; 750 } 751 if (dev == NULL) 752 return 1; 753 if (it->cls != NULL) 754 cls = TAILQ_PREV(it->cls, rte_class_list, next); 755 cls = rte_class_find(cls, class_next_dev_cmp, ctx); 756 if (cls != NULL) { 757 it->cls = cls; 758 goto end; 759 } 760 goto next_dev_on_bus; 761 end: 762 it->device = dev; 763 return dev == NULL; 764 } 765 struct rte_device * 766 rte_dev_iterator_next(struct rte_dev_iterator *it) 767 { 768 struct rte_bus *bus = NULL; 769 int old_errno = rte_errno; 770 char *bus_str = NULL; 771 char *cls_str = NULL; 772 773 rte_errno = 0; 774 if (it->bus_str == NULL && it->cls_str == NULL) { 775 /* Invalid iterator. */ 776 rte_errno = EINVAL; 777 return NULL; 778 } 779 if (it->bus != NULL) 780 bus = TAILQ_PREV(it->bus, rte_bus_list, next); 781 if (it->bus_str != NULL) { 782 bus_str = dev_str_sane_copy(it->bus_str); 783 if (bus_str == NULL) 784 goto out; 785 } 786 if (it->cls_str != NULL) { 787 cls_str = dev_str_sane_copy(it->cls_str); 788 if (cls_str == NULL) 789 goto out; 790 } 791 while ((bus = rte_bus_find(bus, bus_next_dev_cmp, 792 CTX(it, bus_str, cls_str)))) { 793 if (it->device != NULL) { 794 it->bus = bus; 795 goto out; 796 } 797 if (it->bus_str != NULL || 798 rte_errno != 0) 799 break; 800 } 801 if (rte_errno == 0) 802 rte_errno = old_errno; 803 out: 804 free(bus_str); 805 free(cls_str); 806 return it->device; 807 } 808 809 int 810 rte_dev_dma_map(struct rte_device *dev, void *addr, uint64_t iova, 811 size_t len) 812 { 813 if (dev->bus->dma_map == NULL || len == 0) { 814 rte_errno = ENOTSUP; 815 return -1; 816 } 817 /* Memory must be registered through rte_extmem_* APIs */ 818 if (rte_mem_virt2memseg_list(addr) == NULL) { 819 rte_errno = EINVAL; 820 return -1; 821 } 822 823 return dev->bus->dma_map(dev, addr, iova, len); 824 } 825 826 int 827 rte_dev_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, 828 size_t len) 829 { 830 if (dev->bus->dma_unmap == NULL || len == 0) { 831 rte_errno = ENOTSUP; 832 return -1; 833 } 834 /* Memory must be registered through rte_extmem_* APIs */ 835 if (rte_mem_virt2memseg_list(addr) == NULL) { 836 rte_errno = EINVAL; 837 return -1; 838 } 839 840 return dev->bus->dma_unmap(dev, addr, iova, len); 841 } 842