File: | home/bhubbard/working/src/ceph/src/spdk/dpdk/lib/librte_eal/common/eal_common_dev.c |
Warning: | line 312, column 6 Access to field 'bus' results in a dereference of a null pointer (loaded from variable 'dev') |
[?] Use j/k keys for keyboard navigation
1 | /* SPDX-License-Identifier: BSD-3-Clause | |||
2 | * Copyright(c) 2010-2014 Intel Corporation. | |||
3 | * Copyright(c) 2014 6WIND S.A. | |||
4 | */ | |||
5 | ||||
6 | #include <stdio.h> | |||
7 | #include <string.h> | |||
8 | #include <inttypes.h> | |||
9 | #include <sys/queue.h> | |||
10 | ||||
11 | #include <rte_compat.h> | |||
12 | #include <rte_bus.h> | |||
13 | #include <rte_class.h> | |||
14 | #include <rte_dev.h> | |||
15 | #include <rte_devargs.h> | |||
16 | #include <rte_debug.h> | |||
17 | #include <rte_errno(per_lcore__rte_errno).h> | |||
18 | #include <rte_kvargs.h> | |||
19 | #include <rte_log.h> | |||
20 | #include <rte_spinlock.h> | |||
21 | #include <rte_malloc.h> | |||
22 | #include <rte_string_fns.h> | |||
23 | ||||
24 | #include "eal_private.h" | |||
25 | #include "hotplug_mp.h" | |||
26 | ||||
27 | /** | |||
28 | * The device event callback description. | |||
29 | * | |||
30 | * It contains callback address to be registered by user application, | |||
31 | * the pointer to the parameters for callback, and the device name. | |||
32 | */ | |||
33 | struct dev_event_callback { | |||
34 | TAILQ_ENTRY(dev_event_callback)struct { struct dev_event_callback *tqe_next; struct dev_event_callback * *tqe_prev; } next; /**< Callbacks list */ | |||
35 | rte_dev_event_cb_fn cb_fn; /**< Callback address */ | |||
36 | void *cb_arg; /**< Callback parameter */ | |||
37 | char *dev_name; /**< Callback device name, NULL is for all device */ | |||
38 | uint32_t active; /**< Callback is executing */ | |||
39 | }; | |||
40 | ||||
41 | /** @internal Structure to keep track of registered callbacks */ | |||
42 | TAILQ_HEAD(dev_event_cb_list, dev_event_callback)struct dev_event_cb_list { struct dev_event_callback *tqh_first ; struct dev_event_callback * *tqh_last; }; | |||
43 | ||||
44 | /* The device event callback list for all registered callbacks. */ | |||
45 | static struct dev_event_cb_list dev_event_cbs; | |||
46 | ||||
47 | /* spinlock for device callbacks */ | |||
48 | static rte_spinlock_t dev_event_lock = RTE_SPINLOCK_INITIALIZER{ 0 }; | |||
49 | ||||
50 | struct dev_next_ctx { | |||
51 | struct rte_dev_iterator *it; | |||
52 | const char *bus_str; | |||
53 | const char *cls_str; | |||
54 | }; | |||
55 | ||||
56 | #define CTX(it, bus_str, cls_str)(&(const struct dev_next_ctx){ .it = it, .bus_str = bus_str , .cls_str = cls_str, }) \ | |||
57 | (&(const struct dev_next_ctx){ \ | |||
58 | .it = it, \ | |||
59 | .bus_str = bus_str, \ | |||
60 | .cls_str = cls_str, \ | |||
61 | }) | |||
62 | ||||
63 | #define ITCTX(ptr)(((struct dev_next_ctx *)(intptr_t)ptr)->it) \ | |||
64 | (((struct dev_next_ctx *)(intptr_t)ptr)->it) | |||
65 | ||||
66 | #define BUSCTX(ptr)(((struct dev_next_ctx *)(intptr_t)ptr)->bus_str) \ | |||
67 | (((struct dev_next_ctx *)(intptr_t)ptr)->bus_str) | |||
68 | ||||
69 | #define CLSCTX(ptr)(((struct dev_next_ctx *)(intptr_t)ptr)->cls_str) \ | |||
70 | (((struct dev_next_ctx *)(intptr_t)ptr)->cls_str) | |||
71 | ||||
72 | static int cmp_dev_name(const struct rte_device *dev, const void *_name) | |||
73 | { | |||
74 | const char *name = _name; | |||
75 | ||||
76 | return strcmp(dev->name, name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (dev->name) && __builtin_constant_p (name) && (__s1_len = __builtin_strlen (dev->name), __s2_len = __builtin_strlen (name), (!((size_t)(const void *)((dev->name) + 1) - (size_t )(const void *)(dev->name) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((name) + 1) - (size_t)(const void * )(name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (dev-> name, name) : (__builtin_constant_p (dev->name) && ((size_t)(const void *)((dev->name) + 1) - (size_t)(const void *)(dev->name) == 1) && (__s1_len = __builtin_strlen (dev->name), __s1_len < 4) ? (__builtin_constant_p (name ) && ((size_t)(const void *)((name) + 1) - (size_t)(const void *)(name) == 1) ? __builtin_strcmp (dev->name, name) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (name); int __result = (((const unsigned char *) (const char *) (dev->name))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (dev->name))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (dev->name))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (dev->name))[3] - __s2[3]); } } __result ; }))) : (__builtin_constant_p (name) && ((size_t)(const void *)((name) + 1) - (size_t)(const void *)(name) == 1) && (__s2_len = __builtin_strlen (name), __s2_len < 4) ? (__builtin_constant_p (dev->name) && ((size_t)(const void *)((dev->name ) + 1) - (size_t)(const void *)(dev->name) == 1) ? __builtin_strcmp (dev->name, name) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (dev->name ); int __result = (((const unsigned char *) (const char *) (name ))[0] - __s2[0]); if (__s2_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (name ))[1] - __s2[1]); if (__s2_len > 1 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (name ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (name)) [3] - __s2[3]); } } __result; })))) : __builtin_strcmp (dev-> name, name)))); }); | |||
77 | } | |||
78 | ||||
79 | int | |||
80 | rte_dev_is_probed(const struct rte_device *dev) | |||
81 | { | |||
82 | /* The field driver should be set only when the probe is successful. */ | |||
83 | return dev->driver != NULL((void*)0); | |||
84 | } | |||
85 | ||||
86 | /* helper function to build devargs, caller should free the memory */ | |||
87 | static int | |||
88 | build_devargs(const char *busname, const char *devname, | |||
89 | const char *drvargs, char **devargs) | |||
90 | { | |||
91 | int length; | |||
92 | ||||
93 | length = snprintf(NULL((void*)0), 0, "%s:%s,%s", busname, devname, drvargs); | |||
94 | if (length < 0) | |||
95 | return -EINVAL22; | |||
96 | ||||
97 | *devargs = malloc(length + 1); | |||
98 | if (*devargs == NULL((void*)0)) | |||
99 | return -ENOMEM12; | |||
100 | ||||
101 | length = snprintf(*devargs, length + 1, "%s:%s,%s", | |||
102 | busname, devname, drvargs); | |||
103 | if (length < 0) { | |||
104 | free(*devargs); | |||
105 | return -EINVAL22; | |||
106 | } | |||
107 | ||||
108 | return 0; | |||
109 | } | |||
110 | ||||
111 | int | |||
112 | rte_eal_hotplug_add(const char *busname, const char *devname, | |||
113 | const char *drvargs) | |||
114 | { | |||
115 | ||||
116 | char *devargs; | |||
117 | int ret; | |||
118 | ||||
119 | ret = build_devargs(busname, devname, drvargs, &devargs); | |||
120 | if (ret != 0) | |||
| ||||
121 | return ret; | |||
122 | ||||
123 | ret = rte_dev_probe(devargs); | |||
124 | free(devargs); | |||
125 | ||||
126 | return ret; | |||
127 | } | |||
128 | ||||
129 | /* probe device at local process. */ | |||
130 | int | |||
131 | local_dev_probe(const char *devargs, struct rte_device **new_dev) | |||
132 | { | |||
133 | struct rte_device *dev; | |||
134 | struct rte_devargs *da; | |||
135 | int ret; | |||
136 | ||||
137 | *new_dev = NULL((void*)0); | |||
138 | da = calloc(1, sizeof(*da)); | |||
139 | if (da == NULL((void*)0)) | |||
140 | return -ENOMEM12; | |||
141 | ||||
142 | ret = rte_devargs_parse(da, devargs); | |||
143 | if (ret) | |||
144 | goto err_devarg; | |||
145 | ||||
146 | if (da->bus->plug == NULL((void*)0)) { | |||
147 | RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)\n",rte_log(4U, 0, "EAL" ": " "Function plug not supported by bus (%s)\n" , da->bus->name) | |||
148 | da->bus->name)rte_log(4U, 0, "EAL" ": " "Function plug not supported by bus (%s)\n" , da->bus->name); | |||
149 | ret = -ENOTSUP95; | |||
150 | goto err_devarg; | |||
151 | } | |||
152 | ||||
153 | ret = rte_devargs_insert(&da); | |||
154 | if (ret) | |||
155 | goto err_devarg; | |||
156 | ||||
157 | /* the rte_devargs will be referenced in the matching rte_device */ | |||
158 | ret = da->bus->scan(); | |||
159 | if (ret) | |||
160 | goto err_devarg; | |||
161 | ||||
162 | dev = da->bus->find_device(NULL((void*)0), cmp_dev_name, da->name); | |||
163 | if (dev == NULL((void*)0)) { | |||
164 | RTE_LOG(ERR, EAL, "Cannot find device (%s)\n",rte_log(4U, 0, "EAL" ": " "Cannot find device (%s)\n", da-> name) | |||
165 | da->name)rte_log(4U, 0, "EAL" ": " "Cannot find device (%s)\n", da-> name); | |||
166 | ret = -ENODEV19; | |||
167 | goto err_devarg; | |||
168 | } | |||
169 | /* Since there is a matching device, it is now its responsibility | |||
170 | * to manage the devargs we've just inserted. From this point | |||
171 | * those devargs shouldn't be removed manually anymore. | |||
172 | */ | |||
173 | ||||
174 | ret = dev->bus->plug(dev); | |||
175 | if (ret && !rte_dev_is_probed(dev)) { /* if hasn't ever succeeded */ | |||
176 | RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n",rte_log(4U, 0, "EAL" ": " "Driver cannot attach the device (%s)\n" , dev->name) | |||
177 | dev->name)rte_log(4U, 0, "EAL" ": " "Driver cannot attach the device (%s)\n" , dev->name); | |||
178 | return ret; | |||
179 | } | |||
180 | ||||
181 | *new_dev = dev; | |||
182 | return ret; | |||
183 | ||||
184 | err_devarg: | |||
185 | if (rte_devargs_remove(da) != 0) { | |||
186 | free(da->args); | |||
187 | free(da); | |||
188 | } | |||
189 | return ret; | |||
190 | } | |||
191 | ||||
192 | int | |||
193 | rte_dev_probe(const char *devargs) | |||
194 | { | |||
195 | struct eal_dev_mp_req req; | |||
196 | struct rte_device *dev; | |||
197 | int ret; | |||
198 | ||||
199 | memset(&req, 0, sizeof(req)); | |||
200 | req.t = EAL_DEV_REQ_TYPE_ATTACH; | |||
201 | strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN)rte_strlcpy(req.devargs, devargs, 128); | |||
202 | ||||
203 | if (rte_eal_process_type() != RTE_PROC_PRIMARY) { | |||
204 | /** | |||
205 | * If in secondary process, just send IPC request to | |||
206 | * primary process. | |||
207 | */ | |||
208 | ret = eal_dev_hotplug_request_to_primary(&req); | |||
209 | if (ret != 0) { | |||
210 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to send hotplug request to primary\n" ) | |||
211 | "Failed to send hotplug request to primary\n")rte_log(4U, 0, "EAL" ": " "Failed to send hotplug request to primary\n" ); | |||
212 | return -ENOMSG42; | |||
213 | } | |||
214 | if (req.result != 0) | |||
215 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to hotplug add device\n") | |||
216 | "Failed to hotplug add device\n")rte_log(4U, 0, "EAL" ": " "Failed to hotplug add device\n"); | |||
217 | return req.result; | |||
218 | } | |||
219 | ||||
220 | /* attach a shared device from primary start from here: */ | |||
221 | ||||
222 | /* primary attach the new device itself. */ | |||
223 | ret = local_dev_probe(devargs, &dev); | |||
224 | ||||
225 | if (ret != 0) { | |||
226 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to attach device on primary process\n" ) | |||
227 | "Failed to attach device on primary process\n")rte_log(4U, 0, "EAL" ": " "Failed to attach device on primary process\n" ); | |||
228 | ||||
229 | /** | |||
230 | * it is possible that secondary process failed to attached a | |||
231 | * device that primary process have during initialization, | |||
232 | * so for -EEXIST case, we still need to sync with secondary | |||
233 | * process. | |||
234 | */ | |||
235 | if (ret != -EEXIST17) | |||
236 | return ret; | |||
237 | } | |||
238 | ||||
239 | /* primary send attach sync request to secondary. */ | |||
240 | ret = eal_dev_hotplug_request_to_secondary(&req); | |||
241 | ||||
242 | /* if any communication error, we need to rollback. */ | |||
243 | if (ret != 0) { | |||
244 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to send hotplug add request to secondary\n" ) | |||
245 | "Failed to send hotplug add request to secondary\n")rte_log(4U, 0, "EAL" ": " "Failed to send hotplug add request to secondary\n" ); | |||
246 | ret = -ENOMSG42; | |||
247 | goto rollback; | |||
248 | } | |||
249 | ||||
250 | /** | |||
251 | * if any secondary failed to attach, we need to consider if rollback | |||
252 | * is necessary. | |||
253 | */ | |||
254 | if (req.result != 0) { | |||
255 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to attach device on secondary process\n" ) | |||
256 | "Failed to attach device on secondary process\n")rte_log(4U, 0, "EAL" ": " "Failed to attach device on secondary process\n" ); | |||
257 | ret = req.result; | |||
258 | ||||
259 | /* for -EEXIST, we don't need to rollback. */ | |||
260 | if (ret == -EEXIST17) | |||
261 | return ret; | |||
262 | goto rollback; | |||
263 | } | |||
264 | ||||
265 | return 0; | |||
266 | ||||
267 | rollback: | |||
268 | req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK; | |||
269 | ||||
270 | /* primary send rollback request to secondary. */ | |||
271 | if (eal_dev_hotplug_request_to_secondary(&req) != 0) | |||
272 | RTE_LOG(WARNING, EAL,rte_log(5U, 0, "EAL" ": " "Failed to rollback device attach on secondary." "Devices in secondary may not sync with primary\n") | |||
273 | "Failed to rollback device attach on secondary."rte_log(5U, 0, "EAL" ": " "Failed to rollback device attach on secondary." "Devices in secondary may not sync with primary\n") | |||
274 | "Devices in secondary may not sync with primary\n")rte_log(5U, 0, "EAL" ": " "Failed to rollback device attach on secondary." "Devices in secondary may not sync with primary\n"); | |||
275 | ||||
276 | /* primary rollback itself. */ | |||
277 | if (local_dev_remove(dev) != 0) | |||
278 | RTE_LOG(WARNING, EAL,rte_log(5U, 0, "EAL" ": " "Failed to rollback device attach on primary." "Devices in secondary may not sync with primary\n") | |||
279 | "Failed to rollback device attach on primary."rte_log(5U, 0, "EAL" ": " "Failed to rollback device attach on primary." "Devices in secondary may not sync with primary\n") | |||
280 | "Devices in secondary may not sync with primary\n")rte_log(5U, 0, "EAL" ": " "Failed to rollback device attach on primary." "Devices in secondary may not sync with primary\n"); | |||
281 | ||||
282 | return ret; | |||
283 | } | |||
284 | ||||
285 | int | |||
286 | rte_eal_hotplug_remove(const char *busname, const char *devname) | |||
287 | { | |||
288 | struct rte_device *dev; | |||
289 | struct rte_bus *bus; | |||
290 | ||||
291 | bus = rte_bus_find_by_name(busname); | |||
292 | if (bus == NULL((void*)0)) { | |||
293 | RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname)rte_log(4U, 0, "EAL" ": " "Cannot find bus (%s)\n", busname); | |||
294 | return -ENOENT2; | |||
295 | } | |||
296 | ||||
297 | dev = bus->find_device(NULL((void*)0), cmp_dev_name, devname); | |||
298 | if (dev == NULL((void*)0)) { | |||
299 | RTE_LOG(ERR, EAL, "Cannot find plugged device (%s)\n", devname)rte_log(4U, 0, "EAL" ": " "Cannot find plugged device (%s)\n" , devname); | |||
300 | return -EINVAL22; | |||
301 | } | |||
302 | ||||
303 | return rte_dev_remove(dev); | |||
304 | } | |||
305 | ||||
306 | /* remove device at local process. */ | |||
307 | int | |||
308 | local_dev_remove(struct rte_device *dev) | |||
309 | { | |||
310 | int ret; | |||
311 | ||||
312 | if (dev->bus->unplug == NULL((void*)0)) { | |||
| ||||
313 | RTE_LOG(ERR, EAL, "Function unplug not supported by bus (%s)\n",rte_log(4U, 0, "EAL" ": " "Function unplug not supported by bus (%s)\n" , dev->bus->name) | |||
314 | dev->bus->name)rte_log(4U, 0, "EAL" ": " "Function unplug not supported by bus (%s)\n" , dev->bus->name); | |||
315 | return -ENOTSUP95; | |||
316 | } | |||
317 | ||||
318 | ret = dev->bus->unplug(dev); | |||
319 | if (ret) { | |||
320 | RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",rte_log(4U, 0, "EAL" ": " "Driver cannot detach the device (%s)\n" , dev->name) | |||
321 | dev->name)rte_log(4U, 0, "EAL" ": " "Driver cannot detach the device (%s)\n" , dev->name); | |||
322 | return ret; | |||
323 | } | |||
324 | ||||
325 | return 0; | |||
326 | } | |||
327 | ||||
328 | int | |||
329 | rte_dev_remove(struct rte_device *dev) | |||
330 | { | |||
331 | struct eal_dev_mp_req req; | |||
332 | char *devargs; | |||
333 | int ret; | |||
334 | ||||
335 | if (!rte_dev_is_probed(dev)) { | |||
336 | RTE_LOG(ERR, EAL, "Device is not probed\n")rte_log(4U, 0, "EAL" ": " "Device is not probed\n"); | |||
337 | return -ENOENT2; | |||
338 | } | |||
339 | ||||
340 | ret = build_devargs(dev->bus->name, dev->name, "", &devargs); | |||
341 | if (ret != 0) | |||
342 | return ret; | |||
343 | ||||
344 | memset(&req, 0, sizeof(req)); | |||
345 | req.t = EAL_DEV_REQ_TYPE_DETACH; | |||
346 | strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN)rte_strlcpy(req.devargs, devargs, 128); | |||
347 | free(devargs); | |||
348 | ||||
349 | if (rte_eal_process_type() != RTE_PROC_PRIMARY) { | |||
350 | /** | |||
351 | * If in secondary process, just send IPC request to | |||
352 | * primary process. | |||
353 | */ | |||
354 | ret = eal_dev_hotplug_request_to_primary(&req); | |||
355 | if (ret != 0) { | |||
356 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to send hotplug request to primary\n" ) | |||
357 | "Failed to send hotplug request to primary\n")rte_log(4U, 0, "EAL" ": " "Failed to send hotplug request to primary\n" ); | |||
358 | return -ENOMSG42; | |||
359 | } | |||
360 | if (req.result != 0) | |||
361 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to hotplug remove device\n" ) | |||
362 | "Failed to hotplug remove device\n")rte_log(4U, 0, "EAL" ": " "Failed to hotplug remove device\n" ); | |||
363 | return req.result; | |||
364 | } | |||
365 | ||||
366 | /* detach a device from primary start from here: */ | |||
367 | ||||
368 | /* primary send detach sync request to secondary */ | |||
369 | ret = eal_dev_hotplug_request_to_secondary(&req); | |||
370 | ||||
371 | /** | |||
372 | * if communication error, we need to rollback, because it is possible | |||
373 | * part of the secondary processes still detached it successfully. | |||
374 | */ | |||
375 | if (ret != 0) { | |||
376 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to send device detach request to secondary\n" ) | |||
377 | "Failed to send device detach request to secondary\n")rte_log(4U, 0, "EAL" ": " "Failed to send device detach request to secondary\n" ); | |||
378 | ret = -ENOMSG42; | |||
379 | goto rollback; | |||
380 | } | |||
381 | ||||
382 | /** | |||
383 | * if any secondary failed to detach, we need to consider if rollback | |||
384 | * is necessary. | |||
385 | */ | |||
386 | if (req.result != 0) { | |||
387 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to detach device on secondary process\n" ) | |||
388 | "Failed to detach device on secondary process\n")rte_log(4U, 0, "EAL" ": " "Failed to detach device on secondary process\n" ); | |||
389 | ret = req.result; | |||
390 | /** | |||
391 | * if -ENOENT, we don't need to rollback, since devices is | |||
392 | * already detached on secondary process. | |||
393 | */ | |||
394 | if (ret != -ENOENT2) | |||
395 | goto rollback; | |||
396 | } | |||
397 | ||||
398 | /* primary detach the device itself. */ | |||
399 | ret = local_dev_remove(dev); | |||
400 | ||||
401 | /* if primary failed, still need to consider if rollback is necessary */ | |||
402 | if (ret != 0) { | |||
403 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to detach device on primary process\n" ) | |||
404 | "Failed to detach device on primary process\n")rte_log(4U, 0, "EAL" ": " "Failed to detach device on primary process\n" ); | |||
405 | /* if -ENOENT, we don't need to rollback */ | |||
406 | if (ret == -ENOENT2) | |||
407 | return ret; | |||
408 | goto rollback; | |||
409 | } | |||
410 | ||||
411 | return 0; | |||
412 | ||||
413 | rollback: | |||
414 | req.t = EAL_DEV_REQ_TYPE_DETACH_ROLLBACK; | |||
415 | ||||
416 | /* primary send rollback request to secondary. */ | |||
417 | if (eal_dev_hotplug_request_to_secondary(&req) != 0) | |||
418 | RTE_LOG(WARNING, EAL,rte_log(5U, 0, "EAL" ": " "Failed to rollback device detach on secondary." "Devices in secondary may not sync with primary\n") | |||
419 | "Failed to rollback device detach on secondary."rte_log(5U, 0, "EAL" ": " "Failed to rollback device detach on secondary." "Devices in secondary may not sync with primary\n") | |||
420 | "Devices in secondary may not sync with primary\n")rte_log(5U, 0, "EAL" ": " "Failed to rollback device detach on secondary." "Devices in secondary may not sync with primary\n"); | |||
421 | ||||
422 | return ret; | |||
423 | } | |||
424 | ||||
425 | int __rte_experimental__attribute__((section(".text.experimental"))) | |||
426 | rte_dev_event_callback_register(const char *device_name, | |||
427 | rte_dev_event_cb_fn cb_fn, | |||
428 | void *cb_arg) | |||
429 | { | |||
430 | struct dev_event_callback *event_cb; | |||
431 | int ret; | |||
432 | ||||
433 | if (!cb_fn) | |||
434 | return -EINVAL22; | |||
435 | ||||
436 | rte_spinlock_lock(&dev_event_lock); | |||
437 | ||||
438 | if (TAILQ_EMPTY(&dev_event_cbs)((&dev_event_cbs)->tqh_first == ((void*)0))) | |||
439 | TAILQ_INIT(&dev_event_cbs)do { (&dev_event_cbs)->tqh_first = ((void*)0); (&dev_event_cbs )->tqh_last = &(&dev_event_cbs)->tqh_first; } while ( 0); | |||
440 | ||||
441 | TAILQ_FOREACH(event_cb, &dev_event_cbs, next)for ((event_cb) = ((&dev_event_cbs)->tqh_first); (event_cb ); (event_cb) = ((event_cb)->next.tqe_next)) { | |||
442 | if (event_cb->cb_fn == cb_fn && event_cb->cb_arg == cb_arg) { | |||
443 | if (device_name == NULL((void*)0) && event_cb->dev_name == NULL((void*)0)) | |||
444 | break; | |||
445 | if (device_name == NULL((void*)0) || event_cb->dev_name == NULL((void*)0)) | |||
446 | continue; | |||
447 | if (!strcmp(event_cb->dev_name, device_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (event_cb->dev_name) && __builtin_constant_p (device_name ) && (__s1_len = __builtin_strlen (event_cb->dev_name ), __s2_len = __builtin_strlen (device_name), (!((size_t)(const void *)((event_cb->dev_name) + 1) - (size_t)(const void * )(event_cb->dev_name) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((device_name) + 1) - (size_t)(const void *)(device_name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (event_cb->dev_name, device_name) : (__builtin_constant_p (event_cb->dev_name) && ((size_t)(const void *)(( event_cb->dev_name) + 1) - (size_t)(const void *)(event_cb ->dev_name) == 1) && (__s1_len = __builtin_strlen ( event_cb->dev_name), __s1_len < 4) ? (__builtin_constant_p (device_name) && ((size_t)(const void *)((device_name ) + 1) - (size_t)(const void *)(device_name) == 1) ? __builtin_strcmp (event_cb->dev_name, device_name) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (device_name); int __result = (((const unsigned char *) (const char *) (event_cb->dev_name))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (event_cb->dev_name))[1] - __s2[1] ); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (event_cb->dev_name ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (event_cb ->dev_name))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (device_name) && ((size_t)(const void *)((device_name ) + 1) - (size_t)(const void *)(device_name) == 1) && (__s2_len = __builtin_strlen (device_name), __s2_len < 4) ? (__builtin_constant_p (event_cb->dev_name) && ( (size_t)(const void *)((event_cb->dev_name) + 1) - (size_t )(const void *)(event_cb->dev_name) == 1) ? __builtin_strcmp (event_cb->dev_name, device_name) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (event_cb->dev_name); int __result = (((const unsigned char *) (const char *) (device_name))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (device_name))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (device_name))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (device_name))[3] - __s2[3]); } } __result ; })))) : __builtin_strcmp (event_cb->dev_name, device_name )))); })) | |||
448 | break; | |||
449 | } | |||
450 | } | |||
451 | ||||
452 | /* create a new callback. */ | |||
453 | if (event_cb == NULL((void*)0)) { | |||
454 | event_cb = malloc(sizeof(struct dev_event_callback)); | |||
455 | if (event_cb != NULL((void*)0)) { | |||
456 | event_cb->cb_fn = cb_fn; | |||
457 | event_cb->cb_arg = cb_arg; | |||
458 | event_cb->active = 0; | |||
459 | if (!device_name) { | |||
460 | event_cb->dev_name = NULL((void*)0); | |||
461 | } else { | |||
462 | event_cb->dev_name = strdup(device_name)(__extension__ (__builtin_constant_p (device_name) && ((size_t)(const void *)((device_name) + 1) - (size_t)(const void *)(device_name) == 1) ? (((const char *) (device_name))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (device_name) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, device_name, __len); __retval; })) : __strdup (device_name ))); | |||
463 | if (event_cb->dev_name == NULL((void*)0)) { | |||
464 | ret = -ENOMEM12; | |||
465 | goto error; | |||
466 | } | |||
467 | } | |||
468 | TAILQ_INSERT_TAIL(&dev_event_cbs, event_cb, next)do { (event_cb)->next.tqe_next = ((void*)0); (event_cb)-> next.tqe_prev = (&dev_event_cbs)->tqh_last; *(&dev_event_cbs )->tqh_last = (event_cb); (&dev_event_cbs)->tqh_last = &(event_cb)->next.tqe_next; } while ( 0); | |||
469 | } else { | |||
470 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Failed to allocate memory for device " "event callback.") | |||
471 | "Failed to allocate memory for device "rte_log(4U, 0, "EAL" ": " "Failed to allocate memory for device " "event callback.") | |||
472 | "event callback.")rte_log(4U, 0, "EAL" ": " "Failed to allocate memory for device " "event callback."); | |||
473 | ret = -ENOMEM12; | |||
474 | goto error; | |||
475 | } | |||
476 | } else { | |||
477 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "The callback is already exist, no need " "to register again.\n") | |||
478 | "The callback is already exist, no need "rte_log(4U, 0, "EAL" ": " "The callback is already exist, no need " "to register again.\n") | |||
479 | "to register again.\n")rte_log(4U, 0, "EAL" ": " "The callback is already exist, no need " "to register again.\n"); | |||
480 | ret = -EEXIST17; | |||
481 | } | |||
482 | ||||
483 | rte_spinlock_unlock(&dev_event_lock); | |||
484 | return 0; | |||
485 | error: | |||
486 | free(event_cb); | |||
487 | rte_spinlock_unlock(&dev_event_lock); | |||
488 | return ret; | |||
489 | } | |||
490 | ||||
491 | int __rte_experimental__attribute__((section(".text.experimental"))) | |||
492 | rte_dev_event_callback_unregister(const char *device_name, | |||
493 | rte_dev_event_cb_fn cb_fn, | |||
494 | void *cb_arg) | |||
495 | { | |||
496 | int ret = 0; | |||
497 | struct dev_event_callback *event_cb, *next; | |||
498 | ||||
499 | if (!cb_fn) | |||
500 | return -EINVAL22; | |||
501 | ||||
502 | rte_spinlock_lock(&dev_event_lock); | |||
503 | /*walk through the callbacks and remove all that match. */ | |||
504 | for (event_cb = TAILQ_FIRST(&dev_event_cbs)((&dev_event_cbs)->tqh_first); event_cb != NULL((void*)0); | |||
505 | event_cb = next) { | |||
506 | ||||
507 | next = TAILQ_NEXT(event_cb, next)((event_cb)->next.tqe_next); | |||
508 | ||||
509 | if (device_name != NULL((void*)0) && event_cb->dev_name != NULL((void*)0)) { | |||
510 | if (!strcmp(event_cb->dev_name, device_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (event_cb->dev_name) && __builtin_constant_p (device_name ) && (__s1_len = __builtin_strlen (event_cb->dev_name ), __s2_len = __builtin_strlen (device_name), (!((size_t)(const void *)((event_cb->dev_name) + 1) - (size_t)(const void * )(event_cb->dev_name) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((device_name) + 1) - (size_t)(const void *)(device_name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (event_cb->dev_name, device_name) : (__builtin_constant_p (event_cb->dev_name) && ((size_t)(const void *)(( event_cb->dev_name) + 1) - (size_t)(const void *)(event_cb ->dev_name) == 1) && (__s1_len = __builtin_strlen ( event_cb->dev_name), __s1_len < 4) ? (__builtin_constant_p (device_name) && ((size_t)(const void *)((device_name ) + 1) - (size_t)(const void *)(device_name) == 1) ? __builtin_strcmp (event_cb->dev_name, device_name) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (device_name); int __result = (((const unsigned char *) (const char *) (event_cb->dev_name))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (event_cb->dev_name))[1] - __s2[1] ); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (event_cb->dev_name ))[2] - __s2[2]); if (__s1_len > 2 && __result == 0 ) __result = (((const unsigned char *) (const char *) (event_cb ->dev_name))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (device_name) && ((size_t)(const void *)((device_name ) + 1) - (size_t)(const void *)(device_name) == 1) && (__s2_len = __builtin_strlen (device_name), __s2_len < 4) ? (__builtin_constant_p (event_cb->dev_name) && ( (size_t)(const void *)((event_cb->dev_name) + 1) - (size_t )(const void *)(event_cb->dev_name) == 1) ? __builtin_strcmp (event_cb->dev_name, device_name) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (event_cb->dev_name); int __result = (((const unsigned char *) (const char *) (device_name))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (device_name))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (device_name))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (device_name))[3] - __s2[3]); } } __result ; })))) : __builtin_strcmp (event_cb->dev_name, device_name )))); })) { | |||
511 | if (event_cb->cb_fn != cb_fn || | |||
512 | (cb_arg != (void *)-1 && | |||
513 | event_cb->cb_arg != cb_arg)) | |||
514 | continue; | |||
515 | } | |||
516 | } else if (device_name != NULL((void*)0)) { | |||
517 | continue; | |||
518 | } | |||
519 | ||||
520 | /* | |||
521 | * if this callback is not executing right now, | |||
522 | * then remove it. | |||
523 | */ | |||
524 | if (event_cb->active == 0) { | |||
525 | TAILQ_REMOVE(&dev_event_cbs, event_cb, next)do { if (((event_cb)->next.tqe_next) != ((void*)0)) (event_cb )->next.tqe_next->next.tqe_prev = (event_cb)->next.tqe_prev ; else (&dev_event_cbs)->tqh_last = (event_cb)->next .tqe_prev; *(event_cb)->next.tqe_prev = (event_cb)->next .tqe_next; } while ( 0); | |||
526 | free(event_cb); | |||
527 | ret++; | |||
528 | } else { | |||
529 | continue; | |||
530 | } | |||
531 | } | |||
532 | rte_spinlock_unlock(&dev_event_lock); | |||
533 | return ret; | |||
534 | } | |||
535 | ||||
536 | void __rte_experimental__attribute__((section(".text.experimental"))) | |||
537 | rte_dev_event_callback_process(const char *device_name, | |||
538 | enum rte_dev_event_type event) | |||
539 | { | |||
540 | struct dev_event_callback *cb_lst; | |||
541 | ||||
542 | if (device_name == NULL((void*)0)) | |||
543 | return; | |||
544 | ||||
545 | rte_spinlock_lock(&dev_event_lock); | |||
546 | ||||
547 | TAILQ_FOREACH(cb_lst, &dev_event_cbs, next)for ((cb_lst) = ((&dev_event_cbs)->tqh_first); (cb_lst ); (cb_lst) = ((cb_lst)->next.tqe_next)) { | |||
548 | if (cb_lst->dev_name) { | |||
549 | if (strcmp(cb_lst->dev_name, device_name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (cb_lst->dev_name) && __builtin_constant_p (device_name ) && (__s1_len = __builtin_strlen (cb_lst->dev_name ), __s2_len = __builtin_strlen (device_name), (!((size_t)(const void *)((cb_lst->dev_name) + 1) - (size_t)(const void *)( cb_lst->dev_name) == 1) || __s1_len >= 4) && (! ((size_t)(const void *)((device_name) + 1) - (size_t)(const void *)(device_name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (cb_lst->dev_name, device_name) : (__builtin_constant_p ( cb_lst->dev_name) && ((size_t)(const void *)((cb_lst ->dev_name) + 1) - (size_t)(const void *)(cb_lst->dev_name ) == 1) && (__s1_len = __builtin_strlen (cb_lst->dev_name ), __s1_len < 4) ? (__builtin_constant_p (device_name) && ((size_t)(const void *)((device_name) + 1) - (size_t)(const void *)(device_name) == 1) ? __builtin_strcmp (cb_lst->dev_name , device_name) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (device_name); int __result = (((const unsigned char *) (const char *) (cb_lst->dev_name ))[0] - __s2[0]); if (__s1_len > 0 && __result == 0 ) { __result = (((const unsigned char *) (const char *) (cb_lst ->dev_name))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (cb_lst->dev_name))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (cb_lst->dev_name))[3] - __s2[3]); } } __result ; }))) : (__builtin_constant_p (device_name) && ((size_t )(const void *)((device_name) + 1) - (size_t)(const void *)(device_name ) == 1) && (__s2_len = __builtin_strlen (device_name) , __s2_len < 4) ? (__builtin_constant_p (cb_lst->dev_name ) && ((size_t)(const void *)((cb_lst->dev_name) + 1 ) - (size_t)(const void *)(cb_lst->dev_name) == 1) ? __builtin_strcmp (cb_lst->dev_name, device_name) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (cb_lst->dev_name); int __result = (((const unsigned char *) (const char *) (device_name))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (device_name))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (device_name))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (device_name))[3] - __s2[3]); } } __result ; })))) : __builtin_strcmp (cb_lst->dev_name, device_name) ))); })) | |||
550 | continue; | |||
551 | } | |||
552 | cb_lst->active = 1; | |||
553 | rte_spinlock_unlock(&dev_event_lock); | |||
554 | cb_lst->cb_fn(device_name, event, | |||
555 | cb_lst->cb_arg); | |||
556 | rte_spinlock_lock(&dev_event_lock); | |||
557 | cb_lst->active = 0; | |||
558 | } | |||
559 | rte_spinlock_unlock(&dev_event_lock); | |||
560 | } | |||
561 | ||||
562 | __rte_experimental__attribute__((section(".text.experimental"))) | |||
563 | int | |||
564 | rte_dev_iterator_init(struct rte_dev_iterator *it, | |||
565 | const char *dev_str) | |||
566 | { | |||
567 | struct rte_devargs devargs; | |||
568 | struct rte_class *cls = NULL((void*)0); | |||
569 | struct rte_bus *bus = NULL((void*)0); | |||
570 | ||||
571 | /* Having both bus_str and cls_str NULL is illegal, | |||
572 | * marking this iterator as invalid unless | |||
573 | * everything goes well. | |||
574 | */ | |||
575 | it->bus_str = NULL((void*)0); | |||
576 | it->cls_str = NULL((void*)0); | |||
577 | ||||
578 | devargs.data = dev_str; | |||
579 | if (rte_devargs_layers_parse(&devargs, dev_str)) | |||
580 | goto get_out; | |||
581 | ||||
582 | bus = devargs.bus; | |||
583 | cls = devargs.cls; | |||
584 | /* The string should have at least | |||
585 | * one layer specified. | |||
586 | */ | |||
587 | if (bus == NULL((void*)0) && cls == NULL((void*)0)) { | |||
588 | RTE_LOG(ERR, EAL,rte_log(4U, 0, "EAL" ": " "Either bus or class must be specified.\n" ) | |||
589 | "Either bus or class must be specified.\n")rte_log(4U, 0, "EAL" ": " "Either bus or class must be specified.\n" ); | |||
590 | rte_errno(per_lcore__rte_errno) = EINVAL22; | |||
591 | goto get_out; | |||
592 | } | |||
593 | if (bus != NULL((void*)0) && bus->dev_iterate == NULL((void*)0)) { | |||
594 | RTE_LOG(ERR, EAL, "Bus %s not supported\n", bus->name)rte_log(4U, 0, "EAL" ": " "Bus %s not supported\n", bus->name ); | |||
595 | rte_errno(per_lcore__rte_errno) = ENOTSUP95; | |||
596 | goto get_out; | |||
597 | } | |||
598 | if (cls != NULL((void*)0) && cls->dev_iterate == NULL((void*)0)) { | |||
599 | RTE_LOG(ERR, EAL, "Class %s not supported\n", cls->name)rte_log(4U, 0, "EAL" ": " "Class %s not supported\n", cls-> name); | |||
600 | rte_errno(per_lcore__rte_errno) = ENOTSUP95; | |||
601 | goto get_out; | |||
602 | } | |||
603 | it->bus_str = devargs.bus_str; | |||
604 | it->cls_str = devargs.cls_str; | |||
605 | it->dev_str = dev_str; | |||
606 | it->bus = bus; | |||
607 | it->cls = cls; | |||
608 | it->device = NULL((void*)0); | |||
609 | it->class_device = NULL((void*)0); | |||
610 | get_out: | |||
611 | return -rte_errno(per_lcore__rte_errno); | |||
612 | } | |||
613 | ||||
614 | static char * | |||
615 | dev_str_sane_copy(const char *str) | |||
616 | { | |||
617 | size_t end; | |||
618 | char *copy; | |||
619 | ||||
620 | end = strcspn(str, ",/")__extension__ ({ char __r0, __r1, __r2; (__builtin_constant_p (",/") && ((size_t)(const void *)((",/") + 1) - (size_t )(const void *)(",/") == 1) ? ((__builtin_constant_p (str) && ((size_t)(const void *)((str) + 1) - (size_t)(const void *)( str) == 1)) ? __builtin_strcspn (str, ",/") : ((__r0 = ((const char *) (",/"))[0], __r0 == '\0') ? strlen (str) : ((__r1 = ( (const char *) (",/"))[1], __r1 == '\0') ? __strcspn_c1 (str, __r0) : ((__r2 = ((const char *) (",/"))[2], __r2 == '\0') ? __strcspn_c2 (str, __r0, __r1) : (((const char *) (",/"))[3] == '\0' ? __strcspn_c3 (str, __r0, __r1, __r2) : __builtin_strcspn (str, ",/")))))) : __builtin_strcspn (str, ",/")); }); | |||
621 | if (str[end] == ',') { | |||
622 | copy = strdup(&str[end + 1])(__extension__ (__builtin_constant_p (&str[end + 1]) && ((size_t)(const void *)((&str[end + 1]) + 1) - (size_t)( const void *)(&str[end + 1]) == 1) ? (((const char *) (& str[end + 1]))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t ) 1) : ({ size_t __len = strlen (&str[end + 1]) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void* )0)) __retval = (char *) memcpy (__retval, &str[end + 1], __len); __retval; })) : __strdup (&str[end + 1]))); | |||
623 | } else { | |||
624 | /* '/' or '\0' */ | |||
625 | copy = strdup("")(__extension__ (__builtin_constant_p ("") && ((size_t )(const void *)(("") + 1) - (size_t)(const void *)("") == 1) ? (((const char *) (""))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen ("") + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, "", __len); __retval; })) : __strdup (""))); | |||
626 | } | |||
627 | if (copy == NULL((void*)0)) { | |||
628 | rte_errno(per_lcore__rte_errno) = ENOMEM12; | |||
629 | } else { | |||
630 | char *slash; | |||
631 | ||||
632 | slash = strchr(copy, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p (copy) && ('/') == '\0' ? (char *) __rawmemchr (copy , '/') : __builtin_strchr (copy, '/'))); | |||
633 | if (slash != NULL((void*)0)) | |||
634 | slash[0] = '\0'; | |||
635 | } | |||
636 | return copy; | |||
637 | } | |||
638 | ||||
639 | static int | |||
640 | class_next_dev_cmp(const struct rte_class *cls, | |||
641 | const void *ctx) | |||
642 | { | |||
643 | struct rte_dev_iterator *it; | |||
644 | const char *cls_str = NULL((void*)0); | |||
645 | void *dev; | |||
646 | ||||
647 | if (cls->dev_iterate == NULL((void*)0)) | |||
648 | return 1; | |||
649 | it = ITCTX(ctx)(((struct dev_next_ctx *)(intptr_t)ctx)->it); | |||
650 | cls_str = CLSCTX(ctx)(((struct dev_next_ctx *)(intptr_t)ctx)->cls_str); | |||
651 | dev = it->class_device; | |||
652 | /* it->cls_str != NULL means a class | |||
653 | * was specified in the devstr. | |||
654 | */ | |||
655 | if (it->cls_str != NULL((void*)0) && cls != it->cls) | |||
656 | return 1; | |||
657 | /* If an error occurred previously, | |||
658 | * no need to test further. | |||
659 | */ | |||
660 | if (rte_errno(per_lcore__rte_errno) != 0) | |||
661 | return -1; | |||
662 | dev = cls->dev_iterate(dev, cls_str, it); | |||
663 | it->class_device = dev; | |||
664 | return dev == NULL((void*)0); | |||
665 | } | |||
666 | ||||
667 | static int | |||
668 | bus_next_dev_cmp(const struct rte_bus *bus, | |||
669 | const void *ctx) | |||
670 | { | |||
671 | struct rte_device *dev = NULL((void*)0); | |||
672 | struct rte_class *cls = NULL((void*)0); | |||
673 | struct rte_dev_iterator *it; | |||
674 | const char *bus_str = NULL((void*)0); | |||
675 | ||||
676 | if (bus->dev_iterate == NULL((void*)0)) | |||
677 | return 1; | |||
678 | it = ITCTX(ctx)(((struct dev_next_ctx *)(intptr_t)ctx)->it); | |||
679 | bus_str = BUSCTX(ctx)(((struct dev_next_ctx *)(intptr_t)ctx)->bus_str); | |||
680 | dev = it->device; | |||
681 | /* it->bus_str != NULL means a bus | |||
682 | * was specified in the devstr. | |||
683 | */ | |||
684 | if (it->bus_str != NULL((void*)0) && bus != it->bus) | |||
685 | return 1; | |||
686 | /* If an error occurred previously, | |||
687 | * no need to test further. | |||
688 | */ | |||
689 | if (rte_errno(per_lcore__rte_errno) != 0) | |||
690 | return -1; | |||
691 | if (it->cls_str == NULL((void*)0)) { | |||
692 | dev = bus->dev_iterate(dev, bus_str, it); | |||
693 | goto end; | |||
694 | } | |||
695 | /* cls_str != NULL */ | |||
696 | if (dev == NULL((void*)0)) { | |||
697 | next_dev_on_bus: | |||
698 | dev = bus->dev_iterate(dev, bus_str, it); | |||
699 | it->device = dev; | |||
700 | } | |||
701 | if (dev == NULL((void*)0)) | |||
702 | return 1; | |||
703 | if (it->cls != NULL((void*)0)) | |||
704 | cls = TAILQ_PREV(it->cls, rte_class_list, next)(*(((struct rte_class_list *)((it->cls)->next.tqe_prev) )->tqh_last)); | |||
705 | cls = rte_class_find(cls, class_next_dev_cmp, ctx); | |||
706 | if (cls != NULL((void*)0)) { | |||
707 | it->cls = cls; | |||
708 | goto end; | |||
709 | } | |||
710 | goto next_dev_on_bus; | |||
711 | end: | |||
712 | it->device = dev; | |||
713 | return dev == NULL((void*)0); | |||
714 | } | |||
715 | __rte_experimental__attribute__((section(".text.experimental"))) | |||
716 | struct rte_device * | |||
717 | rte_dev_iterator_next(struct rte_dev_iterator *it) | |||
718 | { | |||
719 | struct rte_bus *bus = NULL((void*)0); | |||
720 | int old_errno = rte_errno(per_lcore__rte_errno); | |||
721 | char *bus_str = NULL((void*)0); | |||
722 | char *cls_str = NULL((void*)0); | |||
723 | ||||
724 | rte_errno(per_lcore__rte_errno) = 0; | |||
725 | if (it->bus_str == NULL((void*)0) && it->cls_str == NULL((void*)0)) { | |||
726 | /* Invalid iterator. */ | |||
727 | rte_errno(per_lcore__rte_errno) = EINVAL22; | |||
728 | return NULL((void*)0); | |||
729 | } | |||
730 | if (it->bus != NULL((void*)0)) | |||
731 | bus = TAILQ_PREV(it->bus, rte_bus_list, next)(*(((struct rte_bus_list *)((it->bus)->next.tqe_prev))-> tqh_last)); | |||
732 | if (it->bus_str != NULL((void*)0)) { | |||
733 | bus_str = dev_str_sane_copy(it->bus_str); | |||
734 | if (bus_str == NULL((void*)0)) | |||
735 | goto out; | |||
736 | } | |||
737 | if (it->cls_str != NULL((void*)0)) { | |||
738 | cls_str = dev_str_sane_copy(it->cls_str); | |||
739 | if (cls_str == NULL((void*)0)) | |||
740 | goto out; | |||
741 | } | |||
742 | while ((bus = rte_bus_find(bus, bus_next_dev_cmp, | |||
743 | CTX(it, bus_str, cls_str)(&(const struct dev_next_ctx){ .it = it, .bus_str = bus_str , .cls_str = cls_str, })))) { | |||
744 | if (it->device != NULL((void*)0)) { | |||
745 | it->bus = bus; | |||
746 | goto out; | |||
747 | } | |||
748 | if (it->bus_str != NULL((void*)0) || | |||
749 | rte_errno(per_lcore__rte_errno) != 0) | |||
750 | break; | |||
751 | } | |||
752 | if (rte_errno(per_lcore__rte_errno) == 0) | |||
753 | rte_errno(per_lcore__rte_errno) = old_errno; | |||
754 | out: | |||
755 | free(bus_str); | |||
756 | free(cls_str); | |||
757 | return it->device; | |||
758 | } | |||
759 | ||||
760 | int | |||
761 | rte_dev_dma_map(struct rte_device *dev, void *addr, uint64_t iova, | |||
762 | size_t len) | |||
763 | { | |||
764 | if (dev->bus->dma_map == NULL((void*)0) || len == 0) { | |||
765 | rte_errno(per_lcore__rte_errno) = ENOTSUP95; | |||
766 | return -1; | |||
767 | } | |||
768 | /* Memory must be registered through rte_extmem_* APIs */ | |||
769 | if (rte_mem_virt2memseg_list(addr) == NULL((void*)0)) { | |||
770 | rte_errno(per_lcore__rte_errno) = EINVAL22; | |||
771 | return -1; | |||
772 | } | |||
773 | ||||
774 | return dev->bus->dma_map(dev, addr, iova, len); | |||
775 | } | |||
776 | ||||
777 | int | |||
778 | rte_dev_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, | |||
779 | size_t len) | |||
780 | { | |||
781 | if (dev->bus->dma_unmap == NULL((void*)0) || len == 0) { | |||
782 | rte_errno(per_lcore__rte_errno) = ENOTSUP95; | |||
783 | return -1; | |||
784 | } | |||
785 | /* Memory must be registered through rte_extmem_* APIs */ | |||
786 | if (rte_mem_virt2memseg_list(addr) == NULL((void*)0)) { | |||
787 | rte_errno(per_lcore__rte_errno) = EINVAL22; | |||
788 | return -1; | |||
789 | } | |||
790 | ||||
791 | return dev->bus->dma_unmap(dev, addr, iova, len); | |||
792 | } |