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 /* DPDK alarm/interrupt thread */ 50 static pthread_t g_dpdk_tid; 51 static pthread_mutex_t g_pci_mutex = PTHREAD_MUTEX_INITIALIZER; 52 static TAILQ_HEAD(, spdk_pci_device) g_pci_devices = TAILQ_HEAD_INITIALIZER(g_pci_devices); 53 /* devices hotplugged on a dpdk thread */ 54 static TAILQ_HEAD(, spdk_pci_device) g_pci_hotplugged_devices = 55 TAILQ_HEAD_INITIALIZER(g_pci_hotplugged_devices); 56 static TAILQ_HEAD(, spdk_pci_driver) g_pci_drivers = TAILQ_HEAD_INITIALIZER(g_pci_drivers); 57 58 static int 59 spdk_map_bar_rte(struct spdk_pci_device *device, uint32_t bar, 60 void **mapped_addr, uint64_t *phys_addr, uint64_t *size) 61 { 62 struct rte_pci_device *dev = device->dev_handle; 63 64 *mapped_addr = dev->mem_resource[bar].addr; 65 *phys_addr = (uint64_t)dev->mem_resource[bar].phys_addr; 66 *size = (uint64_t)dev->mem_resource[bar].len; 67 68 return 0; 69 } 70 71 static int 72 spdk_unmap_bar_rte(struct spdk_pci_device *device, uint32_t bar, void *addr) 73 { 74 return 0; 75 } 76 77 static int 78 spdk_cfg_read_rte(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 79 { 80 int rc; 81 82 rc = rte_pci_read_config(dev->dev_handle, value, len, offset); 83 84 #if defined(__FreeBSD__) && RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0) 85 /* Older DPDKs return 0 on success and -1 on failure */ 86 return rc; 87 #endif 88 return (rc > 0 && (uint32_t) rc == len) ? 0 : -1; 89 } 90 91 static int 92 spdk_cfg_write_rte(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 93 { 94 int rc; 95 96 rc = rte_pci_write_config(dev->dev_handle, value, len, offset); 97 98 #ifdef __FreeBSD__ 99 /* DPDK returns 0 on success and -1 on failure */ 100 return rc; 101 #endif 102 return (rc > 0 && (uint32_t) rc == len) ? 0 : -1; 103 } 104 105 static void 106 spdk_detach_rte_cb(void *_dev) 107 { 108 struct rte_pci_device *rte_dev = _dev; 109 110 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) 111 char bdf[32]; 112 int i = 0, rc; 113 114 snprintf(bdf, sizeof(bdf), "%s", rte_dev->device.name); 115 do { 116 rc = rte_eal_hotplug_remove("pci", bdf); 117 } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT); 118 #else 119 rte_eal_dev_detach(&rte_dev->device); 120 #endif 121 } 122 123 static void 124 spdk_detach_rte(struct spdk_pci_device *dev) 125 { 126 struct rte_pci_device *rte_dev = dev->dev_handle; 127 int i; 128 bool removed; 129 130 /* The device was already marked as available and could be attached 131 * again while we go asynchronous, so we explicitly forbid that. 132 */ 133 dev->internal.pending_removal = true; 134 if (spdk_process_is_primary() && !pthread_equal(g_dpdk_tid, pthread_self())) { 135 rte_eal_alarm_set(1, spdk_detach_rte_cb, rte_dev); 136 /* wait up to 20ms for the cb to start executing */ 137 for (i = 20; i > 0; i--) { 138 139 spdk_delay_us(1000); 140 pthread_mutex_lock(&g_pci_mutex); 141 removed = dev->internal.removed; 142 pthread_mutex_unlock(&g_pci_mutex); 143 144 if (removed) { 145 break; 146 } 147 } 148 149 /* besides checking the removed flag, we also need to wait 150 * for the dpdk detach function to unwind, as it's doing some 151 * operations even after calling our detach callback. Simply 152 * cancell the alarm - if it started executing already, this 153 * call will block and wait for it to finish. 154 */ 155 rte_eal_alarm_cancel(spdk_detach_rte_cb, rte_dev); 156 157 /* the device could have been finally removed, so just check 158 * it again. 159 */ 160 pthread_mutex_lock(&g_pci_mutex); 161 removed = dev->internal.removed; 162 pthread_mutex_unlock(&g_pci_mutex); 163 if (!removed) { 164 fprintf(stderr, "Timeout waiting for DPDK to remove PCI device %s.\n", 165 rte_dev->name); 166 } 167 } else { 168 spdk_detach_rte_cb(rte_dev); 169 } 170 } 171 172 void 173 spdk_pci_driver_register(struct spdk_pci_driver *driver) 174 { 175 TAILQ_INSERT_TAIL(&g_pci_drivers, driver, tailq); 176 } 177 178 #if RTE_VERSION >= RTE_VERSION_NUM(18, 5, 0, 0) 179 static void 180 spdk_pci_device_rte_hotremove_cb(void *dev) 181 { 182 spdk_detach_rte((struct spdk_pci_device *)dev); 183 } 184 185 static void 186 spdk_pci_device_rte_hotremove(const char *device_name, 187 enum rte_dev_event_type event, 188 void *cb_arg) 189 { 190 struct spdk_pci_device *dev; 191 bool can_detach = false; 192 193 if (event != RTE_DEV_EVENT_REMOVE) { 194 return; 195 } 196 197 pthread_mutex_lock(&g_pci_mutex); 198 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 199 struct rte_pci_device *rte_dev = dev->dev_handle; 200 if (strcmp(rte_dev->name, device_name) == 0 && 201 !dev->internal.pending_removal) { 202 can_detach = !dev->internal.attached; 203 /* prevent any further attaches */ 204 dev->internal.pending_removal = true; 205 break; 206 } 207 } 208 pthread_mutex_unlock(&g_pci_mutex); 209 210 if (dev != NULL && can_detach) { 211 /* If device is not attached, we can remove it right away. 212 * 213 * Because the user's callback is invoked in eal interrupt 214 * callback, the interrupt callback need to be finished before 215 * it can be unregistered when detaching device. So finish 216 * callback soon and use a deferred removal to detach device 217 * is need. It is a workaround, once the device detaching be 218 * moved into the eal in the future, the deferred removal could 219 * be deleted. 220 */ 221 rte_eal_alarm_set(1, spdk_pci_device_rte_hotremove_cb, dev); 222 } 223 } 224 #endif 225 226 static void 227 cleanup_pci_devices(void) 228 { 229 struct spdk_pci_device *dev, *tmp; 230 231 pthread_mutex_lock(&g_pci_mutex); 232 /* cleanup removed devices */ 233 TAILQ_FOREACH_SAFE(dev, &g_pci_devices, internal.tailq, tmp) { 234 if (!dev->internal.removed) { 235 continue; 236 } 237 238 spdk_vtophys_pci_device_removed(dev->dev_handle); 239 TAILQ_REMOVE(&g_pci_devices, dev, internal.tailq); 240 free(dev); 241 } 242 243 /* add newly-attached devices */ 244 TAILQ_FOREACH_SAFE(dev, &g_pci_hotplugged_devices, internal.tailq, tmp) { 245 TAILQ_REMOVE(&g_pci_hotplugged_devices, dev, internal.tailq); 246 TAILQ_INSERT_TAIL(&g_pci_devices, dev, internal.tailq); 247 spdk_vtophys_pci_device_added(dev->dev_handle); 248 } 249 pthread_mutex_unlock(&g_pci_mutex); 250 } 251 252 static void 253 _get_alarm_thread_cb(void *unused) 254 { 255 g_dpdk_tid = pthread_self(); 256 } 257 258 void 259 spdk_pci_init(void) 260 { 261 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) 262 struct spdk_pci_driver *driver; 263 264 /* We need to pre-register pci drivers for the pci devices to be 265 * attachable in multi-process with DPDK 18.11+. 266 * 267 * DPDK 18.11+ does its best to ensure all devices are equally 268 * attached or detached in all processes within a shared memory group. 269 * For SPDK it means that if a device is hotplugged in the primary, 270 * then DPDK will automatically send an IPC hotplug request to all other 271 * processes. Those other processes may not have the same SPDK PCI 272 * driver registered and may fail to attach the device. DPDK will send 273 * back the failure status, and the the primary process will also fail 274 * to hotplug the device. To prevent that, we need to pre-register the 275 * pci drivers here. 276 */ 277 TAILQ_FOREACH(driver, &g_pci_drivers, tailq) { 278 assert(!driver->is_registered); 279 driver->is_registered = true; 280 rte_pci_register(&driver->driver); 281 } 282 #endif 283 284 #if RTE_VERSION >= RTE_VERSION_NUM(18, 5, 0, 0) 285 /* Register a single hotremove callback for all devices. */ 286 if (spdk_process_is_primary()) { 287 rte_dev_event_callback_register(NULL, spdk_pci_device_rte_hotremove, NULL); 288 } 289 #endif 290 291 rte_eal_alarm_set(1, _get_alarm_thread_cb, NULL); 292 /* alarms are executed in order, so this one will be always executed 293 * before any real hotremove alarms and we don't need to wait for it. 294 */ 295 } 296 297 void 298 spdk_pci_fini(void) 299 { 300 struct spdk_pci_device *dev; 301 char bdf[32]; 302 303 cleanup_pci_devices(); 304 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 305 if (dev->internal.attached) { 306 spdk_pci_addr_fmt(bdf, sizeof(bdf), &dev->addr); 307 fprintf(stderr, "Device %s is still attached at shutdown!\n", bdf); 308 } 309 } 310 311 #if RTE_VERSION >= RTE_VERSION_NUM(18, 5, 0, 0) 312 if (spdk_process_is_primary()) { 313 rte_dev_event_callback_unregister(NULL, spdk_pci_device_rte_hotremove, NULL); 314 } 315 #endif 316 } 317 318 int 319 spdk_pci_device_init(struct rte_pci_driver *_drv, 320 struct rte_pci_device *_dev) 321 { 322 struct spdk_pci_driver *driver = (struct spdk_pci_driver *)_drv; 323 struct spdk_pci_device *dev; 324 int rc; 325 326 #if RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0) 327 if (!driver->cb_fn) { 328 /* Return a positive value to indicate that this device does 329 * not belong to this driver, but this isn't an error. 330 */ 331 return 1; 332 } 333 #endif 334 335 dev = calloc(1, sizeof(*dev)); 336 if (dev == NULL) { 337 return -1; 338 } 339 340 dev->dev_handle = _dev; 341 342 dev->addr.domain = _dev->addr.domain; 343 dev->addr.bus = _dev->addr.bus; 344 dev->addr.dev = _dev->addr.devid; 345 dev->addr.func = _dev->addr.function; 346 dev->id.vendor_id = _dev->id.vendor_id; 347 dev->id.device_id = _dev->id.device_id; 348 dev->id.subvendor_id = _dev->id.subsystem_vendor_id; 349 dev->id.subdevice_id = _dev->id.subsystem_device_id; 350 dev->socket_id = _dev->device.numa_node; 351 dev->type = "pci"; 352 353 dev->map_bar = spdk_map_bar_rte; 354 dev->unmap_bar = spdk_unmap_bar_rte; 355 dev->cfg_read = spdk_cfg_read_rte; 356 dev->cfg_write = spdk_cfg_write_rte; 357 dev->detach = spdk_detach_rte; 358 359 dev->internal.driver = driver; 360 dev->internal.claim_fd = -1; 361 362 if (driver->cb_fn != NULL) { 363 rc = driver->cb_fn(driver->cb_arg, dev); 364 if (rc != 0) { 365 free(dev); 366 return rc; 367 } 368 dev->internal.attached = true; 369 } 370 371 pthread_mutex_lock(&g_pci_mutex); 372 TAILQ_INSERT_TAIL(&g_pci_hotplugged_devices, dev, internal.tailq); 373 pthread_mutex_unlock(&g_pci_mutex); 374 return 0; 375 } 376 377 int 378 spdk_pci_device_fini(struct rte_pci_device *_dev) 379 { 380 struct spdk_pci_device *dev; 381 382 pthread_mutex_lock(&g_pci_mutex); 383 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 384 if (dev->dev_handle == _dev) { 385 break; 386 } 387 } 388 389 if (dev == NULL || dev->internal.attached) { 390 /* The device might be still referenced somewhere in SPDK. */ 391 pthread_mutex_unlock(&g_pci_mutex); 392 return -1; 393 } 394 395 assert(!dev->internal.removed); 396 dev->internal.removed = true; 397 pthread_mutex_unlock(&g_pci_mutex); 398 return 0; 399 400 } 401 402 void 403 spdk_pci_device_detach(struct spdk_pci_device *dev) 404 { 405 assert(dev->internal.attached); 406 407 if (dev->internal.claim_fd >= 0) { 408 spdk_pci_device_unclaim(dev); 409 } 410 411 dev->internal.attached = false; 412 dev->detach(dev); 413 414 cleanup_pci_devices(); 415 } 416 417 int 418 spdk_pci_device_attach(struct spdk_pci_driver *driver, 419 spdk_pci_enum_cb enum_cb, 420 void *enum_ctx, struct spdk_pci_addr *pci_address) 421 { 422 struct spdk_pci_device *dev; 423 int rc; 424 char bdf[32]; 425 426 spdk_pci_addr_fmt(bdf, sizeof(bdf), pci_address); 427 428 cleanup_pci_devices(); 429 430 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 431 if (spdk_pci_addr_compare(&dev->addr, pci_address) == 0) { 432 break; 433 } 434 } 435 436 if (dev != NULL && dev->internal.driver == driver) { 437 pthread_mutex_lock(&g_pci_mutex); 438 if (dev->internal.attached || dev->internal.pending_removal) { 439 pthread_mutex_unlock(&g_pci_mutex); 440 return -1; 441 } 442 443 rc = enum_cb(enum_ctx, dev); 444 if (rc == 0) { 445 dev->internal.attached = true; 446 } 447 pthread_mutex_unlock(&g_pci_mutex); 448 return rc; 449 } 450 451 if (!driver->is_registered) { 452 driver->is_registered = true; 453 rte_pci_register(&driver->driver); 454 } 455 456 driver->cb_fn = enum_cb; 457 driver->cb_arg = enum_ctx; 458 459 #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) 460 int i = 0; 461 462 do { 463 rc = rte_eal_hotplug_add("pci", bdf, ""); 464 } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT); 465 466 if (i > 1 && rc == -EEXIST) { 467 /* Even though the previous request timed out, the device 468 * was attached successfully. 469 */ 470 rc = 0; 471 } 472 #else 473 rc = rte_eal_dev_attach(bdf, ""); 474 #endif 475 476 driver->cb_arg = NULL; 477 driver->cb_fn = NULL; 478 479 cleanup_pci_devices(); 480 return rc == 0 ? 0 : -1; 481 } 482 483 /* Note: You can call spdk_pci_enumerate from more than one thread 484 * simultaneously safely, but you cannot call spdk_pci_enumerate 485 * and rte_eal_pci_probe simultaneously. 486 */ 487 int 488 spdk_pci_enumerate(struct spdk_pci_driver *driver, 489 spdk_pci_enum_cb enum_cb, 490 void *enum_ctx) 491 { 492 struct spdk_pci_device *dev; 493 int rc; 494 495 cleanup_pci_devices(); 496 497 pthread_mutex_lock(&g_pci_mutex); 498 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) { 499 if (dev->internal.attached || 500 dev->internal.driver != driver || 501 dev->internal.pending_removal) { 502 continue; 503 } 504 505 rc = enum_cb(enum_ctx, dev); 506 if (rc == 0) { 507 dev->internal.attached = true; 508 } else if (rc < 0) { 509 pthread_mutex_unlock(&g_pci_mutex); 510 return -1; 511 } 512 } 513 pthread_mutex_unlock(&g_pci_mutex); 514 515 if (!driver->is_registered) { 516 driver->is_registered = true; 517 rte_pci_register(&driver->driver); 518 } 519 520 driver->cb_fn = enum_cb; 521 driver->cb_arg = enum_ctx; 522 523 if (rte_bus_scan() != 0 || rte_bus_probe() != 0) { 524 driver->cb_arg = NULL; 525 driver->cb_fn = NULL; 526 return -1; 527 } 528 529 driver->cb_arg = NULL; 530 driver->cb_fn = NULL; 531 532 cleanup_pci_devices(); 533 return 0; 534 } 535 536 struct spdk_pci_device * 537 spdk_pci_get_first_device(void) 538 { 539 return TAILQ_FIRST(&g_pci_devices); 540 } 541 542 struct spdk_pci_device * 543 spdk_pci_get_next_device(struct spdk_pci_device *prev) 544 { 545 return TAILQ_NEXT(prev, internal.tailq); 546 } 547 548 int 549 spdk_pci_device_map_bar(struct spdk_pci_device *dev, uint32_t bar, 550 void **mapped_addr, uint64_t *phys_addr, uint64_t *size) 551 { 552 return dev->map_bar(dev, bar, mapped_addr, phys_addr, size); 553 } 554 555 int 556 spdk_pci_device_unmap_bar(struct spdk_pci_device *dev, uint32_t bar, void *addr) 557 { 558 return dev->unmap_bar(dev, bar, addr); 559 } 560 561 uint32_t 562 spdk_pci_device_get_domain(struct spdk_pci_device *dev) 563 { 564 return dev->addr.domain; 565 } 566 567 uint8_t 568 spdk_pci_device_get_bus(struct spdk_pci_device *dev) 569 { 570 return dev->addr.bus; 571 } 572 573 uint8_t 574 spdk_pci_device_get_dev(struct spdk_pci_device *dev) 575 { 576 return dev->addr.dev; 577 } 578 579 uint8_t 580 spdk_pci_device_get_func(struct spdk_pci_device *dev) 581 { 582 return dev->addr.func; 583 } 584 585 uint16_t 586 spdk_pci_device_get_vendor_id(struct spdk_pci_device *dev) 587 { 588 return dev->id.vendor_id; 589 } 590 591 uint16_t 592 spdk_pci_device_get_device_id(struct spdk_pci_device *dev) 593 { 594 return dev->id.device_id; 595 } 596 597 uint16_t 598 spdk_pci_device_get_subvendor_id(struct spdk_pci_device *dev) 599 { 600 return dev->id.subvendor_id; 601 } 602 603 uint16_t 604 spdk_pci_device_get_subdevice_id(struct spdk_pci_device *dev) 605 { 606 return dev->id.subdevice_id; 607 } 608 609 struct spdk_pci_id 610 spdk_pci_device_get_id(struct spdk_pci_device *dev) 611 { 612 return dev->id; 613 } 614 615 int 616 spdk_pci_device_get_socket_id(struct spdk_pci_device *dev) 617 { 618 return dev->socket_id; 619 } 620 621 int 622 spdk_pci_device_cfg_read(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 623 { 624 return dev->cfg_read(dev, value, len, offset); 625 } 626 627 int 628 spdk_pci_device_cfg_write(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset) 629 { 630 return dev->cfg_write(dev, value, len, offset); 631 } 632 633 int 634 spdk_pci_device_cfg_read8(struct spdk_pci_device *dev, uint8_t *value, uint32_t offset) 635 { 636 return spdk_pci_device_cfg_read(dev, value, 1, offset); 637 } 638 639 int 640 spdk_pci_device_cfg_write8(struct spdk_pci_device *dev, uint8_t value, uint32_t offset) 641 { 642 return spdk_pci_device_cfg_write(dev, &value, 1, offset); 643 } 644 645 int 646 spdk_pci_device_cfg_read16(struct spdk_pci_device *dev, uint16_t *value, uint32_t offset) 647 { 648 return spdk_pci_device_cfg_read(dev, value, 2, offset); 649 } 650 651 int 652 spdk_pci_device_cfg_write16(struct spdk_pci_device *dev, uint16_t value, uint32_t offset) 653 { 654 return spdk_pci_device_cfg_write(dev, &value, 2, offset); 655 } 656 657 int 658 spdk_pci_device_cfg_read32(struct spdk_pci_device *dev, uint32_t *value, uint32_t offset) 659 { 660 return spdk_pci_device_cfg_read(dev, value, 4, offset); 661 } 662 663 int 664 spdk_pci_device_cfg_write32(struct spdk_pci_device *dev, uint32_t value, uint32_t offset) 665 { 666 return spdk_pci_device_cfg_write(dev, &value, 4, offset); 667 } 668 669 int 670 spdk_pci_device_get_serial_number(struct spdk_pci_device *dev, char *sn, size_t len) 671 { 672 int err; 673 uint32_t pos, header = 0; 674 uint32_t i, buf[2]; 675 676 if (len < 17) { 677 return -1; 678 } 679 680 err = spdk_pci_device_cfg_read32(dev, &header, PCI_CFG_SIZE); 681 if (err || !header) { 682 return -1; 683 } 684 685 pos = PCI_CFG_SIZE; 686 while (1) { 687 if ((header & 0x0000ffff) == PCI_EXT_CAP_ID_SN) { 688 if (pos) { 689 /* skip the header */ 690 pos += 4; 691 for (i = 0; i < 2; i++) { 692 err = spdk_pci_device_cfg_read32(dev, &buf[i], pos + 4 * i); 693 if (err) { 694 return -1; 695 } 696 } 697 snprintf(sn, len, "%08x%08x", buf[1], buf[0]); 698 return 0; 699 } 700 } 701 pos = (header >> 20) & 0xffc; 702 /* 0 if no other items exist */ 703 if (pos < PCI_CFG_SIZE) { 704 return -1; 705 } 706 err = spdk_pci_device_cfg_read32(dev, &header, pos); 707 if (err) { 708 return -1; 709 } 710 } 711 return -1; 712 } 713 714 struct spdk_pci_addr 715 spdk_pci_device_get_addr(struct spdk_pci_device *dev) 716 { 717 return dev->addr; 718 } 719 720 bool 721 spdk_pci_device_is_removed(struct spdk_pci_device *dev) 722 { 723 return dev->internal.pending_removal; 724 } 725 726 int 727 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2) 728 { 729 if (a1->domain > a2->domain) { 730 return 1; 731 } else if (a1->domain < a2->domain) { 732 return -1; 733 } else if (a1->bus > a2->bus) { 734 return 1; 735 } else if (a1->bus < a2->bus) { 736 return -1; 737 } else if (a1->dev > a2->dev) { 738 return 1; 739 } else if (a1->dev < a2->dev) { 740 return -1; 741 } else if (a1->func > a2->func) { 742 return 1; 743 } else if (a1->func < a2->func) { 744 return -1; 745 } 746 747 return 0; 748 } 749 750 #ifdef __linux__ 751 int 752 spdk_pci_device_claim(struct spdk_pci_device *dev) 753 { 754 int dev_fd; 755 char dev_name[64]; 756 int pid; 757 void *dev_map; 758 struct flock pcidev_lock = { 759 .l_type = F_WRLCK, 760 .l_whence = SEEK_SET, 761 .l_start = 0, 762 .l_len = 0, 763 }; 764 765 snprintf(dev_name, sizeof(dev_name), "/tmp/spdk_pci_lock_%04x:%02x:%02x.%x", 766 dev->addr.domain, dev->addr.bus, dev->addr.dev, dev->addr.func); 767 768 dev_fd = open(dev_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 769 if (dev_fd == -1) { 770 fprintf(stderr, "could not open %s\n", dev_name); 771 return -errno; 772 } 773 774 if (ftruncate(dev_fd, sizeof(int)) != 0) { 775 fprintf(stderr, "could not truncate %s\n", dev_name); 776 close(dev_fd); 777 return -errno; 778 } 779 780 dev_map = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, 781 MAP_SHARED, dev_fd, 0); 782 if (dev_map == MAP_FAILED) { 783 fprintf(stderr, "could not mmap dev %s (%d)\n", dev_name, errno); 784 close(dev_fd); 785 return -errno; 786 } 787 788 if (fcntl(dev_fd, F_SETLK, &pcidev_lock) != 0) { 789 pid = *(int *)dev_map; 790 fprintf(stderr, "Cannot create lock on device %s, probably" 791 " process %d has claimed it\n", dev_name, pid); 792 munmap(dev_map, sizeof(int)); 793 close(dev_fd); 794 /* F_SETLK returns unspecified errnos, normalize them */ 795 return -EACCES; 796 } 797 798 *(int *)dev_map = (int)getpid(); 799 munmap(dev_map, sizeof(int)); 800 dev->internal.claim_fd = dev_fd; 801 /* Keep dev_fd open to maintain the lock. */ 802 return 0; 803 } 804 805 void 806 spdk_pci_device_unclaim(struct spdk_pci_device *dev) 807 { 808 char dev_name[64]; 809 810 snprintf(dev_name, sizeof(dev_name), "/tmp/spdk_pci_lock_%04x:%02x:%02x.%x", 811 dev->addr.domain, dev->addr.bus, dev->addr.dev, dev->addr.func); 812 813 close(dev->internal.claim_fd); 814 dev->internal.claim_fd = -1; 815 unlink(dev_name); 816 } 817 #endif /* __linux__ */ 818 819 #ifdef __FreeBSD__ 820 int 821 spdk_pci_device_claim(struct spdk_pci_device *dev) 822 { 823 /* TODO */ 824 return 0; 825 } 826 827 void 828 spdk_pci_device_unclaim(struct spdk_pci_device *dev) 829 { 830 /* TODO */ 831 } 832 #endif /* __FreeBSD__ */ 833 834 int 835 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf) 836 { 837 unsigned domain, bus, dev, func; 838 839 if (addr == NULL || bdf == NULL) { 840 return -EINVAL; 841 } 842 843 if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) || 844 (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) { 845 /* Matched a full address - all variables are initialized */ 846 } else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) { 847 func = 0; 848 } else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) || 849 (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) { 850 domain = 0; 851 } else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) || 852 (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) { 853 domain = 0; 854 func = 0; 855 } else { 856 return -EINVAL; 857 } 858 859 if (bus > 0xFF || dev > 0x1F || func > 7) { 860 return -EINVAL; 861 } 862 863 addr->domain = domain; 864 addr->bus = bus; 865 addr->dev = dev; 866 addr->func = func; 867 868 return 0; 869 } 870 871 int 872 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr) 873 { 874 int rc; 875 876 rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x", 877 addr->domain, addr->bus, 878 addr->dev, addr->func); 879 880 if (rc > 0 && (size_t)rc < sz) { 881 return 0; 882 } 883 884 return -1; 885 } 886 887 void 888 spdk_pci_hook_device(struct spdk_pci_driver *drv, struct spdk_pci_device *dev) 889 { 890 assert(dev->map_bar != NULL); 891 assert(dev->unmap_bar != NULL); 892 assert(dev->cfg_read != NULL); 893 assert(dev->cfg_write != NULL); 894 assert(dev->detach != NULL); 895 dev->internal.driver = drv; 896 TAILQ_INSERT_TAIL(&g_pci_devices, dev, internal.tailq); 897 } 898 899 void 900 spdk_pci_unhook_device(struct spdk_pci_device *dev) 901 { 902 assert(!dev->internal.attached); 903 TAILQ_REMOVE(&g_pci_devices, dev, internal.tailq); 904 } 905 906 const char * 907 spdk_pci_device_get_type(const struct spdk_pci_device *dev) 908 { 909 return dev->type; 910 } 911