xref: /linux/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Kselftest for PCI Endpoint Subsystem
4  *
5  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
6  *             https://www.samsung.com
7  * Author: Aman Gupta <aman1.gupta@samsung.com>
8  *
9  * Copyright (c) 2024, Linaro Ltd.
10  * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
11  */
12 
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <stdbool.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <sys/ioctl.h>
19 #include <unistd.h>
20 
21 #include "../../../../include/uapi/linux/pcitest.h"
22 
23 #include "kselftest_harness.h"
24 
25 #define pci_ep_ioctl(cmd, arg)			\
26 ({						\
27 	ret = ioctl(self->fd, cmd, arg);	\
28 	ret = ret < 0 ? -errno : ret;		\
29 })
30 
31 static const char *test_device = "/dev/pci-endpoint-test.0";
32 static const unsigned long test_size[5] = { 1, 1024, 1025, 1024000, 1024001 };
33 
34 FIXTURE(pci_ep_bar)
35 {
36 	int fd;
37 };
38 
39 FIXTURE_SETUP(pci_ep_bar)
40 {
41 	self->fd = open(test_device, O_RDWR);
42 
43 	ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
44 }
45 
46 FIXTURE_TEARDOWN(pci_ep_bar)
47 {
48 	close(self->fd);
49 }
50 
51 FIXTURE_VARIANT(pci_ep_bar)
52 {
53 	int barno;
54 };
55 
56 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR0) { .barno = 0 };
57 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR1) { .barno = 1 };
58 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR2) { .barno = 2 };
59 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR3) { .barno = 3 };
60 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR4) { .barno = 4 };
61 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR5) { .barno = 5 };
62 
63 TEST_F(pci_ep_bar, BAR_TEST)
64 {
65 	int ret;
66 
67 	pci_ep_ioctl(PCITEST_BAR, variant->barno);
68 	if (ret == -ENODATA)
69 		SKIP(return, "BAR is disabled");
70 	EXPECT_FALSE(ret) TH_LOG("Test failed for BAR%d", variant->barno);
71 }
72 
73 TEST_F(pci_ep_bar, BAR_SUBRANGE_TEST)
74 {
75 	int ret;
76 
77 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
78 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
79 
80 	pci_ep_ioctl(PCITEST_BAR_SUBRANGE, variant->barno);
81 	if (ret == -ENODATA)
82 		SKIP(return, "BAR is disabled");
83 	if (ret == -EBUSY)
84 		SKIP(return, "BAR is test register space");
85 	if (ret == -EOPNOTSUPP)
86 		SKIP(return, "Subrange map is not supported");
87 	EXPECT_FALSE(ret) TH_LOG("Test failed for BAR%d", variant->barno);
88 }
89 
90 FIXTURE(pci_ep_basic)
91 {
92 	int fd;
93 };
94 
95 FIXTURE_SETUP(pci_ep_basic)
96 {
97 	self->fd = open(test_device, O_RDWR);
98 
99 	ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
100 }
101 
102 FIXTURE_TEARDOWN(pci_ep_basic)
103 {
104 	close(self->fd);
105 }
106 
107 TEST_F(pci_ep_basic, CONSECUTIVE_BAR_TEST)
108 {
109 	int ret;
110 
111 	pci_ep_ioctl(PCITEST_BARS, 0);
112 	EXPECT_FALSE(ret) TH_LOG("Consecutive BAR test failed");
113 }
114 
115 TEST_F(pci_ep_basic, LEGACY_IRQ_TEST)
116 {
117 	int ret;
118 
119 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_INTX);
120 	ASSERT_EQ(0, ret) TH_LOG("Can't set Legacy IRQ type");
121 
122 	pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
123 	ASSERT_EQ(PCITEST_IRQ_TYPE_INTX, ret) TH_LOG("Can't get Legacy IRQ type");
124 
125 	pci_ep_ioctl(PCITEST_LEGACY_IRQ, 0);
126 	EXPECT_FALSE(ret) TH_LOG("Test failed for Legacy IRQ");
127 }
128 
129 TEST_F(pci_ep_basic, MSI_TEST)
130 {
131 	int ret, i;
132 
133 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSI);
134 	ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type");
135 
136 	pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
137 	ASSERT_EQ(PCITEST_IRQ_TYPE_MSI, ret) TH_LOG("Can't get MSI IRQ type");
138 
139 	for (i = 1; i <= 32; i++) {
140 		pci_ep_ioctl(PCITEST_MSI, i);
141 		if (ret == -EINVAL)
142 			SKIP(return, "MSI%d is disabled", i);
143 		EXPECT_FALSE(ret) TH_LOG("Test failed for MSI%d", i);
144 	}
145 }
146 
147 TEST_F(pci_ep_basic, MSIX_TEST)
148 {
149 	int ret, i;
150 
151 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSIX);
152 	ASSERT_EQ(0, ret) TH_LOG("Can't set MSI-X IRQ type");
153 
154 	pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
155 	ASSERT_EQ(PCITEST_IRQ_TYPE_MSIX, ret) TH_LOG("Can't get MSI-X IRQ type");
156 
157 	for (i = 1; i <= 2048; i++) {
158 		pci_ep_ioctl(PCITEST_MSIX, i);
159 		if (ret == -EINVAL)
160 			SKIP(return, "MSI-X%d is disabled", i);
161 		EXPECT_FALSE(ret) TH_LOG("Test failed for MSI-X%d", i);
162 	}
163 }
164 
165 FIXTURE(pci_ep_data_transfer)
166 {
167 	int fd;
168 };
169 
170 FIXTURE_SETUP(pci_ep_data_transfer)
171 {
172 	self->fd = open(test_device, O_RDWR);
173 
174 	ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
175 }
176 
177 FIXTURE_TEARDOWN(pci_ep_data_transfer)
178 {
179 	close(self->fd);
180 }
181 
182 FIXTURE_VARIANT(pci_ep_data_transfer)
183 {
184 	bool use_dma;
185 };
186 
187 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, memcpy)
188 {
189 	.use_dma = false,
190 };
191 
192 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, dma)
193 {
194 	.use_dma = true,
195 };
196 
197 TEST_F(pci_ep_data_transfer, READ_TEST)
198 {
199 	struct pci_endpoint_test_xfer_param param = {};
200 	int ret, i;
201 
202 	if (variant->use_dma)
203 		param.flags = PCITEST_FLAGS_USE_DMA;
204 
205 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
206 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
207 
208 	for (i = 0; i < ARRAY_SIZE(test_size); i++) {
209 		param.size = test_size[i];
210 		pci_ep_ioctl(PCITEST_READ, &param);
211 		EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
212 					 test_size[i]);
213 	}
214 }
215 
216 TEST_F(pci_ep_data_transfer, WRITE_TEST)
217 {
218 	struct pci_endpoint_test_xfer_param param = {};
219 	int ret, i;
220 
221 	if (variant->use_dma)
222 		param.flags = PCITEST_FLAGS_USE_DMA;
223 
224 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
225 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
226 
227 	for (i = 0; i < ARRAY_SIZE(test_size); i++) {
228 		param.size = test_size[i];
229 		pci_ep_ioctl(PCITEST_WRITE, &param);
230 		EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
231 					 test_size[i]);
232 	}
233 }
234 
235 TEST_F(pci_ep_data_transfer, COPY_TEST)
236 {
237 	struct pci_endpoint_test_xfer_param param = {};
238 	int ret, i;
239 
240 	if (variant->use_dma)
241 		param.flags = PCITEST_FLAGS_USE_DMA;
242 
243 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
244 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
245 
246 	for (i = 0; i < ARRAY_SIZE(test_size); i++) {
247 		param.size = test_size[i];
248 		pci_ep_ioctl(PCITEST_COPY, &param);
249 		EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
250 					 test_size[i]);
251 	}
252 }
253 
254 FIXTURE(pcie_ep_doorbell)
255 {
256 	int fd;
257 };
258 
259 FIXTURE_SETUP(pcie_ep_doorbell)
260 {
261 	self->fd = open(test_device, O_RDWR);
262 
263 	ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
264 };
265 
266 FIXTURE_TEARDOWN(pcie_ep_doorbell)
267 {
268 	close(self->fd);
269 };
270 
271 TEST_F(pcie_ep_doorbell, DOORBELL_TEST)
272 {
273 	int ret;
274 
275 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
276 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
277 
278 	pci_ep_ioctl(PCITEST_DOORBELL, 0);
279 	EXPECT_FALSE(ret) TH_LOG("Test failed for Doorbell\n");
280 }
281 TEST_HARNESS_MAIN
282