LCOV - code coverage report
Current view: top level - spdk/lib/env_dpdk - pci.c (source / functions) Hit Total Coverage
Test: Combined Lines: 412 536 76.9 %
Date: 2024-07-15 17:41:13 Functions: 53 64 82.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 220 406 54.2 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2015 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "env_internal.h"
       7                 :            : #include "pci_dpdk.h"
       8                 :            : 
       9                 :            : #include <rte_alarm.h>
      10                 :            : #include <rte_devargs.h>
      11                 :            : #include <rte_pci.h>
      12                 :            : #include "spdk/env.h"
      13                 :            : #include "spdk/log.h"
      14                 :            : #include "spdk/string.h"
      15                 :            : #include "spdk/memory.h"
      16                 :            : 
      17                 :            : #define SYSFS_PCI_DRIVERS       "/sys/bus/pci/drivers"
      18                 :            : 
      19                 :            : #define PCI_CFG_SIZE            256
      20                 :            : #define PCI_EXT_CAP_ID_SN       0x03
      21                 :            : 
      22                 :            : /* DPDK 18.11+ hotplug isn't robust. Multiple apps starting at the same time
      23                 :            :  * might cause the internal IPC to misbehave. Just retry in such case.
      24                 :            :  */
      25                 :            : #define DPDK_HOTPLUG_RETRY_COUNT 4
      26                 :            : 
      27                 :            : /* DPDK alarm/interrupt thread */
      28                 :            : static pthread_mutex_t g_pci_mutex = PTHREAD_MUTEX_INITIALIZER;
      29                 :            : static TAILQ_HEAD(, spdk_pci_device) g_pci_devices = TAILQ_HEAD_INITIALIZER(g_pci_devices);
      30                 :            : /* devices hotplugged on a dpdk thread */
      31                 :            : static TAILQ_HEAD(, spdk_pci_device) g_pci_hotplugged_devices =
      32                 :            :         TAILQ_HEAD_INITIALIZER(g_pci_hotplugged_devices);
      33                 :            : static TAILQ_HEAD(, spdk_pci_driver) g_pci_drivers = TAILQ_HEAD_INITIALIZER(g_pci_drivers);
      34                 :            : static TAILQ_HEAD(, spdk_pci_device_provider) g_pci_device_providers =
      35                 :            :         TAILQ_HEAD_INITIALIZER(g_pci_device_providers);
      36                 :            : 
      37                 :            : int pci_device_init(struct rte_pci_driver *driver, struct rte_pci_device *device);
      38                 :            : int pci_device_fini(struct rte_pci_device *device);
      39                 :            : 
      40                 :            : struct env_devargs {
      41                 :            :         struct rte_bus  *bus;
      42                 :            :         char            name[128];
      43                 :            :         uint64_t        allowed_at;
      44                 :            :         TAILQ_ENTRY(env_devargs) link;
      45                 :            : };
      46                 :            : static TAILQ_HEAD(, env_devargs) g_env_devargs = TAILQ_HEAD_INITIALIZER(g_env_devargs);
      47                 :            : 
      48                 :            : static struct env_devargs *
      49                 :    1842647 : find_env_devargs(struct rte_bus *bus, const char *name)
      50                 :            : {
      51                 :            :         struct env_devargs *da;
      52                 :            : 
      53         [ +  + ]:   20706511 :         TAILQ_FOREACH(da, &g_env_devargs, link) {
      54   [ +  -  +  +  :   20517289 :                 if (bus == da->bus && !strcmp(name, da->name)) {
             -  +  +  + ]
      55                 :    1653425 :                         return da;
      56                 :            :                 }
      57                 :            :         }
      58                 :            : 
      59                 :     189222 :         return NULL;
      60                 :            : }
      61                 :            : 
      62                 :            : static int
      63                 :       1262 : map_bar_rte(struct spdk_pci_device *device, uint32_t bar,
      64                 :            :             void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
      65                 :            : {
      66                 :            :         struct rte_mem_resource *res;
      67                 :            : 
      68                 :       1262 :         res = dpdk_pci_device_get_mem_resource(device->dev_handle, bar);
      69                 :       1262 :         *mapped_addr = res->addr;
      70                 :       1262 :         *phys_addr = (uint64_t)res->phys_addr;
      71                 :       1262 :         *size = (uint64_t)res->len;
      72                 :            : 
      73                 :       1262 :         return 0;
      74                 :            : }
      75                 :            : 
      76                 :            : static int
      77                 :       1127 : unmap_bar_rte(struct spdk_pci_device *device, uint32_t bar, void *addr)
      78                 :            : {
      79                 :       1127 :         return 0;
      80                 :            : }
      81                 :            : 
      82                 :            : static int
      83                 :       1080 : cfg_read_rte(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
      84                 :            : {
      85                 :       1080 :         return dpdk_pci_device_read_config(dev->dev_handle, value, len, offset);
      86                 :            : }
      87                 :            : 
      88                 :            : static int
      89                 :       1080 : cfg_write_rte(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
      90                 :            : {
      91                 :       1080 :         return dpdk_pci_device_write_config(dev->dev_handle, value, len, offset);
      92                 :            : }
      93                 :            : 
      94                 :            : static void
      95                 :       1044 : remove_rte_dev(struct rte_pci_device *rte_dev)
      96                 :            : {
      97                 :        348 :         char bdf[32];
      98                 :       1044 :         int i = 0, rc;
      99                 :            : 
     100         [ -  + ]:       1044 :         snprintf(bdf, sizeof(bdf), "%s", dpdk_pci_device_get_name(rte_dev));
     101                 :            :         do {
     102                 :       1044 :                 rc = rte_eal_hotplug_remove("pci", bdf);
     103   [ -  +  -  - ]:       1044 :         } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT);
     104                 :       1044 : }
     105                 :            : 
     106                 :            : static void
     107                 :       1044 : detach_rte_cb(void *_dev)
     108                 :            : {
     109                 :       1044 :         remove_rte_dev(_dev);
     110                 :       1044 : }
     111                 :            : 
     112                 :            : /* if it's a physical device we need to deal with DPDK on
     113                 :            :  * a different process and we can't just unset one flag
     114                 :            :  * here. We also want to stop using any device resources
     115                 :            :  * so that the device isn't "in use" by the userspace driver
     116                 :            :  * once we detach it. This would allow attaching the device
     117                 :            :  * to a different process, or to a kernel driver like nvme.
     118                 :            :  */
     119                 :            : static void
     120                 :       1269 : detach_rte(struct spdk_pci_device *dev)
     121                 :            : {
     122                 :       1269 :         struct rte_pci_device *rte_dev = dev->dev_handle;
     123                 :            :         int i;
     124                 :            :         bool removed;
     125                 :            : 
     126         [ +  + ]:       1269 :         if (!spdk_process_is_primary()) {
     127                 :        225 :                 return;
     128                 :            :         }
     129                 :            : 
     130         [ -  + ]:       1044 :         pthread_mutex_lock(&g_pci_mutex);
     131                 :       1044 :         dev->internal.attached = false;
     132                 :            :         /* prevent the hotremove notification from removing this device */
     133                 :       1044 :         dev->internal.pending_removal = true;
     134         [ -  + ]:       1044 :         pthread_mutex_unlock(&g_pci_mutex);
     135                 :            : 
     136                 :       1044 :         rte_eal_alarm_set(1, detach_rte_cb, rte_dev);
     137                 :            : 
     138                 :            :         /* wait up to 2s for the cb to execute */
     139         [ +  - ]:       1067 :         for (i = 2000; i > 0; i--) {
     140                 :            : 
     141                 :       1067 :                 spdk_delay_us(1000);
     142         [ -  + ]:       1067 :                 pthread_mutex_lock(&g_pci_mutex);
     143         [ -  + ]:       1067 :                 removed = dev->internal.removed;
     144         [ -  + ]:       1067 :                 pthread_mutex_unlock(&g_pci_mutex);
     145                 :            : 
     146         [ +  + ]:       1067 :                 if (removed) {
     147                 :       1044 :                         break;
     148                 :            :                 }
     149                 :            :         }
     150                 :            : 
     151                 :            :         /* besides checking the removed flag, we also need to wait
     152                 :            :          * for the dpdk detach function to unwind, as it's doing some
     153                 :            :          * operations even after calling our detach callback. Simply
     154                 :            :          * cancel the alarm - if it started executing already, this
     155                 :            :          * call will block and wait for it to finish.
     156                 :            :          */
     157                 :       1044 :         rte_eal_alarm_cancel(detach_rte_cb, rte_dev);
     158                 :            : 
     159                 :            :         /* the device could have been finally removed, so just check
     160                 :            :          * it again.
     161                 :            :          */
     162         [ -  + ]:       1044 :         pthread_mutex_lock(&g_pci_mutex);
     163         [ -  + ]:       1044 :         removed = dev->internal.removed;
     164         [ -  + ]:       1044 :         pthread_mutex_unlock(&g_pci_mutex);
     165         [ -  + ]:       1044 :         if (!removed) {
     166                 :          0 :                 SPDK_ERRLOG("Timeout waiting for DPDK to remove PCI device %s.\n",
     167                 :            :                             dpdk_pci_device_get_name(rte_dev));
     168                 :            :                 /* If we reach this state, then the device couldn't be removed and most likely
     169                 :            :                    a subsequent hot add of a device in the same BDF will fail */
     170                 :            :         }
     171                 :            : }
     172                 :            : 
     173                 :            : void
     174                 :      14786 : spdk_pci_driver_register(const char *name, struct spdk_pci_id *id_table, uint32_t flags)
     175                 :            : {
     176                 :            :         struct spdk_pci_driver *driver;
     177                 :            : 
     178                 :      14786 :         driver = calloc(1, sizeof(*driver));
     179         [ -  + ]:      14786 :         if (!driver) {
     180                 :            :                 /* we can't do any better than bailing atm */
     181                 :          0 :                 return;
     182                 :            :         }
     183                 :            : 
     184                 :      14786 :         driver->name = name;
     185                 :      14786 :         driver->id_table = id_table;
     186                 :      14786 :         driver->drv_flags = flags;
     187                 :      14786 :         driver->driver = (struct rte_pci_driver *)driver->driver_buf;
     188                 :      14786 :         TAILQ_INSERT_TAIL(&g_pci_drivers, driver, tailq);
     189                 :            : }
     190                 :            : 
     191                 :            : struct spdk_pci_driver *
     192                 :      85393 : spdk_pci_nvme_get_driver(void)
     193                 :            : {
     194                 :      85393 :         return spdk_pci_get_driver("nvme");
     195                 :            : }
     196                 :            : 
     197                 :            : struct spdk_pci_driver *
     198                 :      85419 : spdk_pci_get_driver(const char *name)
     199                 :            : {
     200                 :            :         struct spdk_pci_driver *driver;
     201                 :            : 
     202         [ +  - ]:     302320 :         TAILQ_FOREACH(driver, &g_pci_drivers, tailq) {
     203   [ +  +  -  +  :     302320 :                 if (strcmp(driver->name, name) == 0) {
                   +  + ]
     204                 :      85419 :                         return driver;
     205                 :            :                 }
     206                 :            :         }
     207                 :            : 
     208                 :          0 :         return NULL;
     209                 :            : }
     210                 :            : 
     211                 :            : static void
     212                 :          9 : pci_device_rte_dev_event(const char *device_name,
     213                 :            :                          enum rte_dev_event_type event,
     214                 :            :                          void *cb_arg)
     215                 :            : {
     216                 :            :         struct spdk_pci_device *dev;
     217                 :          9 :         bool can_detach = false;
     218                 :            : 
     219         [ -  + ]:          9 :         switch (event) {
     220                 :          0 :         default:
     221                 :            :         case RTE_DEV_EVENT_ADD:
     222                 :            :                 /* Nothing to do here yet. */
     223                 :          0 :                 break;
     224                 :          9 :         case RTE_DEV_EVENT_REMOVE:
     225                 :          9 :                 pthread_mutex_lock(&g_pci_mutex);
     226         [ +  - ]:          9 :                 TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
     227                 :          9 :                         struct rte_pci_device *rte_dev = dev->dev_handle;
     228                 :            : 
     229   [ -  +  -  +  :          9 :                         if (strcmp(dpdk_pci_device_get_name(rte_dev), device_name)) {
                   -  + ]
     230                 :          0 :                                 continue;
     231                 :            :                         }
     232                 :            : 
     233                 :            :                         /* Note: these ERRLOGs are useful for triaging issue #2983. */
     234   [ -  +  +  -  :          9 :                         if (dev->internal.pending_removal || dev->internal.removed) {
             -  +  -  + ]
     235                 :          0 :                                 SPDK_ERRLOG("Received event for device SPDK already tried to remove\n");
     236   [ #  #  #  # ]:          0 :                                 SPDK_ERRLOG("pending_removal=%d removed=%d\n", dev->internal.pending_removal,
     237                 :            :                                             dev->internal.removed);
     238                 :            :                         }
     239                 :            : 
     240   [ -  +  +  - ]:          9 :                         if (!dev->internal.pending_removal) {
     241         [ -  + ]:          9 :                                 can_detach = !dev->internal.attached;
     242                 :            :                                 /* prevent any further attaches */
     243                 :          9 :                                 dev->internal.pending_removal = true;
     244                 :          9 :                                 break;
     245                 :            :                         }
     246                 :            :                 }
     247                 :          9 :                 pthread_mutex_unlock(&g_pci_mutex);
     248                 :            : 
     249         [ -  + ]:          9 :                 if (can_detach) {
     250                 :            :                         /* if device is not attached we can remove it right away.
     251                 :            :                          * Otherwise it will be removed at detach.
     252                 :            :                          *
     253                 :            :                          * Because the user's callback is invoked in eal interrupt
     254                 :            :                          * callback, the interrupt callback need to be finished before
     255                 :            :                          * it can be unregistered when detaching device. So finish
     256                 :            :                          * callback soon and use a deferred removal to detach device
     257                 :            :                          * is need. It is a workaround, once the device detaching be
     258                 :            :                          * moved into the eal in the future, the deferred removal could
     259                 :            :                          * be deleted.
     260                 :            :                          */
     261         [ #  # ]:          0 :                         assert(dev != NULL);
     262                 :          0 :                         rte_eal_alarm_set(1, detach_rte_cb, dev->dev_handle);
     263                 :            :                 }
     264                 :          9 :                 break;
     265                 :            :         }
     266                 :          9 : }
     267                 :            : 
     268                 :            : static void
     269                 :     175164 : cleanup_pci_devices(void)
     270                 :            : {
     271                 :            :         struct spdk_pci_device *dev, *tmp;
     272                 :            : 
     273         [ -  + ]:     175164 :         pthread_mutex_lock(&g_pci_mutex);
     274                 :            :         /* cleanup removed devices */
     275         [ +  + ]:     409910 :         TAILQ_FOREACH_SAFE(dev, &g_pci_devices, internal.tailq, tmp) {
     276   [ +  +  +  + ]:     234746 :                 if (!dev->internal.removed) {
     277                 :     233702 :                         continue;
     278                 :            :                 }
     279                 :            : 
     280                 :       1044 :                 vtophys_pci_device_removed(dev->dev_handle);
     281         [ +  + ]:       1044 :                 TAILQ_REMOVE(&g_pci_devices, dev, internal.tailq);
     282                 :       1044 :                 free(dev);
     283                 :            :         }
     284                 :            : 
     285                 :            :         /* add newly-attached devices */
     286         [ +  + ]:     176944 :         TAILQ_FOREACH_SAFE(dev, &g_pci_hotplugged_devices, internal.tailq, tmp) {
     287         [ +  + ]:       1780 :                 TAILQ_REMOVE(&g_pci_hotplugged_devices, dev, internal.tailq);
     288                 :       1780 :                 TAILQ_INSERT_TAIL(&g_pci_devices, dev, internal.tailq);
     289                 :       1780 :                 vtophys_pci_device_added(dev->dev_handle);
     290                 :            :         }
     291         [ -  + ]:     175164 :         pthread_mutex_unlock(&g_pci_mutex);
     292                 :     175164 : }
     293                 :            : 
     294                 :            : static int scan_pci_bus(bool delay_init);
     295                 :            : 
     296                 :            : static inline void
     297                 :       3101 : _pci_env_init(void)
     298                 :            : {
     299                 :            :         /* We assume devices were present on the bus for more than 2 seconds
     300                 :            :          * before initializing SPDK and there's no need to wait more. We scan
     301                 :            :          * the bus, but we don't block any devices.
     302                 :            :          */
     303                 :       3101 :         scan_pci_bus(false);
     304                 :            : 
     305                 :            :         /* Register a single hotremove callback for all devices. */
     306         [ +  + ]:       3101 :         if (spdk_process_is_primary()) {
     307                 :       2951 :                 rte_dev_event_callback_register(NULL, pci_device_rte_dev_event, NULL);
     308                 :            :         }
     309                 :       3101 : }
     310                 :            : 
     311                 :            : int
     312                 :       3044 : pci_env_init(void)
     313                 :            : {
     314                 :            :         struct spdk_pci_driver *driver;
     315                 :            :         int rc;
     316                 :            : 
     317                 :       3044 :         rc = dpdk_pci_init();
     318         [ -  + ]:       3044 :         if (rc) {
     319                 :          0 :                 return rc;
     320                 :            :         }
     321                 :            : 
     322         [ +  + ]:      17217 :         TAILQ_FOREACH(driver, &g_pci_drivers, tailq) {
     323                 :      14173 :                 dpdk_pci_driver_register(driver, pci_device_init, pci_device_fini);
     324                 :            :         }
     325                 :            : 
     326                 :       3044 :         _pci_env_init();
     327                 :       3044 :         return 0;
     328                 :            : }
     329                 :            : 
     330                 :            : void
     331                 :         57 : pci_env_reinit(void)
     332                 :            : {
     333                 :            :         /* There is no need to register pci drivers again, since they were
     334                 :            :          * already pre-registered in pci_env_init.
     335                 :            :          */
     336                 :            : 
     337                 :         57 :         _pci_env_init();
     338                 :         57 : }
     339                 :            : 
     340                 :            : void
     341                 :       2981 : pci_env_fini(void)
     342                 :            : {
     343                 :            :         struct spdk_pci_device *dev;
     344                 :       1253 :         char bdf[32];
     345                 :            : 
     346                 :       2981 :         cleanup_pci_devices();
     347         [ +  + ]:       3341 :         TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
     348   [ -  +  +  + ]:        360 :                 if (dev->internal.attached) {
     349                 :         32 :                         spdk_pci_addr_fmt(bdf, sizeof(bdf), &dev->addr);
     350                 :         32 :                         SPDK_ERRLOG("Device %s is still attached at shutdown!\n", bdf);
     351                 :            :                 }
     352                 :            :         }
     353                 :            : 
     354         [ +  + ]:       2981 :         if (spdk_process_is_primary()) {
     355                 :       2891 :                 rte_dev_event_callback_unregister(NULL, pci_device_rte_dev_event, NULL);
     356                 :            :         }
     357                 :       2981 : }
     358                 :            : 
     359                 :            : int
     360                 :       1802 : pci_device_init(struct rte_pci_driver *_drv,
     361                 :            :                 struct rte_pci_device *_dev)
     362                 :            : {
     363                 :       1802 :         struct spdk_pci_driver *driver = (struct spdk_pci_driver *)_drv;
     364                 :            :         struct spdk_pci_device *dev;
     365                 :            :         struct rte_pci_addr *addr;
     366                 :            :         struct rte_pci_id *id;
     367                 :            :         int rc;
     368                 :            : 
     369                 :       1802 :         dev = calloc(1, sizeof(*dev));
     370         [ -  + ]:       1802 :         if (dev == NULL) {
     371                 :          0 :                 return -1;
     372                 :            :         }
     373                 :            : 
     374                 :       1802 :         dev->dev_handle = _dev;
     375                 :            : 
     376                 :       1802 :         addr = dpdk_pci_device_get_addr(_dev);
     377                 :       1802 :         dev->addr.domain = addr->domain;
     378                 :       1802 :         dev->addr.bus = addr->bus;
     379                 :       1802 :         dev->addr.dev = addr->devid;
     380                 :       1802 :         dev->addr.func = addr->function;
     381                 :            : 
     382                 :       1802 :         id = dpdk_pci_device_get_id(_dev);
     383                 :       1802 :         dev->id.class_id = id->class_id;
     384                 :       1802 :         dev->id.vendor_id = id->vendor_id;
     385                 :       1802 :         dev->id.device_id = id->device_id;
     386                 :       1802 :         dev->id.subvendor_id = id->subsystem_vendor_id;
     387                 :       1802 :         dev->id.subdevice_id = id->subsystem_device_id;
     388                 :            : 
     389                 :       1802 :         dev->socket_id = dpdk_pci_device_get_numa_node(_dev);
     390                 :       1802 :         dev->type = "pci";
     391                 :            : 
     392                 :       1802 :         dev->map_bar = map_bar_rte;
     393                 :       1802 :         dev->unmap_bar = unmap_bar_rte;
     394                 :       1802 :         dev->cfg_read = cfg_read_rte;
     395                 :       1802 :         dev->cfg_write = cfg_write_rte;
     396                 :            : 
     397                 :       1802 :         dev->internal.driver = driver;
     398                 :       1802 :         dev->internal.claim_fd = -1;
     399                 :            : 
     400         [ +  + ]:       1802 :         if (driver->cb_fn != NULL) {
     401                 :       1336 :                 rc = driver->cb_fn(driver->cb_arg, dev);
     402         [ +  + ]:       1336 :                 if (rc != 0) {
     403                 :         22 :                         free(dev);
     404                 :         22 :                         return rc;
     405                 :            :                 }
     406                 :       1314 :                 dev->internal.attached = true;
     407                 :            :         }
     408                 :            : 
     409         [ -  + ]:       1780 :         pthread_mutex_lock(&g_pci_mutex);
     410                 :       1780 :         TAILQ_INSERT_TAIL(&g_pci_hotplugged_devices, dev, internal.tailq);
     411         [ -  + ]:       1780 :         pthread_mutex_unlock(&g_pci_mutex);
     412                 :       1780 :         return 0;
     413                 :            : }
     414                 :            : 
     415                 :            : static void
     416                 :      96839 : set_allowed_at(struct rte_devargs *rte_da, uint64_t tsc)
     417                 :            : {
     418                 :            :         struct env_devargs *env_da;
     419                 :            : 
     420                 :      96839 :         env_da = find_env_devargs(rte_da->bus, rte_da->name);
     421         [ +  + ]:      96839 :         if (env_da == NULL) {
     422                 :      94611 :                 env_da = calloc(1, sizeof(*env_da));
     423         [ -  + ]:      94611 :                 if (env_da == NULL) {
     424                 :          0 :                         SPDK_ERRLOG("could not set_allowed_at for device %s\n", rte_da->name);
     425                 :          0 :                         return;
     426                 :            :                 }
     427                 :      94611 :                 env_da->bus = rte_da->bus;
     428                 :      94611 :                 spdk_strcpy_pad(env_da->name, rte_da->name, sizeof(env_da->name), 0);
     429                 :      94611 :                 TAILQ_INSERT_TAIL(&g_env_devargs, env_da, link);
     430                 :            :         }
     431                 :            : 
     432                 :      96839 :         env_da->allowed_at = tsc;
     433                 :            : }
     434                 :            : 
     435                 :            : static uint64_t
     436                 :    1745808 : get_allowed_at(struct rte_devargs *rte_da)
     437                 :            : {
     438                 :            :         struct env_devargs *env_da;
     439                 :            : 
     440                 :    1745808 :         env_da = find_env_devargs(rte_da->bus, rte_da->name);
     441         [ +  + ]:    1745808 :         if (env_da) {
     442                 :    1651197 :                 return env_da->allowed_at;
     443                 :            :         } else {
     444                 :      94611 :                 return 0;
     445                 :            :         }
     446                 :            : }
     447                 :            : 
     448                 :            : int
     449                 :       1668 : pci_device_fini(struct rte_pci_device *_dev)
     450                 :            : {
     451                 :            :         struct spdk_pci_device *dev;
     452                 :            : 
     453         [ -  + ]:       1668 :         pthread_mutex_lock(&g_pci_mutex);
     454         [ +  - ]:       5139 :         TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
     455         [ +  + ]:       5139 :                 if (dev->dev_handle == _dev) {
     456                 :       1668 :                         break;
     457                 :            :                 }
     458                 :            :         }
     459                 :            : 
     460   [ +  -  +  +  :       1668 :         if (dev == NULL || dev->internal.attached) {
                   +  + ]
     461                 :            :                 /* The device might be still referenced somewhere in SPDK. */
     462         [ -  + ]:         45 :                 pthread_mutex_unlock(&g_pci_mutex);
     463                 :         45 :                 return -EBUSY;
     464                 :            :         }
     465                 :            : 
     466                 :            :         /* remove our allowed_at option */
     467         [ +  - ]:       1623 :         if (dpdk_pci_device_get_devargs(_dev)) {
     468                 :       1623 :                 set_allowed_at(dpdk_pci_device_get_devargs(_dev), 0);
     469                 :            :         }
     470                 :            : 
     471                 :            :         /* It is possible that removed flag was already set when there is a race
     472                 :            :          * between the remove notification for this process, and another process
     473                 :            :          * that is also detaching from this same device (for example, when using
     474                 :            :          * nvme driver in multi-process mode.  So do not assert here.  See
     475                 :            :          * #2456 for additional details.
     476                 :            :          */
     477                 :       1623 :         dev->internal.removed = true;
     478         [ -  + ]:       1623 :         pthread_mutex_unlock(&g_pci_mutex);
     479                 :       1623 :         return 0;
     480                 :            : 
     481                 :            : }
     482                 :            : 
     483                 :            : void
     484                 :       1288 : spdk_pci_device_detach(struct spdk_pci_device *dev)
     485                 :            : {
     486                 :            :         struct spdk_pci_device_provider *provider;
     487                 :            : 
     488   [ -  +  -  + ]:       1288 :         assert(dev->internal.attached);
     489                 :            : 
     490         [ +  + ]:       1288 :         if (dev->internal.claim_fd >= 0) {
     491                 :        403 :                 spdk_pci_device_unclaim(dev);
     492                 :            :         }
     493                 :            : 
     494         [ +  - ]:       1786 :         TAILQ_FOREACH(provider, &g_pci_device_providers, tailq) {
     495   [ +  +  -  +  :       1786 :                 if (strcmp(dev->type, provider->name) == 0) {
                   +  + ]
     496                 :       1288 :                         break;
     497                 :            :                 }
     498                 :            :         }
     499                 :            : 
     500         [ -  + ]:       1288 :         assert(provider != NULL);
     501                 :       1288 :         dev->internal.attached = false;
     502                 :       1288 :         provider->detach_cb(dev);
     503                 :            : 
     504                 :       1288 :         cleanup_pci_devices();
     505                 :       1288 : }
     506                 :            : 
     507                 :            : static int
     508                 :      87985 : scan_pci_bus(bool delay_init)
     509                 :            : {
     510                 :      43715 :         struct rte_dev_iterator it;
     511                 :            :         struct rte_device *rte_dev;
     512                 :            :         uint64_t now;
     513                 :            : 
     514                 :      87985 :         dpdk_bus_scan();
     515                 :      87985 :         now = spdk_get_ticks();
     516                 :            : 
     517         [ +  + ]:      87985 :         if (!TAILQ_FIRST(&g_pci_drivers)) {
     518                 :         21 :                 return 0;
     519                 :            :         }
     520                 :            : 
     521         [ +  + ]:    1007942 :         RTE_DEV_FOREACH(rte_dev, "bus=pci", &it) {
     522                 :     400928 :                 struct rte_devargs *da;
     523                 :            : 
     524                 :     919978 :                 da = dpdk_device_get_devargs(rte_dev);
     525         [ +  + ]:     919978 :                 if (!da) {
     526                 :      23862 :                         char devargs_str[128];
     527                 :            : 
     528                 :            :                         /* the device was never blocked or allowed */
     529                 :      94683 :                         da = calloc(1, sizeof(*da));
     530         [ -  + ]:      94683 :                         if (!da) {
     531                 :          0 :                                 return -1;
     532                 :            :                         }
     533                 :            : 
     534         [ -  + ]:      94683 :                         snprintf(devargs_str, sizeof(devargs_str), "pci:%s", dpdk_device_get_name(rte_dev));
     535         [ -  + ]:      94683 :                         if (rte_devargs_parse(da, devargs_str) != 0) {
     536                 :          0 :                                 free(da);
     537                 :          0 :                                 return -1;
     538                 :            :                         }
     539                 :            : 
     540                 :      94683 :                         rte_devargs_insert(&da);
     541                 :      94683 :                         dpdk_device_set_devargs(rte_dev, da);
     542                 :            :                 }
     543                 :            : 
     544         [ +  + ]:     919978 :                 if (get_allowed_at(da)) {
     545                 :     825295 :                         uint64_t allowed_at = get_allowed_at(da);
     546                 :            : 
     547                 :            :                         /* this device was seen by spdk before... */
     548   [ +  +  +  + ]:     825295 :                         if (da->policy == RTE_DEV_BLOCKED && allowed_at <= now) {
     549                 :         45 :                                 da->policy = RTE_DEV_ALLOWED;
     550                 :            :                         }
     551   [ -  +  -  - ]:      94683 :                 } else if ((dpdk_device_scan_allowed(rte_dev) && da->policy == RTE_DEV_ALLOWED) ||
     552         [ +  - ]:      94683 :                            da->policy != RTE_DEV_BLOCKED) {
     553                 :            :                         /* override the policy only if not permanently blocked */
     554                 :            : 
     555         [ +  + ]:      94683 :                         if (delay_init) {
     556                 :         72 :                                 da->policy = RTE_DEV_BLOCKED;
     557                 :         72 :                                 set_allowed_at(da, now + 2 * spdk_get_ticks_hz());
     558                 :            :                         } else {
     559                 :      94611 :                                 da->policy = RTE_DEV_ALLOWED;
     560                 :      94611 :                                 set_allowed_at(da, now);
     561                 :            :                         }
     562                 :            :                 }
     563                 :            :         }
     564                 :            : 
     565                 :      87964 :         return 0;
     566                 :            : }
     567                 :            : 
     568                 :            : static int
     569                 :        554 : pci_attach_rte(const struct spdk_pci_addr *addr)
     570                 :            : {
     571                 :        306 :         char bdf[32];
     572                 :        554 :         int rc, i = 0;
     573                 :            : 
     574                 :        554 :         spdk_pci_addr_fmt(bdf, sizeof(bdf), addr);
     575                 :            : 
     576                 :            :         do {
     577                 :        554 :                 rc = rte_eal_hotplug_add("pci", bdf, "");
     578   [ -  +  -  - ]:        554 :         } while (rc == -ENOMSG && ++i <= DPDK_HOTPLUG_RETRY_COUNT);
     579                 :            : 
     580   [ -  +  -  - ]:        554 :         if (i > 1 && rc == -EEXIST) {
     581                 :            :                 /* Even though the previous request timed out, the device
     582                 :            :                  * was attached successfully.
     583                 :            :                  */
     584                 :          0 :                 rc = 0;
     585                 :            :         }
     586                 :            : 
     587                 :        554 :         return rc;
     588                 :            : }
     589                 :            : 
     590                 :            : static struct spdk_pci_device_provider g_pci_rte_provider = {
     591                 :            :         .name = "pci",
     592                 :            :         .attach_cb = pci_attach_rte,
     593                 :            :         .detach_cb = detach_rte,
     594                 :            : };
     595                 :            : 
     596                 :       3203 : SPDK_PCI_REGISTER_DEVICE_PROVIDER(pci, &g_pci_rte_provider);
     597                 :            : 
     598                 :            : int
     599                 :        573 : spdk_pci_device_attach(struct spdk_pci_driver *driver,
     600                 :            :                        spdk_pci_enum_cb enum_cb,
     601                 :            :                        void *enum_ctx, struct spdk_pci_addr *pci_address)
     602                 :            : {
     603                 :            :         struct spdk_pci_device *dev;
     604                 :            :         struct spdk_pci_device_provider *provider;
     605                 :            :         struct rte_pci_device *rte_dev;
     606                 :            :         struct rte_devargs *da;
     607                 :            :         int rc;
     608                 :            : 
     609                 :        573 :         cleanup_pci_devices();
     610                 :            : 
     611         [ +  + ]:        736 :         TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
     612         [ +  + ]:        182 :                 if (spdk_pci_addr_compare(&dev->addr, pci_address) == 0) {
     613                 :         19 :                         break;
     614                 :            :                 }
     615                 :            :         }
     616                 :            : 
     617   [ +  +  +  - ]:        573 :         if (dev != NULL && dev->internal.driver == driver) {
     618         [ -  + ]:         19 :                 pthread_mutex_lock(&g_pci_mutex);
     619   [ +  +  +  +  :         19 :                 if (dev->internal.attached || dev->internal.pending_removal) {
             -  +  -  + ]
     620         [ #  # ]:          0 :                         pthread_mutex_unlock(&g_pci_mutex);
     621                 :          0 :                         return -1;
     622                 :            :                 }
     623                 :            : 
     624                 :         19 :                 rc = enum_cb(enum_ctx, dev);
     625         [ +  - ]:         19 :                 if (rc == 0) {
     626                 :         19 :                         dev->internal.attached = true;
     627                 :            :                 }
     628         [ -  + ]:         19 :                 pthread_mutex_unlock(&g_pci_mutex);
     629                 :         19 :                 return rc;
     630                 :            :         }
     631                 :            : 
     632                 :        554 :         driver->cb_fn = enum_cb;
     633                 :        554 :         driver->cb_arg = enum_ctx;
     634                 :            : 
     635                 :        554 :         rc = -ENODEV;
     636         [ +  + ]:        946 :         TAILQ_FOREACH(provider, &g_pci_device_providers, tailq) {
     637                 :        927 :                 rc = provider->attach_cb(pci_address);
     638         [ +  + ]:        927 :                 if (rc == 0) {
     639                 :        535 :                         break;
     640                 :            :                 }
     641                 :            :         }
     642                 :            : 
     643                 :        554 :         driver->cb_arg = NULL;
     644                 :        554 :         driver->cb_fn = NULL;
     645                 :            : 
     646                 :        554 :         cleanup_pci_devices();
     647                 :            : 
     648         [ +  + ]:        554 :         if (rc != 0) {
     649                 :         19 :                 return -1;
     650                 :            :         }
     651                 :            : 
     652                 :            :         /* explicit attach ignores the allowlist, so if we blocked this
     653                 :            :          * device before let's enable it now - just for clarity.
     654                 :            :          */
     655         [ +  - ]:        698 :         TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
     656         [ +  + ]:        698 :                 if (spdk_pci_addr_compare(&dev->addr, pci_address) == 0) {
     657                 :        535 :                         break;
     658                 :            :                 }
     659                 :            :         }
     660         [ -  + ]:        535 :         assert(dev != NULL);
     661                 :            : 
     662                 :        535 :         rte_dev = dev->dev_handle;
     663         [ +  - ]:        535 :         if (rte_dev != NULL) {
     664                 :        535 :                 da = dpdk_pci_device_get_devargs(rte_dev);
     665   [ +  -  +  + ]:        535 :                 if (da && get_allowed_at(da)) {
     666                 :        533 :                         set_allowed_at(da, spdk_get_ticks());
     667                 :        533 :                         da->policy = RTE_DEV_ALLOWED;
     668                 :            :                 }
     669                 :            :         }
     670                 :            : 
     671                 :        535 :         return 0;
     672                 :            : }
     673                 :            : 
     674                 :            : /* Note: You can call spdk_pci_enumerate from more than one thread
     675                 :            :  *       simultaneously safely, but you cannot call spdk_pci_enumerate
     676                 :            :  *       and rte_eal_pci_probe simultaneously.
     677                 :            :  */
     678                 :            : int
     679                 :      84884 : spdk_pci_enumerate(struct spdk_pci_driver *driver,
     680                 :            :                    spdk_pci_enum_cb enum_cb,
     681                 :            :                    void *enum_ctx)
     682                 :            : {
     683                 :            :         struct spdk_pci_device *dev;
     684                 :            :         int rc;
     685                 :            : 
     686                 :      84884 :         cleanup_pci_devices();
     687                 :            : 
     688         [ -  + ]:      84884 :         pthread_mutex_lock(&g_pci_mutex);
     689         [ +  + ]:     199330 :         TAILQ_FOREACH(dev, &g_pci_devices, internal.tailq) {
     690   [ -  +  -  + ]:     114446 :                 if (dev->internal.attached ||
     691         [ #  # ]:          0 :                     dev->internal.driver != driver ||
     692   [ #  #  #  # ]:          0 :                     dev->internal.pending_removal) {
     693                 :     114446 :                         continue;
     694                 :            :                 }
     695                 :            : 
     696                 :          0 :                 rc = enum_cb(enum_ctx, dev);
     697         [ #  # ]:          0 :                 if (rc == 0) {
     698                 :          0 :                         dev->internal.attached = true;
     699         [ #  # ]:          0 :                 } else if (rc < 0) {
     700         [ #  # ]:          0 :                         pthread_mutex_unlock(&g_pci_mutex);
     701                 :          0 :                         return -1;
     702                 :            :                 }
     703                 :            :         }
     704         [ -  + ]:      84884 :         pthread_mutex_unlock(&g_pci_mutex);
     705                 :            : 
     706         [ -  + ]:      84884 :         if (scan_pci_bus(true) != 0) {
     707                 :          0 :                 return -1;
     708                 :            :         }
     709                 :            : 
     710                 :      84884 :         driver->cb_fn = enum_cb;
     711                 :      84884 :         driver->cb_arg = enum_ctx;
     712                 :            : 
     713         [ -  + ]:      84884 :         if (dpdk_bus_probe() != 0) {
     714                 :          0 :                 driver->cb_arg = NULL;
     715                 :          0 :                 driver->cb_fn = NULL;
     716                 :          0 :                 return -1;
     717                 :            :         }
     718                 :            : 
     719                 :      84884 :         driver->cb_arg = NULL;
     720                 :      84884 :         driver->cb_fn = NULL;
     721                 :            : 
     722                 :      84884 :         cleanup_pci_devices();
     723                 :      84884 :         return 0;
     724                 :            : }
     725                 :            : 
     726                 :            : void
     727                 :          0 : spdk_pci_for_each_device(void *ctx, void (*fn)(void *ctx, struct spdk_pci_device *dev))
     728                 :            : {
     729                 :            :         struct spdk_pci_device *dev, *tmp;
     730                 :            : 
     731         [ #  # ]:          0 :         pthread_mutex_lock(&g_pci_mutex);
     732         [ #  # ]:          0 :         TAILQ_FOREACH_SAFE(dev, &g_pci_devices, internal.tailq, tmp) {
     733                 :          0 :                 fn(ctx, dev);
     734                 :            :         }
     735         [ #  # ]:          0 :         pthread_mutex_unlock(&g_pci_mutex);
     736                 :          0 : }
     737                 :            : 
     738                 :            : int
     739                 :       1300 : spdk_pci_device_map_bar(struct spdk_pci_device *dev, uint32_t bar,
     740                 :            :                         void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
     741                 :            : {
     742                 :            :         int rc;
     743                 :            : 
     744                 :       1300 :         rc = dev->map_bar(dev, bar, mapped_addr, phys_addr, size);
     745         [ +  + ]:       1300 :         if (rc) {
     746                 :         19 :                 return rc;
     747                 :            :         }
     748                 :            : 
     749                 :            : #if VFIO_ENABLED
     750                 :            :         /* Automatically map the BAR to the IOMMU */
     751         [ +  + ]:       1281 :         if (!spdk_iommu_is_enabled()) {
     752                 :        773 :                 return 0;
     753                 :            :         }
     754                 :            : 
     755         [ +  + ]:        508 :         if (rte_eal_iova_mode() == RTE_IOVA_VA) {
     756                 :            :                 /* We'll use the virtual address as the iova to match DPDK. */
     757                 :        497 :                 rc = vtophys_iommu_map_dma_bar((uint64_t)(*mapped_addr), (uint64_t) * mapped_addr, *size);
     758         [ -  + ]:        497 :                 if (rc) {
     759                 :          0 :                         dev->unmap_bar(dev, bar, *mapped_addr);
     760                 :          0 :                         return -EFAULT;
     761                 :            :                 }
     762                 :            : 
     763                 :        497 :                 *phys_addr = (uint64_t)(*mapped_addr);
     764                 :            :         } else {
     765                 :            :                 /* We'll use the physical address as the iova to match DPDK. */
     766                 :         11 :                 rc = vtophys_iommu_map_dma_bar((uint64_t)(*mapped_addr), *phys_addr, *size);
     767         [ -  + ]:         11 :                 if (rc) {
     768                 :          0 :                         dev->unmap_bar(dev, bar, *mapped_addr);
     769                 :          0 :                         return -EFAULT;
     770                 :            :                 }
     771                 :            :         }
     772                 :            : #endif
     773                 :        508 :         return rc;
     774                 :            : }
     775                 :            : 
     776                 :            : int
     777                 :       1146 : spdk_pci_device_unmap_bar(struct spdk_pci_device *dev, uint32_t bar, void *addr)
     778                 :            : {
     779                 :            : #if VFIO_ENABLED
     780                 :            :         int rc;
     781                 :            : 
     782         [ +  + ]:       1146 :         if (spdk_iommu_is_enabled()) {
     783                 :        484 :                 rc = vtophys_iommu_unmap_dma_bar((uint64_t)addr);
     784         [ -  + ]:        484 :                 if (rc) {
     785                 :          0 :                         return -EFAULT;
     786                 :            :                 }
     787                 :            :         }
     788                 :            : #endif
     789                 :            : 
     790                 :       1146 :         return dev->unmap_bar(dev, bar, addr);
     791                 :            : }
     792                 :            : 
     793                 :            : int
     794                 :          0 : spdk_pci_device_enable_interrupt(struct spdk_pci_device *dev)
     795                 :            : {
     796                 :          0 :         return dpdk_pci_device_enable_interrupt(dev->dev_handle);
     797                 :            : }
     798                 :            : 
     799                 :            : int
     800                 :          0 : spdk_pci_device_disable_interrupt(struct spdk_pci_device *dev)
     801                 :            : {
     802                 :          0 :         return dpdk_pci_device_disable_interrupt(dev->dev_handle);
     803                 :            : }
     804                 :            : 
     805                 :            : int
     806                 :          0 : spdk_pci_device_get_interrupt_efd(struct spdk_pci_device *dev)
     807                 :            : {
     808                 :          0 :         return dpdk_pci_device_get_interrupt_efd(dev->dev_handle);
     809                 :            : }
     810                 :            : 
     811                 :            : uint32_t
     812                 :         32 : spdk_pci_device_get_domain(struct spdk_pci_device *dev)
     813                 :            : {
     814                 :         32 :         return dev->addr.domain;
     815                 :            : }
     816                 :            : 
     817                 :            : uint8_t
     818                 :         32 : spdk_pci_device_get_bus(struct spdk_pci_device *dev)
     819                 :            : {
     820                 :         32 :         return dev->addr.bus;
     821                 :            : }
     822                 :            : 
     823                 :            : uint8_t
     824                 :         32 : spdk_pci_device_get_dev(struct spdk_pci_device *dev)
     825                 :            : {
     826                 :         32 :         return dev->addr.dev;
     827                 :            : }
     828                 :            : 
     829                 :            : uint8_t
     830                 :         32 : spdk_pci_device_get_func(struct spdk_pci_device *dev)
     831                 :            : {
     832                 :         32 :         return dev->addr.func;
     833                 :            : }
     834                 :            : 
     835                 :            : uint16_t
     836                 :         52 : spdk_pci_device_get_vendor_id(struct spdk_pci_device *dev)
     837                 :            : {
     838                 :         52 :         return dev->id.vendor_id;
     839                 :            : }
     840                 :            : 
     841                 :            : uint16_t
     842                 :         42 : spdk_pci_device_get_device_id(struct spdk_pci_device *dev)
     843                 :            : {
     844                 :         42 :         return dev->id.device_id;
     845                 :            : }
     846                 :            : 
     847                 :            : uint16_t
     848                 :          0 : spdk_pci_device_get_subvendor_id(struct spdk_pci_device *dev)
     849                 :            : {
     850                 :          0 :         return dev->id.subvendor_id;
     851                 :            : }
     852                 :            : 
     853                 :            : uint16_t
     854                 :          0 : spdk_pci_device_get_subdevice_id(struct spdk_pci_device *dev)
     855                 :            : {
     856                 :          0 :         return dev->id.subdevice_id;
     857                 :            : }
     858                 :            : 
     859                 :            : struct spdk_pci_id
     860                 :        797 : spdk_pci_device_get_id(struct spdk_pci_device *dev)
     861                 :            : {
     862                 :        797 :         return dev->id;
     863                 :            : }
     864                 :            : 
     865                 :            : int
     866                 :          0 : spdk_pci_device_get_socket_id(struct spdk_pci_device *dev)
     867                 :            : {
     868                 :          0 :         return dev->socket_id;
     869                 :            : }
     870                 :            : 
     871                 :            : int
     872                 :       1137 : spdk_pci_device_cfg_read(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
     873                 :            : {
     874                 :       1137 :         return dev->cfg_read(dev, value, len, offset);
     875                 :            : }
     876                 :            : 
     877                 :            : int
     878                 :       1118 : spdk_pci_device_cfg_write(struct spdk_pci_device *dev, void *value, uint32_t len, uint32_t offset)
     879                 :            : {
     880                 :       1118 :         return dev->cfg_write(dev, value, len, offset);
     881                 :            : }
     882                 :            : 
     883                 :            : int
     884                 :          0 : spdk_pci_device_cfg_read8(struct spdk_pci_device *dev, uint8_t *value, uint32_t offset)
     885                 :            : {
     886                 :          0 :         return spdk_pci_device_cfg_read(dev, value, 1, offset);
     887                 :            : }
     888                 :            : 
     889                 :            : int
     890                 :          0 : spdk_pci_device_cfg_write8(struct spdk_pci_device *dev, uint8_t value, uint32_t offset)
     891                 :            : {
     892                 :          0 :         return spdk_pci_device_cfg_write(dev, &value, 1, offset);
     893                 :            : }
     894                 :            : 
     895                 :            : int
     896                 :        664 : spdk_pci_device_cfg_read16(struct spdk_pci_device *dev, uint16_t *value, uint32_t offset)
     897                 :            : {
     898                 :        664 :         return spdk_pci_device_cfg_read(dev, value, 2, offset);
     899                 :            : }
     900                 :            : 
     901                 :            : int
     902                 :        664 : spdk_pci_device_cfg_write16(struct spdk_pci_device *dev, uint16_t value, uint32_t offset)
     903                 :            : {
     904                 :        664 :         return spdk_pci_device_cfg_write(dev, &value, 2, offset);
     905                 :            : }
     906                 :            : 
     907                 :            : int
     908                 :        473 : spdk_pci_device_cfg_read32(struct spdk_pci_device *dev, uint32_t *value, uint32_t offset)
     909                 :            : {
     910                 :        473 :         return spdk_pci_device_cfg_read(dev, value, 4, offset);
     911                 :            : }
     912                 :            : 
     913                 :            : int
     914                 :        454 : spdk_pci_device_cfg_write32(struct spdk_pci_device *dev, uint32_t value, uint32_t offset)
     915                 :            : {
     916                 :        454 :         return spdk_pci_device_cfg_write(dev, &value, 4, offset);
     917                 :            : }
     918                 :            : 
     919                 :            : int
     920                 :          0 : spdk_pci_device_get_serial_number(struct spdk_pci_device *dev, char *sn, size_t len)
     921                 :            : {
     922                 :            :         int err;
     923                 :          0 :         uint32_t pos, header = 0;
     924                 :          0 :         uint32_t i, buf[2];
     925                 :            : 
     926         [ #  # ]:          0 :         if (len < 17) {
     927                 :          0 :                 return -1;
     928                 :            :         }
     929                 :            : 
     930                 :          0 :         err = spdk_pci_device_cfg_read32(dev, &header, PCI_CFG_SIZE);
     931   [ #  #  #  # ]:          0 :         if (err || !header) {
     932                 :          0 :                 return -1;
     933                 :            :         }
     934                 :            : 
     935                 :          0 :         pos = PCI_CFG_SIZE;
     936                 :            :         while (1) {
     937         [ #  # ]:          0 :                 if ((header & 0x0000ffff) == PCI_EXT_CAP_ID_SN) {
     938         [ #  # ]:          0 :                         if (pos) {
     939                 :            :                                 /* skip the header */
     940                 :          0 :                                 pos += 4;
     941         [ #  # ]:          0 :                                 for (i = 0; i < 2; i++) {
     942                 :          0 :                                         err = spdk_pci_device_cfg_read32(dev, &buf[i], pos + 4 * i);
     943         [ #  # ]:          0 :                                         if (err) {
     944                 :          0 :                                                 return -1;
     945                 :            :                                         }
     946                 :            :                                 }
     947         [ #  # ]:          0 :                                 snprintf(sn, len, "%08x%08x", buf[1], buf[0]);
     948                 :          0 :                                 return 0;
     949                 :            :                         }
     950                 :            :                 }
     951                 :          0 :                 pos = (header >> 20) & 0xffc;
     952                 :            :                 /* 0 if no other items exist */
     953         [ #  # ]:          0 :                 if (pos < PCI_CFG_SIZE) {
     954                 :          0 :                         return -1;
     955                 :            :                 }
     956                 :          0 :                 err = spdk_pci_device_cfg_read32(dev, &header, pos);
     957         [ #  # ]:          0 :                 if (err) {
     958                 :          0 :                         return -1;
     959                 :            :                 }
     960                 :            :         }
     961                 :            :         return -1;
     962                 :            : }
     963                 :            : 
     964                 :            : struct spdk_pci_addr
     965                 :       1304 : spdk_pci_device_get_addr(struct spdk_pci_device *dev)
     966                 :            : {
     967                 :       1304 :         return dev->addr;
     968                 :            : }
     969                 :            : 
     970                 :            : bool
     971                 :     114621 : spdk_pci_device_is_removed(struct spdk_pci_device *dev)
     972                 :            : {
     973         [ -  + ]:     114621 :         return dev->internal.pending_removal;
     974                 :            : }
     975                 :            : 
     976                 :            : int
     977                 :       2526 : spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2)
     978                 :            : {
     979         [ -  + ]:       2526 :         if (a1->domain > a2->domain) {
     980                 :          0 :                 return 1;
     981         [ -  + ]:       2526 :         } else if (a1->domain < a2->domain) {
     982                 :          0 :                 return -1;
     983         [ -  + ]:       2526 :         } else if (a1->bus > a2->bus) {
     984                 :          0 :                 return 1;
     985         [ -  + ]:       2526 :         } else if (a1->bus < a2->bus) {
     986                 :          0 :                 return -1;
     987         [ +  + ]:       2526 :         } else if (a1->dev > a2->dev) {
     988                 :        280 :                 return 1;
     989         [ +  + ]:       2246 :         } else if (a1->dev < a2->dev) {
     990                 :        787 :                 return -1;
     991         [ -  + ]:       1459 :         } else if (a1->func > a2->func) {
     992                 :          0 :                 return 1;
     993         [ -  + ]:       1459 :         } else if (a1->func < a2->func) {
     994                 :          0 :                 return -1;
     995                 :            :         }
     996                 :            : 
     997                 :       1459 :         return 0;
     998                 :            : }
     999                 :            : 
    1000                 :            : #ifdef __linux__
    1001                 :            : int
    1002                 :       1086 : spdk_pci_device_claim(struct spdk_pci_device *dev)
    1003                 :            : {
    1004                 :            :         int dev_fd;
    1005                 :        364 :         char dev_name[64];
    1006                 :            :         int pid;
    1007                 :            :         void *dev_map;
    1008                 :       1086 :         struct flock pcidev_lock = {
    1009                 :            :                 .l_type = F_WRLCK,
    1010                 :            :                 .l_whence = SEEK_SET,
    1011                 :            :                 .l_start = 0,
    1012                 :            :                 .l_len = 0,
    1013                 :            :         };
    1014                 :            : 
    1015                 :       1086 :         snprintf(dev_name, sizeof(dev_name), "/var/tmp/spdk_pci_lock_%04x:%02x:%02x.%x",
    1016                 :       1086 :                  dev->addr.domain, dev->addr.bus, dev->addr.dev, dev->addr.func);
    1017                 :            : 
    1018                 :       1086 :         dev_fd = open(dev_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    1019         [ -  + ]:       1086 :         if (dev_fd == -1) {
    1020                 :          0 :                 SPDK_ERRLOG("could not open %s\n", dev_name);
    1021                 :          0 :                 return -errno;
    1022                 :            :         }
    1023                 :            : 
    1024         [ -  + ]:       1086 :         if (ftruncate(dev_fd, sizeof(int)) != 0) {
    1025                 :          0 :                 SPDK_ERRLOG("could not truncate %s\n", dev_name);
    1026                 :          0 :                 close(dev_fd);
    1027                 :          0 :                 return -errno;
    1028                 :            :         }
    1029                 :            : 
    1030                 :       1086 :         dev_map = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
    1031                 :            :                        MAP_SHARED, dev_fd, 0);
    1032         [ -  + ]:       1086 :         if (dev_map == MAP_FAILED) {
    1033                 :          0 :                 SPDK_ERRLOG("could not mmap dev %s (%d)\n", dev_name, errno);
    1034                 :          0 :                 close(dev_fd);
    1035                 :          0 :                 return -errno;
    1036                 :            :         }
    1037                 :            : 
    1038         [ +  + ]:       1086 :         if (fcntl(dev_fd, F_SETLK, &pcidev_lock) != 0) {
    1039                 :         19 :                 pid = *(int *)dev_map;
    1040                 :         19 :                 SPDK_ERRLOG("Cannot create lock on device %s, probably"
    1041                 :            :                             " process %d has claimed it\n", dev_name, pid);
    1042                 :         19 :                 munmap(dev_map, sizeof(int));
    1043                 :         19 :                 close(dev_fd);
    1044                 :            :                 /* F_SETLK returns unspecified errnos, normalize them */
    1045                 :         19 :                 return -EACCES;
    1046                 :            :         }
    1047                 :            : 
    1048                 :       1067 :         *(int *)dev_map = (int)getpid();
    1049                 :       1067 :         munmap(dev_map, sizeof(int));
    1050                 :       1067 :         dev->internal.claim_fd = dev_fd;
    1051                 :            :         /* Keep dev_fd open to maintain the lock. */
    1052                 :       1067 :         return 0;
    1053                 :            : }
    1054                 :            : 
    1055                 :            : void
    1056                 :       1063 : spdk_pci_device_unclaim(struct spdk_pci_device *dev)
    1057                 :            : {
    1058                 :        356 :         char dev_name[64];
    1059                 :            : 
    1060         [ -  + ]:       1063 :         snprintf(dev_name, sizeof(dev_name), "/var/tmp/spdk_pci_lock_%04x:%02x:%02x.%x",
    1061                 :       1063 :                  dev->addr.domain, dev->addr.bus, dev->addr.dev, dev->addr.func);
    1062                 :            : 
    1063                 :       1063 :         close(dev->internal.claim_fd);
    1064                 :       1063 :         dev->internal.claim_fd = -1;
    1065         [ -  + ]:       1063 :         unlink(dev_name);
    1066                 :       1063 : }
    1067                 :            : #else /* !__linux__ */
    1068                 :            : int
    1069                 :            : spdk_pci_device_claim(struct spdk_pci_device *dev)
    1070                 :            : {
    1071                 :            :         /* TODO */
    1072                 :            :         return 0;
    1073                 :            : }
    1074                 :            : 
    1075                 :            : void
    1076                 :            : spdk_pci_device_unclaim(struct spdk_pci_device *dev)
    1077                 :            : {
    1078                 :            :         /* TODO */
    1079                 :            : }
    1080                 :            : #endif /* __linux__ */
    1081                 :            : 
    1082                 :            : int
    1083                 :       3110 : spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
    1084                 :            : {
    1085                 :       1980 :         unsigned domain, bus, dev, func;
    1086                 :            : 
    1087   [ +  -  -  + ]:       3110 :         if (addr == NULL || bdf == NULL) {
    1088                 :          0 :                 return -EINVAL;
    1089                 :            :         }
    1090                 :            : 
    1091   [ +  +  +  + ]:       3110 :         if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) ||
    1092   [ -  +  -  + ]:         10 :             (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) {
    1093                 :            :                 /* Matched a full address - all variables are initialized */
    1094   [ #  #  #  # ]:          0 :         } else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) {
    1095                 :          0 :                 func = 0;
    1096   [ #  #  #  # ]:          0 :         } else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) ||
    1097   [ #  #  #  # ]:          0 :                    (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) {
    1098                 :          0 :                 domain = 0;
    1099   [ #  #  #  # ]:          0 :         } else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) ||
    1100   [ #  #  #  # ]:          0 :                    (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) {
    1101                 :          0 :                 domain = 0;
    1102                 :          0 :                 func = 0;
    1103                 :            :         } else {
    1104                 :          0 :                 return -EINVAL;
    1105                 :            :         }
    1106                 :            : 
    1107   [ +  -  +  -  :       3110 :         if (bus > 0xFF || dev > 0x1F || func > 7) {
                   -  + ]
    1108                 :          0 :                 return -EINVAL;
    1109                 :            :         }
    1110                 :            : 
    1111                 :       3110 :         addr->domain = domain;
    1112                 :       3110 :         addr->bus = bus;
    1113                 :       3110 :         addr->dev = dev;
    1114                 :       3110 :         addr->func = func;
    1115                 :            : 
    1116                 :       3110 :         return 0;
    1117                 :            : }
    1118                 :            : 
    1119                 :            : int
    1120                 :       1579 : spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr)
    1121                 :            : {
    1122                 :            :         int rc;
    1123                 :            : 
    1124         [ -  + ]:        539 :         rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x",
    1125         [ -  + ]:       1579 :                       addr->domain, addr->bus,
    1126                 :       1579 :                       addr->dev, addr->func);
    1127                 :            : 
    1128   [ +  -  +  - ]:       1579 :         if (rc > 0 && (size_t)rc < sz) {
    1129                 :       1579 :                 return 0;
    1130                 :            :         }
    1131                 :            : 
    1132                 :          0 :         return -1;
    1133                 :            : }
    1134                 :            : 
    1135                 :            : int
    1136                 :         19 : spdk_pci_hook_device(struct spdk_pci_driver *drv, struct spdk_pci_device *dev)
    1137                 :            : {
    1138                 :            :         int rc;
    1139                 :            : 
    1140         [ -  + ]:         19 :         assert(dev->map_bar != NULL);
    1141         [ -  + ]:         19 :         assert(dev->unmap_bar != NULL);
    1142         [ -  + ]:         19 :         assert(dev->cfg_read != NULL);
    1143         [ -  + ]:         19 :         assert(dev->cfg_write != NULL);
    1144                 :         19 :         dev->internal.driver = drv;
    1145                 :            : 
    1146         [ -  + ]:         19 :         if (drv->cb_fn != NULL) {
    1147                 :          0 :                 rc = drv->cb_fn(drv->cb_arg, dev);
    1148         [ #  # ]:          0 :                 if (rc != 0) {
    1149                 :          0 :                         return -ECANCELED;
    1150                 :            :                 }
    1151                 :            : 
    1152                 :          0 :                 dev->internal.attached = true;
    1153                 :            :         }
    1154                 :            : 
    1155                 :         19 :         TAILQ_INSERT_TAIL(&g_pci_devices, dev, internal.tailq);
    1156                 :            : 
    1157                 :         19 :         return 0;
    1158                 :            : }
    1159                 :            : 
    1160                 :            : void
    1161                 :         19 : spdk_pci_unhook_device(struct spdk_pci_device *dev)
    1162                 :            : {
    1163   [ -  +  -  + ]:         19 :         assert(!dev->internal.attached);
    1164         [ -  + ]:         19 :         TAILQ_REMOVE(&g_pci_devices, dev, internal.tailq);
    1165                 :         19 : }
    1166                 :            : 
    1167                 :            : void
    1168                 :       5754 : spdk_pci_register_device_provider(struct spdk_pci_device_provider *provider)
    1169                 :            : {
    1170                 :       5754 :         TAILQ_INSERT_TAIL(&g_pci_device_providers, provider, tailq);
    1171                 :       5754 : }
    1172                 :            : 
    1173                 :            : const char *
    1174                 :          0 : spdk_pci_device_get_type(const struct spdk_pci_device *dev)
    1175                 :            : {
    1176                 :          0 :         return dev->type;
    1177                 :            : }
    1178                 :            : 
    1179                 :            : int
    1180                 :         70 : spdk_pci_device_allow(struct spdk_pci_addr *pci_addr)
    1181                 :            : {
    1182                 :         35 :         struct rte_devargs *da;
    1183                 :         35 :         char devargs_str[128];
    1184                 :            : 
    1185                 :         70 :         da = calloc(1, sizeof(*da));
    1186         [ -  + ]:         70 :         if (da == NULL) {
    1187                 :          0 :                 SPDK_ERRLOG("could not allocate rte_devargs\n");
    1188                 :          0 :                 return -ENOMEM;
    1189                 :            :         }
    1190                 :            : 
    1191         [ -  + ]:         70 :         snprintf(devargs_str, sizeof(devargs_str), "pci:%04x:%02x:%02x.%x",
    1192                 :         70 :                  pci_addr->domain, pci_addr->bus, pci_addr->dev, pci_addr->func);
    1193         [ -  + ]:         70 :         if (rte_devargs_parse(da, devargs_str) != 0) {
    1194                 :          0 :                 SPDK_ERRLOG("rte_devargs_parse() failed on '%s'\n", devargs_str);
    1195                 :          0 :                 free(da);
    1196                 :          0 :                 return -EINVAL;
    1197                 :            :         }
    1198                 :         70 :         da->policy = RTE_DEV_ALLOWED;
    1199                 :            :         /* Note: if a devargs already exists for this device address, it just gets
    1200                 :            :          * overridden.  So we do not need to check if the devargs already exists.
    1201                 :            :          * DPDK will take care of memory management for the devargs structure after
    1202                 :            :          * it has been inserted, so there's nothing SPDK needs to track.
    1203                 :            :          */
    1204         [ -  + ]:         70 :         if (rte_devargs_insert(&da) != 0) {
    1205                 :          0 :                 SPDK_ERRLOG("rte_devargs_insert() failed on '%s'\n", devargs_str);
    1206                 :          0 :                 free(da);
    1207                 :          0 :                 return -EINVAL;
    1208                 :            :         }
    1209                 :            : 
    1210                 :         70 :         return 0;
    1211                 :            : }

Generated by: LCOV version 1.14