File: | home/bhubbard/working/src/ceph/src/spdk/dpdk/lib/librte_eal/common/eal_common_dev.c |
Warning: | line 480, column 3 Value stored to 'ret' is never read |
[?] 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; |
Value stored to 'ret' is never read | |
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 | } |