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