| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | /** | 
|  | 2 | * Userspace PCI Endpoint Test Module | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 2017 Texas Instruments | 
|  | 5 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | 
|  | 6 | * | 
|  | 7 | * This program is free software: you can redistribute it and/or modify | 
|  | 8 | * it under the terms of the GNU General Public License version 2 of | 
|  | 9 | * the License as published by the Free Software Foundation. | 
|  | 10 | * | 
|  | 11 | * This program is distributed in the hope that it will be useful, | 
|  | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 14 | * GNU General Public License for more details. | 
|  | 15 | * | 
|  | 16 | * You should have received a copy of the GNU General Public License | 
|  | 17 | * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 18 | */ | 
|  | 19 |  | 
|  | 20 | #include <errno.h> | 
|  | 21 | #include <fcntl.h> | 
|  | 22 | #include <stdbool.h> | 
|  | 23 | #include <stdio.h> | 
|  | 24 | #include <stdlib.h> | 
|  | 25 | #include <sys/ioctl.h> | 
|  | 26 | #include <unistd.h> | 
|  | 27 |  | 
|  | 28 | #include <linux/pcitest.h> | 
|  | 29 |  | 
|  | 30 | #define BILLION 1E9 | 
|  | 31 |  | 
|  | 32 | static char *result[] = { "NOT OKAY", "OKAY" }; | 
|  | 33 | static char *irq[] = { "LEGACY", "MSI", "MSI-X" }; | 
|  | 34 |  | 
|  | 35 | struct pci_test { | 
|  | 36 | char		*device; | 
|  | 37 | char		barnum; | 
|  | 38 | bool		legacyirq; | 
|  | 39 | unsigned int	msinum; | 
|  | 40 | unsigned int	msixnum; | 
|  | 41 | int		irqtype; | 
|  | 42 | bool		set_irqtype; | 
|  | 43 | bool		get_irqtype; | 
|  | 44 | bool		read; | 
|  | 45 | bool		write; | 
|  | 46 | bool		copy; | 
|  | 47 | unsigned long	size; | 
|  | 48 | }; | 
|  | 49 |  | 
|  | 50 | static int run_test(struct pci_test *test) | 
|  | 51 | { | 
|  | 52 | int ret = -EINVAL; | 
|  | 53 | int fd; | 
|  | 54 |  | 
|  | 55 | fd = open(test->device, O_RDWR); | 
|  | 56 | if (fd < 0) { | 
|  | 57 | perror("can't open PCI Endpoint Test device"); | 
|  | 58 | return -ENODEV; | 
|  | 59 | } | 
|  | 60 |  | 
|  | 61 | if (test->barnum >= 0 && test->barnum <= 5) { | 
|  | 62 | ret = ioctl(fd, PCITEST_BAR, test->barnum); | 
|  | 63 | fprintf(stdout, "BAR%d:\t\t", test->barnum); | 
|  | 64 | if (ret < 0) | 
|  | 65 | fprintf(stdout, "TEST FAILED\n"); | 
|  | 66 | else | 
|  | 67 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | if (test->set_irqtype) { | 
|  | 71 | ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype); | 
|  | 72 | fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]); | 
|  | 73 | if (ret < 0) | 
|  | 74 | fprintf(stdout, "FAILED\n"); | 
|  | 75 | else | 
|  | 76 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 77 | } | 
|  | 78 |  | 
|  | 79 | if (test->get_irqtype) { | 
|  | 80 | ret = ioctl(fd, PCITEST_GET_IRQTYPE); | 
|  | 81 | fprintf(stdout, "GET IRQ TYPE:\t\t"); | 
|  | 82 | if (ret < 0) | 
|  | 83 | fprintf(stdout, "FAILED\n"); | 
|  | 84 | else | 
|  | 85 | fprintf(stdout, "%s\n", irq[ret]); | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | if (test->legacyirq) { | 
|  | 89 | ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0); | 
|  | 90 | fprintf(stdout, "LEGACY IRQ:\t"); | 
|  | 91 | if (ret < 0) | 
|  | 92 | fprintf(stdout, "TEST FAILED\n"); | 
|  | 93 | else | 
|  | 94 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | if (test->msinum > 0 && test->msinum <= 32) { | 
|  | 98 | ret = ioctl(fd, PCITEST_MSI, test->msinum); | 
|  | 99 | fprintf(stdout, "MSI%d:\t\t", test->msinum); | 
|  | 100 | if (ret < 0) | 
|  | 101 | fprintf(stdout, "TEST FAILED\n"); | 
|  | 102 | else | 
|  | 103 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | if (test->msixnum > 0 && test->msixnum <= 2048) { | 
|  | 107 | ret = ioctl(fd, PCITEST_MSIX, test->msixnum); | 
|  | 108 | fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); | 
|  | 109 | if (ret < 0) | 
|  | 110 | fprintf(stdout, "TEST FAILED\n"); | 
|  | 111 | else | 
|  | 112 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 113 | } | 
|  | 114 |  | 
|  | 115 | if (test->write) { | 
|  | 116 | ret = ioctl(fd, PCITEST_WRITE, test->size); | 
|  | 117 | fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size); | 
|  | 118 | if (ret < 0) | 
|  | 119 | fprintf(stdout, "TEST FAILED\n"); | 
|  | 120 | else | 
|  | 121 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | if (test->read) { | 
|  | 125 | ret = ioctl(fd, PCITEST_READ, test->size); | 
|  | 126 | fprintf(stdout, "READ (%7ld bytes):\t\t", test->size); | 
|  | 127 | if (ret < 0) | 
|  | 128 | fprintf(stdout, "TEST FAILED\n"); | 
|  | 129 | else | 
|  | 130 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 | if (test->copy) { | 
|  | 134 | ret = ioctl(fd, PCITEST_COPY, test->size); | 
|  | 135 | fprintf(stdout, "COPY (%7ld bytes):\t\t", test->size); | 
|  | 136 | if (ret < 0) | 
|  | 137 | fprintf(stdout, "TEST FAILED\n"); | 
|  | 138 | else | 
|  | 139 | fprintf(stdout, "%s\n", result[ret]); | 
|  | 140 | } | 
|  | 141 |  | 
|  | 142 | fflush(stdout); | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | int main(int argc, char **argv) | 
|  | 146 | { | 
|  | 147 | int c; | 
|  | 148 | struct pci_test *test; | 
|  | 149 |  | 
|  | 150 | test = calloc(1, sizeof(*test)); | 
|  | 151 | if (!test) { | 
|  | 152 | perror("Fail to allocate memory for pci_test\n"); | 
|  | 153 | return -ENOMEM; | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | /* since '0' is a valid BAR number, initialize it to -1 */ | 
|  | 157 | test->barnum = -1; | 
|  | 158 |  | 
|  | 159 | /* set default size as 100KB */ | 
|  | 160 | test->size = 0x19000; | 
|  | 161 |  | 
|  | 162 | /* set default endpoint device */ | 
|  | 163 | test->device = "/dev/pci-endpoint-test.0"; | 
|  | 164 |  | 
|  | 165 | while ((c = getopt(argc, argv, "D:b:m:x:i:Ilrwcs:")) != EOF) | 
|  | 166 | switch (c) { | 
|  | 167 | case 'D': | 
|  | 168 | test->device = optarg; | 
|  | 169 | continue; | 
|  | 170 | case 'b': | 
|  | 171 | test->barnum = atoi(optarg); | 
|  | 172 | if (test->barnum < 0 || test->barnum > 5) | 
|  | 173 | goto usage; | 
|  | 174 | continue; | 
|  | 175 | case 'l': | 
|  | 176 | test->legacyirq = true; | 
|  | 177 | continue; | 
|  | 178 | case 'm': | 
|  | 179 | test->msinum = atoi(optarg); | 
|  | 180 | if (test->msinum < 1 || test->msinum > 32) | 
|  | 181 | goto usage; | 
|  | 182 | continue; | 
|  | 183 | case 'x': | 
|  | 184 | test->msixnum = atoi(optarg); | 
|  | 185 | if (test->msixnum < 1 || test->msixnum > 2048) | 
|  | 186 | goto usage; | 
|  | 187 | continue; | 
|  | 188 | case 'i': | 
|  | 189 | test->irqtype = atoi(optarg); | 
|  | 190 | if (test->irqtype < 0 || test->irqtype > 2) | 
|  | 191 | goto usage; | 
|  | 192 | test->set_irqtype = true; | 
|  | 193 | continue; | 
|  | 194 | case 'I': | 
|  | 195 | test->get_irqtype = true; | 
|  | 196 | continue; | 
|  | 197 | case 'r': | 
|  | 198 | test->read = true; | 
|  | 199 | continue; | 
|  | 200 | case 'w': | 
|  | 201 | test->write = true; | 
|  | 202 | continue; | 
|  | 203 | case 'c': | 
|  | 204 | test->copy = true; | 
|  | 205 | continue; | 
|  | 206 | case 's': | 
|  | 207 | test->size = strtoul(optarg, NULL, 0); | 
|  | 208 | continue; | 
|  | 209 | case '?': | 
|  | 210 | case 'h': | 
|  | 211 | default: | 
|  | 212 | usage: | 
|  | 213 | fprintf(stderr, | 
|  | 214 | "usage: %s [options]\n" | 
|  | 215 | "Options:\n" | 
|  | 216 | "\t-D <dev>		PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n" | 
|  | 217 | "\t-b <bar num>		BAR test (bar number between 0..5)\n" | 
|  | 218 | "\t-m <msi num>		MSI test (msi number between 1..32)\n" | 
|  | 219 | "\t-x <msix num>	\tMSI-X test (msix number between 1..2048)\n" | 
|  | 220 | "\t-i <irq type>	\tSet IRQ type (0 - Legacy, 1 - MSI, 2 - MSI-X)\n" | 
|  | 221 | "\t-I			Get current IRQ type configured\n" | 
|  | 222 | "\t-l			Legacy IRQ test\n" | 
|  | 223 | "\t-r			Read buffer test\n" | 
|  | 224 | "\t-w			Write buffer test\n" | 
|  | 225 | "\t-c			Copy buffer test\n" | 
|  | 226 | "\t-s <size>		Size of buffer {default: 100KB}\n", | 
|  | 227 | argv[0]); | 
|  | 228 | return -EINVAL; | 
|  | 229 | } | 
|  | 230 |  | 
|  | 231 | run_test(test); | 
|  | 232 | return 0; | 
|  | 233 | } |