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