xref: /dpdk/drivers/bus/auxiliary/auxiliary_common.c (revision 30d38a718b9f63f0bda9e24dae90486303f1b206)
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