[PATCH 09/14] dmaengine: dma350: Support dma-channel-mask

Jisheng Zhang posted 14 patches 1 month, 1 week ago
[PATCH 09/14] dmaengine: dma350: Support dma-channel-mask
Posted by Jisheng Zhang 1 month, 1 week ago
Not all channels are available to kernel, we need to support
dma-channel-mask.

Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
---
 drivers/dma/arm-dma350.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
index 6a6d1c2a3ee6..72067518799e 100644
--- a/drivers/dma/arm-dma350.c
+++ b/drivers/dma/arm-dma350.c
@@ -534,7 +534,7 @@ static int d350_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct d350 *dmac;
 	void __iomem *base;
-	u32 reg;
+	u32 reg, dma_chan_mask;
 	int ret, nchan, dw, aw, r, p;
 	bool coherent, memset;
 
@@ -563,6 +563,15 @@ static int d350_probe(struct platform_device *pdev)
 
 	dmac->nchan = nchan;
 
+	/* Enable all channels by default */
+	dma_chan_mask = nchan - 1;
+
+	ret = of_property_read_u32(dev->of_node, "dma-channel-mask", &dma_chan_mask);
+	if (ret < 0 && (ret != -EINVAL)) {
+		dev_err(&pdev->dev, "dma-channel-mask is not complete.\n");
+		return ret;
+	}
+
 	reg = readl_relaxed(base + DMAINFO + DMA_BUILDCFG1);
 	dmac->nreq = FIELD_GET(DMA_CFG_NUM_TRIGGER_IN, reg);
 
@@ -592,6 +601,11 @@ static int d350_probe(struct platform_device *pdev)
 	memset = true;
 	for (int i = 0; i < nchan; i++) {
 		struct d350_chan *dch = &dmac->channels[i];
+		char ch_irqname[8];
+
+		/* skip for reserved channels */
+		if (!test_bit(i, (unsigned long *)&dma_chan_mask))
+			continue;
 
 		dch->coherent = coherent;
 		dch->base = base + DMACH(i);
@@ -602,7 +616,9 @@ static int d350_probe(struct platform_device *pdev)
 			dev_warn(dev, "No command link support on channel %d\n", i);
 			continue;
 		}
-		dch->irq = platform_get_irq(pdev, i);
+
+		snprintf(ch_irqname, sizeof(ch_irqname), "ch%d", i);
+		dch->irq = platform_get_irq_byname(pdev, ch_irqname);
 		if (dch->irq < 0)
 			return dch->irq;
 
-- 
2.50.0
Re: [PATCH 09/14] dmaengine: dma350: Support dma-channel-mask
Posted by kernel test robot 1 month, 1 week ago
Hi Jisheng,

kernel test robot noticed the following build warnings:

[auto build test WARNING on vkoul-dmaengine/next]
[also build test WARNING on robh/for-next linus/master v6.17-rc2 next-20250822]
[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/Jisheng-Zhang/dmaengine-dma350-Fix-CH_CTRL_USESRCTRIGIN-definition/20250824-000425
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next
patch link:    https://lore.kernel.org/r/20250823154009.25992-10-jszhang%40kernel.org
patch subject: [PATCH 09/14] dmaengine: dma350: Support dma-channel-mask
config: arm64-randconfig-002-20250824 (https://download.01.org/0day-ci/archive/20250824/202508241415.b7kiTLel-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250824/202508241415.b7kiTLel-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/202508241415.b7kiTLel-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/dma/arm-dma350.c: In function 'd350_probe':
>> drivers/dma/arm-dma350.c:620:61: warning: '%d' directive output may be truncated writing between 1 and 10 bytes into a region of size 6 [-Wformat-truncation=]
     620 |                 snprintf(ch_irqname, sizeof(ch_irqname), "ch%d", i);
         |                                                             ^~
   drivers/dma/arm-dma350.c:620:58: note: directive argument in the range [0, 2147483646]
     620 |                 snprintf(ch_irqname, sizeof(ch_irqname), "ch%d", i);
         |                                                          ^~~~~~
   drivers/dma/arm-dma350.c:620:17: note: 'snprintf' output between 4 and 13 bytes into a destination of size 8
     620 |                 snprintf(ch_irqname, sizeof(ch_irqname), "ch%d", i);
         |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +620 drivers/dma/arm-dma350.c

   531	
   532	static int d350_probe(struct platform_device *pdev)
   533	{
   534		struct device *dev = &pdev->dev;
   535		struct d350 *dmac;
   536		void __iomem *base;
   537		u32 reg, dma_chan_mask;
   538		int ret, nchan, dw, aw, r, p;
   539		bool coherent, memset;
   540	
   541		base = devm_platform_ioremap_resource(pdev, 0);
   542		if (IS_ERR(base))
   543			return PTR_ERR(base);
   544	
   545		reg = readl_relaxed(base + DMAINFO + IIDR);
   546		r = FIELD_GET(IIDR_VARIANT, reg);
   547		p = FIELD_GET(IIDR_REVISION, reg);
   548		if (FIELD_GET(IIDR_IMPLEMENTER, reg) != IMPLEMENTER_ARM ||
   549		    FIELD_GET(IIDR_PRODUCTID, reg) != PRODUCTID_DMA350)
   550			return dev_err_probe(dev, -ENODEV, "Not a DMA-350!");
   551	
   552		reg = readl_relaxed(base + DMAINFO + DMA_BUILDCFG0);
   553		nchan = FIELD_GET(DMA_CFG_NUM_CHANNELS, reg) + 1;
   554		dw = 1 << FIELD_GET(DMA_CFG_DATA_WIDTH, reg);
   555		aw = FIELD_GET(DMA_CFG_ADDR_WIDTH, reg) + 1;
   556	
   557		dma_set_mask_and_coherent(dev, DMA_BIT_MASK(aw));
   558		coherent = device_get_dma_attr(dev) == DEV_DMA_COHERENT;
   559	
   560		dmac = devm_kzalloc(dev, struct_size(dmac, channels, nchan), GFP_KERNEL);
   561		if (!dmac)
   562			return -ENOMEM;
   563	
   564		dmac->nchan = nchan;
   565	
   566		/* Enable all channels by default */
   567		dma_chan_mask = nchan - 1;
   568	
   569		ret = of_property_read_u32(dev->of_node, "dma-channel-mask", &dma_chan_mask);
   570		if (ret < 0 && (ret != -EINVAL)) {
   571			dev_err(&pdev->dev, "dma-channel-mask is not complete.\n");
   572			return ret;
   573		}
   574	
   575		reg = readl_relaxed(base + DMAINFO + DMA_BUILDCFG1);
   576		dmac->nreq = FIELD_GET(DMA_CFG_NUM_TRIGGER_IN, reg);
   577	
   578		dev_dbg(dev, "DMA-350 r%dp%d with %d channels, %d requests\n", r, p, dmac->nchan, dmac->nreq);
   579	
   580		dmac->dma.dev = dev;
   581		for (int i = min(dw, 16); i > 0; i /= 2) {
   582			dmac->dma.src_addr_widths |= BIT(i);
   583			dmac->dma.dst_addr_widths |= BIT(i);
   584		}
   585		dmac->dma.directions = BIT(DMA_MEM_TO_MEM);
   586		dmac->dma.descriptor_reuse = true;
   587		dmac->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
   588		dmac->dma.device_alloc_chan_resources = d350_alloc_chan_resources;
   589		dmac->dma.device_free_chan_resources = d350_free_chan_resources;
   590		dma_cap_set(DMA_MEMCPY, dmac->dma.cap_mask);
   591		dmac->dma.device_prep_dma_memcpy = d350_prep_memcpy;
   592		dmac->dma.device_pause = d350_pause;
   593		dmac->dma.device_resume = d350_resume;
   594		dmac->dma.device_terminate_all = d350_terminate_all;
   595		dmac->dma.device_synchronize = d350_synchronize;
   596		dmac->dma.device_tx_status = d350_tx_status;
   597		dmac->dma.device_issue_pending = d350_issue_pending;
   598		INIT_LIST_HEAD(&dmac->dma.channels);
   599	
   600		/* Would be nice to have per-channel caps for this... */
   601		memset = true;
   602		for (int i = 0; i < nchan; i++) {
   603			struct d350_chan *dch = &dmac->channels[i];
   604			char ch_irqname[8];
   605	
   606			/* skip for reserved channels */
   607			if (!test_bit(i, (unsigned long *)&dma_chan_mask))
   608				continue;
   609	
   610			dch->coherent = coherent;
   611			dch->base = base + DMACH(i);
   612			writel_relaxed(CH_CMD_CLEAR, dch->base + CH_CMD);
   613	
   614			reg = readl_relaxed(dch->base + CH_BUILDCFG1);
   615			if (!(FIELD_GET(CH_CFG_HAS_CMDLINK, reg))) {
   616				dev_warn(dev, "No command link support on channel %d\n", i);
   617				continue;
   618			}
   619	
 > 620			snprintf(ch_irqname, sizeof(ch_irqname), "ch%d", i);
   621			dch->irq = platform_get_irq_byname(pdev, ch_irqname);
   622			if (dch->irq < 0)
   623				return dch->irq;
   624	
   625			dch->has_wrap = FIELD_GET(CH_CFG_HAS_WRAP, reg);
   626			dch->has_trig = FIELD_GET(CH_CFG_HAS_TRIGIN, reg) &
   627					FIELD_GET(CH_CFG_HAS_TRIGSEL, reg);
   628	
   629			/* Fill is a special case of Wrap */
   630			memset &= dch->has_wrap;
   631	
   632			reg = readl_relaxed(dch->base + CH_BUILDCFG0);
   633			dch->tsz = FIELD_GET(CH_CFG_DATA_WIDTH, reg);
   634	
   635			reg = FIELD_PREP(CH_LINK_SHAREATTR, coherent ? SHAREATTR_ISH : SHAREATTR_OSH);
   636			reg |= FIELD_PREP(CH_LINK_MEMATTR, coherent ? MEMATTR_WB : MEMATTR_NC);
   637			writel_relaxed(reg, dch->base + CH_LINKATTR);
   638	
   639			dch->vc.desc_free = d350_desc_free;
   640			vchan_init(&dch->vc, &dmac->dma);
   641		}
   642	
   643		if (memset) {
   644			dma_cap_set(DMA_MEMSET, dmac->dma.cap_mask);
   645			dmac->dma.device_prep_dma_memset = d350_prep_memset;
   646		}
   647	
   648		platform_set_drvdata(pdev, dmac);
   649	
   650		ret = dmaenginem_async_device_register(&dmac->dma);
   651		if (ret)
   652			return dev_err_probe(dev, ret, "Failed to register DMA device\n");
   653	
   654		return of_dma_controller_register(dev->of_node, of_dma_xlate_by_chan_id, &dmac->dma);
   655	}
   656	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH 09/14] dmaengine: dma350: Support dma-channel-mask
Posted by Krzysztof Kozlowski 1 month, 1 week ago
On 23/08/2025 17:40, Jisheng Zhang wrote:
> Not all channels are available to kernel, we need to support
> dma-channel-mask.
> 
> Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
> ---
>  drivers/dma/arm-dma350.c | 20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c
> index 6a6d1c2a3ee6..72067518799e 100644
> --- a/drivers/dma/arm-dma350.c
> +++ b/drivers/dma/arm-dma350.c
> @@ -534,7 +534,7 @@ static int d350_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct d350 *dmac;
>  	void __iomem *base;
> -	u32 reg;
> +	u32 reg, dma_chan_mask;
>  	int ret, nchan, dw, aw, r, p;
>  	bool coherent, memset;
>  
> @@ -563,6 +563,15 @@ static int d350_probe(struct platform_device *pdev)
>  
>  	dmac->nchan = nchan;
>  
> +	/* Enable all channels by default */
> +	dma_chan_mask = nchan - 1;
> +
> +	ret = of_property_read_u32(dev->of_node, "dma-channel-mask", &dma_chan_mask);
> +	if (ret < 0 && (ret != -EINVAL)) {
> +		dev_err(&pdev->dev, "dma-channel-mask is not complete.\n");
> +		return ret;
> +	}
> +
>  	reg = readl_relaxed(base + DMAINFO + DMA_BUILDCFG1);
>  	dmac->nreq = FIELD_GET(DMA_CFG_NUM_TRIGGER_IN, reg);
>  
> @@ -592,6 +601,11 @@ static int d350_probe(struct platform_device *pdev)
>  	memset = true;
>  	for (int i = 0; i < nchan; i++) {
>  		struct d350_chan *dch = &dmac->channels[i];
> +		char ch_irqname[8];
> +
> +		/* skip for reserved channels */
> +		if (!test_bit(i, (unsigned long *)&dma_chan_mask))
> +			continue;
>  
>  		dch->coherent = coherent;
>  		dch->base = base + DMACH(i);
> @@ -602,7 +616,9 @@ static int d350_probe(struct platform_device *pdev)
>  			dev_warn(dev, "No command link support on channel %d\n", i);
>  			continue;
>  		}
> -		dch->irq = platform_get_irq(pdev, i);
> +
> +		snprintf(ch_irqname, sizeof(ch_irqname), "ch%d", i);
> +		dch->irq = platform_get_irq_byname(pdev, ch_irqname);

Actual ABI break.

That's a no-go, sorry. You cannot decide to break all users just because
"Not all channels are available to the kernel". That's really, really
incomplete ABI breakage reasoning.

See also writing bindings doc.

Best regards,
Krzysztof