LCOV - code coverage report
Current view: top level - drivers/net/virtio - virtio_pci_ethdev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 4 82 4.9 %
Date: 2025-02-01 18:54:23 Functions: 1 8 12.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 40 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2016 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdint.h>
       6                 :            : #include <string.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <errno.h>
       9                 :            : #include <unistd.h>
      10                 :            : 
      11                 :            : #include <ethdev_driver.h>
      12                 :            : #include <ethdev_pci.h>
      13                 :            : #include <rte_pci.h>
      14                 :            : #include <bus_pci_driver.h>
      15                 :            : #include <rte_errno.h>
      16                 :            : 
      17                 :            : #include <rte_memory.h>
      18                 :            : #include <rte_eal.h>
      19                 :            : #include <dev_driver.h>
      20                 :            : #include <rte_kvargs.h>
      21                 :            : 
      22                 :            : #include "virtio.h"
      23                 :            : #include "virtio_ethdev.h"
      24                 :            : #include "virtio_pci.h"
      25                 :            : #include "virtio_logs.h"
      26                 :            : 
      27                 :            : /*
      28                 :            :  * The set of PCI devices this driver supports
      29                 :            :  */
      30                 :            : static const struct rte_pci_id pci_id_virtio_map[] = {
      31                 :            :         { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_LEGACY_DEVICEID_NET) },
      32                 :            :         { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_MODERN_DEVICEID_NET) },
      33                 :            :         { .vendor_id = 0, /* sentinel */ },
      34                 :            : };
      35                 :            : 
      36                 :            : 
      37                 :            : /*
      38                 :            :  * Remap the PCI device again (IO port map for legacy device and
      39                 :            :  * memory map for modern device), so that the secondary process
      40                 :            :  * could have the PCI initiated correctly.
      41                 :            :  */
      42                 :            : static int
      43                 :          0 : virtio_remap_pci(struct rte_pci_device *pci_dev, struct virtio_pci_dev *dev)
      44                 :            : {
      45                 :          0 :         struct virtio_hw *hw = &dev->hw;
      46                 :            : 
      47         [ #  # ]:          0 :         if (dev->modern) {
      48                 :            :                 /*
      49                 :            :                  * We don't have to re-parse the PCI config space, since
      50                 :            :                  * rte_pci_map_device() makes sure the mapped address
      51                 :            :                  * in secondary process would equal to the one mapped in
      52                 :            :                  * the primary process: error will be returned if that
      53                 :            :                  * requirement is not met.
      54                 :            :                  *
      55                 :            :                  * That said, we could simply reuse all cap pointers
      56                 :            :                  * (such as dev_cfg, common_cfg, etc.) parsed from the
      57                 :            :                  * primary process, which is stored in shared memory.
      58                 :            :                  */
      59         [ #  # ]:          0 :                 if (rte_pci_map_device(pci_dev)) {
      60                 :          0 :                         PMD_INIT_LOG(DEBUG, "failed to map pci device!");
      61                 :          0 :                         return -1;
      62                 :            :                 }
      63                 :            :         } else {
      64         [ #  # ]:          0 :                 if (vtpci_legacy_ioport_map(hw) < 0)
      65                 :          0 :                         return -1;
      66                 :            :         }
      67                 :            : 
      68                 :            :         return 0;
      69                 :            : }
      70                 :            : 
      71                 :            : static int
      72                 :          0 : eth_virtio_pci_init(struct rte_eth_dev *eth_dev)
      73                 :            : {
      74                 :          0 :         struct virtio_pci_dev *dev = eth_dev->data->dev_private;
      75                 :          0 :         struct virtio_hw *hw = &dev->hw;
      76                 :          0 :         struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
      77                 :            :         int ret;
      78                 :            : 
      79         [ #  # ]:          0 :         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
      80                 :          0 :                 hw->port_id = eth_dev->data->port_id;
      81                 :          0 :                 VTPCI_DEV(hw) = pci_dev;
      82                 :          0 :                 ret = vtpci_init(RTE_ETH_DEV_TO_PCI(eth_dev), dev);
      83         [ #  # ]:          0 :                 if (ret) {
      84                 :          0 :                         PMD_INIT_LOG(ERR, "Failed to init PCI device");
      85                 :          0 :                         return -1;
      86                 :            :                 }
      87                 :            :         } else {
      88                 :          0 :                 VTPCI_DEV(hw) = pci_dev;
      89         [ #  # ]:          0 :                 if (dev->modern)
      90                 :          0 :                         VIRTIO_OPS(hw) = &modern_ops;
      91                 :            :                 else
      92                 :          0 :                         VIRTIO_OPS(hw) = &legacy_ops;
      93                 :            : 
      94                 :          0 :                 ret = virtio_remap_pci(RTE_ETH_DEV_TO_PCI(eth_dev), dev);
      95         [ #  # ]:          0 :                 if (ret < 0) {
      96                 :          0 :                         PMD_INIT_LOG(ERR, "Failed to remap PCI device");
      97                 :          0 :                         return -1;
      98                 :            :                 }
      99                 :            :         }
     100                 :            : 
     101                 :          0 :         ret = eth_virtio_dev_init(eth_dev);
     102         [ #  # ]:          0 :         if (ret < 0) {
     103                 :          0 :                 PMD_INIT_LOG(ERR, "Failed to init virtio device");
     104                 :          0 :                 goto err_unmap;
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x",
     108                 :            :                 eth_dev->data->port_id, pci_dev->id.vendor_id,
     109                 :            :                 pci_dev->id.device_id);
     110                 :            : 
     111                 :          0 :         return 0;
     112                 :            : 
     113                 :            : err_unmap:
     114                 :          0 :         rte_pci_unmap_device(RTE_ETH_DEV_TO_PCI(eth_dev));
     115         [ #  # ]:          0 :         if (!dev->modern)
     116                 :          0 :                 vtpci_legacy_ioport_unmap(hw);
     117                 :            : 
     118                 :            :         return ret;
     119                 :            : }
     120                 :            : 
     121                 :            : static int
     122                 :          0 : eth_virtio_pci_uninit(struct rte_eth_dev *eth_dev)
     123                 :            : {
     124                 :            :         int ret;
     125                 :            :         struct virtio_pci_dev *dev;
     126                 :            :         struct virtio_hw *hw;
     127                 :          0 :         PMD_INIT_FUNC_TRACE();
     128                 :            : 
     129         [ #  # ]:          0 :         if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
     130                 :          0 :                 dev = eth_dev->data->dev_private;
     131                 :          0 :                 hw = &dev->hw;
     132                 :            : 
     133         [ #  # ]:          0 :                 if (dev->modern)
     134                 :          0 :                         rte_pci_unmap_device(RTE_ETH_DEV_TO_PCI(eth_dev));
     135                 :            :                 else
     136                 :          0 :                         vtpci_legacy_ioport_unmap(hw);
     137                 :          0 :                 return 0;
     138                 :            :         }
     139                 :            : 
     140                 :          0 :         ret = virtio_dev_stop(eth_dev);
     141                 :          0 :         virtio_dev_close(eth_dev);
     142                 :            : 
     143                 :          0 :         PMD_INIT_LOG(DEBUG, "dev_uninit completed");
     144                 :            : 
     145                 :          0 :         return ret;
     146                 :            : }
     147                 :            : 
     148                 :          0 : static int vdpa_check_handler(__rte_unused const char *key,
     149                 :            :                 const char *value, void *ret_val)
     150                 :            : {
     151         [ #  # ]:          0 :         if (value == NULL || ret_val == NULL)
     152                 :            :                 return -EINVAL;
     153                 :            : 
     154         [ #  # ]:          0 :         if (strcmp(value, "1") == 0)
     155                 :          0 :                 *(int *)ret_val = 1;
     156                 :            :         else
     157                 :          0 :                 *(int *)ret_val = 0;
     158                 :            : 
     159                 :            :         return 0;
     160                 :            : }
     161                 :            : 
     162                 :            : #define VIRTIO_ARG_VDPA       "vdpa"
     163                 :            : 
     164                 :            : static int
     165                 :          0 : virtio_pci_devargs_parse(struct rte_devargs *devargs, int *vdpa)
     166                 :            : {
     167                 :            :         struct rte_kvargs *kvlist;
     168                 :            :         int ret = 0;
     169                 :            : 
     170         [ #  # ]:          0 :         if (devargs == NULL)
     171                 :            :                 return 0;
     172                 :            : 
     173                 :          0 :         kvlist = rte_kvargs_parse(devargs->args, NULL);
     174         [ #  # ]:          0 :         if (kvlist == NULL) {
     175                 :          0 :                 PMD_INIT_LOG(ERR, "error when parsing param");
     176                 :          0 :                 return 0;
     177                 :            :         }
     178                 :            : 
     179         [ #  # ]:          0 :         if (rte_kvargs_count(kvlist, VIRTIO_ARG_VDPA) == 1) {
     180                 :            :                 /* vdpa mode selected when there's a key-value pair:
     181                 :            :                  * vdpa=1
     182                 :            :                  */
     183                 :          0 :                 ret = rte_kvargs_process(kvlist, VIRTIO_ARG_VDPA,
     184                 :            :                                 vdpa_check_handler, vdpa);
     185         [ #  # ]:          0 :                 if (ret < 0)
     186                 :          0 :                         PMD_INIT_LOG(ERR, "Failed to parse %s", VIRTIO_ARG_VDPA);
     187                 :            :         }
     188                 :            : 
     189                 :          0 :         rte_kvargs_free(kvlist);
     190                 :            : 
     191                 :          0 :         return ret;
     192                 :            : }
     193                 :            : 
     194                 :          0 : static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
     195                 :            :         struct rte_pci_device *pci_dev)
     196                 :            : {
     197                 :          0 :         int vdpa = 0;
     198                 :            :         int ret = 0;
     199                 :            : 
     200                 :          0 :         ret = virtio_pci_devargs_parse(pci_dev->device.devargs, &vdpa);
     201         [ #  # ]:          0 :         if (ret < 0) {
     202                 :          0 :                 PMD_INIT_LOG(ERR, "devargs parsing is failed");
     203                 :          0 :                 return ret;
     204                 :            :         }
     205                 :            :         /* virtio pmd skips probe if device needs to work in vdpa mode */
     206         [ #  # ]:          0 :         if (vdpa == 1)
     207                 :            :                 return 1;
     208                 :            : 
     209                 :          0 :         return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct virtio_pci_dev),
     210                 :            :                 eth_virtio_pci_init);
     211                 :            : }
     212                 :            : 
     213                 :          0 : static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev)
     214                 :            : {
     215                 :            :         int ret;
     216                 :            : 
     217                 :          0 :         ret = rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_pci_uninit);
     218                 :            :         /* Port has already been released by close. */
     219         [ #  # ]:          0 :         if (ret == -ENODEV)
     220                 :            :                 ret = 0;
     221                 :          0 :         return ret;
     222                 :            : }
     223                 :            : 
     224                 :            : static struct rte_pci_driver rte_virtio_net_pci_pmd = {
     225                 :            :         .driver = {
     226                 :            :                 .name = "net_virtio",
     227                 :            :         },
     228                 :            :         .id_table = pci_id_virtio_map,
     229                 :            :         .drv_flags = 0,
     230                 :            :         .probe = eth_virtio_pci_probe,
     231                 :            :         .remove = eth_virtio_pci_remove,
     232                 :            : };
     233                 :            : 
     234                 :        252 : RTE_INIT(rte_virtio_net_pci_pmd_init)
     235                 :            : {
     236                 :        252 :         rte_eal_iopl_init();
     237                 :        252 :         rte_pci_register(&rte_virtio_net_pci_pmd);
     238                 :        252 : }
     239                 :            : 
     240                 :            : RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map);
     241                 :            : RTE_PMD_REGISTER_KMOD_DEP(net_virtio, "* igb_uio | uio_pci_generic | vfio-pci");
     242                 :            : RTE_PMD_EXPORT_NAME(net_virtio, __COUNTER__);

Generated by: LCOV version 1.14