Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 HiSilicon Limited
3 : : */
4 : :
5 : : #include <ctype.h>
6 : : #include <dirent.h>
7 : : #include <errno.h>
8 : : #include <fcntl.h>
9 : : #include <unistd.h>
10 : : #include <stdlib.h>
11 : : #include <string.h>
12 : : #include <sys/ioctl.h>
13 : : #include <sys/mman.h>
14 : : #include <sys/stat.h>
15 : : #include <sys/types.h>
16 : :
17 : : #include <eal_export.h>
18 : : #include <rte_bitops.h>
19 : : #include <rte_common.h>
20 : : #include <rte_devargs.h>
21 : : #include <rte_eal_paging.h>
22 : : #include <rte_errno.h>
23 : : #include <rte_log.h>
24 : : #include <rte_kvargs.h>
25 : : #include <bus_driver.h>
26 : :
27 : : #include "bus_uacce_driver.h"
28 : :
29 : : #define UACCE_BUS_CLASS_PATH "/sys/class/uacce"
30 : :
31 : : /* UACCE device flag of SVA. */
32 : : #define UACCE_DEV_FLGA_SVA RTE_BIT32(0)
33 : :
34 : : /* Support -a uacce:device-name when start DPDK application. */
35 : : #define UACCE_DEV_PREFIX "uacce:"
36 : :
37 : : /*
38 : : * Structure describing the UACCE bus.
39 : : */
40 : : struct rte_uacce_bus {
41 : : struct rte_bus bus; /* Inherit the generic class. */
42 : : TAILQ_HEAD(, rte_uacce_device) device_list; /* List of devices. */
43 : : TAILQ_HEAD(, rte_uacce_driver) driver_list; /* List of drivers. */
44 : : };
45 : :
46 : : /* Forward declaration of UACCE bus. */
47 : : static struct rte_uacce_bus uacce_bus;
48 : :
49 : : enum uacce_params {
50 : : RTE_UACCE_PARAM_NAME,
51 : : };
52 : :
53 : : static const char *const uacce_params_keys[] = {
54 : : [RTE_UACCE_PARAM_NAME] = "name",
55 : : NULL,
56 : : };
57 : :
58 : : #define FOREACH_DEVICE_ON_UACCEBUS(p) \
59 : : RTE_TAILQ_FOREACH(p, &uacce_bus.device_list, next)
60 : : #define FOREACH_DRIVER_ON_UACCEBUS(p) \
61 : : RTE_TAILQ_FOREACH(p, &uacce_bus.driver_list, next)
62 : :
63 : : extern int uacce_bus_logtype;
64 : : #define RTE_LOGTYPE_UACCE_BUS uacce_bus_logtype
65 : : #define UACCE_BUS_LOG(level, ...) \
66 : : RTE_LOG_LINE(level, UACCE_BUS, __VA_ARGS__)
67 : : #define UACCE_BUS_ERR(fmt, ...) UACCE_BUS_LOG(ERR, fmt, ##__VA_ARGS__)
68 : : #define UACCE_BUS_WARN(fmt, ...) UACCE_BUS_LOG(WARNING, fmt, ##__VA_ARGS__)
69 : : #define UACCE_BUS_INFO(fmt, ...) UACCE_BUS_LOG(INFO, fmt, ##__VA_ARGS__)
70 : : #define UACCE_BUS_DEBUG(fmt, ...) UACCE_BUS_LOG(DEBUG, fmt, ##__VA_ARGS__)
71 : :
72 : :
73 : : /*
74 : : * Returns the number of bytes read (removed last newline) on success.
75 : : * Otherwise negative value is returned.
76 : : */
77 : : static int
78 : 0 : uacce_read_attr(const char *dev_root, const char *attr, char *buf, uint32_t sz)
79 : : {
80 : 0 : char filename[PATH_MAX] = {0};
81 : : int ret;
82 : : int fd;
83 : :
84 : : snprintf(filename, sizeof(filename), "%s/%s", dev_root, attr);
85 : : fd = open(filename, O_RDONLY, 0);
86 [ # # ]: 0 : if (fd < 0) {
87 : 0 : UACCE_BUS_ERR("failed to open %s", filename);
88 : 0 : return -EIO;
89 : : }
90 : :
91 [ # # ]: 0 : ret = read(fd, buf, sz);
92 [ # # ]: 0 : if (ret > 0) {
93 : : /* Remove the last new line character. */
94 [ # # ]: 0 : if (buf[ret - 1] == '\n') {
95 : 0 : buf[ret - 1] = '\0';
96 : 0 : ret--;
97 : : }
98 : : }
99 [ # # ]: 0 : if (ret <= 0) {
100 : 0 : UACCE_BUS_ERR("failed to read %s", filename);
101 : : ret = -EIO;
102 : : }
103 : :
104 : 0 : close(fd);
105 : :
106 : 0 : return ret;
107 : : }
108 : :
109 : : /* 0 on success. Otherwise negative value is returned. */
110 : : static int
111 : 0 : uacce_read_attr_int(const char *dev_root, const char *attr, int *val)
112 : : {
113 : 0 : char buf[RTE_UACCE_ATTR_MAX_SIZE] = {0};
114 : 0 : char *s = NULL;
115 : : int ret;
116 : :
117 : 0 : ret = uacce_read_attr(dev_root, attr, buf, sizeof(buf) - 1);
118 [ # # ]: 0 : if (ret < 0)
119 : : return ret;
120 : :
121 : 0 : *val = strtol(buf, &s, 0);
122 [ # # ]: 0 : if (s[0] != '\0') {
123 : 0 : UACCE_BUS_ERR("read attr %s/%s expect an integer value", dev_root, attr);
124 : 0 : return -EINVAL;
125 : : }
126 : :
127 : : return 0;
128 : : }
129 : :
130 : : /* 0 on success. Otherwise negative value is returned. */
131 : : static int
132 : 0 : uacce_read_attr_u32(const char *dev_root, const char *attr, uint32_t *val)
133 : : {
134 : 0 : char buf[RTE_UACCE_ATTR_MAX_SIZE] = {0};
135 : 0 : char *s = NULL;
136 : : int ret;
137 : :
138 : 0 : ret = uacce_read_attr(dev_root, attr, buf, sizeof(buf) - 1);
139 [ # # ]: 0 : if (ret < 0)
140 : : return ret;
141 : :
142 : 0 : *val = strtoul(buf, &s, 0);
143 [ # # ]: 0 : if (s[0] != '\0') {
144 : 0 : UACCE_BUS_ERR("read attr %s/%s expect an uint32 value", dev_root, attr);
145 : 0 : return -EINVAL;
146 : : }
147 : :
148 : : return 0;
149 : : }
150 : :
151 : : static int
152 : : uacce_read_api(struct rte_uacce_device *dev)
153 : : {
154 : 0 : int ret = uacce_read_attr(dev->dev_root, "api", dev->api, sizeof(dev->api) - 1);
155 : : if (ret < 0)
156 : : return ret;
157 : : return 0;
158 : : }
159 : :
160 : : static int
161 : : uacce_read_algs(struct rte_uacce_device *dev)
162 : : {
163 : 0 : int ret = uacce_read_attr(dev->dev_root, "algorithms", dev->algs, sizeof(dev->algs) - 1);
164 : : if (ret < 0)
165 : : return ret;
166 : : return 0;
167 : : }
168 : :
169 : : static int
170 : : uacce_read_flags(struct rte_uacce_device *dev)
171 : : {
172 : 0 : return uacce_read_attr_u32(dev->dev_root, "flags", &dev->flags);
173 : : }
174 : :
175 : : static void
176 : 0 : uacce_read_numa_node(struct rte_uacce_device *dev)
177 : : {
178 : 0 : int ret = uacce_read_attr_int(dev->dev_root, "device/numa_node", &dev->numa_node);
179 [ # # ]: 0 : if (ret != 0) {
180 : 0 : UACCE_BUS_WARN("read attr numa_node failed! set to default");
181 : 0 : dev->numa_node = -1;
182 : : }
183 : 0 : }
184 : :
185 : : static int
186 : 0 : uacce_read_qfrt_sz(struct rte_uacce_device *dev)
187 : : {
188 : 0 : int ret = uacce_read_attr_u32(dev->dev_root, "region_mmio_size",
189 : : &dev->qfrt_sz[RTE_UACCE_QFRT_MMIO]);
190 [ # # ]: 0 : if (ret != 0)
191 : : return ret;
192 : 0 : return uacce_read_attr_u32(dev->dev_root, "region_dus_size",
193 : : &dev->qfrt_sz[RTE_UACCE_QFRT_DUS]);
194 : : }
195 : :
196 : : static int
197 : 0 : uacce_verify(struct rte_uacce_device *dev)
198 : : {
199 [ # # ]: 0 : if (!(dev->flags & UACCE_DEV_FLGA_SVA)) {
200 : 0 : UACCE_BUS_WARN("device %s don't support SVA, skip it!", dev->name);
201 : 0 : return 1; /* >0 will skip this device. */
202 : : }
203 : :
204 : : return 0;
205 : : }
206 : :
207 : : /*
208 : : * Scan one UACCE sysfs entry, and fill the devices list from it.
209 : : * It reads api/algs/flags/numa_node/region-size (please refer Linux kernel:
210 : : * Documentation/ABI/testing/sysfs-driver-uacce) and stores them for later
211 : : * device-driver matching, driver init...
212 : : */
213 : : static int
214 : 0 : uacce_scan_one(const char *dev_name)
215 : : {
216 : : struct rte_uacce_device *dev;
217 : : int ret;
218 : :
219 : 0 : dev = calloc(1, sizeof(*dev));
220 [ # # ]: 0 : if (!dev)
221 : : return -ENOMEM;
222 : :
223 : 0 : dev->device.bus = &uacce_bus.bus;
224 : 0 : dev->device.name = dev->name;
225 : 0 : dev->device.devargs = rte_bus_find_devargs(&uacce_bus.bus, dev_name);
226 : : snprintf(dev->name, sizeof(dev->name), "%s", dev_name);
227 : 0 : snprintf(dev->dev_root, sizeof(dev->dev_root), "%s/%s",
228 : : UACCE_BUS_CLASS_PATH, dev_name);
229 : 0 : snprintf(dev->cdev_path, sizeof(dev->cdev_path), "/dev/%s", dev_name);
230 : :
231 : : ret = uacce_read_api(dev);
232 [ # # ]: 0 : if (ret != 0)
233 : 0 : goto err;
234 : : ret = uacce_read_algs(dev);
235 [ # # ]: 0 : if (ret != 0)
236 : 0 : goto err;
237 : : ret = uacce_read_flags(dev);
238 [ # # ]: 0 : if (ret != 0)
239 : 0 : goto err;
240 : 0 : uacce_read_numa_node(dev);
241 : 0 : ret = uacce_read_qfrt_sz(dev);
242 [ # # ]: 0 : if (ret != 0)
243 : 0 : goto err;
244 : :
245 : 0 : ret = uacce_verify(dev);
246 [ # # ]: 0 : if (ret != 0)
247 : 0 : goto err;
248 : :
249 : 0 : TAILQ_INSERT_TAIL(&uacce_bus.device_list, dev, next);
250 : 0 : return 0;
251 : :
252 : 0 : err:
253 : 0 : free(dev);
254 : 0 : return ret;
255 : : }
256 : :
257 : : static int
258 : 216 : uacce_scan(void)
259 : : {
260 : : struct dirent *e;
261 : : DIR *dir;
262 : :
263 : 216 : dir = opendir(UACCE_BUS_CLASS_PATH);
264 [ + - ]: 216 : if (dir == NULL) {
265 : 216 : UACCE_BUS_LOG(INFO, "open %s failed!", UACCE_BUS_CLASS_PATH);
266 : 216 : return 0;
267 : : }
268 : :
269 [ # # ]: 0 : while ((e = readdir(dir)) != NULL) {
270 [ # # ]: 0 : if (e->d_name[0] == '.')
271 : 0 : continue;
272 : :
273 [ # # ]: 0 : if (strlen(e->d_name) >= RTE_DEV_NAME_MAX_LEN) {
274 : 0 : UACCE_BUS_LOG(WARNING, "uacce device name %s too long, skip it!",
275 : : e->d_name);
276 : 0 : continue;
277 : : }
278 : :
279 [ # # ]: 0 : if (rte_bus_device_is_ignored(&uacce_bus.bus, e->d_name))
280 : 0 : continue;
281 : :
282 [ # # ]: 0 : if (uacce_scan_one(e->d_name) < 0)
283 : 0 : goto error;
284 : : }
285 : 0 : closedir(dir);
286 : 0 : return 0;
287 : :
288 : : error:
289 : 0 : closedir(dir);
290 : 0 : return -1;
291 : : }
292 : :
293 : : static uint32_t
294 : 0 : uacce_calc_api_ver(const char *api, int *offset)
295 : : {
296 : 0 : int len = strlen(api);
297 : 0 : int end = len - 1;
298 : : unsigned long ver;
299 : :
300 [ # # # # ]: 0 : while (end >= 0 && isdigit(api[end]))
301 : 0 : end--;
302 : :
303 [ # # # # : 0 : if (end <= 0 || end == len - 1 || api[end] != 'v')
# # ]
304 : : return 0;
305 : :
306 : 0 : ver = strtoul(api + end + 1, NULL, 10);
307 [ # # ]: 0 : if (ver > UINT32_MAX)
308 : : return 0;
309 : :
310 [ # # ]: 0 : if (offset != NULL)
311 : 0 : *offset = end + 1;
312 : 0 : return (uint32_t)ver;
313 : : }
314 : :
315 : : static bool
316 : 0 : uacce_match_api(const struct rte_uacce_device *dev, bool forward_compat,
317 : : const struct rte_uacce_id *id_table)
318 : : {
319 : 0 : int dev_ver_off = 0, id_ver_off = 0;
320 : : uint32_t dev_ver, id_ver;
321 : :
322 [ # # ]: 0 : if (!forward_compat)
323 : 0 : return strcmp(id_table->dev_api, dev->api) == 0;
324 : :
325 : 0 : dev_ver = uacce_calc_api_ver(dev->api, &dev_ver_off);
326 : 0 : id_ver = uacce_calc_api_ver(id_table->dev_api, &id_ver_off);
327 [ # # ]: 0 : return dev_ver > 0 && id_ver > 0 && dev_ver_off == id_ver_off &&
328 [ # # # # : 0 : strncmp(id_table->dev_api, dev->api, dev_ver_off) == 0 &&
# # ]
329 : : dev_ver >= id_ver;
330 : : }
331 : :
332 : : static bool
333 : 0 : uacce_match(const struct rte_uacce_driver *dr, struct rte_uacce_device *dev)
334 : : {
335 : 0 : bool forward_compat = !!(dr->drv_flags & RTE_UACCE_DRV_FORWARD_COMPATIBILITY_DEV);
336 : 0 : uint32_t api_ver = uacce_calc_api_ver(dev->api, NULL);
337 : : const struct rte_uacce_id *id_table;
338 : : const char *map;
339 : : uint32_t len;
340 : :
341 [ # # ]: 0 : for (id_table = dr->id_table; id_table->dev_api != NULL; id_table++) {
342 [ # # ]: 0 : if (!uacce_match_api(dev, forward_compat, id_table))
343 : 0 : continue;
344 : :
345 [ # # ]: 0 : if (id_table->dev_alg == NULL) {
346 : 0 : dev->api_ver = api_ver;
347 : 0 : return true;
348 : : }
349 : :
350 : : /* The dev->algs's algrothims is separated by new line, for
351 : : * example: dev->algs could be: aaa\nbbbb\ncc, which has three
352 : : * algorithms: aaa, bbbb and cc.
353 : : * The id_table->dev_alg should be a single algrithm, e.g. bbbb.
354 : : */
355 : 0 : map = strstr(dev->algs, id_table->dev_alg);
356 [ # # ]: 0 : if (map == NULL)
357 : 0 : continue;
358 [ # # # # ]: 0 : if (map != dev->algs && map[-1] != '\n')
359 : 0 : continue;
360 : 0 : len = strlen(id_table->dev_alg);
361 [ # # ]: 0 : if (map[len] != '\0' && map[len] != '\n')
362 : 0 : continue;
363 : :
364 : 0 : dev->api_ver = api_ver;
365 : 0 : return true;
366 : : }
367 : :
368 : : return false;
369 : : }
370 : :
371 : : static int
372 : 0 : uacce_probe_one_driver(struct rte_uacce_driver *dr, struct rte_uacce_device *dev)
373 : : {
374 : 0 : const char *dev_name = dev->name;
375 : : bool already_probed;
376 : : int ret;
377 : :
378 [ # # ]: 0 : if (!uacce_match(dr, dev))
379 : : /* Match of device and driver failed */
380 : : return 1;
381 : :
382 : 0 : already_probed = rte_dev_is_probed(&dev->device);
383 [ # # ]: 0 : if (already_probed) {
384 : 0 : UACCE_BUS_INFO("device %s is already probed", dev_name);
385 : 0 : return -EEXIST;
386 : : }
387 : :
388 : 0 : UACCE_BUS_DEBUG("probe device %s using driver %s", dev_name, dr->driver.name);
389 : :
390 : 0 : ret = dr->probe(dr, dev);
391 [ # # ]: 0 : if (ret != 0) {
392 : 0 : UACCE_BUS_ERR("probe device %s with driver %s failed %d",
393 : : dev_name, dr->driver.name, ret);
394 : : } else {
395 : 0 : dev->device.driver = &dr->driver;
396 : 0 : dev->driver = dr;
397 : 0 : UACCE_BUS_DEBUG("probe device %s with driver %s success",
398 : : dev_name, dr->driver.name);
399 : : }
400 : :
401 : : return ret;
402 : : }
403 : :
404 : : static int
405 : 0 : uacce_probe_all_drivers(struct rte_uacce_device *dev)
406 : : {
407 : : struct rte_uacce_driver *dr;
408 : : int rc;
409 : :
410 [ # # ]: 0 : FOREACH_DRIVER_ON_UACCEBUS(dr) {
411 : 0 : rc = uacce_probe_one_driver(dr, dev);
412 [ # # ]: 0 : if (rc < 0)
413 : : /* negative value is an error */
414 : 0 : return rc;
415 [ # # ]: 0 : if (rc > 0)
416 : : /* positive value means driver doesn't support it */
417 : : continue;
418 : : return 0;
419 : : }
420 : :
421 : : return 1;
422 : : }
423 : :
424 : : static int
425 : 211 : uacce_probe(void)
426 : : {
427 : : size_t probed = 0, failed = 0;
428 : : struct rte_uacce_device *dev;
429 : : int ret;
430 : :
431 [ - + ]: 211 : FOREACH_DEVICE_ON_UACCEBUS(dev) {
432 : 0 : probed++;
433 : :
434 : 0 : ret = uacce_probe_all_drivers(dev);
435 [ # # ]: 0 : if (ret < 0) {
436 : 0 : UACCE_BUS_LOG(ERR, "Requested device %s cannot be used",
437 : : dev->name);
438 : 0 : rte_errno = errno;
439 : 0 : failed++;
440 : : }
441 : : }
442 : :
443 [ + - ]: 211 : return (probed && probed == failed) ? -1 : 0;
444 : : }
445 : :
446 : : static int
447 : 277 : uacce_cleanup(void)
448 : : {
449 : : struct rte_uacce_device *dev, *tmp_dev;
450 : : int error = 0;
451 : :
452 [ - + ]: 277 : RTE_TAILQ_FOREACH_SAFE(dev, &uacce_bus.device_list, next, tmp_dev) {
453 : 0 : struct rte_uacce_driver *dr = dev->driver;
454 : : int ret = 0;
455 : :
456 [ # # # # ]: 0 : if (dr == NULL || dr->remove == NULL)
457 : 0 : goto free;
458 : :
459 : 0 : ret = dr->remove(dev);
460 [ # # ]: 0 : if (ret < 0) {
461 : 0 : rte_errno = errno;
462 : : error = -1;
463 : : }
464 : 0 : dev->driver = NULL;
465 : 0 : dev->device.driver = NULL;
466 : :
467 : 0 : free:
468 [ # # ]: 0 : TAILQ_REMOVE(&uacce_bus.device_list, dev, next);
469 : 0 : free(dev);
470 : : }
471 : :
472 : 277 : return error;
473 : : }
474 : :
475 : : static int
476 : 0 : uacce_plug(struct rte_device *dev)
477 : : {
478 : 0 : return uacce_probe_all_drivers(RTE_DEV_TO_UACCE_DEV(dev));
479 : : }
480 : :
481 : : static int
482 : 0 : uacce_detach_dev(struct rte_uacce_device *dev)
483 : : {
484 : : struct rte_uacce_driver *dr;
485 : : int ret = 0;
486 : :
487 : 0 : dr = dev->driver;
488 : :
489 : 0 : UACCE_BUS_DEBUG("detach device %s using driver: %s", dev->device.name, dr->driver.name);
490 : :
491 [ # # ]: 0 : if (dr->remove) {
492 : 0 : ret = dr->remove(dev);
493 [ # # ]: 0 : if (ret < 0)
494 : : return ret;
495 : : }
496 : :
497 : 0 : dev->driver = NULL;
498 : 0 : dev->device.driver = NULL;
499 : :
500 : 0 : return 0;
501 : : }
502 : :
503 : : static int
504 : 0 : uacce_unplug(struct rte_device *dev)
505 : : {
506 : : struct rte_uacce_device *uacce_dev;
507 : : int ret;
508 : :
509 : 0 : uacce_dev = RTE_DEV_TO_UACCE_DEV(dev);
510 : 0 : ret = uacce_detach_dev(uacce_dev);
511 [ # # ]: 0 : if (ret == 0) {
512 [ # # ]: 0 : TAILQ_REMOVE(&uacce_bus.device_list, uacce_dev, next);
513 : 0 : rte_devargs_remove(dev->devargs);
514 : 0 : free(uacce_dev);
515 : : }
516 : :
517 : 0 : return ret;
518 : : }
519 : :
520 : : static struct rte_device *
521 : 0 : uacce_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, const void *data)
522 : : {
523 : : const struct rte_uacce_device *uacce_start;
524 : : struct rte_uacce_device *uacce_dev;
525 : :
526 [ # # ]: 0 : if (start != NULL) {
527 : 0 : uacce_start = RTE_DEV_TO_UACCE_DEV_CONST(start);
528 : 0 : uacce_dev = TAILQ_NEXT(uacce_start, next);
529 : : } else {
530 : 0 : uacce_dev = TAILQ_FIRST(&uacce_bus.device_list);
531 : : }
532 : :
533 [ # # ]: 0 : while (uacce_dev != NULL) {
534 [ # # ]: 0 : if (cmp(&uacce_dev->device, data) == 0)
535 : 0 : return &uacce_dev->device;
536 : 0 : uacce_dev = TAILQ_NEXT(uacce_dev, next);
537 : : }
538 : :
539 : : return NULL;
540 : : }
541 : :
542 : : static int
543 : 30 : uacce_parse(const char *name, void *addr)
544 : : {
545 : : const char **out = addr;
546 : : int ret;
547 : :
548 : 30 : ret = strncmp(name, UACCE_DEV_PREFIX, strlen(UACCE_DEV_PREFIX));
549 : :
550 [ - + ]: 30 : if (ret == 0 && addr)
551 : 0 : *out = name;
552 : :
553 : 30 : return ret;
554 : : }
555 : :
556 : : static int
557 : 0 : uacce_dev_match(const struct rte_device *dev, const void *_kvlist)
558 : : {
559 : : const char *key = uacce_params_keys[RTE_UACCE_PARAM_NAME];
560 : : const struct rte_kvargs *kvlist = _kvlist;
561 : : const char *name;
562 : :
563 : : /* no kvlist arg, all devices match. */
564 [ # # ]: 0 : if (kvlist == NULL)
565 : : return 0;
566 : :
567 : : /* if key is present in kvlist and does not match, filter device. */
568 : 0 : name = rte_kvargs_get(kvlist, key);
569 [ # # # # ]: 0 : if (name != NULL && strcmp(name, dev->name))
570 : 0 : return -1;
571 : :
572 : : return 0;
573 : : }
574 : :
575 : : static void *
576 : 0 : uacce_dev_iterate(const void *start, const char *str,
577 : : const struct rte_dev_iterator *it __rte_unused)
578 : : {
579 : : rte_bus_find_device_t find_device;
580 : : struct rte_kvargs *kvargs = NULL;
581 : : struct rte_device *dev;
582 : :
583 [ # # ]: 0 : if (str != NULL) {
584 : 0 : kvargs = rte_kvargs_parse(str, uacce_params_keys);
585 [ # # ]: 0 : if (kvargs == NULL) {
586 : 0 : UACCE_BUS_ERR("cannot parse argument list %s", str);
587 : 0 : return NULL;
588 : : }
589 : : }
590 : 0 : find_device = uacce_bus.bus.find_device;
591 : 0 : dev = find_device(start, uacce_dev_match, kvargs);
592 : 0 : rte_kvargs_free(kvargs);
593 : 0 : return dev;
594 : : }
595 : :
596 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_avail_queues)
597 : : int
598 : 0 : rte_uacce_avail_queues(struct rte_uacce_device *dev)
599 : : {
600 : 0 : int avails = 0;
601 : : int ret;
602 : :
603 : 0 : ret = uacce_read_attr_int(dev->dev_root, "available_instances", &avails);
604 [ # # ]: 0 : if (ret == 0)
605 : 0 : ret = avails;
606 : :
607 : 0 : return ret;
608 : : }
609 : :
610 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_queue_alloc)
611 : : int
612 : 0 : rte_uacce_queue_alloc(struct rte_uacce_device *dev, struct rte_uacce_qcontex *qctx)
613 : : {
614 : : memset(qctx, 0, sizeof(*qctx));
615 : :
616 : 0 : qctx->fd = open(dev->cdev_path, O_RDWR | O_CLOEXEC);
617 [ # # ]: 0 : if (qctx->fd >= 0) {
618 : 0 : qctx->dev = dev;
619 : 0 : return 0;
620 : : }
621 : :
622 : : return -EIO;
623 : : }
624 : :
625 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_queue_free)
626 : : void
627 : 0 : rte_uacce_queue_free(struct rte_uacce_qcontex *qctx)
628 : : {
629 [ # # ]: 0 : if (qctx->fd >= 0)
630 : 0 : close(qctx->fd);
631 : : memset(qctx, 0, sizeof(*qctx));
632 : 0 : qctx->fd = -1;
633 : 0 : }
634 : :
635 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_queue_start)
636 : : int
637 : 0 : rte_uacce_queue_start(struct rte_uacce_qcontex *qctx)
638 : : {
639 : : #define UACCE_CMD_START_Q _IO('W', 0)
640 : 0 : return ioctl(qctx->fd, UACCE_CMD_START_Q);
641 : : }
642 : :
643 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_queue_ioctl)
644 : : int
645 : 0 : rte_uacce_queue_ioctl(struct rte_uacce_qcontex *qctx, unsigned long cmd, void *arg)
646 : : {
647 [ # # ]: 0 : if (arg == NULL)
648 : 0 : return ioctl(qctx->fd, cmd);
649 : :
650 : 0 : return ioctl(qctx->fd, cmd, arg);
651 : : }
652 : :
653 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_queue_mmap)
654 : : void *
655 : 0 : rte_uacce_queue_mmap(struct rte_uacce_qcontex *qctx, enum rte_uacce_qfrt qfrt)
656 : : {
657 : 0 : size_t size = qctx->dev->qfrt_sz[qfrt];
658 : 0 : off_t off = qfrt * getpagesize();
659 : : void *addr;
660 : :
661 [ # # # # ]: 0 : if (size == 0 || qctx->qfrt_base[qfrt] != NULL) {
662 : 0 : UACCE_BUS_ERR("failed to mmap for %s, size is zero or already mmapped!",
663 : : qctx->dev->name);
664 : 0 : return NULL;
665 : : }
666 : :
667 : 0 : addr = rte_mem_map(NULL, size, RTE_PROT_READ | RTE_PROT_WRITE, RTE_MAP_SHARED,
668 : : qctx->fd, off);
669 [ # # ]: 0 : if (addr == NULL) {
670 : 0 : UACCE_BUS_ERR("failed to mmap for %s, qfrt %d err %s!",
671 : : qctx->dev->name, qfrt, rte_strerror(rte_errno));
672 : 0 : return NULL;
673 : : }
674 : 0 : qctx->qfrt_base[qfrt] = addr;
675 : :
676 : 0 : return addr;
677 : : }
678 : :
679 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_queue_unmap)
680 : : void
681 : 0 : rte_uacce_queue_unmap(struct rte_uacce_qcontex *qctx, enum rte_uacce_qfrt qfrt)
682 : : {
683 [ # # ]: 0 : if (qctx->qfrt_base[qfrt] != NULL) {
684 : 0 : rte_mem_unmap(qctx->qfrt_base[qfrt], qctx->dev->qfrt_sz[qfrt]);
685 : 0 : qctx->qfrt_base[qfrt] = NULL;
686 : : }
687 : 0 : }
688 : :
689 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_register)
690 : : void
691 : 284 : rte_uacce_register(struct rte_uacce_driver *driver)
692 : : {
693 : 284 : TAILQ_INSERT_TAIL(&uacce_bus.driver_list, driver, next);
694 : 284 : driver->bus = &uacce_bus;
695 : 284 : }
696 : :
697 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_uacce_unregister)
698 : : void
699 : 0 : rte_uacce_unregister(struct rte_uacce_driver *driver)
700 : : {
701 [ # # ]: 0 : TAILQ_REMOVE(&uacce_bus.driver_list, driver, next);
702 : 0 : driver->bus = NULL;
703 : 0 : }
704 : :
705 : : static struct rte_uacce_bus uacce_bus = {
706 : : .bus = {
707 : : .scan = uacce_scan,
708 : : .probe = uacce_probe,
709 : : .cleanup = uacce_cleanup,
710 : : .plug = uacce_plug,
711 : : .unplug = uacce_unplug,
712 : : .find_device = uacce_find_device,
713 : : .parse = uacce_parse,
714 : : .dev_iterate = uacce_dev_iterate,
715 : : },
716 : : .device_list = TAILQ_HEAD_INITIALIZER(uacce_bus.device_list),
717 : : .driver_list = TAILQ_HEAD_INITIALIZER(uacce_bus.driver_list),
718 : : };
719 : :
720 : 284 : RTE_REGISTER_BUS(uacce, uacce_bus.bus);
721 [ - + ]: 284 : RTE_LOG_REGISTER_DEFAULT(uacce_bus_logtype, NOTICE);
|