PCI: Add data integrity check for PCIe DMA

Add CRC check after PCIe DMA to verify data integrity.

Bug 3636902
Bug 3868928

Change-Id: If497ce769571c6c837acbfbbb64b2242dfabef26
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2718787
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2720336
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2815927
Reviewed-by: Nagarjuna Kristam <nkristam@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Tested-by: Nagarjuna Kristam <nkristam@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Manikanta Maddireddy
2022-05-26 18:03:48 +05:30
committed by mobile promotions
parent b26885400f
commit 319fa69bd5
3 changed files with 71 additions and 14 deletions

View File

@@ -14,6 +14,7 @@
#define EDMA_ABORT_TEST_EN (edma->edma_ch & 0x40000000)
#define EDMA_STOP_TEST_EN (edma->edma_ch & 0x20000000)
#define EDMA_CRC_TEST_EN (edma->edma_ch & 0x10000000)
#define IS_EDMA_CH_ENABLED(i) (edma->edma_ch & ((BIT(i) << 4)))
#define IS_EDMA_CH_ASYNC(i) (edma->edma_ch & BIT(i))
#define REMOTE_EDMA_TEST_EN (edma->edma_ch & 0x80000000)
@@ -26,7 +27,9 @@
struct edmalib_common {
struct device *fdev;
void *bar0_virt;
void (*raise_irq)(void *p);
void *priv;
struct pcie_epf_bar0 *epf_bar0;
void *src_virt;
void __iomem *dma_base;
u32 dma_size;
@@ -114,6 +117,7 @@ static int edmalib_common_test(struct edmalib_common *edma)
char *xfer_str[2] = {"WR", "RD"};
u32 l_r;
char *l_r_str[2] = {"local", "remote"};
struct pcie_epf_bar0 *epf_bar0 = edma->epf_bar0;
if (!edma->stress_count) {
tegra_pcie_edma_deinit(edma->cookie);
@@ -129,6 +133,16 @@ static int edmalib_common_test(struct edmalib_common *edma)
edma->edma_ch |= 0xF5;
}
if (EDMA_CRC_TEST_EN) {
/* 4 channels in sync mode */
edma->edma_ch = (EDMA_CRC_TEST_EN | 0xF0);
/* Single SZ_4K packet on each channel, so total SZ_16K of data */
edma->stress_count = 1;
edma->dma_size = SZ_4K;
edma->nents = nents = 4;
epf_bar0->wr_data[0].size = edma->dma_size * edma->nents;
}
if (edma->cookie && edma->prev_edma_ch != edma->edma_ch) {
edma->st_as_ch = -1;
dev_info(edma->fdev, "edma_ch changed from 0x%x != 0x%x, deinit\n",
@@ -291,6 +305,19 @@ static int edmalib_common_test(struct edmalib_common *edma)
edma->tsz, diff, EDMA_PERF);
}
}
if (EDMA_CRC_TEST_EN && !REMOTE_EDMA_TEST_EN) {
u32 crc;
edma->raise_irq(edma->priv);
crc = crc32_le(~0, edma->src_virt, epf_bar0->wr_data[0].size);
msleep(100);
if (crc != epf_bar0->wr_data[0].crc)
dev_err(edma->fdev, "CRC check failed, LCRC: 0x%x RCRC: 0x%x\n",
crc, epf_bar0->wr_data[0].crc);
else
dev_err(edma->fdev, "CRC check pass\n");
}
dev_info(edma->fdev, "%s: EDMA LIB submit done\n", __func__);
return 0;