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