[1/1] dmaengine: fsl-dma: fix DMA error when enabling sg if 'DONE' bit is set

Message ID 20230920203741.3184727-1-Frank.Li@nxp.com
State New
Headers
Series [1/1] dmaengine: fsl-dma: fix DMA error when enabling sg if 'DONE' bit is set |

Commit Message

Frank Li Sept. 20, 2023, 8:37 p.m. UTC
  In eDMAv3, clearing 'DONE' bit (bit 30) of CHn_CSR is required when
enabling scatter-gather (SG). eDMAv4 does not require this change.

Cc: <stable@vger.kernel.org>
Fixes: 72f5801a4e2b ("dmaengine: fsl-edma: integrate v3 support")
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/fsl-edma-common.c | 12 ++++++++++++
 drivers/dma/fsl-edma-common.h | 14 +++++++++++++-
 drivers/dma/fsl-edma-main.c   |  2 +-
 3 files changed, 26 insertions(+), 2 deletions(-)
  

Comments

kernel test robot Sept. 21, 2023, 9:54 a.m. UTC | #1
Hi Frank,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.6-rc2 next-20230921]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Frank-Li/dmaengine-fsl-dma-fix-DMA-error-when-enabling-sg-if-DONE-bit-is-set/20230921-043838
base:   linus/master
patch link:    https://lore.kernel.org/r/20230920203741.3184727-1-Frank.Li%40nxp.com
patch subject: [PATCH 1/1] dmaengine: fsl-dma: fix DMA error when enabling sg if 'DONE' bit is set
config: i386-randconfig-062-20230921 (https://download.01.org/0day-ci/archive/20230921/202309211717.aYksVles-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230921/202309211717.aYksVles-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309211717.aYksVles-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/dma/fsl-edma-common.c:76:15: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:93:9: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:96:17: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:98:15: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:100:9: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:125:19: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:131:17: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:134:9: sparse: sparse: cast removes address space '__iomem' of expression
>> drivers/dma/fsl-edma-common.c:463:21: sparse: sparse: restricted __le16 degrades to integer
   drivers/dma/fsl-edma-common.c:465:21: sparse: sparse: restricted __le16 degrades to integer
   drivers/dma/fsl-edma-common.c:466:17: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/dma/fsl-edma-common.c:466:17: sparse: sparse: cast removes address space '__iomem' of expression

vim +463 drivers/dma/fsl-edma-common.c

   422	
   423	static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
   424					  struct fsl_edma_hw_tcd *tcd)
   425	{
   426		u16 csr = 0;
   427	
   428		/*
   429		 * TCD parameters are stored in struct fsl_edma_hw_tcd in little
   430		 * endian format. However, we need to load the TCD registers in
   431		 * big- or little-endian obeying the eDMA engine model endian,
   432		 * and this is performed from specific edma_write functions
   433		 */
   434		edma_write_tcdreg(fsl_chan, 0, csr);
   435	
   436		edma_write_tcdreg(fsl_chan, tcd->saddr, saddr);
   437		edma_write_tcdreg(fsl_chan, tcd->daddr, daddr);
   438	
   439		edma_write_tcdreg(fsl_chan, tcd->attr, attr);
   440		edma_write_tcdreg(fsl_chan, tcd->soff, soff);
   441	
   442		edma_write_tcdreg(fsl_chan, tcd->nbytes, nbytes);
   443		edma_write_tcdreg(fsl_chan, tcd->slast, slast);
   444	
   445		edma_write_tcdreg(fsl_chan, tcd->citer, citer);
   446		edma_write_tcdreg(fsl_chan, tcd->biter, biter);
   447		edma_write_tcdreg(fsl_chan, tcd->doff, doff);
   448	
   449		edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga);
   450	
   451		if (fsl_chan->is_sw) {
   452			csr = le16_to_cpu(tcd->csr);
   453			csr |= EDMA_TCD_CSR_START;
   454			tcd->csr = cpu_to_le16(csr);
   455		}
   456	
   457		/*
   458		 * Must clear CHn_CSR[DONE] bit before enable TCDn_CSR[ESG] at EDMAv3
   459		 * eDMAv4 have not such requirement.
   460		 * Change MLINK need clear CHn_CSR[DONE] for both eDMAv3 and eDMAv4.
   461		 */
   462		if (((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_SG) &&
 > 463			(tcd->csr & EDMA_TCD_CSR_E_SG)) ||
   464		    ((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_LINK) &&
   465			(tcd->csr & EDMA_TCD_CSR_E_LINK)))
   466			edma_writel_chreg(fsl_chan, edma_readl_chreg(fsl_chan, ch_csr), ch_csr);
   467	
   468	
   469		edma_write_tcdreg(fsl_chan, tcd->csr, csr);
   470	}
   471
  

Patch

diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index 70e24e76d73b6..2b834502e30a5 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -460,6 +460,18 @@  static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
 		tcd->csr = cpu_to_le16(csr);
 	}
 
+	/*
+	 * Must clear CHn_CSR[DONE] bit before enable TCDn_CSR[ESG] at EDMAv3
+	 * eDMAv4 have not such requirement.
+	 * Change MLINK need clear CHn_CSR[DONE] for both eDMAv3 and eDMAv4.
+	 */
+	if (((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_SG) &&
+		(tcd->csr & EDMA_TCD_CSR_E_SG)) ||
+	    ((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_LINK) &&
+		(tcd->csr & EDMA_TCD_CSR_E_LINK)))
+		edma_writel_chreg(fsl_chan, edma_readl_chreg(fsl_chan, ch_csr), ch_csr);
+
+
 	edma_write_tcdreg(fsl_chan, tcd->csr, csr);
 }
 
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index a9e27110ac7d7..6a74bf9facaa0 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -183,11 +183,23 @@  struct fsl_edma_desc {
 #define FSL_EDMA_DRV_BUS_8BYTE		BIT(10)
 #define FSL_EDMA_DRV_DEV_TO_DEV		BIT(11)
 #define FSL_EDMA_DRV_ALIGN_64BYTE	BIT(12)
+/* Need clean CHn_CSR DONE before enable TCD's ESG */
+#define FSL_EDMA_DRV_CLEAR_DONE_E_SG	BIT(13)
+/* Need clean CHn_CSR DONE before enable TCD's MAJORELINK */
+#define FSL_EDMA_DRV_CLEAR_DONE_E_LINK	BIT(14)
 
 #define FSL_EDMA_DRV_EDMA3	(FSL_EDMA_DRV_SPLIT_REG |	\
 				 FSL_EDMA_DRV_BUS_8BYTE |	\
 				 FSL_EDMA_DRV_DEV_TO_DEV |	\
-				 FSL_EDMA_DRV_ALIGN_64BYTE)
+				 FSL_EDMA_DRV_ALIGN_64BYTE |	\
+				 FSL_EDMA_DRV_CLEAR_DONE_E_SG |	\
+				 FSL_EDMA_DRV_CLEAR_DONE_E_LINK)
+
+#define FSL_EDMA_DRV_EDMA4	(FSL_EDMA_DRV_SPLIT_REG |	\
+				 FSL_EDMA_DRV_BUS_8BYTE |	\
+				 FSL_EDMA_DRV_DEV_TO_DEV |	\
+				 FSL_EDMA_DRV_ALIGN_64BYTE |	\
+				 FSL_EDMA_DRV_CLEAR_DONE_E_LINK)
 
 struct fsl_edma_drvdata {
 	u32			dmamuxs; /* only used before v3 */
diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
index 2c20460e53aa9..4f8312b64f144 100644
--- a/drivers/dma/fsl-edma-main.c
+++ b/drivers/dma/fsl-edma-main.c
@@ -357,7 +357,7 @@  static struct fsl_edma_drvdata imx93_data3 = {
 };
 
 static struct fsl_edma_drvdata imx93_data4 = {
-	.flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3,
+	.flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4,
 	.chreg_space_sz = 0x8000,
 	.chreg_off = 0x10000,
 	.setup_irq = fsl_edma3_irq_init,