LCOV - code coverage report
Current view: top level - drivers/bus/vdev - vdev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 164 225 72.9 %
Date: 2026-07-01 18:02:41 Functions: 18 23 78.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 89 156 57.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2016 RehiveTech. All rights reserved.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <string.h>
       6                 :            : #include <inttypes.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <stdlib.h>
       9                 :            : #include <stdint.h>
      10                 :            : #include <stdbool.h>
      11                 :            : #include <sys/queue.h>
      12                 :            : 
      13                 :            : #include <rte_os_shim.h>
      14                 :            : #include <eal_export.h>
      15                 :            : #include <rte_eal.h>
      16                 :            : #include <dev_driver.h>
      17                 :            : #include <bus_driver.h>
      18                 :            : #include <rte_common.h>
      19                 :            : #include <rte_devargs.h>
      20                 :            : #include <rte_log.h>
      21                 :            : #include <rte_memory.h>
      22                 :            : #include <rte_tailq.h>
      23                 :            : #include <rte_spinlock.h>
      24                 :            : #include <rte_string_fns.h>
      25                 :            : #include <rte_errno.h>
      26                 :            : 
      27                 :            : #include "bus_vdev_driver.h"
      28                 :            : 
      29                 :            : #define VDEV_MP_KEY     "bus_vdev_mp"
      30                 :            : 
      31                 :            : int vdev_logtype_bus;
      32                 :            : #define RTE_LOGTYPE_VDEV_BUS vdev_logtype_bus
      33                 :            : 
      34                 :            : #define VDEV_LOG(level, ...) \
      35                 :            :         RTE_LOG_LINE_PREFIX(level, VDEV_BUS, "%s(): ", __func__, __VA_ARGS__)
      36                 :            : 
      37                 :            : /* Forward declare to access virtual bus name */
      38                 :            : static struct rte_bus rte_vdev_bus;
      39                 :            : 
      40                 :            : /* The lock needs to be recursive because a vdev can manage another vdev. */
      41                 :            : static rte_spinlock_recursive_t vdev_device_list_lock =
      42                 :            :         RTE_SPINLOCK_RECURSIVE_INITIALIZER;
      43                 :            : 
      44                 :            : struct vdev_custom_scan {
      45                 :            :         TAILQ_ENTRY(vdev_custom_scan) next;
      46                 :            :         rte_vdev_scan_callback callback;
      47                 :            :         void *user_arg;
      48                 :            : };
      49                 :            : TAILQ_HEAD(vdev_custom_scans, vdev_custom_scan);
      50                 :            : static struct vdev_custom_scans vdev_custom_scans =
      51                 :            :         TAILQ_HEAD_INITIALIZER(vdev_custom_scans);
      52                 :            : static rte_spinlock_t vdev_custom_scan_lock = RTE_SPINLOCK_INITIALIZER;
      53                 :            : 
      54                 :            : /* register a driver */
      55                 :            : RTE_EXPORT_INTERNAL_SYMBOL(rte_vdev_register)
      56                 :            : void
      57                 :      12040 : rte_vdev_register(struct rte_vdev_driver *driver)
      58                 :            : {
      59                 :      12040 :         rte_bus_add_driver(&rte_vdev_bus, &driver->driver);
      60                 :      12040 : }
      61                 :            : 
      62                 :            : /* unregister a driver */
      63                 :            : RTE_EXPORT_INTERNAL_SYMBOL(rte_vdev_unregister)
      64                 :            : void
      65                 :          0 : rte_vdev_unregister(struct rte_vdev_driver *driver)
      66                 :            : {
      67                 :          0 :         rte_bus_remove_driver(&rte_vdev_bus, &driver->driver);
      68                 :          0 : }
      69                 :            : 
      70                 :            : RTE_EXPORT_SYMBOL(rte_vdev_add_custom_scan)
      71                 :            : int
      72                 :          0 : rte_vdev_add_custom_scan(rte_vdev_scan_callback callback, void *user_arg)
      73                 :            : {
      74                 :            :         struct vdev_custom_scan *custom_scan;
      75                 :            : 
      76                 :            :         rte_spinlock_lock(&vdev_custom_scan_lock);
      77                 :            : 
      78                 :            :         /* check if already registered */
      79         [ #  # ]:          0 :         TAILQ_FOREACH(custom_scan, &vdev_custom_scans, next) {
      80         [ #  # ]:          0 :                 if (custom_scan->callback == callback &&
      81         [ #  # ]:          0 :                                 custom_scan->user_arg == user_arg)
      82                 :            :                         break;
      83                 :            :         }
      84                 :            : 
      85         [ #  # ]:          0 :         if (custom_scan == NULL) {
      86                 :          0 :                 custom_scan = malloc(sizeof(struct vdev_custom_scan));
      87         [ #  # ]:          0 :                 if (custom_scan != NULL) {
      88                 :          0 :                         custom_scan->callback = callback;
      89                 :          0 :                         custom_scan->user_arg = user_arg;
      90                 :          0 :                         TAILQ_INSERT_TAIL(&vdev_custom_scans, custom_scan, next);
      91                 :            :                 }
      92                 :            :         }
      93                 :            : 
      94                 :            :         rte_spinlock_unlock(&vdev_custom_scan_lock);
      95                 :            : 
      96         [ #  # ]:          0 :         return (custom_scan == NULL) ? -1 : 0;
      97                 :            : }
      98                 :            : 
      99                 :            : RTE_EXPORT_SYMBOL(rte_vdev_remove_custom_scan)
     100                 :            : int
     101                 :          0 : rte_vdev_remove_custom_scan(rte_vdev_scan_callback callback, void *user_arg)
     102                 :            : {
     103                 :            :         struct vdev_custom_scan *custom_scan, *tmp_scan;
     104                 :            : 
     105                 :            :         rte_spinlock_lock(&vdev_custom_scan_lock);
     106         [ #  # ]:          0 :         RTE_TAILQ_FOREACH_SAFE(custom_scan, &vdev_custom_scans, next,
     107                 :            :                                 tmp_scan) {
     108         [ #  # ]:          0 :                 if (custom_scan->callback != callback ||
     109   [ #  #  #  # ]:          0 :                                 (custom_scan->user_arg != (void *)-1 &&
     110                 :            :                                 custom_scan->user_arg != user_arg))
     111                 :          0 :                         continue;
     112         [ #  # ]:          0 :                 TAILQ_REMOVE(&vdev_custom_scans, custom_scan, next);
     113                 :          0 :                 free(custom_scan);
     114                 :            :         }
     115                 :            :         rte_spinlock_unlock(&vdev_custom_scan_lock);
     116                 :            : 
     117                 :          0 :         return 0;
     118                 :            : }
     119                 :            : 
     120                 :            : static int
     121                 :         41 : vdev_parse(const char *name, void *addr)
     122                 :            : {
     123                 :            :         struct rte_vdev_driver **out = addr;
     124                 :            :         struct rte_vdev_driver *driver = NULL;
     125                 :            : 
     126         [ +  + ]:       1039 :         RTE_BUS_FOREACH_DRV(driver, &rte_vdev_bus) {
     127         [ +  + ]:       1024 :                 if (strncmp(driver->driver.name, name,
     128                 :            :                             strlen(driver->driver.name)) == 0)
     129                 :            :                         break;
     130         [ +  + ]:        998 :                 if (driver->driver.alias &&
     131         [ +  - ]:        357 :                     strncmp(driver->driver.alias, name,
     132                 :            :                             strlen(driver->driver.alias)) == 0)
     133                 :            :                         break;
     134                 :            :         }
     135                 :         41 :         if (driver != NULL &&
     136         [ +  + ]:         41 :             addr != NULL)
     137                 :         10 :                 *out = driver;
     138                 :         41 :         return driver == NULL;
     139                 :            : }
     140                 :            : 
     141                 :            : static int
     142                 :          0 : vdev_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
     143                 :            : {
     144                 :            :         struct rte_vdev_device *vdev = RTE_BUS_DEVICE(dev, *vdev);
     145                 :          0 :         const struct rte_vdev_driver *driver = RTE_BUS_DRIVER(vdev->device.driver, *driver);
     146                 :            : 
     147         [ #  # ]:          0 :         if (driver->dma_map != NULL)
     148                 :          0 :                 return driver->dma_map(vdev, addr, iova, len);
     149                 :            : 
     150                 :            :         return 0;
     151                 :            : }
     152                 :            : 
     153                 :            : static int
     154                 :          0 : vdev_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
     155                 :            : {
     156                 :            :         struct rte_vdev_device *vdev = RTE_BUS_DEVICE(dev, *vdev);
     157                 :          0 :         const struct rte_vdev_driver *driver = RTE_BUS_DRIVER(vdev->device.driver, *driver);
     158                 :            : 
     159         [ #  # ]:          0 :         if (driver->dma_unmap != NULL)
     160                 :          0 :                 return driver->dma_unmap(vdev, addr, iova, len);
     161                 :            : 
     162                 :            :         return 0;
     163                 :            : }
     164                 :            : 
     165                 :            : /*
     166                 :            :  * Check if a vdev driver matches a vdev device by name.
     167                 :            :  */
     168                 :            : static bool
     169                 :        913 : vdev_bus_match(const struct rte_driver *drv, const struct rte_device *dev)
     170                 :            : {
     171                 :        913 :         const char *name = dev->name;
     172                 :            : 
     173                 :            :         /* Check driver name match */
     174         [ +  + ]:        913 :         if (strncmp(drv->name, name, strlen(drv->name)) == 0)
     175                 :            :                 return true;
     176                 :            : 
     177                 :            :         /* Check driver alias match */
     178   [ +  +  +  + ]:        844 :         if (drv->alias && strncmp(drv->alias, name, strlen(drv->alias)) == 0)
     179                 :          2 :                 return true;
     180                 :            : 
     181                 :            :         return false;
     182                 :            : }
     183                 :            : 
     184                 :            : static int
     185         [ +  - ]:         71 : vdev_probe_device(struct rte_driver *drv, struct rte_device *dev)
     186                 :            : {
     187                 :            :         struct rte_vdev_device *vdev_dev = RTE_BUS_DEVICE(dev, *vdev_dev);
     188                 :            :         struct rte_vdev_driver *vdev_drv = RTE_BUS_DRIVER(drv, *vdev_drv);
     189                 :            :         const char *name;
     190                 :            :         enum rte_iova_mode iova_mode;
     191                 :            : 
     192                 :            :         name = rte_vdev_device_name(vdev_dev);
     193                 :         71 :         VDEV_LOG(DEBUG, "Search driver to probe device %s", name);
     194                 :            : 
     195                 :         71 :         iova_mode = rte_eal_iova_mode();
     196   [ +  +  -  + ]:         71 :         if ((vdev_drv->drv_flags & RTE_VDEV_DRV_NEED_IOVA_AS_VA) && (iova_mode == RTE_IOVA_PA)) {
     197                 :          0 :                 VDEV_LOG(ERR, "%s requires VA IOVA mode but current mode is PA, not initializing",
     198                 :            :                                 name);
     199                 :          0 :                 return -1;
     200                 :            :         }
     201                 :            : 
     202                 :         71 :         return vdev_drv->probe(vdev_dev);
     203                 :            : }
     204                 :            : 
     205                 :            : /* The caller shall be responsible for thread-safe */
     206                 :            : static struct rte_vdev_device *
     207                 :        127 : find_vdev(const char *name)
     208                 :            : {
     209                 :            :         struct rte_vdev_device *dev;
     210                 :            : 
     211         [ +  - ]:        127 :         if (!name)
     212                 :            :                 return NULL;
     213                 :            : 
     214   [ +  +  +  - ]:        182 :         RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
     215                 :            :                 const char *devname = rte_vdev_device_name(dev);
     216                 :            : 
     217         [ +  + ]:        109 :                 if (!strcmp(devname, name))
     218                 :         54 :                         return dev;
     219                 :            :         }
     220                 :            : 
     221                 :            :         return NULL;
     222                 :            : }
     223                 :            : 
     224                 :            : static struct rte_devargs *
     225                 :         60 : alloc_devargs(const char *name, const char *args)
     226                 :            : {
     227                 :            :         struct rte_devargs *devargs;
     228                 :            :         int ret;
     229                 :            : 
     230                 :         60 :         devargs = calloc(1, sizeof(*devargs));
     231         [ +  - ]:         60 :         if (!devargs)
     232                 :            :                 return NULL;
     233                 :            : 
     234                 :         60 :         devargs->bus = &rte_vdev_bus;
     235         [ +  + ]:         60 :         if (args)
     236                 :         54 :                 devargs->data = strdup(args);
     237                 :            :         else
     238                 :          6 :                 devargs->data = strdup("");
     239         [ -  + ]:         60 :         if (devargs->data == NULL) {
     240                 :          0 :                 free(devargs);
     241                 :          0 :                 return NULL;
     242                 :            :         }
     243                 :         60 :         devargs->args = devargs->data;
     244                 :            : 
     245         [ -  + ]:         60 :         ret = strlcpy(devargs->name, name, sizeof(devargs->name));
     246         [ -  + ]:         60 :         if (ret < 0 || ret >= (int)sizeof(devargs->name)) {
     247                 :          0 :                 rte_devargs_reset(devargs);
     248                 :          0 :                 free(devargs);
     249                 :          0 :                 return NULL;
     250                 :            :         }
     251                 :            : 
     252                 :            :         return devargs;
     253                 :            : }
     254                 :            : 
     255                 :            : static int
     256                 :         60 : insert_vdev(const char *name, const char *args,
     257                 :            :                 struct rte_vdev_device **p_dev,
     258                 :            :                 bool init)
     259                 :            : {
     260                 :            :         struct rte_vdev_device *dev;
     261                 :            :         struct rte_devargs *devargs;
     262                 :            :         int ret;
     263                 :            : 
     264         [ +  - ]:         60 :         if (name == NULL)
     265                 :            :                 return -EINVAL;
     266                 :            : 
     267                 :         60 :         devargs = alloc_devargs(name, args);
     268                 :            : 
     269         [ +  - ]:         60 :         if (!devargs)
     270                 :            :                 return -ENOMEM;
     271                 :            : 
     272                 :         60 :         dev = calloc(1, sizeof(*dev));
     273         [ -  + ]:         60 :         if (!dev) {
     274                 :            :                 ret = -ENOMEM;
     275                 :          0 :                 goto fail;
     276                 :            :         }
     277                 :            : 
     278                 :         60 :         dev->device.numa_node = SOCKET_ID_ANY;
     279                 :            : 
     280         [ -  + ]:         60 :         if (find_vdev(name)) {
     281                 :            :                 /*
     282                 :            :                  * A vdev is expected to have only one port.
     283                 :            :                  * So there is no reason to try probing again,
     284                 :            :                  * even with new arguments.
     285                 :            :                  */
     286                 :            :                 ret = -EEXIST;
     287                 :          0 :                 goto fail;
     288                 :            :         }
     289                 :            : 
     290         [ +  + ]:         60 :         if (init)
     291                 :         59 :                 rte_devargs_insert(&devargs);
     292                 :         60 :         dev->device.devargs = devargs;
     293                 :         60 :         dev->device.name = devargs->name;
     294                 :         60 :         rte_bus_add_device(&rte_vdev_bus, &dev->device);
     295                 :            : 
     296         [ +  + ]:         60 :         if (p_dev)
     297                 :         59 :                 *p_dev = dev;
     298                 :            : 
     299                 :            :         return 0;
     300                 :          0 : fail:
     301                 :          0 :         rte_devargs_reset(devargs);
     302                 :          0 :         free(devargs);
     303                 :          0 :         free(dev);
     304                 :          0 :         return ret;
     305                 :            : }
     306                 :            : 
     307                 :            : RTE_EXPORT_SYMBOL(rte_vdev_init)
     308                 :            : int
     309                 :         59 : rte_vdev_init(const char *name, const char *args)
     310                 :            : {
     311                 :            :         struct rte_vdev_device *dev;
     312                 :            :         int ret;
     313                 :            : 
     314                 :         59 :         rte_spinlock_recursive_lock(&vdev_device_list_lock);
     315                 :         59 :         ret = insert_vdev(name, args, &dev, true);
     316         [ +  - ]:         59 :         if (ret == 0) {
     317                 :            :                 struct rte_driver *drv = NULL;
     318                 :            : 
     319                 :         59 : next_driver:
     320                 :         59 :                 drv = rte_bus_find_driver(&rte_vdev_bus, drv, &dev->device);
     321         [ -  + ]:         59 :                 if (drv == NULL) {
     322                 :          0 :                         VDEV_LOG(ERR, "no driver found for %s", name);
     323                 :            :                         ret = -1;
     324         [ +  - ]:         59 :                 } else if (rte_dev_is_probed(&dev->device)) {
     325                 :            :                         ret = -EEXIST;
     326                 :            :                 } else {
     327                 :         59 :                         dev->device.driver = drv;
     328                 :         59 :                         ret = rte_vdev_bus.probe_device(drv, &dev->device);
     329         [ +  + ]:         59 :                         if (ret != 0)
     330                 :          4 :                                 dev->device.driver = NULL;
     331                 :            :                 }
     332         [ +  + ]:         59 :                 if (ret < 0) {
     333                 :            :                         /* If fails, remove it from vdev list */
     334                 :          4 :                         rte_bus_remove_device(&rte_vdev_bus, &dev->device);
     335                 :          4 :                         rte_devargs_remove(dev->device.devargs);
     336                 :          4 :                         free(dev);
     337         [ -  + ]:         55 :                 } else if (ret > 0) {
     338                 :          0 :                         goto next_driver;
     339                 :            :                 }
     340                 :            :         }
     341                 :         59 :         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
     342                 :         59 :         return ret;
     343                 :            : }
     344                 :            : 
     345                 :            : static int
     346                 :         14 : vdev_unplug_device(struct rte_device *rte_dev)
     347                 :            : {
     348                 :         67 :         const struct rte_vdev_driver *driver = RTE_BUS_DRIVER(rte_dev->driver, *driver);
     349                 :            :         struct rte_vdev_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
     350                 :            : 
     351   [ +  -  +  - ]:         67 :         if (driver->remove)
     352                 :         67 :                 return driver->remove(dev);
     353                 :            : 
     354                 :            :         return 0;
     355                 :            : }
     356                 :            : 
     357                 :            : RTE_EXPORT_SYMBOL(rte_vdev_uninit)
     358                 :            : int
     359                 :         54 : rte_vdev_uninit(const char *name)
     360                 :            : {
     361                 :            :         struct rte_vdev_device *dev;
     362                 :            :         int ret;
     363                 :            : 
     364         [ +  - ]:         54 :         if (name == NULL)
     365                 :            :                 return -EINVAL;
     366                 :            : 
     367                 :         54 :         rte_spinlock_recursive_lock(&vdev_device_list_lock);
     368                 :            : 
     369                 :         54 :         dev = find_vdev(name);
     370         [ +  + ]:         54 :         if (!dev) {
     371                 :            :                 ret = -ENOENT;
     372                 :          1 :                 goto unlock;
     373                 :            :         }
     374                 :            : 
     375         [ +  - ]:         53 :         if (rte_dev_is_probed(&dev->device)) {
     376                 :            :                 ret = vdev_unplug_device(&dev->device);
     377                 :            :         } else {
     378                 :          0 :                 VDEV_LOG(DEBUG, "no driver attach to device %s", name);
     379                 :            :                 ret = 1;
     380                 :            :         }
     381         [ -  + ]:         53 :         if (ret)
     382                 :          0 :                 goto unlock;
     383                 :            : 
     384                 :         53 :         rte_bus_remove_device(&rte_vdev_bus, &dev->device);
     385                 :         53 :         rte_devargs_remove(dev->device.devargs);
     386                 :         53 :         free(dev);
     387                 :            : 
     388                 :         54 : unlock:
     389                 :         54 :         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
     390                 :         54 :         return ret;
     391                 :            : }
     392                 :            : 
     393                 :            : struct vdev_param {
     394                 :            : #define VDEV_SCAN_REQ   1
     395                 :            : #define VDEV_SCAN_ONE   2
     396                 :            : #define VDEV_SCAN_REP   3
     397                 :            :         int type;
     398                 :            :         int num;
     399                 :            :         char name[RTE_DEV_NAME_MAX_LEN];
     400                 :            : };
     401                 :            : 
     402                 :            : /**
     403                 :            :  * This function works as the action for both primary and secondary process
     404                 :            :  * for static vdev discovery when a secondary process is booting.
     405                 :            :  *
     406                 :            :  * step 1, secondary process sends a sync request to ask for vdev in primary;
     407                 :            :  * step 2, primary process receives the request, and send vdevs one by one;
     408                 :            :  * step 3, primary process sends back reply, which indicates how many vdevs
     409                 :            :  * are sent.
     410                 :            :  */
     411                 :            : static int
     412      [ +  +  - ]:         32 : vdev_action(const struct rte_mp_msg *mp_msg, const void *peer)
     413                 :            : {
     414                 :            :         struct rte_vdev_device *dev;
     415                 :            :         struct rte_mp_msg mp_resp;
     416                 :            :         struct vdev_param *ou = (struct vdev_param *)&mp_resp.param;
     417                 :            :         const struct vdev_param *in = (const struct vdev_param *)mp_msg->param;
     418                 :            :         const char *devname;
     419                 :            :         int num;
     420                 :            :         int ret;
     421                 :            : 
     422                 :            :         strlcpy(mp_resp.name, VDEV_MP_KEY, sizeof(mp_resp.name));
     423                 :         32 :         mp_resp.len_param = sizeof(*ou);
     424                 :         32 :         mp_resp.num_fds = 0;
     425                 :            : 
     426      [ +  +  - ]:         32 :         switch (in->type) {
     427                 :         31 :         case VDEV_SCAN_REQ:
     428                 :         31 :                 ou->type = VDEV_SCAN_ONE;
     429                 :         31 :                 ou->num = 1;
     430                 :            :                 num = 0;
     431                 :            : 
     432                 :         31 :                 rte_spinlock_recursive_lock(&vdev_device_list_lock);
     433   [ +  +  +  - ]:         32 :                 RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
     434                 :            :                         devname = rte_vdev_device_name(dev);
     435         [ -  + ]:          1 :                         if (strlen(devname) == 0) {
     436                 :          0 :                                 VDEV_LOG(INFO, "vdev with no name is not sent");
     437                 :          0 :                                 continue;
     438                 :            :                         }
     439                 :          1 :                         VDEV_LOG(INFO, "send vdev, %s", devname);
     440                 :            :                         strlcpy(ou->name, devname, RTE_DEV_NAME_MAX_LEN);
     441         [ -  + ]:          1 :                         if (rte_mp_sendmsg(&mp_resp) < 0)
     442                 :          0 :                                 VDEV_LOG(ERR, "send vdev, %s, failed, %s",
     443                 :            :                                          devname, strerror(rte_errno));
     444                 :          1 :                         num++;
     445                 :            :                 }
     446                 :         31 :                 rte_spinlock_recursive_unlock(&vdev_device_list_lock);
     447                 :            : 
     448                 :         31 :                 ou->type = VDEV_SCAN_REP;
     449                 :         31 :                 ou->num = num;
     450         [ -  + ]:         31 :                 if (rte_mp_reply(&mp_resp, peer) < 0)
     451                 :          0 :                         VDEV_LOG(ERR, "Failed to reply a scan request");
     452                 :            :                 break;
     453                 :          1 :         case VDEV_SCAN_ONE:
     454                 :          1 :                 VDEV_LOG(INFO, "receive vdev, %s", in->name);
     455                 :          1 :                 ret = insert_vdev(in->name, NULL, NULL, false);
     456         [ -  + ]:          1 :                 if (ret == -EEXIST)
     457                 :          0 :                         VDEV_LOG(DEBUG, "device already exist, %s", in->name);
     458         [ -  + ]:          1 :                 else if (ret < 0)
     459                 :          0 :                         VDEV_LOG(ERR, "failed to add vdev, %s", in->name);
     460                 :            :                 break;
     461                 :          0 :         default:
     462                 :          0 :                 VDEV_LOG(ERR, "vdev cannot recognize this message");
     463                 :            :         }
     464                 :            : 
     465                 :         32 :         return 0;
     466                 :            : }
     467                 :            : 
     468                 :            : static int
     469                 :        225 : vdev_scan(void)
     470                 :            : {
     471                 :            :         struct rte_vdev_device *dev;
     472                 :            :         struct rte_devargs *devargs;
     473                 :            :         struct vdev_custom_scan *custom_scan;
     474                 :            : 
     475         [ +  + ]:        225 :         if (rte_mp_action_register(VDEV_MP_KEY, vdev_action) < 0 &&
     476         [ +  - ]:         10 :             rte_errno != EEXIST) {
     477                 :            :                 /* for primary, unsupported IPC is not an error */
     478         [ +  - ]:         10 :                 if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
     479         [ +  - ]:         10 :                                 rte_errno == ENOTSUP)
     480                 :         10 :                         goto scan;
     481                 :          0 :                 VDEV_LOG(ERR, "Failed to add vdev mp action");
     482                 :          0 :                 return -1;
     483                 :            :         }
     484                 :            : 
     485         [ +  + ]:        215 :         if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
     486                 :            :                 struct rte_mp_msg mp_req, *mp_rep;
     487                 :            :                 struct rte_mp_reply mp_reply;
     488                 :         32 :                 struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
     489                 :            :                 struct vdev_param *req = (struct vdev_param *)mp_req.param;
     490                 :            :                 struct vdev_param *resp;
     491                 :            : 
     492                 :            :                 strlcpy(mp_req.name, VDEV_MP_KEY, sizeof(mp_req.name));
     493                 :         32 :                 mp_req.len_param = sizeof(*req);
     494                 :         32 :                 mp_req.num_fds = 0;
     495                 :         32 :                 req->type = VDEV_SCAN_REQ;
     496         [ +  + ]:         32 :                 if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
     497         [ +  - ]:         31 :                     mp_reply.nb_received == 1) {
     498                 :         31 :                         mp_rep = &mp_reply.msgs[0];
     499                 :            :                         resp = (struct vdev_param *)mp_rep->param;
     500                 :         31 :                         VDEV_LOG(INFO, "Received %d vdevs", resp->num);
     501                 :         31 :                         free(mp_reply.msgs);
     502                 :            :                 } else
     503                 :          1 :                         VDEV_LOG(ERR, "Failed to request vdev from primary");
     504                 :            : 
     505                 :            :                 /* Fall through to allow private vdevs in secondary process */
     506                 :            :         }
     507                 :            : 
     508                 :        225 : scan:
     509                 :            :         /* call custom scan callbacks if any */
     510                 :            :         rte_spinlock_lock(&vdev_custom_scan_lock);
     511         [ -  + ]:        225 :         TAILQ_FOREACH(custom_scan, &vdev_custom_scans, next) {
     512         [ #  # ]:          0 :                 if (custom_scan->callback != NULL)
     513                 :            :                         /*
     514                 :            :                          * the callback should update devargs list
     515                 :            :                          * by calling rte_devargs_insert() with
     516                 :            :                          *     devargs.bus = rte_bus_find_by_name("vdev");
     517                 :            :                          *     devargs.type = RTE_DEVTYPE_VIRTUAL;
     518                 :            :                          *     devargs.policy = RTE_DEV_ALLOWED;
     519                 :            :                          */
     520                 :          0 :                         custom_scan->callback(custom_scan->user_arg);
     521                 :            :         }
     522                 :            :         rte_spinlock_unlock(&vdev_custom_scan_lock);
     523                 :            : 
     524                 :            :         /* for virtual devices we scan the devargs_list populated via cmdline */
     525         [ +  + ]:        238 :         RTE_EAL_DEVARGS_FOREACH(rte_vdev_bus.name, devargs) {
     526                 :            : 
     527                 :         13 :                 dev = calloc(1, sizeof(*dev));
     528         [ +  - ]:         13 :                 if (!dev)
     529                 :            :                         return -1;
     530                 :            : 
     531                 :         13 :                 rte_spinlock_recursive_lock(&vdev_device_list_lock);
     532                 :            : 
     533         [ +  + ]:         13 :                 if (find_vdev(devargs->name)) {
     534                 :          1 :                         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
     535                 :          1 :                         free(dev);
     536                 :          1 :                         continue;
     537                 :            :                 }
     538                 :            : 
     539                 :         12 :                 dev->device.devargs = devargs;
     540                 :         12 :                 dev->device.numa_node = SOCKET_ID_ANY;
     541                 :         12 :                 dev->device.name = devargs->name;
     542                 :            : 
     543                 :         12 :                 rte_bus_add_device(&rte_vdev_bus, &dev->device);
     544                 :            : 
     545                 :         12 :                 rte_spinlock_recursive_unlock(&vdev_device_list_lock);
     546                 :            :         }
     547                 :            : 
     548                 :            :         return 0;
     549                 :            : }
     550                 :            : 
     551                 :            : static void
     552                 :         15 : vdev_free_device(struct rte_device *dev)
     553                 :            : {
     554                 :         15 :         free(RTE_BUS_DEVICE(dev, struct rte_vdev_device));
     555                 :         15 : }
     556                 :            : 
     557                 :            : static int
     558                 :        294 : vdev_cleanup(struct rte_bus *bus)
     559                 :            : {
     560                 :            :         int error;
     561                 :            : 
     562                 :        294 :         rte_spinlock_recursive_lock(&vdev_device_list_lock);
     563                 :        294 :         error = rte_bus_generic_cleanup(bus);
     564                 :        294 :         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
     565                 :            : 
     566                 :        294 :         return error;
     567                 :            : }
     568                 :            : 
     569                 :            : static struct rte_device *
     570                 :          7 : vdev_find_device(const struct rte_bus *bus, const struct rte_device *start,
     571                 :            :         rte_dev_cmp_t cmp, const void *data)
     572                 :            : {
     573                 :            :         struct rte_device *dev;
     574                 :            : 
     575                 :          7 :         rte_spinlock_recursive_lock(&vdev_device_list_lock);
     576                 :          7 :         dev = rte_bus_generic_find_device(bus, start, cmp, data);
     577                 :          7 :         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
     578                 :            : 
     579                 :          7 :         return dev;
     580                 :            : }
     581                 :            : 
     582                 :            : static enum rte_iova_mode
     583                 :        225 : vdev_get_iommu_class(void)
     584                 :            : {
     585                 :            :         const char *name;
     586                 :            :         struct rte_vdev_device *dev;
     587                 :            :         struct rte_vdev_driver *driver;
     588                 :            : 
     589   [ +  +  +  - ]:        234 :         RTE_BUS_FOREACH_DEV(dev, &rte_vdev_bus) {
     590                 :            :                 name = rte_vdev_device_name(dev);
     591         [ -  + ]:         10 :                 if (vdev_parse(name, &driver))
     592                 :          0 :                         continue;
     593                 :            : 
     594         [ +  + ]:         10 :                 if (driver->drv_flags & RTE_VDEV_DRV_NEED_IOVA_AS_VA)
     595                 :            :                         return RTE_IOVA_VA;
     596                 :            :         }
     597                 :            : 
     598                 :            :         return RTE_IOVA_DC;
     599                 :            : }
     600                 :            : 
     601                 :            : static struct rte_bus rte_vdev_bus = {
     602                 :            :         .scan = vdev_scan,
     603                 :            :         .probe = rte_bus_generic_probe,
     604                 :            :         .free_device = vdev_free_device,
     605                 :            :         .cleanup = vdev_cleanup,
     606                 :            :         .find_device = vdev_find_device,
     607                 :            :         .match = vdev_bus_match,
     608                 :            :         .probe_device = vdev_probe_device,
     609                 :            :         .unplug_device = vdev_unplug_device,
     610                 :            :         .parse = vdev_parse,
     611                 :            :         .dma_map = vdev_dma_map,
     612                 :            :         .dma_unmap = vdev_dma_unmap,
     613                 :            :         .get_iommu_class = vdev_get_iommu_class,
     614                 :            :         .dev_iterate = rte_bus_generic_dev_iterate,
     615                 :            : };
     616                 :            : 
     617                 :        301 : RTE_REGISTER_BUS(vdev, rte_vdev_bus);
     618         [ -  + ]:        301 : RTE_LOG_REGISTER_DEFAULT(vdev_logtype_bus, NOTICE);

Generated by: LCOV version 1.14