linux/tools/pci/pcitest.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/**
   3 * Userspace PCI Endpoint Test Module
   4 *
   5 * Copyright (C) 2017 Texas Instruments
   6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
   7 */
   8
   9#include <errno.h>
  10#include <fcntl.h>
  11#include <stdbool.h>
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <sys/ioctl.h>
  15#include <unistd.h>
  16
  17#include <linux/pcitest.h>
  18
  19#define BILLION 1E9
  20
  21static char *result[] = { "NOT OKAY", "OKAY" };
  22static char *irq[] = { "LEGACY", "MSI", "MSI-X" };
  23
  24struct pci_test {
  25        char            *device;
  26        char            barnum;
  27        bool            legacyirq;
  28        unsigned int    msinum;
  29        unsigned int    msixnum;
  30        int             irqtype;
  31        bool            set_irqtype;
  32        bool            get_irqtype;
  33        bool            clear_irq;
  34        bool            read;
  35        bool            write;
  36        bool            copy;
  37        unsigned long   size;
  38        bool            use_dma;
  39};
  40
  41static int run_test(struct pci_test *test)
  42{
  43        struct pci_endpoint_test_xfer_param param = {};
  44        int ret = -EINVAL;
  45        int fd;
  46
  47        fd = open(test->device, O_RDWR);
  48        if (fd < 0) {
  49                perror("can't open PCI Endpoint Test device");
  50                return -ENODEV;
  51        }
  52
  53        if (test->barnum >= 0 && test->barnum <= 5) {
  54                ret = ioctl(fd, PCITEST_BAR, test->barnum);
  55                fprintf(stdout, "BAR%d:\t\t", test->barnum);
  56                if (ret < 0)
  57                        fprintf(stdout, "TEST FAILED\n");
  58                else
  59                        fprintf(stdout, "%s\n", result[ret]);
  60        }
  61
  62        if (test->set_irqtype) {
  63                ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype);
  64                fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]);
  65                if (ret < 0)
  66                        fprintf(stdout, "FAILED\n");
  67                else
  68                        fprintf(stdout, "%s\n", result[ret]);
  69        }
  70
  71        if (test->get_irqtype) {
  72                ret = ioctl(fd, PCITEST_GET_IRQTYPE);
  73                fprintf(stdout, "GET IRQ TYPE:\t\t");
  74                if (ret < 0)
  75                        fprintf(stdout, "FAILED\n");
  76                else
  77                        fprintf(stdout, "%s\n", irq[ret]);
  78        }
  79
  80        if (test->clear_irq) {
  81                ret = ioctl(fd, PCITEST_CLEAR_IRQ);
  82                fprintf(stdout, "CLEAR IRQ:\t\t");
  83                if (ret < 0)
  84                        fprintf(stdout, "FAILED\n");
  85                else
  86                        fprintf(stdout, "%s\n", result[ret]);
  87        }
  88
  89        if (test->legacyirq) {
  90                ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0);
  91                fprintf(stdout, "LEGACY IRQ:\t");
  92                if (ret < 0)
  93                        fprintf(stdout, "TEST FAILED\n");
  94                else
  95                        fprintf(stdout, "%s\n", result[ret]);
  96        }
  97
  98        if (test->msinum > 0 && test->msinum <= 32) {
  99                ret = ioctl(fd, PCITEST_MSI, test->msinum);
 100                fprintf(stdout, "MSI%d:\t\t", test->msinum);
 101                if (ret < 0)
 102                        fprintf(stdout, "TEST FAILED\n");
 103                else
 104                        fprintf(stdout, "%s\n", result[ret]);
 105        }
 106
 107        if (test->msixnum > 0 && test->msixnum <= 2048) {
 108                ret = ioctl(fd, PCITEST_MSIX, test->msixnum);
 109                fprintf(stdout, "MSI-X%d:\t\t", test->msixnum);
 110                if (ret < 0)
 111                        fprintf(stdout, "TEST FAILED\n");
 112                else
 113                        fprintf(stdout, "%s\n", result[ret]);
 114        }
 115
 116        if (test->write) {
 117                param.size = test->size;
 118                if (test->use_dma)
 119                        param.flags = PCITEST_FLAGS_USE_DMA;
 120                ret = ioctl(fd, PCITEST_WRITE, &param);
 121                fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size);
 122                if (ret < 0)
 123                        fprintf(stdout, "TEST FAILED\n");
 124                else
 125                        fprintf(stdout, "%s\n", result[ret]);
 126        }
 127
 128        if (test->read) {
 129                param.size = test->size;
 130                if (test->use_dma)
 131                        param.flags = PCITEST_FLAGS_USE_DMA;
 132                ret = ioctl(fd, PCITEST_READ, &param);
 133                fprintf(stdout, "READ (%7ld bytes):\t\t", test->size);
 134                if (ret < 0)
 135                        fprintf(stdout, "TEST FAILED\n");
 136                else
 137                        fprintf(stdout, "%s\n", result[ret]);
 138        }
 139
 140        if (test->copy) {
 141                param.size = test->size;
 142                if (test->use_dma)
 143                        param.flags = PCITEST_FLAGS_USE_DMA;
 144                ret = ioctl(fd, PCITEST_COPY, &param);
 145                fprintf(stdout, "COPY (%7ld bytes):\t\t", test->size);
 146                if (ret < 0)
 147                        fprintf(stdout, "TEST FAILED\n");
 148                else
 149                        fprintf(stdout, "%s\n", result[ret]);
 150        }
 151
 152        fflush(stdout);
 153        close(fd);
 154        return (ret < 0) ? ret : 1 - ret; /* return 0 if test succeeded */
 155}
 156
 157int main(int argc, char **argv)
 158{
 159        int c;
 160        struct pci_test *test;
 161
 162        test = calloc(1, sizeof(*test));
 163        if (!test) {
 164                perror("Fail to allocate memory for pci_test\n");
 165                return -ENOMEM;
 166        }
 167
 168        /* since '0' is a valid BAR number, initialize it to -1 */
 169        test->barnum = -1;
 170
 171        /* set default size as 100KB */
 172        test->size = 0x19000;
 173
 174        /* set default endpoint device */
 175        test->device = "/dev/pci-endpoint-test.0";
 176
 177        while ((c = getopt(argc, argv, "D:b:m:x:i:deIlhrwcs:")) != EOF)
 178        switch (c) {
 179        case 'D':
 180                test->device = optarg;
 181                continue;
 182        case 'b':
 183                test->barnum = atoi(optarg);
 184                if (test->barnum < 0 || test->barnum > 5)
 185                        goto usage;
 186                continue;
 187        case 'l':
 188                test->legacyirq = true;
 189                continue;
 190        case 'm':
 191                test->msinum = atoi(optarg);
 192                if (test->msinum < 1 || test->msinum > 32)
 193                        goto usage;
 194                continue;
 195        case 'x':
 196                test->msixnum = atoi(optarg);
 197                if (test->msixnum < 1 || test->msixnum > 2048)
 198                        goto usage;
 199                continue;
 200        case 'i':
 201                test->irqtype = atoi(optarg);
 202                if (test->irqtype < 0 || test->irqtype > 2)
 203                        goto usage;
 204                test->set_irqtype = true;
 205                continue;
 206        case 'I':
 207                test->get_irqtype = true;
 208                continue;
 209        case 'r':
 210                test->read = true;
 211                continue;
 212        case 'w':
 213                test->write = true;
 214                continue;
 215        case 'c':
 216                test->copy = true;
 217                continue;
 218        case 'e':
 219                test->clear_irq = true;
 220                continue;
 221        case 's':
 222                test->size = strtoul(optarg, NULL, 0);
 223                continue;
 224        case 'd':
 225                test->use_dma = true;
 226                continue;
 227        case 'h':
 228        default:
 229usage:
 230                fprintf(stderr,
 231                        "usage: %s [options]\n"
 232                        "Options:\n"
 233                        "\t-D <dev>             PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n"
 234                        "\t-b <bar num>         BAR test (bar number between 0..5)\n"
 235                        "\t-m <msi num>         MSI test (msi number between 1..32)\n"
 236                        "\t-x <msix num>        \tMSI-X test (msix number between 1..2048)\n"
 237                        "\t-i <irq type>        \tSet IRQ type (0 - Legacy, 1 - MSI, 2 - MSI-X)\n"
 238                        "\t-e                   Clear IRQ\n"
 239                        "\t-I                   Get current IRQ type configured\n"
 240                        "\t-d                   Use DMA\n"
 241                        "\t-l                   Legacy IRQ test\n"
 242                        "\t-r                   Read buffer test\n"
 243                        "\t-w                   Write buffer test\n"
 244                        "\t-c                   Copy buffer test\n"
 245                        "\t-s <size>            Size of buffer {default: 100KB}\n"
 246                        "\t-h                   Print this help message\n",
 247                        argv[0]);
 248                return -EINVAL;
 249        }
 250
 251        return run_test(test);
 252}
 253