1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "env_internal.h" 35 36 #include <rte_alarm.h> 37 #include "spdk/env.h" 38 39 #define SYSFS_PCI_DRIVERS "/sys/bus/pci/drivers" 40 41 #define PCI_CFG_SIZE 256 42 #define PCI_EXT_CAP_ID_SN 0x03 43 44 /* DPDK 18.11+ hotplug isn't robust. Multiple apps starting at the same time 45 * might cause the internal IPC to misbehave. Just retry in such case. 46 */ 47 #define DPDK_HOTPLUG_RETRY_COUNT 4 48 49 static pthread_mutex_t g_pci_mutex = PTHREAD_MUTEX_INITIALIZER; 50 static TAILQ_HEAD(, spdk_pci_device) g_pci_devices = TAILQ_HEAD_INITIALIZER(g_pci_devices); 51 /* devices hotplugged on a dpdk thread */ 52 static TAILQ_HEAD(, spdk_pci_device) g_pci_hotplugged_devices = 53 TAILQ_HEAD_INITIALIZER(g_pci_hotplugged_devices); 54 static TAILQ_HEAD(, spdk_pci_driver) g_pci_drivers = TAILQ_HEAD_INITIALIZER(g_pci_drivers); 55 56 static int 57 spdk_map_bar_rte(struct spdk_pci_device *device, uint32_t bar, 58 void **mapped_addr, uint64_t *phys_addr, uint64_t *size) 59 { 60 struct rte_pci_device *dev = device->dev_handle; 61 62 *mapped_addr = dev->mem_resource[bar].addr; 63 *phys_addr = (uint64_t)dev->mem_resource[bar].phys_addr; 64 *size = (uint64_t)dev->mem_resource[bar].len; 65 66 return 0; 67 } 68 69 static int 70 spdk_unmap_bar_rte(struct spdk_pci_device *device, uint32_t bar, void *addr) 71 { 72 return 0; 73 } 74 75 static int 76 spdk_cfg_read_rte(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 77 { 78 int rc; 79 80 rc = rte_pci_read_config(dev->dev_handle, value, len, offset); 81 82 #if defined(__FreeBSD__) && RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0) 83 /* Older DPDKs return 0 on success and -1 on failure */ 84 return rc; 85 #endif 86 return (rc > 0 && (uint32_t) rc == len) ? 0 : -1; 87 } 88 89 static int 90 spdk_cfg_write_rte(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 91 { 92 int rc; 93 94 rc = rte_pci_write_config(dev->dev_handle, value, len, offset); 95 96 #ifdef __FreeBSD__ 97 /* DPDK returns 0 on success and -1 on failure */ 98 return rc; 99 #endif 100 return (rc > 0 && (uint32_t) rc == len) ? 0 : -1; 101 } 102 103 static void 104 spdk_detach_rte_cb(void *_dev) 105 { 106 struct rte_pci_device *rte_dev = _dev; 107 108 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) 109 char bdf[32]; 110 int i = 0, rc; 111 112 snprintf(bdf, sizeof(bdf), "%s", rte_dev->device.name); 113 do { 114 rc = rte_eal_hotplug_remove("pci", bdf); 115 } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT); 116 #else 117 rte_eal_dev_detach(&rte_dev->device); 118 #endif 119 } 120 121 static void 122 spdk_detach_rte(struct spdk_pci_device *dev) 123 { 124 /* The device was already marked as available and could be attached 125 * again while we go asynchronous, so we explicitly forbid that. 126 */ 127 dev->internal.pending_removal = true; 128 if (spdk_process_is_primary()) { 129 rte_eal_alarm_set(10, spdk_detach_rte_cb, dev->dev_handle); 130 } else { 131 spdk_detach_rte_cb(dev->dev_handle); 132 } 133 } 134 135 void 136 spdk_pci_driver_register(struct spdk_pci_driver *driver) 137 { 138 TAILQ_INSERT_TAIL(&g_pci_drivers, driver, tailq); 139 } 140 141 #if RTE_VERSION >= RTE_VERSION_NUM(18, 5, 0, 0) 142 static void 143 spdk_pci_device_rte_hotremove(const char *device_name, 144 enum rte_dev_event_type event, 145 void *cb_arg) 146 { 147 struct spdk_pci_device *dev; 148 bool can_detach = false; 149 150 if (event != RTE_DEV_EVENT_REMOVE) { 151 return; 152 } 153 154 pthread_mutex_lock(&g_pci_mutex); 155 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 156 struct rte_pci_device *rte_dev = dev->dev_handle; 157 158 if (strcmp(rte_dev->name, device_name) == 0 && 159 !dev->internal.pending_removal) { 160 can_detach = !dev->internal.attached; 161 /* prevent any further attaches */ 162 dev->internal.pending_removal = true; 163 break; 164 } 165 } 166 pthread_mutex_unlock(&g_pci_mutex); 167 168 if (dev != NULL && can_detach) { 169 /* if device is not attached, we can remove it right away. */ 170 spdk_detach_rte(dev); 171 } 172 } 173 #endif 174 175 static void 176 cleanup_pci_devices(void) 177 { 178 struct spdk_pci_device *dev, *tmp; 179 180 pthread_mutex_lock(&g_pci_mutex); 181 /* cleanup removed devices */ 182 TAILQ_FOREACH_SAFE(dev, &g_pci_devices, internal.tailq, tmp) { 183 if (!dev->internal.removed) { 184 continue; 185 } 186 187 spdk_vtophys_pci_device_removed(dev->dev_handle); 188 TAILQ_REMOVE(&g_pci_devices, dev, internal.tailq); 189 free(dev); 190 } 191 192 /* add newly-attached devices */ 193 TAILQ_FOREACH_SAFE(dev, &g_pci_hotplugged_devices, internal.tailq, tmp) { 194 TAILQ_REMOVE(&g_pci_hotplugged_devices, dev, internal.tailq); 195 TAILQ_INSERT_TAIL(&g_pci_devices, dev, internal.tailq); 196 spdk_vtophys_pci_device_added(dev->dev_handle); 197 } 198 pthread_mutex_unlock(&g_pci_mutex); 199 } 200 201 void 202 spdk_pci_init(void) 203 { 204 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) 205 struct spdk_pci_driver *driver; 206 207 /* We need to pre-register pci drivers for the pci devices to be 208 * attachable in multi-process with DPDK 18.11+. 209 * 210 * DPDK 18.11+ does its best to ensure all devices are equally 211 * attached or detached in all processes within a shared memory group. 212 * For SPDK it means that if a device is hotplugged in the primary, 213 * then DPDK will automatically send an IPC hotplug request to all other 214 * processes. Those other processes may not have the same SPDK PCI 215 * driver registered and may fail to attach the device. DPDK will send 216 * back the failure status, and the the primary process will also fail 217 * to hotplug the device. To prevent that, we need to pre-register the 218 * pci drivers here. 219 */ 220 TAILQ_FOREACH(driver, &g_pci_drivers, tailq) { 221 assert(!driver->is_registered); 222 driver->is_registered = true; 223 rte_pci_register(&driver->driver); 224 } 225 #endif 226 227 #if RTE_VERSION >= RTE_VERSION_NUM(18, 5, 0, 0) 228 /* Register a single hotremove callback for all devices. */ 229 if (spdk_process_is_primary()) { 230 rte_dev_event_callback_register(NULL, spdk_pci_device_rte_hotremove, NULL); 231 } 232 #endif 233 } 234 235 void 236 spdk_pci_fini(void) 237 { 238 struct spdk_pci_device *dev; 239 char bdf[32]; 240 241 cleanup_pci_devices(); 242 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 243 if (dev->internal.attached) { 244 spdk_pci_addr_fmt(bdf, sizeof(bdf), &dev->addr); 245 fprintf(stderr, "Device %s is still attached at shutdown!\n", bdf); 246 } 247 } 248 249 #if RTE_VERSION >= RTE_VERSION_NUM(18, 5, 0, 0) 250 if (spdk_process_is_primary()) { 251 rte_dev_event_callback_unregister(NULL, spdk_pci_device_rte_hotremove, NULL); 252 } 253 #endif 254 } 255 256 int 257 spdk_pci_device_init(struct rte_pci_driver *_drv, 258 struct rte_pci_device *_dev) 259 { 260 struct spdk_pci_driver *driver = (struct spdk_pci_driver *)_drv; 261 struct spdk_pci_device *dev; 262 int rc; 263 264 #if RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0) 265 if (!driver->cb_fn) { 266 /* Return a positive value to indicate that this device does 267 * not belong to this driver, but this isn't an error. 268 */ 269 return 1; 270 } 271 #endif 272 273 dev = calloc(1, sizeof(*dev)); 274 if (dev == NULL) { 275 return -1; 276 } 277 278 dev->dev_handle = _dev; 279 280 dev->addr.domain = _dev->addr.domain; 281 dev->addr.bus = _dev->addr.bus; 282 dev->addr.dev = _dev->addr.devid; 283 dev->addr.func = _dev->addr.function; 284 dev->id.vendor_id = _dev->id.vendor_id; 285 dev->id.device_id = _dev->id.device_id; 286 dev->id.subvendor_id = _dev->id.subsystem_vendor_id; 287 dev->id.subdevice_id = _dev->id.subsystem_device_id; 288 dev->socket_id = _dev->device.numa_node; 289 290 dev->map_bar = spdk_map_bar_rte; 291 dev->unmap_bar = spdk_unmap_bar_rte; 292 dev->cfg_read = spdk_cfg_read_rte; 293 dev->cfg_write = spdk_cfg_write_rte; 294 dev->detach = spdk_detach_rte; 295 296 dev->internal.driver = driver; 297 298 if (driver->cb_fn != NULL) { 299 rc = driver->cb_fn(driver->cb_arg, dev); 300 if (rc != 0) { 301 free(dev); 302 return rc; 303 } 304 dev->internal.attached = true; 305 } 306 307 pthread_mutex_lock(&g_pci_mutex); 308 TAILQ_INSERT_TAIL(&g_pci_hotplugged_devices, dev, internal.tailq); 309 pthread_mutex_unlock(&g_pci_mutex); 310 return 0; 311 } 312 313 int 314 spdk_pci_device_fini(struct rte_pci_device *_dev) 315 { 316 struct spdk_pci_device *dev; 317 318 pthread_mutex_lock(&g_pci_mutex); 319 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 320 if (dev->dev_handle == _dev) { 321 break; 322 } 323 } 324 325 if (dev == NULL || dev->internal.attached) { 326 /* The device might be still referenced somewhere in SPDK. */ 327 pthread_mutex_unlock(&g_pci_mutex); 328 return -1; 329 } 330 331 assert(!dev->internal.removed); 332 dev->internal.removed = true; 333 pthread_mutex_unlock(&g_pci_mutex); 334 return 0; 335 336 } 337 338 void 339 spdk_pci_device_detach(struct spdk_pci_device *dev) 340 { 341 assert(dev->internal.attached); 342 dev->internal.attached = false; 343 dev->detach(dev); 344 345 cleanup_pci_devices(); 346 } 347 348 int 349 spdk_pci_device_attach(struct spdk_pci_driver *driver, 350 spdk_pci_enum_cb enum_cb, 351 void *enum_ctx, struct spdk_pci_addr *pci_address) 352 { 353 struct spdk_pci_device *dev; 354 int rc; 355 char bdf[32]; 356 357 spdk_pci_addr_fmt(bdf, sizeof(bdf), pci_address); 358 359 cleanup_pci_devices(); 360 361 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 362 if (spdk_pci_addr_compare(&dev->addr, pci_address) == 0) { 363 break; 364 } 365 } 366 367 if (dev != NULL && dev->internal.driver == driver) { 368 pthread_mutex_lock(&g_pci_mutex); 369 if (dev->internal.attached || dev->internal.pending_removal) { 370 pthread_mutex_unlock(&g_pci_mutex); 371 return -1; 372 } 373 374 rc = enum_cb(enum_ctx, dev); 375 if (rc == 0) { 376 dev->internal.attached = true; 377 } 378 pthread_mutex_unlock(&g_pci_mutex); 379 return rc; 380 } 381 382 if (!driver->is_registered) { 383 driver->is_registered = true; 384 rte_pci_register(&driver->driver); 385 } 386 387 driver->cb_fn = enum_cb; 388 driver->cb_arg = enum_ctx; 389 390 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) 391 int i = 0; 392 393 do { 394 rc = rte_eal_hotplug_add("pci", bdf, ""); 395 } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT); 396 397 if (i > 1 && rc == -EEXIST) { 398 /* Even though the previous request timed out, the device 399 * was attached successfully. 400 */ 401 rc = 0; 402 } 403 #else 404 rc = rte_eal_dev_attach(bdf, ""); 405 #endif 406 407 driver->cb_arg = NULL; 408 driver->cb_fn = NULL; 409 410 cleanup_pci_devices(); 411 return rc == 0 ? 0 : -1; 412 } 413 414 /* Note: You can call spdk_pci_enumerate from more than one thread 415 * simultaneously safely, but you cannot call spdk_pci_enumerate 416 * and rte_eal_pci_probe simultaneously. 417 */ 418 int 419 spdk_pci_enumerate(struct spdk_pci_driver *driver, 420 spdk_pci_enum_cb enum_cb, 421 void *enum_ctx) 422 { 423 struct spdk_pci_device *dev; 424 int rc; 425 426 cleanup_pci_devices(); 427 428 pthread_mutex_lock(&g_pci_mutex); 429 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 430 if (dev->internal.attached || 431 dev->internal.driver != driver || 432 dev->internal.pending_removal) { 433 continue; 434 } 435 436 rc = enum_cb(enum_ctx, dev); 437 if (rc == 0) { 438 dev->internal.attached = true; 439 } else if (rc < 0) { 440 pthread_mutex_unlock(&g_pci_mutex); 441 return -1; 442 } 443 } 444 pthread_mutex_unlock(&g_pci_mutex); 445 446 if (!driver->is_registered) { 447 driver->is_registered = true; 448 rte_pci_register(&driver->driver); 449 } 450 451 driver->cb_fn = enum_cb; 452 driver->cb_arg = enum_ctx; 453 454 if (rte_bus_scan() != 0 || rte_bus_probe() != 0) { 455 driver->cb_arg = NULL; 456 driver->cb_fn = NULL; 457 return -1; 458 } 459 460 driver->cb_arg = NULL; 461 driver->cb_fn = NULL; 462 463 cleanup_pci_devices(); 464 return 0; 465 } 466 467 struct spdk_pci_device * 468 spdk_pci_get_first_device(void) 469 { 470 return TAILQ_FIRST(&g_pci_devices); 471 } 472 473 struct spdk_pci_device * 474 spdk_pci_get_next_device(struct spdk_pci_device *prev) 475 { 476 return TAILQ_NEXT(prev, internal.tailq); 477 } 478 479 int 480 spdk_pci_device_map_bar(struct spdk_pci_device *dev, uint32_t bar, 481 void **mapped_addr, uint64_t *phys_addr, uint64_t *size) 482 { 483 return dev->map_bar(dev, bar, mapped_addr, phys_addr, size); 484 } 485 486 int 487 spdk_pci_device_unmap_bar(struct spdk_pci_device *dev, uint32_t bar, void *addr) 488 { 489 return dev->unmap_bar(dev, bar, addr); 490 } 491 492 uint32_t 493 spdk_pci_device_get_domain(struct spdk_pci_device *dev) 494 { 495 return dev->addr.domain; 496 } 497 498 uint8_t 499 spdk_pci_device_get_bus(struct spdk_pci_device *dev) 500 { 501 return dev->addr.bus; 502 } 503 504 uint8_t 505 spdk_pci_device_get_dev(struct spdk_pci_device *dev) 506 { 507 return dev->addr.dev; 508 } 509 510 uint8_t 511 spdk_pci_device_get_func(struct spdk_pci_device *dev) 512 { 513 return dev->addr.func; 514 } 515 516 uint16_t 517 spdk_pci_device_get_vendor_id(struct spdk_pci_device *dev) 518 { 519 return dev->id.vendor_id; 520 } 521 522 uint16_t 523 spdk_pci_device_get_device_id(struct spdk_pci_device *dev) 524 { 525 return dev->id.device_id; 526 } 527 528 uint16_t 529 spdk_pci_device_get_subvendor_id(struct spdk_pci_device *dev) 530 { 531 return dev->id.subvendor_id; 532 } 533 534 uint16_t 535 spdk_pci_device_get_subdevice_id(struct spdk_pci_device *dev) 536 { 537 return dev->id.subdevice_id; 538 } 539 540 struct spdk_pci_id 541 spdk_pci_device_get_id(struct spdk_pci_device *dev) 542 { 543 return dev->id; 544 } 545 546 int 547 spdk_pci_device_get_socket_id(struct spdk_pci_device *dev) 548 { 549 return dev->socket_id; 550 } 551 552 int 553 spdk_pci_device_cfg_read(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 554 { 555 return dev->cfg_read(dev, value, len, offset); 556 } 557 558 int 559 spdk_pci_device_cfg_write(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 560 { 561 return dev->cfg_write(dev, value, len, offset); 562 } 563 564 int 565 spdk_pci_device_cfg_read8(struct spdk_pci_device *dev, uint8_t *value, uint32_t offset) 566 { 567 return spdk_pci_device_cfg_read(dev, value, 1, offset); 568 } 569 570 int 571 spdk_pci_device_cfg_write8(struct spdk_pci_device *dev, uint8_t value, uint32_t offset) 572 { 573 return spdk_pci_device_cfg_write(dev, &value, 1, offset); 574 } 575 576 int 577 spdk_pci_device_cfg_read16(struct spdk_pci_device *dev, uint16_t *value, uint32_t offset) 578 { 579 return spdk_pci_device_cfg_read(dev, value, 2, offset); 580 } 581 582 int 583 spdk_pci_device_cfg_write16(struct spdk_pci_device *dev, uint16_t value, uint32_t offset) 584 { 585 return spdk_pci_device_cfg_write(dev, &value, 2, offset); 586 } 587 588 int 589 spdk_pci_device_cfg_read32(struct spdk_pci_device *dev, uint32_t *value, uint32_t offset) 590 { 591 return spdk_pci_device_cfg_read(dev, value, 4, offset); 592 } 593 594 int 595 spdk_pci_device_cfg_write32(struct spdk_pci_device *dev, uint32_t value, uint32_t offset) 596 { 597 return spdk_pci_device_cfg_write(dev, &value, 4, offset); 598 } 599 600 int 601 spdk_pci_device_get_serial_number(struct spdk_pci_device *dev, char *sn, size_t len) 602 { 603 int err; 604 uint32_t pos, header = 0; 605 uint32_t i, buf[2]; 606 607 if (len < 17) { 608 return -1; 609 } 610 611 err = spdk_pci_device_cfg_read32(dev, &header, PCI_CFG_SIZE); 612 if (err || !header) { 613 return -1; 614 } 615 616 pos = PCI_CFG_SIZE; 617 while (1) { 618 if ((header & 0x0000ffff) == PCI_EXT_CAP_ID_SN) { 619 if (pos) { 620 /* skip the header */ 621 pos += 4; 622 for (i = 0; i < 2; i++) { 623 err = spdk_pci_device_cfg_read32(dev, &buf[i], pos + 4 * i); 624 if (err) { 625 return -1; 626 } 627 } 628 snprintf(sn, len, "%08x%08x", buf[1], buf[0]); 629 return 0; 630 } 631 } 632 pos = (header >> 20) & 0xffc; 633 /* 0 if no other items exist */ 634 if (pos < PCI_CFG_SIZE) { 635 return -1; 636 } 637 err = spdk_pci_device_cfg_read32(dev, &header, pos); 638 if (err) { 639 return -1; 640 } 641 } 642 return -1; 643 } 644 645 struct spdk_pci_addr 646 spdk_pci_device_get_addr(struct spdk_pci_device *dev) 647 { 648 return dev->addr; 649 } 650 651 bool 652 spdk_pci_device_is_removed(struct spdk_pci_device *dev) 653 { 654 return dev->internal.pending_removal; 655 } 656 657 int 658 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2) 659 { 660 if (a1->domain > a2->domain) { 661 return 1; 662 } else if (a1->domain < a2->domain) { 663 return -1; 664 } else if (a1->bus > a2->bus) { 665 return 1; 666 } else if (a1->bus < a2->bus) { 667 return -1; 668 } else if (a1->dev > a2->dev) { 669 return 1; 670 } else if (a1->dev < a2->dev) { 671 return -1; 672 } else if (a1->func > a2->func) { 673 return 1; 674 } else if (a1->func < a2->func) { 675 return -1; 676 } 677 678 return 0; 679 } 680 681 #ifdef __linux__ 682 int 683 spdk_pci_device_claim(const struct spdk_pci_addr *pci_addr) 684 { 685 int dev_fd; 686 char dev_name[64]; 687 int pid; 688 void *dev_map; 689 struct flock pcidev_lock = { 690 .l_type = F_WRLCK, 691 .l_whence = SEEK_SET, 692 .l_start = 0, 693 .l_len = 0, 694 }; 695 696 snprintf(dev_name, sizeof(dev_name), "/tmp/spdk_pci_lock_%04x:%02x:%02x.%x", pci_addr->domain, 697 pci_addr->bus, 698 pci_addr->dev, pci_addr->func); 699 700 dev_fd = open(dev_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 701 if (dev_fd == -1) { 702 fprintf(stderr, "could not open %s\n", dev_name); 703 return -1; 704 } 705 706 if (ftruncate(dev_fd, sizeof(int)) != 0) { 707 fprintf(stderr, "could not truncate %s\n", dev_name); 708 close(dev_fd); 709 return -1; 710 } 711 712 dev_map = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, 713 MAP_SHARED, dev_fd, 0); 714 if (dev_map == MAP_FAILED) { 715 fprintf(stderr, "could not mmap dev %s (%d)\n", dev_name, errno); 716 close(dev_fd); 717 return -1; 718 } 719 720 if (fcntl(dev_fd, F_SETLK, &pcidev_lock) != 0) { 721 pid = *(int *)dev_map; 722 fprintf(stderr, "Cannot create lock on device %s, probably" 723 " process %d has claimed it\n", dev_name, pid); 724 munmap(dev_map, sizeof(int)); 725 close(dev_fd); 726 return -1; 727 } 728 729 *(int *)dev_map = (int)getpid(); 730 munmap(dev_map, sizeof(int)); 731 /* Keep dev_fd open to maintain the lock. */ 732 return dev_fd; 733 } 734 #endif /* __linux__ */ 735 736 #ifdef __FreeBSD__ 737 int 738 spdk_pci_device_claim(const struct spdk_pci_addr *pci_addr) 739 { 740 /* TODO */ 741 return 0; 742 } 743 #endif /* __FreeBSD__ */ 744 745 int 746 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf) 747 { 748 unsigned domain, bus, dev, func; 749 750 if (addr == NULL || bdf == NULL) { 751 return -EINVAL; 752 } 753 754 if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) || 755 (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) { 756 /* Matched a full address - all variables are initialized */ 757 } else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) { 758 func = 0; 759 } else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) || 760 (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) { 761 domain = 0; 762 } else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) || 763 (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) { 764 domain = 0; 765 func = 0; 766 } else { 767 return -EINVAL; 768 } 769 770 if (bus > 0xFF || dev > 0x1F || func > 7) { 771 return -EINVAL; 772 } 773 774 addr->domain = domain; 775 addr->bus = bus; 776 addr->dev = dev; 777 addr->func = func; 778 779 return 0; 780 } 781 782 int 783 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr) 784 { 785 int rc; 786 787 rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x", 788 addr->domain, addr->bus, 789 addr->dev, addr->func); 790 791 if (rc > 0 && (size_t)rc < sz) { 792 return 0; 793 } 794 795 return -1; 796 } 797 798 void 799 spdk_pci_hook_device(struct spdk_pci_driver *drv, struct spdk_pci_device *dev) 800 { 801 assert(dev->map_bar != NULL); 802 assert(dev->unmap_bar != NULL); 803 assert(dev->cfg_read != NULL); 804 assert(dev->cfg_write != NULL); 805 assert(dev->detach != NULL); 806 dev->internal.driver = drv; 807 TAILQ_INSERT_TAIL(&g_pci_devices, dev, internal.tailq); 808 } 809 810 void 811 spdk_pci_unhook_device(struct spdk_pci_device *dev) 812 { 813 assert(!dev->internal.attached); 814 TAILQ_REMOVE(&g_pci_devices, dev, internal.tailq); 815 } 816