4 * Copyright(c) 2016 RehiveTech. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
16 * * Neither the name of RehiveTech nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <sys/queue.h>
43 #include <rte_common.h>
44 #include <rte_devargs.h>
45 #include <rte_memory.h>
47 /** Double linked list of virtual device drivers. */
48 TAILQ_HEAD(vdev_device_list
, rte_vdev_device
);
50 static struct vdev_device_list vdev_device_list
=
51 TAILQ_HEAD_INITIALIZER(vdev_device_list
);
52 struct vdev_driver_list vdev_driver_list
=
53 TAILQ_HEAD_INITIALIZER(vdev_driver_list
);
55 static void rte_vdev_bus_register(void);
57 /* register a driver */
59 rte_vdev_register(struct rte_vdev_driver
*driver
)
61 rte_vdev_bus_register();
63 TAILQ_INSERT_TAIL(&vdev_driver_list
, driver
, next
);
66 /* unregister a driver */
68 rte_vdev_unregister(struct rte_vdev_driver
*driver
)
70 TAILQ_REMOVE(&vdev_driver_list
, driver
, next
);
74 * Parse "driver" devargs without adding a dependency on rte_kvargs.h
76 static char *parse_driver_arg(const char *args
)
81 if (!args
|| args
[0] == '\0')
87 if (strncmp(c
, "driver=", 7) == 0) {
106 vdev_probe_all_drivers(struct rte_vdev_device
*dev
)
110 struct rte_vdev_driver
*driver
;
113 drv_name
= parse_driver_arg(rte_vdev_device_args(dev
));
114 name
= drv_name
? drv_name
: rte_vdev_device_name(dev
);
116 RTE_LOG(DEBUG
, EAL
, "Search driver %s to probe device %s\n", name
,
117 rte_vdev_device_name(dev
));
119 TAILQ_FOREACH(driver
, &vdev_driver_list
, next
) {
121 * search a driver prefix in virtual device name.
122 * For example, if the driver is pcap PMD, driver->name
123 * will be "net_pcap", but "name" will be "net_pcapN".
124 * So use strncmp to compare.
126 if (!strncmp(driver
->driver
.name
, name
,
127 strlen(driver
->driver
.name
))) {
128 dev
->device
.driver
= &driver
->driver
;
129 ret
= driver
->probe(dev
);
131 dev
->device
.driver
= NULL
;
136 /* Give new names precedence over aliases. */
137 TAILQ_FOREACH(driver
, &vdev_driver_list
, next
) {
138 if (driver
->driver
.alias
&&
139 !strncmp(driver
->driver
.alias
, name
,
140 strlen(driver
->driver
.alias
))) {
141 dev
->device
.driver
= &driver
->driver
;
142 ret
= driver
->probe(dev
);
144 dev
->device
.driver
= NULL
;
154 static struct rte_vdev_device
*
155 find_vdev(const char *name
)
157 struct rte_vdev_device
*dev
;
162 TAILQ_FOREACH(dev
, &vdev_device_list
, next
) {
163 const char *devname
= rte_vdev_device_name(dev
);
164 if (!strncmp(devname
, name
, strlen(name
)))
171 static struct rte_devargs
*
172 alloc_devargs(const char *name
, const char *args
)
174 struct rte_devargs
*devargs
;
177 devargs
= calloc(1, sizeof(*devargs
));
181 devargs
->type
= RTE_DEVTYPE_VIRTUAL
;
183 devargs
->args
= strdup(args
);
185 ret
= snprintf(devargs
->virt
.drv_name
,
186 sizeof(devargs
->virt
.drv_name
), "%s", name
);
187 if (ret
< 0 || ret
>= (int)sizeof(devargs
->virt
.drv_name
)) {
197 rte_vdev_init(const char *name
, const char *args
)
199 struct rte_vdev_device
*dev
;
200 struct rte_devargs
*devargs
;
206 dev
= find_vdev(name
);
210 devargs
= alloc_devargs(name
, args
);
214 dev
= calloc(1, sizeof(*dev
));
220 dev
->device
.devargs
= devargs
;
221 dev
->device
.numa_node
= SOCKET_ID_ANY
;
222 dev
->device
.name
= devargs
->virt
.drv_name
;
224 ret
= vdev_probe_all_drivers(dev
);
227 RTE_LOG(ERR
, EAL
, "no driver found for %s\n", name
);
231 TAILQ_INSERT_TAIL(&devargs_list
, devargs
, next
);
233 TAILQ_INSERT_TAIL(&vdev_device_list
, dev
, next
);
244 vdev_remove_driver(struct rte_vdev_device
*dev
)
246 const char *name
= rte_vdev_device_name(dev
);
247 const struct rte_vdev_driver
*driver
;
249 if (!dev
->device
.driver
) {
250 RTE_LOG(DEBUG
, EAL
, "no driver attach to device %s\n", name
);
254 driver
= container_of(dev
->device
.driver
, const struct rte_vdev_driver
,
256 return driver
->remove(dev
);
260 rte_vdev_uninit(const char *name
)
262 struct rte_vdev_device
*dev
;
263 struct rte_devargs
*devargs
;
269 dev
= find_vdev(name
);
273 devargs
= dev
->device
.devargs
;
275 ret
= vdev_remove_driver(dev
);
279 TAILQ_REMOVE(&vdev_device_list
, dev
, next
);
281 TAILQ_REMOVE(&devargs_list
, devargs
, next
);
292 struct rte_vdev_device
*dev
;
293 struct rte_devargs
*devargs
;
295 /* for virtual devices we scan the devargs_list populated via cmdline */
297 TAILQ_FOREACH(devargs
, &devargs_list
, next
) {
299 if (devargs
->type
!= RTE_DEVTYPE_VIRTUAL
)
302 dev
= find_vdev(devargs
->virt
.drv_name
);
306 dev
= calloc(1, sizeof(*dev
));
310 dev
->device
.devargs
= devargs
;
311 dev
->device
.numa_node
= SOCKET_ID_ANY
;
312 dev
->device
.name
= devargs
->virt
.drv_name
;
314 TAILQ_INSERT_TAIL(&vdev_device_list
, dev
, next
);
323 struct rte_vdev_device
*dev
;
325 /* call the init function for each virtual device */
326 TAILQ_FOREACH(dev
, &vdev_device_list
, next
) {
328 if (dev
->device
.driver
)
331 if (vdev_probe_all_drivers(dev
)) {
332 RTE_LOG(ERR
, EAL
, "failed to initialize %s device\n",
333 rte_vdev_device_name(dev
));
341 static struct rte_bus rte_vdev_bus
= {
346 RTE_INIT(rte_vdev_bus_register
);
348 static void rte_vdev_bus_register(void)
350 static int registered
;
356 rte_vdev_bus
.name
= RTE_STR(virtual);
357 rte_bus_register(&rte_vdev_bus
);