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 EXPECT_FALSE(ret) TH_LOG("Test failed for MSI%d", i);
125 }
126 }
127
TEST_F(pci_ep_basic,MSIX_TEST)128 TEST_F(pci_ep_basic, MSIX_TEST)
129 {
130 int ret, i;
131
132 pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSIX);
133 ASSERT_EQ(0, ret) TH_LOG("Can't set MSI-X IRQ type");
134
135 pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
136 ASSERT_EQ(PCITEST_IRQ_TYPE_MSIX, ret) TH_LOG("Can't get MSI-X IRQ type");
137
138 for (i = 1; i <= 2048; i++) {
139 pci_ep_ioctl(PCITEST_MSIX, i);
140 EXPECT_FALSE(ret) TH_LOG("Test failed for MSI-X%d", i);
141 }
142 }
143
FIXTURE(pci_ep_data_transfer)144 FIXTURE(pci_ep_data_transfer)
145 {
146 int fd;
147 };
148
FIXTURE_SETUP(pci_ep_data_transfer)149 FIXTURE_SETUP(pci_ep_data_transfer)
150 {
151 self->fd = open(test_device, O_RDWR);
152
153 ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
154 }
155
FIXTURE_TEARDOWN(pci_ep_data_transfer)156 FIXTURE_TEARDOWN(pci_ep_data_transfer)
157 {
158 close(self->fd);
159 }
160
FIXTURE_VARIANT(pci_ep_data_transfer)161 FIXTURE_VARIANT(pci_ep_data_transfer)
162 {
163 bool use_dma;
164 };
165
FIXTURE_VARIANT_ADD(pci_ep_data_transfer,memcpy)166 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, memcpy)
167 {
168 .use_dma = false,
169 };
170
FIXTURE_VARIANT_ADD(pci_ep_data_transfer,dma)171 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, dma)
172 {
173 .use_dma = true,
174 };
175
TEST_F(pci_ep_data_transfer,READ_TEST)176 TEST_F(pci_ep_data_transfer, READ_TEST)
177 {
178 struct pci_endpoint_test_xfer_param param = {};
179 int ret, i;
180
181 if (variant->use_dma)
182 param.flags = PCITEST_FLAGS_USE_DMA;
183
184 pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
185 ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
186
187 for (i = 0; i < ARRAY_SIZE(test_size); i++) {
188 param.size = test_size[i];
189 pci_ep_ioctl(PCITEST_READ, ¶m);
190 EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
191 test_size[i]);
192 }
193 }
194
TEST_F(pci_ep_data_transfer,WRITE_TEST)195 TEST_F(pci_ep_data_transfer, WRITE_TEST)
196 {
197 struct pci_endpoint_test_xfer_param param = {};
198 int ret, i;
199
200 if (variant->use_dma)
201 param.flags = PCITEST_FLAGS_USE_DMA;
202
203 pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
204 ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
205
206 for (i = 0; i < ARRAY_SIZE(test_size); i++) {
207 param.size = test_size[i];
208 pci_ep_ioctl(PCITEST_WRITE, ¶m);
209 EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
210 test_size[i]);
211 }
212 }
213
TEST_F(pci_ep_data_transfer,COPY_TEST)214 TEST_F(pci_ep_data_transfer, COPY_TEST)
215 {
216 struct pci_endpoint_test_xfer_param param = {};
217 int ret, i;
218
219 if (variant->use_dma)
220 param.flags = PCITEST_FLAGS_USE_DMA;
221
222 pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
223 ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
224
225 for (i = 0; i < ARRAY_SIZE(test_size); i++) {
226 param.size = test_size[i];
227 pci_ep_ioctl(PCITEST_COPY, ¶m);
228 EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
229 test_size[i]);
230 }
231 }
232 TEST_HARNESS_MAIN
233