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