1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
11 #include <ethdev_driver.h>
12 #include <ethdev_pci.h>
14 #include <rte_bus_pci.h>
15 #include <rte_errno.h>
17 #include <rte_memory.h>
20 #include <rte_kvargs.h>
22 #include "virtio_ethdev.h"
23 #include "virtio_pci.h"
24 #include "virtio_logs.h"
27 * The set of PCI devices this driver supports
29 static const struct rte_pci_id pci_id_virtio_map[] = {
30 { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_LEGACY_DEVICEID_NET) },
31 { RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_MODERN_DEVICEID_NET) },
32 { .vendor_id = 0, /* sentinel */ },
37 * Remap the PCI device again (IO port map for legacy device and
38 * memory map for modern device), so that the secondary process
39 * could have the PCI initiated correctly.
42 virtio_remap_pci(struct rte_pci_device *pci_dev, struct virtio_hw *hw)
44 if (hw->bus_type == VIRTIO_BUS_PCI_MODERN) {
46 * We don't have to re-parse the PCI config space, since
47 * rte_pci_map_device() makes sure the mapped address
48 * in secondary process would equal to the one mapped in
49 * the primary process: error will be returned if that
50 * requirement is not met.
52 * That said, we could simply reuse all cap pointers
53 * (such as dev_cfg, common_cfg, etc.) parsed from the
54 * primary process, which is stored in shared memory.
56 if (rte_pci_map_device(pci_dev)) {
57 PMD_INIT_LOG(DEBUG, "failed to map pci device!");
60 } else if (hw->bus_type == VIRTIO_BUS_PCI_LEGACY) {
61 if (rte_pci_ioport_map(pci_dev, 0, VTPCI_IO(hw)) < 0)
69 eth_virtio_pci_init(struct rte_eth_dev *eth_dev)
71 struct virtio_pci_dev *dev = eth_dev->data->dev_private;
72 struct virtio_hw *hw = &dev->hw;
73 struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
76 if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
77 ret = vtpci_init(RTE_ETH_DEV_TO_PCI(eth_dev), hw);
79 PMD_INIT_LOG(ERR, "Failed to init PCI device\n");
83 ret = virtio_remap_pci(RTE_ETH_DEV_TO_PCI(eth_dev), hw);
85 PMD_INIT_LOG(ERR, "Failed to remap PCI device\n");
90 ret = eth_virtio_dev_init(eth_dev);
92 PMD_INIT_LOG(ERR, "Failed to init virtio device\n");
96 PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x",
97 eth_dev->data->port_id, pci_dev->id.vendor_id,
98 pci_dev->id.device_id);
103 rte_pci_unmap_device(RTE_ETH_DEV_TO_PCI(eth_dev));
104 if (hw->bus_type == VIRTIO_BUS_PCI_LEGACY)
105 rte_pci_ioport_unmap(VTPCI_IO(hw));
111 eth_virtio_pci_uninit(struct rte_eth_dev *eth_dev)
114 PMD_INIT_FUNC_TRACE();
116 if (rte_eal_process_type() == RTE_PROC_SECONDARY)
119 ret = virtio_dev_stop(eth_dev);
120 virtio_dev_close(eth_dev);
122 PMD_INIT_LOG(DEBUG, "dev_uninit completed");
127 static int vdpa_check_handler(__rte_unused const char *key,
128 const char *value, void *ret_val)
130 if (strcmp(value, "1") == 0)
138 #define VIRTIO_ARG_VDPA "vdpa"
141 virtio_pci_devargs_parse(struct rte_devargs *devargs, int *vdpa)
143 struct rte_kvargs *kvlist;
149 kvlist = rte_kvargs_parse(devargs->args, NULL);
150 if (kvlist == NULL) {
151 PMD_INIT_LOG(ERR, "error when parsing param");
155 if (rte_kvargs_count(kvlist, VIRTIO_ARG_VDPA) == 1) {
156 /* vdpa mode selected when there's a key-value pair:
159 ret = rte_kvargs_process(kvlist, VIRTIO_ARG_VDPA,
160 vdpa_check_handler, vdpa);
162 PMD_INIT_LOG(ERR, "Failed to parse %s", VIRTIO_ARG_VDPA);
165 rte_kvargs_free(kvlist);
170 static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
171 struct rte_pci_device *pci_dev)
176 ret = virtio_pci_devargs_parse(pci_dev->device.devargs, &vdpa);
178 PMD_INIT_LOG(ERR, "devargs parsing is failed");
181 /* virtio pmd skips probe if device needs to work in vdpa mode */
185 return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct virtio_pci_dev),
186 eth_virtio_pci_init);
189 static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev)
193 ret = rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_pci_uninit);
194 /* Port has already been released by close. */
200 static struct rte_pci_driver rte_virtio_net_pci_pmd = {
202 .name = "net_virtio",
204 .id_table = pci_id_virtio_map,
206 .probe = eth_virtio_pci_probe,
207 .remove = eth_virtio_pci_remove,
210 RTE_INIT(rte_virtio_net_pci_pmd_init)
213 rte_pci_register(&rte_virtio_net_pci_pmd);
216 RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map);
217 RTE_PMD_REGISTER_KMOD_DEP(net_virtio, "* igb_uio | uio_pci_generic | vfio-pci");
218 RTE_PMD_EXPORT_NAME(net_virtio, __COUNTER__);