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