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 static int 36 eth_virtio_pci_init(struct rte_eth_dev *eth_dev) 37 { 38 return eth_virtio_dev_init(eth_dev); 39 } 40 41 static int 42 eth_virtio_pci_uninit(struct rte_eth_dev *eth_dev) 43 { 44 int ret; 45 PMD_INIT_FUNC_TRACE(); 46 47 if (rte_eal_process_type() == RTE_PROC_SECONDARY) 48 return 0; 49 50 ret = virtio_dev_stop(eth_dev); 51 virtio_dev_close(eth_dev); 52 53 PMD_INIT_LOG(DEBUG, "dev_uninit completed"); 54 55 return ret; 56 } 57 58 static int vdpa_check_handler(__rte_unused const char *key, 59 const char *value, void *ret_val) 60 { 61 if (strcmp(value, "1") == 0) 62 *(int *)ret_val = 1; 63 else 64 *(int *)ret_val = 0; 65 66 return 0; 67 } 68 69 #define VIRTIO_ARG_VDPA "vdpa" 70 71 static int 72 virtio_pci_devargs_parse(struct rte_devargs *devargs, int *vdpa) 73 { 74 struct rte_kvargs *kvlist; 75 int ret = 0; 76 77 if (devargs == NULL) 78 return 0; 79 80 kvlist = rte_kvargs_parse(devargs->args, NULL); 81 if (kvlist == NULL) { 82 PMD_INIT_LOG(ERR, "error when parsing param"); 83 return 0; 84 } 85 86 if (rte_kvargs_count(kvlist, VIRTIO_ARG_VDPA) == 1) { 87 /* vdpa mode selected when there's a key-value pair: 88 * vdpa=1 89 */ 90 ret = rte_kvargs_process(kvlist, VIRTIO_ARG_VDPA, 91 vdpa_check_handler, vdpa); 92 if (ret < 0) 93 PMD_INIT_LOG(ERR, "Failed to parse %s", VIRTIO_ARG_VDPA); 94 } 95 96 rte_kvargs_free(kvlist); 97 98 return ret; 99 } 100 101 static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, 102 struct rte_pci_device *pci_dev) 103 { 104 int vdpa = 0; 105 int ret = 0; 106 107 ret = virtio_pci_devargs_parse(pci_dev->device.devargs, &vdpa); 108 if (ret < 0) { 109 PMD_INIT_LOG(ERR, "devargs parsing is failed"); 110 return ret; 111 } 112 /* virtio pmd skips probe if device needs to work in vdpa mode */ 113 if (vdpa == 1) 114 return 1; 115 116 return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct virtio_pci_dev), 117 eth_virtio_pci_init); 118 } 119 120 static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev) 121 { 122 int ret; 123 124 ret = rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_pci_uninit); 125 /* Port has already been released by close. */ 126 if (ret == -ENODEV) 127 ret = 0; 128 return ret; 129 } 130 131 static struct rte_pci_driver rte_virtio_net_pci_pmd = { 132 .driver = { 133 .name = "net_virtio", 134 }, 135 .id_table = pci_id_virtio_map, 136 .drv_flags = 0, 137 .probe = eth_virtio_pci_probe, 138 .remove = eth_virtio_pci_remove, 139 }; 140 141 RTE_INIT(rte_virtio_net_pci_pmd_init) 142 { 143 rte_eal_iopl_init(); 144 rte_pci_register(&rte_virtio_net_pci_pmd); 145 } 146 147 RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map); 148 RTE_PMD_REGISTER_KMOD_DEP(net_virtio, "* igb_uio | uio_pci_generic | vfio-pci"); 149 RTE_PMD_EXPORT_NAME(net_virtio, __COUNTER__); 150