xref: /dpdk/drivers/net/virtio/virtio_pci_ethdev.c (revision 1ac793468953c98311c54ed908a87c1312094aed)
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 		ret = virtio_remap_pci(RTE_ETH_DEV_TO_PCI(eth_dev), dev);
88 		if (ret < 0) {
89 			PMD_INIT_LOG(ERR, "Failed to remap PCI device\n");
90 			return -1;
91 		}
92 	}
93 
94 	ret = eth_virtio_dev_init(eth_dev);
95 	if (ret < 0) {
96 		PMD_INIT_LOG(ERR, "Failed to init virtio device\n");
97 		goto err_unmap;
98 	}
99 
100 	PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x",
101 		eth_dev->data->port_id, pci_dev->id.vendor_id,
102 		pci_dev->id.device_id);
103 
104 	return 0;
105 
106 err_unmap:
107 	rte_pci_unmap_device(RTE_ETH_DEV_TO_PCI(eth_dev));
108 	if (hw->bus_type == VIRTIO_BUS_PCI_LEGACY)
109 		rte_pci_ioport_unmap(VTPCI_IO(hw));
110 
111 	return ret;
112 }
113 
114 static int
115 eth_virtio_pci_uninit(struct rte_eth_dev *eth_dev)
116 {
117 	int ret;
118 	PMD_INIT_FUNC_TRACE();
119 
120 	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
121 		return 0;
122 
123 	ret = virtio_dev_stop(eth_dev);
124 	virtio_dev_close(eth_dev);
125 
126 	PMD_INIT_LOG(DEBUG, "dev_uninit completed");
127 
128 	return ret;
129 }
130 
131 static int vdpa_check_handler(__rte_unused const char *key,
132 		const char *value, void *ret_val)
133 {
134 	if (strcmp(value, "1") == 0)
135 		*(int *)ret_val = 1;
136 	else
137 		*(int *)ret_val = 0;
138 
139 	return 0;
140 }
141 
142 #define VIRTIO_ARG_VDPA       "vdpa"
143 
144 static int
145 virtio_pci_devargs_parse(struct rte_devargs *devargs, int *vdpa)
146 {
147 	struct rte_kvargs *kvlist;
148 	int ret = 0;
149 
150 	if (devargs == NULL)
151 		return 0;
152 
153 	kvlist = rte_kvargs_parse(devargs->args, NULL);
154 	if (kvlist == NULL) {
155 		PMD_INIT_LOG(ERR, "error when parsing param");
156 		return 0;
157 	}
158 
159 	if (rte_kvargs_count(kvlist, VIRTIO_ARG_VDPA) == 1) {
160 		/* vdpa mode selected when there's a key-value pair:
161 		 * vdpa=1
162 		 */
163 		ret = rte_kvargs_process(kvlist, VIRTIO_ARG_VDPA,
164 				vdpa_check_handler, vdpa);
165 		if (ret < 0)
166 			PMD_INIT_LOG(ERR, "Failed to parse %s", VIRTIO_ARG_VDPA);
167 	}
168 
169 	rte_kvargs_free(kvlist);
170 
171 	return ret;
172 }
173 
174 static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
175 	struct rte_pci_device *pci_dev)
176 {
177 	int vdpa = 0;
178 	int ret = 0;
179 
180 	ret = virtio_pci_devargs_parse(pci_dev->device.devargs, &vdpa);
181 	if (ret < 0) {
182 		PMD_INIT_LOG(ERR, "devargs parsing is failed");
183 		return ret;
184 	}
185 	/* virtio pmd skips probe if device needs to work in vdpa mode */
186 	if (vdpa == 1)
187 		return 1;
188 
189 	return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct virtio_pci_dev),
190 		eth_virtio_pci_init);
191 }
192 
193 static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev)
194 {
195 	int ret;
196 
197 	ret = rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_pci_uninit);
198 	/* Port has already been released by close. */
199 	if (ret == -ENODEV)
200 		ret = 0;
201 	return ret;
202 }
203 
204 static struct rte_pci_driver rte_virtio_net_pci_pmd = {
205 	.driver = {
206 		.name = "net_virtio",
207 	},
208 	.id_table = pci_id_virtio_map,
209 	.drv_flags = 0,
210 	.probe = eth_virtio_pci_probe,
211 	.remove = eth_virtio_pci_remove,
212 };
213 
214 RTE_INIT(rte_virtio_net_pci_pmd_init)
215 {
216 	rte_eal_iopl_init();
217 	rte_pci_register(&rte_virtio_net_pci_pmd);
218 }
219 
220 RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map);
221 RTE_PMD_REGISTER_KMOD_DEP(net_virtio, "* igb_uio | uio_pci_generic | vfio-pci");
222 RTE_PMD_EXPORT_NAME(net_virtio, __COUNTER__);
223