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