Re: [PATCH v7 05/10] dmaengine: dw-edma: Add channel delegation helpers
Frank Li <[email protected]>
| Newsgroups | org.kernel.vger.dmaengine,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <an4W8hK3ZONZsVER@SMW015318> |
On Thu, Aug 13, 2026 at 03:37:52PM +0900, Koichiro Den wrote: > Endpoint functions that expose endpoint-local DesignWare eDMA channels > to a remote host need to reserve exact hardware channels and hand > interrupt ownership to the remote side before publishing the channels. > > Add DW eDMA-specific helpers that validate an idle, already reserved > channel and switch it to remote interrupt routing. The matching reclaim > helper can quiesce the channel while it is still remote-routed, then > restores the channel's default routing. The dmaengine channel reservation > remains with the caller. > > Reclaim is best-effort because its callers cannot abort teardown. Report > a quiesce failure locally, but always restore the default routing. > > Signed-off-by: Koichiro Den <[email protected]> > --- > Changes in v7: > - Leave dmaengine channel selection and lifetime management to the > endpoint function, per discussion with Frank on v6 patch 4. > > drivers/dma/dw-edma/dw-edma-core.c | 39 ++++++++++++++++++++++++++++++ > include/linux/dma/edma.h | 11 +++++++++ > 2 files changed, 50 insertions(+) After change to static id, needn't these private API. You can get expected channel and use dma_slave_config to config use DW_EDMA_CH_IRQ_REMOTE Frank > diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c > index d214df55da3c..1582ecfc2965 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; > + > + 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); > +} > +EXPORT_SYMBOL_GPL(dw_edma_reclaim_chan); > + > MODULE_LICENSE("GPL v2"); > MODULE_DESCRIPTION("Synopsys DesignWare eDMA controller core driver"); > MODULE_AUTHOR("Gustavo Pimentel <[email protected]>"); > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h > index 3c8e2ef9dee0..61ebb808981e 100644 > --- a/include/linux/dma/edma.h > +++ b/include/linux/dma/edma.h > @@ -153,6 +153,8 @@ struct dw_edma_chip { > #if IS_REACHABLE(CONFIG_DW_EDMA) > int dw_edma_probe(struct dw_edma_chip *chip); > int dw_edma_remove(struct dw_edma_chip *chip); > +int dw_edma_delegate_chan(struct dma_chan *chan); > +void dw_edma_reclaim_chan(struct dma_chan *chan, bool quiesce); > #else > static inline int dw_edma_probe(struct dw_edma_chip *chip) > { > @@ -163,6 +165,15 @@ static inline int dw_edma_remove(struct dw_edma_chip *chip) > { > return 0; > } > + > +static inline int dw_edma_delegate_chan(struct dma_chan *chan) > +{ > + return -ENODEV; > +} > + > +static inline void dw_edma_reclaim_chan(struct dma_chan *chan, bool quiesce) > +{ > +} > #endif /* CONFIG_DW_EDMA */ > > #endif /* _DW_EDMA_H */ > -- > 2.51.0 >