Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2018, Microsoft Corporation.
3 : : * All Rights Reserved.
4 : : */
5 : :
6 : : #include <string.h>
7 : : #include <unistd.h>
8 : : #include <dirent.h>
9 : : #include <fcntl.h>
10 : : #include <sys/queue.h>
11 : : #include <sys/mman.h>
12 : :
13 : : #include <eal_export.h>
14 : : #include <rte_log.h>
15 : : #include <rte_eal.h>
16 : : #include <rte_tailq.h>
17 : : #include <rte_devargs.h>
18 : : #include <rte_lcore.h>
19 : : #include <rte_malloc.h>
20 : : #include <rte_errno.h>
21 : : #include <rte_memory.h>
22 : : #include <rte_bus_vmbus.h>
23 : :
24 : : #include "private.h"
25 : :
26 : : /* map a particular resource from a file */
27 : : void *
28 : 0 : vmbus_map_resource(void *requested_addr, int fd, off_t offset, size_t size,
29 : : int flags)
30 : : {
31 : : void *mapaddr;
32 : :
33 : : /* Map the memory resource of device */
34 : 0 : mapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,
35 : : MAP_SHARED | flags, fd, offset);
36 [ # # ]: 0 : if (mapaddr == MAP_FAILED) {
37 : 0 : VMBUS_LOG(ERR,
38 : : "mmap(%d, %p, %zu, %ld) failed: %s",
39 : : fd, requested_addr, size, (long)offset,
40 : : strerror(errno));
41 : : } else {
42 : 0 : VMBUS_LOG(DEBUG, " VMBUS memory mapped at %p",
43 : : mapaddr);
44 : : }
45 : 0 : return mapaddr;
46 : : }
47 : :
48 : : /* unmap a particular resource */
49 : : void
50 : 0 : vmbus_unmap_resource(void *requested_addr, size_t size)
51 : : {
52 [ # # ]: 0 : if (requested_addr == NULL)
53 : : return;
54 : :
55 : : /* Unmap the VMBUS memory resource of device */
56 [ # # ]: 0 : if (munmap(requested_addr, size)) {
57 : 0 : VMBUS_LOG(ERR, "munmap(%p, 0x%lx) failed: %s",
58 : : requested_addr, (unsigned long)size,
59 : : strerror(errno));
60 : : } else {
61 : 0 : VMBUS_LOG(DEBUG, " VMBUS memory unmapped at %p",
62 : : requested_addr);
63 : : }
64 : : }
65 : :
66 : : static bool
67 : 0 : vmbus_bus_match(const struct rte_driver *drv, const struct rte_device *dev)
68 : : {
69 : : const struct rte_vmbus_driver *dr = RTE_BUS_DRIVER(drv, *dr);
70 : : const struct rte_vmbus_device *vmbus_dev = RTE_BUS_DEVICE(dev, *vmbus_dev);
71 : : const rte_uuid_t *id_table;
72 : :
73 [ # # ]: 0 : for (id_table = dr->id_table; !rte_uuid_is_null(*id_table); ++id_table) {
74 [ # # ]: 0 : if (rte_uuid_compare(*id_table, vmbus_dev->class_id) == 0)
75 : : return true;
76 : : }
77 : :
78 : : return false;
79 : : }
80 : :
81 : : /*
82 : : * If device ID match, call the devinit() function of the driver.
83 : : */
84 : : static int
85 : 0 : vmbus_probe_device(struct rte_driver *drv, struct rte_device *dev)
86 : : {
87 : : struct rte_vmbus_device *vmbus_dev = RTE_BUS_DEVICE(dev, *vmbus_dev);
88 : : struct rte_vmbus_driver *vmbus_drv = RTE_BUS_DRIVER(drv, *vmbus_drv);
89 : : char guid[RTE_UUID_STRLEN];
90 : : int ret;
91 : :
92 : 0 : rte_uuid_unparse(vmbus_dev->device_id, guid, sizeof(guid));
93 : 0 : VMBUS_LOG(INFO, "VMBUS device %s on NUMA socket %i",
94 : : guid, vmbus_dev->device.numa_node);
95 : :
96 : : /* no initialization when marked as blocked, return without error */
97 [ # # ]: 0 : if (vmbus_dev->device.devargs != NULL &&
98 [ # # ]: 0 : vmbus_dev->device.devargs->policy == RTE_DEV_BLOCKED) {
99 : 0 : VMBUS_LOG(INFO, " Device is blocked, not initializing");
100 : 0 : return 1;
101 : : }
102 : :
103 : : /* allocate interrupt handle instance */
104 : 0 : vmbus_dev->intr_handle =
105 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
106 [ # # ]: 0 : if (vmbus_dev->intr_handle == NULL)
107 : : return -ENOMEM;
108 : :
109 : : /* map resources for device */
110 : 0 : ret = rte_vmbus_map_device(vmbus_dev);
111 [ # # ]: 0 : if (ret != 0)
112 : 0 : goto free_intr;
113 : :
114 [ # # # # ]: 0 : if (vmbus_dev->device.numa_node < 0 && rte_socket_count() > 1)
115 : 0 : VMBUS_LOG(INFO, "Device %s is not NUMA-aware", guid);
116 : :
117 : : /* call the driver probe() function */
118 : 0 : VMBUS_LOG(INFO, " probe driver: %s", vmbus_drv->driver.name);
119 : 0 : ret = vmbus_drv->probe(vmbus_drv, vmbus_dev);
120 [ # # ]: 0 : if (ret != 0)
121 : 0 : goto unmap;
122 : :
123 : : return 0;
124 : :
125 : : unmap:
126 : 0 : rte_vmbus_unmap_device(vmbus_dev);
127 : 0 : free_intr:
128 : 0 : rte_intr_instance_free(vmbus_dev->intr_handle);
129 : 0 : vmbus_dev->intr_handle = NULL;
130 : :
131 : 0 : return ret;
132 : : }
133 : :
134 : : /*
135 : : * Scan the vmbus, and call the devinit() function for
136 : : * all registered drivers that have a matching entry in its id_table
137 : : * for discovered devices.
138 : : */
139 : : RTE_EXPORT_SYMBOL(rte_vmbus_probe)
140 : : int
141 : 0 : rte_vmbus_probe(void)
142 : : {
143 : 0 : return rte_bus_generic_probe(&rte_vmbus_bus);
144 : : }
145 : :
146 : : static int
147 : 0 : vmbus_unplug_device(struct rte_device *rte_dev)
148 : : {
149 : 0 : const struct rte_vmbus_driver *drv = RTE_BUS_DRIVER(rte_dev->driver, *drv);
150 : : struct rte_vmbus_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
151 : : int ret = 0;
152 : :
153 [ # # ]: 0 : if (drv->remove != NULL) {
154 : 0 : ret = drv->remove(dev);
155 [ # # ]: 0 : if (ret < 0)
156 : : return ret;
157 : : }
158 : :
159 : 0 : rte_vmbus_unmap_device(dev);
160 : 0 : rte_intr_instance_free(dev->intr_handle);
161 : 0 : dev->intr_handle = NULL;
162 : :
163 : 0 : return 0;
164 : : }
165 : :
166 : : static void
167 : 0 : vmbus_free_device(struct rte_device *dev)
168 : : {
169 : 0 : free(RTE_BUS_DEVICE(dev, struct rte_vmbus_device));
170 : 0 : }
171 : :
172 : : static int
173 : 15 : vmbus_parse(const char *name, void *addr)
174 : : {
175 : : rte_uuid_t guid;
176 : : int ret;
177 : :
178 : 15 : ret = rte_uuid_parse(name, guid);
179 [ - + ]: 15 : if (ret == 0 && addr)
180 : : memcpy(addr, &guid, sizeof(guid));
181 : :
182 : 15 : return ret;
183 : : }
184 : :
185 : : static int
186 : 0 : vmbus_dev_compare(const char *name1, const char *name2)
187 : : {
188 : : rte_uuid_t guid1, guid2;
189 : :
190 [ # # # # ]: 0 : if (vmbus_parse(name1, &guid1) != 0 ||
191 : 0 : vmbus_parse(name2, &guid2) != 0)
192 : 0 : return 1;
193 : :
194 : 0 : return rte_uuid_compare(guid1, guid2);
195 : : }
196 : :
197 : : /* register vmbus driver */
198 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_vmbus_register)
199 : : void
200 : 301 : rte_vmbus_register(struct rte_vmbus_driver *driver)
201 : : {
202 : 301 : VMBUS_LOG(DEBUG,
203 : : "Registered driver %s", driver->driver.name);
204 : :
205 : 301 : rte_bus_add_driver(&rte_vmbus_bus, &driver->driver);
206 : 301 : }
207 : :
208 : : /* unregister vmbus driver */
209 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_vmbus_unregister)
210 : : void
211 : 0 : rte_vmbus_unregister(struct rte_vmbus_driver *driver)
212 : : {
213 : 0 : rte_bus_remove_driver(&rte_vmbus_bus, &driver->driver);
214 : 0 : }
215 : :
216 : : /* VMBUS doesn't support hotplug */
217 : : struct rte_bus rte_vmbus_bus = {
218 : : .scan = rte_vmbus_scan,
219 : : .probe = rte_bus_generic_probe,
220 : : .free_device = vmbus_free_device,
221 : : .cleanup = rte_bus_generic_cleanup,
222 : : .find_device = rte_bus_generic_find_device,
223 : : .match = vmbus_bus_match,
224 : : .probe_device = vmbus_probe_device,
225 : : .unplug_device = vmbus_unplug_device,
226 : : .parse = vmbus_parse,
227 : : .dev_compare = vmbus_dev_compare,
228 : : };
229 : :
230 : 301 : RTE_REGISTER_BUS(vmbus, rte_vmbus_bus);
231 [ - + ]: 301 : RTE_LOG_REGISTER_DEFAULT(vmbus_logtype_bus, NOTICE);
|