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