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 clear_irq; 34 bool read; 35 bool write; 36 bool copy; 37 unsigned long size; 38 bool use_dma; 39 }; 40 41 static 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, ¶m); 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, ¶m); 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, ¶m); 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 157 int 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: 229 usage: 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