mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00

For PCITEST_MSI we really want to set PCITEST_SET_IRQTYPE explicitly to PCITEST_IRQ_TYPE_MSI, since we want to test if MSI works. For PCITEST_MSIX we really want to set PCITEST_SET_IRQTYPE explicitly to PCITEST_IRQ_TYPE_MSIX, since we want to test if MSI works. For PCITEST_LEGACY_IRQ we really want to set PCITEST_SET_IRQTYPE explicitly to PCITEST_IRQ_TYPE_INTX, since we want to test if INTx works. However, for PCITEST_WRITE, PCITEST_READ, PCITEST_COPY, we really don't care which IRQ type that is used, we just want to use a IRQ type that is supported by the EPC. The old behavior was to always use MSI for PCITEST_WRITE, PCITEST_READ, PCITEST_COPY, was to always set IRQ type to MSI before doing the actual test, however, there are EPC drivers that do not support MSI. Add a new PCITEST_IRQ_TYPE_AUTO, that will use the CAPS register to see which IRQ types the endpoint supports, and use one of the supported IRQ types. For backwards compatibility, if the endpoint does not expose any supported IRQ type in the CAPS register, simply fallback to using MSI, as it was unconditionally done before. Signed-off-by: Niklas Cassel <cassel@kernel.org> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org> Link: https://lore.kernel.org/r/20250310111016.859445-16-cassel@kernel.org
233 lines
5.0 KiB
C
233 lines
5.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Kselftest for PCI Endpoint Subsystem
|
|
*
|
|
* Copyright (c) 2022 Samsung Electronics Co., Ltd.
|
|
* https://www.samsung.com
|
|
* Author: Aman Gupta <aman1.gupta@samsung.com>
|
|
*
|
|
* Copyright (c) 2024, Linaro Ltd.
|
|
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "../../../../include/uapi/linux/pcitest.h"
|
|
|
|
#include "../kselftest_harness.h"
|
|
|
|
#define pci_ep_ioctl(cmd, arg) \
|
|
({ \
|
|
ret = ioctl(self->fd, cmd, arg); \
|
|
ret = ret < 0 ? -errno : ret; \
|
|
})
|
|
|
|
static const char *test_device = "/dev/pci-endpoint-test.0";
|
|
static const unsigned long test_size[5] = { 1, 1024, 1025, 1024000, 1024001 };
|
|
|
|
FIXTURE(pci_ep_bar)
|
|
{
|
|
int fd;
|
|
};
|
|
|
|
FIXTURE_SETUP(pci_ep_bar)
|
|
{
|
|
self->fd = open(test_device, O_RDWR);
|
|
|
|
ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
|
|
}
|
|
|
|
FIXTURE_TEARDOWN(pci_ep_bar)
|
|
{
|
|
close(self->fd);
|
|
}
|
|
|
|
FIXTURE_VARIANT(pci_ep_bar)
|
|
{
|
|
int barno;
|
|
};
|
|
|
|
FIXTURE_VARIANT_ADD(pci_ep_bar, BAR0) { .barno = 0 };
|
|
FIXTURE_VARIANT_ADD(pci_ep_bar, BAR1) { .barno = 1 };
|
|
FIXTURE_VARIANT_ADD(pci_ep_bar, BAR2) { .barno = 2 };
|
|
FIXTURE_VARIANT_ADD(pci_ep_bar, BAR3) { .barno = 3 };
|
|
FIXTURE_VARIANT_ADD(pci_ep_bar, BAR4) { .barno = 4 };
|
|
FIXTURE_VARIANT_ADD(pci_ep_bar, BAR5) { .barno = 5 };
|
|
|
|
TEST_F(pci_ep_bar, BAR_TEST)
|
|
{
|
|
int ret;
|
|
|
|
pci_ep_ioctl(PCITEST_BAR, variant->barno);
|
|
if (ret == -ENODATA)
|
|
SKIP(return, "BAR is disabled");
|
|
EXPECT_FALSE(ret) TH_LOG("Test failed for BAR%d", variant->barno);
|
|
}
|
|
|
|
FIXTURE(pci_ep_basic)
|
|
{
|
|
int fd;
|
|
};
|
|
|
|
FIXTURE_SETUP(pci_ep_basic)
|
|
{
|
|
self->fd = open(test_device, O_RDWR);
|
|
|
|
ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
|
|
}
|
|
|
|
FIXTURE_TEARDOWN(pci_ep_basic)
|
|
{
|
|
close(self->fd);
|
|
}
|
|
|
|
TEST_F(pci_ep_basic, CONSECUTIVE_BAR_TEST)
|
|
{
|
|
int ret;
|
|
|
|
pci_ep_ioctl(PCITEST_BARS, 0);
|
|
EXPECT_FALSE(ret) TH_LOG("Consecutive BAR test failed");
|
|
}
|
|
|
|
TEST_F(pci_ep_basic, LEGACY_IRQ_TEST)
|
|
{
|
|
int ret;
|
|
|
|
pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_INTX);
|
|
ASSERT_EQ(0, ret) TH_LOG("Can't set Legacy IRQ type");
|
|
|
|
pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
|
|
ASSERT_EQ(PCITEST_IRQ_TYPE_INTX, ret) TH_LOG("Can't get Legacy IRQ type");
|
|
|
|
pci_ep_ioctl(PCITEST_LEGACY_IRQ, 0);
|
|
EXPECT_FALSE(ret) TH_LOG("Test failed for Legacy IRQ");
|
|
}
|
|
|
|
TEST_F(pci_ep_basic, MSI_TEST)
|
|
{
|
|
int ret, i;
|
|
|
|
pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSI);
|
|
ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type");
|
|
|
|
pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
|
|
ASSERT_EQ(PCITEST_IRQ_TYPE_MSI, ret) TH_LOG("Can't get MSI IRQ type");
|
|
|
|
for (i = 1; i <= 32; i++) {
|
|
pci_ep_ioctl(PCITEST_MSI, i);
|
|
EXPECT_FALSE(ret) TH_LOG("Test failed for MSI%d", i);
|
|
}
|
|
}
|
|
|
|
TEST_F(pci_ep_basic, MSIX_TEST)
|
|
{
|
|
int ret, i;
|
|
|
|
pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSIX);
|
|
ASSERT_EQ(0, ret) TH_LOG("Can't set MSI-X IRQ type");
|
|
|
|
pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0);
|
|
ASSERT_EQ(PCITEST_IRQ_TYPE_MSIX, ret) TH_LOG("Can't get MSI-X IRQ type");
|
|
|
|
for (i = 1; i <= 2048; i++) {
|
|
pci_ep_ioctl(PCITEST_MSIX, i);
|
|
EXPECT_FALSE(ret) TH_LOG("Test failed for MSI-X%d", i);
|
|
}
|
|
}
|
|
|
|
FIXTURE(pci_ep_data_transfer)
|
|
{
|
|
int fd;
|
|
};
|
|
|
|
FIXTURE_SETUP(pci_ep_data_transfer)
|
|
{
|
|
self->fd = open(test_device, O_RDWR);
|
|
|
|
ASSERT_NE(-1, self->fd) TH_LOG("Can't open PCI Endpoint Test device");
|
|
}
|
|
|
|
FIXTURE_TEARDOWN(pci_ep_data_transfer)
|
|
{
|
|
close(self->fd);
|
|
}
|
|
|
|
FIXTURE_VARIANT(pci_ep_data_transfer)
|
|
{
|
|
bool use_dma;
|
|
};
|
|
|
|
FIXTURE_VARIANT_ADD(pci_ep_data_transfer, memcpy)
|
|
{
|
|
.use_dma = false,
|
|
};
|
|
|
|
FIXTURE_VARIANT_ADD(pci_ep_data_transfer, dma)
|
|
{
|
|
.use_dma = true,
|
|
};
|
|
|
|
TEST_F(pci_ep_data_transfer, READ_TEST)
|
|
{
|
|
struct pci_endpoint_test_xfer_param param = {};
|
|
int ret, i;
|
|
|
|
if (variant->use_dma)
|
|
param.flags = PCITEST_FLAGS_USE_DMA;
|
|
|
|
pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
|
|
ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
|
|
|
|
for (i = 0; i < ARRAY_SIZE(test_size); i++) {
|
|
param.size = test_size[i];
|
|
pci_ep_ioctl(PCITEST_READ, ¶m);
|
|
EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
|
|
test_size[i]);
|
|
}
|
|
}
|
|
|
|
TEST_F(pci_ep_data_transfer, WRITE_TEST)
|
|
{
|
|
struct pci_endpoint_test_xfer_param param = {};
|
|
int ret, i;
|
|
|
|
if (variant->use_dma)
|
|
param.flags = PCITEST_FLAGS_USE_DMA;
|
|
|
|
pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
|
|
ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
|
|
|
|
for (i = 0; i < ARRAY_SIZE(test_size); i++) {
|
|
param.size = test_size[i];
|
|
pci_ep_ioctl(PCITEST_WRITE, ¶m);
|
|
EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
|
|
test_size[i]);
|
|
}
|
|
}
|
|
|
|
TEST_F(pci_ep_data_transfer, COPY_TEST)
|
|
{
|
|
struct pci_endpoint_test_xfer_param param = {};
|
|
int ret, i;
|
|
|
|
if (variant->use_dma)
|
|
param.flags = PCITEST_FLAGS_USE_DMA;
|
|
|
|
pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_AUTO);
|
|
ASSERT_EQ(0, ret) TH_LOG("Can't set AUTO IRQ type");
|
|
|
|
for (i = 0; i < ARRAY_SIZE(test_size); i++) {
|
|
param.size = test_size[i];
|
|
pci_ep_ioctl(PCITEST_COPY, ¶m);
|
|
EXPECT_FALSE(ret) TH_LOG("Test failed for size (%ld)",
|
|
test_size[i]);
|
|
}
|
|
}
|
|
TEST_HARNESS_MAIN
|