xref: /dpdk/drivers/net/virtio/virtio_pci_ethdev.c (revision 36a7a2e7a53fd269725429eec2d2354d8ca17f3e)
1*36a7a2e7SMaxime Coquelin /* SPDX-License-Identifier: BSD-3-Clause
2*36a7a2e7SMaxime Coquelin  * Copyright(c) 2010-2016 Intel Corporation
3*36a7a2e7SMaxime Coquelin  */
4*36a7a2e7SMaxime Coquelin 
5*36a7a2e7SMaxime Coquelin #include <stdint.h>
6*36a7a2e7SMaxime Coquelin #include <string.h>
7*36a7a2e7SMaxime Coquelin #include <stdio.h>
8*36a7a2e7SMaxime Coquelin #include <errno.h>
9*36a7a2e7SMaxime Coquelin #include <unistd.h>
10*36a7a2e7SMaxime Coquelin 
11*36a7a2e7SMaxime Coquelin #include <ethdev_driver.h>
12*36a7a2e7SMaxime Coquelin #include <ethdev_pci.h>
13*36a7a2e7SMaxime Coquelin #include <rte_pci.h>
14*36a7a2e7SMaxime Coquelin #include <rte_bus_pci.h>
15*36a7a2e7SMaxime Coquelin #include <rte_errno.h>
16*36a7a2e7SMaxime Coquelin 
17*36a7a2e7SMaxime Coquelin #include <rte_memory.h>
18*36a7a2e7SMaxime Coquelin #include <rte_eal.h>
19*36a7a2e7SMaxime Coquelin #include <rte_dev.h>
20*36a7a2e7SMaxime Coquelin #include <rte_kvargs.h>
21*36a7a2e7SMaxime Coquelin 
22*36a7a2e7SMaxime Coquelin #include "virtio_ethdev.h"
23*36a7a2e7SMaxime Coquelin #include "virtio_pci.h"
24*36a7a2e7SMaxime Coquelin #include "virtio_logs.h"
25*36a7a2e7SMaxime Coquelin 
26*36a7a2e7SMaxime Coquelin /*
27*36a7a2e7SMaxime Coquelin  * The set of PCI devices this driver supports
28*36a7a2e7SMaxime Coquelin  */
29*36a7a2e7SMaxime Coquelin static const struct rte_pci_id pci_id_virtio_map[] = {
30*36a7a2e7SMaxime Coquelin 	{ RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_LEGACY_DEVICEID_NET) },
31*36a7a2e7SMaxime Coquelin 	{ RTE_PCI_DEVICE(VIRTIO_PCI_VENDORID, VIRTIO_PCI_MODERN_DEVICEID_NET) },
32*36a7a2e7SMaxime Coquelin 	{ .vendor_id = 0, /* sentinel */ },
33*36a7a2e7SMaxime Coquelin };
34*36a7a2e7SMaxime Coquelin 
35*36a7a2e7SMaxime Coquelin static int
36*36a7a2e7SMaxime Coquelin eth_virtio_pci_init(struct rte_eth_dev *eth_dev)
37*36a7a2e7SMaxime Coquelin {
38*36a7a2e7SMaxime Coquelin 	return eth_virtio_dev_init(eth_dev);
39*36a7a2e7SMaxime Coquelin }
40*36a7a2e7SMaxime Coquelin 
41*36a7a2e7SMaxime Coquelin static int
42*36a7a2e7SMaxime Coquelin eth_virtio_pci_uninit(struct rte_eth_dev *eth_dev)
43*36a7a2e7SMaxime Coquelin {
44*36a7a2e7SMaxime Coquelin 	int ret;
45*36a7a2e7SMaxime Coquelin 	PMD_INIT_FUNC_TRACE();
46*36a7a2e7SMaxime Coquelin 
47*36a7a2e7SMaxime Coquelin 	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
48*36a7a2e7SMaxime Coquelin 		return 0;
49*36a7a2e7SMaxime Coquelin 
50*36a7a2e7SMaxime Coquelin 	ret = virtio_dev_stop(eth_dev);
51*36a7a2e7SMaxime Coquelin 	virtio_dev_close(eth_dev);
52*36a7a2e7SMaxime Coquelin 
53*36a7a2e7SMaxime Coquelin 	PMD_INIT_LOG(DEBUG, "dev_uninit completed");
54*36a7a2e7SMaxime Coquelin 
55*36a7a2e7SMaxime Coquelin 	return ret;
56*36a7a2e7SMaxime Coquelin }
57*36a7a2e7SMaxime Coquelin 
58*36a7a2e7SMaxime Coquelin static int vdpa_check_handler(__rte_unused const char *key,
59*36a7a2e7SMaxime Coquelin 		const char *value, void *ret_val)
60*36a7a2e7SMaxime Coquelin {
61*36a7a2e7SMaxime Coquelin 	if (strcmp(value, "1") == 0)
62*36a7a2e7SMaxime Coquelin 		*(int *)ret_val = 1;
63*36a7a2e7SMaxime Coquelin 	else
64*36a7a2e7SMaxime Coquelin 		*(int *)ret_val = 0;
65*36a7a2e7SMaxime Coquelin 
66*36a7a2e7SMaxime Coquelin 	return 0;
67*36a7a2e7SMaxime Coquelin }
68*36a7a2e7SMaxime Coquelin 
69*36a7a2e7SMaxime Coquelin #define VIRTIO_ARG_VDPA       "vdpa"
70*36a7a2e7SMaxime Coquelin 
71*36a7a2e7SMaxime Coquelin static int
72*36a7a2e7SMaxime Coquelin virtio_pci_devargs_parse(struct rte_devargs *devargs, int *vdpa)
73*36a7a2e7SMaxime Coquelin {
74*36a7a2e7SMaxime Coquelin 	struct rte_kvargs *kvlist;
75*36a7a2e7SMaxime Coquelin 	int ret = 0;
76*36a7a2e7SMaxime Coquelin 
77*36a7a2e7SMaxime Coquelin 	if (devargs == NULL)
78*36a7a2e7SMaxime Coquelin 		return 0;
79*36a7a2e7SMaxime Coquelin 
80*36a7a2e7SMaxime Coquelin 	kvlist = rte_kvargs_parse(devargs->args, NULL);
81*36a7a2e7SMaxime Coquelin 	if (kvlist == NULL) {
82*36a7a2e7SMaxime Coquelin 		PMD_INIT_LOG(ERR, "error when parsing param");
83*36a7a2e7SMaxime Coquelin 		return 0;
84*36a7a2e7SMaxime Coquelin 	}
85*36a7a2e7SMaxime Coquelin 
86*36a7a2e7SMaxime Coquelin 	if (rte_kvargs_count(kvlist, VIRTIO_ARG_VDPA) == 1) {
87*36a7a2e7SMaxime Coquelin 		/* vdpa mode selected when there's a key-value pair:
88*36a7a2e7SMaxime Coquelin 		 * vdpa=1
89*36a7a2e7SMaxime Coquelin 		 */
90*36a7a2e7SMaxime Coquelin 		ret = rte_kvargs_process(kvlist, VIRTIO_ARG_VDPA,
91*36a7a2e7SMaxime Coquelin 				vdpa_check_handler, vdpa);
92*36a7a2e7SMaxime Coquelin 		if (ret < 0)
93*36a7a2e7SMaxime Coquelin 			PMD_INIT_LOG(ERR, "Failed to parse %s", VIRTIO_ARG_VDPA);
94*36a7a2e7SMaxime Coquelin 	}
95*36a7a2e7SMaxime Coquelin 
96*36a7a2e7SMaxime Coquelin 	rte_kvargs_free(kvlist);
97*36a7a2e7SMaxime Coquelin 
98*36a7a2e7SMaxime Coquelin 	return ret;
99*36a7a2e7SMaxime Coquelin }
100*36a7a2e7SMaxime Coquelin 
101*36a7a2e7SMaxime Coquelin static int eth_virtio_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
102*36a7a2e7SMaxime Coquelin 	struct rte_pci_device *pci_dev)
103*36a7a2e7SMaxime Coquelin {
104*36a7a2e7SMaxime Coquelin 	int vdpa = 0;
105*36a7a2e7SMaxime Coquelin 	int ret = 0;
106*36a7a2e7SMaxime Coquelin 
107*36a7a2e7SMaxime Coquelin 	ret = virtio_pci_devargs_parse(pci_dev->device.devargs, &vdpa);
108*36a7a2e7SMaxime Coquelin 	if (ret < 0) {
109*36a7a2e7SMaxime Coquelin 		PMD_INIT_LOG(ERR, "devargs parsing is failed");
110*36a7a2e7SMaxime Coquelin 		return ret;
111*36a7a2e7SMaxime Coquelin 	}
112*36a7a2e7SMaxime Coquelin 	/* virtio pmd skips probe if device needs to work in vdpa mode */
113*36a7a2e7SMaxime Coquelin 	if (vdpa == 1)
114*36a7a2e7SMaxime Coquelin 		return 1;
115*36a7a2e7SMaxime Coquelin 
116*36a7a2e7SMaxime Coquelin 	return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct virtio_pci_dev),
117*36a7a2e7SMaxime Coquelin 		eth_virtio_pci_init);
118*36a7a2e7SMaxime Coquelin }
119*36a7a2e7SMaxime Coquelin 
120*36a7a2e7SMaxime Coquelin static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev)
121*36a7a2e7SMaxime Coquelin {
122*36a7a2e7SMaxime Coquelin 	int ret;
123*36a7a2e7SMaxime Coquelin 
124*36a7a2e7SMaxime Coquelin 	ret = rte_eth_dev_pci_generic_remove(pci_dev, eth_virtio_pci_uninit);
125*36a7a2e7SMaxime Coquelin 	/* Port has already been released by close. */
126*36a7a2e7SMaxime Coquelin 	if (ret == -ENODEV)
127*36a7a2e7SMaxime Coquelin 		ret = 0;
128*36a7a2e7SMaxime Coquelin 	return ret;
129*36a7a2e7SMaxime Coquelin }
130*36a7a2e7SMaxime Coquelin 
131*36a7a2e7SMaxime Coquelin static struct rte_pci_driver rte_virtio_net_pci_pmd = {
132*36a7a2e7SMaxime Coquelin 	.driver = {
133*36a7a2e7SMaxime Coquelin 		.name = "net_virtio",
134*36a7a2e7SMaxime Coquelin 	},
135*36a7a2e7SMaxime Coquelin 	.id_table = pci_id_virtio_map,
136*36a7a2e7SMaxime Coquelin 	.drv_flags = 0,
137*36a7a2e7SMaxime Coquelin 	.probe = eth_virtio_pci_probe,
138*36a7a2e7SMaxime Coquelin 	.remove = eth_virtio_pci_remove,
139*36a7a2e7SMaxime Coquelin };
140*36a7a2e7SMaxime Coquelin 
141*36a7a2e7SMaxime Coquelin RTE_INIT(rte_virtio_net_pci_pmd_init)
142*36a7a2e7SMaxime Coquelin {
143*36a7a2e7SMaxime Coquelin 	rte_eal_iopl_init();
144*36a7a2e7SMaxime Coquelin 	rte_pci_register(&rte_virtio_net_pci_pmd);
145*36a7a2e7SMaxime Coquelin }
146*36a7a2e7SMaxime Coquelin 
147*36a7a2e7SMaxime Coquelin RTE_PMD_REGISTER_PCI_TABLE(net_virtio, pci_id_virtio_map);
148*36a7a2e7SMaxime Coquelin RTE_PMD_REGISTER_KMOD_DEP(net_virtio, "* igb_uio | uio_pci_generic | vfio-pci");
149*36a7a2e7SMaxime Coquelin RTE_PMD_EXPORT_NAME(net_virtio, __COUNTER__);
150