xref: /linux/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c (revision 2f2c7254931f41b5736e3ba12aaa9ac1bbeeeb92)
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 
FIXTURE(pci_ep_bar)34 FIXTURE(pci_ep_bar)
35 {
36 	int fd;
37 };
38 
FIXTURE_SETUP(pci_ep_bar)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 
FIXTURE_TEARDOWN(pci_ep_bar)46 FIXTURE_TEARDOWN(pci_ep_bar)
47 {
48 	close(self->fd);
49 }
50 
FIXTURE_VARIANT(pci_ep_bar)51 FIXTURE_VARIANT(pci_ep_bar)
52 {
53 	int barno;
54 };
55 
FIXTURE_VARIANT_ADD(pci_ep_bar,BAR0)56 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR0) { .barno = 0 };
FIXTURE_VARIANT_ADD(pci_ep_bar,BAR1)57 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR1) { .barno = 1 };
FIXTURE_VARIANT_ADD(pci_ep_bar,BAR2)58 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR2) { .barno = 2 };
FIXTURE_VARIANT_ADD(pci_ep_bar,BAR3)59 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR3) { .barno = 3 };
FIXTURE_VARIANT_ADD(pci_ep_bar,BAR4)60 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR4) { .barno = 4 };
FIXTURE_VARIANT_ADD(pci_ep_bar,BAR5)61 FIXTURE_VARIANT_ADD(pci_ep_bar, BAR5) { .barno = 5 };
62 
TEST_F(pci_ep_bar,BAR_TEST)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 
FIXTURE(pci_ep_basic)73 FIXTURE(pci_ep_basic)
74 {
75 	int fd;
76 };
77 
FIXTURE_SETUP(pci_ep_basic)78 FIXTURE_SETUP(pci_ep_basic)
79 {
80 	self->fd = open(test_device, O_RDWR);
81 
82 	ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
83 }
84 
FIXTURE_TEARDOWN(pci_ep_basic)85 FIXTURE_TEARDOWN(pci_ep_basic)
86 {
87 	close(self->fd);
88 }
89 
TEST_F(pci_ep_basic,CONSECUTIVE_BAR_TEST)90 TEST_F(pci_ep_basic, CONSECUTIVE_BAR_TEST)
91 {
92 	int ret;
93 
94 	pci_ep_ioctl(PCITEST_BARS, 0);
95 	EXPECT_FALSE(ret) TH_LOG("Consecutive BAR test failed");
96 }
97 
TEST_F(pci_ep_basic,LEGACY_IRQ_TEST)98 TEST_F(pci_ep_basic, LEGACY_IRQ_TEST)
99 {
100 	int ret;
101 
102 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_INTX);
103 	ASSERT_EQ(0, ret) TH_LOG("Can't set Legacy IRQ type");
104 
105 	pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
106 	ASSERT_EQ(PCITEST_IRQ_TYPE_INTX, ret) TH_LOG("Can't get Legacy IRQ type");
107 
108 	pci_ep_ioctl(PCITEST_LEGACY_IRQ, 0);
109 	EXPECT_FALSE(ret) TH_LOG("Test failed for Legacy IRQ");
110 }
111 
TEST_F(pci_ep_basic,MSI_TEST)112 TEST_F(pci_ep_basic, MSI_TEST)
113 {
114 	int ret, i;
115 
116 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSI);
117 	ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type");
118 
119 	pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
120 	ASSERT_EQ(PCITEST_IRQ_TYPE_MSI, ret) TH_LOG("Can't get MSI IRQ type");
121 
122 	for (i = 1; i <= 32; i++) {
123 		pci_ep_ioctl(PCITEST_MSI, i);
124 		if (ret == -EINVAL)
125 			SKIP(return, "MSI%d is disabled", i);
126 		EXPECT_FALSE(ret) TH_LOG("Test failed for MSI%d", i);
127 	}
128 }
129 
TEST_F(pci_ep_basic,MSIX_TEST)130 TEST_F(pci_ep_basic, MSIX_TEST)
131 {
132 	int ret, i;
133 
134 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSIX);
135 	ASSERT_EQ(0, ret) TH_LOG("Can't set MSI-X IRQ type");
136 
137 	pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
138 	ASSERT_EQ(PCITEST_IRQ_TYPE_MSIX, ret) TH_LOG("Can't get MSI-X IRQ type");
139 
140 	for (i = 1; i <= 2048; i++) {
141 		pci_ep_ioctl(PCITEST_MSIX, i);
142 		if (ret == -EINVAL)
143 			SKIP(return, "MSI-X%d is disabled", i);
144 		EXPECT_FALSE(ret) TH_LOG("Test failed for MSI-X%d", i);
145 	}
146 }
147 
FIXTURE(pci_ep_data_transfer)148 FIXTURE(pci_ep_data_transfer)
149 {
150 	int fd;
151 };
152 
FIXTURE_SETUP(pci_ep_data_transfer)153 FIXTURE_SETUP(pci_ep_data_transfer)
154 {
155 	self->fd = open(test_device, O_RDWR);
156 
157 	ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
158 }
159 
FIXTURE_TEARDOWN(pci_ep_data_transfer)160 FIXTURE_TEARDOWN(pci_ep_data_transfer)
161 {
162 	close(self->fd);
163 }
164 
FIXTURE_VARIANT(pci_ep_data_transfer)165 FIXTURE_VARIANT(pci_ep_data_transfer)
166 {
167 	bool use_dma;
168 };
169 
FIXTURE_VARIANT_ADD(pci_ep_data_transfer,memcpy)170 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, memcpy)
171 {
172 	.use_dma = false,
173 };
174 
FIXTURE_VARIANT_ADD(pci_ep_data_transfer,dma)175 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, dma)
176 {
177 	.use_dma = true,
178 };
179 
TEST_F(pci_ep_data_transfer,READ_TEST)180 TEST_F(pci_ep_data_transfer, READ_TEST)
181 {
182 	struct pci_endpoint_test_xfer_param param = {};
183 	int ret, i;
184 
185 	if (variant->use_dma)
186 		param.flags = PCITEST_FLAGS_USE_DMA;
187 
188 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
189 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
190 
191 	for (i = 0; i < ARRAY_SIZE(test_size); i++) {
192 		param.size = test_size[i];
193 		pci_ep_ioctl(PCITEST_READ, &param);
194 		EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
195 					 test_size[i]);
196 	}
197 }
198 
TEST_F(pci_ep_data_transfer,WRITE_TEST)199 TEST_F(pci_ep_data_transfer, WRITE_TEST)
200 {
201 	struct pci_endpoint_test_xfer_param param = {};
202 	int ret, i;
203 
204 	if (variant->use_dma)
205 		param.flags = PCITEST_FLAGS_USE_DMA;
206 
207 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
208 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
209 
210 	for (i = 0; i < ARRAY_SIZE(test_size); i++) {
211 		param.size = test_size[i];
212 		pci_ep_ioctl(PCITEST_WRITE, &param);
213 		EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
214 					 test_size[i]);
215 	}
216 }
217 
TEST_F(pci_ep_data_transfer,COPY_TEST)218 TEST_F(pci_ep_data_transfer, COPY_TEST)
219 {
220 	struct pci_endpoint_test_xfer_param param = {};
221 	int ret, i;
222 
223 	if (variant->use_dma)
224 		param.flags = PCITEST_FLAGS_USE_DMA;
225 
226 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
227 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
228 
229 	for (i = 0; i < ARRAY_SIZE(test_size); i++) {
230 		param.size = test_size[i];
231 		pci_ep_ioctl(PCITEST_COPY, &param);
232 		EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
233 					 test_size[i]);
234 	}
235 }
236 
FIXTURE(pcie_ep_doorbell)237 FIXTURE(pcie_ep_doorbell)
238 {
239 	int fd;
240 };
241 
FIXTURE_SETUP(pcie_ep_doorbell)242 FIXTURE_SETUP(pcie_ep_doorbell)
243 {
244 	self->fd = open(test_device, O_RDWR);
245 
246 	ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
247 };
248 
FIXTURE_TEARDOWN(pcie_ep_doorbell)249 FIXTURE_TEARDOWN(pcie_ep_doorbell)
250 {
251 	close(self->fd);
252 };
253 
TEST_F(pcie_ep_doorbell,DOORBELL_TEST)254 TEST_F(pcie_ep_doorbell, DOORBELL_TEST)
255 {
256 	int ret;
257 
258 	pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
259 	ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
260 
261 	pci_ep_ioctl(PCITEST_DOORBELL, 0);
262 	EXPECT_FALSE(ret) TH_LOG("Test failed for Doorbell\n");
263 }
264 TEST_HARNESS_MAIN
265