From af1451b6738ec7cf91f2914f53845424959ec4ee Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Thu, 23 Jan 2025 13:01:49 +0100 Subject: [PATCH 01/18] selftests: pci_endpoint: Skip disabled BARs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently BARs that have been disabled by the endpoint controller driver will result in a test FAIL. Returning FAIL for a BAR that is disabled seems overly pessimistic. There are EPC that disables one or more BARs intentionally. One reason for this is that there are certain EPCs that are hardwired to expose internal PCIe controller registers over a certain BAR, so the EPC driver disables such a BAR, such that the host will not overwrite random registers during testing. Such a BAR will be disabled by the EPC driver's init function, and the BAR will be marked as BAR_RESERVED, such that it will be unavailable to endpoint function drivers. Let's return FAIL only for BARs that are actually enabled and failed the test, and let's return skip for BARs that are not even enabled. Signed-off-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250123120147.3603409-4-cassel@kernel.org Signed-off-by: Manivannan Sadhasivam Signed-off-by: Krzysztof Wilczyński --- tools/testing/selftests/pci_endpoint/pci_endpoint_test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c index c267b822c108..576c590b277b 100644 --- a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c +++ b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c @@ -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); } From a28d2f2398060a27ca3ad89d33c9761c7afd5b8a Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:47 +0900 Subject: [PATCH 02/18] selftests: pci_endpoint: Add GET_IRQTYPE checks to each interrupt test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add GET_IRQTYPE API checks to each interrupt test. While at it, change pci_ep_ioctl() to get the appropriate return value from ioctl(). Suggested-by: Manivannan Sadhasivam Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/20250225110252.28866-2-hayashi.kunihiko@socionext.com [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński --- .../selftests/pci_endpoint/pci_endpoint_test.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c index 576c590b277b..d05e107d0698 100644 --- a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c +++ b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c @@ -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"; @@ -102,6 +102,9 @@ TEST_F(pci_ep_basic, LEGACY_IRQ_TEST) pci_ep_ioctl(PCITEST_SET_IRQTYPE, 0); ASSERT_EQ(0, ret) TH_LOG("Can't set Legacy IRQ type"); + pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0); + ASSERT_EQ(0, 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"); } @@ -113,6 +116,9 @@ TEST_F(pci_ep_basic, MSI_TEST) pci_ep_ioctl(PCITEST_SET_IRQTYPE, 1); ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type"); + pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0); + ASSERT_EQ(1, 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); @@ -126,6 +132,9 @@ TEST_F(pci_ep_basic, MSIX_TEST) pci_ep_ioctl(PCITEST_SET_IRQTYPE, 2); ASSERT_EQ(0, ret) TH_LOG("Can't set MSI-X IRQ type"); + pci_ep_ioctl(PCITEST_GET_IRQTYPE, 0); + ASSERT_EQ(2, 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); From 2a93192d2058507b2e39b590fc1efa0e03344136 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Tue, 4 Feb 2025 12:06:41 +0100 Subject: [PATCH 03/18] misc: pci_endpoint_test: Fix pci_endpoint_test_bars_read_bar() error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit f26d37ee9bda ("misc: pci_endpoint_test: Fix IOCTL return value") changed the return value of pci_endpoint_test_bars_read_bar() from false to -EINVAL on error, however, it failed to update the error handling. Fixes: f26d37ee9bda ("misc: pci_endpoint_test: Fix IOCTL return value") Signed-off-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250204110640.570823-2-cassel@kernel.org Signed-off-by: Manivannan Sadhasivam Signed-off-by: Krzysztof Wilczyński --- drivers/misc/pci_endpoint_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index d5ac71a49386..7584d1876859 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -382,7 +382,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 +398,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; } } From c727ebe94c0444953ac96fc78247520b13f7362d Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Thu, 23 Jan 2025 11:31:28 +0100 Subject: [PATCH 04/18] misc: pci_endpoint_test: Fix potential truncation in pci_endpoint_test_probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Increase the size of the string buffer to avoid potential truncation in pci_endpoint_test_probe(). This fixes the following build warning when compiling with W=1: drivers/misc/pci_endpoint_test.c:29:49: note: directive argument in the range [0, 2147483647] 29 | #define DRV_MODULE_NAME "pci-endpoint-test" | ^~~~~~~~~~~~~~~~~~~ drivers/misc/pci_endpoint_test.c:998:38: note: in expansion of macro ‘DRV_MODULE_NAME’ 998 | snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); | ^~~~~~~~~~~~~~~ drivers/misc/pci_endpoint_test.c:998:9: note: ‘snprintf’ output between 20 and 29 bytes into a destination of size 24 998 | snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20250123103127.3581432-2-cassel@kernel.org Signed-off-by: Manivannan Sadhasivam [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński --- drivers/misc/pci_endpoint_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 7584d1876859..0fa5ddd1969b 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -910,7 +910,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; From 7e80bbef1d697dbce7a39cfad0df770880fe3f29 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Thu, 23 Jan 2025 13:01:48 +0100 Subject: [PATCH 05/18] misc: pci_endpoint_test: Give disabled BARs a distinct error code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code returns -ENOMEM if test->bar[barno] is NULL. There can be two reasons why test->bar[barno] is NULL: 1) The pci_ioremap_bar() call in pci_endpoint_test_probe() failed. 2) The BAR was skipped, because it is disabled by the endpoint. Many PCI endpoint controller drivers will disable all BARs in their init function. A disabled BAR will have a size of 0. A PCI endpoint function driver will be able to enable any BAR that is not marked as BAR_RESERVED (which means that the BAR should not be touched by the EPF driver). Thus, perform check if the size is 0, before checking if test->bar[barno] is NULL, such that we can return different errors. This will allow the selftests to return SKIP instead of FAIL for disabled BARs. Signed-off-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20250123120147.3603409-3-cassel@kernel.org Signed-off-by: Manivannan Sadhasivam [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński --- drivers/misc/pci_endpoint_test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 0fa5ddd1969b..705659f5f0e9 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -292,11 +292,13 @@ static int pci_endpoint_test_bar(struct pci_endpoint_test *test, void *read_buf __free(kfree) = NULL; struct pci_dev *pdev = test->pdev; + 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; From 7962c82a6e648d07bf0067796e4a0e69ba1fc702 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Fri, 24 Jan 2025 10:33:01 +0100 Subject: [PATCH 06/18] misc: pci_endpoint_test: Handle BAR sizes larger than INT_MAX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running 'pcitest -b 0' fails with "TEST FAILED" when the BAR0 size is e.g. 8 GB. The return value of the pci_resource_len() macro can be larger than that of a signed integer type. Thus, when using 'pcitest' with an 8 GB BAR, the bar_size of the integer type will overflow. Change bar_size from integer to resource_size_t to prevent integer overflow for large BAR sizes with 32-bit compilers. In order to handle 64-bit resource_type_t on 32-bit platforms, we would have needed to use a function like div_u64() or similar. Instead, change the code to use addition instead of division. This avoids the need for div_u64() or similar, while also simplifying the code. Fixes: cda370ec6d1f ("misc: pci_endpoint_test: Avoid using hard-coded BAR sizes") Co-developed-by: Hans Zhang <18255117159@163.com> Signed-off-by: Hans Zhang <18255117159@163.com> Signed-off-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Tested-by: Jon Hunter Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20250124093300.3629624-2-cassel@kernel.org [mani: added fixes tag] Signed-off-by: Manivannan Sadhasivam Signed-off-by: Krzysztof Wilczyński --- drivers/misc/pci_endpoint_test.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 705659f5f0e9..a3d2caa7a6bb 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -272,9 +272,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,10 +287,11 @@ 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) @@ -316,11 +317,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; } From f6cb7828c8e17520d4f5afb416515d3fae1af9a9 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:48 +0900 Subject: [PATCH 07/18] misc: pci_endpoint_test: Avoid issue of interrupts remaining after request_irq error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After devm_request_irq() fails with error in pci_endpoint_test_request_irq(), the pci_endpoint_test_free_irq_vectors() is called assuming that all IRQs have been released. However, some requested IRQs remain unreleased, so there are still /proc/irq/* entries remaining, and this results in WARN() with the following message: remove_proc_entry: removing non-empty directory 'irq/30', leaking at least 'pci-endpoint-test.0' WARNING: CPU: 0 PID: 202 at fs/proc/generic.c:719 remove_proc_entry +0x190/0x19c To solve this issue, set the number of remaining IRQs to test->num_irqs, and release IRQs in advance by calling pci_endpoint_test_release_irq(). Cc: stable@vger.kernel.org Fixes: e03327122e2c ("pci_endpoint_test: Add 2 ioctl commands") Reviewed-by: Manivannan Sadhasivam Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/20250225110252.28866-3-hayashi.kunihiko@socionext.com [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński --- drivers/misc/pci_endpoint_test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index a3d2caa7a6bb..9e56d200d2f0 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -259,6 +259,9 @@ fail: break; } + test->num_irqs = i; + pci_endpoint_test_release_irq(test); + return ret; } From 919d14603dab6a9cf03ebbeb2cfa556df48737c8 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:49 +0900 Subject: [PATCH 08/18] misc: pci_endpoint_test: Fix displaying 'irq_type' after 'request_irq' error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two variables that indicate the interrupt type to be used in the next test execution, global "irq_type" and "test->irq_type". The former is referenced from pci_endpoint_test_get_irq() to preserve the current type for ioctl(PCITEST_GET_IRQTYPE). In the pci_endpoint_test_request_irq(), since this global variable is referenced when an error occurs, the unintended error message is displayed. For example, after running "pcitest -i 2", the following message shows "MSI 3" even if the current IRQ type becomes "MSI-X": pci-endpoint-test 0000:01:00.0: Failed to request IRQ 30 for MSI 3 SET IRQ TYPE TO MSI-X: NOT OKAY Fix this issue by using "test->irq_type" instead of global "irq_type". Cc: stable@vger.kernel.org Fixes: b2ba9225e031 ("misc: pci_endpoint_test: Avoid using module parameter to determine irqtype") Reviewed-by: Manivannan Sadhasivam Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/20250225110252.28866-4-hayashi.kunihiko@socionext.com [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński --- drivers/misc/pci_endpoint_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 9e56d200d2f0..acf3d8dab131 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -242,7 +242,7 @@ static int pci_endpoint_test_request_irq(struct pci_endpoint_test *test) return 0; fail: - switch (irq_type) { + switch (test->irq_type) { case IRQ_TYPE_INTX: dev_err(dev, "Failed to request IRQ %d for Legacy\n", pci_irq_vector(pdev, i)); From baaef0a274cfb75f9b50eab3ef93205e604f662c Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:50 +0900 Subject: [PATCH 09/18] misc: pci_endpoint_test: Fix 'irq_type' to convey the correct type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two variables that indicate the interrupt type to be used in the next test execution, "irq_type" as global and "test->irq_type". The global is referenced from pci_endpoint_test_get_irq() to preserve the current type for ioctl(PCITEST_GET_IRQTYPE). The type set in this function isn't reflected in the global "irq_type", so ioctl(PCITEST_GET_IRQTYPE) returns the previous type. As a result, the wrong type is displayed in old version of "pcitest" as follows: - Result of running "pcitest -i 0" SET IRQ TYPE TO LEGACY: OKAY - Result of running "pcitest -I" GET IRQ TYPE: MSI Whereas running the new version of "pcitest" in kselftest results in an error as follows: # RUN pci_ep_basic.LEGACY_IRQ_TEST ... # pci_endpoint_test.c:104:LEGACY_IRQ_TEST:Expected 0 (0) == ret (1) # pci_endpoint_test.c:104:LEGACY_IRQ_TEST:Can't get Legacy IRQ type Fix this issue by propagating the current type to the global "irq_type". Fixes: b2ba9225e031 ("misc: pci_endpoint_test: Avoid using module parameter to determine irqtype") Signed-off-by: Kunihiko Hayashi [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński Reviewed-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250225110252.28866-5-hayashi.kunihiko@socionext.com --- drivers/misc/pci_endpoint_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index acf3d8dab131..896392c428de 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -833,6 +833,7 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test, return ret; } + irq_type = test->irq_type; return 0; } From a402006d48a9c4f94156c01c1293a426c3af7b4b Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:51 +0900 Subject: [PATCH 10/18] misc: pci_endpoint_test: Remove global 'irq_type' and 'no_msi' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global variable "irq_type" preserves the current value of ioctl(GET_IRQTYPE). However, all tests that use interrupts first call ioctl(SET_IRQTYPE) to set "test->irq_type", then write the value of test->irq_type into the register pointed by test_reg_bar, and request the interrupt to the endpoint. The endpoint function driver, pci-epf-test, refers to the register, and determine which type of interrupt to raise. The global variable "irq_type" is never used in the actual test, so remove the variable and replace it with "test->irq_type". Also, for the same reason, the variable "no_msi" can be removed. Initially, "test->irq_type" has IRQ_TYPE_UNDEFINED, and the ioctl(GET_IRQTYPE) before calling ioctl(SET_IRQTYPE) will return an error. Suggested-by: Niklas Cassel Suggested-by: Manivannan Sadhasivam Signed-off-by: Kunihiko Hayashi [kwilczynski: commit log] Signed-off-by: Krzysztof Wilczyński Reviewed-by: Manivannan Sadhasivam Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20250225110252.28866-6-hayashi.kunihiko@socionext.com --- drivers/misc/pci_endpoint_test.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 896392c428de..326e8e467c42 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -96,14 +96,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, @@ -833,7 +825,6 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test, return ret; } - irq_type = test->irq_type; return 0; } @@ -882,7 +873,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); @@ -939,15 +930,12 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, test->pdev = pdev; test->irq_type = IRQ_TYPE_UNDEFINED; - if (no_msi) - irq_type = IRQ_TYPE_INTX; - 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); @@ -969,7 +957,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; From e1ec81ebfffbaf6b28be91ac179a5cc90d79436b Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Tue, 25 Feb 2025 20:02:52 +0900 Subject: [PATCH 11/18] misc: pci_endpoint_test: Do not use managed IRQ functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pci_endpoint_test_request_irq() and pci_endpoint_test_release_irq() are called repeatedly by the users through pci_endpoint_test_set_irq(). So using the managed version of IRQ functions within these functions has no effect. Suggested-by: Manivannan Sadhasivam Reviewed-by: Manivannan Sadhasivam Signed-off-by: Kunihiko Hayashi Acked-by: Arnd Bergmann Link: https://lore.kernel.org/r/20250225110252.28866-7-hayashi.kunihiko@socionext.com Signed-off-by: Krzysztof Wilczyński --- drivers/misc/pci_endpoint_test.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 326e8e467c42..7a14114488a0 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -208,10 +208,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; } @@ -224,9 +223,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; } From 2b48d3dcb74a22af05aeb707614584eb15ef16da Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 10 Mar 2025 12:10:18 +0100 Subject: [PATCH 12/18] PCI: endpoint: pcitest: Add IRQ_TYPE_* defines to UAPI header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These IRQ_TYPE_* defines are used by both drivers/misc/pci_endpoint_test.c and tools/testing/selftests/pci_endpoint/pci_endpoint_test.c. Considering that both the misc driver and the selftest already includes the pcitest.h UAPI header, it makes sense for these IRQ_TYPE_* defines to be located in the pcitest.h UAPI header. Signed-off-by: Niklas Cassel Signed-off-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20250310111016.859445-10-cassel@kernel.org --- include/uapi/linux/pcitest.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/uapi/linux/pcitest.h b/include/uapi/linux/pcitest.h index acd261f49866..304bf9be0f9a 100644 --- a/include/uapi/linux/pcitest.h +++ b/include/uapi/linux/pcitest.h @@ -23,6 +23,11 @@ #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_FLAGS_USE_DMA 0x00000001 struct pci_endpoint_test_xfer_param { From 64a7704ae16f5836ba74152553ae2a7338229a9d Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 10 Mar 2025 12:10:19 +0100 Subject: [PATCH 13/18] misc: pci_endpoint_test: Use IRQ_TYPE_* defines from UAPI header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the IRQ_TYPE_* defines from the UAPI header rather than duplicating these defines in the driver itself. No functional change. Signed-off-by: Niklas Cassel Signed-off-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20250310111016.859445-11-cassel@kernel.org --- drivers/misc/pci_endpoint_test.c | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 7a14114488a0..abcf1d91de37 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -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 @@ -158,7 +153,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, @@ -169,7 +164,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"); @@ -177,7 +172,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"); @@ -185,7 +180,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"); @@ -234,16 +229,16 @@ static int pci_endpoint_test_request_irq(struct pci_endpoint_test *test) fail: switch (test->irq_type) { - case IRQ_TYPE_INTX: + 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); @@ -409,7 +404,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); @@ -429,7 +424,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 : @@ -505,7 +501,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; } @@ -637,7 +634,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; } @@ -733,7 +731,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; } @@ -803,7 +802,8 @@ 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_MSIX) { dev_err(dev, "Invalid IRQ type option\n"); return -EINVAL; } @@ -927,7 +927,7 @@ 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; + test->irq_type = PCITEST_IRQ_TYPE_UNDEFINED; data = (struct pci_endpoint_test_data *)ent->driver_data; if (data) { @@ -1078,23 +1078,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, }; /* From 24a42582b00810970decb051ce3e25d2c661dd92 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 10 Mar 2025 12:10:20 +0100 Subject: [PATCH 14/18] selftests: pci_endpoint: Use IRQ_TYPE_* defines from UAPI header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to improve readability, use the IRQ_TYPE_* defines from the UAPI header rather than using raw values. No functional change. Signed-off-by: Niklas Cassel Signed-off-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20250310111016.859445-12-cassel@kernel.org --- .../selftests/pci_endpoint/pci_endpoint_test.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c index d05e107d0698..fdf4bc6aa9d2 100644 --- a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c +++ b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c @@ -99,11 +99,11 @@ 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(0, ret) TH_LOG("Can't get Legacy IRQ type"); + 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"); @@ -113,11 +113,11 @@ 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(1, ret) TH_LOG("Can't get MSI IRQ type"); + 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); @@ -129,11 +129,11 @@ 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(2, ret) TH_LOG("Can't get MSI-X IRQ type"); + 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); @@ -181,7 +181,7 @@ 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); + pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSI); ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type"); for (i = 0; i < ARRAY_SIZE(test_size); i++) { @@ -200,7 +200,7 @@ 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); + pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSI); ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type"); for (i = 0; i < ARRAY_SIZE(test_size); i++) { @@ -219,7 +219,7 @@ 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); + pci_ep_ioctl(PCITEST_SET_IRQTYPE, PCITEST_IRQ_TYPE_MSI); ASSERT_EQ(0, ret) TH_LOG("Can't set MSI IRQ type"); for (i = 0; i < ARRAY_SIZE(test_size); i++) { From 4b313c69a38e28b2f002198c3909fb553e9b0176 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 10 Mar 2025 12:10:21 +0100 Subject: [PATCH 15/18] PCI: endpoint: Add intx_capable to epc_features struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In struct pci_epc_features, an EPC driver can already specify if they support MSI (by setting msi_capable) and MSI-X (by setting msix_capable). Thus, for consistency, allow an EPC driver to specify if it supports INTx interrupts as well (by setting intx_capable). Since this struct is zero initialized, EPC drivers that want to claim INTx support will need to set intx_capable to true. Signed-off-by: Niklas Cassel [kwilczynski: add missing kernel-doc for "intx_capable"] Signed-off-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20250310111016.859445-13-cassel@kernel.org --- include/linux/pci-epc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index e818e3fdcded..9d14d78abd14 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -221,6 +221,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 */ @@ -228,6 +229,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; }; From e55c67837a8cd42d6936e567f2ac75337b0e57f6 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 10 Mar 2025 12:10:22 +0100 Subject: [PATCH 16/18] PCI: dw-rockchip: Endpoint mode cannot raise INTx interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neither RK3568 or RK3588 supports INTx interrupts. Since epc_features is zero initialized, this is strictly not needed. However, setting intx_capable explicitly to false makes it more clear that neither RK3568 or RK3588 supports INTx interrupts. No functional change. Signed-off-by: Niklas Cassel Signed-off-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20250310111016.859445-14-cassel@kernel.org --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 93698abff4d9..4aa25bcf9106 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -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_FIXED, .fixed_size = SZ_1M, }, .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, @@ -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_FIXED, .fixed_size = SZ_1M, }, .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_1M, }, From 7c3b54cf6464b4d6ba5440ae5bb44552f099a078 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 10 Mar 2025 12:10:23 +0100 Subject: [PATCH 17/18] PCI: endpoint: pci-epf-test: Expose supported IRQ types in CAPS register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose the supported IRQ types in the CAPS register. This way, the host side driver (drivers/misc/pci_endpoint_test.c) can know which IRQ types that the endpoint supports. The host side driver will make use of this information in a follow-up commit. Signed-off-by: Niklas Cassel Signed-off-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20250310111016.859445-15-cassel@kernel.org --- drivers/pci/endpoint/functions/pci-epf-test.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index b94e205ae10b..1b1e92c1460f 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -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; @@ -753,6 +756,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); } From 08818c6d7f276eb5895959f34c491a3911ae7820 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Mon, 10 Mar 2025 12:10:24 +0100 Subject: [PATCH 18/18] misc: pci_endpoint_test: Add support for PCITEST_IRQ_TYPE_AUTO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20250310111016.859445-16-cassel@kernel.org --- drivers/misc/pci_endpoint_test.c | 25 +++++++++++++++---- include/uapi/linux/pcitest.h | 1 + .../pci_endpoint/pci_endpoint_test.c | 12 ++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index abcf1d91de37..1b57850dea9f 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -66,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 @@ -113,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; }; @@ -803,11 +807,23 @@ static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test, int ret; if (req_irq_type < PCITEST_IRQ_TYPE_INTX || - req_irq_type > PCITEST_IRQ_TYPE_MSIX) { + 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; @@ -893,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; } diff --git a/include/uapi/linux/pcitest.h b/include/uapi/linux/pcitest.h index 304bf9be0f9a..d3aa8715a525 100644 --- a/include/uapi/linux/pcitest.h +++ b/include/uapi/linux/pcitest.h @@ -27,6 +27,7 @@ #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 diff --git a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c index fdf4bc6aa9d2..ac26481d29d9 100644 --- a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c +++ b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c @@ -181,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, PCITEST_IRQ_TYPE_MSI); - 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]; @@ -200,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, PCITEST_IRQ_TYPE_MSI); - 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]; @@ -219,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, PCITEST_IRQ_TYPE_MSI); - 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];