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 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 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 148 FIXTURE(pci_ep_data_transfer) 149 { 150 int fd; 151 }; 152 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 160 FIXTURE_TEARDOWN(pci_ep_data_transfer) 161 { 162 close(self->fd); 163 } 164 165 FIXTURE_VARIANT(pci_ep_data_transfer) 166 { 167 bool use_dma; 168 }; 169 170 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, memcpy) 171 { 172 .use_dma = false, 173 }; 174 175 FIXTURE_VARIANT_ADD(pci_ep_data_transfer, dma) 176 { 177 .use_dma = true, 178 }; 179 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, ¶m); 194 EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)", 195 test_size[i]); 196 } 197 } 198 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, ¶m); 213 EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)", 214 test_size[i]); 215 } 216 } 217 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, ¶m); 232 EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)", 233 test_size[i]); 234 } 235 } 236 237 FIXTURE(pcie_ep_doorbell) 238 { 239 int fd; 240 }; 241 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 249 FIXTURE_TEARDOWN(pcie_ep_doorbell) 250 { 251 close(self->fd); 252 }; 253 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