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