Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <inttypes.h>
7 : : #include <stdint.h>
8 : : #include <stdbool.h>
9 : : #include <stdlib.h>
10 : : #include <stdio.h>
11 : : #include <sys/queue.h>
12 : : #include <rte_errno.h>
13 : : #include <rte_interrupts.h>
14 : : #include <rte_log.h>
15 : : #include <bus_driver.h>
16 : : #include <rte_per_lcore.h>
17 : : #include <rte_memory.h>
18 : : #include <rte_eal.h>
19 : : #include <rte_eal_paging.h>
20 : : #include <rte_lcore.h>
21 : : #include <rte_string_fns.h>
22 : : #include <rte_common.h>
23 : : #include <rte_devargs.h>
24 : :
25 : : #include "private.h"
26 : :
27 : : static struct rte_devargs *
28 : 0 : auxiliary_devargs_lookup(const char *name)
29 : : {
30 : : struct rte_devargs *devargs;
31 : :
32 [ # # ]: 0 : RTE_EAL_DEVARGS_FOREACH(RTE_BUS_AUXILIARY_NAME, devargs) {
33 [ # # ]: 0 : if (strcmp(devargs->name, name) == 0)
34 : 0 : return devargs;
35 : : }
36 : : return NULL;
37 : : }
38 : :
39 : : /*
40 : : * Test whether the auxiliary device exist.
41 : : *
42 : : * Stub for OS not supporting auxiliary bus.
43 : : */
44 : : __rte_weak bool
45 : 0 : auxiliary_dev_exists(const char *name)
46 : : {
47 : : RTE_SET_USED(name);
48 : 0 : return false;
49 : : }
50 : :
51 : : /*
52 : : * Scan the devices in the auxiliary bus.
53 : : *
54 : : * Stub for OS not supporting auxiliary bus.
55 : : */
56 : : __rte_weak int
57 : 0 : auxiliary_scan(void)
58 : : {
59 : 0 : return 0;
60 : : }
61 : :
62 : : /*
63 : : * Update a device's devargs being scanned.
64 : : */
65 : : void
66 : 0 : auxiliary_on_scan(struct rte_auxiliary_device *aux_dev)
67 : : {
68 : 0 : aux_dev->device.devargs = auxiliary_devargs_lookup(aux_dev->name);
69 : 0 : }
70 : :
71 : : /*
72 : : * Match the auxiliary driver and device using driver function.
73 : : */
74 : : bool
75 : 0 : auxiliary_match(const struct rte_auxiliary_driver *aux_drv,
76 : : const struct rte_auxiliary_device *aux_dev)
77 : : {
78 [ # # ]: 0 : if (aux_drv->match == NULL)
79 : : return false;
80 : 0 : return aux_drv->match(aux_dev->name);
81 : : }
82 : :
83 : : /*
84 : : * Call the probe() function of the driver.
85 : : */
86 : : static int
87 : 0 : rte_auxiliary_probe_one_driver(struct rte_auxiliary_driver *drv,
88 : : struct rte_auxiliary_device *dev)
89 : : {
90 : : enum rte_iova_mode iova_mode;
91 : : int ret;
92 : :
93 [ # # ]: 0 : if (drv == NULL || dev == NULL)
94 : : return -EINVAL;
95 : :
96 : : /* Check if driver supports it. */
97 [ # # ]: 0 : if (!auxiliary_match(drv, dev))
98 : : /* Match of device and driver failed */
99 : : return 1;
100 : :
101 : : /* No initialization when marked as blocked, return without error. */
102 [ # # ]: 0 : if (dev->device.devargs != NULL &&
103 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_BLOCKED) {
104 : 0 : AUXILIARY_LOG(INFO, "Device is blocked, not initializing");
105 : 0 : return -1;
106 : : }
107 : :
108 [ # # # # ]: 0 : if (dev->device.numa_node < 0 && rte_socket_count() > 1)
109 : 0 : AUXILIARY_LOG(INFO, "Device %s is not NUMA-aware", dev->name);
110 : :
111 [ # # ]: 0 : if (rte_dev_is_probed(&dev->device)) {
112 : 0 : AUXILIARY_LOG(DEBUG, "Device %s is already probed on auxiliary bus",
113 : : dev->device.name);
114 : 0 : return -EEXIST;
115 : : }
116 : :
117 : 0 : iova_mode = rte_eal_iova_mode();
118 [ # # # # ]: 0 : if ((drv->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0 &&
119 : : iova_mode != RTE_IOVA_VA) {
120 : 0 : AUXILIARY_LOG(ERR, "Driver %s expecting VA IOVA mode but current mode is PA, not initializing",
121 : : drv->driver.name);
122 : 0 : return -EINVAL;
123 : : }
124 : :
125 : : /* Allocate interrupt instance */
126 : 0 : dev->intr_handle =
127 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
128 [ # # ]: 0 : if (dev->intr_handle == NULL) {
129 : 0 : AUXILIARY_LOG(ERR, "Could not allocate interrupt instance for device %s",
130 : : dev->name);
131 : 0 : return -ENOMEM;
132 : : }
133 : :
134 : 0 : dev->driver = drv;
135 : :
136 : 0 : AUXILIARY_LOG(INFO, "Probe auxiliary driver: %s device: %s (NUMA node %i)",
137 : : drv->driver.name, dev->name, dev->device.numa_node);
138 : 0 : ret = drv->probe(drv, dev);
139 [ # # ]: 0 : if (ret != 0) {
140 : 0 : dev->driver = NULL;
141 : 0 : rte_intr_instance_free(dev->intr_handle);
142 : 0 : dev->intr_handle = NULL;
143 : : } else {
144 : 0 : dev->device.driver = &drv->driver;
145 : : }
146 : :
147 : : return ret;
148 : : }
149 : :
150 : : /*
151 : : * Call the remove() function of the driver.
152 : : */
153 : : static int
154 : 0 : rte_auxiliary_driver_remove_dev(struct rte_auxiliary_device *dev)
155 : : {
156 : : struct rte_auxiliary_driver *drv;
157 : : int ret = 0;
158 : :
159 [ # # ]: 0 : if (dev == NULL)
160 : : return -EINVAL;
161 : :
162 : 0 : drv = dev->driver;
163 : :
164 : 0 : AUXILIARY_LOG(DEBUG, "Driver %s remove auxiliary device %s on NUMA node %i",
165 : : drv->driver.name, dev->name, dev->device.numa_node);
166 : :
167 [ # # ]: 0 : if (drv->remove != NULL) {
168 : 0 : ret = drv->remove(dev);
169 [ # # ]: 0 : if (ret < 0)
170 : : return ret;
171 : : }
172 : :
173 : : /* clear driver structure */
174 : 0 : dev->driver = NULL;
175 : 0 : dev->device.driver = NULL;
176 : :
177 : 0 : return 0;
178 : : }
179 : :
180 : : /*
181 : : * Call the probe() function of all registered drivers for the given device.
182 : : * Return < 0 if initialization failed.
183 : : * Return 1 if no driver is found for this device.
184 : : */
185 : : static int
186 : 0 : auxiliary_probe_all_drivers(struct rte_auxiliary_device *dev)
187 : : {
188 : : struct rte_auxiliary_driver *drv;
189 : : int rc;
190 : :
191 [ # # ]: 0 : if (dev == NULL)
192 : : return -EINVAL;
193 : :
194 [ # # ]: 0 : FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
195 [ # # ]: 0 : if (!drv->match(dev->name))
196 : 0 : continue;
197 : :
198 : 0 : rc = rte_auxiliary_probe_one_driver(drv, dev);
199 [ # # ]: 0 : if (rc < 0)
200 : : /* negative value is an error */
201 : 0 : return rc;
202 [ # # ]: 0 : if (rc > 0)
203 : : /* positive value means driver doesn't support it */
204 : 0 : continue;
205 : : return 0;
206 : : }
207 : : return 1;
208 : : }
209 : :
210 : : /*
211 : : * Scan the content of the auxiliary bus, and call the probe function for
212 : : * all registered drivers to try to probe discovered devices.
213 : : */
214 : : static int
215 : 179 : auxiliary_probe(void)
216 : : {
217 : : struct rte_auxiliary_device *dev = NULL;
218 : : size_t probed = 0, failed = 0;
219 : : int ret = 0;
220 : :
221 [ - + ]: 179 : FOREACH_DEVICE_ON_AUXILIARY_BUS(dev) {
222 : 0 : probed++;
223 : :
224 : 0 : ret = auxiliary_probe_all_drivers(dev);
225 [ # # ]: 0 : if (ret < 0) {
226 [ # # ]: 0 : if (ret != -EEXIST) {
227 : 0 : AUXILIARY_LOG(ERR, "Requested device %s cannot be used",
228 : : dev->name);
229 : 0 : rte_errno = errno;
230 : 0 : failed++;
231 : : }
232 : : ret = 0;
233 : : }
234 : : }
235 : :
236 [ + - ]: 179 : return (probed && probed == failed) ? -1 : 0;
237 : : }
238 : :
239 : : static int
240 : 37 : auxiliary_parse(const char *name, void *addr)
241 : : {
242 : : struct rte_auxiliary_driver *drv = NULL;
243 : : const char **out = addr;
244 : :
245 : : /* Allow empty device name "auxiliary:" to bypass entire bus scan. */
246 [ + - ]: 37 : if (strlen(name) == 0)
247 : : return 0;
248 : :
249 [ + + ]: 74 : FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
250 [ + - ]: 37 : if (drv->match(name))
251 : : break;
252 : : }
253 [ - + ]: 37 : if (drv != NULL && addr != NULL)
254 : 0 : *out = name;
255 [ + - ]: 37 : return drv != NULL ? 0 : -1;
256 : : }
257 : :
258 : : /* Register a driver */
259 : : void
260 : 251 : rte_auxiliary_register(struct rte_auxiliary_driver *driver)
261 : : {
262 : 251 : TAILQ_INSERT_TAIL(&auxiliary_bus.driver_list, driver, next);
263 : 251 : }
264 : :
265 : : /* Unregister a driver */
266 : : void
267 : 251 : rte_auxiliary_unregister(struct rte_auxiliary_driver *driver)
268 : : {
269 [ - + ]: 251 : TAILQ_REMOVE(&auxiliary_bus.driver_list, driver, next);
270 : 251 : }
271 : :
272 : : /* Add a device to auxiliary bus */
273 : : void
274 : 0 : auxiliary_add_device(struct rte_auxiliary_device *aux_dev)
275 : : {
276 : 0 : TAILQ_INSERT_TAIL(&auxiliary_bus.device_list, aux_dev, next);
277 : 0 : }
278 : :
279 : : /* Insert a device into a predefined position in auxiliary bus */
280 : : void
281 : 0 : auxiliary_insert_device(struct rte_auxiliary_device *exist_aux_dev,
282 : : struct rte_auxiliary_device *new_aux_dev)
283 : : {
284 : 0 : TAILQ_INSERT_BEFORE(exist_aux_dev, new_aux_dev, next);
285 : 0 : }
286 : :
287 : : /* Remove a device from auxiliary bus */
288 : : static void
289 : : rte_auxiliary_remove_device(struct rte_auxiliary_device *auxiliary_dev)
290 : : {
291 [ # # ]: 0 : TAILQ_REMOVE(&auxiliary_bus.device_list, auxiliary_dev, next);
292 : : }
293 : :
294 : : static struct rte_device *
295 : 0 : auxiliary_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
296 : : const void *data)
297 : : {
298 : : const struct rte_auxiliary_device *pstart;
299 : : struct rte_auxiliary_device *adev;
300 : :
301 [ # # ]: 0 : if (start != NULL) {
302 : 0 : pstart = RTE_DEV_TO_AUXILIARY_CONST(start);
303 : 0 : adev = TAILQ_NEXT(pstart, next);
304 : : } else {
305 : 0 : adev = TAILQ_FIRST(&auxiliary_bus.device_list);
306 : : }
307 [ # # ]: 0 : while (adev != NULL) {
308 [ # # ]: 0 : if (cmp(&adev->device, data) == 0)
309 : 0 : return &adev->device;
310 : 0 : adev = TAILQ_NEXT(adev, next);
311 : : }
312 : : return NULL;
313 : : }
314 : :
315 : : static int
316 : 0 : auxiliary_plug(struct rte_device *dev)
317 : : {
318 [ # # ]: 0 : if (!auxiliary_dev_exists(dev->name))
319 : : return -ENOENT;
320 : 0 : return auxiliary_probe_all_drivers(RTE_DEV_TO_AUXILIARY(dev));
321 : : }
322 : :
323 : : static int
324 : 0 : auxiliary_unplug(struct rte_device *dev)
325 : : {
326 : : struct rte_auxiliary_device *adev;
327 : : int ret;
328 : :
329 : 0 : adev = RTE_DEV_TO_AUXILIARY(dev);
330 : 0 : ret = rte_auxiliary_driver_remove_dev(adev);
331 [ # # ]: 0 : if (ret == 0) {
332 : : rte_auxiliary_remove_device(adev);
333 : 0 : rte_devargs_remove(dev->devargs);
334 : 0 : rte_intr_instance_free(adev->intr_handle);
335 : 0 : free(adev);
336 : : }
337 : 0 : return ret;
338 : : }
339 : :
340 : : static int
341 : 251 : auxiliary_cleanup(void)
342 : : {
343 : : struct rte_auxiliary_device *dev, *tmp_dev;
344 : : int error = 0;
345 : :
346 [ - + ]: 251 : RTE_TAILQ_FOREACH_SAFE(dev, &auxiliary_bus.device_list, next, tmp_dev) {
347 : : int ret;
348 : :
349 : 0 : ret = auxiliary_unplug(&dev->device);
350 [ # # ]: 0 : if (ret < 0) {
351 : 0 : rte_errno = errno;
352 : : error = -1;
353 : : }
354 : : }
355 : :
356 : 251 : return error;
357 : : }
358 : :
359 : : static int
360 : 0 : auxiliary_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
361 : : {
362 : 0 : struct rte_auxiliary_device *aux_dev = RTE_DEV_TO_AUXILIARY(dev);
363 : :
364 [ # # # # ]: 0 : if (dev == NULL || aux_dev->driver == NULL) {
365 : 0 : rte_errno = EINVAL;
366 : 0 : return -1;
367 : : }
368 [ # # ]: 0 : if (aux_dev->driver->dma_map == NULL) {
369 : 0 : rte_errno = ENOTSUP;
370 : 0 : return -1;
371 : : }
372 : 0 : return aux_dev->driver->dma_map(aux_dev, addr, iova, len);
373 : : }
374 : :
375 : : static int
376 : 0 : auxiliary_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova,
377 : : size_t len)
378 : : {
379 : 0 : struct rte_auxiliary_device *aux_dev = RTE_DEV_TO_AUXILIARY(dev);
380 : :
381 [ # # # # ]: 0 : if (dev == NULL || aux_dev->driver == NULL) {
382 : 0 : rte_errno = EINVAL;
383 : 0 : return -1;
384 : : }
385 [ # # ]: 0 : if (aux_dev->driver->dma_unmap == NULL) {
386 : 0 : rte_errno = ENOTSUP;
387 : 0 : return -1;
388 : : }
389 : 0 : return aux_dev->driver->dma_unmap(aux_dev, addr, iova, len);
390 : : }
391 : :
392 : : bool
393 : 0 : auxiliary_is_ignored_device(const char *name)
394 : : {
395 : 0 : struct rte_devargs *devargs = auxiliary_devargs_lookup(name);
396 : :
397 [ # # # ]: 0 : switch (auxiliary_bus.bus.conf.scan_mode) {
398 : 0 : case RTE_BUS_SCAN_ALLOWLIST:
399 [ # # # # ]: 0 : if (devargs && devargs->policy == RTE_DEV_ALLOWED)
400 : 0 : return false;
401 : : break;
402 : 0 : case RTE_BUS_SCAN_UNDEFINED:
403 : : case RTE_BUS_SCAN_BLOCKLIST:
404 [ # # # # ]: 0 : if (devargs == NULL || devargs->policy != RTE_DEV_BLOCKED)
405 : 0 : return false;
406 : : break;
407 : : }
408 : : return true;
409 : : }
410 : :
411 : : static enum rte_iova_mode
412 : 184 : auxiliary_get_iommu_class(void)
413 : : {
414 : : const struct rte_auxiliary_driver *drv;
415 : :
416 [ + + ]: 368 : FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
417 [ + - ]: 184 : if ((drv->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0)
418 : : return RTE_IOVA_VA;
419 : : }
420 : :
421 : : return RTE_IOVA_DC;
422 : : }
423 : :
424 : : struct rte_auxiliary_bus auxiliary_bus = {
425 : : .bus = {
426 : : .scan = auxiliary_scan,
427 : : .probe = auxiliary_probe,
428 : : .cleanup = auxiliary_cleanup,
429 : : .find_device = auxiliary_find_device,
430 : : .plug = auxiliary_plug,
431 : : .unplug = auxiliary_unplug,
432 : : .parse = auxiliary_parse,
433 : : .dma_map = auxiliary_dma_map,
434 : : .dma_unmap = auxiliary_dma_unmap,
435 : : .get_iommu_class = auxiliary_get_iommu_class,
436 : : .dev_iterate = auxiliary_dev_iterate,
437 : : },
438 : : .device_list = TAILQ_HEAD_INITIALIZER(auxiliary_bus.device_list),
439 : : .driver_list = TAILQ_HEAD_INITIALIZER(auxiliary_bus.driver_list),
440 : : };
441 : :
442 : 251 : RTE_REGISTER_BUS(auxiliary, auxiliary_bus.bus);
443 [ - + ]: 251 : RTE_LOG_REGISTER_DEFAULT(auxiliary_bus_logtype, NOTICE);
|