LCOV - code coverage report
Current view: top level - drivers/bus/vdev - vdev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 161 248 64.9 %
Date: 2024-12-01 18:57:19 Functions: 17 24 70.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 97 180 53.9 %

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

Generated by: LCOV version 1.14