Message ID | 20241231131341.39292-4-manivannan.sadhasivam@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | [v4,1/3] misc: pci_endpoint_test: Fix the return value of IOCTL | expand |
On Tue, Dec 31, 2024 at 06:43:41PM +0530, Manivannan Sadhasivam wrote: (...) > + # RUN pci_ep_data_transfer.dma.COPY_TEST ... > + # OK pci_ep_data_transfer.dma.COPY_TEST > + ok 11 pci_ep_data_transfer.dma.COPY_TEST > + # PASSED: 11 / 11 tests passed. > + # Totals: pass:11 fail:0 xfail:0 xpass:0 skip:0 error:0 > + > + > +Testcase 11 (pci_ep_data_transfer.dma.COPY_TEST) will fail for most of the DMA > +capable endpoint controllers due to the absence of the MEMCPY over DMA. For such > +controllers, it is advisable to skip the forementioned testcase using below > +command:: Hm.. this is strictly not correct. If will currently fail because pci-epf-test.c does: if ((reg->flags & FLAG_USE_DMA) && epf_test->dma_private) return -EINVAL; So even if a DMA driver has support for the DMA_MEMCPY cap, if the DMA driver also has the DMA_PRIVATE cap, this test will fail because of the code in pci-epf-test.c. Not sure how to formulate this properly... Perhaps: Testcase 11 (pci_ep_data_transfer.dma.COPY_TEST) will fail for DMA drivers that have the DMA_PRIVATE cap set. For DMA drivers which have the DMA_PRIVATE cap set, it is advisable to skip the forementioned testcase using below command:: > + > + # pci_endpoint_test -f pci_ep_basic -v memcpy -T COPY_TEST -v dma Is this really correct? I would guess that it should be pci_endpoint_test -f pci_ep_data_transfer -v memcpy -T COPY_TEST -v dma (...) > +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); > + } > +}
On Tue, Dec 31, 2024 at 06:42:42PM +0100, Niklas Cassel wrote: > On Tue, Dec 31, 2024 at 06:43:41PM +0530, Manivannan Sadhasivam wrote: > > (...) > > > + # RUN pci_ep_data_transfer.dma.COPY_TEST ... > > + # OK pci_ep_data_transfer.dma.COPY_TEST > > + ok 11 pci_ep_data_transfer.dma.COPY_TEST > > + # PASSED: 11 / 11 tests passed. > > + # Totals: pass:11 fail:0 xfail:0 xpass:0 skip:0 error:0 > > + > > + > > +Testcase 11 (pci_ep_data_transfer.dma.COPY_TEST) will fail for most of the DMA > > +capable endpoint controllers due to the absence of the MEMCPY over DMA. For such > > +controllers, it is advisable to skip the forementioned testcase using below > > +command:: > > Hm.. this is strictly not correct. If will currently fail because pci-epf-test.c > does: > if ((reg->flags & FLAG_USE_DMA) && epf_test->dma_private) > return -EINVAL; > > So even if a DMA driver has support for the DMA_MEMCPY cap, if the DMA driver > also has the DMA_PRIVATE cap, this test will fail because of the code in > pci-epf-test.c. > Right. But I think the condition should be changed to test for the MEMCPY capability instead. Like, diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index ef6677f34116..0b211d60a85b 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -328,7 +328,7 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, void *copy_buf = NULL, *buf; if (reg->flags & FLAG_USE_DMA) { - if (epf_test->dma_private) { + if (!dma_has_cap(DMA_MEMCPY, epf_test->dma_chan_tx->device->cap_mask)) { dev_err(dev, "Cannot transfer data using DMA\n"); ret = -EINVAL; goto set_status; > Not sure how to formulate this properly... Perhaps: > Testcase 11 (pci_ep_data_transfer.dma.COPY_TEST) will fail for DMA drivers that > have the DMA_PRIVATE cap set. For DMA drivers which have the DMA_PRIVATE cap > set, it is advisable to skip the forementioned testcase using below command:: > > > + > > + # pci_endpoint_test -f pci_ep_basic -v memcpy -T COPY_TEST -v dma > > Is this really correct? I would guess that it should be > pci_endpoint_test -f pci_ep_data_transfer -v memcpy -T COPY_TEST -v dma > ah, typo. Thanks for catching! > > (...) > > > +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); > > + } > > +} > > From looking at this function, will we still be able to test a single BAR? > Previous pcitest.c allowed us to do pcitest -b <barno> to only test a > specific BAR. I think that is a useful feature that we shouldn't remove. > > It would be nice if we could do something like: > # pci_endpoint_test -f pci_ep_basic -T BAR_TEST -v <barno> > I'll try to add it. > > (...) > > > + > > +TEST_F(pci_ep_data_transfer, COPY_TEST) > > +{ > > + struct pci_endpoint_test_xfer_param param = {0}; > > This (also other places in this file) can be written as: > struct pci_endpoint_test_xfer_param param = {}; > Ack. - Mani
On 31 December 2024 20:18:12 CET, Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> wrote: >On Tue, Dec 31, 2024 at 06:42:42PM +0100, Niklas Cassel wrote: >> On Tue, Dec 31, 2024 at 06:43:41PM +0530, Manivannan Sadhasivam wrote: >> >> (...) >> >> > + # RUN pci_ep_data_transfer.dma.COPY_TEST ... >> > + # OK pci_ep_data_transfer.dma.COPY_TEST >> > + ok 11 pci_ep_data_transfer.dma.COPY_TEST >> > + # PASSED: 11 / 11 tests passed. >> > + # Totals: pass:11 fail:0 xfail:0 xpass:0 skip:0 error:0 >> > + >> > + >> > +Testcase 11 (pci_ep_data_transfer.dma.COPY_TEST) will fail for most of the DMA >> > +capable endpoint controllers due to the absence of the MEMCPY over DMA. For such >> > +controllers, it is advisable to skip the forementioned testcase using below >> > +command:: >> >> Hm.. this is strictly not correct. If will currently fail because pci-epf-test.c >> does: >> if ((reg->flags & FLAG_USE_DMA) && epf_test->dma_private) >> return -EINVAL; >> >> So even if a DMA driver has support for the DMA_MEMCPY cap, if the DMA driver >> also has the DMA_PRIVATE cap, this test will fail because of the code in >> pci-epf-test.c. >> > >Right. But I think the condition should be changed to test for the MEMCPY >capability instead. Like, > >diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c >index ef6677f34116..0b211d60a85b 100644 >--- a/drivers/pci/endpoint/functions/pci-epf-test.c >+++ b/drivers/pci/endpoint/functions/pci-epf-test.c >@@ -328,7 +328,7 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, > void *copy_buf = NULL, *buf; > > if (reg->flags & FLAG_USE_DMA) { >- if (epf_test->dma_private) { >+ if (!dma_has_cap(DMA_MEMCPY, epf_test->dma_chan_tx->device->cap_mask)) { > dev_err(dev, "Cannot transfer data using DMA\n"); > ret = -EINVAL; > goto set_status; > That check does seem to make more sense than the code that is currently there. (Perhaps send this as a proper patch?) Note that I'm not an expert at dmaengine. I have some patches that adds DMA_MEMCPY to dw-edma, but I'm not sure if the DWC eDMA hardware supports having both src and dst as PCI addresses, or if only one of them can be a PCI address (with the other one being a local address). If only one of them can be a PCI address, then I'm not sure if your suggested patch is correct. Kind regards, Niklas
On Tue, Dec 31, 2024 at 08:33:57PM +0100, Niklas Cassel wrote: > > > On 31 December 2024 20:18:12 CET, Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> wrote: > >On Tue, Dec 31, 2024 at 06:42:42PM +0100, Niklas Cassel wrote: > >> On Tue, Dec 31, 2024 at 06:43:41PM +0530, Manivannan Sadhasivam wrote: > >> > >> (...) > >> > >> > + # RUN pci_ep_data_transfer.dma.COPY_TEST ... > >> > + # OK pci_ep_data_transfer.dma.COPY_TEST > >> > + ok 11 pci_ep_data_transfer.dma.COPY_TEST > >> > + # PASSED: 11 / 11 tests passed. > >> > + # Totals: pass:11 fail:0 xfail:0 xpass:0 skip:0 error:0 > >> > + > >> > + > >> > +Testcase 11 (pci_ep_data_transfer.dma.COPY_TEST) will fail for most of the DMA > >> > +capable endpoint controllers due to the absence of the MEMCPY over DMA. For such > >> > +controllers, it is advisable to skip the forementioned testcase using below > >> > +command:: > >> > >> Hm.. this is strictly not correct. If will currently fail because pci-epf-test.c > >> does: > >> if ((reg->flags & FLAG_USE_DMA) && epf_test->dma_private) > >> return -EINVAL; > >> > >> So even if a DMA driver has support for the DMA_MEMCPY cap, if the DMA driver > >> also has the DMA_PRIVATE cap, this test will fail because of the code in > >> pci-epf-test.c. > >> > > > >Right. But I think the condition should be changed to test for the MEMCPY > >capability instead. Like, > > > >diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c > >index ef6677f34116..0b211d60a85b 100644 > >--- a/drivers/pci/endpoint/functions/pci-epf-test.c > >+++ b/drivers/pci/endpoint/functions/pci-epf-test.c > >@@ -328,7 +328,7 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, > > void *copy_buf = NULL, *buf; > > > > if (reg->flags & FLAG_USE_DMA) { > >- if (epf_test->dma_private) { > >+ if (!dma_has_cap(DMA_MEMCPY, epf_test->dma_chan_tx->device->cap_mask)) { > > dev_err(dev, "Cannot transfer data using DMA\n"); > > ret = -EINVAL; > > goto set_status; > > > > That check does seem to make more sense than the code that is currently there. > (Perhaps send this as a proper patch?) Will do. > Note that I'm not an expert at dmaengine. > > I have some patches that adds DMA_MEMCPY to dw-edma, but I'm not sure if the DWC eDMA hardware supports having both src and dst as PCI addresses, or if only one of them can be a PCI address (with the other one being a local address). > > If only one of them can be a PCI address, then I'm not sure if your suggested patch is correct. > I don't see why that would be an issue. DMA_MEMCPY is independent of PCI/local addresses. If a dmaengine driver support doing MEMCPY, then the dma cap should be sufficient. As you said, if a controller supports both SLAVE and MEMCPY, the test currently errors out, which is wrong. - Mani
Hello Mani, Vinod, On Thu, Jan 02, 2025 at 12:34:04PM +0530, Manivannan Sadhasivam wrote: > On Tue, Dec 31, 2024 at 08:33:57PM +0100, Niklas Cassel wrote: > > > > I have some patches that adds DMA_MEMCPY to dw-edma, but I'm not sure if the DWC eDMA hardware supports having both src and dst as PCI addresses, or if only one of them can be a PCI address (with the other one being a local address). > > > > If only one of them can be a PCI address, then I'm not sure if your suggested patch is correct. > > > > I don't see why that would be an issue. DMA_MEMCPY is independent of PCI/local > addresses. If a dmaengine driver support doing MEMCPY, then the dma cap should > be sufficient. As you said, if a controller supports both SLAVE and MEMCPY, the > test currently errors out, which is wrong. While I am okay with your suggested change to pci-epf-test.c: > >- if (epf_test->dma_private) { > >+ if (!dma_has_cap(DMA_MEMCPY, epf_test->dma_chan_tx->device->cap_mask)) { Since this will ensure that a DMA driver implementing DMA_MEMCPY, which cannot be shared (has DMA_PRIVATE set), will not error out. What I'm trying to explain is that in: https://lore.kernel.org/linux-pci/Z2BW4CjdE1p50AhC@vaman/ https://lore.kernel.org/linux-pci/20241217090129.6dodrgi4tn7l3cod@thinkpad/ Vinod (any you) suggested that we should add support for prep_memcpy() (which implies also setting cap DMA_MEMCPY) in the dw-edma DMA driver. However, from section "6.3 Using the DMA" in the DWC databook, the DWC eDMA hardware only supports: - Transfer (copy) of a block of data from local memory to remote memory. - Transfer (copy) of a block of data from remote memory to local memory. Currently, we have: https://github.com/torvalds/linux/blob/v6.13-rc5/include/linux/dmaengine.h#L843-L844 https://github.com/torvalds/linux/blob/v6.13-rc5/drivers/dma/dw-edma/dw-edma-core.c#L215-L231 Where we can expose per-channel capabilities, so we set MEM_TO_DEV/DEV_TO_MEM per channel, however, these are returned in a struct dma_slave_caps *caps, so this is AFAICT only for DMA_SLAVE, not for DMA_MEMCPY. Looking at: https://github.com/torvalds/linux/blob/v6.13-rc5/include/linux/dmaengine.h#L975-L979 it seems that DMA_MEMCPY is always assumed to be MEM_TO_MEM. To me, it seems that we would either need a new dma_transaction_type (e.g. DMA_COPY) where we can set dir: MEM_TO_DEV, DEV_TO_MEM, or DEV_TO_DEV. (dw-edma would not support DEV_TO_DEV.) Or, if we should stick with DMA_MEMCPY, we would need another way of telling client drivers that only src or dst can be a remote address. Until this is solved, I think I will stop my work on adding DMA_MEMCPY to the dw-edma driver. Kind regards, Niklas
On Thu, Jan 02, 2025 at 03:23:14PM +0100, Niklas Cassel wrote: > Hello Mani, Vinod, > > On Thu, Jan 02, 2025 at 12:34:04PM +0530, Manivannan Sadhasivam wrote: > > On Tue, Dec 31, 2024 at 08:33:57PM +0100, Niklas Cassel wrote: > > > > > > I have some patches that adds DMA_MEMCPY to dw-edma, but I'm not sure if the DWC eDMA hardware supports having both src and dst as PCI addresses, or if only one of them can be a PCI address (with the other one being a local address). > > > > > > If only one of them can be a PCI address, then I'm not sure if your suggested patch is correct. > > > > > > > I don't see why that would be an issue. DMA_MEMCPY is independent of PCI/local > > addresses. If a dmaengine driver support doing MEMCPY, then the dma cap should > > be sufficient. As you said, if a controller supports both SLAVE and MEMCPY, the > > test currently errors out, which is wrong. > > While I am okay with your suggested change to pci-epf-test.c: > > >- if (epf_test->dma_private) { > > >+ if (!dma_has_cap(DMA_MEMCPY, epf_test->dma_chan_tx->device->cap_mask)) { > > Since this will ensure that a DMA driver implementing DMA_MEMCPY, > which cannot be shared (has DMA_PRIVATE set), will not error out. > > > What I'm trying to explain is that in: > https://lore.kernel.org/linux-pci/Z2BW4CjdE1p50AhC@vaman/ > https://lore.kernel.org/linux-pci/20241217090129.6dodrgi4tn7l3cod@thinkpad/ > > Vinod (any you) suggested that we should add support for prep_memcpy() > (which implies also setting cap DMA_MEMCPY) in the dw-edma DMA driver. > > However, from section "6.3 Using the DMA" in the DWC databook, > the DWC eDMA hardware only supports: > - Transfer (copy) of a block of data from local memory to remote memory. > - Transfer (copy) of a block of data from remote memory to local memory. > > > Currently, we have: > https://github.com/torvalds/linux/blob/v6.13-rc5/include/linux/dmaengine.h#L843-L844 > https://github.com/torvalds/linux/blob/v6.13-rc5/drivers/dma/dw-edma/dw-edma-core.c#L215-L231 > > Where we can expose per-channel capabilities, so we set MEM_TO_DEV/DEV_TO_MEM > per channel, however, these are returned in a struct dma_slave_caps *caps, > so this is AFAICT only for DMA_SLAVE, not for DMA_MEMCPY. > > Looking at: > https://github.com/torvalds/linux/blob/v6.13-rc5/include/linux/dmaengine.h#L975-L979 > it seems that DMA_MEMCPY is always assumed to be MEM_TO_MEM. > > To me, it seems that we would either need a new dma_transaction_type (e.g. DMA_COPY) > where we can set dir: > MEM_TO_DEV, DEV_TO_MEM, or DEV_TO_DEV. (dw-edma would not support DEV_TO_DEV.) > > Or, if we should stick with DMA_MEMCPY, we would need another way of telling > client drivers that only src or dst can be a remote address. > > Until this is solved, I think I will stop my work on adding DMA_MEMCPY to the > dw-edma driver. > I think your concern is regarding setting the DMA transfer direction for MEMCPY, right? And you are saying that even if we use tx/rx channels, currently we cannot set DEV_TO_DEV like directions? But I'm somewhat confused about what is blocking you from adding MEMCPY support to the dw-edma driver since that driver cannot support DEV_TO_DEV. In your WIP driver, you were setting the direction based on the channel. Isn't that sufficient enough? - Mani
On Thu, Jan 16, 2025 at 10:17:25AM +0530, Manivannan Sadhasivam wrote: > On Thu, Jan 02, 2025 at 03:23:14PM +0100, Niklas Cassel wrote: > > Hello Mani, Vinod, > > > > On Thu, Jan 02, 2025 at 12:34:04PM +0530, Manivannan Sadhasivam wrote: > > > On Tue, Dec 31, 2024 at 08:33:57PM +0100, Niklas Cassel wrote: > > > > > > > > I have some patches that adds DMA_MEMCPY to dw-edma, but I'm not sure if the DWC eDMA hardware supports having both src and dst as PCI addresses, or if only one of them can be a PCI address (with the other one being a local address). > > > > > > > > If only one of them can be a PCI address, then I'm not sure if your suggested patch is correct. > > > > > > > > > > I don't see why that would be an issue. DMA_MEMCPY is independent of PCI/local > > > addresses. If a dmaengine driver support doing MEMCPY, then the dma cap should > > > be sufficient. As you said, if a controller supports both SLAVE and MEMCPY, the > > > test currently errors out, which is wrong. > > > > While I am okay with your suggested change to pci-epf-test.c: > > > >- if (epf_test->dma_private) { > > > >+ if (!dma_has_cap(DMA_MEMCPY, epf_test->dma_chan_tx->device->cap_mask)) { > > > > Since this will ensure that a DMA driver implementing DMA_MEMCPY, > > which cannot be shared (has DMA_PRIVATE set), will not error out. > > > > > > What I'm trying to explain is that in: > > https://lore.kernel.org/linux-pci/Z2BW4CjdE1p50AhC@vaman/ > > https://lore.kernel.org/linux-pci/20241217090129.6dodrgi4tn7l3cod@thinkpad/ > > > > Vinod (any you) suggested that we should add support for prep_memcpy() > > (which implies also setting cap DMA_MEMCPY) in the dw-edma DMA driver. > > > > However, from section "6.3 Using the DMA" in the DWC databook, > > the DWC eDMA hardware only supports: > > - Transfer (copy) of a block of data from local memory to remote memory. > > - Transfer (copy) of a block of data from remote memory to local memory. > > > > > > Currently, we have: > > https://github.com/torvalds/linux/blob/v6.13-rc5/include/linux/dmaengine.h#L843-L844 > > https://github.com/torvalds/linux/blob/v6.13-rc5/drivers/dma/dw-edma/dw-edma-core.c#L215-L231 > > > > Where we can expose per-channel capabilities, so we set MEM_TO_DEV/DEV_TO_MEM > > per channel, however, these are returned in a struct dma_slave_caps *caps, > > so this is AFAICT only for DMA_SLAVE, not for DMA_MEMCPY. > > > > Looking at: > > https://github.com/torvalds/linux/blob/v6.13-rc5/include/linux/dmaengine.h#L975-L979 > > it seems that DMA_MEMCPY is always assumed to be MEM_TO_MEM. > > > > To me, it seems that we would either need a new dma_transaction_type (e.g. DMA_COPY) > > where we can set dir: > > MEM_TO_DEV, DEV_TO_MEM, or DEV_TO_DEV. (dw-edma would not support DEV_TO_DEV.) > > > > Or, if we should stick with DMA_MEMCPY, we would need another way of telling > > client drivers that only src or dst can be a remote address. > > > > Until this is solved, I think I will stop my work on adding DMA_MEMCPY to the > > dw-edma driver. > > > > I think your concern is regarding setting the DMA transfer direction for MEMCPY, > right? And you are saying that even if we use tx/rx channels, currently we > cannot set DEV_TO_DEV like directions? > > But I'm somewhat confused about what is blocking you from adding MEMCPY support > to the dw-edma driver since that driver cannot support DEV_TO_DEV. In your WIP > driver, you were setting the direction based on the channel. Isn't that > sufficient enough? What I did in the WIP driver patches was to set the direction to either DEV_TO_MEM, or MEM_TO_DEV. But that is wrong, since the prep_memcpy() API doesn't take a direction. In fact, it appears that memcpy is always assumed to be MEM_TO_MEM: https://github.com/torvalds/linux/blob/v6.13-rc7/include/linux/dmaengine.h#L74 E.g. the dw-edma driver cannot have both src address and dst address as a local address (MEM_TO_MEM), so using DMA_MEMCPY API feels totally wrong. Either dst or src has to be a local address (MEM), and the one that isn't a local address has to be a PCI address (DEV). Sure, calling a PCI address DEV might not be 100% correct, but I cannot think of a better way... We also cannot treat a PCI address as MEM, as dw-edma cannot do PCI to PCI transfers. I think the best way forward would be to create a new _prep_slave_memcpy() or similar, that does take a direction, and thus does not require dmaengine_slave_config() to be called before every _prep_slave_memcpy() call, since that is basically what is not allowing us to have multiple transactions outstanding in parallel. Kind regards, Niklas
diff --git a/Documentation/PCI/endpoint/pci-test-howto.rst b/Documentation/PCI/endpoint/pci-test-howto.rst index c4ae7af50ede..3d664c279c80 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,58 @@ 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..11 + # Starting 11 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.CONSECUTIVE_BAR_TEST ... + # OK pci_ep_basic.CONSECUTIVE_BAR_TEST + ok 2 pci_ep_basic.CONSECUTIVE_BAR_TEST + # RUN pci_ep_basic.LEGACY_IRQ_TEST ... + # OK pci_ep_basic.LEGACY_IRQ_TEST + ok 3 pci_ep_basic.LEGACY_IRQ_TEST + # RUN pci_ep_basic.MSI_TEST ... + # OK pci_ep_basic.MSI_TEST + ok 4 pci_ep_basic.MSI_TEST + # RUN pci_ep_basic.MSIX_TEST ... + # OK pci_ep_basic.MSIX_TEST + ok 5 pci_ep_basic.MSIX_TEST + # RUN pci_ep_data_transfer.memcpy.READ_TEST ... + # OK pci_ep_data_transfer.memcpy.READ_TEST + ok 6 pci_ep_data_transfer.memcpy.READ_TEST + # RUN pci_ep_data_transfer.memcpy.WRITE_TEST ... + # OK pci_ep_data_transfer.memcpy.WRITE_TEST + ok 7 pci_ep_data_transfer.memcpy.WRITE_TEST + # RUN pci_ep_data_transfer.memcpy.COPY_TEST ... + # OK pci_ep_data_transfer.memcpy.COPY_TEST + ok 8 pci_ep_data_transfer.memcpy.COPY_TEST + # RUN pci_ep_data_transfer.dma.READ_TEST ... + # OK pci_ep_data_transfer.dma.READ_TEST + ok 9 pci_ep_data_transfer.dma.READ_TEST + # RUN pci_ep_data_transfer.dma.WRITE_TEST ... + # OK pci_ep_data_transfer.dma.WRITE_TEST + ok 10 pci_ep_data_transfer.dma.WRITE_TEST + # RUN pci_ep_data_transfer.dma.COPY_TEST ... + # OK pci_ep_data_transfer.dma.COPY_TEST + ok 11 pci_ep_data_transfer.dma.COPY_TEST + # PASSED: 11 / 11 tests passed. + # Totals: pass:11 fail:0 xfail:0 xpass:0 skip:0 error:0 + + +Testcase 11 (pci_ep_data_transfer.dma.COPY_TEST) will fail for most of the DMA +capable endpoint controllers due to the absence of the MEMCPY over DMA. For such +controllers, it is advisable to skip the forementioned testcase using below +command:: + + # pci_endpoint_test -f pci_ep_basic -v memcpy -T COPY_TEST -v dma diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 2401e973c359..50931cd6aff2 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 += pcie_bwctrl TARGETS += perf_events TARGETS += pidfd 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..964dfb80ff12 --- /dev/null +++ b/tools/testing/selftests/pci_endpoint/pci_endpoint_test.c @@ -0,0 +1,194 @@ +// 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, CONSECUTIVE_BAR_TEST) +{ + int ret; + + pci_ep_ioctl(PCITEST_BARS, 0); + EXPECT_FALSE(ret) TH_LOG("Consecutive BAR test failed"); +} + +TEST_F(pci_ep_basic, LEGACY_IRQ_TEST) +{ + int ret; + + pci_ep_ioctl(PCITEST_SET_IRQTYPE, 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 b96cc118839b..000000000000 --- a/tools/testing/selftests/pci_endpoint/pcitest.c +++ /dev/null @@ -1,265 +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 consecutive_bar_test; - 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->consecutive_bar_test) { - ret = ioctl(fd, PCITEST_BARS); - fprintf(stdout, "Consecutive BAR test:\t\t"); - 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%u:\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%u:\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 (%7lu 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 (%7lu 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 (%7lu 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:Cm: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 'C': - test->consecutive_bar_test = true; - 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-C Consecutive BAR test\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 770f4d6df34b..000000000000 --- a/tools/testing/selftests/pci_endpoint/pcitest.sh +++ /dev/null @@ -1,73 +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 -pcitest -C -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