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 : : /* allocate interrupt handle instance */
97 : 0 : vmbus_dev->intr_handle =
98 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
99 [ # # ]: 0 : if (vmbus_dev->intr_handle == NULL)
100 : : return -ENOMEM;
101 : :
102 : : /* map resources for device */
103 : 0 : ret = rte_vmbus_map_device(vmbus_dev);
104 [ # # ]: 0 : if (ret != 0)
105 : 0 : goto free_intr;
106 : :
107 [ # # # # ]: 0 : if (vmbus_dev->device.numa_node < 0 && rte_socket_count() > 1)
108 : 0 : VMBUS_LOG(INFO, "Device %s is not NUMA-aware", guid);
109 : :
110 : : /* call the driver probe() function */
111 : 0 : VMBUS_LOG(INFO, " probe driver: %s", vmbus_drv->driver.name);
112 : 0 : ret = vmbus_drv->probe(vmbus_drv, vmbus_dev);
113 [ # # ]: 0 : if (ret != 0)
114 : 0 : goto unmap;
115 : :
116 : : return 0;
117 : :
118 : : unmap:
119 : 0 : rte_vmbus_unmap_device(vmbus_dev);
120 : 0 : free_intr:
121 : 0 : rte_intr_instance_free(vmbus_dev->intr_handle);
122 : 0 : vmbus_dev->intr_handle = NULL;
123 : :
124 : 0 : return ret;
125 : : }
126 : :
127 : : /*
128 : : * Scan the vmbus, and call the devinit() function for
129 : : * all registered drivers that have a matching entry in its id_table
130 : : * for discovered devices.
131 : : */
132 : : RTE_EXPORT_SYMBOL(rte_vmbus_probe)
133 : : int
134 : 0 : rte_vmbus_probe(void)
135 : : {
136 : 0 : return rte_bus_generic_probe(&rte_vmbus_bus);
137 : : }
138 : :
139 : : static int
140 : 0 : vmbus_unplug_device(struct rte_device *rte_dev)
141 : : {
142 : 0 : const struct rte_vmbus_driver *drv = RTE_BUS_DRIVER(rte_dev->driver, *drv);
143 : : struct rte_vmbus_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
144 : : int ret = 0;
145 : :
146 [ # # ]: 0 : if (drv->remove != NULL) {
147 : 0 : ret = drv->remove(dev);
148 [ # # ]: 0 : if (ret < 0)
149 : : return ret;
150 : : }
151 : :
152 : 0 : rte_vmbus_unmap_device(dev);
153 : 0 : rte_intr_instance_free(dev->intr_handle);
154 : 0 : dev->intr_handle = NULL;
155 : :
156 : 0 : return 0;
157 : : }
158 : :
159 : : static void
160 : 0 : vmbus_free_device(struct rte_device *dev)
161 : : {
162 : 0 : free(RTE_BUS_DEVICE(dev, struct rte_vmbus_device));
163 : 0 : }
164 : :
165 : : static int
166 : 15 : vmbus_parse(const char *name, void *addr)
167 : : {
168 : : rte_uuid_t guid;
169 : : int ret;
170 : :
171 : 15 : ret = rte_uuid_parse(name, guid);
172 [ - + ]: 15 : if (ret == 0 && addr)
173 : : memcpy(addr, &guid, sizeof(guid));
174 : :
175 : 15 : return ret;
176 : : }
177 : :
178 : : static int
179 : 0 : vmbus_dev_compare(const char *name1, const char *name2)
180 : : {
181 : : rte_uuid_t guid1, guid2;
182 : :
183 [ # # # # ]: 0 : if (vmbus_parse(name1, &guid1) != 0 ||
184 : 0 : vmbus_parse(name2, &guid2) != 0)
185 : 0 : return 1;
186 : :
187 : 0 : return rte_uuid_compare(guid1, guid2);
188 : : }
189 : :
190 : : /* register vmbus driver */
191 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_vmbus_register)
192 : : void
193 : 303 : rte_vmbus_register(struct rte_vmbus_driver *driver)
194 : : {
195 : 303 : VMBUS_LOG(DEBUG,
196 : : "Registered driver %s", driver->driver.name);
197 : :
198 : 303 : rte_bus_add_driver(&rte_vmbus_bus, &driver->driver);
199 : 303 : }
200 : :
201 : : /* unregister vmbus driver */
202 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_vmbus_unregister)
203 : : void
204 : 0 : rte_vmbus_unregister(struct rte_vmbus_driver *driver)
205 : : {
206 : 0 : rte_bus_remove_driver(&rte_vmbus_bus, &driver->driver);
207 : 0 : }
208 : :
209 : : /* VMBUS doesn't support hotplug */
210 : : struct rte_bus rte_vmbus_bus = {
211 : : .scan = rte_vmbus_scan,
212 : : .probe = rte_bus_generic_probe,
213 : : .free_device = vmbus_free_device,
214 : : .cleanup = rte_bus_generic_cleanup,
215 : : .find_device = rte_bus_generic_find_device,
216 : : .match = vmbus_bus_match,
217 : : .probe_device = vmbus_probe_device,
218 : : .unplug_device = vmbus_unplug_device,
219 : : .parse = vmbus_parse,
220 : : .dev_compare = vmbus_dev_compare,
221 : : };
222 : :
223 : 303 : RTE_REGISTER_BUS(vmbus, rte_vmbus_bus);
224 [ - + ]: 303 : RTE_LOG_REGISTER_DEFAULT(vmbus_logtype_bus, NOTICE);
|