LCOV - code coverage report
Current view: top level - drivers/vdpa/sfc - sfc_vdpa.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 2 136 1.5 %
Date: 2025-01-02 22:41:34 Functions: 2 11 18.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 64 1.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2020-2021 Xilinx, Inc.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdbool.h>
       6                 :            : #include <stdint.h>
       7                 :            : #include <pthread.h>
       8                 :            : #include <sys/queue.h>
       9                 :            : 
      10                 :            : #include <rte_common.h>
      11                 :            : #include <rte_devargs.h>
      12                 :            : #include <rte_errno.h>
      13                 :            : #include <rte_kvargs.h>
      14                 :            : #include <rte_string_fns.h>
      15                 :            : #include <rte_vfio.h>
      16                 :            : #include <rte_vhost.h>
      17                 :            : 
      18                 :            : #include "efx.h"
      19                 :            : #include "sfc_efx.h"
      20                 :            : #include "sfc_vdpa.h"
      21                 :            : 
      22                 :            : TAILQ_HEAD(sfc_vdpa_adapter_list_head, sfc_vdpa_adapter);
      23                 :            : static struct sfc_vdpa_adapter_list_head sfc_vdpa_adapter_list =
      24                 :            :         TAILQ_HEAD_INITIALIZER(sfc_vdpa_adapter_list);
      25                 :            : 
      26                 :            : static pthread_mutex_t sfc_vdpa_adapter_list_lock = PTHREAD_MUTEX_INITIALIZER;
      27                 :            : 
      28                 :            : struct sfc_vdpa_adapter *
      29                 :          0 : sfc_vdpa_get_adapter_by_dev(struct rte_pci_device *pdev)
      30                 :            : {
      31                 :            :         bool found = false;
      32                 :            :         struct sfc_vdpa_adapter *sva;
      33                 :            : 
      34                 :          0 :         pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
      35                 :            : 
      36         [ #  # ]:          0 :         TAILQ_FOREACH(sva, &sfc_vdpa_adapter_list, next) {
      37         [ #  # ]:          0 :                 if (pdev == sva->pdev) {
      38                 :            :                         found = true;
      39                 :            :                         break;
      40                 :            :                 }
      41                 :            :         }
      42                 :            : 
      43                 :          0 :         pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
      44                 :            : 
      45         [ #  # ]:          0 :         return found ? sva : NULL;
      46                 :            : }
      47                 :            : 
      48                 :            : struct sfc_vdpa_ops_data *
      49                 :          0 : sfc_vdpa_get_data_by_dev(struct rte_vdpa_device *vdpa_dev)
      50                 :            : {
      51                 :            :         bool found = false;
      52                 :            :         struct sfc_vdpa_adapter *sva;
      53                 :            : 
      54                 :          0 :         pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
      55                 :            : 
      56         [ #  # ]:          0 :         TAILQ_FOREACH(sva, &sfc_vdpa_adapter_list, next) {
      57         [ #  # ]:          0 :                 if (vdpa_dev == sva->ops_data->vdpa_dev) {
      58                 :            :                         found = true;
      59                 :            :                         break;
      60                 :            :                 }
      61                 :            :         }
      62                 :            : 
      63                 :          0 :         pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
      64                 :            : 
      65         [ #  # ]:          0 :         return found ? sva->ops_data : NULL;
      66                 :            : }
      67                 :            : 
      68                 :            : static int
      69                 :          0 : sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
      70                 :            : {
      71                 :          0 :         struct rte_pci_device *dev = sva->pdev;
      72                 :          0 :         char dev_name[RTE_DEV_NAME_MAX_LEN] = {0};
      73                 :            :         int rc;
      74                 :            : 
      75                 :          0 :         rte_pci_device_name(&dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
      76                 :            : 
      77                 :          0 :         sva->vfio_container_fd = rte_vfio_container_create();
      78         [ #  # ]:          0 :         if (sva->vfio_container_fd < 0)   {
      79                 :          0 :                 sfc_vdpa_err(sva, "failed to create VFIO container");
      80                 :          0 :                 goto fail_container_create;
      81                 :            :         }
      82                 :            : 
      83                 :          0 :         rc = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
      84                 :            :                                     &sva->iommu_group_num);
      85         [ #  # ]:          0 :         if (rc <= 0) {
      86                 :          0 :                 sfc_vdpa_err(sva, "failed to get IOMMU group for %s : %s",
      87                 :            :                              dev_name, rte_strerror(-rc));
      88                 :          0 :                 goto fail_get_group_num;
      89                 :            :         }
      90                 :            : 
      91                 :          0 :         sva->vfio_group_fd =
      92                 :          0 :                 rte_vfio_container_group_bind(sva->vfio_container_fd,
      93                 :            :                                               sva->iommu_group_num);
      94         [ #  # ]:          0 :         if (sva->vfio_group_fd < 0) {
      95                 :          0 :                 sfc_vdpa_err(sva,
      96                 :            :                              "failed to bind IOMMU group %d to container %d",
      97                 :            :                              sva->iommu_group_num, sva->vfio_container_fd);
      98                 :          0 :                 goto fail_group_bind;
      99                 :            :         }
     100                 :            : 
     101         [ #  # ]:          0 :         if (rte_pci_map_device(dev) != 0) {
     102                 :          0 :                 sfc_vdpa_err(sva, "failed to map PCI device %s : %s",
     103                 :            :                              dev_name, rte_strerror(rte_errno));
     104                 :          0 :                 goto fail_pci_map_device;
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         sva->vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
     108                 :            : 
     109                 :          0 :         return 0;
     110                 :            : 
     111                 :            : fail_pci_map_device:
     112         [ #  # ]:          0 :         if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
     113                 :            :                                         sva->iommu_group_num) != 0) {
     114                 :          0 :                 sfc_vdpa_err(sva,
     115                 :            :                              "failed to unbind IOMMU group %d from container %d",
     116                 :            :                              sva->iommu_group_num, sva->vfio_container_fd);
     117                 :            :         }
     118                 :            : 
     119                 :          0 : fail_group_bind:
     120                 :          0 : fail_get_group_num:
     121         [ #  # ]:          0 :         if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
     122                 :          0 :                 sfc_vdpa_err(sva, "failed to destroy container %d",
     123                 :            :                              sva->vfio_container_fd);
     124                 :            :         }
     125                 :            : 
     126                 :          0 : fail_container_create:
     127                 :            :         return -1;
     128                 :            : }
     129                 :            : 
     130                 :            : static void
     131                 :          0 : sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter *sva)
     132                 :            : {
     133                 :          0 :         rte_pci_unmap_device(sva->pdev);
     134                 :            : 
     135         [ #  # ]:          0 :         if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
     136                 :            :                                             sva->iommu_group_num) != 0) {
     137                 :          0 :                 sfc_vdpa_err(sva,
     138                 :            :                              "failed to unbind IOMMU group %d from container %d",
     139                 :            :                              sva->iommu_group_num, sva->vfio_container_fd);
     140                 :            :         }
     141                 :            : 
     142         [ #  # ]:          0 :         if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
     143                 :          0 :                 sfc_vdpa_err(sva,
     144                 :            :                              "failed to destroy container %d",
     145                 :            :                              sva->vfio_container_fd);
     146                 :            :         }
     147                 :          0 : }
     148                 :            : 
     149                 :            : static int
     150                 :          0 : sfc_vdpa_set_log_prefix(struct sfc_vdpa_adapter *sva)
     151                 :            : {
     152                 :          0 :         struct rte_pci_device *pci_dev = sva->pdev;
     153                 :            :         int ret;
     154                 :            : 
     155                 :          0 :         ret = snprintf(sva->log_prefix, sizeof(sva->log_prefix),
     156                 :            :                        "PMD: sfc_vdpa " PCI_PRI_FMT " : ",
     157                 :          0 :                        pci_dev->addr.domain, pci_dev->addr.bus,
     158         [ #  # ]:          0 :                        pci_dev->addr.devid, pci_dev->addr.function);
     159                 :            : 
     160         [ #  # ]:          0 :         if (ret < 0 || ret >= (int)sizeof(sva->log_prefix)) {
     161                 :          0 :                 SFC_VDPA_GENERIC_LOG(ERR,
     162                 :            :                         "reserved log prefix is too short for " PCI_PRI_FMT,
     163                 :            :                         pci_dev->addr.domain, pci_dev->addr.bus,
     164                 :            :                         pci_dev->addr.devid, pci_dev->addr.function);
     165                 :          0 :                 return -EINVAL;
     166                 :            :         }
     167                 :            : 
     168                 :            :         return 0;
     169                 :            : }
     170                 :            : 
     171                 :            : uint32_t
     172                 :          0 : sfc_vdpa_register_logtype(const struct rte_pci_addr *pci_addr,
     173                 :            :                           const char *lt_prefix_str, uint32_t ll_default)
     174                 :            : {
     175                 :          0 :         size_t lt_prefix_str_size = strlen(lt_prefix_str);
     176                 :            :         size_t lt_str_size_max;
     177                 :            :         char *lt_str = NULL;
     178                 :            :         int ret;
     179                 :            : 
     180                 :            :         if (SIZE_MAX - PCI_PRI_STR_SIZE - 1 > lt_prefix_str_size) {
     181                 :          0 :                 ++lt_prefix_str_size; /* Reserve space for prefix separator */
     182                 :          0 :                 lt_str_size_max = lt_prefix_str_size + PCI_PRI_STR_SIZE + 1;
     183                 :            :         } else {
     184                 :            :                 return sfc_vdpa_logtype_driver;
     185                 :            :         }
     186                 :            : 
     187                 :          0 :         lt_str = rte_zmalloc("logtype_str", lt_str_size_max, 0);
     188         [ #  # ]:          0 :         if (lt_str == NULL)
     189                 :          0 :                 return sfc_vdpa_logtype_driver;
     190                 :            : 
     191                 :            :         strncpy(lt_str, lt_prefix_str, lt_prefix_str_size);
     192                 :          0 :         lt_str[lt_prefix_str_size - 1] = '.';
     193                 :          0 :         rte_pci_device_name(pci_addr, lt_str + lt_prefix_str_size,
     194                 :            :                             lt_str_size_max - lt_prefix_str_size);
     195                 :          0 :         lt_str[lt_str_size_max - 1] = '\0';
     196                 :            : 
     197                 :          0 :         ret = rte_log_register_type_and_pick_level(lt_str, ll_default);
     198                 :          0 :         rte_free(lt_str);
     199                 :            : 
     200         [ #  # ]:          0 :         return ret < 0 ? sfc_vdpa_logtype_driver : ret;
     201                 :            : }
     202                 :            : 
     203                 :            : static int
     204                 :          0 : sfc_vdpa_kvargs_parse(struct sfc_vdpa_adapter *sva)
     205                 :            : {
     206                 :          0 :         struct rte_pci_device *pci_dev = sva->pdev;
     207                 :          0 :         struct rte_devargs *devargs = pci_dev->device.devargs;
     208                 :            :         /*
     209                 :            :          * To get the device class a mandatory param 'class' is being
     210                 :            :          * used so included SFC_EFX_KVARG_DEV_CLASS in the param list.
     211                 :            :          */
     212                 :          0 :         const char **params = (const char *[]){
     213                 :            :                 RTE_DEVARGS_KEY_CLASS,
     214                 :            :                 SFC_VDPA_MAC_ADDR,
     215                 :            :                 NULL,
     216                 :            :         };
     217                 :            : 
     218         [ #  # ]:          0 :         if (devargs == NULL)
     219                 :            :                 return 0;
     220                 :            : 
     221                 :          0 :         sva->kvargs = rte_kvargs_parse(devargs->args, params);
     222         [ #  # ]:          0 :         if (sva->kvargs == NULL)
     223                 :          0 :                 return -EINVAL;
     224                 :            : 
     225                 :            :         return 0;
     226                 :            : }
     227                 :            : 
     228                 :            : static struct rte_pci_id pci_id_sfc_vdpa_efx_map[] = {
     229                 :            :         { RTE_PCI_DEVICE(EFX_PCI_VENID_XILINX, EFX_PCI_DEVID_RIVERHEAD_VF) },
     230                 :            :         { .vendor_id = 0, /* sentinel */ },
     231                 :            : };
     232                 :            : 
     233                 :            : static int
     234                 :          0 : sfc_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
     235                 :            :         struct rte_pci_device *pci_dev)
     236                 :            : {
     237                 :            :         struct sfc_vdpa_adapter *sva = NULL;
     238                 :            :         uint32_t logtype_main;
     239                 :            :         int ret = 0;
     240                 :            : 
     241         [ #  # ]:          0 :         if (sfc_efx_dev_class_get(pci_dev->device.devargs) !=
     242                 :            :                         SFC_EFX_DEV_CLASS_VDPA) {
     243                 :          0 :                 SFC_VDPA_GENERIC_LOG(INFO,
     244                 :            :                         "Incompatible device class: skip probing, should be probed by other sfc driver.");
     245                 :          0 :                         return 1;
     246                 :            :         }
     247                 :            : 
     248                 :            :         /*
     249                 :            :          * It will not be probed in the secondary process. As device class
     250                 :            :          * is vdpa so return 0 to avoid probe by other sfc driver
     251                 :            :          */
     252         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     253                 :            :                 return 0;
     254                 :            : 
     255                 :          0 :         logtype_main = sfc_vdpa_register_logtype(&pci_dev->addr,
     256                 :            :                                                  SFC_VDPA_LOGTYPE_MAIN_STR,
     257                 :            :                                                  RTE_LOG_NOTICE);
     258                 :            : 
     259                 :          0 :         sva = rte_zmalloc("sfc_vdpa", sizeof(struct sfc_vdpa_adapter), 0);
     260         [ #  # ]:          0 :         if (sva == NULL)
     261                 :          0 :                 goto fail_zmalloc;
     262                 :            : 
     263                 :          0 :         sva->pdev = pci_dev;
     264                 :          0 :         sva->logtype_main = logtype_main;
     265                 :            : 
     266                 :          0 :         ret = sfc_vdpa_set_log_prefix(sva);
     267         [ #  # ]:          0 :         if (ret != 0)
     268                 :          0 :                 goto fail_set_log_prefix;
     269                 :            : 
     270                 :          0 :         ret = sfc_vdpa_kvargs_parse(sva);
     271         [ #  # ]:          0 :         if (ret != 0)
     272                 :          0 :                 goto fail_kvargs_parse;
     273                 :            : 
     274                 :          0 :         sfc_vdpa_log_init(sva, "entry");
     275                 :            : 
     276                 :            :         sfc_vdpa_adapter_lock_init(sva);
     277                 :            : 
     278                 :          0 :         sfc_vdpa_log_init(sva, "vfio init");
     279         [ #  # ]:          0 :         if (sfc_vdpa_vfio_setup(sva) < 0) {
     280                 :          0 :                 sfc_vdpa_err(sva, "failed to setup device %s", pci_dev->name);
     281                 :          0 :                 goto fail_vfio_setup;
     282                 :            :         }
     283                 :            : 
     284                 :          0 :         sfc_vdpa_log_init(sva, "hw init");
     285         [ #  # ]:          0 :         if (sfc_vdpa_hw_init(sva) != 0) {
     286                 :          0 :                 sfc_vdpa_err(sva, "failed to init HW %s", pci_dev->name);
     287                 :          0 :                 goto fail_hw_init;
     288                 :            :         }
     289                 :            : 
     290                 :          0 :         sfc_vdpa_log_init(sva, "dev init");
     291                 :          0 :         sva->ops_data = sfc_vdpa_device_init(sva, SFC_VDPA_AS_VF);
     292         [ #  # ]:          0 :         if (sva->ops_data == NULL) {
     293                 :          0 :                 sfc_vdpa_err(sva, "failed vDPA dev init %s", pci_dev->name);
     294                 :          0 :                 goto fail_dev_init;
     295                 :            :         }
     296                 :            : 
     297                 :          0 :         pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
     298                 :          0 :         TAILQ_INSERT_TAIL(&sfc_vdpa_adapter_list, sva, next);
     299                 :          0 :         pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
     300                 :            : 
     301                 :          0 :         sfc_vdpa_log_init(sva, "done");
     302                 :            : 
     303                 :          0 :         return 0;
     304                 :            : 
     305                 :            : fail_dev_init:
     306                 :          0 :         sfc_vdpa_hw_fini(sva);
     307                 :            : 
     308                 :          0 : fail_hw_init:
     309                 :          0 :         sfc_vdpa_vfio_teardown(sva);
     310                 :            : 
     311                 :          0 : fail_vfio_setup:
     312                 :            :         sfc_vdpa_adapter_lock_fini(sva);
     313                 :            : 
     314                 :          0 : fail_kvargs_parse:
     315                 :          0 : fail_set_log_prefix:
     316                 :          0 :         rte_free(sva);
     317                 :            : 
     318                 :            : fail_zmalloc:
     319                 :            :         return -1;
     320                 :            : }
     321                 :            : 
     322                 :            : static int
     323                 :          0 : sfc_vdpa_pci_remove(struct rte_pci_device *pci_dev)
     324                 :            : {
     325                 :            :         struct sfc_vdpa_adapter *sva = NULL;
     326                 :            : 
     327         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     328                 :            :                 return -1;
     329                 :            : 
     330                 :          0 :         sva = sfc_vdpa_get_adapter_by_dev(pci_dev);
     331         [ #  # ]:          0 :         if (sva == NULL) {
     332                 :          0 :                 SFC_VDPA_GENERIC_LOG(INFO,
     333                 :            :                         "Invalid device: %s.", pci_dev->name);
     334                 :          0 :                 return -1;
     335                 :            :         }
     336                 :            : 
     337                 :          0 :         pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
     338         [ #  # ]:          0 :         TAILQ_REMOVE(&sfc_vdpa_adapter_list, sva, next);
     339                 :          0 :         pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
     340                 :            : 
     341                 :          0 :         sfc_vdpa_device_fini(sva->ops_data);
     342                 :            : 
     343                 :          0 :         sfc_vdpa_hw_fini(sva);
     344                 :            : 
     345                 :          0 :         sfc_vdpa_vfio_teardown(sva);
     346                 :            : 
     347                 :            :         sfc_vdpa_adapter_lock_fini(sva);
     348                 :            : 
     349                 :          0 :         rte_free(sva);
     350                 :            : 
     351                 :          0 :         return 0;
     352                 :            : }
     353                 :            : 
     354                 :            : static struct rte_pci_driver rte_sfc_vdpa = {
     355                 :            :         .id_table = pci_id_sfc_vdpa_efx_map,
     356                 :            :         .drv_flags = 0,
     357                 :            :         .probe = sfc_vdpa_pci_probe,
     358                 :            :         .remove = sfc_vdpa_pci_remove,
     359                 :            : };
     360                 :            : 
     361                 :        251 : RTE_PMD_REGISTER_PCI(net_sfc_vdpa, rte_sfc_vdpa);
     362                 :            : RTE_PMD_REGISTER_PCI_TABLE(net_sfc_vdpa, pci_id_sfc_vdpa_efx_map);
     363                 :            : RTE_PMD_REGISTER_KMOD_DEP(net_sfc_vdpa, "* vfio-pci");
     364         [ -  + ]:        251 : RTE_LOG_REGISTER_SUFFIX(sfc_vdpa_logtype_driver, driver, NOTICE);

Generated by: LCOV version 1.14