Hi,
This series carries forward the effort to add Kselftest for PCI Endpoint Subsystem started by Aman Gupta [1] a while ago. I reworked the initial version based on another patch that fixes the return values of IOCTLs in pci_endpoint_test driver and did many cleanups. Since the resulting work modified the initial version substantially, I took over the authorship.
This series also incorporates the review comment by Shuah Khan [2] to move the existing tests from 'tools/pci' to 'tools/testing/kselftest/pci_endpoint' before migrating to Kselftest framework. I made sure that the tests are executable in each commit and updated documentation accordingly.
NOTE: Patch 1 is strictly not related to this series, but necessary to execute Kselftests with Qualcomm Endpoint devices. So this can be merged separately.
- Mani
[1] https://lore.kernel.org/linux-pci/20221007053934.5188-1-aman1.gupta@samsung.... [2] https://lore.kernel.org/linux-pci/b2a5db97-dc59-33ab-71cd-f591e0b1b34d@linux...
Changes in v2:
* Added a patch that fixes return values of IOCTL in pci_endpoint_test driver * Moved the existing tests to new location before migrating * Added a fix for BARs on Qcom devices * Updated documentation and also added fixture variants for memcpy & DMA modes
Manivannan Sadhasivam (4): PCI: qcom-ep: Mark BAR0/BAR2 as 64bit BARs and BAR1/BAR3 as RESERVED misc: pci_endpoint_test: Fix the return value of IOCTL selftests: Move PCI Endpoint tests from tools/pci to Kselftests selftests: pci_endpoint: Migrate to Kselftest framework
Documentation/PCI/endpoint/pci-test-howto.rst | 144 +++------- MAINTAINERS | 2 +- drivers/misc/pci_endpoint_test.c | 236 ++++++++--------- drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 + tools/pci/Build | 1 - tools/pci/Makefile | 58 ---- tools/pci/pcitest.c | 250 ------------------ tools/pci/pcitest.sh | 72 ----- tools/testing/selftests/Makefile | 1 + .../testing/selftests/pci_endpoint/.gitignore | 2 + tools/testing/selftests/pci_endpoint/Makefile | 7 + tools/testing/selftests/pci_endpoint/config | 4 + .../pci_endpoint/pci_endpoint_test.c | 186 +++++++++++++ 13 files changed, 365 insertions(+), 602 deletions(-) delete mode 100644 tools/pci/Build delete mode 100644 tools/pci/Makefile delete mode 100644 tools/pci/pcitest.c delete mode 100644 tools/pci/pcitest.sh create mode 100644 tools/testing/selftests/pci_endpoint/.gitignore create mode 100644 tools/testing/selftests/pci_endpoint/Makefile create mode 100644 tools/testing/selftests/pci_endpoint/config create mode 100644 tools/testing/selftests/pci_endpoint/pci_endpoint_test.c
On all Qcom endpoint SoCs, BAR0/BAR2 are 64bit BARs by default and software cannot change the type. So mark the those BARs as 64bit BARs and also mark the successive BAR1/BAR3 as RESERVED BARs so that the EPF drivers cannot use them.
Cc: stable+noautosel@kernel.org # depends on patch introducing only_64bit flag Fixes: f55fee56a631 ("PCI: qcom-ep: Add Qualcomm PCIe Endpoint controller driver") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org --- drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index e588fcc54589..f925c4ad4294 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -823,6 +823,10 @@ static const struct pci_epc_features qcom_pcie_epc_features = { .msi_capable = true, .msix_capable = false, .align = SZ_4K, + .bar[BAR_0] = { .only_64bit = true, }, + .bar[BAR_1] = { .type = BAR_RESERVED, }, + .bar[BAR_2] = { .only_64bit = true, }, + .bar[BAR_3] = { .type = BAR_RESERVED, }, };
static const struct pci_epc_features *
On Fri, Nov 29, 2024 at 02:54:12PM +0530, Manivannan Sadhasivam wrote:
On all Qcom endpoint SoCs, BAR0/BAR2 are 64bit BARs by default and software cannot change the type. So mark the those BARs as 64bit BARs and also mark the successive BAR1/BAR3 as RESERVED BARs so that the EPF drivers cannot use them.
Cc: stable+noautosel@kernel.org # depends on patch introducing only_64bit flag Fixes: f55fee56a631 ("PCI: qcom-ep: Add Qualcomm PCIe Endpoint controller driver") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 ++++ 1 file changed, 4 insertions(+)
Reviewed-by: Dmitry Baryshkov dmitry.baryshkov@linaro.org
On Fri, Nov 29, 2024 at 02:54:12PM +0530, Manivannan Sadhasivam wrote:
On all Qcom endpoint SoCs, BAR0/BAR2 are 64bit BARs by default and software cannot change the type. So mark the those BARs as 64bit BARs and also mark the successive BAR1/BAR3 as RESERVED BARs so that the EPF drivers cannot use them.
"Default" implies an initial setting that can be changed, but you say "by default" and also "software cannot change the type." Can they be anything *other* than 64-bit BARs?
If they're hardwired to be 64-bit BARs, I would just say that.
Cc: stable+noautosel@kernel.org # depends on patch introducing only_64bit flag
If stable maintainers need to act on this, do they need to search for the patch introducing only_64bit flag? That seems onerous; is there a SHA1 that would make it easier?
Fixes: f55fee56a631 ("PCI: qcom-ep: Add Qualcomm PCIe Endpoint controller driver") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index e588fcc54589..f925c4ad4294 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -823,6 +823,10 @@ static const struct pci_epc_features qcom_pcie_epc_features = { .msi_capable = true, .msix_capable = false, .align = SZ_4K,
- .bar[BAR_0] = { .only_64bit = true, },
- .bar[BAR_1] = { .type = BAR_RESERVED, },
- .bar[BAR_2] = { .only_64bit = true, },
- .bar[BAR_3] = { .type = BAR_RESERVED, },
}; static const struct pci_epc_features * -- 2.25.1
On Fri, Nov 29, 2024 at 01:55:37PM -0600, Bjorn Helgaas wrote:
On Fri, Nov 29, 2024 at 02:54:12PM +0530, Manivannan Sadhasivam wrote:
On all Qcom endpoint SoCs, BAR0/BAR2 are 64bit BARs by default and software cannot change the type. So mark the those BARs as 64bit BARs and also mark the successive BAR1/BAR3 as RESERVED BARs so that the EPF drivers cannot use them.
"Default" implies an initial setting that can be changed, but you say "by default" and also "software cannot change the type." Can they be anything *other* than 64-bit BARs?
If they're hardwired to be 64-bit BARs, I would just say that.
Cc: stable+noautosel@kernel.org # depends on patch introducing only_64bit flag
If stable maintainers need to act on this, do they need to search for the patch introducing only_64bit flag? That seems onerous; is there a SHA1 that would make it easier?
Fixes: f55fee56a631 ("PCI: qcom-ep: Add Qualcomm PCIe Endpoint controller driver")
Yes, having a sha1 that has that "feature addition" would be great, surely that isn't 6.13-rc1, is it?
thanks,
greg k-h
On Fri, Nov 29, 2024 at 01:55:37PM -0600, Bjorn Helgaas wrote:
On Fri, Nov 29, 2024 at 02:54:12PM +0530, Manivannan Sadhasivam wrote:
On all Qcom endpoint SoCs, BAR0/BAR2 are 64bit BARs by default and software cannot change the type. So mark the those BARs as 64bit BARs and also mark the successive BAR1/BAR3 as RESERVED BARs so that the EPF drivers cannot use them.
"Default" implies an initial setting that can be changed, but you say "by default" and also "software cannot change the type." Can they be anything *other* than 64-bit BARs?
If they're hardwired to be 64-bit BARs, I would just say that.
Cc: stable+noautosel@kernel.org # depends on patch introducing only_64bit flag
If stable maintainers need to act on this, do they need to search for the patch introducing only_64bit flag? That seems onerous; is there a SHA1 that would make it easier?
But that's not the point of having noautosel tag, AFAIK.
Documentation/process/stable-kernel-rules.rst clearly says that this tag is to be used when we do not want the stable team to backport the commit due to a missing dependency.
If we really want stable team to backport the change with dependencies, then the dependencies should be mentioned using the SHAs:
From Documentation/process/stable-kernel-rules.rst:
``` * Specify any additional patch prerequisites for cherry picking::
Cc: stable@vger.kernel.org # 3.3.x: a1f84a3: sched: Check for idle Cc: stable@vger.kernel.org # 3.3.x: 1b9508f: sched: Rate-limit newidle Cc: stable@vger.kernel.org # 3.3.x: fd21073: sched: Fix affinity logic Cc: stable@vger.kernel.org # 3.3.x Signed-off-by: Ingo Molnar mingo@elte.hu
The tag sequence has the meaning of::
git cherry-pick a1f84a3 git cherry-pick 1b9508f git cherry-pick fd21073 git cherry-pick <this commit> ```
Here I did not intend to backport this change with commit adding only_64bit flag because, I'm not sure if that dependency alone would be sufficient. If someone really cares about backporting this change, then they should figure out the dependencies, test the functionality and then ask the stable team.
- Mani
Fixes: f55fee56a631 ("PCI: qcom-ep: Add Qualcomm PCIe Endpoint controller driver") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index e588fcc54589..f925c4ad4294 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -823,6 +823,10 @@ static const struct pci_epc_features qcom_pcie_epc_features = { .msi_capable = true, .msix_capable = false, .align = SZ_4K,
- .bar[BAR_0] = { .only_64bit = true, },
- .bar[BAR_1] = { .type = BAR_RESERVED, },
- .bar[BAR_2] = { .only_64bit = true, },
- .bar[BAR_3] = { .type = BAR_RESERVED, },
}; static const struct pci_epc_features * -- 2.25.1
On Mon, Dec 02, 2024 at 06:28:45PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 01:55:37PM -0600, Bjorn Helgaas wrote:
On Fri, Nov 29, 2024 at 02:54:12PM +0530, Manivannan Sadhasivam wrote:
On all Qcom endpoint SoCs, BAR0/BAR2 are 64bit BARs by default and software cannot change the type. So mark the those BARs as 64bit BARs and also mark the successive BAR1/BAR3 as RESERVED BARs so that the EPF drivers cannot use them.
...
Cc: stable+noautosel@kernel.org # depends on patch introducing only_64bit flag
If stable maintainers need to act on this, do they need to search for the patch introducing only_64bit flag? That seems onerous; is there a SHA1 that would make it easier?
But that's not the point of having noautosel tag, AFAIK.
Documentation/process/stable-kernel-rules.rst clearly says that this tag is to be used when we do not want the stable team to backport the commit due to a missing dependency. ...
Here I did not intend to backport this change with commit adding only_64bit flag because, I'm not sure if that dependency alone would be sufficient. If someone really cares about backporting this change, then they should figure out the dependencies, test the functionality and then ask the stable team.
Oh, sorry, I was assuming "stable+noautosel@kernel.org" was a hint for stable maintainers to pick this up, not a hint to ignore it. Eventually this meaning will sink in.
Bjorn
IOCTLs are supposed to return 0 for success and negative error codes for failure. Currently, this driver is returning 0 for failure and 1 for success, that's not correct. Hence, fix it!
Reported-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Closes: https://lore.kernel.org/all/YvzNg5ROnxEApDgS@kroah.com Fixes: 2c156ac71c6b ("misc: Add host side PCI driver for PCI test function device") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org --- drivers/misc/pci_endpoint_test.c | 236 +++++++++++++++---------------- tools/pci/pcitest.c | 47 +++--- 2 files changed, 140 insertions(+), 143 deletions(-)
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 3aaaf47fa4ee..752fa5fe52d7 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -166,43 +166,47 @@ static void pci_endpoint_test_free_irq_vectors(struct pci_endpoint_test *test) test->irq_type = IRQ_TYPE_UNDEFINED; }
-static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test, +static int pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test, int type) { - int irq = -1; + int irq; struct pci_dev *pdev = test->pdev; struct device *dev = &pdev->dev; - bool res = true;
switch (type) { case IRQ_TYPE_INTX: irq = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_INTX); - if (irq < 0) + if (irq < 0) { dev_err(dev, "Failed to get Legacy interrupt\n"); + return -ENOSPC; + } + break; case IRQ_TYPE_MSI: irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); - if (irq < 0) + if (irq < 0) { dev_err(dev, "Failed to get MSI interrupts\n"); + return -ENOSPC; + } + break; case IRQ_TYPE_MSIX: irq = pci_alloc_irq_vectors(pdev, 1, 2048, PCI_IRQ_MSIX); - if (irq < 0) + if (irq < 0) { dev_err(dev, "Failed to get MSI-X interrupts\n"); + return -ENOSPC; + } + break; default: dev_err(dev, "Invalid IRQ type selected\n"); - } - - if (irq < 0) { - irq = 0; - res = false; + return -EINVAL; }
test->irq_type = type; test->num_irqs = irq;
- return res; + return 0; }
static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test) @@ -217,22 +221,22 @@ static void pci_endpoint_test_release_irq(struct pci_endpoint_test *test) test->num_irqs = 0; }
-static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test) +static int pci_endpoint_test_request_irq(struct pci_endpoint_test *test) { int i; - int err; + int ret; struct pci_dev *pdev = test->pdev; struct device *dev = &pdev->dev;
for (i = 0; i < test->num_irqs; i++) { - err = devm_request_irq(dev, pci_irq_vector(pdev, i), + ret = devm_request_irq(dev, pci_irq_vector(pdev, i), pci_endpoint_test_irqhandler, IRQF_SHARED, test->name, test); - if (err) + if (ret) goto fail; }
- return true; + return 0;
fail: switch (irq_type) { @@ -252,7 +256,7 @@ static bool pci_endpoint_test_request_irq(struct pci_endpoint_test *test) break; }
- return false; + return ret; }
static const u32 bar_test_pattern[] = { @@ -277,7 +281,7 @@ static int pci_endpoint_test_bar_memcmp(struct pci_endpoint_test *test, return memcmp(write_buf, read_buf, size); }
-static bool pci_endpoint_test_bar(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, remain; @@ -286,7 +290,7 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, struct pci_dev *pdev = test->pdev;
if (!test->bar[barno]) - return false; + return -ENOMEM;
bar_size = pci_resource_len(pdev, barno);
@@ -301,28 +305,28 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
write_buf = kmalloc(buf_size, GFP_KERNEL); if (!write_buf) - return false; + return -ENOMEM;
read_buf = kmalloc(buf_size, GFP_KERNEL); if (!read_buf) - return false; + 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)) - return false; + return -EIO;
remain = bar_size % buf_size; if (remain) if (pci_endpoint_test_bar_memcmp(test, barno, buf_size * iters, write_buf, read_buf, remain)) - return false; + return -EIO;
- return true; + return 0; }
-static bool pci_endpoint_test_intx_irq(struct pci_endpoint_test *test) +static int pci_endpoint_test_intx_irq(struct pci_endpoint_test *test) { u32 val;
@@ -334,12 +338,12 @@ static bool pci_endpoint_test_intx_irq(struct pci_endpoint_test *test) val = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); if (!val) - return false; + return -ETIMEDOUT;
- return true; + return 0; }
-static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, +static int pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, u16 msi_num, bool msix) { u32 val; @@ -354,9 +358,12 @@ static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test, val = wait_for_completion_timeout(&test->irq_raised, msecs_to_jiffies(1000)); if (!val) - return false; + return -ETIMEDOUT;
- return pci_irq_vector(pdev, msi_num - 1) == test->last_irq; + if (!(pci_irq_vector(pdev, msi_num - 1) == test->last_irq)) + return -EIO; + + return 0; }
static int pci_endpoint_test_validate_xfer_params(struct device *dev, @@ -375,11 +382,10 @@ static int pci_endpoint_test_validate_xfer_params(struct device *dev, return 0; }
-static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, +static int pci_endpoint_test_copy(struct pci_endpoint_test *test, unsigned long arg) { struct pci_endpoint_test_xfer_param param; - bool ret = false; void *src_addr; void *dst_addr; u32 flags = 0; @@ -398,17 +404,17 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, int irq_type = test->irq_type; u32 src_crc32; u32 dst_crc32; - int err; + int ret;
- err = copy_from_user(¶m, (void __user *)arg, sizeof(param)); - if (err) { + ret = copy_from_user(¶m, (void __user *)arg, sizeof(param)); + if (ret) { dev_err(dev, "Failed to get transfer param\n"); - return false; + return -EFAULT; }
- err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); - if (err) - return false; + ret = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); + if (ret) + return ret;
size = param.size;
@@ -418,22 +424,21 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test,
if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX) { dev_err(dev, "Invalid IRQ type option\n"); - goto err; + return -EINVAL; }
orig_src_addr = kzalloc(size + alignment, GFP_KERNEL); if (!orig_src_addr) { dev_err(dev, "Failed to allocate source buffer\n"); - ret = false; - goto err; + return -ENOMEM; }
get_random_bytes(orig_src_addr, size + alignment); orig_src_phys_addr = dma_map_single(dev, orig_src_addr, size + alignment, DMA_TO_DEVICE); - if (dma_mapping_error(dev, orig_src_phys_addr)) { + ret = dma_mapping_error(dev, orig_src_phys_addr); + if (ret) { dev_err(dev, "failed to map source buffer address\n"); - ret = false; goto err_src_phys_addr; }
@@ -457,15 +462,15 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, orig_dst_addr = kzalloc(size + alignment, GFP_KERNEL); if (!orig_dst_addr) { dev_err(dev, "Failed to allocate destination address\n"); - ret = false; + ret = -ENOMEM; goto err_dst_addr; }
orig_dst_phys_addr = dma_map_single(dev, orig_dst_addr, size + alignment, DMA_FROM_DEVICE); - if (dma_mapping_error(dev, orig_dst_phys_addr)) { + ret = dma_mapping_error(dev, orig_dst_phys_addr); + if (ret) { dev_err(dev, "failed to map destination buffer address\n"); - ret = false; goto err_dst_phys_addr; }
@@ -498,8 +503,8 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, DMA_FROM_DEVICE);
dst_crc32 = crc32_le(~0, dst_addr, size); - if (dst_crc32 == src_crc32) - ret = true; + if (dst_crc32 != src_crc32) + ret = -EIO;
err_dst_phys_addr: kfree(orig_dst_addr); @@ -510,16 +515,13 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test,
err_src_phys_addr: kfree(orig_src_addr); - -err: return ret; }
-static bool pci_endpoint_test_write(struct pci_endpoint_test *test, +static int pci_endpoint_test_write(struct pci_endpoint_test *test, unsigned long arg) { struct pci_endpoint_test_xfer_param param; - bool ret = false; u32 flags = 0; bool use_dma; u32 reg; @@ -534,17 +536,17 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, int irq_type = test->irq_type; size_t size; u32 crc32; - int err; + int ret;
- err = copy_from_user(¶m, (void __user *)arg, sizeof(param)); - if (err != 0) { + ret = copy_from_user(¶m, (void __user *)arg, sizeof(param)); + if (ret) { dev_err(dev, "Failed to get transfer param\n"); - return false; + return -EFAULT; }
- err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); - if (err) - return false; + ret = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); + if (ret) + return ret;
size = param.size;
@@ -554,23 +556,22 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test,
if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX) { dev_err(dev, "Invalid IRQ type option\n"); - goto err; + return -EINVAL; }
orig_addr = kzalloc(size + alignment, GFP_KERNEL); if (!orig_addr) { dev_err(dev, "Failed to allocate address\n"); - ret = false; - goto err; + return -ENOMEM; }
get_random_bytes(orig_addr, size + alignment);
orig_phys_addr = dma_map_single(dev, orig_addr, size + alignment, DMA_TO_DEVICE); - if (dma_mapping_error(dev, orig_phys_addr)) { + ret = dma_mapping_error(dev, orig_phys_addr); + if (ret) { dev_err(dev, "failed to map source buffer address\n"); - ret = false; goto err_phys_addr; }
@@ -603,24 +604,21 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, wait_for_completion(&test->irq_raised);
reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS); - if (reg & STATUS_READ_SUCCESS) - ret = true; + if (!(reg & STATUS_READ_SUCCESS)) + ret = -EIO;
dma_unmap_single(dev, orig_phys_addr, size + alignment, DMA_TO_DEVICE);
err_phys_addr: kfree(orig_addr); - -err: return ret; }
-static bool pci_endpoint_test_read(struct pci_endpoint_test *test, +static int pci_endpoint_test_read(struct pci_endpoint_test *test, unsigned long arg) { struct pci_endpoint_test_xfer_param param; - bool ret = false; u32 flags = 0; bool use_dma; size_t size; @@ -634,17 +632,17 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t alignment = test->alignment; int irq_type = test->irq_type; u32 crc32; - int err; + int ret;
- err = copy_from_user(¶m, (void __user *)arg, sizeof(param)); - if (err) { + ret = copy_from_user(¶m, (void __user *)arg, sizeof(param)); + if (ret) { dev_err(dev, "Failed to get transfer param\n"); - return false; + return -EFAULT; }
- err = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); - if (err) - return false; + ret = pci_endpoint_test_validate_xfer_params(dev, ¶m, alignment); + if (ret) + return ret;
size = param.size;
@@ -654,21 +652,20 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test,
if (irq_type < IRQ_TYPE_INTX || irq_type > IRQ_TYPE_MSIX) { dev_err(dev, "Invalid IRQ type option\n"); - goto err; + return -EINVAL; }
orig_addr = kzalloc(size + alignment, GFP_KERNEL); if (!orig_addr) { dev_err(dev, "Failed to allocate destination address\n"); - ret = false; - goto err; + return -ENOMEM; }
orig_phys_addr = dma_map_single(dev, orig_addr, size + alignment, DMA_FROM_DEVICE); - if (dma_mapping_error(dev, orig_phys_addr)) { + ret = dma_mapping_error(dev, orig_phys_addr); + if (ret) { dev_err(dev, "failed to map source buffer address\n"); - ret = false; goto err_phys_addr; }
@@ -700,50 +697,51 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, DMA_FROM_DEVICE);
crc32 = crc32_le(~0, addr, size); - if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) - ret = true; + if (crc32 != pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM)) + ret = -EIO;
err_phys_addr: kfree(orig_addr); -err: return ret; }
-static bool pci_endpoint_test_clear_irq(struct pci_endpoint_test *test) +static int pci_endpoint_test_clear_irq(struct pci_endpoint_test *test) { pci_endpoint_test_release_irq(test); pci_endpoint_test_free_irq_vectors(test); - return true; + + return 0; }
-static bool pci_endpoint_test_set_irq(struct pci_endpoint_test *test, +static int pci_endpoint_test_set_irq(struct pci_endpoint_test *test, int req_irq_type) { struct pci_dev *pdev = test->pdev; struct device *dev = &pdev->dev; + int ret;
if (req_irq_type < IRQ_TYPE_INTX || req_irq_type > IRQ_TYPE_MSIX) { dev_err(dev, "Invalid IRQ type option\n"); - return false; + return -EINVAL; }
if (test->irq_type == req_irq_type) - return true; + return 0;
pci_endpoint_test_release_irq(test); pci_endpoint_test_free_irq_vectors(test);
- if (!pci_endpoint_test_alloc_irq_vectors(test, req_irq_type)) - goto err; - - if (!pci_endpoint_test_request_irq(test)) - goto err; + ret = pci_endpoint_test_alloc_irq_vectors(test, req_irq_type); + if (ret) + return ret;
- return true; + ret = pci_endpoint_test_request_irq(test); + if (ret) { + pci_endpoint_test_free_irq_vectors(test); + return ret; + }
-err: - pci_endpoint_test_free_irq_vectors(test); - return false; + return 0; }
static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd, @@ -808,7 +806,7 @@ static const struct file_operations pci_endpoint_test_fops = { static int pci_endpoint_test_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - int err; + int ret; int id; char name[24]; enum pci_barno bar; @@ -847,24 +845,23 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48));
- err = pci_enable_device(pdev); - if (err) { + ret = pci_enable_device(pdev); + if (ret) { dev_err(dev, "Cannot enable PCI device\n"); - return err; + return ret; }
- err = pci_request_regions(pdev, DRV_MODULE_NAME); - if (err) { + ret = pci_request_regions(pdev, DRV_MODULE_NAME); + if (ret) { dev_err(dev, "Cannot obtain PCI resources\n"); goto err_disable_pdev; }
pci_set_master(pdev);
- if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) { - err = -EINVAL; + ret = pci_endpoint_test_alloc_irq_vectors(test, irq_type); + if (ret) goto err_disable_irq; - }
for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { @@ -879,7 +876,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
test->base = test->bar[test_reg_bar]; if (!test->base) { - err = -ENOMEM; + ret = -ENOMEM; dev_err(dev, "Cannot perform PCI test without BAR%d\n", test_reg_bar); goto err_iounmap; @@ -889,7 +886,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
id = ida_alloc(&pci_endpoint_test_ida, GFP_KERNEL); if (id < 0) { - err = id; + ret = id; dev_err(dev, "Unable to get id\n"); goto err_iounmap; } @@ -897,27 +894,26 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); test->name = kstrdup(name, GFP_KERNEL); if (!test->name) { - err = -ENOMEM; + ret = -ENOMEM; goto err_ida_remove; }
- if (!pci_endpoint_test_request_irq(test)) { - err = -EINVAL; + ret = pci_endpoint_test_request_irq(test); + if (ret) goto err_kfree_test_name; - }
misc_device = &test->miscdev; misc_device->minor = MISC_DYNAMIC_MINOR; misc_device->name = kstrdup(name, GFP_KERNEL); if (!misc_device->name) { - err = -ENOMEM; + ret = -ENOMEM; goto err_release_irq; } misc_device->parent = &pdev->dev; misc_device->fops = &pci_endpoint_test_fops;
- err = misc_register(misc_device); - if (err) { + ret = misc_register(misc_device); + if (ret) { dev_err(dev, "Failed to register device\n"); goto err_kfree_name; } @@ -949,7 +945,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, err_disable_pdev: pci_disable_device(pdev);
- return err; + return ret; }
static void pci_endpoint_test_remove(struct pci_dev *pdev) diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c index 470258009ddc..545e04ad63a2 100644 --- a/tools/pci/pcitest.c +++ b/tools/pci/pcitest.c @@ -16,7 +16,6 @@
#include <linux/pcitest.h>
-static char *result[] = { "NOT OKAY", "OKAY" }; static char *irq[] = { "LEGACY", "MSI", "MSI-X" };
struct pci_test { @@ -52,63 +51,65 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_BAR, test->barnum); fprintf(stdout, "BAR%d:\t\t", test->barnum); if (ret < 0) - fprintf(stdout, "TEST FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->set_irqtype) { ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype); fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]); if (ret < 0) - fprintf(stdout, "FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->get_irqtype) { ret = ioctl(fd, PCITEST_GET_IRQTYPE); fprintf(stdout, "GET IRQ TYPE:\t\t"); - if (ret < 0) - fprintf(stdout, "FAILED\n"); - else + if (ret < 0) { + fprintf(stdout, "NOT OKAY\n"); + } else { fprintf(stdout, "%s\n", irq[ret]); + ret = 0; + } }
if (test->clear_irq) { ret = ioctl(fd, PCITEST_CLEAR_IRQ); fprintf(stdout, "CLEAR IRQ:\t\t"); if (ret < 0) - fprintf(stdout, "FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->legacyirq) { ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0); fprintf(stdout, "LEGACY IRQ:\t"); if (ret < 0) - fprintf(stdout, "TEST FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->msinum > 0 && test->msinum <= 32) { ret = ioctl(fd, PCITEST_MSI, test->msinum); fprintf(stdout, "MSI%d:\t\t", test->msinum); if (ret < 0) - fprintf(stdout, "TEST FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->msixnum > 0 && test->msixnum <= 2048) { ret = ioctl(fd, PCITEST_MSIX, test->msixnum); fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); if (ret < 0) - fprintf(stdout, "TEST FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->write) { @@ -118,9 +119,9 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_WRITE, ¶m); fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size); if (ret < 0) - fprintf(stdout, "TEST FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->read) { @@ -130,9 +131,9 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_READ, ¶m); fprintf(stdout, "READ (%7ld bytes):\t\t", test->size); if (ret < 0) - fprintf(stdout, "TEST FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
if (test->copy) { @@ -142,14 +143,14 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_COPY, ¶m); fprintf(stdout, "COPY (%7ld bytes):\t\t", test->size); if (ret < 0) - fprintf(stdout, "TEST FAILED\n"); + fprintf(stdout, "NOT OKAY\n"); else - fprintf(stdout, "%s\n", result[ret]); + fprintf(stdout, "OKAY\n"); }
fflush(stdout); close(fd); - return (ret < 0) ? ret : 1 - ret; /* return 0 if test succeeded */ + return ret; }
int main(int argc, char **argv)
On 11/29/24 18:24, Manivannan Sadhasivam wrote:
IOCTLs are supposed to return 0 for success and negative error codes for failure. Currently, this driver is returning 0 for failure and 1 for success, that's not correct. Hence, fix it!
Reported-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Closes: https://lore.kernel.org/all/YvzNg5ROnxEApDgS@kroah.com Fixes: 2c156ac71c6b ("misc: Add host side PCI driver for PCI test function device") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
Looks OK to me.
Reviewed-by: Damien Le Moal dlemoal@kernel.org
One nit below.
[...]
static void pci_endpoint_test_remove(struct pci_dev *pdev) diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c index 470258009ddc..545e04ad63a2 100644 --- a/tools/pci/pcitest.c +++ b/tools/pci/pcitest.c @@ -16,7 +16,6 @@ #include <linux/pcitest.h> -static char *result[] = { "NOT OKAY", "OKAY" }; static char *irq[] = { "LEGACY", "MSI", "MSI-X" }; struct pci_test { @@ -52,63 +51,65 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_BAR, test->barnum); fprintf(stdout, "BAR%d:\t\t", test->barnum); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
fprintf(stdout, "OKAY\n");
Maybe replace all this "if (ret < 0) ... else ..." and all the ones below with something a call to:
static void test_result(int ret) { fprintf(stdout, "%sOKAY\n", ret < 0 ? "NOT " : ""); }
or simply with the call:
fprintf(stdout, "%sOKAY\n", ret < 0 ? "NOT " : "");
to avoid all these repetition.
} if (test->set_irqtype) { ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype); fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]); if (ret < 0)
fprintf(stdout, "FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
if (test->get_irqtype) { ret = ioctl(fd, PCITEST_GET_IRQTYPE); fprintf(stdout, "GET IRQ TYPE:\t\t");
if (ret < 0)
fprintf(stdout, "FAILED\n");
else
if (ret < 0) {
fprintf(stdout, "NOT OKAY\n");
} else { fprintf(stdout, "%s\n", irq[ret]);
ret = 0;
}}
if (test->clear_irq) { ret = ioctl(fd, PCITEST_CLEAR_IRQ); fprintf(stdout, "CLEAR IRQ:\t\t"); if (ret < 0)
fprintf(stdout, "FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
if (test->legacyirq) { ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0); fprintf(stdout, "LEGACY IRQ:\t"); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
if (test->msinum > 0 && test->msinum <= 32) { ret = ioctl(fd, PCITEST_MSI, test->msinum); fprintf(stdout, "MSI%d:\t\t", test->msinum); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
if (test->msixnum > 0 && test->msixnum <= 2048) { ret = ioctl(fd, PCITEST_MSIX, test->msixnum); fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
if (test->write) { @@ -118,9 +119,9 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_WRITE, ¶m); fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
if (test->read) { @@ -130,9 +131,9 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_READ, ¶m); fprintf(stdout, "READ (%7ld bytes):\t\t", test->size); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
if (test->copy) { @@ -142,14 +143,14 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_COPY, ¶m); fprintf(stdout, "COPY (%7ld bytes):\t\t", test->size); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
}fprintf(stdout, "OKAY\n");
fflush(stdout); close(fd);
- return (ret < 0) ? ret : 1 - ret; /* return 0 if test succeeded */
- return ret;
} int main(int argc, char **argv)
On Fri, Nov 29, 2024 at 07:51:30PM +0900, Damien Le Moal wrote:
On 11/29/24 18:24, Manivannan Sadhasivam wrote:
IOCTLs are supposed to return 0 for success and negative error codes for failure. Currently, this driver is returning 0 for failure and 1 for success, that's not correct. Hence, fix it!
Reported-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Closes: https://lore.kernel.org/all/YvzNg5ROnxEApDgS@kroah.com Fixes: 2c156ac71c6b ("misc: Add host side PCI driver for PCI test function device") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
Looks OK to me.
Reviewed-by: Damien Le Moal dlemoal@kernel.org
One nit below.
[...]
static void pci_endpoint_test_remove(struct pci_dev *pdev) diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c index 470258009ddc..545e04ad63a2 100644 --- a/tools/pci/pcitest.c +++ b/tools/pci/pcitest.c @@ -16,7 +16,6 @@ #include <linux/pcitest.h> -static char *result[] = { "NOT OKAY", "OKAY" }; static char *irq[] = { "LEGACY", "MSI", "MSI-X" }; struct pci_test { @@ -52,63 +51,65 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_BAR, test->barnum); fprintf(stdout, "BAR%d:\t\t", test->barnum); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
fprintf(stdout, "OKAY\n");
Maybe replace all this "if (ret < 0) ... else ..." and all the ones below with something a call to:
static void test_result(int ret) { fprintf(stdout, "%sOKAY\n", ret < 0 ? "NOT " : ""); }
or simply with the call:
fprintf(stdout, "%sOKAY\n", ret < 0 ? "NOT " : "");
to avoid all these repetition.
Sounds good to me. Will incorporate in next version, thanks!
- Mani
On Fri, Nov 29, 2024 at 10:00:30PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 07:51:30PM +0900, Damien Le Moal wrote:
On 11/29/24 18:24, Manivannan Sadhasivam wrote:
IOCTLs are supposed to return 0 for success and negative error codes for failure. Currently, this driver is returning 0 for failure and 1 for success, that's not correct. Hence, fix it!
Reported-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Closes: https://lore.kernel.org/all/YvzNg5ROnxEApDgS@kroah.com Fixes: 2c156ac71c6b ("misc: Add host side PCI driver for PCI test function device") Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org
Looks OK to me.
Reviewed-by: Damien Le Moal dlemoal@kernel.org
One nit below.
[...]
static void pci_endpoint_test_remove(struct pci_dev *pdev) diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c index 470258009ddc..545e04ad63a2 100644 --- a/tools/pci/pcitest.c +++ b/tools/pci/pcitest.c @@ -16,7 +16,6 @@ #include <linux/pcitest.h> -static char *result[] = { "NOT OKAY", "OKAY" }; static char *irq[] = { "LEGACY", "MSI", "MSI-X" }; struct pci_test { @@ -52,63 +51,65 @@ static int run_test(struct pci_test *test) ret = ioctl(fd, PCITEST_BAR, test->barnum); fprintf(stdout, "BAR%d:\t\t", test->barnum); if (ret < 0)
fprintf(stdout, "TEST FAILED\n");
elsefprintf(stdout, "NOT OKAY\n");
fprintf(stdout, "%s\n", result[ret]);
fprintf(stdout, "OKAY\n");
Maybe replace all this "if (ret < 0) ... else ..." and all the ones below with something a call to:
static void test_result(int ret) { fprintf(stdout, "%sOKAY\n", ret < 0 ? "NOT " : ""); }
or simply with the call:
fprintf(stdout, "%sOKAY\n", ret < 0 ? "NOT " : "");
to avoid all these repetition.
Sounds good to me. Will incorporate in next version, thanks!
Maybe not. This test is converted to Kselftest in successive patches, so no need to simplify it.
- Mani
This just moves the existing tests under tools/pci to tools/testing/selftests/pci_endpoint and adjusts the paths in Makefile accordingly. Migration to Kselftest framework will be done in subsequent commits.
Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org --- Documentation/PCI/endpoint/pci-test-howto.rst | 9 +++++---- MAINTAINERS | 2 +- tools/testing/selftests/pci_endpoint/.gitignore | 3 +++ tools/{pci => testing/selftests/pci_endpoint}/Build | 0 tools/{pci => testing/selftests/pci_endpoint}/Makefile | 10 +++++----- .../{pci => testing/selftests/pci_endpoint}/pcitest.c | 0 .../{pci => testing/selftests/pci_endpoint}/pcitest.sh | 0 7 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 tools/testing/selftests/pci_endpoint/.gitignore rename tools/{pci => testing/selftests/pci_endpoint}/Build (100%) rename tools/{pci => testing/selftests/pci_endpoint}/Makefile (83%) rename tools/{pci => testing/selftests/pci_endpoint}/pcitest.c (100%) rename tools/{pci => testing/selftests/pci_endpoint}/pcitest.sh (100%)
diff --git a/Documentation/PCI/endpoint/pci-test-howto.rst b/Documentation/PCI/endpoint/pci-test-howto.rst index 909f770a07d6..c4ae7af50ede 100644 --- a/Documentation/PCI/endpoint/pci-test-howto.rst +++ b/Documentation/PCI/endpoint/pci-test-howto.rst @@ -123,16 +123,17 @@ above:: Using Endpoint Test function Device -----------------------------------
-pcitest.sh added in tools/pci/ can be used to run all the default PCI endpoint -tests. To compile this tool the following commands should be used:: +pcitest.sh added in tools/testing/selftests/pci_endpoint can be used to run all +the default PCI endpoint tests. To compile this tool the following commands +should be used::
# cd <kernel-dir> - # make -C tools/pci + # make -C tools/testing/selftests/pci_endpoint
or if you desire to compile and install in your system::
# cd <kernel-dir> - # make -C tools/pci install + # make -C tools/testing/selftests/pci_endpoint install
The tool and script will be located in <rootfs>/usr/bin/
diff --git a/MAINTAINERS b/MAINTAINERS index 21fdaa19229a..f116f78a2ec5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17794,7 +17794,7 @@ F: Documentation/PCI/endpoint/* F: Documentation/misc-devices/pci-endpoint-test.rst F: drivers/misc/pci_endpoint_test.c F: drivers/pci/endpoint/ -F: tools/pci/ +F: tools/testing/selftests/pci_endpoint/
PCI ENHANCED ERROR HANDLING (EEH) FOR POWERPC M: Mahesh J Salgaonkar mahesh@linux.ibm.com diff --git a/tools/testing/selftests/pci_endpoint/.gitignore b/tools/testing/selftests/pci_endpoint/.gitignore new file mode 100644 index 000000000000..29ab47c48484 --- /dev/null +++ b/tools/testing/selftests/pci_endpoint/.gitignore @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +*.o +pcitest diff --git a/tools/pci/Build b/tools/testing/selftests/pci_endpoint/Build similarity index 100% rename from tools/pci/Build rename to tools/testing/selftests/pci_endpoint/Build diff --git a/tools/pci/Makefile b/tools/testing/selftests/pci_endpoint/Makefile similarity index 83% rename from tools/pci/Makefile rename to tools/testing/selftests/pci_endpoint/Makefile index 62d41f1a1e2c..3c6fe18e32cc 100644 --- a/tools/pci/Makefile +++ b/tools/testing/selftests/pci_endpoint/Makefile @@ -1,11 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 -include ../scripts/Makefile.include +include ../../../scripts/Makefile.include
bindir ?= /usr/bin
ifeq ($(srctree),) -srctree := $(patsubst %/,%,$(dir $(CURDIR))) -srctree := $(patsubst %/,%,$(dir $(srctree))) +srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR))) endif
# Do not use make's built-in rules @@ -27,10 +26,11 @@ include $(srctree)/tools/build/Makefile.include # # We need the following to be outside of kernel tree # -$(OUTPUT)include/linux/: ../../include/uapi/linux/ +$(OUTPUT)include/linux/: ../../../../include/uapi/linux/ mkdir -p $(OUTPUT)include/linux/ 2>&1 || true - ln -sf $(CURDIR)/../../include/uapi/linux/pcitest.h $@ + ln -sf $(CURDIR)/../../../../include/uapi/linux/pcitest.h $@
+$(info ${CURDIR}) prepare: $(OUTPUT)include/linux/
PCITEST_IN := $(OUTPUT)pcitest-in.o diff --git a/tools/pci/pcitest.c b/tools/testing/selftests/pci_endpoint/pcitest.c similarity index 100% rename from tools/pci/pcitest.c rename to tools/testing/selftests/pci_endpoint/pcitest.c diff --git a/tools/pci/pcitest.sh b/tools/testing/selftests/pci_endpoint/pcitest.sh similarity index 100% rename from tools/pci/pcitest.sh rename to tools/testing/selftests/pci_endpoint/pcitest.sh
Migrate the PCI endpoint test to Kselftest framework. All the tests that were part of the previous pcitest.sh file were migrated.
Below is the exclusive list of tests:
1. BAR Tests (BAR0 to BAR5) 2. Legacy IRQ Tests 3. MSI Interrupt Tests (MSI1 to MSI32) 4. MSI-X Interrupt Tests (MSI-X1 to MSI-X2048) 5. Read Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes) 6. Write Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes) 7. Copy Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes) 8. Read Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes) 9. Write Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes) 10. Copy Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
DMA and MEMCPY tests are added as fixture variants and can be executed separately as below:
$ pci_endpoint_test -V dma (excluding DMA tests) $ pci_endpoint_test -V memcpy (excluding MEMCPY tests)
Co-developed-by: Aman Gupta aman1.gupta@samsung.com Signed-off-by: Aman Gupta aman1.gupta@samsung.com Co-developed-by: Padmanabhan Rajanbabu p.rajanbabu@samsung.com Signed-off-by: Padmanabhan Rajanbabu p.rajanbabu@samsung.com [mani: reworked based on the IOCTL fix, cleanups, documentation, commit message] Signed-off-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org --- Documentation/PCI/endpoint/pci-test-howto.rst | 143 +++------- tools/testing/selftests/Makefile | 1 + .../testing/selftests/pci_endpoint/.gitignore | 3 +- tools/testing/selftests/pci_endpoint/Build | 1 - tools/testing/selftests/pci_endpoint/Makefile | 59 +--- tools/testing/selftests/pci_endpoint/config | 4 + .../pci_endpoint/pci_endpoint_test.c | 186 +++++++++++++ .../testing/selftests/pci_endpoint/pcitest.c | 251 ------------------ .../testing/selftests/pci_endpoint/pcitest.sh | 72 ----- 9 files changed, 239 insertions(+), 481 deletions(-) delete mode 100644 tools/testing/selftests/pci_endpoint/Build create mode 100644 tools/testing/selftests/pci_endpoint/config create mode 100644 tools/testing/selftests/pci_endpoint/pci_endpoint_test.c delete mode 100644 tools/testing/selftests/pci_endpoint/pcitest.c delete mode 100644 tools/testing/selftests/pci_endpoint/pcitest.sh
diff --git a/Documentation/PCI/endpoint/pci-test-howto.rst b/Documentation/PCI/endpoint/pci-test-howto.rst index c4ae7af50ede..a0ff47cec605 100644 --- a/Documentation/PCI/endpoint/pci-test-howto.rst +++ b/Documentation/PCI/endpoint/pci-test-howto.rst @@ -123,9 +123,9 @@ above:: Using Endpoint Test function Device -----------------------------------
-pcitest.sh added in tools/testing/selftests/pci_endpoint can be used to run all -the default PCI endpoint tests. To compile this tool the following commands -should be used:: +Kselftest added in tools/testing/selftests/pci_endpoint can be used to run all +the default PCI endpoint tests. To build the Kselftest for PCI endpoint +subsystem, the following commands should be used::
# cd <kernel-dir> # make -C tools/testing/selftests/pci_endpoint @@ -133,104 +133,47 @@ should be used:: or if you desire to compile and install in your system::
# cd <kernel-dir> - # make -C tools/testing/selftests/pci_endpoint install + # make -C tools/testing/selftests/pci_endpoint INSTALL_PATH=/usr/bin install
-The tool and script will be located in <rootfs>/usr/bin/ +The test will be located in <rootfs>/usr/bin/
- -pcitest.sh Output -~~~~~~~~~~~~~~~~~ +Kselftest Output +~~~~~~~~~~~~~~~~ ::
- # pcitest.sh - BAR tests - - BAR0: OKAY - BAR1: OKAY - BAR2: OKAY - BAR3: OKAY - BAR4: NOT OKAY - BAR5: NOT OKAY - - Interrupt tests - - SET IRQ TYPE TO LEGACY: OKAY - LEGACY IRQ: NOT OKAY - SET IRQ TYPE TO MSI: OKAY - MSI1: OKAY - MSI2: OKAY - MSI3: OKAY - MSI4: OKAY - MSI5: OKAY - MSI6: OKAY - MSI7: OKAY - MSI8: OKAY - MSI9: OKAY - MSI10: OKAY - MSI11: OKAY - MSI12: OKAY - MSI13: OKAY - MSI14: OKAY - MSI15: OKAY - MSI16: OKAY - MSI17: NOT OKAY - MSI18: NOT OKAY - MSI19: NOT OKAY - MSI20: NOT OKAY - MSI21: NOT OKAY - MSI22: NOT OKAY - MSI23: NOT OKAY - MSI24: NOT OKAY - MSI25: NOT OKAY - MSI26: NOT OKAY - MSI27: NOT OKAY - MSI28: NOT OKAY - MSI29: NOT OKAY - MSI30: NOT OKAY - MSI31: NOT OKAY - MSI32: NOT OKAY - SET IRQ TYPE TO MSI-X: OKAY - MSI-X1: OKAY - MSI-X2: OKAY - MSI-X3: OKAY - MSI-X4: OKAY - MSI-X5: OKAY - MSI-X6: OKAY - MSI-X7: OKAY - MSI-X8: OKAY - MSI-X9: NOT OKAY - MSI-X10: NOT OKAY - MSI-X11: NOT OKAY - MSI-X12: NOT OKAY - MSI-X13: NOT OKAY - MSI-X14: NOT OKAY - MSI-X15: NOT OKAY - MSI-X16: NOT OKAY - [...] - MSI-X2047: NOT OKAY - MSI-X2048: NOT OKAY - - Read Tests - - SET IRQ TYPE TO MSI: OKAY - READ ( 1 bytes): OKAY - READ ( 1024 bytes): OKAY - READ ( 1025 bytes): OKAY - READ (1024000 bytes): OKAY - READ (1024001 bytes): OKAY - - Write Tests - - WRITE ( 1 bytes): OKAY - WRITE ( 1024 bytes): OKAY - WRITE ( 1025 bytes): OKAY - WRITE (1024000 bytes): OKAY - WRITE (1024001 bytes): OKAY - - Copy Tests - - COPY ( 1 bytes): OKAY - COPY ( 1024 bytes): OKAY - COPY ( 1025 bytes): OKAY - COPY (1024000 bytes): OKAY - COPY (1024001 bytes): OKAY + # pci_endpoint_test + TAP version 13 + 1..10 + # Starting 10 tests from 3 test cases. + # RUN pci_ep_basic.BAR_TEST ... + # OK pci_ep_basic.BAR_TEST + ok 1 pci_ep_basic.BAR_TEST + # RUN pci_ep_basic.LEGACY_IRQ_TEST ... + # OK pci_ep_basic.LEGACY_IRQ_TEST + ok 2 pci_ep_basic.LEGACY_IRQ_TEST + # RUN pci_ep_basic.MSI_TEST ... + # OK pci_ep_basic.MSI_TEST + ok 3 pci_ep_basic.MSI_TEST + # RUN pci_ep_basic.MSIX_TEST ... + # OK pci_ep_basic.MSIX_TEST + ok 4 pci_ep_basic.MSIX_TEST + # RUN pci_ep_data_transfer.memcpy.READ_TEST ... + # OK pci_ep_data_transfer.memcpy.READ_TEST + ok 5 pci_ep_data_transfer.memcpy.READ_TEST + # RUN pci_ep_data_transfer.memcpy.WRITE_TEST ... + # OK pci_ep_data_transfer.memcpy.WRITE_TEST + ok 6 pci_ep_data_transfer.memcpy.WRITE_TEST + # RUN pci_ep_data_transfer.memcpy.COPY_TEST ... + # OK pci_ep_data_transfer.memcpy.COPY_TEST + ok 7 pci_ep_data_transfer.memcpy.COPY_TEST + # RUN pci_ep_data_transfer.dma.READ_TEST ... + # OK pci_ep_data_transfer.dma.READ_TEST + ok 8 pci_ep_data_transfer.dma.READ_TEST + # RUN pci_ep_data_transfer.dma.WRITE_TEST ... + # OK pci_ep_data_transfer.dma.WRITE_TEST + ok 9 pci_ep_data_transfer.dma.WRITE_TEST + # RUN pci_ep_data_transfer.dma.COPY_TEST ... + # OK pci_ep_data_transfer.dma.COPY_TEST + ok 10 pci_ep_data_transfer.dma.COPY_TEST + # PASSED: 10 / 10 tests passed. + # Totals: pass:10 fail:0 xfail:0 xpass:0 skip:0 error:0 diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 363d031a16f7..d1c7089e7423 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -72,6 +72,7 @@ TARGETS += net/packetdrill TARGETS += net/rds TARGETS += net/tcp_ao TARGETS += nsfs +TARGETS += pci_endpoint TARGETS += perf_events TARGETS += pidfd TARGETS += pid_namespace diff --git a/tools/testing/selftests/pci_endpoint/.gitignore b/tools/testing/selftests/pci_endpoint/.gitignore index 29ab47c48484..6a4837a3e034 100644 --- a/tools/testing/selftests/pci_endpoint/.gitignore +++ b/tools/testing/selftests/pci_endpoint/.gitignore @@ -1,3 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -*.o -pcitest +pci_endpoint_test diff --git a/tools/testing/selftests/pci_endpoint/Build b/tools/testing/selftests/pci_endpoint/Build deleted file mode 100644 index c375aea21790..000000000000 --- a/tools/testing/selftests/pci_endpoint/Build +++ /dev/null @@ -1 +0,0 @@ -pcitest-y += pcitest.o diff --git a/tools/testing/selftests/pci_endpoint/Makefile b/tools/testing/selftests/pci_endpoint/Makefile index 3c6fe18e32cc..bf21ebf20b4a 100644 --- a/tools/testing/selftests/pci_endpoint/Makefile +++ b/tools/testing/selftests/pci_endpoint/Makefile @@ -1,58 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -include ../../../scripts/Makefile.include +CFLAGS += -O2 -Wl,-no-as-needed -Wall $(KHDR_INCLUDES) +LDFLAGS += -lrt -lpthread -lm
-bindir ?= /usr/bin +TEST_GEN_PROGS = pci_endpoint_test
-ifeq ($(srctree),) -srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR))) -endif - -# Do not use make's built-in rules -# (this improves performance and avoids hard-to-debug behaviour); -MAKEFLAGS += -r - -CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include - -ALL_TARGETS := pcitest -ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) - -SCRIPTS := pcitest.sh - -all: $(ALL_PROGRAMS) - -export srctree OUTPUT CC LD CFLAGS -include $(srctree)/tools/build/Makefile.include - -# -# We need the following to be outside of kernel tree -# -$(OUTPUT)include/linux/: ../../../../include/uapi/linux/ - mkdir -p $(OUTPUT)include/linux/ 2>&1 || true - ln -sf $(CURDIR)/../../../../include/uapi/linux/pcitest.h $@ - -$(info ${CURDIR}) -prepare: $(OUTPUT)include/linux/ - -PCITEST_IN := $(OUTPUT)pcitest-in.o -$(PCITEST_IN): prepare FORCE - $(Q)$(MAKE) $(build)=pcitest -$(OUTPUT)pcitest: $(PCITEST_IN) - $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ - -clean: - rm -f $(ALL_PROGRAMS) - rm -rf $(OUTPUT)include/ - find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '.*.cmd' -delete -o -name '.*.d' -delete - -install: $(ALL_PROGRAMS) - install -d -m 755 $(DESTDIR)$(bindir); \ - for program in $(ALL_PROGRAMS); do \ - install $$program $(DESTDIR)$(bindir); \ - done; \ - for script in $(SCRIPTS); do \ - install $$script $(DESTDIR)$(bindir); \ - done - -FORCE: - -.PHONY: all install clean FORCE prepare +include ../lib.mk diff --git a/tools/testing/selftests/pci_endpoint/config b/tools/testing/selftests/pci_endpoint/config new file mode 100644 index 000000000000..7cdcf117db8d --- /dev/null +++ b/tools/testing/selftests/pci_endpoint/config @@ -0,0 +1,4 @@ +CONFIG_PCI_ENDPOINT=y +CONFIG_PCI_ENDPOINT_CONFIGFS=y +CONFIG_PCI_EPF_TEST=m +CONFIG_PCI_ENDPOINT_TEST=m diff --git a/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c new file mode 100644 index 000000000000..de6d70ba3079 --- /dev/null +++ b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c @@ -0,0 +1,186 @@ +// 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 : 0; \ +}) + +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_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, BAR_TEST) +{ + int ret, i; + + for (i = 0; i <= 5; i++) { + pci_ep_ioctl(PCITEST_BAR, i); + EXPECT_FALSE(ret) TH_LOG("Test failed for BAR%d", i); + } +} + +TEST_F(pci_ep_basic, LEGACY_IRQ_TEST) +{ + int ret; + + pci_ep_ioctl(PCITEST_SET_IRQTYPE, 0); + ASSERT_EQ(0, ret) TH_LOG("Can't set 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, 1); + ASSERT_EQ(0, ret) TH_LOG("Can't set 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, 2); + ASSERT_EQ(0, ret) TH_LOG("Can't set 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 = {0}; + int ret, i; + + 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"); + + 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 = {0}; + int ret, i; + + 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"); + + 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 = {0}; + int ret, i; + + 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"); + + 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 diff --git a/tools/testing/selftests/pci_endpoint/pcitest.c b/tools/testing/selftests/pci_endpoint/pcitest.c deleted file mode 100644 index 545e04ad63a2..000000000000 --- a/tools/testing/selftests/pci_endpoint/pcitest.c +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/** - * Userspace PCI Endpoint Test Module - * - * Copyright (C) 2017 Texas Instruments - * Author: Kishon Vijay Abraham I kishon@ti.com - */ - -#include <errno.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <unistd.h> - -#include <linux/pcitest.h> - -static char *irq[] = { "LEGACY", "MSI", "MSI-X" }; - -struct pci_test { - char *device; - char barnum; - bool legacyirq; - unsigned int msinum; - unsigned int msixnum; - int irqtype; - bool set_irqtype; - bool get_irqtype; - bool clear_irq; - bool read; - bool write; - bool copy; - unsigned long size; - bool use_dma; -}; - -static int run_test(struct pci_test *test) -{ - struct pci_endpoint_test_xfer_param param = {}; - int ret = -EINVAL; - int fd; - - fd = open(test->device, O_RDWR); - if (fd < 0) { - perror("can't open PCI Endpoint Test device"); - return -ENODEV; - } - - if (test->barnum >= 0 && test->barnum <= 5) { - ret = ioctl(fd, PCITEST_BAR, test->barnum); - fprintf(stdout, "BAR%d:\t\t", test->barnum); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->set_irqtype) { - ret = ioctl(fd, PCITEST_SET_IRQTYPE, test->irqtype); - fprintf(stdout, "SET IRQ TYPE TO %s:\t\t", irq[test->irqtype]); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->get_irqtype) { - ret = ioctl(fd, PCITEST_GET_IRQTYPE); - fprintf(stdout, "GET IRQ TYPE:\t\t"); - if (ret < 0) { - fprintf(stdout, "NOT OKAY\n"); - } else { - fprintf(stdout, "%s\n", irq[ret]); - ret = 0; - } - } - - if (test->clear_irq) { - ret = ioctl(fd, PCITEST_CLEAR_IRQ); - fprintf(stdout, "CLEAR IRQ:\t\t"); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->legacyirq) { - ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0); - fprintf(stdout, "LEGACY IRQ:\t"); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->msinum > 0 && test->msinum <= 32) { - ret = ioctl(fd, PCITEST_MSI, test->msinum); - fprintf(stdout, "MSI%d:\t\t", test->msinum); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->msixnum > 0 && test->msixnum <= 2048) { - ret = ioctl(fd, PCITEST_MSIX, test->msixnum); - fprintf(stdout, "MSI-X%d:\t\t", test->msixnum); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->write) { - param.size = test->size; - if (test->use_dma) - param.flags = PCITEST_FLAGS_USE_DMA; - ret = ioctl(fd, PCITEST_WRITE, ¶m); - fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->read) { - param.size = test->size; - if (test->use_dma) - param.flags = PCITEST_FLAGS_USE_DMA; - ret = ioctl(fd, PCITEST_READ, ¶m); - fprintf(stdout, "READ (%7ld bytes):\t\t", test->size); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - if (test->copy) { - param.size = test->size; - if (test->use_dma) - param.flags = PCITEST_FLAGS_USE_DMA; - ret = ioctl(fd, PCITEST_COPY, ¶m); - fprintf(stdout, "COPY (%7ld bytes):\t\t", test->size); - if (ret < 0) - fprintf(stdout, "NOT OKAY\n"); - else - fprintf(stdout, "OKAY\n"); - } - - fflush(stdout); - close(fd); - return ret; -} - -int main(int argc, char **argv) -{ - int c; - struct pci_test *test; - - test = calloc(1, sizeof(*test)); - if (!test) { - perror("Fail to allocate memory for pci_test\n"); - return -ENOMEM; - } - - /* since '0' is a valid BAR number, initialize it to -1 */ - test->barnum = -1; - - /* set default size as 100KB */ - test->size = 0x19000; - - /* set default endpoint device */ - test->device = "/dev/pci-endpoint-test.0"; - - while ((c = getopt(argc, argv, "D:b:m:x:i:deIlhrwcs:")) != EOF) - switch (c) { - case 'D': - test->device = optarg; - continue; - case 'b': - test->barnum = atoi(optarg); - if (test->barnum < 0 || test->barnum > 5) - goto usage; - continue; - case 'l': - test->legacyirq = true; - continue; - case 'm': - test->msinum = atoi(optarg); - if (test->msinum < 1 || test->msinum > 32) - goto usage; - continue; - case 'x': - test->msixnum = atoi(optarg); - if (test->msixnum < 1 || test->msixnum > 2048) - goto usage; - continue; - case 'i': - test->irqtype = atoi(optarg); - if (test->irqtype < 0 || test->irqtype > 2) - goto usage; - test->set_irqtype = true; - continue; - case 'I': - test->get_irqtype = true; - continue; - case 'r': - test->read = true; - continue; - case 'w': - test->write = true; - continue; - case 'c': - test->copy = true; - continue; - case 'e': - test->clear_irq = true; - continue; - case 's': - test->size = strtoul(optarg, NULL, 0); - continue; - case 'd': - test->use_dma = true; - continue; - case 'h': - default: -usage: - fprintf(stderr, - "usage: %s [options]\n" - "Options:\n" - "\t-D <dev> PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n" - "\t-b <bar num> BAR test (bar number between 0..5)\n" - "\t-m <msi num> MSI test (msi number between 1..32)\n" - "\t-x <msix num> \tMSI-X test (msix number between 1..2048)\n" - "\t-i <irq type> \tSet IRQ type (0 - Legacy, 1 - MSI, 2 - MSI-X)\n" - "\t-e Clear IRQ\n" - "\t-I Get current IRQ type configured\n" - "\t-d Use DMA\n" - "\t-l Legacy IRQ test\n" - "\t-r Read buffer test\n" - "\t-w Write buffer test\n" - "\t-c Copy buffer test\n" - "\t-s <size> Size of buffer {default: 100KB}\n" - "\t-h Print this help message\n", - argv[0]); - return -EINVAL; - } - - return run_test(test); -} diff --git a/tools/testing/selftests/pci_endpoint/pcitest.sh b/tools/testing/selftests/pci_endpoint/pcitest.sh deleted file mode 100644 index 75ed48ff2990..000000000000 --- a/tools/testing/selftests/pci_endpoint/pcitest.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -echo "BAR tests" -echo - -bar=0 - -while [ $bar -lt 6 ] -do - pcitest -b $bar - bar=`expr $bar + 1` -done -echo - -echo "Interrupt tests" -echo - -pcitest -i 0 -pcitest -l - -pcitest -i 1 -msi=1 - -while [ $msi -lt 33 ] -do - pcitest -m $msi - msi=`expr $msi + 1` -done -echo - -pcitest -i 2 -msix=1 - -while [ $msix -lt 2049 ] -do - pcitest -x $msix - msix=`expr $msix + 1` -done -echo - -echo "Read Tests" -echo - -pcitest -i 1 - -pcitest -r -s 1 -pcitest -r -s 1024 -pcitest -r -s 1025 -pcitest -r -s 1024000 -pcitest -r -s 1024001 -echo - -echo "Write Tests" -echo - -pcitest -w -s 1 -pcitest -w -s 1024 -pcitest -w -s 1025 -pcitest -w -s 1024000 -pcitest -w -s 1024001 -echo - -echo "Copy Tests" -echo - -pcitest -c -s 1 -pcitest -c -s 1024 -pcitest -c -s 1025 -pcitest -c -s 1024000 -pcitest -c -s 1024001 -echo
Hello Mani,
On Fri, Nov 29, 2024 at 02:54:15PM +0530, Manivannan Sadhasivam wrote:
Migrate the PCI endpoint test to Kselftest framework. All the tests that were part of the previous pcitest.sh file were migrated.
Below is the exclusive list of tests:
- BAR Tests (BAR0 to BAR5)
- Legacy IRQ Tests
- MSI Interrupt Tests (MSI1 to MSI32)
- MSI-X Interrupt Tests (MSI-X1 to MSI-X2048)
- Read Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Read Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
I'm not sure if it is a great idea to add test case number 10.
While it will work if you use the "dummy memcpy" DMA channel which uses MMIO under the hood, if you actually enable a real DMA controller (which often sets the DMA_PRIVATE cap in the DMA controller driver (e.g. if you are using a DWC based PCIe EP controller and select CONFIG_DW_EDMA=y)), pci_epf_test_copy() will fail with: [ 93.779444] pci_epf_test pci_epf_test.0: Cannot transfer data using DMA
See: https://github.com/torvalds/linux/blob/v6.12/drivers/pci/endpoint/functions/...
Kind regards, Niklas
On Fri, Nov 29, 2024 at 02:51:26PM +0100, Niklas Cassel wrote:
Hello Mani,
On Fri, Nov 29, 2024 at 02:54:15PM +0530, Manivannan Sadhasivam wrote:
Migrate the PCI endpoint test to Kselftest framework. All the tests that were part of the previous pcitest.sh file were migrated.
Below is the exclusive list of tests:
- BAR Tests (BAR0 to BAR5)
- Legacy IRQ Tests
- MSI Interrupt Tests (MSI1 to MSI32)
- MSI-X Interrupt Tests (MSI-X1 to MSI-X2048)
- Read Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Read Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
I'm not sure if it is a great idea to add test case number 10.
While it will work if you use the "dummy memcpy" DMA channel which uses MMIO under the hood, if you actually enable a real DMA controller (which often sets the DMA_PRIVATE cap in the DMA controller driver (e.g. if you are using a DWC based PCIe EP controller and select CONFIG_DW_EDMA=y)), pci_epf_test_copy() will fail with: [ 93.779444] pci_epf_test pci_epf_test.0: Cannot transfer data using DMA
So the idea is to exercise all the options provided by the epf-test driver. In that sense, we need to have the DMA COPY test. However, I do agree that the common DMA controllers will fail this case. So how about just simulating the DMA COPY for controllers implementing DMA_PRIVATE cap? I don't think it hurts to have this feature in test driver.
- Mani
On Fri, Nov 29, 2024 at 10:05:55PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 02:51:26PM +0100, Niklas Cassel wrote:
Hello Mani,
On Fri, Nov 29, 2024 at 02:54:15PM +0530, Manivannan Sadhasivam wrote:
Migrate the PCI endpoint test to Kselftest framework. All the tests that were part of the previous pcitest.sh file were migrated.
Below is the exclusive list of tests:
- BAR Tests (BAR0 to BAR5)
- Legacy IRQ Tests
- MSI Interrupt Tests (MSI1 to MSI32)
- MSI-X Interrupt Tests (MSI-X1 to MSI-X2048)
- Read Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Read Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
I'm not sure if it is a great idea to add test case number 10.
While it will work if you use the "dummy memcpy" DMA channel which uses MMIO under the hood, if you actually enable a real DMA controller (which often sets the DMA_PRIVATE cap in the DMA controller driver (e.g. if you are using a DWC based PCIe EP controller and select CONFIG_DW_EDMA=y)), pci_epf_test_copy() will fail with: [ 93.779444] pci_epf_test pci_epf_test.0: Cannot transfer data using DMA
So the idea is to exercise all the options provided by the epf-test driver. In that sense, we need to have the DMA COPY test. However, I do agree that the common DMA controllers will fail this case. So how about just simulating the DMA COPY for controllers implementing DMA_PRIVATE cap? I don't think it hurts to have this feature in test driver.
I guess you could modify pci-epf-test to simply do MMIO in test_copy(), if USE_DMA && DMA_PRIVATE is set, as you suggest.
We should probably print a warning/info that we are falling back to MMIO in that case though.
Kind regards, Niklas
On Fri, Nov 29, 2024 at 05:42:26PM +0100, Niklas Cassel wrote:
On Fri, Nov 29, 2024 at 10:05:55PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 02:51:26PM +0100, Niklas Cassel wrote:
Hello Mani,
On Fri, Nov 29, 2024 at 02:54:15PM +0530, Manivannan Sadhasivam wrote:
Migrate the PCI endpoint test to Kselftest framework. All the tests that were part of the previous pcitest.sh file were migrated.
Below is the exclusive list of tests:
- BAR Tests (BAR0 to BAR5)
- Legacy IRQ Tests
- MSI Interrupt Tests (MSI1 to MSI32)
- MSI-X Interrupt Tests (MSI-X1 to MSI-X2048)
- Read Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Read Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
I'm not sure if it is a great idea to add test case number 10.
While it will work if you use the "dummy memcpy" DMA channel which uses MMIO under the hood, if you actually enable a real DMA controller (which often sets the DMA_PRIVATE cap in the DMA controller driver (e.g. if you are using a DWC based PCIe EP controller and select CONFIG_DW_EDMA=y)), pci_epf_test_copy() will fail with: [ 93.779444] pci_epf_test pci_epf_test.0: Cannot transfer data using DMA
So the idea is to exercise all the options provided by the epf-test driver. In that sense, we need to have the DMA COPY test. However, I do agree that the common DMA controllers will fail this case. So how about just simulating the DMA COPY for controllers implementing DMA_PRIVATE cap? I don't think it hurts to have this feature in test driver.
I guess you could modify pci-epf-test to simply do MMIO in test_copy(), if USE_DMA && DMA_PRIVATE is set, as you suggest.
No not memcpy, but using the DMA to copy from src to local buf and then local buf to dst. This way, we do not need to fallback and at the same time simulate DMA COPY.
- Mani
On Fri, Nov 29, 2024 at 10:22:56PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 05:42:26PM +0100, Niklas Cassel wrote:
On Fri, Nov 29, 2024 at 10:05:55PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 02:51:26PM +0100, Niklas Cassel wrote:
Hello Mani,
On Fri, Nov 29, 2024 at 02:54:15PM +0530, Manivannan Sadhasivam wrote:
Migrate the PCI endpoint test to Kselftest framework. All the tests that were part of the previous pcitest.sh file were migrated.
Below is the exclusive list of tests:
- BAR Tests (BAR0 to BAR5)
- Legacy IRQ Tests
- MSI Interrupt Tests (MSI1 to MSI32)
- MSI-X Interrupt Tests (MSI-X1 to MSI-X2048)
- Read Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Read Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
I'm not sure if it is a great idea to add test case number 10.
While it will work if you use the "dummy memcpy" DMA channel which uses MMIO under the hood, if you actually enable a real DMA controller (which often sets the DMA_PRIVATE cap in the DMA controller driver (e.g. if you are using a DWC based PCIe EP controller and select CONFIG_DW_EDMA=y)), pci_epf_test_copy() will fail with: [ 93.779444] pci_epf_test pci_epf_test.0: Cannot transfer data using DMA
So the idea is to exercise all the options provided by the epf-test driver. In that sense, we need to have the DMA COPY test. However, I do agree that the common DMA controllers will fail this case. So how about just simulating the DMA COPY for controllers implementing DMA_PRIVATE cap? I don't think it hurts to have this feature in test driver.
I guess you could modify pci-epf-test to simply do MMIO in test_copy(), if USE_DMA && DMA_PRIVATE is set, as you suggest.
No not memcpy, but using the DMA to copy from src to local buf and then local buf to dst. This way, we do not need to fallback and at the same time simulate DMA COPY.
Sounds very slow :)
What would be the value to add such code to pci-epf-test?
Sounds like we would just add a lot of extra code in pci-epf-test.c that would not test anything new. (It would basically just be the DMA read test followed by the DMA write test. If those tests pass, this new simulated test should be guaranteed to pass.)
Wouldn't it make more sense to simply do something like:
if (use_dma && dma_prive) { dev_warn(dev, "DEV_TO_DEV not supported with USE_DMA, falling back to MMIO\n"); use_dma = 0; }
Kind regards, Niklas
On Fri, Nov 29, 2024 at 06:13:12PM +0100, Niklas Cassel wrote:
On Fri, Nov 29, 2024 at 10:22:56PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 05:42:26PM +0100, Niklas Cassel wrote:
On Fri, Nov 29, 2024 at 10:05:55PM +0530, Manivannan Sadhasivam wrote:
On Fri, Nov 29, 2024 at 02:51:26PM +0100, Niklas Cassel wrote:
Hello Mani,
On Fri, Nov 29, 2024 at 02:54:15PM +0530, Manivannan Sadhasivam wrote:
Migrate the PCI endpoint test to Kselftest framework. All the tests that were part of the previous pcitest.sh file were migrated.
Below is the exclusive list of tests:
- BAR Tests (BAR0 to BAR5)
- Legacy IRQ Tests
- MSI Interrupt Tests (MSI1 to MSI32)
- MSI-X Interrupt Tests (MSI-X1 to MSI-X2048)
- Read Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - MEMCPY (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Read Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Write Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
- Copy Tests - DMA (For 1, 1024, 1025, 1024000, 1024001 Bytes)
I'm not sure if it is a great idea to add test case number 10.
While it will work if you use the "dummy memcpy" DMA channel which uses MMIO under the hood, if you actually enable a real DMA controller (which often sets the DMA_PRIVATE cap in the DMA controller driver (e.g. if you are using a DWC based PCIe EP controller and select CONFIG_DW_EDMA=y)), pci_epf_test_copy() will fail with: [ 93.779444] pci_epf_test pci_epf_test.0: Cannot transfer data using DMA
So the idea is to exercise all the options provided by the epf-test driver. In that sense, we need to have the DMA COPY test. However, I do agree that the common DMA controllers will fail this case. So how about just simulating the DMA COPY for controllers implementing DMA_PRIVATE cap? I don't think it hurts to have this feature in test driver.
I guess you could modify pci-epf-test to simply do MMIO in test_copy(), if USE_DMA && DMA_PRIVATE is set, as you suggest.
No not memcpy, but using the DMA to copy from src to local buf and then local buf to dst. This way, we do not need to fallback and at the same time simulate DMA COPY.
Sounds very slow :)
What would be the value to add such code to pci-epf-test?
Well, the test case is to test COPY functionality using DMA. Either we use MEM_TO_MEM if supported, or just do DMA from source to dst. Even if the performance is going to be half of what read/write would achieve separately, it would give users a real benchmark. Otherwise, we have to skip the test case altogether. Like,
./pci_endpoint_test -f pci_ep_basic -v memcpy -T COPY_TEST -v dma
Perhaps we should document this limitation and show above command to skip the COPY_TEST for DMA?
Sounds like we would just add a lot of extra code in pci-epf-test.c that would not test anything new. (It would basically just be the DMA read test followed by the DMA write test. If those tests pass, this new simulated test should be guaranteed to pass.)
Wouldn't it make more sense to simply do something like:
if (use_dma && dma_prive) { dev_warn(dev, "DEV_TO_DEV not supported with USE_DMA, falling back to MMIO\n"); use_dma = 0; }
Maybe yes, but memcpy is also doing the same. The problem with falling back is that, it provides a fake benchmark to the users which I want to avoid doing so.
- Mani
linux-kselftest-mirror@lists.linaro.org