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-05-01 17:49:45 Functions: 3 41 7.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 4 583 0.7 %

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

Generated by: LCOV version 1.14