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 *
auxiliary_devargs_lookup(const char * name)28 auxiliary_devargs_lookup(const char *name)
29 {
30 struct rte_devargs *devargs;
31
32 RTE_EAL_DEVARGS_FOREACH(RTE_BUS_AUXILIARY_NAME, devargs) {
33 if (strcmp(devargs->name, name) == 0)
34 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
auxiliary_dev_exists(const char * name)45 auxiliary_dev_exists(const char *name)
46 {
47 RTE_SET_USED(name);
48 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
auxiliary_scan(void)57 auxiliary_scan(void)
58 {
59 return 0;
60 }
61
62 /*
63 * Update a device's devargs being scanned.
64 */
65 void
auxiliary_on_scan(struct rte_auxiliary_device * aux_dev)66 auxiliary_on_scan(struct rte_auxiliary_device *aux_dev)
67 {
68 aux_dev->device.devargs = auxiliary_devargs_lookup(aux_dev->name);
69 }
70
71 /*
72 * Match the auxiliary driver and device using driver function.
73 */
74 bool
auxiliary_match(const struct rte_auxiliary_driver * aux_drv,const struct rte_auxiliary_device * aux_dev)75 auxiliary_match(const struct rte_auxiliary_driver *aux_drv,
76 const struct rte_auxiliary_device *aux_dev)
77 {
78 if (aux_drv->match == NULL)
79 return false;
80 return aux_drv->match(aux_dev->name);
81 }
82
83 /*
84 * Call the probe() function of the driver.
85 */
86 static int
rte_auxiliary_probe_one_driver(struct rte_auxiliary_driver * drv,struct rte_auxiliary_device * dev)87 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 if (drv == NULL || dev == NULL)
94 return -EINVAL;
95
96 /* Check if driver supports it. */
97 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 if (dev->device.devargs != NULL &&
103 dev->device.devargs->policy == RTE_DEV_BLOCKED) {
104 AUXILIARY_LOG(INFO, "Device is blocked, not initializing");
105 return -1;
106 }
107
108 if (dev->device.numa_node < 0 && rte_socket_count() > 1)
109 AUXILIARY_LOG(INFO, "Device %s is not NUMA-aware", dev->name);
110
111 if (rte_dev_is_probed(&dev->device)) {
112 AUXILIARY_LOG(DEBUG, "Device %s is already probed on auxiliary bus",
113 dev->device.name);
114 return -EEXIST;
115 }
116
117 iova_mode = rte_eal_iova_mode();
118 if ((drv->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0 &&
119 iova_mode != RTE_IOVA_VA) {
120 AUXILIARY_LOG(ERR, "Driver %s expecting VA IOVA mode but current mode is PA, not initializing",
121 drv->driver.name);
122 return -EINVAL;
123 }
124
125 /* Allocate interrupt instance */
126 dev->intr_handle =
127 rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
128 if (dev->intr_handle == NULL) {
129 AUXILIARY_LOG(ERR, "Could not allocate interrupt instance for device %s",
130 dev->name);
131 return -ENOMEM;
132 }
133
134 dev->driver = drv;
135
136 AUXILIARY_LOG(INFO, "Probe auxiliary driver: %s device: %s (NUMA node %i)",
137 drv->driver.name, dev->name, dev->device.numa_node);
138 ret = drv->probe(drv, dev);
139 if (ret != 0) {
140 dev->driver = NULL;
141 rte_intr_instance_free(dev->intr_handle);
142 dev->intr_handle = NULL;
143 } else {
144 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
rte_auxiliary_driver_remove_dev(struct rte_auxiliary_device * dev)154 rte_auxiliary_driver_remove_dev(struct rte_auxiliary_device *dev)
155 {
156 struct rte_auxiliary_driver *drv;
157 int ret = 0;
158
159 if (dev == NULL)
160 return -EINVAL;
161
162 drv = dev->driver;
163
164 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 if (drv->remove != NULL) {
168 ret = drv->remove(dev);
169 if (ret < 0)
170 return ret;
171 }
172
173 /* clear driver structure */
174 dev->driver = NULL;
175 dev->device.driver = NULL;
176
177 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
auxiliary_probe_all_drivers(struct rte_auxiliary_device * dev)186 auxiliary_probe_all_drivers(struct rte_auxiliary_device *dev)
187 {
188 struct rte_auxiliary_driver *drv;
189 int rc;
190
191 if (dev == NULL)
192 return -EINVAL;
193
194 FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
195 if (!drv->match(dev->name))
196 continue;
197
198 rc = rte_auxiliary_probe_one_driver(drv, dev);
199 if (rc < 0)
200 /* negative value is an error */
201 return rc;
202 if (rc > 0)
203 /* positive value means driver doesn't support it */
204 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
auxiliary_probe(void)215 auxiliary_probe(void)
216 {
217 struct rte_auxiliary_device *dev = NULL;
218 size_t probed = 0, failed = 0;
219 int ret = 0;
220
221 FOREACH_DEVICE_ON_AUXILIARY_BUS(dev) {
222 probed++;
223
224 ret = auxiliary_probe_all_drivers(dev);
225 if (ret < 0) {
226 if (ret != -EEXIST) {
227 AUXILIARY_LOG(ERR, "Requested device %s cannot be used",
228 dev->name);
229 rte_errno = errno;
230 failed++;
231 }
232 ret = 0;
233 }
234 }
235
236 return (probed && probed == failed) ? -1 : 0;
237 }
238
239 static int
auxiliary_parse(const char * name,void * addr)240 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 if (strlen(name) == 0)
247 return 0;
248
249 FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
250 if (drv->match(name))
251 break;
252 }
253 if (drv != NULL && addr != NULL)
254 *out = name;
255 return drv != NULL ? 0 : -1;
256 }
257
258 /* Register a driver */
259 void
rte_auxiliary_register(struct rte_auxiliary_driver * driver)260 rte_auxiliary_register(struct rte_auxiliary_driver *driver)
261 {
262 TAILQ_INSERT_TAIL(&auxiliary_bus.driver_list, driver, next);
263 }
264
265 /* Unregister a driver */
266 void
rte_auxiliary_unregister(struct rte_auxiliary_driver * driver)267 rte_auxiliary_unregister(struct rte_auxiliary_driver *driver)
268 {
269 TAILQ_REMOVE(&auxiliary_bus.driver_list, driver, next);
270 }
271
272 /* Add a device to auxiliary bus */
273 void
auxiliary_add_device(struct rte_auxiliary_device * aux_dev)274 auxiliary_add_device(struct rte_auxiliary_device *aux_dev)
275 {
276 TAILQ_INSERT_TAIL(&auxiliary_bus.device_list, aux_dev, next);
277 }
278
279 /* Insert a device into a predefined position in auxiliary bus */
280 void
auxiliary_insert_device(struct rte_auxiliary_device * exist_aux_dev,struct rte_auxiliary_device * new_aux_dev)281 auxiliary_insert_device(struct rte_auxiliary_device *exist_aux_dev,
282 struct rte_auxiliary_device *new_aux_dev)
283 {
284 TAILQ_INSERT_BEFORE(exist_aux_dev, new_aux_dev, next);
285 }
286
287 /* Remove a device from auxiliary bus */
288 static void
rte_auxiliary_remove_device(struct rte_auxiliary_device * auxiliary_dev)289 rte_auxiliary_remove_device(struct rte_auxiliary_device *auxiliary_dev)
290 {
291 TAILQ_REMOVE(&auxiliary_bus.device_list, auxiliary_dev, next);
292 }
293
294 static struct rte_device *
auxiliary_find_device(const struct rte_device * start,rte_dev_cmp_t cmp,const void * data)295 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 if (start != NULL) {
302 pstart = RTE_DEV_TO_AUXILIARY_CONST(start);
303 adev = TAILQ_NEXT(pstart, next);
304 } else {
305 adev = TAILQ_FIRST(&auxiliary_bus.device_list);
306 }
307 while (adev != NULL) {
308 if (cmp(&adev->device, data) == 0)
309 return &adev->device;
310 adev = TAILQ_NEXT(adev, next);
311 }
312 return NULL;
313 }
314
315 static int
auxiliary_plug(struct rte_device * dev)316 auxiliary_plug(struct rte_device *dev)
317 {
318 if (!auxiliary_dev_exists(dev->name))
319 return -ENOENT;
320 return auxiliary_probe_all_drivers(RTE_DEV_TO_AUXILIARY(dev));
321 }
322
323 static int
auxiliary_unplug(struct rte_device * dev)324 auxiliary_unplug(struct rte_device *dev)
325 {
326 struct rte_auxiliary_device *adev;
327 int ret;
328
329 adev = RTE_DEV_TO_AUXILIARY(dev);
330 ret = rte_auxiliary_driver_remove_dev(adev);
331 if (ret == 0) {
332 rte_auxiliary_remove_device(adev);
333 rte_devargs_remove(dev->devargs);
334 rte_intr_instance_free(adev->intr_handle);
335 free(adev);
336 }
337 return ret;
338 }
339
340 static int
auxiliary_cleanup(void)341 auxiliary_cleanup(void)
342 {
343 struct rte_auxiliary_device *dev, *tmp_dev;
344 int error = 0;
345
346 RTE_TAILQ_FOREACH_SAFE(dev, &auxiliary_bus.device_list, next, tmp_dev) {
347 int ret;
348
349 ret = auxiliary_unplug(&dev->device);
350 if (ret < 0) {
351 rte_errno = errno;
352 error = -1;
353 }
354 }
355
356 return error;
357 }
358
359 static int
auxiliary_dma_map(struct rte_device * dev,void * addr,uint64_t iova,size_t len)360 auxiliary_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
361 {
362 struct rte_auxiliary_device *aux_dev = RTE_DEV_TO_AUXILIARY(dev);
363
364 if (dev == NULL || aux_dev->driver == NULL) {
365 rte_errno = EINVAL;
366 return -1;
367 }
368 if (aux_dev->driver->dma_map == NULL) {
369 rte_errno = ENOTSUP;
370 return -1;
371 }
372 return aux_dev->driver->dma_map(aux_dev, addr, iova, len);
373 }
374
375 static int
auxiliary_dma_unmap(struct rte_device * dev,void * addr,uint64_t iova,size_t len)376 auxiliary_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova,
377 size_t len)
378 {
379 struct rte_auxiliary_device *aux_dev = RTE_DEV_TO_AUXILIARY(dev);
380
381 if (dev == NULL || aux_dev->driver == NULL) {
382 rte_errno = EINVAL;
383 return -1;
384 }
385 if (aux_dev->driver->dma_unmap == NULL) {
386 rte_errno = ENOTSUP;
387 return -1;
388 }
389 return aux_dev->driver->dma_unmap(aux_dev, addr, iova, len);
390 }
391
392 bool
auxiliary_is_ignored_device(const char * name)393 auxiliary_is_ignored_device(const char *name)
394 {
395 struct rte_devargs *devargs = auxiliary_devargs_lookup(name);
396
397 switch (auxiliary_bus.bus.conf.scan_mode) {
398 case RTE_BUS_SCAN_ALLOWLIST:
399 if (devargs && devargs->policy == RTE_DEV_ALLOWED)
400 return false;
401 break;
402 case RTE_BUS_SCAN_UNDEFINED:
403 case RTE_BUS_SCAN_BLOCKLIST:
404 if (devargs == NULL || devargs->policy != RTE_DEV_BLOCKED)
405 return false;
406 break;
407 }
408 return true;
409 }
410
411 static enum rte_iova_mode
auxiliary_get_iommu_class(void)412 auxiliary_get_iommu_class(void)
413 {
414 const struct rte_auxiliary_driver *drv;
415
416 FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
417 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 RTE_REGISTER_BUS(auxiliary, auxiliary_bus.bus);
443 RTE_LOG_REGISTER_DEFAULT(auxiliary_bus_logtype, NOTICE);
444