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, ¶m); 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, ¶m); 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, ¶m); 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