From cdfa3fbd8ad69d04867d7431ce216624efc0c6ca Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Fri, 6 Aug 2021 09:50:00 +0800 Subject: [PATCH] PCI: rockchip: add checksum for dma trx Change-Id: Ib51edd5527976a4aa66893937918911d9d1d20c1 Signed-off-by: Simon Xue --- drivers/pci/controller/rockchip-pcie-dma.c | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/pci/controller/rockchip-pcie-dma.c b/drivers/pci/controller/rockchip-pcie-dma.c index edcd58e9a710..68c720cdcab3 100644 --- a/drivers/pci/controller/rockchip-pcie-dma.c +++ b/drivers/pci/controller/rockchip-pcie-dma.c @@ -122,6 +122,7 @@ #define PCIE_DMA_SET_DATA_CHECK_POS (SZ_1M - 0x4) #define PCIE_DMA_SET_LOCAL_IDX_POS (SZ_1M - 0x8) #define PCIE_DMA_SET_BUF_SIZE_POS (SZ_1M - 0xc) +#define PCIE_DMA_SET_CHK_SUM_POS (SZ_1M - 0x10) #define PCIE_DMA_DATA_CHECK 0x12345678 #define PCIE_DMA_DATA_ACK_CHECK 0xdeadbeef @@ -130,6 +131,8 @@ #define PCIE_DMA_PARAM_SIZE 64 #define PCIE_DMA_CHN0 0x0 +static int enable_check_sum; + struct pcie_misc_dev { struct miscdevice dev; struct dma_trx_obj *obj; @@ -140,6 +143,18 @@ static inline bool is_rc(struct dma_trx_obj *obj) return (obj->busno == 0); } +static unsigned int rk_pcie_check_sum(unsigned int *src, int size) +{ + unsigned int result = 0; + + size /= sizeof(*src); + + while (size-- > 0) + result ^= *src++; + + return result; +} + static void rk_pcie_prepare_dma(struct dma_trx_obj *obj, unsigned int idx, unsigned int bus_idx, unsigned int local_idx, size_t buf_size, @@ -150,6 +165,7 @@ static void rk_pcie_prepare_dma(struct dma_trx_obj *obj, void *virt; unsigned long flags; struct dma_table *table = NULL; + unsigned int checksum; switch (type) { case PCIE_DMA_DATA_SND: @@ -171,6 +187,11 @@ static void rk_pcie_prepare_dma(struct dma_trx_obj *obj, writel(local_idx, virt + PCIE_DMA_SET_LOCAL_IDX_POS); writel(buf_size, virt + PCIE_DMA_SET_BUF_SIZE_POS); + if (enable_check_sum) { + checksum = rk_pcie_check_sum(virt, SZ_1M - 0x10); + writel(checksum, virt + PCIE_DMA_SET_CHK_SUM_POS); + } + buf_size = SZ_1M; break; case PCIE_DMA_DATA_RCV_ACK: @@ -275,6 +296,7 @@ static enum hrtimer_restart rk_pcie_scan_timer(struct hrtimer *timer) bool need_ack = false; struct dma_trx_obj *obj = container_of(timer, struct dma_trx_obj, scan_timer); + unsigned int check_sum, check_sum_tmp; for (i = 0; i < PCIE_DMA_BUF_CNT; i++) { sda_base = obj->mem_base + PCIE_DMA_BUF_SIZE * i; @@ -290,7 +312,19 @@ static enum hrtimer_restart rk_pcie_scan_timer(struct hrtimer *timer) if (sdv == PCIE_DMA_DATA_CHECK) { if (!need_ack) need_ack = true; + if (enable_check_sum) { + check_sum = readl(scan_data_addr + PCIE_DMA_SET_CHK_SUM_POS); + check_sum_tmp = rk_pcie_check_sum(scan_data_addr, SZ_1M - 0x10); + if (check_sum != check_sum_tmp) { + pr_err("checksum[%d] failed, 0x%x, should be 0x%x\n", + idx, check_sum_tmp, check_sum); + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, + 32, 4, scan_data_addr, SZ_1M, false); + } + writel(0x0, scan_data_addr + PCIE_DMA_SET_CHK_SUM_POS); + } writel(0x0, scan_data_addr + PCIE_DMA_SET_DATA_CHECK_POS); + set_bit(i, &obj->local_read_available); rk_pcie_prepare_dma(obj, idx, 0, 0, 0x4, PCIE_DMA_DATA_RCV_ACK); @@ -647,12 +681,25 @@ static int rk_pcie_debugfs_open(struct inode *inode, struct file *file) return single_open(file, rk_pcie_debugfs_trx_show, inode->i_private); } +static ssize_t rk_pcie_debugfs_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + int ret; + + ret = kstrtoint_from_user(user_buf, count, 0, &enable_check_sum); + if (ret) + return ret; + + return count; +} + static const struct file_operations rk_pcie_debugfs_fops = { .owner = THIS_MODULE, .open = rk_pcie_debugfs_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, + .write = rk_pcie_debugfs_write, }; #endif