From 49bb1dec112f4776fa9100d6c1df79cbf17169f5 Mon Sep 17 00:00:00 2001 From: Manikanta Maddireddy Date: Tue, 25 Jun 2024 14:12:07 +0000 Subject: [PATCH] PCI: EPF: dma-test: Add outbound ATU test function PCIe endpoint controller supports 8 outbound channels to map Root port address and access it as memory mapped IO. Add test function to verify this feature. Bug 4705051 Change-Id: I126e94619c581ed15f1d6db54845de209742af0e Signed-off-by: Manikanta Maddireddy Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3163953 GVS: buildbot_gerritrpt Reviewed-by: Bibek Basu Reviewed-by: Nagarjuna Kristam --- drivers/misc/tegra-pcie-dma-test.c | 2 + .../pci/endpoint/functions/pci-epf-dma-test.c | 56 +++++++++++++++++++ include/linux/tegra-pcie-edma-test-common.h | 4 ++ 3 files changed, 62 insertions(+) diff --git a/drivers/misc/tegra-pcie-dma-test.c b/drivers/misc/tegra-pcie-dma-test.c index eec13218..434d2df3 100644 --- a/drivers/misc/tegra-pcie-dma-test.c +++ b/drivers/misc/tegra-pcie-dma-test.c @@ -240,6 +240,8 @@ static int ep_test_dma_probe(struct pci_dev *pdev, const struct pci_device_id *i /* Update RP DMA system memory base address allocated with EP pci_dev in BAR0 */ epf_bar = (__force struct pcie_epf_bar *)ep->bar_virt; epf_bar->rp_phy_addr = ep->ep_dma_phy; + /* Assign OB magic number */ + *((u64 *)((u8 *)ep->ep_dma_virt + PCIE_EP_OB_OFFSET)) = PCIE_EP_OB_MAGIC; pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &val_16); if (val_16 & PCI_MSI_FLAGS_64BIT) { diff --git a/drivers/pci/endpoint/functions/pci-epf-dma-test.c b/drivers/pci/endpoint/functions/pci-epf-dma-test.c index f3b5bc51..3d9211d4 100644 --- a/drivers/pci/endpoint/functions/pci-epf-dma-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-dma-test.c @@ -114,11 +114,67 @@ static int edmalib_read_test(struct seq_file *s, void *data) return edmalib_common_test(&epfnv->edma); } +/* debugfs to perform EP outbound access */ +static int edmalib_test_ob(struct seq_file *s, void *data) +{ + struct pcie_epf_dma *epfnv = (struct pcie_epf_dma *)dev_get_drvdata(s->private); + struct pcie_epf_bar *epf_bar = (struct pcie_epf_bar *)epfnv->bar_virt; + struct pci_epc *epc = epfnv->epc; + void __iomem *dst_va[10] = { 0 }; + phys_addr_t dst_pci_addr[10] = { 0 }; + int i, ret; + + if (!epf_bar->rp_phy_addr) { + dev_err(epfnv->fdev, "RP DMA address is null\n"); + return -1; + } + + for (i = 0; i < 10; i++) { + dst_va[i] = pci_epc_mem_alloc_addr(epc, &dst_pci_addr[i], SZ_64K); + if (!dst_va[i]) { + dev_err(epfnv->fdev, "failed to allocate dst PCIe address, ob ch: %u\n", i); + break; + } + dev_dbg(epfnv->fdev, "Mapping %llx(EP) to %llx(RP) for size SZ_64K, ob ch: %d\n", + dst_pci_addr[i], epf_bar->rp_phy_addr, i); + + if (lpci_epc_map_addr(epc, 0, dst_pci_addr[i], epf_bar->rp_phy_addr, SZ_64K) < 0) { + dev_err(epfnv->fdev, "failed to map rp_phy_addr, ob ch: %d\n", i); + break; + } + if (*((u64 *) ((u8 *)dst_va[i] + PCIE_EP_OB_OFFSET)) != PCIE_EP_OB_MAGIC) { + dev_err(epfnv->fdev, "magic number: %llx is not matching, ob ch: %d\n", + *((u64 *) ((u8 *)dst_va[i] + PCIE_EP_OB_OFFSET)), i); + break; + } + } + + if (i == 8) { + dev_info(epfnv->fdev, "Eight outbound channel mapping success\n"); + ret = 0; + } else { + dev_info(epfnv->fdev, "Outbound channel mapping failed at ch: %d\n", i); + ret = -1; + } + + while (i >= 0) { + if (dst_pci_addr[i]) + lpci_epc_unmap_addr(epc, 0, dst_pci_addr[i]); + if (dst_va[i]) + pci_epc_mem_free_addr(epc, dst_pci_addr[i], dst_va[i], SZ_64K); + i--; + } + + return ret; +} + static void init_debugfs(struct pcie_epf_dma *epfnv) { debugfs_create_devm_seqfile(epfnv->fdev, "edmalib_test", epfnv->debugfs, edmalib_test); debugfs_create_devm_seqfile(epfnv->fdev, "edmalib_read_test", epfnv->debugfs, edmalib_read_test); + debugfs_create_devm_seqfile(epfnv->fdev, "edmalib_test_ob", epfnv->debugfs, + edmalib_test_ob); debugfs_create_u32("dma_size", 0644, epfnv->debugfs, &epfnv->dma_size); epfnv->dma_size = SZ_1M; diff --git a/include/linux/tegra-pcie-edma-test-common.h b/include/linux/tegra-pcie-edma-test-common.h index 6725845f..33b68d49 100644 --- a/include/linux/tegra-pcie-edma-test-common.h +++ b/include/linux/tegra-pcie-edma-test-common.h @@ -64,6 +64,10 @@ static inline void dma_common_wr(void __iomem *p, u32 val, u32 offset) /* DMA base offset starts at 0x20000 from ATU_DMA base */ #define DMA_OFFSET 0x20000 +/* Outbound magic number */ +#define PCIE_EP_OB_MAGIC 0xA5A519885A5A1984LU +#define PCIE_EP_OB_OFFSET SZ_16K + struct sanity_data { u32 size; u32 src_offset;