dpdk/drivers/crypto/ccp/ccp_pci.c
<<
>>
Prefs
   1/*   SPDX-License-Identifier: BSD-3-Clause
   2 *   Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
   3 */
   4
   5#include <dirent.h>
   6#include <fcntl.h>
   7#include <stdio.h>
   8#include <string.h>
   9#include <unistd.h>
  10
  11#include <rte_string_fns.h>
  12
  13#include "ccp_pci.h"
  14
  15static const char * const uio_module_names[] = {
  16        "igb_uio",
  17        "uio_pci_generic",
  18        "vfio_pci"
  19};
  20
  21int
  22ccp_check_pci_uio_module(void)
  23{
  24        FILE *fp;
  25        int i;
  26        char buf[BUFSIZ];
  27
  28        fp = fopen(PROC_MODULES, "r");
  29        if (fp == NULL)
  30                return -1;
  31        i = 0;
  32        while (uio_module_names[i] != NULL) {
  33                while (fgets(buf, sizeof(buf), fp) != NULL) {
  34                        if (!strncmp(buf, uio_module_names[i],
  35                                     strlen(uio_module_names[i]))) {
  36                                fclose(fp);
  37                                return i;
  38                        }
  39                }
  40                i++;
  41                rewind(fp);
  42        }
  43        fclose(fp);
  44        printf("Insert igb_uio or uio_pci_generic kernel module(s)");
  45        return -1;/* uio not inserted */
  46}
  47
  48/*
  49 * split up a pci address into its constituent parts.
  50 */
  51int
  52ccp_parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
  53                          uint8_t *bus, uint8_t *devid, uint8_t *function)
  54{
  55        /* first split on ':' */
  56        union splitaddr {
  57                struct {
  58                        char *domain;
  59                        char *bus;
  60                        char *devid;
  61                        char *function;
  62                };
  63                char *str[PCI_FMT_NVAL];
  64                /* last element-separator is "." not ":" */
  65        } splitaddr;
  66
  67        char *buf_copy = strndup(buf, bufsize);
  68
  69        if (buf_copy == NULL)
  70                return -1;
  71
  72        if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
  73                        != PCI_FMT_NVAL - 1)
  74                goto error;
  75        /* final split is on '.' between devid and function */
  76        splitaddr.function = strchr(splitaddr.devid, '.');
  77        if (splitaddr.function == NULL)
  78                goto error;
  79        *splitaddr.function++ = '\0';
  80
  81        /* now convert to int values */
  82        errno = 0;
  83        *domain = (uint8_t)strtoul(splitaddr.domain, NULL, 16);
  84        *bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
  85        *devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
  86        *function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
  87        if (errno != 0)
  88                goto error;
  89
  90        free(buf_copy); /* free the copy made with strdup */
  91        return 0;
  92error:
  93        free(buf_copy);
  94        return -1;
  95}
  96
  97int
  98ccp_pci_parse_sysfs_value(const char *filename, unsigned long *val)
  99{
 100        FILE *f;
 101        char buf[BUFSIZ];
 102        char *end = NULL;
 103
 104        f = fopen(filename, "r");
 105        if (f == NULL)
 106                return -1;
 107        if (fgets(buf, sizeof(buf), f) == NULL) {
 108                fclose(f);
 109                return -1;
 110        }
 111        *val = strtoul(buf, &end, 0);
 112        if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
 113                fclose(f);
 114                return -1;
 115        }
 116        fclose(f);
 117        return 0;
 118}
 119
 120/** IO resource type: */
 121#define IORESOURCE_IO         0x00000100
 122#define IORESOURCE_MEM        0x00000200
 123
 124/* parse one line of the "resource" sysfs file (note that the 'line'
 125 * string is modified)
 126 */
 127static int
 128ccp_pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr,
 129                                 uint64_t *end_addr, uint64_t *flags)
 130{
 131        union pci_resource_info {
 132                struct {
 133                        char *phys_addr;
 134                        char *end_addr;
 135                        char *flags;
 136                };
 137                char *ptrs[PCI_RESOURCE_FMT_NVAL];
 138        } res_info;
 139
 140        if (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3)
 141                return -1;
 142        errno = 0;
 143        *phys_addr = strtoull(res_info.phys_addr, NULL, 16);
 144        *end_addr = strtoull(res_info.end_addr, NULL, 16);
 145        *flags = strtoull(res_info.flags, NULL, 16);
 146        if (errno != 0)
 147                return -1;
 148
 149        return 0;
 150}
 151
 152/* parse the "resource" sysfs file */
 153int
 154ccp_pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev)
 155{
 156        FILE *fp;
 157        char buf[BUFSIZ];
 158        int i;
 159        uint64_t phys_addr, end_addr, flags;
 160
 161        fp = fopen(filename, "r");
 162        if (fp == NULL)
 163                return -1;
 164
 165        for (i = 0; i < PCI_MAX_RESOURCE; i++) {
 166                if (fgets(buf, sizeof(buf), fp) == NULL)
 167                        goto error;
 168                if (ccp_pci_parse_one_sysfs_resource(buf, sizeof(buf),
 169                                &phys_addr, &end_addr, &flags) < 0)
 170                        goto error;
 171
 172                if (flags & IORESOURCE_MEM) {
 173                        dev->mem_resource[i].phys_addr = phys_addr;
 174                        dev->mem_resource[i].len = end_addr - phys_addr + 1;
 175                        /* not mapped for now */
 176                        dev->mem_resource[i].addr = NULL;
 177                }
 178        }
 179        fclose(fp);
 180        return 0;
 181
 182error:
 183        fclose(fp);
 184        return -1;
 185}
 186
 187int
 188ccp_find_uio_devname(const char *dirname)
 189{
 190
 191        DIR *dir;
 192        struct dirent *e;
 193        char dirname_uio[PATH_MAX];
 194        unsigned int uio_num;
 195        int ret = -1;
 196
 197        /* depending on kernel version, uio can be located in uio/uioX
 198         * or uio:uioX
 199         */
 200        snprintf(dirname_uio, sizeof(dirname_uio), "%s/uio", dirname);
 201        dir = opendir(dirname_uio);
 202        if (dir == NULL) {
 203        /* retry with the parent directory might be different kernel version*/
 204                dir = opendir(dirname);
 205                if (dir == NULL)
 206                        return -1;
 207        }
 208
 209        /* take the first file starting with "uio" */
 210        while ((e = readdir(dir)) != NULL) {
 211                /* format could be uio%d ...*/
 212                int shortprefix_len = sizeof("uio") - 1;
 213                /* ... or uio:uio%d */
 214                int longprefix_len = sizeof("uio:uio") - 1;
 215                char *endptr;
 216
 217                if (strncmp(e->d_name, "uio", 3) != 0)
 218                        continue;
 219
 220                /* first try uio%d */
 221                errno = 0;
 222                uio_num = strtoull(e->d_name + shortprefix_len, &endptr, 10);
 223                if (errno == 0 && endptr != (e->d_name + shortprefix_len)) {
 224                        ret = uio_num;
 225                        break;
 226                }
 227
 228                /* then try uio:uio%d */
 229                errno = 0;
 230                uio_num = strtoull(e->d_name + longprefix_len, &endptr, 10);
 231                if (errno == 0 && endptr != (e->d_name + longprefix_len)) {
 232                        ret = uio_num;
 233                        break;
 234                }
 235        }
 236        closedir(dir);
 237        return ret;
 238
 239
 240}
 241