From: Frank Li <Frank.li@oss.nxp.com>
To: Koichiro Den <den@valinux.co.jp>
Cc: Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>,
Manivannan Sadhasivam <mani@kernel.org>,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/3] dmaengine: dw-edma: Configure remote interrupt routing
Date: Fri, 28 Aug 2026 13:41:57 -0500 [thread overview]
Message-ID: <apHWdSznP88op0i9@SMW015318> (raw)
In-Reply-To: <20260828163611.2691264-3-den@valinux.co.jp>
On Sat, Aug 29, 2026 at 01:36:10AM +0900, Koichiro Den wrote:
> An endpoint function can reserve an endpoint-local channel while the RC
> programs it through an exposed register window. Such a channel must route
> interrupts remotely and ignore them on the endpoint.
>
> Use dma_slave_config to set enum dw_edma_ch_irq_mode on idle channels of a
> local eDMA-compatible instance. Synchronizing a remote-routed channel
> quiesces the hardware, after which the caller can restore its routing and
> release it.
>
> The eDMA quiesce may stop a complete direction. The caller must own every
> channel in that direction and stop remote programming first.
>
> Suggested-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> Changes in v2:
> - Rework the channel routing from PCI DMA EPF v7 patches 5 and 6.
> https://lore.kernel.org/r/20260813063757.3131865-6-den@valinux.co.jp/
> https://lore.kernel.org/r/20260813063757.3131865-7-den@valinux.co.jp/
> - Use dma_slave_config instead of private delegation helpers. (Frank)
> https://lore.kernel.org/r/ao2nHoCwfTEEiFSr@SMW015318/
>
> drivers/dma/dw-edma/dw-edma-core.c | 51 +++++++++++++++++++++++++++---
> include/linux/dma/edma.h | 6 ++++
> 2 files changed, 52 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index a678c70a78fe..a8c6bd508fcd 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c
> @@ -177,6 +177,30 @@ dw_edma_get_default_irq_mode(struct dw_edma_chan *chan)
> DW_EDMA_CH_IRQ_REMOTE;
> }
>
> +static int dw_edma_device_config_irq_mode(struct dw_edma_chan *chan,
> + struct dma_slave_config *config)
> +{
> + enum dw_edma_ch_irq_mode mode;
> +
> + if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) ||
> + config->peripheral_size != sizeof(mode))
> + return -EINVAL;
> +
> + mode = *(enum dw_edma_ch_irq_mode *)config->peripheral_config;
existing code use peripheral_config indicate non_ll mode, is it compatible
with irq mode?
Frank
> + if (mode != DW_EDMA_CH_IRQ_LOCAL && mode != DW_EDMA_CH_IRQ_REMOTE)
> + return -EINVAL;
> +
> + guard(spinlock_irqsave)(&chan->vc.lock);
> +
> + if (chan->configured || chan->status != EDMA_ST_IDLE ||
> + chan->request != EDMA_REQ_NONE)
> + return -EBUSY;
> +
> + chan->irq_mode = mode;
> +
> + return 0;
> +}
> +
> static int dw_edma_device_config(struct dma_chan *dchan,
> struct dma_slave_config *config)
> {
> @@ -184,6 +208,10 @@ static int dw_edma_device_config(struct dma_chan *dchan,
> bool cfg_non_ll;
> int non_ll = 0;
>
> + if (chan->dw->chip->mf != EDMA_MF_HDMA_NATIVE &&
> + config->peripheral_config)
> + return dw_edma_device_config_irq_mode(chan, config);
> +
> chan->non_ll = false;
> if (chan->dw->chip->mf == EDMA_MF_HDMA_NATIVE) {
> if (config->peripheral_config &&
> @@ -213,10 +241,6 @@ static int dw_edma_device_config(struct dma_chan *dchan,
>
> if (cfg_non_ll || non_ll)
> chan->non_ll = true;
> - } else if (config->peripheral_config) {
> - dev_err(dchan->device->dev,
> - "peripheral config param applicable only for HDMA\n");
> - return -EINVAL;
> }
>
> memcpy(&chan->config, config, sizeof(*config));
> @@ -893,6 +917,17 @@ static void dw_edma_wait_termination(struct dma_chan *dchan)
> static void dw_edma_device_synchronize(struct dma_chan *dchan)
> {
> struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
> + bool remote;
> +
> + scoped_guard(spinlock_irqsave, &chan->vc.lock)
> + remote = chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL &&
> + chan->irq_mode == DW_EDMA_CH_IRQ_REMOTE;
> +
> + if (remote && dw_edma_core_ch_quiesce(chan))
> + dev_warn(chan->dw->chip->dev,
> + "failed to quiesce remote-routed %s channel %u\n",
> + chan->dir == EDMA_DIR_WRITE ? "write" : "read",
> + chan->id);
>
> dw_edma_wait_termination(dchan);
> cancel_work_sync(&chan->irq_work);
> @@ -903,12 +938,18 @@ static void dw_edma_device_synchronize(struct dma_chan *dchan)
> static void dw_edma_free_chan_resources(struct dma_chan *dchan)
> {
> struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
> + enum dw_edma_ch_irq_mode default_mode =
> + dw_edma_get_default_irq_mode(chan);
>
> dw_edma_device_terminate_all(dchan);
> dw_edma_device_synchronize(dchan);
>
> - scoped_guard(spinlock_irqsave, &chan->vc.lock)
> + scoped_guard(spinlock_irqsave, &chan->vc.lock) {
> chan->configured = false;
> + /* Avoid a redundant write racing with shared-IRQ readers. */
> + if (chan->irq_mode != default_mode)
> + chan->irq_mode = default_mode;
> + }
>
> vchan_free_chan_resources(&chan->vc);
> }
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index 3c8e2ef9dee0..54491c9e4b5e 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -92,6 +92,12 @@ enum dw_edma_chip_flags {
> * handed over to and driven by the remote side, and the recipe above is
> * applied by the driving instance.
> *
> + * On a local eDMA-compatible instance, clients may pass this enum through
> + * dma_slave_config.peripheral_config to switch an idle, unconfigured channel
> + * between LOCAL and REMOTE routing. Before synchronizing a REMOTE channel,
> + * the client must stop remote programming and own every channel affected by
> + * the hardware quiesce.
> + *
> * HDMA linked-list watermark interrupts have the same LWIE/RWIE guidance. HDMA
> * non-linked-list mode has dedicated local and remote stop/abort interrupt
> * enables.
> --
> 2.51.0
>
next prev parent reply other threads:[~2026-08-28 18:42 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-28 16:36 [PATCH v2 0/3] dmaengine: dw-edma: Prepare channels for remote use Koichiro Den
2026-08-28 16:36 ` [PATCH v2 1/3] dmaengine: Allow drivers to assign static channel IDs Koichiro Den
2026-08-28 16:55 ` sashiko-bot
2026-08-28 16:36 ` [PATCH v2 2/3] dmaengine: dw-edma: Configure remote interrupt routing Koichiro Den
2026-08-28 16:49 ` sashiko-bot
2026-08-28 18:41 ` Frank Li [this message]
2026-08-29 18:13 ` Koichiro Den
2026-08-31 15:55 ` Frank Li
2026-08-28 16:36 ` [PATCH v2 3/3] dmaengine: dw-edma: Account for the MSI vector offset Koichiro Den
2026-08-28 18:46 ` Frank Li
2026-08-29 17:43 ` Koichiro Den
2026-08-31 16:02 ` Frank Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=apHWdSznP88op0i9@SMW015318 \
--to=frank.li@oss.nxp.com \
--cc=Frank.Li@kernel.org \
--cc=den@valinux.co.jp \
--cc=dmaengine@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mani@kernel.org \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.