Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright (c) 2015-2016 Freescale Semiconductor, Inc. All rights reserved.
4 : : * Copyright 2016-2024 NXP
5 : : *
6 : : */
7 : :
8 : : #include <unistd.h>
9 : : #include <stdio.h>
10 : : #include <sys/types.h>
11 : : #include <string.h>
12 : : #include <stdlib.h>
13 : : #include <fcntl.h>
14 : : #include <errno.h>
15 : : #include <sys/ioctl.h>
16 : : #include <sys/stat.h>
17 : : #include <sys/mman.h>
18 : : #include <sys/vfs.h>
19 : : #include <libgen.h>
20 : : #include <dirent.h>
21 : : #include <sys/eventfd.h>
22 : : #include <ctype.h>
23 : :
24 : : #include <eal_export.h>
25 : : #include <eal_filesystem.h>
26 : : #include <rte_mbuf.h>
27 : : #include <ethdev_driver.h>
28 : : #include <rte_malloc.h>
29 : : #include <rte_memcpy.h>
30 : : #include <rte_string_fns.h>
31 : : #include <rte_cycles.h>
32 : : #include <rte_kvargs.h>
33 : : #include <dev_driver.h>
34 : : #include <rte_eal_memconfig.h>
35 : : #include <eal_vfio.h>
36 : :
37 : : #include "private.h"
38 : : #include "fslmc_vfio.h"
39 : : #include "fslmc_logs.h"
40 : : #include <mc/fsl_dpmng.h>
41 : :
42 : : #include "portal/dpaa2_hw_pvt.h"
43 : : #include "portal/dpaa2_hw_dpio.h"
44 : :
45 : : #define FSLMC_VFIO_MP "fslmc_vfio_mp_sync"
46 : :
47 : : /* Container is composed by multiple groups, however,
48 : : * now each process only supports single group with in container.
49 : : */
50 : : static struct fslmc_vfio_container s_vfio_container;
51 : : /* Currently we only support single group/process. */
52 : : static const char *fslmc_group; /* dprc.x*/
53 : : static void *(*rte_mcp_ptr_list);
54 : :
55 : : struct fslmc_dmaseg {
56 : : uint64_t vaddr;
57 : : uint64_t iova;
58 : : uint64_t size;
59 : :
60 : : TAILQ_ENTRY(fslmc_dmaseg) next;
61 : : };
62 : :
63 : : TAILQ_HEAD(fslmc_dmaseg_list, fslmc_dmaseg);
64 : :
65 : : struct fslmc_dmaseg_list fslmc_memsegs =
66 : : TAILQ_HEAD_INITIALIZER(fslmc_memsegs);
67 : : struct fslmc_dmaseg_list fslmc_iosegs =
68 : : TAILQ_HEAD_INITIALIZER(fslmc_iosegs);
69 : :
70 : : static uint64_t fslmc_mem_va2iova = RTE_BAD_IOVA;
71 : : static int fslmc_mem_map_num;
72 : :
73 : : struct fslmc_mem_param {
74 : : struct vfio_mp_param mp_param;
75 : : struct fslmc_dmaseg_list memsegs;
76 : : struct fslmc_dmaseg_list iosegs;
77 : : uint64_t mem_va2iova;
78 : : int mem_map_num;
79 : : };
80 : :
81 : : enum {
82 : : FSLMC_VFIO_SOCKET_REQ_CONTAINER = 0x100,
83 : : FSLMC_VFIO_SOCKET_REQ_GROUP,
84 : : FSLMC_VFIO_SOCKET_REQ_MEM
85 : : };
86 : :
87 : : RTE_EXPORT_INTERNAL_SYMBOL(dpaa2_get_mcp_ptr)
88 : : void *
89 : 0 : dpaa2_get_mcp_ptr(int portal_idx)
90 : : {
91 [ # # ]: 0 : if (rte_mcp_ptr_list)
92 : 0 : return rte_mcp_ptr_list[portal_idx];
93 : : else
94 : : return NULL;
95 : : }
96 : :
97 : : static struct rte_dpaa2_object_list dpaa2_obj_list =
98 : : TAILQ_HEAD_INITIALIZER(dpaa2_obj_list);
99 : :
100 : : static uint64_t
101 : 0 : fslmc_io_virt2phy(const void *virtaddr)
102 : : {
103 : 0 : FILE *fp = fopen("/proc/self/maps", "r");
104 : 0 : char *line = NULL;
105 : : size_t linesz;
106 : : uint64_t start, end, phy;
107 : 0 : const uint64_t va = (const uint64_t)virtaddr;
108 : : char tmp[1024];
109 : : int ret;
110 : :
111 [ # # ]: 0 : if (!fp)
112 : : return RTE_BAD_IOVA;
113 [ # # ]: 0 : while (getdelim(&line, &linesz, '\n', fp) > 0) {
114 : 0 : char *ptr = line;
115 : : int n;
116 : :
117 : : /** Parse virtual address range.*/
118 : : n = 0;
119 [ # # # # ]: 0 : while (*ptr && !isspace(*ptr)) {
120 : 0 : tmp[n] = *ptr;
121 : 0 : ptr++;
122 : 0 : n++;
123 : : }
124 : 0 : tmp[n] = 0;
125 : 0 : ret = sscanf(tmp, "%" SCNx64 "-%" SCNx64, &start, &end);
126 [ # # ]: 0 : if (ret != 2)
127 : 0 : continue;
128 [ # # # # ]: 0 : if (va < start || va >= end)
129 : 0 : continue;
130 : :
131 : : /** This virtual address is in this segment.*/
132 : 0 : while (*ptr == ' ' || *ptr == 'r' ||
133 : : *ptr == 'w' || *ptr == 's' ||
134 [ # # ]: 0 : *ptr == 'p' || *ptr == 'x' ||
135 : : *ptr == '-')
136 : 0 : ptr++;
137 : :
138 : : /** Extract phy address*/
139 : : n = 0;
140 [ # # # # ]: 0 : while (*ptr && !isspace(*ptr)) {
141 : 0 : tmp[n] = *ptr;
142 : 0 : ptr++;
143 : 0 : n++;
144 : : }
145 : 0 : tmp[n] = 0;
146 : 0 : phy = strtoul(tmp, 0, 16);
147 [ # # ]: 0 : if (!phy)
148 : 0 : continue;
149 : :
150 : 0 : fclose(fp);
151 : 0 : return phy + va - start;
152 : : }
153 : :
154 : 0 : fclose(fp);
155 : 0 : return RTE_BAD_IOVA;
156 : : }
157 : :
158 : : /*register a fslmc bus based dpaa2 driver */
159 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_object_register)
160 : : void
161 : 1512 : rte_fslmc_object_register(struct rte_dpaa2_object *object)
162 : : {
163 [ - + ]: 1512 : RTE_VERIFY(object);
164 : :
165 : 1512 : TAILQ_INSERT_TAIL(&dpaa2_obj_list, object, next);
166 : 1512 : }
167 : :
168 : : static const char *
169 : : fslmc_vfio_get_group_name(void)
170 : : {
171 : 252 : return fslmc_group;
172 : : }
173 : :
174 : : static void
175 : : fslmc_vfio_set_group_name(const char *group_name)
176 : : {
177 : 0 : fslmc_group = group_name;
178 : : }
179 : :
180 : : static int
181 : 0 : fslmc_vfio_add_group(int vfio_group_fd,
182 : : int iommu_group_num, const char *group_name)
183 : : {
184 : : struct fslmc_vfio_group *group;
185 : :
186 : 0 : group = rte_zmalloc(NULL, sizeof(struct fslmc_vfio_group), 0);
187 [ # # ]: 0 : if (!group)
188 : : return -ENOMEM;
189 : 0 : group->fd = vfio_group_fd;
190 : 0 : group->groupid = iommu_group_num;
191 : 0 : rte_strscpy(group->group_name, group_name, sizeof(group->group_name));
192 [ # # ]: 0 : if (rte_vfio_noiommu_is_enabled() > 0)
193 : 0 : group->iommu_type = RTE_VFIO_NOIOMMU;
194 : : else
195 : 0 : group->iommu_type = VFIO_TYPE1_IOMMU;
196 [ # # ]: 0 : LIST_INSERT_HEAD(&s_vfio_container.groups, group, next);
197 : :
198 : 0 : return 0;
199 : : }
200 : :
201 : : static int
202 : 0 : fslmc_vfio_clear_group(int vfio_group_fd)
203 : : {
204 : : struct fslmc_vfio_group *group;
205 : : struct fslmc_vfio_device *dev;
206 : : int clear = 0;
207 : :
208 [ # # ]: 0 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
209 [ # # ]: 0 : if (group->fd == vfio_group_fd) {
210 [ # # ]: 0 : LIST_FOREACH(dev, &group->vfio_devices, next)
211 [ # # ]: 0 : LIST_REMOVE(dev, next);
212 : :
213 : 0 : close(vfio_group_fd);
214 [ # # ]: 0 : LIST_REMOVE(group, next);
215 : 0 : rte_free(group);
216 : : clear = 1;
217 : :
218 : 0 : break;
219 : : }
220 : : }
221 : :
222 [ # # ]: 0 : if (LIST_EMPTY(&s_vfio_container.groups)) {
223 [ # # ]: 0 : if (s_vfio_container.fd > 0)
224 : 0 : close(s_vfio_container.fd);
225 : :
226 : 0 : s_vfio_container.fd = -1;
227 : : }
228 [ # # ]: 0 : if (clear)
229 : 0 : return 0;
230 : :
231 : : return -ENODEV;
232 : : }
233 : :
234 : : static int
235 : : fslmc_vfio_connect_container(int vfio_group_fd)
236 : : {
237 : : struct fslmc_vfio_group *group;
238 : :
239 [ # # # # ]: 0 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
240 [ # # # # ]: 0 : if (group->fd == vfio_group_fd) {
241 : 0 : group->connected = 1;
242 : :
243 : 0 : return 0;
244 : : }
245 : : }
246 : :
247 : : return -ENODEV;
248 : : }
249 : :
250 : : static int
251 : : fslmc_vfio_container_connected(int vfio_group_fd)
252 : : {
253 : : struct fslmc_vfio_group *group;
254 : :
255 [ # # # # : 0 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
# # # # ]
256 [ # # # # : 0 : if (group->fd == vfio_group_fd) {
# # # # ]
257 [ # # # # : 0 : if (group->connected)
# # # # ]
258 : : return 1;
259 : : }
260 : : }
261 : : return 0;
262 : : }
263 : :
264 : : static int
265 : : fslmc_vfio_iommu_type(int vfio_group_fd)
266 : : {
267 : : struct fslmc_vfio_group *group;
268 : :
269 [ # # # # : 0 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
# # ]
270 [ # # # # : 0 : if (group->fd == vfio_group_fd)
# # ]
271 : 0 : return group->iommu_type;
272 : : }
273 : : return -ENODEV;
274 : : }
275 : :
276 : : static int
277 : 252 : fslmc_vfio_group_fd_by_name(const char *group_name)
278 : : {
279 : : struct fslmc_vfio_group *group;
280 : :
281 [ - + ]: 252 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
282 [ # # ]: 0 : if (!strcmp(group->group_name, group_name))
283 : 0 : return group->fd;
284 : : }
285 : : return -ENODEV;
286 : : }
287 : :
288 : : static int
289 : : fslmc_vfio_group_fd_by_id(int group_id)
290 : : {
291 : : struct fslmc_vfio_group *group;
292 : :
293 [ # # ]: 0 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
294 [ # # ]: 0 : if (group->groupid == group_id)
295 : 0 : return group->fd;
296 : : }
297 : : return -ENODEV;
298 : : }
299 : :
300 : : static int
301 : 0 : fslmc_vfio_group_add_dev(int vfio_group_fd,
302 : : int dev_fd, const char *name)
303 : : {
304 : : struct fslmc_vfio_group *group;
305 : : struct fslmc_vfio_device *dev;
306 : :
307 [ # # ]: 0 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
308 [ # # ]: 0 : if (group->fd == vfio_group_fd) {
309 : 0 : dev = rte_zmalloc(NULL,
310 : : sizeof(struct fslmc_vfio_device), 0);
311 : 0 : dev->fd = dev_fd;
312 : 0 : rte_strscpy(dev->dev_name, name, sizeof(dev->dev_name));
313 [ # # ]: 0 : LIST_INSERT_HEAD(&group->vfio_devices, dev, next);
314 : 0 : return 0;
315 : : }
316 : : }
317 : : return -ENODEV;
318 : : }
319 : :
320 : : static int
321 : 0 : fslmc_vfio_group_remove_dev(int vfio_group_fd,
322 : : const char *name)
323 : : {
324 : : struct fslmc_vfio_group *group = NULL;
325 : : struct fslmc_vfio_device *dev;
326 : : int removed = 0;
327 : :
328 [ # # ]: 0 : LIST_FOREACH(group, &s_vfio_container.groups, next) {
329 [ # # ]: 0 : if (group->fd == vfio_group_fd)
330 : : break;
331 : : }
332 : :
333 [ # # ]: 0 : if (group) {
334 [ # # ]: 0 : LIST_FOREACH(dev, &group->vfio_devices, next) {
335 [ # # ]: 0 : if (!strcmp(dev->dev_name, name)) {
336 [ # # ]: 0 : LIST_REMOVE(dev, next);
337 : : removed = 1;
338 : : break;
339 : : }
340 : : }
341 : : }
342 : :
343 : : if (removed)
344 : 0 : return 0;
345 : :
346 : : return -ENODEV;
347 : : }
348 : :
349 : : static int
350 : : fslmc_vfio_container_fd(void)
351 : : {
352 : 0 : return s_vfio_container.fd;
353 : : }
354 : :
355 : : static int
356 : 0 : fslmc_get_group_id(const char *group_name,
357 : : int *groupid)
358 : : {
359 : : int ret;
360 : :
361 : : /* get group number */
362 : 0 : ret = rte_vfio_get_group_num(SYSFS_FSL_MC_DEVICES,
363 : : group_name, groupid);
364 [ # # ]: 0 : if (ret <= 0) {
365 : 0 : DPAA2_BUS_ERR("Find %s IOMMU group", group_name);
366 [ # # ]: 0 : if (ret < 0)
367 : : return ret;
368 : :
369 : 0 : return -EIO;
370 : : }
371 : :
372 : 0 : DPAA2_BUS_DEBUG("GROUP(%s) has VFIO iommu group id = %d",
373 : : group_name, *groupid);
374 : :
375 : 0 : return 0;
376 : : }
377 : :
378 : : static int
379 : 0 : fslmc_vfio_open_group_fd(const char *group_name)
380 : : {
381 : : int vfio_group_fd;
382 : : char filename[PATH_MAX];
383 : : struct rte_mp_msg mp_req, *mp_rep;
384 : 0 : struct rte_mp_reply mp_reply = {0};
385 : 0 : struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
386 : : struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
387 : : int iommu_group_num, ret;
388 : :
389 : 0 : vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name);
390 [ # # ]: 0 : if (vfio_group_fd > 0)
391 : : return vfio_group_fd;
392 : :
393 : 0 : ret = fslmc_get_group_id(group_name, &iommu_group_num);
394 [ # # ]: 0 : if (ret)
395 : : return ret;
396 : : /* if primary, try to open the group */
397 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
398 : : /* try regular group format */
399 : 0 : snprintf(filename, sizeof(filename),
400 : : VFIO_GROUP_FMT, iommu_group_num);
401 : : vfio_group_fd = open(filename, O_RDWR);
402 : :
403 : 0 : goto add_vfio_group;
404 : : }
405 : : /* if we're in a secondary process, request group fd from the primary
406 : : * process via mp channel.
407 : : */
408 : 0 : p->req = FSLMC_VFIO_SOCKET_REQ_GROUP;
409 : 0 : p->group_num = iommu_group_num;
410 : 0 : rte_strscpy(mp_req.name, FSLMC_VFIO_MP, sizeof(mp_req.name));
411 : 0 : mp_req.len_param = sizeof(*p);
412 : 0 : mp_req.num_fds = 0;
413 : :
414 : : vfio_group_fd = -1;
415 [ # # ]: 0 : if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
416 [ # # ]: 0 : mp_reply.nb_received == 1) {
417 : 0 : mp_rep = &mp_reply.msgs[0];
418 : : p = (struct vfio_mp_param *)mp_rep->param;
419 [ # # # # ]: 0 : if (p->result == SOCKET_OK && mp_rep->num_fds == 1)
420 : 0 : vfio_group_fd = mp_rep->fds[0];
421 [ # # ]: 0 : else if (p->result == SOCKET_NO_FD)
422 : 0 : DPAA2_BUS_ERR("Bad VFIO group fd");
423 : : }
424 : :
425 : 0 : free(mp_reply.msgs);
426 : :
427 : 0 : add_vfio_group:
428 [ # # ]: 0 : if (vfio_group_fd < 0) {
429 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
430 : 0 : DPAA2_BUS_ERR("Open VFIO group(%s) failed(%d)",
431 : : filename, vfio_group_fd);
432 : : } else {
433 : 0 : DPAA2_BUS_ERR("Cannot request group fd(%d)",
434 : : vfio_group_fd);
435 : : }
436 : : } else {
437 : 0 : ret = fslmc_vfio_add_group(vfio_group_fd, iommu_group_num,
438 : : group_name);
439 [ # # ]: 0 : if (ret) {
440 : 0 : close(vfio_group_fd);
441 : 0 : return ret;
442 : : }
443 : : }
444 : :
445 : : return vfio_group_fd;
446 : : }
447 : :
448 : : static int
449 : 0 : fslmc_vfio_check_extensions(int vfio_container_fd)
450 : : {
451 : : int ret;
452 : : uint32_t idx, n_extensions = 0;
453 : : static const int type_id[] = {RTE_VFIO_TYPE1, RTE_VFIO_SPAPR,
454 : : RTE_VFIO_NOIOMMU};
455 : : static const char * const type_id_nm[] = {"Type 1",
456 : : "sPAPR", "No-IOMMU"};
457 : :
458 [ # # ]: 0 : for (idx = 0; idx < RTE_DIM(type_id); idx++) {
459 : 0 : ret = ioctl(vfio_container_fd, VFIO_CHECK_EXTENSION,
460 : 0 : type_id[idx]);
461 [ # # ]: 0 : if (ret < 0) {
462 : 0 : DPAA2_BUS_ERR("Could not get IOMMU type, error %i (%s)",
463 : : errno, strerror(errno));
464 : 0 : close(vfio_container_fd);
465 : 0 : return -errno;
466 [ # # ]: 0 : } else if (ret == 1) {
467 : : /* we found a supported extension */
468 : 0 : n_extensions++;
469 : : }
470 [ # # ]: 0 : DPAA2_BUS_DEBUG("IOMMU type %d (%s) is %s",
471 : : type_id[idx], type_id_nm[idx],
472 : : ret ? "supported" : "not supported");
473 : : }
474 : :
475 : : /* if we didn't find any supported IOMMU types, fail */
476 [ # # ]: 0 : if (!n_extensions) {
477 : 0 : close(vfio_container_fd);
478 : 0 : return -EIO;
479 : : }
480 : :
481 : : return 0;
482 : : }
483 : :
484 : : static int
485 : 0 : fslmc_vfio_open_container_fd(void)
486 : : {
487 : : int ret, vfio_container_fd;
488 : : struct rte_mp_msg mp_req, *mp_rep;
489 : 0 : struct rte_mp_reply mp_reply = {0};
490 : 0 : struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
491 : : struct vfio_mp_param *p = (void *)mp_req.param;
492 : :
493 [ # # ]: 0 : if (fslmc_vfio_container_fd() > 0)
494 : : return fslmc_vfio_container_fd();
495 : :
496 : : /* if we're in a primary process, try to open the container */
497 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
498 : : vfio_container_fd = open(VFIO_CONTAINER_PATH, O_RDWR);
499 [ # # ]: 0 : if (vfio_container_fd < 0) {
500 : 0 : DPAA2_BUS_ERR("Open VFIO container(%s), err(%d)",
501 : : VFIO_CONTAINER_PATH, vfio_container_fd);
502 : : ret = vfio_container_fd;
503 : 0 : goto err_exit;
504 : : }
505 : :
506 : : /* check VFIO API version */
507 : 0 : ret = ioctl(vfio_container_fd, VFIO_GET_API_VERSION);
508 [ # # ]: 0 : if (ret < 0) {
509 : 0 : DPAA2_BUS_ERR("Get VFIO API version(%d)",
510 : : ret);
511 [ # # ]: 0 : } else if (ret != VFIO_API_VERSION) {
512 : 0 : DPAA2_BUS_ERR("Unsupported VFIO API version(%d)",
513 : : ret);
514 : : ret = -ENOTSUP;
515 : : }
516 [ # # ]: 0 : if (ret < 0) {
517 : 0 : close(vfio_container_fd);
518 : 0 : goto err_exit;
519 : : }
520 : :
521 : 0 : ret = fslmc_vfio_check_extensions(vfio_container_fd);
522 [ # # ]: 0 : if (ret) {
523 : 0 : DPAA2_BUS_ERR("Unsupported IOMMU extensions found(%d)",
524 : : ret);
525 : 0 : close(vfio_container_fd);
526 : 0 : goto err_exit;
527 : : }
528 : :
529 : 0 : goto success_exit;
530 : : }
531 : : /*
532 : : * if we're in a secondary process, request container fd from the
533 : : * primary process via mp channel
534 : : */
535 : 0 : p->req = FSLMC_VFIO_SOCKET_REQ_CONTAINER;
536 : 0 : rte_strscpy(mp_req.name, FSLMC_VFIO_MP, sizeof(mp_req.name));
537 : 0 : mp_req.len_param = sizeof(*p);
538 : 0 : mp_req.num_fds = 0;
539 : :
540 : : vfio_container_fd = -1;
541 : 0 : ret = rte_mp_request_sync(&mp_req, &mp_reply, &ts);
542 [ # # ]: 0 : if (ret)
543 : 0 : goto err_exit;
544 : :
545 [ # # ]: 0 : if (mp_reply.nb_received != 1) {
546 : : ret = -EIO;
547 : 0 : goto err_exit;
548 : : }
549 : :
550 : 0 : mp_rep = &mp_reply.msgs[0];
551 : : p = (void *)mp_rep->param;
552 [ # # # # ]: 0 : if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
553 : 0 : vfio_container_fd = mp_rep->fds[0];
554 : 0 : free(mp_reply.msgs);
555 : : }
556 : :
557 : 0 : success_exit:
558 : 0 : s_vfio_container.fd = vfio_container_fd;
559 : :
560 : 0 : return vfio_container_fd;
561 : :
562 : 0 : err_exit:
563 : 0 : free(mp_reply.msgs);
564 : 0 : DPAA2_BUS_ERR("Open container fd err(%d)", ret);
565 : 0 : return ret;
566 : : }
567 : :
568 : : int
569 : 0 : fslmc_get_container_group(const char *group_name,
570 : : int *groupid)
571 : : {
572 : : int ret;
573 : :
574 [ # # ]: 0 : if (!group_name) {
575 : 0 : DPAA2_BUS_ERR("No group name provided!");
576 : :
577 : 0 : return -EINVAL;
578 : : }
579 : 0 : ret = fslmc_get_group_id(group_name, groupid);
580 [ # # ]: 0 : if (ret)
581 : : return ret;
582 : :
583 : : fslmc_vfio_set_group_name(group_name);
584 : :
585 : 0 : return 0;
586 : : }
587 : :
588 : : static int
589 : 0 : fslmc_vfio_mp_primary(const struct rte_mp_msg *msg,
590 : : const void *peer)
591 : : {
592 : : int fd = -1;
593 : : int ret;
594 : : struct rte_mp_msg reply;
595 : : struct vfio_mp_param *r = (void *)reply.param;
596 : : const struct vfio_mp_param *m = (const void *)msg->param;
597 : : struct fslmc_mem_param *map;
598 : :
599 [ # # ]: 0 : if (msg->len_param != sizeof(*m)) {
600 : 0 : DPAA2_BUS_ERR("Invalid msg size(%d) for req(%d)",
601 : : msg->len_param, m->req);
602 : 0 : return -EINVAL;
603 : : }
604 : :
605 : : memset(&reply, 0, sizeof(reply));
606 : :
607 [ # # # # ]: 0 : switch (m->req) {
608 : 0 : case FSLMC_VFIO_SOCKET_REQ_GROUP:
609 : 0 : r->req = FSLMC_VFIO_SOCKET_REQ_GROUP;
610 : 0 : r->group_num = m->group_num;
611 : : fd = fslmc_vfio_group_fd_by_id(m->group_num);
612 [ # # ]: 0 : if (fd < 0) {
613 : 0 : r->result = SOCKET_ERR;
614 [ # # ]: 0 : } else if (!fd) {
615 : : /* if group exists but isn't bound to VFIO driver */
616 : 0 : r->result = SOCKET_NO_FD;
617 : : } else {
618 : : /* if group exists and is bound to VFIO driver */
619 : : r->result = SOCKET_OK;
620 : 0 : reply.num_fds = 1;
621 : 0 : reply.fds[0] = fd;
622 : : }
623 : 0 : reply.len_param = sizeof(*r);
624 : 0 : break;
625 : 0 : case FSLMC_VFIO_SOCKET_REQ_CONTAINER:
626 : 0 : r->req = FSLMC_VFIO_SOCKET_REQ_CONTAINER;
627 : : fd = fslmc_vfio_container_fd();
628 [ # # ]: 0 : if (fd <= 0) {
629 : 0 : r->result = SOCKET_ERR;
630 : : } else {
631 : : r->result = SOCKET_OK;
632 : 0 : reply.num_fds = 1;
633 : 0 : reply.fds[0] = fd;
634 : : }
635 : 0 : reply.len_param = sizeof(*r);
636 : 0 : break;
637 : 0 : case FSLMC_VFIO_SOCKET_REQ_MEM:
638 : : map = (void *)reply.param;
639 : : r = &map->mp_param;
640 : 0 : r->req = FSLMC_VFIO_SOCKET_REQ_MEM;
641 : : r->result = SOCKET_OK;
642 : 0 : map->memsegs = fslmc_memsegs;
643 : 0 : map->iosegs = fslmc_iosegs;
644 : 0 : map->mem_va2iova = fslmc_mem_va2iova;
645 : 0 : map->mem_map_num = fslmc_mem_map_num;
646 : 0 : reply.len_param = sizeof(struct fslmc_mem_param);
647 : 0 : break;
648 : 0 : default:
649 : 0 : DPAA2_BUS_ERR("VFIO received invalid message(%08x)",
650 : : m->req);
651 : 0 : return -ENOTSUP;
652 : : }
653 : :
654 : 0 : rte_strscpy(reply.name, FSLMC_VFIO_MP, sizeof(reply.name));
655 : 0 : ret = rte_mp_reply(&reply, peer);
656 : :
657 : 0 : return ret;
658 : : }
659 : :
660 : : static int
661 : 0 : fslmc_vfio_mp_sync_mem_req(void)
662 : : {
663 : : struct rte_mp_msg mp_req, *mp_rep;
664 : 0 : struct rte_mp_reply mp_reply = {0};
665 : 0 : struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
666 : : int ret = 0;
667 : : struct vfio_mp_param *mp_param;
668 : : struct fslmc_mem_param *mem_rsp;
669 : :
670 : : mp_param = (void *)mp_req.param;
671 : : memset(&mp_req, 0, sizeof(struct rte_mp_msg));
672 : 0 : mp_param->req = FSLMC_VFIO_SOCKET_REQ_MEM;
673 : 0 : rte_strscpy(mp_req.name, FSLMC_VFIO_MP, sizeof(mp_req.name));
674 : 0 : mp_req.len_param = sizeof(struct vfio_mp_param);
675 [ # # ]: 0 : if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
676 [ # # ]: 0 : mp_reply.nb_received == 1) {
677 : 0 : mp_rep = &mp_reply.msgs[0];
678 : : mem_rsp = (struct fslmc_mem_param *)mp_rep->param;
679 [ # # ]: 0 : if (mem_rsp->mp_param.result == SOCKET_OK) {
680 : 0 : fslmc_memsegs = mem_rsp->memsegs;
681 : 0 : fslmc_mem_va2iova = mem_rsp->mem_va2iova;
682 : 0 : fslmc_mem_map_num = mem_rsp->mem_map_num;
683 : : } else {
684 : 0 : DPAA2_BUS_ERR("Bad MEM SEG");
685 : : ret = -EINVAL;
686 : : }
687 : : } else {
688 : : ret = -EINVAL;
689 : : }
690 : 0 : free(mp_reply.msgs);
691 : :
692 : 0 : return ret;
693 : : }
694 : :
695 : : static int
696 : 0 : fslmc_vfio_mp_sync_setup(void)
697 : : {
698 : : int ret;
699 : :
700 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
701 : 0 : ret = rte_mp_action_register(FSLMC_VFIO_MP,
702 : : fslmc_vfio_mp_primary);
703 [ # # # # ]: 0 : if (ret && rte_errno != ENOTSUP)
704 : 0 : return ret;
705 : : } else {
706 : 0 : ret = fslmc_vfio_mp_sync_mem_req();
707 [ # # ]: 0 : if (ret)
708 : 0 : return ret;
709 : : }
710 : :
711 : : return 0;
712 : : }
713 : :
714 : : static int
715 : 0 : vfio_connect_container(int vfio_container_fd,
716 : : int vfio_group_fd)
717 : : {
718 : : int ret;
719 : : int iommu_type;
720 : :
721 [ # # ]: 0 : if (fslmc_vfio_container_connected(vfio_group_fd)) {
722 : 0 : DPAA2_BUS_WARN("VFIO FD(%d) has connected to container",
723 : : vfio_group_fd);
724 : 0 : return 0;
725 : : }
726 : :
727 : : iommu_type = fslmc_vfio_iommu_type(vfio_group_fd);
728 [ # # ]: 0 : if (iommu_type < 0) {
729 : 0 : DPAA2_BUS_ERR("Get iommu type(%d)", iommu_type);
730 : :
731 : 0 : return iommu_type;
732 : : }
733 : :
734 : : /* Check whether support for SMMU type IOMMU present or not */
735 : 0 : ret = ioctl(vfio_container_fd, VFIO_CHECK_EXTENSION, iommu_type);
736 [ # # ]: 0 : if (ret <= 0) {
737 : 0 : DPAA2_BUS_ERR("Unsupported IOMMU type(%d) ret(%d), err(%d)",
738 : : iommu_type, ret, -errno);
739 : 0 : return -EINVAL;
740 : : }
741 : :
742 : 0 : ret = ioctl(vfio_group_fd, VFIO_GROUP_SET_CONTAINER,
743 : : &vfio_container_fd);
744 [ # # ]: 0 : if (ret) {
745 : 0 : DPAA2_BUS_ERR("Set group container ret(%d), err(%d)",
746 : : ret, -errno);
747 : :
748 : 0 : return ret;
749 : : }
750 : :
751 : 0 : ret = ioctl(vfio_container_fd, VFIO_SET_IOMMU, iommu_type);
752 [ # # ]: 0 : if (ret) {
753 : 0 : DPAA2_BUS_ERR("Set iommu ret(%d), err(%d)",
754 : : ret, -errno);
755 : :
756 : 0 : return ret;
757 : : }
758 : :
759 : : return fslmc_vfio_connect_container(vfio_group_fd);
760 : : }
761 : :
762 : : static int
763 : 0 : fslmc_map_dma(uint64_t vaddr, rte_iova_t iovaddr, size_t len)
764 : : {
765 : 0 : struct vfio_iommu_type1_dma_map dma_map = {
766 : : .argsz = sizeof(struct vfio_iommu_type1_dma_map),
767 : : .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE,
768 : : };
769 : : int ret, fd, is_io = 0;
770 : : const char *group_name = fslmc_vfio_get_group_name();
771 : : struct fslmc_dmaseg *dmaseg = NULL;
772 : : uint64_t phy = 0;
773 : :
774 [ # # ]: 0 : if (rte_eal_iova_mode() == RTE_IOVA_VA) {
775 [ # # ]: 0 : if (vaddr != iovaddr) {
776 : 0 : DPAA2_BUS_ERR("IOVA:VA(%" PRIx64 " : %" PRIx64 ") %s",
777 : : iovaddr, vaddr,
778 : : "should be 1:1 for VA mode");
779 : :
780 : 0 : return -EINVAL;
781 : : }
782 : : }
783 : :
784 : 0 : phy = rte_mem_virt2phy((const void *)(uintptr_t)vaddr);
785 [ # # ]: 0 : if (phy == RTE_BAD_IOVA) {
786 : 0 : phy = fslmc_io_virt2phy((const void *)(uintptr_t)vaddr);
787 [ # # ]: 0 : if (phy == RTE_BAD_IOVA)
788 : : return -ENOMEM;
789 : : is_io = 1;
790 [ # # ]: 0 : } else if (fslmc_mem_va2iova != RTE_BAD_IOVA &&
791 [ # # ]: 0 : fslmc_mem_va2iova != (iovaddr - vaddr)) {
792 : 0 : DPAA2_BUS_WARN("Multiple MEM PA<->VA conversions.");
793 : : }
794 : 0 : DPAA2_BUS_DEBUG("%s(%zu): VA(%" PRIx64 "):IOVA(%" PRIx64 "):PHY(%" PRIx64 ")",
795 : : is_io ? "DMA IO map size" : "DMA MEM map size",
796 : : len, vaddr, iovaddr, phy);
797 : :
798 [ # # ]: 0 : if (is_io)
799 : 0 : goto io_mapping_check;
800 : :
801 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_memsegs, next) {
802 [ # # ]: 0 : if (!((vaddr + len) <= dmaseg->vaddr ||
803 [ # # ]: 0 : (dmaseg->vaddr + dmaseg->size) <= vaddr)) {
804 : 0 : DPAA2_BUS_ERR("MEM: New VA Range(%" PRIx64 " ~ %" PRIx64 ")",
805 : : vaddr, vaddr + len);
806 : 0 : DPAA2_BUS_ERR("MEM: Overlap with (%" PRIx64 " ~ %" PRIx64 ")",
807 : : dmaseg->vaddr,
808 : : dmaseg->vaddr + dmaseg->size);
809 : 0 : return -EEXIST;
810 : : }
811 [ # # ]: 0 : if (!((iovaddr + len) <= dmaseg->iova ||
812 [ # # ]: 0 : (dmaseg->iova + dmaseg->size) <= iovaddr)) {
813 : 0 : DPAA2_BUS_ERR("MEM: New IOVA Range(%" PRIx64 " ~ %" PRIx64 ")",
814 : : iovaddr, iovaddr + len);
815 : 0 : DPAA2_BUS_ERR("MEM: Overlap with (%" PRIx64 " ~ %" PRIx64 ")",
816 : : dmaseg->iova,
817 : : dmaseg->iova + dmaseg->size);
818 : 0 : return -EEXIST;
819 : : }
820 : : }
821 : 0 : goto start_mapping;
822 : :
823 : : io_mapping_check:
824 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_iosegs, next) {
825 [ # # ]: 0 : if (!((vaddr + len) <= dmaseg->vaddr ||
826 [ # # ]: 0 : (dmaseg->vaddr + dmaseg->size) <= vaddr)) {
827 : 0 : DPAA2_BUS_ERR("IO: New VA Range (%" PRIx64 " ~ %" PRIx64 ")",
828 : : vaddr, vaddr + len);
829 : 0 : DPAA2_BUS_ERR("IO: Overlap with (%" PRIx64 " ~ %" PRIx64 ")",
830 : : dmaseg->vaddr,
831 : : dmaseg->vaddr + dmaseg->size);
832 : 0 : return -EEXIST;
833 : : }
834 [ # # ]: 0 : if (!((iovaddr + len) <= dmaseg->iova ||
835 [ # # ]: 0 : (dmaseg->iova + dmaseg->size) <= iovaddr)) {
836 : 0 : DPAA2_BUS_ERR("IO: New IOVA Range(%" PRIx64 " ~ %" PRIx64 ")",
837 : : iovaddr, iovaddr + len);
838 : 0 : DPAA2_BUS_ERR("IO: Overlap with (%" PRIx64 " ~ %" PRIx64 ")",
839 : : dmaseg->iova,
840 : : dmaseg->iova + dmaseg->size);
841 : 0 : return -EEXIST;
842 : : }
843 : : }
844 : :
845 : 0 : start_mapping:
846 : 0 : fd = fslmc_vfio_group_fd_by_name(group_name);
847 [ # # ]: 0 : if (fd <= 0) {
848 : 0 : DPAA2_BUS_ERR("%s: Get fd by name(%s) failed(%d)",
849 : : __func__, group_name, fd);
850 [ # # ]: 0 : if (fd < 0)
851 : : return fd;
852 : 0 : return -EIO;
853 : : }
854 [ # # ]: 0 : if (fslmc_vfio_iommu_type(fd) == RTE_VFIO_NOIOMMU) {
855 : 0 : DPAA2_BUS_DEBUG("Running in NOIOMMU mode");
856 [ # # ]: 0 : if (phy != iovaddr) {
857 : 0 : DPAA2_BUS_ERR("IOVA should support with IOMMU");
858 : 0 : return -EIO;
859 : : }
860 : 0 : goto end_mapping;
861 : : }
862 : :
863 : 0 : dma_map.size = len;
864 : 0 : dma_map.vaddr = vaddr;
865 : 0 : dma_map.iova = iovaddr;
866 : :
867 : : /* SET DMA MAP for IOMMU */
868 [ # # ]: 0 : if (!fslmc_vfio_container_connected(fd)) {
869 : 0 : DPAA2_BUS_ERR("Container is not connected");
870 : 0 : return -EIO;
871 : : }
872 : :
873 : 0 : ret = ioctl(fslmc_vfio_container_fd(), VFIO_IOMMU_MAP_DMA,
874 : : &dma_map);
875 [ # # ]: 0 : if (ret) {
876 [ # # ]: 0 : DPAA2_BUS_ERR("%s(%d) VA(%" PRIx64 "):IOVA(%" PRIx64 "):PHY(%" PRIx64 ")",
877 : : is_io ? "DMA IO map err" : "DMA MEM map err",
878 : : errno, vaddr, iovaddr, phy);
879 : 0 : return ret;
880 : : }
881 : :
882 : 0 : end_mapping:
883 : 0 : dmaseg = malloc(sizeof(struct fslmc_dmaseg));
884 [ # # ]: 0 : if (!dmaseg) {
885 : 0 : DPAA2_BUS_ERR("DMA segment malloc failed!");
886 : 0 : return -ENOMEM;
887 : : }
888 : 0 : dmaseg->vaddr = vaddr;
889 : 0 : dmaseg->iova = iovaddr;
890 : 0 : dmaseg->size = len;
891 [ # # ]: 0 : if (is_io) {
892 : 0 : TAILQ_INSERT_TAIL(&fslmc_iosegs, dmaseg, next);
893 : : } else {
894 : 0 : fslmc_mem_map_num++;
895 [ # # ]: 0 : if (fslmc_mem_map_num == 1)
896 : 0 : fslmc_mem_va2iova = iovaddr - vaddr;
897 : : else
898 : 0 : fslmc_mem_va2iova = RTE_BAD_IOVA;
899 : 0 : TAILQ_INSERT_TAIL(&fslmc_memsegs, dmaseg, next);
900 : : }
901 [ # # ]: 0 : DPAA2_BUS_LOG(NOTICE,
902 : : "%s(%zx): VA(%" PRIx64 "):IOVA(%" PRIx64 "):PHY(%" PRIx64 ")",
903 : : is_io ? "DMA I/O map size" : "DMA MEM map size",
904 : : len, vaddr, iovaddr, phy);
905 : :
906 : 0 : return 0;
907 : : }
908 : :
909 : : static int
910 : 0 : fslmc_unmap_dma(uint64_t vaddr, uint64_t iovaddr, size_t len)
911 : : {
912 : 0 : struct vfio_iommu_type1_dma_unmap dma_unmap = {
913 : : .argsz = sizeof(struct vfio_iommu_type1_dma_unmap),
914 : : .flags = 0,
915 : : };
916 : : int ret, fd, is_io = 0;
917 : : const char *group_name = fslmc_vfio_get_group_name();
918 : : struct fslmc_dmaseg *dmaseg = NULL;
919 : :
920 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_memsegs, next) {
921 [ # # # # : 0 : if (((vaddr && dmaseg->vaddr == vaddr) || !vaddr) &&
# # ]
922 [ # # ]: 0 : dmaseg->iova == iovaddr &&
923 [ # # ]: 0 : dmaseg->size == len) {
924 : : is_io = 0;
925 : : break;
926 : : }
927 : : }
928 : :
929 [ # # ]: 0 : if (!dmaseg) {
930 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_iosegs, next) {
931 [ # # # # : 0 : if (((vaddr && dmaseg->vaddr == vaddr) || !vaddr) &&
# # ]
932 [ # # ]: 0 : dmaseg->iova == iovaddr &&
933 [ # # ]: 0 : dmaseg->size == len) {
934 : : is_io = 1;
935 : : break;
936 : : }
937 : : }
938 : : }
939 : :
940 [ # # ]: 0 : if (!dmaseg) {
941 : 0 : DPAA2_BUS_ERR("IOVA(%" PRIx64 ") with length(%zx) not mapped",
942 : : iovaddr, len);
943 : 0 : return 0;
944 : : }
945 : :
946 : 0 : fd = fslmc_vfio_group_fd_by_name(group_name);
947 [ # # ]: 0 : if (fd <= 0) {
948 : 0 : DPAA2_BUS_ERR("%s: Get fd by name(%s) failed(%d)",
949 : : __func__, group_name, fd);
950 [ # # ]: 0 : if (fd < 0)
951 : : return fd;
952 : 0 : return -EIO;
953 : : }
954 [ # # ]: 0 : if (fslmc_vfio_iommu_type(fd) == RTE_VFIO_NOIOMMU) {
955 : 0 : DPAA2_BUS_DEBUG("Running in NOIOMMU mode");
956 : 0 : return 0;
957 : : }
958 : :
959 : 0 : dma_unmap.size = len;
960 : 0 : dma_unmap.iova = iovaddr;
961 : :
962 : : /* SET DMA MAP for IOMMU */
963 [ # # ]: 0 : if (!fslmc_vfio_container_connected(fd)) {
964 : 0 : DPAA2_BUS_ERR("Container is not connected ");
965 : 0 : return -EIO;
966 : : }
967 : :
968 : 0 : ret = ioctl(fslmc_vfio_container_fd(), VFIO_IOMMU_UNMAP_DMA,
969 : : &dma_unmap);
970 [ # # ]: 0 : if (ret) {
971 : 0 : DPAA2_BUS_ERR("DMA un-map IOVA(%" PRIx64 " ~ %" PRIx64 ") err(%d)",
972 : : iovaddr, iovaddr + len, errno);
973 : 0 : return ret;
974 : : }
975 : :
976 [ # # ]: 0 : if (is_io) {
977 [ # # ]: 0 : TAILQ_REMOVE(&fslmc_iosegs, dmaseg, next);
978 : : } else {
979 [ # # ]: 0 : TAILQ_REMOVE(&fslmc_memsegs, dmaseg, next);
980 : 0 : fslmc_mem_map_num--;
981 [ # # ]: 0 : if (TAILQ_EMPTY(&fslmc_memsegs))
982 : 0 : fslmc_mem_va2iova = RTE_BAD_IOVA;
983 : : }
984 : :
985 : 0 : free(dmaseg);
986 : :
987 : 0 : return 0;
988 : : }
989 : :
990 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_cold_mem_vaddr_to_iova)
991 : : uint64_t
992 : 0 : rte_fslmc_cold_mem_vaddr_to_iova(void *vaddr,
993 : : uint64_t size)
994 : : {
995 : : struct fslmc_dmaseg *dmaseg;
996 : : uint64_t va;
997 : :
998 : 0 : va = (uint64_t)vaddr;
999 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_memsegs, next) {
1000 [ # # ]: 0 : if (va >= dmaseg->vaddr &&
1001 [ # # ]: 0 : (va + size) < (dmaseg->vaddr + dmaseg->size)) {
1002 : 0 : return dmaseg->iova + va - dmaseg->vaddr;
1003 : : }
1004 : : }
1005 : :
1006 : : return RTE_BAD_IOVA;
1007 : : }
1008 : :
1009 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_cold_mem_iova_to_vaddr)
1010 : : void *
1011 : 0 : rte_fslmc_cold_mem_iova_to_vaddr(uint64_t iova,
1012 : : uint64_t size)
1013 : : {
1014 : : struct fslmc_dmaseg *dmaseg;
1015 : :
1016 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_memsegs, next) {
1017 [ # # ]: 0 : if (iova >= dmaseg->iova &&
1018 [ # # ]: 0 : (iova + size) < (dmaseg->iova + dmaseg->size))
1019 : 0 : return (void *)((uintptr_t)dmaseg->vaddr
1020 : 0 : + (uintptr_t)(iova - dmaseg->iova));
1021 : : }
1022 : :
1023 : : return NULL;
1024 : : }
1025 : :
1026 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_mem_vaddr_to_iova)
1027 : : __rte_hot uint64_t
1028 : 0 : rte_fslmc_mem_vaddr_to_iova(void *vaddr)
1029 : : {
1030 [ # # ]: 0 : if (likely(fslmc_mem_va2iova != RTE_BAD_IOVA))
1031 : 0 : return (uint64_t)vaddr + fslmc_mem_va2iova;
1032 : :
1033 : 0 : return rte_fslmc_cold_mem_vaddr_to_iova(vaddr, 0);
1034 : : }
1035 : :
1036 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_mem_iova_to_vaddr)
1037 : : __rte_hot void *
1038 : 0 : rte_fslmc_mem_iova_to_vaddr(uint64_t iova)
1039 : : {
1040 [ # # ]: 0 : if (likely(fslmc_mem_va2iova != RTE_BAD_IOVA))
1041 : 0 : return (void *)((uintptr_t)iova - (uintptr_t)fslmc_mem_va2iova);
1042 : :
1043 : 0 : return rte_fslmc_cold_mem_iova_to_vaddr(iova, 0);
1044 : : }
1045 : :
1046 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_io_vaddr_to_iova)
1047 : : uint64_t
1048 : 0 : rte_fslmc_io_vaddr_to_iova(void *vaddr)
1049 : : {
1050 : : struct fslmc_dmaseg *dmaseg = NULL;
1051 : 0 : uint64_t va = (uint64_t)vaddr;
1052 : :
1053 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_iosegs, next) {
1054 [ # # ]: 0 : if ((va >= dmaseg->vaddr) &&
1055 [ # # ]: 0 : va < dmaseg->vaddr + dmaseg->size)
1056 : 0 : return dmaseg->iova + va - dmaseg->vaddr;
1057 : : }
1058 : :
1059 : : return RTE_BAD_IOVA;
1060 : : }
1061 : :
1062 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_io_iova_to_vaddr)
1063 : : void *
1064 : 0 : rte_fslmc_io_iova_to_vaddr(uint64_t iova)
1065 : : {
1066 : : struct fslmc_dmaseg *dmaseg = NULL;
1067 : :
1068 [ # # ]: 0 : TAILQ_FOREACH(dmaseg, &fslmc_iosegs, next) {
1069 [ # # ]: 0 : if ((iova >= dmaseg->iova) &&
1070 [ # # ]: 0 : iova < dmaseg->iova + dmaseg->size)
1071 : 0 : return (void *)((uintptr_t)dmaseg->vaddr
1072 : 0 : + (uintptr_t)(iova - dmaseg->iova));
1073 : : }
1074 : :
1075 : : return NULL;
1076 : : }
1077 : :
1078 : : static void
1079 : 0 : fslmc_memevent_cb(enum rte_mem_event type, const void *addr,
1080 : : size_t len, void *arg __rte_unused)
1081 : : {
1082 : : struct rte_memseg_list *msl;
1083 : : struct rte_memseg *ms;
1084 : : size_t cur_len = 0, map_len = 0;
1085 : : uint64_t virt_addr;
1086 : : rte_iova_t iova_addr;
1087 : : int ret;
1088 : :
1089 : 0 : msl = rte_mem_virt2memseg_list(addr);
1090 : :
1091 [ # # ]: 0 : while (cur_len < len) {
1092 : 0 : const void *va = RTE_PTR_ADD(addr, cur_len);
1093 : :
1094 : 0 : ms = rte_mem_virt2memseg(va, msl);
1095 : 0 : iova_addr = ms->iova;
1096 : 0 : virt_addr = ms->addr_64;
1097 : 0 : map_len = ms->len;
1098 : :
1099 [ # # ]: 0 : DPAA2_BUS_DEBUG("%s, va=%p, virt=%" PRIx64 ", iova=%" PRIx64 ", len=%zu",
1100 : : type == RTE_MEM_EVENT_ALLOC ? "alloc" : "dealloc",
1101 : : va, virt_addr, iova_addr, map_len);
1102 : :
1103 : : /* iova_addr may be set to RTE_BAD_IOVA */
1104 [ # # ]: 0 : if (iova_addr == RTE_BAD_IOVA) {
1105 : 0 : DPAA2_BUS_DEBUG("Segment has invalid iova, skipping");
1106 : 0 : cur_len += map_len;
1107 : 0 : continue;
1108 : : }
1109 : :
1110 [ # # ]: 0 : if (type == RTE_MEM_EVENT_ALLOC)
1111 : 0 : ret = fslmc_map_dma(virt_addr, iova_addr, map_len);
1112 : : else
1113 : 0 : ret = fslmc_unmap_dma(virt_addr, iova_addr, map_len);
1114 : :
1115 [ # # ]: 0 : if (ret != 0) {
1116 [ # # ]: 0 : DPAA2_BUS_ERR("%s: Map=%d, addr=%p, len=%zu, err:(%d)",
1117 : : type == RTE_MEM_EVENT_ALLOC ?
1118 : : "DMA Mapping failed. " :
1119 : : "DMA Unmapping failed. ",
1120 : : type, va, map_len, ret);
1121 : 0 : return;
1122 : : }
1123 : :
1124 : 0 : cur_len += map_len;
1125 : : }
1126 : :
1127 [ # # ]: 0 : DPAA2_BUS_DEBUG("Total %s: addr=%p, len=%zu",
1128 : : type == RTE_MEM_EVENT_ALLOC ? "Mapped" : "Unmapped",
1129 : : addr, len);
1130 : : }
1131 : :
1132 : : static int
1133 : 0 : fslmc_dmamap_seg(const struct rte_memseg_list *msl __rte_unused,
1134 : : const struct rte_memseg *ms, void *arg)
1135 : : {
1136 : : int *n_segs = arg;
1137 : : int ret;
1138 : :
1139 : : /* if IOVA address is invalid, skip */
1140 [ # # ]: 0 : if (ms->iova == RTE_BAD_IOVA)
1141 : : return 0;
1142 : :
1143 : 0 : ret = fslmc_map_dma(ms->addr_64, ms->iova, ms->len);
1144 [ # # ]: 0 : if (ret)
1145 : 0 : DPAA2_BUS_ERR("Unable to VFIO map (addr=%p, len=%zu)",
1146 : : ms->addr, ms->len);
1147 : : else
1148 : 0 : (*n_segs)++;
1149 : :
1150 : : return ret;
1151 : : }
1152 : :
1153 : : RTE_EXPORT_SYMBOL(rte_fslmc_vfio_mem_dmamap)
1154 : : int
1155 : 0 : rte_fslmc_vfio_mem_dmamap(uint64_t vaddr, uint64_t iova, uint64_t size)
1156 : : {
1157 : 0 : return fslmc_map_dma(vaddr, iova, size);
1158 : : }
1159 : :
1160 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_fslmc_vfio_mem_dmaunmap)
1161 : : int
1162 : 0 : rte_fslmc_vfio_mem_dmaunmap(uint64_t iova, uint64_t size)
1163 : : {
1164 : 0 : return fslmc_unmap_dma(0, iova, size);
1165 : : }
1166 : :
1167 : : int
1168 : 0 : fslmc_vfio_dmamap(void)
1169 : : {
1170 : 0 : int i = 0, ret;
1171 : :
1172 : : /* Lock before parsing and registering callback to memory subsystem */
1173 : 0 : rte_mcfg_mem_read_lock();
1174 : :
1175 : 0 : ret = rte_memseg_walk(fslmc_dmamap_seg, &i);
1176 [ # # ]: 0 : if (ret) {
1177 : 0 : rte_mcfg_mem_read_unlock();
1178 : 0 : return ret;
1179 : : }
1180 : :
1181 : 0 : ret = rte_mem_event_callback_register("fslmc_memevent_clb",
1182 : : fslmc_memevent_cb, NULL);
1183 [ # # # # ]: 0 : if (ret && rte_errno == ENOTSUP)
1184 : 0 : DPAA2_BUS_DEBUG("Memory event callbacks not supported");
1185 [ # # ]: 0 : else if (ret)
1186 : 0 : DPAA2_BUS_DEBUG("Unable to install memory handler");
1187 : : else
1188 : 0 : DPAA2_BUS_DEBUG("Installed memory callback handler");
1189 : :
1190 : 0 : DPAA2_BUS_DEBUG("Total %d segments found.", i);
1191 : :
1192 : : /* Existing segments have been mapped and memory callback for hotplug
1193 : : * has been installed.
1194 : : */
1195 : 0 : rte_mcfg_mem_read_unlock();
1196 : :
1197 : 0 : return 0;
1198 : : }
1199 : :
1200 : : static int
1201 : 0 : fslmc_vfio_setup_device(const char *dev_addr,
1202 : : int *vfio_dev_fd, struct vfio_device_info *device_info)
1203 : : {
1204 : : struct vfio_group_status group_status = {
1205 : : .argsz = sizeof(group_status)
1206 : : };
1207 : : int vfio_group_fd, ret;
1208 : : const char *group_name = fslmc_vfio_get_group_name();
1209 : :
1210 : 0 : vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name);
1211 [ # # ]: 0 : if (vfio_group_fd <= 0) {
1212 : 0 : DPAA2_BUS_ERR("%s: Get fd by name(%s) failed(%d)",
1213 : : __func__, group_name, vfio_group_fd);
1214 [ # # ]: 0 : if (vfio_group_fd < 0)
1215 : : return vfio_group_fd;
1216 : 0 : return -EIO;
1217 : : }
1218 : :
1219 [ # # ]: 0 : if (!fslmc_vfio_container_connected(vfio_group_fd)) {
1220 : 0 : DPAA2_BUS_ERR("Container is not connected");
1221 : 0 : return -EIO;
1222 : : }
1223 : :
1224 : : /* get a file descriptor for the device */
1225 : 0 : *vfio_dev_fd = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD, dev_addr);
1226 [ # # ]: 0 : if (*vfio_dev_fd < 0) {
1227 : : /* if we cannot get a device fd, this implies a problem with
1228 : : * the VFIO group or the container not having IOMMU configured.
1229 : : */
1230 : :
1231 : 0 : DPAA2_BUS_ERR("Getting a vfio_dev_fd for %s from %s failed",
1232 : : dev_addr, group_name);
1233 : 0 : return -EIO;
1234 : : }
1235 : :
1236 : : /* test and setup the device */
1237 : 0 : ret = ioctl(*vfio_dev_fd, VFIO_DEVICE_GET_INFO, device_info);
1238 [ # # ]: 0 : if (ret) {
1239 : 0 : DPAA2_BUS_ERR("%s cannot get device info err(%d)(%s)",
1240 : : dev_addr, errno, strerror(errno));
1241 : 0 : return ret;
1242 : : }
1243 : :
1244 : 0 : return fslmc_vfio_group_add_dev(vfio_group_fd, *vfio_dev_fd,
1245 : : dev_addr);
1246 : : }
1247 : :
1248 : 0 : static intptr_t vfio_map_mcp_obj(const char *mcp_obj)
1249 : : {
1250 : : intptr_t v_addr = (intptr_t)MAP_FAILED;
1251 : : int32_t ret, mc_fd;
1252 : : struct vfio_group_status status = { .argsz = sizeof(status) };
1253 : :
1254 : 0 : struct vfio_device_info d_info = { .argsz = sizeof(d_info) };
1255 : 0 : struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
1256 : :
1257 : 0 : fslmc_vfio_setup_device(mcp_obj, &mc_fd, &d_info);
1258 : :
1259 : : /* getting device region info*/
1260 : 0 : ret = ioctl(mc_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
1261 [ # # ]: 0 : if (ret < 0) {
1262 : 0 : DPAA2_BUS_ERR("Error in VFIO getting REGION_INFO");
1263 : 0 : goto MC_FAILURE;
1264 : : }
1265 : :
1266 : 0 : v_addr = (size_t)mmap(NULL, reg_info.size,
1267 : : PROT_WRITE | PROT_READ, MAP_SHARED,
1268 : 0 : mc_fd, reg_info.offset);
1269 : :
1270 : 0 : MC_FAILURE:
1271 : 0 : close(mc_fd);
1272 : :
1273 : 0 : return v_addr;
1274 : : }
1275 : :
1276 : : #define IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + sizeof(int))
1277 : :
1278 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_intr_enable)
1279 : 0 : int rte_dpaa2_intr_enable(struct rte_intr_handle *intr_handle, int index)
1280 : : {
1281 : : int len, ret;
1282 : : char irq_set_buf[IRQ_SET_BUF_LEN];
1283 : : struct vfio_irq_set *irq_set;
1284 : : int *fd_ptr, vfio_dev_fd;
1285 : :
1286 : : len = sizeof(irq_set_buf);
1287 : :
1288 : : irq_set = (struct vfio_irq_set *)irq_set_buf;
1289 : 0 : irq_set->argsz = len;
1290 : 0 : irq_set->count = 1;
1291 : 0 : irq_set->flags =
1292 : : VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
1293 : 0 : irq_set->index = index;
1294 : 0 : irq_set->start = 0;
1295 : : fd_ptr = (int *)&irq_set->data;
1296 : 0 : *fd_ptr = rte_intr_fd_get(intr_handle);
1297 : :
1298 : 0 : vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
1299 : 0 : ret = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
1300 [ # # ]: 0 : if (ret) {
1301 : 0 : DPAA2_BUS_ERR("Error:dpaa2 SET IRQs fd=%d, err = %d(%s)",
1302 : : rte_intr_fd_get(intr_handle), errno,
1303 : : strerror(errno));
1304 : 0 : return ret;
1305 : : }
1306 : :
1307 : : return ret;
1308 : : }
1309 : :
1310 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_dpaa2_intr_disable)
1311 : 0 : int rte_dpaa2_intr_disable(struct rte_intr_handle *intr_handle, int index)
1312 : : {
1313 : : struct vfio_irq_set *irq_set;
1314 : : char irq_set_buf[IRQ_SET_BUF_LEN];
1315 : : int len, ret, vfio_dev_fd;
1316 : :
1317 : : len = sizeof(struct vfio_irq_set);
1318 : :
1319 : : irq_set = (struct vfio_irq_set *)irq_set_buf;
1320 : 0 : irq_set->argsz = len;
1321 : 0 : irq_set->flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;
1322 : 0 : irq_set->index = index;
1323 : 0 : irq_set->start = 0;
1324 : 0 : irq_set->count = 0;
1325 : :
1326 : 0 : vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
1327 : 0 : ret = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
1328 [ # # ]: 0 : if (ret)
1329 : 0 : DPAA2_BUS_ERR("Error disabling dpaa2 interrupts for fd %d",
1330 : : rte_intr_fd_get(intr_handle));
1331 : :
1332 : 0 : return ret;
1333 : : }
1334 : :
1335 : : /* set up interrupt support (but not enable interrupts) */
1336 : : int
1337 : 0 : rte_dpaa2_vfio_setup_intr(struct rte_intr_handle *intr_handle,
1338 : : int vfio_dev_fd,
1339 : : int num_irqs)
1340 : : {
1341 : : int i, ret;
1342 : :
1343 : : /* start from MSI-X interrupt type */
1344 [ # # ]: 0 : for (i = 0; i < num_irqs; i++) {
1345 : 0 : struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
1346 : : int fd = -1;
1347 : :
1348 : 0 : irq_info.index = i;
1349 : :
1350 : 0 : ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info);
1351 [ # # ]: 0 : if (ret < 0) {
1352 : 0 : DPAA2_BUS_ERR("Cannot get IRQ(%d) info, error %i (%s)",
1353 : : i, errno, strerror(errno));
1354 : 0 : return ret;
1355 : : }
1356 : :
1357 : : /* if this vector cannot be used with eventfd,
1358 : : * fail if we explicitly
1359 : : * specified interrupt type, otherwise continue
1360 : : */
1361 [ # # ]: 0 : if ((irq_info.flags & VFIO_IRQ_INFO_EVENTFD) == 0)
1362 : 0 : continue;
1363 : :
1364 : : /* set up an eventfd for interrupts */
1365 : 0 : fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
1366 [ # # ]: 0 : if (fd < 0) {
1367 : 0 : DPAA2_BUS_ERR("Cannot set up eventfd, error %i (%s)",
1368 : : errno, strerror(errno));
1369 : 0 : return fd;
1370 : : }
1371 : :
1372 [ # # ]: 0 : if (rte_intr_fd_set(intr_handle, fd))
1373 : 0 : return -rte_errno;
1374 : :
1375 [ # # ]: 0 : if (rte_intr_type_set(intr_handle, RTE_INTR_HANDLE_VFIO_MSI))
1376 : 0 : return -rte_errno;
1377 : :
1378 [ # # ]: 0 : if (rte_intr_dev_fd_set(intr_handle, vfio_dev_fd))
1379 : 0 : return -rte_errno;
1380 : :
1381 : : return 0;
1382 : : }
1383 : :
1384 : : /* if we're here, we haven't found a suitable interrupt vector */
1385 : : return -EIO;
1386 : : }
1387 : :
1388 : : static void
1389 : 0 : fslmc_close_iodevices(struct rte_dpaa2_device *dev,
1390 : : int vfio_fd)
1391 : : {
1392 : : struct rte_dpaa2_object *object = NULL;
1393 : : struct rte_dpaa2_driver *drv;
1394 : : int ret, probe_all;
1395 : :
1396 [ # # # ]: 0 : switch (dev->dev_type) {
1397 : 0 : case DPAA2_IO:
1398 : : case DPAA2_CON:
1399 : : case DPAA2_CI:
1400 : : case DPAA2_BPOOL:
1401 : : case DPAA2_MUX:
1402 [ # # ]: 0 : TAILQ_FOREACH(object, &dpaa2_obj_list, next) {
1403 [ # # ]: 0 : if (dev->dev_type == object->dev_type)
1404 : 0 : object->close(dev->object_id);
1405 : : else
1406 : 0 : continue;
1407 : : }
1408 : : break;
1409 : 0 : case DPAA2_ETH:
1410 : : case DPAA2_CRYPTO:
1411 : : case DPAA2_QDMA:
1412 : 0 : probe_all = rte_fslmc_bus.bus.conf.scan_mode !=
1413 : : RTE_BUS_SCAN_ALLOWLIST;
1414 [ # # ]: 0 : TAILQ_FOREACH(drv, &rte_fslmc_bus.driver_list, next) {
1415 [ # # ]: 0 : if (drv->drv_type != dev->dev_type)
1416 : 0 : continue;
1417 [ # # ]: 0 : if (rte_dev_is_probed(&dev->device))
1418 : 0 : continue;
1419 [ # # ]: 0 : if (probe_all ||
1420 [ # # ]: 0 : (dev->device.devargs &&
1421 [ # # ]: 0 : dev->device.devargs->policy ==
1422 : : RTE_DEV_ALLOWED)) {
1423 : 0 : ret = drv->remove(dev);
1424 [ # # ]: 0 : if (ret)
1425 : 0 : DPAA2_BUS_ERR("Unable to remove");
1426 : : }
1427 : : }
1428 : : break;
1429 : : default:
1430 : : break;
1431 : : }
1432 : :
1433 : 0 : ret = fslmc_vfio_group_remove_dev(vfio_fd, dev->device.name);
1434 [ # # ]: 0 : if (ret) {
1435 : 0 : DPAA2_BUS_ERR("Failed to remove %s from vfio",
1436 : : dev->device.name);
1437 : : }
1438 : 0 : DPAA2_BUS_LOG(DEBUG, "Device (%s) Closed",
1439 : : dev->device.name);
1440 : 0 : }
1441 : :
1442 : : /*
1443 : : * fslmc_process_iodevices for processing only IO (ETH, CRYPTO, and possibly
1444 : : * EVENT) devices.
1445 : : */
1446 : : static int
1447 : 0 : fslmc_process_iodevices(struct rte_dpaa2_device *dev)
1448 : : {
1449 : : int dev_fd, ret;
1450 : 0 : struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
1451 : : struct rte_dpaa2_object *object = NULL;
1452 : :
1453 : 0 : ret = fslmc_vfio_setup_device(dev->device.name, &dev_fd,
1454 : : &device_info);
1455 [ # # ]: 0 : if (ret)
1456 : : return ret;
1457 : :
1458 [ # # # ]: 0 : switch (dev->dev_type) {
1459 : 0 : case DPAA2_ETH:
1460 : 0 : ret = rte_dpaa2_vfio_setup_intr(dev->intr_handle, dev_fd,
1461 : 0 : device_info.num_irqs);
1462 [ # # ]: 0 : if (ret)
1463 : : return ret;
1464 : : break;
1465 : 0 : case DPAA2_CON:
1466 : : case DPAA2_IO:
1467 : : case DPAA2_CI:
1468 : : case DPAA2_BPOOL:
1469 : : case DPAA2_DPRTC:
1470 : : case DPAA2_MUX:
1471 : : case DPAA2_DPRC:
1472 [ # # ]: 0 : TAILQ_FOREACH(object, &dpaa2_obj_list, next) {
1473 [ # # ]: 0 : if (dev->dev_type == object->dev_type)
1474 : 0 : object->create(dev_fd, &device_info, dev);
1475 : : else
1476 : 0 : continue;
1477 : : }
1478 : : break;
1479 : : default:
1480 : : break;
1481 : : }
1482 : :
1483 : 0 : DPAA2_BUS_LOG(DEBUG, "Device (%s) abstracted from VFIO",
1484 : : dev->device.name);
1485 : 0 : return 0;
1486 : : }
1487 : :
1488 : : static int
1489 : 0 : fslmc_process_mcp(struct rte_dpaa2_device *dev)
1490 : : {
1491 : : int ret;
1492 : : intptr_t v_addr;
1493 : 0 : struct fsl_mc_io dpmng = {0};
1494 : 0 : struct mc_version mc_ver_info = {0};
1495 : :
1496 : 0 : rte_mcp_ptr_list = malloc(sizeof(void *) * (MC_PORTAL_INDEX + 1));
1497 [ # # ]: 0 : if (!rte_mcp_ptr_list) {
1498 : 0 : DPAA2_BUS_ERR("Unable to allocate MC portal memory");
1499 : : ret = -ENOMEM;
1500 : 0 : goto cleanup;
1501 : : }
1502 : :
1503 : 0 : v_addr = vfio_map_mcp_obj(dev->device.name);
1504 [ # # ]: 0 : if (v_addr == (intptr_t)MAP_FAILED) {
1505 : 0 : DPAA2_BUS_ERR("Error mapping region (errno = %d)", errno);
1506 : : ret = -1;
1507 : 0 : goto cleanup;
1508 : : }
1509 : :
1510 : : /* check the MC version compatibility */
1511 : 0 : dpmng.regs = (void *)v_addr;
1512 : :
1513 : : /* In case of secondary processes, MC version check is no longer
1514 : : * required.
1515 : : */
1516 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
1517 : 0 : rte_mcp_ptr_list[MC_PORTAL_INDEX] = (void *)v_addr;
1518 : 0 : return 0;
1519 : : }
1520 : :
1521 [ # # ]: 0 : if (mc_get_version(&dpmng, CMD_PRI_LOW, &mc_ver_info)) {
1522 : 0 : DPAA2_BUS_ERR("Unable to obtain MC version");
1523 : : ret = -1;
1524 : 0 : goto cleanup;
1525 : : }
1526 : :
1527 [ # # ]: 0 : if ((mc_ver_info.major != MC_VER_MAJOR) ||
1528 [ # # ]: 0 : (mc_ver_info.minor < MC_VER_MINOR)) {
1529 : 0 : DPAA2_BUS_ERR("DPAA2 MC version not compatible!"
1530 : : " Expected %d.%d.x, Detected %d.%d.%d",
1531 : : MC_VER_MAJOR, MC_VER_MINOR,
1532 : : mc_ver_info.major, mc_ver_info.minor,
1533 : : mc_ver_info.revision);
1534 : : ret = -1;
1535 : 0 : goto cleanup;
1536 : : }
1537 : 0 : rte_mcp_ptr_list[MC_PORTAL_INDEX] = (void *)v_addr;
1538 : :
1539 : 0 : return 0;
1540 : :
1541 : 0 : cleanup:
1542 [ # # ]: 0 : if (rte_mcp_ptr_list) {
1543 : 0 : free(rte_mcp_ptr_list);
1544 : 0 : rte_mcp_ptr_list = NULL;
1545 : : }
1546 : :
1547 : : return ret;
1548 : : }
1549 : :
1550 : : int
1551 : 252 : fslmc_vfio_close_group(void)
1552 : : {
1553 : : struct rte_dpaa2_device *dev, *dev_temp;
1554 : : int vfio_group_fd;
1555 : : const char *group_name = fslmc_vfio_get_group_name();
1556 : :
1557 : 252 : vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name);
1558 [ + - ]: 252 : if (vfio_group_fd <= 0) {
1559 : 252 : DPAA2_BUS_INFO("%s: Get fd by name(%s) failed(%d)",
1560 : : __func__, group_name, vfio_group_fd);
1561 [ - + ]: 252 : if (vfio_group_fd < 0)
1562 : : return vfio_group_fd;
1563 : 0 : return -EIO;
1564 : : }
1565 : :
1566 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next, dev_temp) {
1567 [ # # ]: 0 : if (dev->device.devargs &&
1568 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_BLOCKED) {
1569 : 0 : DPAA2_BUS_LOG(DEBUG, "%s Blacklisted, skipping",
1570 : : dev->device.name);
1571 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
1572 : 0 : continue;
1573 : : }
1574 [ # # # ]: 0 : switch (dev->dev_type) {
1575 : 0 : case DPAA2_ETH:
1576 : : case DPAA2_CRYPTO:
1577 : : case DPAA2_QDMA:
1578 : : case DPAA2_IO:
1579 : 0 : fslmc_close_iodevices(dev, vfio_group_fd);
1580 : 0 : break;
1581 : 0 : case DPAA2_CON:
1582 : : case DPAA2_CI:
1583 : : case DPAA2_BPOOL:
1584 : : case DPAA2_MUX:
1585 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY)
1586 : 0 : continue;
1587 : :
1588 : 0 : fslmc_close_iodevices(dev, vfio_group_fd);
1589 : 0 : break;
1590 : 0 : case DPAA2_DPRTC:
1591 : : default:
1592 : 0 : DPAA2_BUS_DEBUG("Device cannot be closed: Not supported (%s)",
1593 : : dev->device.name);
1594 : : }
1595 : : }
1596 : :
1597 : 0 : fslmc_vfio_clear_group(vfio_group_fd);
1598 : :
1599 : 0 : return 0;
1600 : : }
1601 : :
1602 : : int
1603 : 0 : fslmc_vfio_process_group(void)
1604 : : {
1605 : : int ret;
1606 : : int found_mportal = 0;
1607 : : struct rte_dpaa2_device *dev, *dev_temp;
1608 : : bool is_dpmcp_in_blocklist = false, is_dpio_in_blocklist = false;
1609 : : int dpmcp_count = 0, dpio_count = 0, current_device;
1610 : :
1611 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next,
1612 : : dev_temp) {
1613 [ # # ]: 0 : if (dev->dev_type == DPAA2_MPORTAL) {
1614 : 0 : dpmcp_count++;
1615 [ # # ]: 0 : if (dev->device.devargs &&
1616 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_BLOCKED)
1617 : : is_dpmcp_in_blocklist = true;
1618 : : }
1619 [ # # ]: 0 : if (dev->dev_type == DPAA2_IO) {
1620 : 0 : dpio_count++;
1621 [ # # ]: 0 : if (dev->device.devargs &&
1622 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_BLOCKED)
1623 : : is_dpio_in_blocklist = true;
1624 : : }
1625 : : }
1626 : :
1627 : : /* Search the MCP as that should be initialized first. */
1628 : : current_device = 0;
1629 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next,
1630 : : dev_temp) {
1631 [ # # ]: 0 : if (dev->dev_type == DPAA2_MPORTAL) {
1632 : 0 : current_device++;
1633 [ # # ]: 0 : if (dev->device.devargs &&
1634 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_BLOCKED) {
1635 : 0 : DPAA2_BUS_LOG(DEBUG, "%s Blocked, skipping",
1636 : : dev->device.name);
1637 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list,
1638 : : dev, next);
1639 : 0 : continue;
1640 : : }
1641 : :
1642 [ # # # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY &&
1643 : : !is_dpmcp_in_blocklist) {
1644 : 0 : if (dpmcp_count == 1 ||
1645 [ # # ]: 0 : current_device != dpmcp_count) {
1646 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list,
1647 : : dev, next);
1648 : 0 : continue;
1649 : : }
1650 : : }
1651 : :
1652 [ # # ]: 0 : if (!found_mportal) {
1653 : 0 : ret = fslmc_process_mcp(dev);
1654 [ # # ]: 0 : if (ret) {
1655 : 0 : DPAA2_BUS_ERR("Unable to map MC Portal");
1656 : 0 : return ret;
1657 : : }
1658 : : found_mportal = 1;
1659 : : }
1660 : :
1661 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
1662 : 0 : free(dev);
1663 : : dev = NULL;
1664 : : /* Ideally there is only a single dpmcp, but in case
1665 : : * multiple exists, looping on remaining devices.
1666 : : */
1667 : : }
1668 : : }
1669 : :
1670 : : /* Cannot continue if there is not even a single mportal */
1671 [ # # ]: 0 : if (!found_mportal) {
1672 : 0 : DPAA2_BUS_ERR("No MC Portal device found. Not continuing");
1673 : 0 : return -EIO;
1674 : : }
1675 : :
1676 : : /* Search for DPRC device next as it updates endpoint of
1677 : : * other devices.
1678 : : */
1679 : : current_device = 0;
1680 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next, dev_temp) {
1681 [ # # ]: 0 : if (dev->dev_type == DPAA2_DPRC) {
1682 : 0 : ret = fslmc_process_iodevices(dev);
1683 [ # # ]: 0 : if (ret) {
1684 : 0 : DPAA2_BUS_ERR("Unable to process dprc");
1685 : 0 : return ret;
1686 : : }
1687 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
1688 : : }
1689 : : }
1690 : :
1691 : : current_device = 0;
1692 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(dev, &rte_fslmc_bus.device_list, next,
1693 : : dev_temp) {
1694 [ # # ]: 0 : if (dev->dev_type == DPAA2_IO)
1695 : 0 : current_device++;
1696 [ # # ]: 0 : if (dev->device.devargs &&
1697 [ # # ]: 0 : dev->device.devargs->policy == RTE_DEV_BLOCKED) {
1698 : 0 : DPAA2_BUS_LOG(DEBUG, "%s Blocked, skipping",
1699 : : dev->device.name);
1700 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
1701 : 0 : continue;
1702 : : }
1703 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY &&
1704 [ # # ]: 0 : dev->dev_type != DPAA2_ETH &&
1705 : : dev->dev_type != DPAA2_CRYPTO &&
1706 : 0 : dev->dev_type != DPAA2_QDMA &&
1707 : : dev->dev_type != DPAA2_IO) {
1708 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
1709 : 0 : continue;
1710 : : }
1711 [ # # # # ]: 0 : switch (dev->dev_type) {
1712 : 0 : case DPAA2_ETH:
1713 : : case DPAA2_CRYPTO:
1714 : : case DPAA2_QDMA:
1715 : 0 : ret = fslmc_process_iodevices(dev);
1716 [ # # ]: 0 : if (ret) {
1717 : 0 : DPAA2_BUS_DEBUG("Dev (%s) init failed",
1718 : : dev->device.name);
1719 : 0 : return ret;
1720 : : }
1721 : : break;
1722 : 0 : case DPAA2_CON:
1723 : : case DPAA2_CI:
1724 : : case DPAA2_BPOOL:
1725 : : case DPAA2_DPRTC:
1726 : : case DPAA2_MUX:
1727 : : /* IN case of secondary processes, all control objects
1728 : : * like dpbp, dpcon, dpci are not initialized/required
1729 : : * - all of these are assumed to be initialized and made
1730 : : * available by primary.
1731 : : */
1732 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY)
1733 : 0 : continue;
1734 : :
1735 : : /* Call the object creation routine and remove the
1736 : : * device entry from device list
1737 : : */
1738 : 0 : ret = fslmc_process_iodevices(dev);
1739 [ # # ]: 0 : if (ret) {
1740 : 0 : DPAA2_BUS_DEBUG("Dev (%s) init failed",
1741 : : dev->device.name);
1742 : 0 : return ret;
1743 : : }
1744 : :
1745 : : break;
1746 : 0 : case DPAA2_IO:
1747 [ # # ]: 0 : if (!is_dpio_in_blocklist && dpio_count > 1) {
1748 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY
1749 [ # # ]: 0 : && current_device != dpio_count) {
1750 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list,
1751 : : dev, next);
1752 : 0 : break;
1753 : : }
1754 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY
1755 [ # # ]: 0 : && current_device == dpio_count) {
1756 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list,
1757 : : dev, next);
1758 : 0 : break;
1759 : : }
1760 : : }
1761 : :
1762 : 0 : ret = fslmc_process_iodevices(dev);
1763 [ # # ]: 0 : if (ret) {
1764 : 0 : DPAA2_BUS_DEBUG("Dev (%s) init failed",
1765 : : dev->device.name);
1766 : 0 : return ret;
1767 : : }
1768 : :
1769 : : break;
1770 : 0 : case DPAA2_UNKNOWN:
1771 : : default:
1772 : : /* Unknown - ignore */
1773 : 0 : DPAA2_BUS_DEBUG("Found unknown device (%s)",
1774 : : dev->device.name);
1775 [ # # ]: 0 : TAILQ_REMOVE(&rte_fslmc_bus.device_list, dev, next);
1776 : 0 : free(dev);
1777 : : dev = NULL;
1778 : : }
1779 : : }
1780 : :
1781 : : return 0;
1782 : : }
1783 : :
1784 : : int
1785 : 0 : fslmc_vfio_setup_group(void)
1786 : : {
1787 : : int vfio_group_fd, vfio_container_fd, ret;
1788 : 0 : struct vfio_group_status status = { .argsz = sizeof(status) };
1789 : : const char *group_name = fslmc_vfio_get_group_name();
1790 : :
1791 : : /* MC VFIO setup entry */
1792 : : vfio_container_fd = fslmc_vfio_container_fd();
1793 [ # # ]: 0 : if (vfio_container_fd <= 0) {
1794 : 0 : vfio_container_fd = fslmc_vfio_open_container_fd();
1795 [ # # ]: 0 : if (vfio_container_fd < 0) {
1796 : 0 : DPAA2_BUS_ERR("Failed to create MC VFIO container");
1797 : 0 : return vfio_container_fd;
1798 : : }
1799 : : }
1800 : :
1801 [ # # ]: 0 : if (!group_name) {
1802 : 0 : DPAA2_BUS_DEBUG("DPAA2: DPRC not available");
1803 : 0 : return -EINVAL;
1804 : : }
1805 : :
1806 : 0 : vfio_group_fd = fslmc_vfio_group_fd_by_name(group_name);
1807 [ # # ]: 0 : if (vfio_group_fd < 0) {
1808 : 0 : vfio_group_fd = fslmc_vfio_open_group_fd(group_name);
1809 [ # # ]: 0 : if (vfio_group_fd < 0) {
1810 : 0 : DPAA2_BUS_ERR("open group name(%s) failed(%d)",
1811 : : group_name, vfio_group_fd);
1812 : 0 : return -rte_errno;
1813 : : }
1814 : : }
1815 : :
1816 : : /* Check group viability */
1817 : 0 : ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &status);
1818 [ # # ]: 0 : if (ret) {
1819 : 0 : DPAA2_BUS_ERR("VFIO(%s:fd=%d) error getting group status(%d)",
1820 : : group_name, vfio_group_fd, ret);
1821 : 0 : fslmc_vfio_clear_group(vfio_group_fd);
1822 : 0 : return ret;
1823 : : }
1824 : :
1825 [ # # ]: 0 : if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) {
1826 : 0 : DPAA2_BUS_ERR("VFIO group not viable");
1827 : 0 : fslmc_vfio_clear_group(vfio_group_fd);
1828 : 0 : return -EPERM;
1829 : : }
1830 : :
1831 : : /* check if group does not have a container yet */
1832 [ # # ]: 0 : if (!(status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET)) {
1833 : : /* Now connect this IOMMU group to given container */
1834 : 0 : ret = vfio_connect_container(vfio_container_fd,
1835 : : vfio_group_fd);
1836 : : } else {
1837 : : /* Here is supposed in secondary process,
1838 : : * group has been set to container in primary process.
1839 : : */
1840 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY)
1841 : 0 : DPAA2_BUS_WARN("This group has been set container?");
1842 : : ret = fslmc_vfio_connect_container(vfio_group_fd);
1843 : : }
1844 [ # # ]: 0 : if (ret) {
1845 : 0 : DPAA2_BUS_ERR("vfio group connect failed(%d)", ret);
1846 : 0 : fslmc_vfio_clear_group(vfio_group_fd);
1847 : 0 : return ret;
1848 : : }
1849 : :
1850 : : /* Get Device information */
1851 : 0 : ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD, group_name);
1852 [ # # ]: 0 : if (ret < 0) {
1853 : 0 : DPAA2_BUS_ERR("Error getting device %s fd", group_name);
1854 : 0 : fslmc_vfio_clear_group(vfio_group_fd);
1855 : 0 : return ret;
1856 : : }
1857 : :
1858 : 0 : ret = fslmc_vfio_mp_sync_setup();
1859 [ # # ]: 0 : if (ret) {
1860 : 0 : DPAA2_BUS_ERR("VFIO MP sync setup failed!");
1861 : 0 : fslmc_vfio_clear_group(vfio_group_fd);
1862 : 0 : return ret;
1863 : : }
1864 : :
1865 : 0 : DPAA2_BUS_DEBUG("VFIO GROUP FD is %d", vfio_group_fd);
1866 : :
1867 : 0 : return 0;
1868 : : }
|