mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-04-13 09:59:31 +00:00
Merge branch 'pci/endpoint-test'
- Fix endpoint BAR testing so the test can skip disabled BARs instead of reporting them as failures (Niklas Cassel) - Verify that pci_endpoint interrupt tests set the correct IRQ type (Kunihiko Hayashi) - Fix interpretation of pci_endpoint_test_bars_read_bar() error returns (Niklas Cassel) - Fix potential string truncation in pci_endpoint_test_probe() (Niklas Cassel) - Increase endpoint test BAR size variable to accommodate BARs larger than INT_MAX (Niklas Cassel) - Release IRQs to avoid leak in pci_endpoint interrupt tests (Kunihiko Hayashi) - Log the correct IRQ type when pci_endpoint IRQ request test fails (Kunihiko Hayashi) - Remove pci_endpoint_test irq_type and no_msi globals; instead use test->irq_type (Kunihiko Hayashi) - Remove unnecessary use of managed IRQ functions in pci_endpoint_test (Kunihiko Hayashi) - Add and use IRQ_TYPE_* defines in pci_endpoint_test (Niklas Cassel) - Add struct pci_epc_features.intx_capable and note that RK3568 and RK3588 can't raise INTx interrupts (Niklas Cassel) - Expose supported IRQ types in CAPS so pci_endpoint_test can set appropriate type (Niklas Cassel) - Add PCITEST_IRQ_TYPE_AUTO to pci_endpoint_test for cases where the IRQ type doesn't matter (Niklas Cassel) * pci/endpoint-test: misc: pci_endpoint_test: Add support for PCITEST_IRQ_TYPE_AUTO PCI: endpoint: pci-epf-test: Expose supported IRQ types in CAPS register PCI: dw-rockchip: Endpoint mode cannot raise INTx interrupts PCI: endpoint: Add intx_capable to epc_features struct selftests: pci_endpoint: Use IRQ_TYPE_* defines from UAPI header misc: pci_endpoint_test: Use IRQ_TYPE_* defines from UAPI header PCI: endpoint: pcitest: Add IRQ_TYPE_* defines to UAPI header misc: pci_endpoint_test: Do not use managed IRQ functions misc: pci_endpoint_test: Remove global 'irq_type' and 'no_msi' misc: pci_endpoint_test: Fix 'irq_type' to convey the correct type misc: pci_endpoint_test: Fix displaying 'irq_type' after 'request_irq' error misc: pci_endpoint_test: Avoid issue of interrupts remaining after request_irq error misc: pci_endpoint_test: Handle BAR sizes larger than INT_MAX misc: pci_endpoint_test: Give disabled BARs a distinct error code misc: pci_endpoint_test: Fix potential truncation in pci_endpoint_test_probe() misc: pci_endpoint_test: Fix pci_endpoint_test_bars_read_bar() error handling selftests: pci_endpoint: Add GET_IRQTYPE checks to each interrupt test selftests: pci_endpoint: Skip disabled BARs
This commit is contained in:
commit
cc28c0e5e7
6 changed files with 113 additions and 70 deletions
|
@ -28,11 +28,6 @@
|
|||
|
||||
#define DRV_MODULE_NAME "pci-endpoint-test"
|
||||
|
||||
#define IRQ_TYPE_UNDEFINED -1
|
||||
#define IRQ_TYPE_INTX 0
|
||||
#define IRQ_TYPE_MSI 1
|
||||
#define IRQ_TYPE_MSIX 2
|
||||
|
||||
#define PCI_ENDPOINT_TEST_MAGIC 0x0
|
||||
|
||||
#define PCI_ENDPOINT_TEST_COMMAND 0x4
|
||||
|
@ -71,6 +66,9 @@
|
|||
|
||||
#define PCI_ENDPOINT_TEST_CAPS 0x30
|
||||
#define CAP_UNALIGNED_ACCESS BIT(0)
|
||||
#define CAP_MSI BIT(1)
|
||||
#define CAP_MSIX BIT(2)
|
||||
#define CAP_INTX BIT(3)
|
||||
|
||||
#define PCI_DEVICE_ID_TI_AM654 0xb00c
|
||||
#define PCI_DEVICE_ID_TI_J7200 0xb00f
|
||||
|
@ -96,14 +94,6 @@ static DEFINE_IDA(pci_endpoint_test_ida);
|
|||
#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
|
||||
miscdev)
|
||||
|
||||
static bool no_msi;
|
||||
module_param(no_msi, bool, 0444);
|
||||
MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
|
||||
|
||||
static int irq_type = IRQ_TYPE_MSI;
|
||||
module_param(irq_type, int, 0444);
|
||||
MODULE_PARM_DESC(irq_type, "IRQ mode selection in pci_endpoint_test (0 - Legacy, 1 - MSI, 2 - MSI-X)");
|
||||
|
||||
enum pci_barno {
|
||||
BAR_0,
|
||||
BAR_1,
|
||||
|
@ -126,6 +116,7 @@ struct pci_endpoint_test {
|
|||
struct miscdevice miscdev;
|
||||
enum pci_barno test_reg_bar;
|
||||
size_t alignment;
|
||||
u32 ep_caps;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
|
@ -166,7 +157,7 @@ static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test)
|
|||
struct pci_dev *pdev = test->pdev;
|
||||
|
||||
pci_free_irq_vectors(pdev);
|
||||
test->irq_type = IRQ_TYPE_UNDEFINED;
|
||||
test->irq_type = PCITEST_IRQ_TYPE_UNDEFINED;
|
||||
}
|
||||
|
||||
static int pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
|
||||
|
@ -177,7 +168,7 @@ static int pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
|
|||
struct device *dev = &pdev->dev;
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_INTX:
|
||||
case PCITEST_IRQ_TYPE_INTX:
|
||||
irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "Failed to get Legacy interrupt\n");
|
||||
|
@ -185,7 +176,7 @@ static int pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
|
|||
}
|
||||
|
||||
break;
|
||||
case IRQ_TYPE_MSI:
|
||||
case PCITEST_IRQ_TYPE_MSI:
|
||||
irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "Failed to get MSI interrupts\n");
|
||||
|
@ -193,7 +184,7 @@ static int pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
|
|||
}
|
||||
|
||||
break;
|
||||
case IRQ_TYPE_MSIX:
|
||||
case PCITEST_IRQ_TYPE_MSIX:
|
||||
irq = pci_alloc_irq_vectors(pdev, 1, 2048, PCI_IRQ_MSIX);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "Failed to get MSI-X interrupts\n");
|
||||
|
@ -216,10 +207,9 @@ static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test)
|
|||
{
|
||||
int i;
|
||||
struct pci_dev *pdev = test->pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
for (i = 0; i < test->num_irqs; i++)
|
||||
devm_free_irq(dev, pci_irq_vector(pdev, i), test);
|
||||
free_irq(pci_irq_vector(pdev, i), test);
|
||||
|
||||
test->num_irqs = 0;
|
||||
}
|
||||
|
@ -232,9 +222,9 @@ static int pci_endpoint_test_request_irq(struct pci_endpoint_test *test)
|
|||
struct device *dev = &pdev->dev;
|
||||
|
||||
for (i = 0; i < test->num_irqs; i++) {
|
||||
ret = devm_request_irq(dev, pci_irq_vector(pdev, i),
|
||||
pci_endpoint_test_irqhandler,
|
||||
IRQF_SHARED, test->name, test);
|
||||
ret = request_irq(pci_irq_vector(pdev, i),
|
||||
pci_endpoint_test_irqhandler, IRQF_SHARED,
|
||||
test->name, test);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
@ -242,23 +232,26 @@ static int pci_endpoint_test_request_irq(struct pci_endpoint_test *test)
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
switch (irq_type) {
|
||||
case IRQ_TYPE_INTX:
|
||||
switch (test->irq_type) {
|
||||
case PCITEST_IRQ_TYPE_INTX:
|
||||
dev_err(dev, "Failed to request IRQ %d for Legacy\n",
|
||||
pci_irq_vector(pdev, i));
|
||||
break;
|
||||
case IRQ_TYPE_MSI:
|
||||
case PCITEST_IRQ_TYPE_MSI:
|
||||
dev_err(dev, "Failed to request IRQ %d for MSI %d\n",
|
||||
pci_irq_vector(pdev, i),
|
||||
i + 1);
|
||||
break;
|
||||
case IRQ_TYPE_MSIX:
|
||||
case PCITEST_IRQ_TYPE_MSIX:
|
||||
dev_err(dev, "Failed to request IRQ %d for MSI-X %d\n",
|
||||
pci_irq_vector(pdev, i),
|
||||
i + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
test->num_irqs = i;
|
||||
pci_endpoint_test_release_irq(test);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -272,9 +265,9 @@ static const u32 bar_test_pattern[] = {
|
|||
};
|
||||
|
||||
static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test,
|
||||
enum pci_barno barno, int offset,
|
||||
void *write_buf, void *read_buf,
|
||||
int size)
|
||||
enum pci_barno barno,
|
||||
resource_size_t offset, void *write_buf,
|
||||
void *read_buf, int size)
|
||||
{
|
||||
memset(write_buf, bar_test_pattern[barno], size);
|
||||
memcpy_toio(test->bar[barno] + offset, write_buf, size);
|
||||
|
@ -287,16 +280,19 @@ static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test,
|
|||
static int pci_endpoint_test_bar(struct pci_endpoint_test *test,
|
||||
enum pci_barno barno)
|
||||
{
|
||||
int j, bar_size, buf_size, iters;
|
||||
resource_size_t bar_size, offset = 0;
|
||||
void *write_buf __free(kfree) = NULL;
|
||||
void *read_buf __free(kfree) = NULL;
|
||||
struct pci_dev *pdev = test->pdev;
|
||||
int buf_size;
|
||||
|
||||
bar_size = pci_resource_len(pdev, barno);
|
||||
if (!bar_size)
|
||||
return -ENODATA;
|
||||
|
||||
if (!test->bar[barno])
|
||||
return -ENOMEM;
|
||||
|
||||
bar_size = pci_resource_len(pdev, barno);
|
||||
|
||||
if (barno == test->test_reg_bar)
|
||||
bar_size = 0x4;
|
||||
|
||||
|
@ -314,11 +310,12 @@ static int pci_endpoint_test_bar(struct pci_endpoint_test *test,
|
|||
if (!read_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
iters = bar_size / buf_size;
|
||||
for (j = 0; j < iters; j++)
|
||||
if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * j,
|
||||
write_buf, read_buf, buf_size))
|
||||
while (offset < bar_size) {
|
||||
if (pci_endpoint_test_bar_memcmp(test, barno, offset, write_buf,
|
||||
read_buf, buf_size))
|
||||
return -EIO;
|
||||
offset += buf_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -382,7 +379,7 @@ static int pci_endpoint_test_bars_read_bar(struct pci_endpoint_test *test,
|
|||
static int pci_endpoint_test_bars(struct pci_endpoint_test *test)
|
||||
{
|
||||
enum pci_barno bar;
|
||||
bool ret;
|
||||
int ret;
|
||||
|
||||
/* Write all BARs in order (without reading). */
|
||||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
|
||||
|
@ -398,7 +395,7 @@ static int pci_endpoint_test_bars(struct pci_endpoint_test *test)
|
|||
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
|
||||
if (test->bar[bar]) {
|
||||
ret = pci_endpoint_test_bars_read_bar(test, bar);
|
||||
if (!ret)
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +408,7 @@ static int pci_endpoint_test_intx_irq(struct pci_endpoint_test *test)
|
|||
u32 val;
|
||||
|
||||
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
|
||||
IRQ_TYPE_INTX);
|
||||
PCITEST_IRQ_TYPE_INTX);
|
||||
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, 0);
|
||||
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
|
||||
COMMAND_RAISE_INTX_IRQ);
|
||||
|
@ -431,7 +428,8 @@ static int pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
|
|||
int ret;
|
||||
|
||||
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_TYPE,
|
||||
msix ? IRQ_TYPE_MSIX : IRQ_TYPE_MSI);
|
||||
msix ? PCITEST_IRQ_TYPE_MSIX :
|
||||
PCITEST_IRQ_TYPE_MSI);
|
||||
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_IRQ_NUMBER, msi_num);
|
||||
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
|
||||
msix ? COMMAND_RAISE_MSIX_IRQ :
|
||||
|
@ -507,7 +505,8 @@ static int pci_endpoint_test_copy(struct pci_endpoint_test *test,
|
|||
if (use_dma)
|
||||
flags |= FLAG_USE_DMA;
|
||||
|
||||
if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX) {
|
||||
if (irq_type < PCITEST_IRQ_TYPE_INTX ||
|
||||
irq_type > PCITEST_IRQ_TYPE_MSIX) {
|
||||
dev_err(dev, "Invalid IRQ type option\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -639,7 +638,8 @@ static int pci_endpoint_test_write(struct pci_endpoint_test *test,
|
|||
if (use_dma)
|
||||
flags |= FLAG_USE_DMA;
|
||||
|
||||
if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX) {
|
||||
if (irq_type < PCITEST_IRQ_TYPE_INTX ||
|
||||
irq_type > PCITEST_IRQ_TYPE_MSIX) {
|
||||
dev_err(dev, "Invalid IRQ type option\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -735,7 +735,8 @@ static int pci_endpoint_test_read(struct pci_endpoint_test *test,
|
|||
if (use_dma)
|
||||
flags |= FLAG_USE_DMA;
|
||||
|
||||
if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX) {
|
||||
if (irq_type < PCITEST_IRQ_TYPE_INTX ||
|
||||
irq_type > PCITEST_IRQ_TYPE_MSIX) {
|
||||
dev_err(dev, "Invalid IRQ type option\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -805,11 +806,24 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test,
|
|||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
if (req_irq_type < IRQ_TYPE_INTX || req_irq_type > IRQ_TYPE_MSIX) {
|
||||
if (req_irq_type < PCITEST_IRQ_TYPE_INTX ||
|
||||
req_irq_type > PCITEST_IRQ_TYPE_AUTO) {
|
||||
dev_err(dev, "Invalid IRQ type option\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (req_irq_type == PCITEST_IRQ_TYPE_AUTO) {
|
||||
if (test->ep_caps & CAP_MSI)
|
||||
req_irq_type = PCITEST_IRQ_TYPE_MSI;
|
||||
else if (test->ep_caps & CAP_MSIX)
|
||||
req_irq_type = PCITEST_IRQ_TYPE_MSIX;
|
||||
else if (test->ep_caps & CAP_INTX)
|
||||
req_irq_type = PCITEST_IRQ_TYPE_INTX;
|
||||
else
|
||||
/* fallback to MSI if no caps defined */
|
||||
req_irq_type = PCITEST_IRQ_TYPE_MSI;
|
||||
}
|
||||
|
||||
if (test->irq_type == req_irq_type)
|
||||
return 0;
|
||||
|
||||
|
@ -874,7 +888,7 @@ static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
|
|||
ret = pci_endpoint_test_set_irq(test, arg);
|
||||
break;
|
||||
case PCITEST_GET_IRQTYPE:
|
||||
ret = irq_type;
|
||||
ret = test->irq_type;
|
||||
break;
|
||||
case PCITEST_CLEAR_IRQ:
|
||||
ret = pci_endpoint_test_clear_irq(test);
|
||||
|
@ -895,13 +909,12 @@ static void pci_endpoint_test_get_capabilities(struct pci_endpoint_test *test)
|
|||
{
|
||||
struct pci_dev *pdev = test->pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
u32 caps;
|
||||
|
||||
caps = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CAPS);
|
||||
dev_dbg(dev, "PCI_ENDPOINT_TEST_CAPS: %#x\n", caps);
|
||||
test->ep_caps = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CAPS);
|
||||
dev_dbg(dev, "PCI_ENDPOINT_TEST_CAPS: %#x\n", test->ep_caps);
|
||||
|
||||
/* CAP_UNALIGNED_ACCESS is set if the EP can do unaligned access */
|
||||
if (caps & CAP_UNALIGNED_ACCESS)
|
||||
if (test->ep_caps & CAP_UNALIGNED_ACCESS)
|
||||
test->alignment = 0;
|
||||
}
|
||||
|
||||
|
@ -910,7 +923,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
|
|||
{
|
||||
int ret;
|
||||
int id;
|
||||
char name[24];
|
||||
char name[29];
|
||||
enum pci_barno bar;
|
||||
void __iomem *base;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -929,17 +942,14 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
|
|||
test->test_reg_bar = 0;
|
||||
test->alignment = 0;
|
||||
test->pdev = pdev;
|
||||
test->irq_type = IRQ_TYPE_UNDEFINED;
|
||||
|
||||
if (no_msi)
|
||||
irq_type = IRQ_TYPE_INTX;
|
||||
test->irq_type = PCITEST_IRQ_TYPE_UNDEFINED;
|
||||
|
||||
data = (struct pci_endpoint_test_data *)ent->driver_data;
|
||||
if (data) {
|
||||
test_reg_bar = data->test_reg_bar;
|
||||
test->test_reg_bar = test_reg_bar;
|
||||
test->alignment = data->alignment;
|
||||
irq_type = data->irq_type;
|
||||
test->irq_type = data->irq_type;
|
||||
}
|
||||
|
||||
init_completion(&test->irq_raised);
|
||||
|
@ -961,7 +971,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
|
|||
|
||||
pci_set_master(pdev);
|
||||
|
||||
ret = pci_endpoint_test_alloc_irq_vectors(test, irq_type);
|
||||
ret = pci_endpoint_test_alloc_irq_vectors(test, test->irq_type);
|
||||
if (ret)
|
||||
goto err_disable_irq;
|
||||
|
||||
|
@ -1083,23 +1093,23 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
|
|||
static const struct pci_endpoint_test_data default_data = {
|
||||
.test_reg_bar = BAR_0,
|
||||
.alignment = SZ_4K,
|
||||
.irq_type = IRQ_TYPE_MSI,
|
||||
.irq_type = PCITEST_IRQ_TYPE_MSI,
|
||||
};
|
||||
|
||||
static const struct pci_endpoint_test_data am654_data = {
|
||||
.test_reg_bar = BAR_2,
|
||||
.alignment = SZ_64K,
|
||||
.irq_type = IRQ_TYPE_MSI,
|
||||
.irq_type = PCITEST_IRQ_TYPE_MSI,
|
||||
};
|
||||
|
||||
static const struct pci_endpoint_test_data j721e_data = {
|
||||
.alignment = 256,
|
||||
.irq_type = IRQ_TYPE_MSI,
|
||||
.irq_type = PCITEST_IRQ_TYPE_MSI,
|
||||
};
|
||||
|
||||
static const struct pci_endpoint_test_data rk3588_data = {
|
||||
.alignment = SZ_64K,
|
||||
.irq_type = IRQ_TYPE_MSI,
|
||||
.irq_type = PCITEST_IRQ_TYPE_MSI,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -272,6 +272,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
|
|||
.linkup_notifier = true,
|
||||
.msi_capable = true,
|
||||
.msix_capable = true,
|
||||
.intx_capable = false,
|
||||
.align = SZ_64K,
|
||||
.bar[BAR_0] = { .type = BAR_RESIZABLE, },
|
||||
.bar[BAR_1] = { .type = BAR_RESIZABLE, },
|
||||
|
@ -292,6 +293,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
|
|||
.linkup_notifier = true,
|
||||
.msi_capable = true,
|
||||
.msix_capable = true,
|
||||
.intx_capable = false,
|
||||
.align = SZ_64K,
|
||||
.bar[BAR_0] = { .type = BAR_RESIZABLE, },
|
||||
.bar[BAR_1] = { .type = BAR_RESIZABLE, },
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
#define TIMER_RESOLUTION 1
|
||||
|
||||
#define CAP_UNALIGNED_ACCESS BIT(0)
|
||||
#define CAP_MSI BIT(1)
|
||||
#define CAP_MSIX BIT(2)
|
||||
#define CAP_INTX BIT(3)
|
||||
|
||||
static struct workqueue_struct *kpcitest_workqueue;
|
||||
|
||||
|
@ -774,6 +777,15 @@ static void pci_epf_test_set_capabilities(struct pci_epf *epf)
|
|||
if (epc->ops->align_addr)
|
||||
caps |= CAP_UNALIGNED_ACCESS;
|
||||
|
||||
if (epf_test->epc_features->msi_capable)
|
||||
caps |= CAP_MSI;
|
||||
|
||||
if (epf_test->epc_features->msix_capable)
|
||||
caps |= CAP_MSIX;
|
||||
|
||||
if (epf_test->epc_features->intx_capable)
|
||||
caps |= CAP_INTX;
|
||||
|
||||
reg->caps = cpu_to_le32(caps);
|
||||
}
|
||||
|
||||
|
|
|
@ -225,6 +225,7 @@ struct pci_epc_bar_desc {
|
|||
* @linkup_notifier: indicate if the EPC device can notify EPF driver on link up
|
||||
* @msi_capable: indicate if the endpoint function has MSI capability
|
||||
* @msix_capable: indicate if the endpoint function has MSI-X capability
|
||||
* @intx_capable: indicate if the endpoint can raise INTx interrupts
|
||||
* @bar: array specifying the hardware description for each BAR
|
||||
* @align: alignment size required for BAR buffer allocation
|
||||
*/
|
||||
|
@ -232,6 +233,7 @@ struct pci_epc_features {
|
|||
unsigned int linkup_notifier : 1;
|
||||
unsigned int msi_capable : 1;
|
||||
unsigned int msix_capable : 1;
|
||||
unsigned int intx_capable : 1;
|
||||
struct pci_epc_bar_desc bar[PCI_STD_NUM_BARS];
|
||||
size_t align;
|
||||
};
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
#define PCITEST_BARS _IO('P', 0xa)
|
||||
#define PCITEST_CLEAR_IRQ _IO('P', 0x10)
|
||||
|
||||
#define PCITEST_IRQ_TYPE_UNDEFINED -1
|
||||
#define PCITEST_IRQ_TYPE_INTX 0
|
||||
#define PCITEST_IRQ_TYPE_MSI 1
|
||||
#define PCITEST_IRQ_TYPE_MSIX 2
|
||||
#define PCITEST_IRQ_TYPE_AUTO 3
|
||||
|
||||
#define PCITEST_FLAGS_USE_DMA 0x00000001
|
||||
|
||||
struct pci_endpoint_test_xfer_param {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#define pci_ep_ioctl(cmd, arg) \
|
||||
({ \
|
||||
ret = ioctl(self->fd, cmd, arg); \
|
||||
ret = ret < 0 ? -errno : 0; \
|
||||
ret = ret < 0 ? -errno : ret; \
|
||||
})
|
||||
|
||||
static const char *test_device = "/dev/pci-endpoint-test.0";
|
||||
|
@ -65,6 +65,8 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -97,9 +99,12 @@ TEST_F(pci_ep_basic, LEGACY_IRQ_TEST)
|
|||
{
|
||||
int ret;
|
||||
|
||||
pci_ep_ioctl(PCITEST_SET_IRQTYPE, 0);
|
||||
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");
|
||||
}
|
||||
|
@ -108,9 +113,12 @@ TEST_F(pci_ep_basic, MSI_TEST)
|
|||
{
|
||||
int ret, i;
|
||||
|
||||
pci_ep_ioctl(PCITEST_SET_IRQTYPE, 1);
|
||||
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);
|
||||
|
@ -121,9 +129,12 @@ TEST_F(pci_ep_basic, MSIX_TEST)
|
|||
{
|
||||
int ret, i;
|
||||
|
||||
pci_ep_ioctl(PCITEST_SET_IRQTYPE, 2);
|
||||
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);
|
||||
|
@ -170,8 +181,8 @@ TEST_F(pci_ep_data_transfer, READ_TEST)
|
|||
if (variant->use_dma)
|
||||
param.flags = PCITEST_FLAGS_USE_DMA;
|
||||
|
||||
pci_ep_ioctl(PCITEST_SET_IRQTYPE, 1);
|
||||
ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type");
|
||||
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];
|
||||
|
@ -189,8 +200,8 @@ TEST_F(pci_ep_data_transfer, WRITE_TEST)
|
|||
if (variant->use_dma)
|
||||
param.flags = PCITEST_FLAGS_USE_DMA;
|
||||
|
||||
pci_ep_ioctl(PCITEST_SET_IRQTYPE, 1);
|
||||
ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type");
|
||||
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];
|
||||
|
@ -208,8 +219,8 @@ TEST_F(pci_ep_data_transfer, COPY_TEST)
|
|||
if (variant->use_dma)
|
||||
param.flags = PCITEST_FLAGS_USE_DMA;
|
||||
|
||||
pci_ep_ioctl(PCITEST_SET_IRQTYPE, 1);
|
||||
ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type");
|
||||
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];
|
||||
|
|
Loading…
Add table
Reference in a new issue