xref: /dpdk/drivers/net/virtio/virtio_pci_ethdev.c (revision 36a7a2e7a53fd269725429eec2d2354d8ca17f3e)
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