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

Generated by: LCOV version 1.14