xref: /dpdk/lib/eal/common/eal_common_bus.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
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_string_fns.h>
12 #include <rte_errno.h>
13 
14 #include "eal_private.h"
15 
16 static struct rte_bus_list rte_bus_list =
17 	TAILQ_HEAD_INITIALIZER(rte_bus_list);
18 
19 const char *
rte_bus_name(const struct rte_bus * bus)20 rte_bus_name(const struct rte_bus *bus)
21 {
22 	return bus->name;
23 }
24 
25 void
rte_bus_register(struct rte_bus * bus)26 rte_bus_register(struct rte_bus *bus)
27 {
28 	RTE_VERIFY(bus);
29 	RTE_VERIFY(rte_bus_name(bus) && strlen(rte_bus_name(bus)));
30 	/* A bus should mandatorily have the scan implemented */
31 	RTE_VERIFY(bus->scan);
32 	RTE_VERIFY(bus->probe);
33 	RTE_VERIFY(bus->find_device);
34 	/* Buses supporting driver plug also require unplug. */
35 	RTE_VERIFY(!bus->plug || bus->unplug);
36 
37 	TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
38 	EAL_LOG(DEBUG, "Registered [%s] bus.", rte_bus_name(bus));
39 }
40 
41 void
rte_bus_unregister(struct rte_bus * bus)42 rte_bus_unregister(struct rte_bus *bus)
43 {
44 	TAILQ_REMOVE(&rte_bus_list, bus, next);
45 	EAL_LOG(DEBUG, "Unregistered [%s] bus.", rte_bus_name(bus));
46 }
47 
48 /* Scan all the buses for registered devices */
49 int
rte_bus_scan(void)50 rte_bus_scan(void)
51 {
52 	int ret;
53 	struct rte_bus *bus = NULL;
54 
55 	TAILQ_FOREACH(bus, &rte_bus_list, next) {
56 		ret = bus->scan();
57 		if (ret)
58 			EAL_LOG(ERR, "Scan for (%s) bus failed.",
59 				rte_bus_name(bus));
60 	}
61 
62 	return 0;
63 }
64 
65 /* Probe all devices of all buses */
66 int
rte_bus_probe(void)67 rte_bus_probe(void)
68 {
69 	int ret;
70 	struct rte_bus *bus, *vbus = NULL;
71 
72 	TAILQ_FOREACH(bus, &rte_bus_list, next) {
73 		if (!strcmp(rte_bus_name(bus), "vdev")) {
74 			vbus = bus;
75 			continue;
76 		}
77 
78 		ret = bus->probe();
79 		if (ret)
80 			EAL_LOG(ERR, "Bus (%s) probe failed.",
81 				rte_bus_name(bus));
82 	}
83 
84 	if (vbus) {
85 		ret = vbus->probe();
86 		if (ret)
87 			EAL_LOG(ERR, "Bus (%s) probe failed.",
88 				rte_bus_name(vbus));
89 	}
90 
91 	return 0;
92 }
93 
94 /* Clean up all devices of all buses */
95 int
eal_bus_cleanup(void)96 eal_bus_cleanup(void)
97 {
98 	int ret = 0;
99 	struct rte_bus *bus;
100 
101 	TAILQ_FOREACH(bus, &rte_bus_list, next) {
102 		if (bus->cleanup == NULL)
103 			continue;
104 		if (bus->cleanup() != 0)
105 			ret = -1;
106 	}
107 
108 	return ret;
109 }
110 
111 /* Dump information of a single bus */
112 static int
bus_dump_one(FILE * f,struct rte_bus * bus)113 bus_dump_one(FILE *f, struct rte_bus *bus)
114 {
115 	int ret;
116 
117 	/* For now, dump only the bus name */
118 	ret = fprintf(f, " %s\n", rte_bus_name(bus));
119 
120 	/* Error in case of inability in writing to stream */
121 	if (ret < 0)
122 		return ret;
123 
124 	return 0;
125 }
126 
127 void
rte_bus_dump(FILE * f)128 rte_bus_dump(FILE *f)
129 {
130 	int ret;
131 	struct rte_bus *bus;
132 
133 	TAILQ_FOREACH(bus, &rte_bus_list, next) {
134 		ret = bus_dump_one(f, bus);
135 		if (ret) {
136 			EAL_LOG(ERR, "Unable to write to stream (%d)",
137 				ret);
138 			break;
139 		}
140 	}
141 }
142 
143 struct rte_bus *
rte_bus_find(const struct rte_bus * start,rte_bus_cmp_t cmp,const void * data)144 rte_bus_find(const struct rte_bus *start, rte_bus_cmp_t cmp,
145 	     const void *data)
146 {
147 	struct rte_bus *bus;
148 
149 	if (start != NULL)
150 		bus = TAILQ_NEXT(start, next);
151 	else
152 		bus = TAILQ_FIRST(&rte_bus_list);
153 	while (bus != NULL) {
154 		if (cmp(bus, data) == 0)
155 			break;
156 		bus = TAILQ_NEXT(bus, next);
157 	}
158 	return bus;
159 }
160 
161 static int
cmp_rte_device(const struct rte_device * dev1,const void * _dev2)162 cmp_rte_device(const struct rte_device *dev1, const void *_dev2)
163 {
164 	const struct rte_device *dev2 = _dev2;
165 
166 	return dev1 != dev2;
167 }
168 
169 static int
bus_find_device(const struct rte_bus * bus,const void * _dev)170 bus_find_device(const struct rte_bus *bus, const void *_dev)
171 {
172 	struct rte_device *dev;
173 
174 	dev = bus->find_device(NULL, cmp_rte_device, _dev);
175 	return dev == NULL;
176 }
177 
178 struct rte_bus *
rte_bus_find_by_device(const struct rte_device * dev)179 rte_bus_find_by_device(const struct rte_device *dev)
180 {
181 	return rte_bus_find(NULL, bus_find_device, (const void *)dev);
182 }
183 
184 static int
cmp_bus_name(const struct rte_bus * bus,const void * _name)185 cmp_bus_name(const struct rte_bus *bus, const void *_name)
186 {
187 	const char *name = _name;
188 
189 	return strcmp(rte_bus_name(bus), name);
190 }
191 
192 struct rte_bus *
rte_bus_find_by_name(const char * busname)193 rte_bus_find_by_name(const char *busname)
194 {
195 	return rte_bus_find(NULL, cmp_bus_name, (const void *)busname);
196 }
197 
198 static int
bus_can_parse(const struct rte_bus * bus,const void * _name)199 bus_can_parse(const struct rte_bus *bus, const void *_name)
200 {
201 	const char *name = _name;
202 
203 	return !(bus->parse && bus->parse(name, NULL) == 0);
204 }
205 
206 struct rte_bus *
rte_bus_find_by_device_name(const char * str)207 rte_bus_find_by_device_name(const char *str)
208 {
209 	char name[RTE_DEV_NAME_MAX_LEN];
210 	char *c;
211 
212 	strlcpy(name, str, sizeof(name));
213 	c = strchr(name, ',');
214 	if (c != NULL)
215 		c[0] = '\0';
216 	return rte_bus_find(NULL, bus_can_parse, name);
217 }
218 
219 
220 /*
221  * Get iommu class of devices on the bus.
222  */
223 enum rte_iova_mode
rte_bus_get_iommu_class(void)224 rte_bus_get_iommu_class(void)
225 {
226 	enum rte_iova_mode mode = RTE_IOVA_DC;
227 	bool buses_want_va = false;
228 	bool buses_want_pa = false;
229 	struct rte_bus *bus;
230 
231 	TAILQ_FOREACH(bus, &rte_bus_list, next) {
232 		enum rte_iova_mode bus_iova_mode;
233 
234 		if (bus->get_iommu_class == NULL)
235 			continue;
236 
237 		bus_iova_mode = bus->get_iommu_class();
238 		EAL_LOG(DEBUG, "Bus %s wants IOVA as '%s'",
239 			rte_bus_name(bus),
240 			bus_iova_mode == RTE_IOVA_DC ? "DC" :
241 			(bus_iova_mode == RTE_IOVA_PA ? "PA" : "VA"));
242 		if (bus_iova_mode == RTE_IOVA_PA) {
243 			buses_want_pa = true;
244 			if (!RTE_IOVA_IN_MBUF)
245 				EAL_LOG(WARNING,
246 					"Bus %s wants IOVA as PA not compatible with 'enable_iova_as_pa=false' build option.",
247 					rte_bus_name(bus));
248 		} else if (bus_iova_mode == RTE_IOVA_VA)
249 			buses_want_va = true;
250 	}
251 	if (buses_want_va && !buses_want_pa) {
252 		mode = RTE_IOVA_VA;
253 	} else if (buses_want_pa && !buses_want_va) {
254 		mode = RTE_IOVA_PA;
255 	} else {
256 		mode = RTE_IOVA_DC;
257 		if (buses_want_va) {
258 			EAL_LOG(WARNING, "Some buses want 'VA' but forcing 'DC' because other buses want 'PA'.");
259 			EAL_LOG(WARNING, "Depending on the final decision by the EAL, not all buses may be able to initialize.");
260 		}
261 	}
262 
263 	return mode;
264 }
265 
266 static int
bus_handle_sigbus(const struct rte_bus * bus,const void * failure_addr)267 bus_handle_sigbus(const struct rte_bus *bus,
268 			const void *failure_addr)
269 {
270 	int ret;
271 
272 	if (!bus->sigbus_handler)
273 		return -1;
274 
275 	ret = bus->sigbus_handler(failure_addr);
276 
277 	/* find bus but handle failed, keep the errno be set. */
278 	if (ret < 0 && rte_errno == 0)
279 		rte_errno = ENOTSUP;
280 
281 	return ret > 0;
282 }
283 
284 int
rte_bus_sigbus_handler(const void * failure_addr)285 rte_bus_sigbus_handler(const void *failure_addr)
286 {
287 	struct rte_bus *bus;
288 
289 	int ret = 0;
290 	int old_errno = rte_errno;
291 
292 	rte_errno = 0;
293 
294 	bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr);
295 	/* can not find bus. */
296 	if (!bus)
297 		return 1;
298 	/* find bus but handle failed, pass on the new errno. */
299 	else if (rte_errno != 0)
300 		return -1;
301 
302 	/* restore the old errno. */
303 	rte_errno = old_errno;
304 
305 	return ret;
306 }
307