LCOV - code coverage report
Current view: top level - drivers/bus/pci/linux - pci_uio.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 227 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 13 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 140 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <string.h>
       6                 :            : #include <unistd.h>
       7                 :            : #include <fcntl.h>
       8                 :            : #include <dirent.h>
       9                 :            : #include <inttypes.h>
      10                 :            : #include <sys/stat.h>
      11                 :            : #include <sys/mman.h>
      12                 :            : #include <sys/sysmacros.h>
      13                 :            : 
      14                 :            : #if defined(RTE_ARCH_X86)
      15                 :            : #include <sys/io.h>
      16                 :            : #endif
      17                 :            : 
      18                 :            : #include <rte_string_fns.h>
      19                 :            : #include <rte_log.h>
      20                 :            : #include <rte_pci.h>
      21                 :            : #include <rte_bus_pci.h>
      22                 :            : #include <rte_common.h>
      23                 :            : #include <rte_malloc.h>
      24                 :            : 
      25                 :            : #include "eal_filesystem.h"
      26                 :            : #include "pci_init.h"
      27                 :            : #include "private.h"
      28                 :            : 
      29                 :            : void *pci_map_addr = NULL;
      30                 :            : 
      31                 :            : #define OFF_MAX              ((uint64_t)(off_t)-1)
      32                 :            : 
      33                 :            : int
      34                 :          0 : pci_uio_read_config(const struct rte_intr_handle *intr_handle,
      35                 :            :                     void *buf, size_t len, off_t offset)
      36                 :            : {
      37                 :          0 :         int uio_cfg_fd = rte_intr_dev_fd_get(intr_handle);
      38                 :            : 
      39         [ #  # ]:          0 :         if (uio_cfg_fd < 0)
      40                 :            :                 return -1;
      41                 :            : 
      42                 :          0 :         return pread(uio_cfg_fd, buf, len, offset);
      43                 :            : }
      44                 :            : 
      45                 :            : int
      46                 :          0 : pci_uio_write_config(const struct rte_intr_handle *intr_handle,
      47                 :            :                      const void *buf, size_t len, off_t offset)
      48                 :            : {
      49                 :          0 :         int uio_cfg_fd = rte_intr_dev_fd_get(intr_handle);
      50                 :            : 
      51         [ #  # ]:          0 :         if (uio_cfg_fd < 0)
      52                 :            :                 return -1;
      53                 :            : 
      54                 :          0 :         return pwrite(uio_cfg_fd, buf, len, offset);
      55                 :            : }
      56                 :            : 
      57                 :            : int
      58                 :          0 : pci_uio_mmio_read(const struct rte_pci_device *dev, int bar,
      59                 :            :                   void *buf, size_t len, off_t offset)
      60                 :            : {
      61   [ #  #  #  # ]:          0 :         if (bar >= PCI_MAX_RESOURCE || dev->mem_resource[bar].addr == NULL ||
      62         [ #  # ]:          0 :                         (uint64_t)offset + len > dev->mem_resource[bar].len)
      63                 :            :                 return -1;
      64                 :          0 :         memcpy(buf, (uint8_t *)dev->mem_resource[bar].addr + offset, len);
      65                 :          0 :         return len;
      66                 :            : }
      67                 :            : 
      68                 :            : int
      69                 :          0 : pci_uio_mmio_write(const struct rte_pci_device *dev, int bar,
      70                 :            :                    const void *buf, size_t len, off_t offset)
      71                 :            : {
      72   [ #  #  #  # ]:          0 :         if (bar >= PCI_MAX_RESOURCE || dev->mem_resource[bar].addr == NULL ||
      73         [ #  # ]:          0 :                         (uint64_t)offset + len > dev->mem_resource[bar].len)
      74                 :            :                 return -1;
      75                 :          0 :         memcpy((uint8_t *)dev->mem_resource[bar].addr + offset, buf, len);
      76                 :          0 :         return len;
      77                 :            : }
      78                 :            : 
      79                 :            : static int
      80                 :          0 : pci_mknod_uio_dev(const char *sysfs_uio_path, unsigned uio_num)
      81                 :            : {
      82                 :            :         FILE *f;
      83                 :            :         char filename[PATH_MAX];
      84                 :            :         int ret;
      85                 :            :         unsigned major, minor;
      86                 :            :         dev_t dev;
      87                 :            : 
      88                 :            :         /* get the name of the sysfs file that contains the major and minor
      89                 :            :          * of the uio device and read its content */
      90                 :            :         snprintf(filename, sizeof(filename), "%s/dev", sysfs_uio_path);
      91                 :            : 
      92                 :          0 :         f = fopen(filename, "r");
      93         [ #  # ]:          0 :         if (f == NULL) {
      94                 :          0 :                 PCI_LOG(ERR, "%s(): cannot open sysfs to get major:minor", __func__);
      95                 :          0 :                 return -1;
      96                 :            :         }
      97                 :            : 
      98                 :          0 :         ret = fscanf(f, "%u:%u", &major, &minor);
      99         [ #  # ]:          0 :         if (ret != 2) {
     100                 :          0 :                 PCI_LOG(ERR, "%s(): cannot parse sysfs to get major:minor", __func__);
     101                 :          0 :                 fclose(f);
     102                 :          0 :                 return -1;
     103                 :            :         }
     104                 :          0 :         fclose(f);
     105                 :            : 
     106                 :            :         /* create the char device "mknod /dev/uioX c major minor" */
     107                 :            :         snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num);
     108                 :          0 :         dev = makedev(major, minor);
     109                 :          0 :         ret = mknod(filename, S_IFCHR | S_IRUSR | S_IWUSR, dev);
     110         [ #  # ]:          0 :         if (ret != 0) {
     111                 :          0 :                 PCI_LOG(ERR, "%s(): mknod() failed %s", __func__, strerror(errno));
     112                 :          0 :                 return -1;
     113                 :            :         }
     114                 :            : 
     115                 :            :         return ret;
     116                 :            : }
     117                 :            : 
     118                 :            : /*
     119                 :            :  * Return the uioX char device used for a pci device. On success, return
     120                 :            :  * the UIO number and fill dstbuf string with the path of the device in
     121                 :            :  * sysfs. On error, return a negative value. In this case dstbuf is
     122                 :            :  * invalid.
     123                 :            :  */
     124                 :            : static int
     125                 :          0 : pci_get_uio_dev(struct rte_pci_device *dev, char *dstbuf,
     126                 :            :                            unsigned int buflen, int create)
     127                 :            : {
     128                 :            :         struct rte_pci_addr *loc = &dev->addr;
     129                 :            :         int uio_num = -1;
     130                 :            :         struct dirent *e;
     131                 :            :         DIR *dir;
     132                 :            :         char dirname[PATH_MAX];
     133                 :            : 
     134                 :            :         /* depending on kernel version, uio can be located in uio/uioX
     135                 :            :          * or uio:uioX */
     136                 :            : 
     137                 :          0 :         snprintf(dirname, sizeof(dirname),
     138                 :            :                         "%s/" PCI_PRI_FMT "/uio", rte_pci_get_sysfs_path(),
     139                 :          0 :                         loc->domain, loc->bus, loc->devid, loc->function);
     140                 :            : 
     141                 :          0 :         dir = opendir(dirname);
     142         [ #  # ]:          0 :         if (dir == NULL) {
     143                 :            :                 /* retry with the parent directory */
     144                 :          0 :                 snprintf(dirname, sizeof(dirname),
     145                 :            :                                 "%s/" PCI_PRI_FMT, rte_pci_get_sysfs_path(),
     146                 :          0 :                                 loc->domain, loc->bus, loc->devid, loc->function);
     147                 :          0 :                 dir = opendir(dirname);
     148                 :            : 
     149         [ #  # ]:          0 :                 if (dir == NULL) {
     150                 :          0 :                         PCI_LOG(ERR, "Cannot opendir %s", dirname);
     151                 :          0 :                         return -1;
     152                 :            :                 }
     153                 :            :         }
     154                 :            : 
     155                 :            :         /* take the first file starting with "uio" */
     156         [ #  # ]:          0 :         while ((e = readdir(dir)) != NULL) {
     157                 :            :                 /* format could be uio%d ...*/
     158                 :            :                 int shortprefix_len = sizeof("uio") - 1;
     159                 :            :                 /* ... or uio:uio%d */
     160                 :            :                 int longprefix_len = sizeof("uio:uio") - 1;
     161                 :            :                 char *endptr;
     162                 :            : 
     163         [ #  # ]:          0 :                 if (strncmp(e->d_name, "uio", 3) != 0)
     164                 :          0 :                         continue;
     165                 :            : 
     166                 :            :                 /* first try uio%d */
     167                 :          0 :                 errno = 0;
     168                 :          0 :                 uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
     169   [ #  #  #  # ]:          0 :                 if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
     170                 :          0 :                         snprintf(dstbuf, buflen, "%s/uio%u", dirname, uio_num);
     171                 :          0 :                         break;
     172                 :            :                 }
     173                 :            : 
     174                 :            :                 /* then try uio:uio%d */
     175                 :          0 :                 errno = 0;
     176                 :          0 :                 uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
     177   [ #  #  #  # ]:          0 :                 if (errno == 0 && endptr != (e->d_name + longprefix_len)) {
     178                 :          0 :                         snprintf(dstbuf, buflen, "%s/uio:uio%u", dirname, uio_num);
     179                 :            :                         break;
     180                 :            :                 }
     181                 :            :         }
     182                 :          0 :         closedir(dir);
     183                 :            : 
     184                 :            :         /* No uio resource found */
     185         [ #  # ]:          0 :         if (e == NULL)
     186                 :            :                 return -1;
     187                 :            : 
     188                 :            :         /* create uio device if we've been asked to */
     189   [ #  #  #  #  :          0 :         if (rte_eal_create_uio_dev() && create &&
                   #  # ]
     190                 :          0 :                         pci_mknod_uio_dev(dstbuf, uio_num) < 0)
     191                 :          0 :                 PCI_LOG(WARNING, "Cannot create /dev/uio%u", uio_num);
     192                 :            : 
     193                 :            :         return uio_num;
     194                 :            : }
     195                 :            : 
     196                 :            : void
     197                 :          0 : pci_uio_free_resource(struct rte_pci_device *dev,
     198                 :            :                 struct mapped_pci_resource *uio_res)
     199                 :            : {
     200                 :          0 :         int uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle);
     201                 :            : 
     202                 :          0 :         rte_free(uio_res);
     203                 :            : 
     204         [ #  # ]:          0 :         if (uio_cfg_fd >= 0) {
     205                 :          0 :                 close(uio_cfg_fd);
     206                 :          0 :                 rte_intr_dev_fd_set(dev->intr_handle, -1);
     207                 :            :         }
     208                 :            : 
     209         [ #  # ]:          0 :         if (rte_intr_fd_get(dev->intr_handle) >= 0) {
     210                 :          0 :                 close(rte_intr_fd_get(dev->intr_handle));
     211                 :          0 :                 rte_intr_fd_set(dev->intr_handle, -1);
     212                 :          0 :                 rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN);
     213                 :            :         }
     214                 :          0 : }
     215                 :            : 
     216                 :            : int
     217                 :          0 : pci_uio_alloc_resource(struct rte_pci_device *dev,
     218                 :            :                 struct mapped_pci_resource **uio_res)
     219                 :            : {
     220                 :            :         char dirname[PATH_MAX];
     221                 :            :         char cfgname[PATH_MAX];
     222                 :            :         char devname[PATH_MAX]; /* contains the /dev/uioX */
     223                 :            :         int uio_num, fd, uio_cfg_fd;
     224                 :            :         struct rte_pci_addr *loc;
     225                 :            : 
     226                 :            :         loc = &dev->addr;
     227                 :            : 
     228                 :            :         /* find uio resource */
     229                 :          0 :         uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 1);
     230         [ #  # ]:          0 :         if (uio_num < 0) {
     231                 :          0 :                 PCI_LOG(WARNING, "  "PCI_PRI_FMT" not managed by UIO driver, skipping",
     232                 :            :                         loc->domain, loc->bus, loc->devid, loc->function);
     233                 :          0 :                 return 1;
     234                 :            :         }
     235                 :            :         snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num);
     236                 :            : 
     237                 :            :         /* save fd */
     238                 :            :         fd = open(devname, O_RDWR);
     239         [ #  # ]:          0 :         if (fd < 0) {
     240                 :          0 :                 PCI_LOG(ERR, "Cannot open %s: %s", devname, strerror(errno));
     241                 :          0 :                 goto error;
     242                 :            :         }
     243                 :            : 
     244         [ #  # ]:          0 :         if (rte_intr_fd_set(dev->intr_handle, fd))
     245                 :          0 :                 goto error;
     246                 :            : 
     247                 :            :         snprintf(cfgname, sizeof(cfgname),
     248                 :            :                         "/sys/class/uio/uio%u/device/config", uio_num);
     249                 :            : 
     250                 :            :         uio_cfg_fd = open(cfgname, O_RDWR);
     251         [ #  # ]:          0 :         if (uio_cfg_fd < 0) {
     252                 :          0 :                 PCI_LOG(ERR, "Cannot open %s: %s", cfgname, strerror(errno));
     253                 :          0 :                 goto error;
     254                 :            :         }
     255                 :            : 
     256         [ #  # ]:          0 :         if (rte_intr_dev_fd_set(dev->intr_handle, uio_cfg_fd))
     257                 :          0 :                 goto error;
     258                 :            : 
     259         [ #  # ]:          0 :         if (dev->kdrv == RTE_PCI_KDRV_IGB_UIO) {
     260         [ #  # ]:          0 :                 if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO))
     261                 :          0 :                         goto error;
     262                 :            :         } else {
     263         [ #  # ]:          0 :                 if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO_INTX))
     264                 :          0 :                         goto error;
     265                 :            : 
     266                 :            :                 /* set bus master that is not done by uio_pci_generic */
     267         [ #  # ]:          0 :                 if (rte_pci_set_bus_master(dev, true)) {
     268                 :          0 :                         PCI_LOG(ERR, "Cannot set up bus mastering!");
     269                 :          0 :                         goto error;
     270                 :            :                 }
     271                 :            :         }
     272                 :            : 
     273         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     274                 :            :                 return 0;
     275                 :            : 
     276                 :            :         /* allocate the mapping details for secondary processes*/
     277                 :          0 :         *uio_res = rte_zmalloc("UIO_RES", sizeof(**uio_res), 0);
     278         [ #  # ]:          0 :         if (*uio_res == NULL) {
     279                 :          0 :                 PCI_LOG(ERR, "%s(): cannot store uio mmap details", __func__);
     280                 :          0 :                 goto error;
     281                 :            :         }
     282                 :            : 
     283                 :          0 :         strlcpy((*uio_res)->path, devname, sizeof((*uio_res)->path));
     284                 :          0 :         memcpy(&(*uio_res)->pci_addr, &dev->addr, sizeof((*uio_res)->pci_addr));
     285                 :            : 
     286                 :          0 :         return 0;
     287                 :            : 
     288                 :          0 : error:
     289                 :          0 :         pci_uio_free_resource(dev, *uio_res);
     290                 :          0 :         return -1;
     291                 :            : }
     292                 :            : 
     293                 :            : int
     294                 :          0 : pci_uio_map_resource_by_index(struct rte_pci_device *dev, int res_idx,
     295                 :            :                 struct mapped_pci_resource *uio_res, int map_idx)
     296                 :            : {
     297                 :            :         int fd = -1;
     298                 :            :         char devname[PATH_MAX];
     299                 :            :         void *mapaddr;
     300                 :            :         struct rte_pci_addr *loc;
     301                 :            :         struct pci_map *maps;
     302                 :            :         int wc_activate = 0;
     303                 :            : 
     304         [ #  # ]:          0 :         if (dev->driver != NULL)
     305                 :          0 :                 wc_activate = dev->driver->drv_flags & RTE_PCI_DRV_WC_ACTIVATE;
     306                 :            : 
     307                 :            :         loc = &dev->addr;
     308                 :          0 :         maps = uio_res->maps;
     309                 :            : 
     310                 :            :         /* allocate memory to keep path */
     311                 :          0 :         maps[map_idx].path = rte_malloc(NULL, sizeof(devname), 0);
     312         [ #  # ]:          0 :         if (maps[map_idx].path == NULL) {
     313                 :          0 :                 PCI_LOG(ERR, "Cannot allocate memory for path: %s", strerror(errno));
     314                 :          0 :                 return -1;
     315                 :            :         }
     316                 :            : 
     317                 :            :         /*
     318                 :            :          * open resource file, to mmap it
     319                 :            :          */
     320         [ #  # ]:          0 :         if (wc_activate) {
     321                 :            :                 /* update devname for mmap  */
     322                 :          0 :                 snprintf(devname, sizeof(devname),
     323                 :            :                         "%s/" PCI_PRI_FMT "/resource%d_wc",
     324                 :            :                         rte_pci_get_sysfs_path(),
     325                 :          0 :                         loc->domain, loc->bus, loc->devid,
     326                 :          0 :                         loc->function, res_idx);
     327                 :            : 
     328                 :            :                 fd = open(devname, O_RDWR);
     329   [ #  #  #  # ]:          0 :                 if (fd < 0 && errno != ENOENT) {
     330                 :          0 :                         PCI_LOG(INFO, "%s cannot be mapped. Fall-back to non prefetchable mode.",
     331                 :            :                                 devname);
     332                 :            :                 }
     333                 :            :         }
     334                 :            : 
     335         [ #  # ]:          0 :         if (!wc_activate || fd < 0) {
     336                 :          0 :                 snprintf(devname, sizeof(devname),
     337                 :            :                         "%s/" PCI_PRI_FMT "/resource%d",
     338                 :            :                         rte_pci_get_sysfs_path(),
     339                 :          0 :                         loc->domain, loc->bus, loc->devid,
     340                 :          0 :                         loc->function, res_idx);
     341                 :            : 
     342                 :            :                 /* then try to map resource file */
     343                 :            :                 fd = open(devname, O_RDWR);
     344         [ #  # ]:          0 :                 if (fd < 0) {
     345                 :          0 :                         PCI_LOG(ERR, "Cannot open %s: %s", devname, strerror(errno));
     346                 :          0 :                         goto error;
     347                 :            :                 }
     348                 :            :         }
     349                 :            : 
     350                 :            :         /* try mapping somewhere close to the end of hugepages */
     351         [ #  # ]:          0 :         if (pci_map_addr == NULL)
     352                 :          0 :                 pci_map_addr = pci_find_max_end_va();
     353                 :            : 
     354                 :          0 :         mapaddr = pci_map_resource(pci_map_addr, fd, 0,
     355                 :          0 :                         (size_t)dev->mem_resource[res_idx].len, 0);
     356                 :          0 :         close(fd);
     357         [ #  # ]:          0 :         if (mapaddr == NULL)
     358                 :          0 :                 goto error;
     359                 :            : 
     360                 :          0 :         pci_map_addr = RTE_PTR_ADD(mapaddr,
     361                 :            :                         (size_t)dev->mem_resource[res_idx].len);
     362                 :            : 
     363                 :          0 :         pci_map_addr = RTE_PTR_ALIGN(pci_map_addr, sysconf(_SC_PAGE_SIZE));
     364                 :            : 
     365                 :          0 :         maps[map_idx].phaddr = dev->mem_resource[res_idx].phys_addr;
     366                 :          0 :         maps[map_idx].size = dev->mem_resource[res_idx].len;
     367                 :          0 :         maps[map_idx].addr = mapaddr;
     368                 :          0 :         maps[map_idx].offset = 0;
     369                 :          0 :         strcpy(maps[map_idx].path, devname);
     370                 :          0 :         dev->mem_resource[res_idx].addr = mapaddr;
     371                 :            : 
     372                 :          0 :         return 0;
     373                 :            : 
     374                 :          0 : error:
     375                 :          0 :         rte_free(maps[map_idx].path);
     376                 :          0 :         return -1;
     377                 :            : }
     378                 :            : 
     379                 :            : #define PIO_MAX 0x10000
     380                 :            : 
     381                 :            : #if defined(RTE_ARCH_X86)
     382                 :            : int
     383                 :          0 : pci_uio_ioport_map(struct rte_pci_device *dev, int bar,
     384                 :            :                    struct rte_pci_ioport *p)
     385                 :            : {
     386                 :            :         FILE *f = NULL;
     387                 :            :         char dirname[PATH_MAX];
     388                 :            :         char filename[PATH_MAX];
     389                 :            :         char buf[BUFSIZ];
     390                 :            :         uint64_t phys_addr, end_addr, flags;
     391                 :            :         unsigned long base;
     392                 :            :         int i, fd;
     393                 :            : 
     394                 :            :         /* open and read addresses of the corresponding resource in sysfs */
     395                 :          0 :         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource",
     396                 :          0 :                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
     397                 :          0 :                 dev->addr.devid, dev->addr.function);
     398                 :          0 :         f = fopen(filename, "r");
     399         [ #  # ]:          0 :         if (f == NULL) {
     400                 :          0 :                 PCI_LOG(ERR, "%s(): Cannot open sysfs resource: %s", __func__, strerror(errno));
     401                 :          0 :                 return -1;
     402                 :            :         }
     403                 :            : 
     404         [ #  # ]:          0 :         for (i = 0; i < bar + 1; i++) {
     405         [ #  # ]:          0 :                 if (fgets(buf, sizeof(buf), f) == NULL) {
     406                 :          0 :                         PCI_LOG(ERR, "%s(): Cannot read sysfs resource", __func__);
     407                 :          0 :                         goto error;
     408                 :            :                 }
     409                 :            :         }
     410         [ #  # ]:          0 :         if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
     411                 :            :                 &end_addr, &flags) < 0)
     412                 :          0 :                 goto error;
     413                 :            : 
     414         [ #  # ]:          0 :         if (flags & IORESOURCE_IO) {
     415         [ #  # ]:          0 :                 if (rte_eal_iopl_init()) {
     416                 :          0 :                         PCI_LOG(ERR, "%s(): insufficient ioport permissions for PCI device %s",
     417                 :            :                                 __func__, dev->name);
     418                 :          0 :                         goto error;
     419                 :            :                 }
     420                 :            : 
     421                 :          0 :                 base = (unsigned long)phys_addr;
     422         [ #  # ]:          0 :                 if (base > PIO_MAX) {
     423                 :          0 :                         PCI_LOG(ERR, "%s(): %08lx too large PIO resource", __func__, base);
     424                 :          0 :                         goto error;
     425                 :            :                 }
     426                 :            : 
     427                 :          0 :                 PCI_LOG(DEBUG, "%s(): PIO BAR %08lx detected", __func__, base);
     428         [ #  # ]:          0 :         } else if (flags & IORESOURCE_MEM) {
     429                 :          0 :                 base = (unsigned long)dev->mem_resource[bar].addr;
     430                 :          0 :                 PCI_LOG(DEBUG, "%s(): MMIO BAR %08lx detected", __func__, base);
     431                 :            :         } else {
     432                 :          0 :                 PCI_LOG(ERR, "%s(): unknown BAR type", __func__);
     433                 :          0 :                 goto error;
     434                 :            :         }
     435                 :            : 
     436                 :            :         /* FIXME only for primary process ? */
     437         [ #  # ]:          0 :         if (rte_intr_type_get(dev->intr_handle) ==
     438                 :            :                                         RTE_INTR_HANDLE_UNKNOWN) {
     439                 :          0 :                 int uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname), 0);
     440         [ #  # ]:          0 :                 if (uio_num < 0) {
     441                 :          0 :                         PCI_LOG(ERR, "cannot open %s: %s", dirname, strerror(errno));
     442                 :          0 :                         goto error;
     443                 :            :                 }
     444                 :            : 
     445                 :            :                 snprintf(filename, sizeof(filename), "/dev/uio%u", uio_num);
     446                 :            :                 fd = open(filename, O_RDWR);
     447         [ #  # ]:          0 :                 if (fd < 0) {
     448                 :          0 :                         PCI_LOG(ERR, "Cannot open %s: %s", filename, strerror(errno));
     449                 :          0 :                         goto error;
     450                 :            :                 }
     451         [ #  # ]:          0 :                 if (rte_intr_fd_set(dev->intr_handle, fd))
     452                 :          0 :                         goto error;
     453                 :            : 
     454         [ #  # ]:          0 :                 if (rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UIO))
     455                 :          0 :                         goto error;
     456                 :            :         }
     457                 :            : 
     458                 :          0 :         PCI_LOG(DEBUG, "PCI Port IO found start=0x%lx", base);
     459                 :            : 
     460                 :          0 :         p->base = base;
     461                 :          0 :         p->len = 0;
     462                 :          0 :         fclose(f);
     463                 :          0 :         return 0;
     464                 :          0 : error:
     465                 :            :         if (f)
     466                 :          0 :                 fclose(f);
     467                 :          0 :         return -1;
     468                 :            : }
     469                 :            : #else
     470                 :            : int
     471                 :            : pci_uio_ioport_map(struct rte_pci_device *dev, int bar,
     472                 :            :                    struct rte_pci_ioport *p)
     473                 :            : {
     474                 :            :         FILE *f;
     475                 :            :         char buf[BUFSIZ];
     476                 :            :         char filename[PATH_MAX];
     477                 :            :         uint64_t phys_addr, end_addr, flags;
     478                 :            :         int fd, i;
     479                 :            :         void *addr;
     480                 :            : 
     481                 :            :         /* open and read addresses of the corresponding resource in sysfs */
     482                 :            :         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource",
     483                 :            :                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
     484                 :            :                 dev->addr.devid, dev->addr.function);
     485                 :            :         f = fopen(filename, "r");
     486                 :            :         if (f == NULL) {
     487                 :            :                 PCI_LOG(ERR, "Cannot open sysfs resource: %s", strerror(errno));
     488                 :            :                 return -1;
     489                 :            :         }
     490                 :            :         for (i = 0; i < bar + 1; i++) {
     491                 :            :                 if (fgets(buf, sizeof(buf), f) == NULL) {
     492                 :            :                         PCI_LOG(ERR, "Cannot read sysfs resource");
     493                 :            :                         goto error;
     494                 :            :                 }
     495                 :            :         }
     496                 :            :         if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
     497                 :            :                         &end_addr, &flags) < 0)
     498                 :            :                 goto error;
     499                 :            :         if ((flags & IORESOURCE_IO) == 0) {
     500                 :            :                 PCI_LOG(ERR, "BAR %d is not an IO resource", bar);
     501                 :            :                 goto error;
     502                 :            :         }
     503                 :            :         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource%d",
     504                 :            :                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
     505                 :            :                 dev->addr.devid, dev->addr.function, bar);
     506                 :            : 
     507                 :            :         /* mmap the pci resource */
     508                 :            :         fd = open(filename, O_RDWR);
     509                 :            :         if (fd < 0) {
     510                 :            :                 PCI_LOG(ERR, "Cannot open %s: %s", filename, strerror(errno));
     511                 :            :                 goto error;
     512                 :            :         }
     513                 :            :         addr = mmap(NULL, end_addr + 1, PROT_READ | PROT_WRITE,
     514                 :            :                 MAP_SHARED, fd, 0);
     515                 :            :         close(fd);
     516                 :            :         if (addr == MAP_FAILED) {
     517                 :            :                 PCI_LOG(ERR, "Cannot mmap IO port resource: %s", strerror(errno));
     518                 :            :                 goto error;
     519                 :            :         }
     520                 :            : 
     521                 :            :         /* strangely, the base address is mmap addr + phys_addr */
     522                 :            :         p->base = (uintptr_t)addr + phys_addr;
     523                 :            :         p->len = end_addr + 1;
     524                 :            :         PCI_LOG(DEBUG, "PCI Port IO found start=0x%"PRIx64, p->base);
     525                 :            :         fclose(f);
     526                 :            : 
     527                 :            :         return 0;
     528                 :            : 
     529                 :            : error:
     530                 :            :         fclose(f);
     531                 :            :         return -1;
     532                 :            : }
     533                 :            : #endif
     534                 :            : 
     535                 :            : #if defined(RTE_ARCH_X86)
     536                 :            : 
     537                 :            : static inline uint8_t ioread8(void *addr)
     538                 :            : {
     539                 :            :         uint8_t val;
     540                 :            : 
     541                 :          0 :         val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
     542                 :            :                 *(volatile uint8_t *)addr :
     543                 :            : #ifdef __GLIBC__
     544                 :          0 :                 inb_p((unsigned long)addr);
     545                 :            : #else
     546                 :            :                 inb((unsigned long)addr);
     547                 :            : #endif
     548                 :            : 
     549                 :            :         return val;
     550                 :            : }
     551                 :            : 
     552                 :            : static inline uint16_t ioread16(void *addr)
     553                 :            : {
     554                 :            :         uint16_t val;
     555                 :            : 
     556                 :          0 :         val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
     557                 :            :                 *(volatile uint16_t *)addr :
     558                 :            : #ifdef __GLIBC__
     559                 :          0 :                 inw_p((unsigned long)addr);
     560                 :            : #else
     561                 :            :                 inw((unsigned long)addr);
     562                 :            : #endif
     563                 :            : 
     564                 :            :         return val;
     565                 :            : }
     566                 :            : 
     567                 :            : static inline uint32_t ioread32(void *addr)
     568                 :            : {
     569                 :            :         uint32_t val;
     570                 :            : 
     571                 :            :         val = (uint64_t)(uintptr_t)addr >= PIO_MAX ?
     572                 :          0 :                 *(volatile uint32_t *)addr :
     573                 :            : #ifdef __GLIBC__
     574                 :          0 :                 inl_p((unsigned long)addr);
     575                 :            : #else
     576                 :            :                 inl((unsigned long)addr);
     577                 :            : #endif
     578                 :            : 
     579                 :            :         return val;
     580                 :            : }
     581                 :            : 
     582                 :            : static inline void iowrite8(uint8_t val, void *addr)
     583                 :            : {
     584                 :            :         (uint64_t)(uintptr_t)addr >= PIO_MAX ?
     585                 :          0 :                 *(volatile uint8_t *)addr = val :
     586                 :            : #ifdef __GLIBC__
     587                 :          0 :                 outb_p(val, (unsigned long)addr);
     588                 :            : #else
     589                 :            :                 outb(val, (unsigned long)addr);
     590                 :            : #endif
     591                 :            : }
     592                 :            : 
     593                 :            : static inline void iowrite16(uint16_t val, void *addr)
     594                 :            : {
     595                 :            :         (uint64_t)(uintptr_t)addr >= PIO_MAX ?
     596                 :          0 :                 *(volatile uint16_t *)addr = val :
     597                 :            : #ifdef __GLIBC__
     598                 :          0 :                 outw_p(val, (unsigned long)addr);
     599                 :            : #else
     600                 :            :                 outw(val, (unsigned long)addr);
     601                 :            : #endif
     602                 :            : }
     603                 :            : 
     604                 :            : static inline void iowrite32(uint32_t val, void *addr)
     605                 :            : {
     606                 :            :         (uint64_t)(uintptr_t)addr >= PIO_MAX ?
     607                 :          0 :                 *(volatile uint32_t *)addr = val :
     608                 :            : #ifdef __GLIBC__
     609                 :          0 :                 outl_p(val, (unsigned long)addr);
     610                 :            : #else
     611                 :            :                 outl(val, (unsigned long)addr);
     612                 :            : #endif
     613                 :            : }
     614                 :            : 
     615                 :            : #else /* !RTE_ARCH_X86 */
     616                 :            : 
     617                 :            : static inline uint8_t ioread8(void *addr)
     618                 :            : {
     619                 :            :         return *(volatile uint8_t *)addr;
     620                 :            : }
     621                 :            : 
     622                 :            : static inline uint16_t ioread16(void *addr)
     623                 :            : {
     624                 :            :         return *(volatile uint16_t *)addr;
     625                 :            : }
     626                 :            : 
     627                 :            : static inline uint32_t ioread32(void *addr)
     628                 :            : {
     629                 :            :         return *(volatile uint32_t *)addr;
     630                 :            : }
     631                 :            : 
     632                 :            : static inline void iowrite8(uint8_t val, void *addr)
     633                 :            : {
     634                 :            :         *(volatile uint8_t *)addr = val;
     635                 :            : }
     636                 :            : 
     637                 :            : static inline void iowrite16(uint16_t val, void *addr)
     638                 :            : {
     639                 :            :         *(volatile uint16_t *)addr = val;
     640                 :            : }
     641                 :            : 
     642                 :            : static inline void iowrite32(uint32_t val, void *addr)
     643                 :            : {
     644                 :            :         *(volatile uint32_t *)addr = val;
     645                 :            : }
     646                 :            : 
     647                 :            : #endif /* !RTE_ARCH_X86 */
     648                 :            : 
     649                 :            : void
     650                 :          0 : pci_uio_ioport_read(struct rte_pci_ioport *p,
     651                 :            :                     void *data, size_t len, off_t offset)
     652                 :            : {
     653                 :            :         uint8_t *d;
     654                 :            :         int size;
     655                 :          0 :         uintptr_t reg = p->base + offset;
     656                 :            : 
     657         [ #  # ]:          0 :         for (d = data; len > 0; d += size, reg += size, len -= size) {
     658         [ #  # ]:          0 :                 if (len >= 4) {
     659                 :            :                         size = 4;
     660         [ #  # ]:          0 :                         *(uint32_t *)d = ioread32((void *)reg);
     661         [ #  # ]:          0 :                 } else if (len >= 2) {
     662                 :            :                         size = 2;
     663         [ #  # ]:          0 :                         *(uint16_t *)d = ioread16((void *)reg);
     664                 :            :                 } else {
     665                 :            :                         size = 1;
     666         [ #  # ]:          0 :                         *d = ioread8((void *)reg);
     667                 :            :                 }
     668                 :            :         }
     669                 :          0 : }
     670                 :            : 
     671                 :            : void
     672                 :          0 : pci_uio_ioport_write(struct rte_pci_ioport *p,
     673                 :            :                      const void *data, size_t len, off_t offset)
     674                 :            : {
     675                 :            :         const uint8_t *s;
     676                 :            :         int size;
     677                 :          0 :         uintptr_t reg = p->base + offset;
     678                 :            : 
     679         [ #  # ]:          0 :         for (s = data; len > 0; s += size, reg += size, len -= size) {
     680         [ #  # ]:          0 :                 if (len >= 4) {
     681                 :            :                         size = 4;
     682         [ #  # ]:          0 :                         iowrite32(*(const uint32_t *)s, (void *)reg);
     683         [ #  # ]:          0 :                 } else if (len >= 2) {
     684                 :            :                         size = 2;
     685         [ #  # ]:          0 :                         iowrite16(*(const uint16_t *)s, (void *)reg);
     686                 :            :                 } else {
     687                 :            :                         size = 1;
     688         [ #  # ]:          0 :                         iowrite8(*s, (void *)reg);
     689                 :            :                 }
     690                 :            :         }
     691                 :          0 : }
     692                 :            : 
     693                 :            : int
     694                 :          0 : pci_uio_ioport_unmap(struct rte_pci_ioport *p)
     695                 :            : {
     696                 :            : #if defined(RTE_ARCH_X86)
     697                 :            :         RTE_SET_USED(p);
     698                 :            :         /* FIXME close intr fd ? */
     699                 :          0 :         return 0;
     700                 :            : #else
     701                 :            :         return munmap((void *)(uintptr_t)p->base, p->len);
     702                 :            : #endif
     703                 :            : }

Generated by: LCOV version 1.14