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