Re: [PATCH v7 05/10] dmaengine: dw-edma: Add channel delegation helpers

[email protected]
Newsgroups org.kernel.vger.dmaengine,org.kernel.vger.linux-pci
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Data race on `chan->irq_mode` between channel delegation/reclaim and the hardirq handler.
--

--- Patch [5]: [PATCH v7 05/10] dmaengine: dw-edma: Add channel delegation helpers ---
commit ada234f341417a6397309d554f4e6b955a5ce106
Author: Koichiro Den <[email protected]>

dmaengine: dw-edma: Add channel delegation helpers

This commit introduces helper functions to delegate endpoint-local
DesignWare eDMA channels to a remote host. It adds dw_edma_delegate_chan()
to switch an idle channel to remote interrupt routing, and
dw_edma_reclaim_chan() to restore the channel's default routing.

> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index d214df55da3c3..1582ecfc2965f 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c
[ ... ]
> @@ -1303,6 +1303,45 @@ int dw_edma_remove(struct dw_edma_chip *chip)
>  }
>  EXPORT_SYMBOL_GPL(dw_edma_remove);
>  
> +int dw_edma_delegate_chan(struct dma_chan *dchan)
> +{
> +	struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
> +	int ret = 0;
> +
> +	if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
> +		return -EINVAL;
> +
> +	guard(spinlock_irqsave)(&chan->vc.lock);
> +
> +	if (chan->configured || chan->status != EDMA_ST_IDLE ||
> +	    chan->request != EDMA_REQ_NONE)
> +		ret = -EBUSY;
> +	else
> +		chan->irq_mode = DW_EDMA_CH_IRQ_REMOTE;

[Severity: Medium]
Does this introduce a data race on chan->irq_mode?

The irq_mode is updated here using a plain store while chan->vc.lock is held,
but it appears to be read locklessly during interrupt handling:

drivers/dma/dw-edma/dw-edma-core.h:dw_edma_core_ch_ignore_irq() {
    return chan->irq_mode == DW_EDMA_CH_IRQ_REMOTE;
}

Could the compiler optimize or tear these plain accesses, potentially causing
the interrupt handler to incorrectly ignore or process a spurious interrupt,
or trigger KCSAN warnings? Would using WRITE_ONCE() and READ_ONCE() be
appropriate here?

> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(dw_edma_delegate_chan);
> +
> +void dw_edma_reclaim_chan(struct dma_chan *dchan, bool quiesce)
> +{
> +	struct dw_edma_chan *chan;
> +
> +	if (!dchan)
> +		return;
> +
> +	chan = dchan2dw_edma_chan(dchan);
> +	if (quiesce && dw_edma_core_ch_quiesce(chan))
> +		dev_warn(chan->dw->chip->dev,
> +			 "failed to quiesce delegated %s channel %u\n",
> +			 chan->dir == EDMA_DIR_WRITE ? "write" : "read",
> +			 chan->id);
> +
> +	scoped_guard(spinlock_irqsave, &chan->vc.lock)
> +		chan->irq_mode = dw_edma_get_default_irq_mode(chan);

[Severity: Medium]
Similarly, does this plain store also race with the lockless read in
dw_edma_core_ch_ignore_irq()?

> +}
> +EXPORT_SYMBOL_GPL(dw_edma_reclaim_chan);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.