Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2016 NXP
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <string.h>
7 : : #include <sys/queue.h>
8 : :
9 : : #include <bus_driver.h>
10 : : #include <rte_debug.h>
11 : : #include <rte_devargs.h>
12 : : #include <rte_string_fns.h>
13 : : #include <rte_errno.h>
14 : :
15 : : #include <eal_export.h>
16 : : #include "eal_private.h"
17 : :
18 : : static struct rte_bus_list rte_bus_list =
19 : : TAILQ_HEAD_INITIALIZER(rte_bus_list);
20 : :
21 : : RTE_EXPORT_SYMBOL(rte_bus_name)
22 : : const char *
23 : 32073 : rte_bus_name(const struct rte_bus *bus)
24 : : {
25 : 32073 : return bus->name;
26 : : }
27 : :
28 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_register)
29 : : void
30 : 3124 : rte_bus_register(struct rte_bus *bus)
31 : : {
32 [ - + ]: 3124 : RTE_VERIFY(bus);
33 [ + - - + ]: 3124 : RTE_VERIFY(rte_bus_name(bus) && strlen(rte_bus_name(bus)));
34 : : /* A bus should mandatorily have the scan implemented */
35 [ - + ]: 3124 : RTE_VERIFY(bus->scan);
36 [ - + ]: 3124 : RTE_VERIFY(bus->probe);
37 [ - + ]: 3124 : RTE_VERIFY(bus->find_device);
38 : : /* Buses supporting driver plug also require unplug. */
39 [ + + - + ]: 3124 : RTE_VERIFY(!bus->plug || bus->unplug);
40 : :
41 : 3124 : TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
42 : 3124 : EAL_LOG(DEBUG, "Registered [%s] bus.", rte_bus_name(bus));
43 : 3124 : }
44 : :
45 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_unregister)
46 : : void
47 : 0 : rte_bus_unregister(struct rte_bus *bus)
48 : : {
49 [ # # ]: 0 : TAILQ_REMOVE(&rte_bus_list, bus, next);
50 : 0 : EAL_LOG(DEBUG, "Unregistered [%s] bus.", rte_bus_name(bus));
51 : 0 : }
52 : :
53 : : /* Scan all the buses for registered devices */
54 : : RTE_EXPORT_SYMBOL(rte_bus_scan)
55 : : int
56 : 216 : rte_bus_scan(void)
57 : : {
58 : : int ret;
59 : : struct rte_bus *bus = NULL;
60 : :
61 [ + + ]: 2592 : TAILQ_FOREACH(bus, &rte_bus_list, next) {
62 : 2376 : ret = bus->scan();
63 [ - + ]: 2376 : if (ret)
64 : 0 : EAL_LOG(ERR, "Scan for (%s) bus failed.",
65 : : rte_bus_name(bus));
66 : : }
67 : :
68 : 216 : return 0;
69 : : }
70 : :
71 : : /* Probe all devices of all buses */
72 : : RTE_EXPORT_SYMBOL(rte_bus_probe)
73 : : int
74 : 211 : rte_bus_probe(void)
75 : : {
76 : : int ret;
77 : : struct rte_bus *bus, *vbus = NULL;
78 : :
79 [ + + ]: 2532 : TAILQ_FOREACH(bus, &rte_bus_list, next) {
80 [ + + ]: 2321 : if (!strcmp(rte_bus_name(bus), "vdev")) {
81 : : vbus = bus;
82 : 211 : continue;
83 : : }
84 : :
85 : 2110 : ret = bus->probe();
86 [ - + ]: 2110 : if (ret)
87 : 0 : EAL_LOG(ERR, "Bus (%s) probe failed.",
88 : : rte_bus_name(bus));
89 : : }
90 : :
91 [ + - ]: 211 : if (vbus) {
92 : 211 : ret = vbus->probe();
93 [ - + ]: 211 : if (ret)
94 : 0 : EAL_LOG(ERR, "Bus (%s) probe failed.",
95 : : rte_bus_name(vbus));
96 : : }
97 : :
98 : 211 : return 0;
99 : : }
100 : :
101 : : /* Clean up all devices of all buses */
102 : : int
103 : 277 : eal_bus_cleanup(void)
104 : : {
105 : : int ret = 0;
106 : : struct rte_bus *bus;
107 : :
108 [ + + ]: 3324 : TAILQ_FOREACH(bus, &rte_bus_list, next) {
109 [ + + ]: 3047 : if (bus->cleanup == NULL)
110 : 554 : continue;
111 [ - + ]: 2493 : if (bus->cleanup() != 0)
112 : : ret = -1;
113 : : }
114 : :
115 : 277 : return ret;
116 : : }
117 : :
118 : : /* Dump information of a single bus */
119 : : static int
120 : 0 : bus_dump_one(FILE *f, struct rte_bus *bus)
121 : : {
122 : : int ret;
123 : :
124 : : /* For now, dump only the bus name */
125 : 0 : ret = fprintf(f, " %s\n", rte_bus_name(bus));
126 : :
127 : : /* Error in case of inability in writing to stream */
128 : : if (ret < 0)
129 : : return ret;
130 : :
131 : : return 0;
132 : : }
133 : :
134 : : RTE_EXPORT_SYMBOL(rte_bus_dump)
135 : : void
136 : 0 : rte_bus_dump(FILE *f)
137 : : {
138 : : int ret;
139 : : struct rte_bus *bus;
140 : :
141 [ # # ]: 0 : TAILQ_FOREACH(bus, &rte_bus_list, next) {
142 : 0 : ret = bus_dump_one(f, bus);
143 [ # # ]: 0 : if (ret) {
144 : 0 : EAL_LOG(ERR, "Unable to write to stream (%d)",
145 : : ret);
146 : 0 : break;
147 : : }
148 : : }
149 : 0 : }
150 : :
151 : : RTE_EXPORT_SYMBOL(rte_bus_find)
152 : : struct rte_bus *
153 : 105 : rte_bus_find(const struct rte_bus *start, rte_bus_cmp_t cmp,
154 : : const void *data)
155 : : {
156 : : struct rte_bus *bus;
157 : :
158 [ + + ]: 105 : if (start != NULL)
159 : 3 : bus = TAILQ_NEXT(start, next);
160 : : else
161 : 102 : bus = TAILQ_FIRST(&rte_bus_list);
162 [ + + ]: 1044 : while (bus != NULL) {
163 [ + + ]: 986 : if (cmp(bus, data) == 0)
164 : : break;
165 : 939 : bus = TAILQ_NEXT(bus, next);
166 : : }
167 : 105 : return bus;
168 : : }
169 : :
170 : : static int
171 : 0 : cmp_rte_device(const struct rte_device *dev1, const void *_dev2)
172 : : {
173 : : const struct rte_device *dev2 = _dev2;
174 : :
175 : 0 : return dev1 != dev2;
176 : : }
177 : :
178 : : static int
179 : 0 : bus_find_device(const struct rte_bus *bus, const void *_dev)
180 : : {
181 : : struct rte_device *dev;
182 : :
183 : 0 : dev = bus->find_device(NULL, cmp_rte_device, _dev);
184 : 0 : return dev == NULL;
185 : : }
186 : :
187 : : RTE_EXPORT_SYMBOL(rte_bus_find_by_device)
188 : : struct rte_bus *
189 : 0 : rte_bus_find_by_device(const struct rte_device *dev)
190 : : {
191 : 0 : return rte_bus_find(NULL, bus_find_device, (const void *)dev);
192 : : }
193 : :
194 : : static int
195 : 152 : cmp_bus_name(const struct rte_bus *bus, const void *_name)
196 : : {
197 : : const char *name = _name;
198 : :
199 : 152 : return strcmp(rte_bus_name(bus), name);
200 : : }
201 : :
202 : : RTE_EXPORT_SYMBOL(rte_bus_find_by_name)
203 : : struct rte_bus *
204 : 18 : rte_bus_find_by_name(const char *busname)
205 : : {
206 : 18 : return rte_bus_find(NULL, cmp_bus_name, (const void *)busname);
207 : : }
208 : :
209 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_find_devargs)
210 : : struct rte_devargs *
211 : 18114 : rte_bus_find_devargs(const struct rte_bus *bus, const char *name)
212 : : {
213 : 18114 : rte_bus_dev_compare_t cmp = bus->dev_compare;
214 : 18114 : const char *bus_name = rte_bus_name(bus);
215 : : struct rte_devargs *devargs;
216 : :
217 [ + + ]: 18114 : if (cmp == NULL)
218 : : cmp = strcmp;
219 : :
220 [ + + ]: 18627 : RTE_EAL_DEVARGS_FOREACH(bus_name, devargs) {
221 : 516 : const char *devargs_name = devargs->name;
222 : :
223 : : /* The name in the devargs is usually prefixed with <bus>: */
224 [ - + ]: 516 : if (strncmp(devargs_name, bus_name, strlen(bus_name)) == 0)
225 : 0 : devargs_name += strlen(bus_name) + 1;
226 [ + + ]: 516 : if (cmp(name, devargs_name) != 0)
227 : : continue;
228 : 3 : EAL_LOG(DEBUG, "found devargs for %s:%s", bus_name, name);
229 : 3 : return devargs;
230 : : }
231 : :
232 : 18111 : EAL_LOG(DEBUG, "no devargs for %s:%s", bus_name, name);
233 : 18111 : return NULL;
234 : : }
235 : :
236 : : static int
237 : 372 : bus_can_parse(const struct rte_bus *bus, const void *_name)
238 : : {
239 : : const char *name = _name;
240 : :
241 [ + - + + ]: 372 : return !(bus->parse && bus->parse(name, NULL) == 0);
242 : : }
243 : :
244 : : struct rte_bus *
245 [ + + ]: 42 : rte_bus_find_by_device_name(const char *str)
246 : : {
247 : : char name[RTE_DEV_NAME_MAX_LEN];
248 : : char *c;
249 : :
250 : : strlcpy(name, str, sizeof(name));
251 : 42 : c = strchr(name, ',');
252 [ + + ]: 42 : if (c != NULL)
253 : 1 : c[0] = '\0';
254 : 42 : return rte_bus_find(NULL, bus_can_parse, name);
255 : : }
256 : :
257 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_device_is_ignored)
258 : : bool
259 : 10417 : rte_bus_device_is_ignored(const struct rte_bus *bus, const char *dev_name)
260 : : {
261 : 10417 : const struct internal_config *internal_conf = eal_get_internal_configuration();
262 : 10417 : struct rte_devargs *devargs = rte_bus_find_devargs(bus, dev_name);
263 : 10417 : enum rte_bus_scan_mode scan_mode = bus->conf.scan_mode;
264 : :
265 [ + + ]: 10417 : if (scan_mode == RTE_BUS_SCAN_UNDEFINED) {
266 [ + + ]: 10073 : if (internal_conf->no_auto_probing != 0)
267 : : scan_mode = RTE_BUS_SCAN_ALLOWLIST;
268 : : else
269 : : scan_mode = RTE_BUS_SCAN_BLOCKLIST;
270 : : }
271 : :
272 [ + + ]: 344 : if (scan_mode == RTE_BUS_SCAN_ALLOWLIST) {
273 [ + + - + ]: 377 : if (devargs && devargs->policy == RTE_DEV_ALLOWED)
274 : : return false;
275 : : } else {
276 [ + + + - ]: 10040 : if (devargs == NULL || devargs->policy != RTE_DEV_BLOCKED)
277 : : return false;
278 : : }
279 : :
280 : 377 : EAL_LOG(DEBUG, "device %s:%s is ignored", rte_bus_name(bus), dev_name);
281 : 377 : return true;
282 : : }
283 : :
284 : : /*
285 : : * Get iommu class of devices on the bus.
286 : : */
287 : : RTE_EXPORT_SYMBOL(rte_bus_get_iommu_class)
288 : : enum rte_iova_mode
289 : 216 : rte_bus_get_iommu_class(void)
290 : : {
291 : : enum rte_iova_mode mode = RTE_IOVA_DC;
292 : : bool buses_want_va = false;
293 : : bool buses_want_pa = false;
294 : : struct rte_bus *bus;
295 : :
296 [ + + ]: 2592 : TAILQ_FOREACH(bus, &rte_bus_list, next) {
297 : : enum rte_iova_mode bus_iova_mode;
298 : :
299 [ + + ]: 2376 : if (bus->get_iommu_class == NULL)
300 : 648 : continue;
301 : :
302 : 1728 : bus_iova_mode = bus->get_iommu_class();
303 [ + + + - ]: 1729 : EAL_LOG(DEBUG, "Bus %s wants IOVA as '%s'",
304 : : rte_bus_name(bus),
305 : : bus_iova_mode == RTE_IOVA_DC ? "DC" :
306 : : (bus_iova_mode == RTE_IOVA_PA ? "PA" : "VA"));
307 [ + - ]: 1728 : if (bus_iova_mode == RTE_IOVA_PA) {
308 : : buses_want_pa = true;
309 : : if (!RTE_IOVA_IN_MBUF)
310 : : EAL_LOG(WARNING,
311 : : "Bus %s wants IOVA as PA not compatible with 'enable_iova_as_pa=false' build option.",
312 : : rte_bus_name(bus));
313 [ + + ]: 1728 : } else if (bus_iova_mode == RTE_IOVA_VA)
314 : : buses_want_va = true;
315 : : }
316 [ + + ]: 216 : if (buses_want_va && !buses_want_pa) {
317 : : mode = RTE_IOVA_VA;
318 [ + - ]: 215 : } else if (buses_want_pa && !buses_want_va) {
319 : : mode = RTE_IOVA_PA;
320 : : } else {
321 : : mode = RTE_IOVA_DC;
322 [ - + ]: 215 : if (buses_want_va) {
323 : 0 : EAL_LOG(WARNING, "Some buses want 'VA' but forcing 'DC' because other buses want 'PA'.");
324 : 0 : EAL_LOG(WARNING, "Depending on the final decision by the EAL, not all buses may be able to initialize.");
325 : : }
326 : : }
327 : :
328 : 216 : return mode;
329 : : }
330 : :
331 : : static int
332 : 0 : bus_handle_sigbus(const struct rte_bus *bus,
333 : : const void *failure_addr)
334 : : {
335 : : int ret;
336 : :
337 [ # # ]: 0 : if (!bus->sigbus_handler)
338 : : return -1;
339 : :
340 : 0 : ret = bus->sigbus_handler(failure_addr);
341 : :
342 : : /* find bus but handle failed, keep the errno be set. */
343 [ # # # # ]: 0 : if (ret < 0 && rte_errno == 0)
344 : 0 : rte_errno = ENOTSUP;
345 : :
346 : 0 : return ret > 0;
347 : : }
348 : :
349 : : int
350 : 0 : rte_bus_sigbus_handler(const void *failure_addr)
351 : : {
352 : : struct rte_bus *bus;
353 : :
354 : : int ret = 0;
355 : 0 : int old_errno = rte_errno;
356 : :
357 : 0 : rte_errno = 0;
358 : :
359 : 0 : bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr);
360 : : /* can not find bus. */
361 [ # # ]: 0 : if (!bus)
362 : : return 1;
363 : : /* find bus but handle failed, pass on the new errno. */
364 [ # # ]: 0 : else if (rte_errno != 0)
365 : : return -1;
366 : :
367 : : /* restore the old errno. */
368 : 0 : rte_errno = old_errno;
369 : :
370 : 0 : return ret;
371 : : }
|