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 FIXTURE(pci_ep_basic) 74 { 75 int fd; 76 }; 77 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 85 FIXTURE_TEARDOWN(pci_ep_basic) 86 { 87 close(self->fd); 88 } 89 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 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 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 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 144 FIXTURE(pci_ep_data_transfer) 145 { 146 int fd; 147 }; 148 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 156 FIXTURE_TEARDOWN(pci_ep_data_transfer) 157 { 158 close(self->fd); 159 } 160 161 FIXTURE_VARIANT(pci_ep_data_transfer) 162 { 163 bool use_dma; 164 }; 165 166 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, memcpy) 167 { 168 .use_dma = false, 169 }; 170 171 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, dma) 172 { 173 .use_dma = true, 174 }; 175 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 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 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 233 FIXTURE(pcie_ep_doorbell) 234 { 235 int fd; 236 }; 237 238 FIXTURE_SETUP(pcie_ep_doorbell) 239 { 240 self->fd = open(test_device, O_RDWR); 241 242 ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device"); 243 }; 244 245 FIXTURE_TEARDOWN(pcie_ep_doorbell) 246 { 247 close(self->fd); 248 }; 249 250 TEST_F(pcie_ep_doorbell, DOORBELL_TEST) 251 { 252 int ret; 253 254 pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO); 255 ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type"); 256 257 pci_ep_ioctl(PCITEST_DOORBELL, 0); 258 EXPECT_FALSE(ret) TH_LOG("Test failed for Doorbell\n"); 259 } 260 TEST_HARNESS_MAIN 261