LCOV - code coverage report
Current view: top level - drivers/bus/fslmc - fslmc_vfio.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 12 778 1.5 %
Date: 2025-03-01 20:23:48 Functions: 3 41 7.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 4 583 0.7 %

           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, &reg_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                 :            : }

Generated by: LCOV version 1.14