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 <eal_export.h>
13 : : #include <rte_errno.h>
14 : : #include <rte_interrupts.h>
15 : : #include <rte_log.h>
16 : : #include <bus_driver.h>
17 : : #include <rte_per_lcore.h>
18 : : #include <rte_memory.h>
19 : : #include <rte_eal.h>
20 : : #include <rte_eal_paging.h>
21 : : #include <rte_lcore.h>
22 : : #include <rte_string_fns.h>
23 : : #include <rte_common.h>
24 : : #include <rte_devargs.h>
25 : :
26 : : #include "private.h"
27 : :
28 : : #ifndef AUXILIARY_OS_SUPPORTED
29 : : /*
30 : : * Test whether the auxiliary device exist.
31 : : *
32 : : * Stub for OS not supporting auxiliary bus.
33 : : */
34 : : bool
35 : : auxiliary_dev_exists(const char *name)
36 : : {
37 : : RTE_SET_USED(name);
38 : : return false;
39 : : }
40 : :
41 : : /*
42 : : * Scan the devices in the auxiliary bus.
43 : : *
44 : : * Stub for OS not supporting auxiliary bus.
45 : : */
46 : : int
47 : : auxiliary_scan(void)
48 : : {
49 : : return 0;
50 : : }
51 : : #endif /* AUXILIARY_OS_SUPPORTED */
52 : :
53 : : /*
54 : : * Update a device's devargs being scanned.
55 : : */
56 : : void
57 : 0 : auxiliary_on_scan(struct rte_auxiliary_device *aux_dev)
58 : : {
59 : 0 : aux_dev->device.devargs = rte_bus_find_devargs(&auxiliary_bus, aux_dev->name);
60 : 0 : }
61 : :
62 : : static bool
63 : 0 : auxiliary_bus_match(const struct rte_driver *drv, const struct rte_device *dev)
64 : : {
65 : : const struct rte_auxiliary_driver *aux_drv = RTE_BUS_DRIVER(drv, *aux_drv);
66 : : const struct rte_auxiliary_device *aux_dev = RTE_BUS_DEVICE(dev, *aux_dev);
67 : :
68 [ # # ]: 0 : if (aux_drv->match == NULL)
69 : : return false;
70 : 0 : return aux_drv->match(aux_dev->name);
71 : : }
72 : :
73 : : /*
74 : : * Call the probe() function of the driver.
75 : : */
76 : : static int
77 : 0 : auxiliary_probe_device(struct rte_driver *drv, struct rte_device *dev)
78 : : {
79 : : struct rte_auxiliary_device *aux_dev = RTE_BUS_DEVICE(dev, *aux_dev);
80 : : struct rte_auxiliary_driver *aux_drv = RTE_BUS_DRIVER(drv, *aux_drv);
81 : : enum rte_iova_mode iova_mode;
82 : : int ret;
83 : :
84 [ # # ]: 0 : if (!auxiliary_dev_exists(dev->name))
85 : : return -ENOENT;
86 : :
87 : : /* No initialization when marked as blocked, return without error. */
88 [ # # ]: 0 : if (aux_dev->device.devargs != NULL &&
89 [ # # ]: 0 : aux_dev->device.devargs->policy == RTE_DEV_BLOCKED) {
90 : 0 : AUXILIARY_LOG(INFO, "Device is blocked, not initializing");
91 : 0 : return -1;
92 : : }
93 : :
94 [ # # # # ]: 0 : if (aux_dev->device.numa_node < 0 && rte_socket_count() > 1)
95 : 0 : AUXILIARY_LOG(INFO, "Device %s is not NUMA-aware", aux_dev->name);
96 : :
97 : 0 : iova_mode = rte_eal_iova_mode();
98 [ # # # # ]: 0 : if ((aux_drv->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0 &&
99 : : iova_mode != RTE_IOVA_VA) {
100 : 0 : AUXILIARY_LOG(ERR, "Driver %s expecting VA IOVA mode but current mode is PA, not initializing",
101 : : aux_drv->driver.name);
102 : 0 : return -EINVAL;
103 : : }
104 : :
105 : : /* Allocate interrupt instance */
106 : 0 : aux_dev->intr_handle =
107 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
108 [ # # ]: 0 : if (aux_dev->intr_handle == NULL) {
109 : 0 : AUXILIARY_LOG(ERR, "Could not allocate interrupt instance for device %s",
110 : : aux_dev->name);
111 : 0 : return -ENOMEM;
112 : : }
113 : :
114 : 0 : AUXILIARY_LOG(INFO, "Probe auxiliary driver: %s device: %s (NUMA node %i)",
115 : : aux_drv->driver.name, aux_dev->name, aux_dev->device.numa_node);
116 : 0 : ret = aux_drv->probe(aux_drv, aux_dev);
117 [ # # ]: 0 : if (ret != 0) {
118 : 0 : rte_intr_instance_free(aux_dev->intr_handle);
119 : 0 : aux_dev->intr_handle = NULL;
120 : : }
121 : :
122 : : return ret;
123 : : }
124 : :
125 : : static int
126 : 0 : auxiliary_unplug_device(struct rte_device *rte_dev)
127 : : {
128 : 0 : const struct rte_auxiliary_driver *drv = RTE_BUS_DRIVER(rte_dev->driver, *drv);
129 : : struct rte_auxiliary_device *dev = RTE_BUS_DEVICE(rte_dev, *dev);
130 : : int ret = 0;
131 : :
132 : 0 : AUXILIARY_LOG(DEBUG, "Driver %s remove auxiliary device %s on NUMA node %i",
133 : : drv->driver.name, dev->name, dev->device.numa_node);
134 : :
135 [ # # ]: 0 : if (drv->remove != NULL) {
136 : 0 : ret = drv->remove(dev);
137 [ # # ]: 0 : if (ret < 0)
138 : : return ret;
139 : : }
140 : :
141 : 0 : rte_intr_instance_free(dev->intr_handle);
142 : 0 : dev->intr_handle = NULL;
143 : :
144 : 0 : return 0;
145 : : }
146 : :
147 : : static int
148 : 42 : auxiliary_parse(const char *name, void *addr)
149 : : {
150 : : struct rte_auxiliary_driver *drv = NULL;
151 : : const char **out = addr;
152 : :
153 : : /* Allow empty device name "auxiliary:" to bypass entire bus scan. */
154 [ + - ]: 42 : if (strlen(name) == 0)
155 : : return 0;
156 : :
157 [ + + ]: 84 : RTE_BUS_FOREACH_DRV(drv, &auxiliary_bus) {
158 [ + - ]: 42 : if (drv->match(name))
159 : : break;
160 : : }
161 [ - + ]: 42 : if (drv != NULL && addr != NULL)
162 : 0 : *out = name;
163 [ + - ]: 42 : return drv != NULL ? 0 : -1;
164 : : }
165 : :
166 : : /* Register a driver */
167 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_auxiliary_register)
168 : : void
169 : 301 : rte_auxiliary_register(struct rte_auxiliary_driver *driver)
170 : : {
171 : 301 : rte_bus_add_driver(&auxiliary_bus, &driver->driver);
172 : 301 : }
173 : :
174 : : /* Unregister a driver */
175 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_auxiliary_unregister)
176 : : void
177 : 301 : rte_auxiliary_unregister(struct rte_auxiliary_driver *driver)
178 : : {
179 : 301 : rte_bus_remove_driver(&auxiliary_bus, &driver->driver);
180 : 301 : }
181 : :
182 : : static void
183 : 0 : auxiliary_free_device(struct rte_device *dev)
184 : : {
185 : 0 : free(RTE_BUS_DEVICE(dev, struct rte_auxiliary_device));
186 : 0 : }
187 : :
188 : : static int
189 : 0 : auxiliary_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
190 : : {
191 : : struct rte_auxiliary_device *aux_dev = RTE_BUS_DEVICE(dev, *aux_dev);
192 : 0 : const struct rte_auxiliary_driver *aux_drv = RTE_BUS_DRIVER(dev->driver, *aux_drv);
193 : :
194 [ # # ]: 0 : if (aux_drv->dma_map == NULL) {
195 : 0 : rte_errno = ENOTSUP;
196 : 0 : return -1;
197 : : }
198 : 0 : return aux_drv->dma_map(aux_dev, addr, iova, len);
199 : : }
200 : :
201 : : static int
202 : 0 : auxiliary_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova,
203 : : size_t len)
204 : : {
205 : : struct rte_auxiliary_device *aux_dev = RTE_BUS_DEVICE(dev, *aux_dev);
206 : 0 : const struct rte_auxiliary_driver *aux_drv = RTE_BUS_DRIVER(dev->driver, *aux_drv);
207 : :
208 [ # # ]: 0 : if (aux_drv->dma_unmap == NULL) {
209 : 0 : rte_errno = ENOTSUP;
210 : 0 : return -1;
211 : : }
212 : 0 : return aux_drv->dma_unmap(aux_dev, addr, iova, len);
213 : : }
214 : :
215 : : static enum rte_iova_mode
216 : 225 : auxiliary_get_iommu_class(void)
217 : : {
218 : : const struct rte_auxiliary_driver *drv;
219 : :
220 [ + + ]: 450 : RTE_BUS_FOREACH_DRV(drv, &auxiliary_bus) {
221 [ + - ]: 225 : if ((drv->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0)
222 : : return RTE_IOVA_VA;
223 : : }
224 : :
225 : : return RTE_IOVA_DC;
226 : : }
227 : :
228 : : struct rte_bus auxiliary_bus = {
229 : : .scan = auxiliary_scan,
230 : : .probe = rte_bus_generic_probe,
231 : : .free_device = auxiliary_free_device,
232 : : .cleanup = rte_bus_generic_cleanup,
233 : : .find_device = rte_bus_generic_find_device,
234 : : .match = auxiliary_bus_match,
235 : : .probe_device = auxiliary_probe_device,
236 : : .unplug_device = auxiliary_unplug_device,
237 : : .parse = auxiliary_parse,
238 : : .dma_map = auxiliary_dma_map,
239 : : .dma_unmap = auxiliary_dma_unmap,
240 : : .get_iommu_class = auxiliary_get_iommu_class,
241 : : .dev_iterate = rte_bus_generic_dev_iterate,
242 : : };
243 : :
244 : 301 : RTE_REGISTER_BUS(auxiliary, auxiliary_bus);
245 [ - + ]: 301 : RTE_LOG_REGISTER_DEFAULT(auxiliary_bus_logtype, NOTICE);
|