All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frank Li <Frank.li@oss.nxp.com>
To: Koichiro Den <den@valinux.co.jp>
Cc: Manivannan Sadhasivam <mani@kernel.org>,
	Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>,
	Cai Huoqing <cai.huoqing@linux.dev>,
	Serge Semin <fancer.lancer@gmail.com>,
	Gustavo Pimentel <Gustavo.Pimentel@synopsys.com>,
	Devendra K Verma <devendra.verma@amd.com>,
	dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 6/7] dmaengine: dw-edma: Snapshot the v0 interrupt status once per handler pass
Date: Sat, 11 Jul 2026 09:44:54 -0500	[thread overview]
Message-ID: <alJW5hjfWklqPgzf@SMW015318> (raw)
In-Reply-To: <20260710080903.2392888-7-den@valinux.co.jp>

On Fri, Jul 10, 2026 at 05:09:02PM +0900, Koichiro Den wrote:
> The v0 interrupt handler reads the interrupt status register twice per
> invocation, once through the DONE accessor and once through the ABORT
> accessor, although both fields live in the same 32-bit register. On
> remote setups (dw-edma-pcie) each read is a non-posted round trip across
> the PCIe link costing on the order of a microsecond, and with one
> completion interrupt per element the duplicate adds up. As an example,
> profiling the R-Car S4 remote path put the handler at ~7us per
> invocation, dominated by such reads.
>
> Read the register once and derive the DONE and ABORT views from the
> snapshot. No abort is lost to this because the pass only clears status
> bits it observed, so an abort raised after the snapshot keeps its status
> and its own interrupt delivery brings it to the next pass. A second
> abort on an observed channel cannot race the clear either, as an aborted
> channel stays halted until software restarts it, and any restart follows
> the abort() handling, which comes after
> dw_edma_v0_core_clear_abort_int().
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes in v2:
>   - New patch in v2, posted as part of this preparation series.
>
>  drivers/dma/dw-edma/dw-edma-v0-core.c | 28 +++++++++++++--------------
>  1 file changed, 13 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> index cfdd6463252e..377812eaa110 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> @@ -218,18 +218,6 @@ static void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
>  		  FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
>  }
>
> -static u32 dw_edma_v0_core_status_done_int(struct dw_edma *dw, enum dw_edma_dir dir)
> -{
> -	return FIELD_GET(EDMA_V0_DONE_INT_MASK,
> -			 GET_RW_32(dw, dir, int_status));
> -}
> -
> -static u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
> -{
> -	return FIELD_GET(EDMA_V0_ABORT_INT_MASK,
> -			 GET_RW_32(dw, dir, int_status));
> -}
> -
>  static irqreturn_t
>  dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
>  			   dw_edma_handler_t done, dw_edma_handler_t abort)
> @@ -239,7 +227,7 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
>  	irqreturn_t ret = IRQ_NONE;
>  	struct dw_edma_chan *chan;
>  	unsigned long off;
> -	u32 mask;
> +	u32 mask, sts;
>
>  	if (dir == EDMA_DIR_WRITE) {
>  		total = dw->wr_ch_cnt;
> @@ -251,7 +239,17 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
>  		mask = dw_irq->rd_mask;
>  	}
>
> -	val = dw_edma_v0_core_status_done_int(dw, dir);
> +	/*
> +	 * DONE and ABORT status share one register, and on remote setups
> +	 * every read is a non-posted round trip across the PCIe link. Take
> +	 * one snapshot and derive both views from it. An abort raised
> +	 * after the snapshot is deferred, not lost: only bits observed in
> +	 * the snapshot are ever cleared below, so its status survives for
> +	 * the next invocation, which its own interrupt delivery triggers.
> +	 */
> +	sts = GET_RW_32(dw, dir, int_status);
> +
> +	val = FIELD_GET(EDMA_V0_DONE_INT_MASK, sts);
>  	val &= mask;
>  	for_each_set_bit(pos, &val, total) {
>  		chan = &dw->chan[pos + off];
> @@ -262,7 +260,7 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
>  		ret = IRQ_HANDLED;
>  	}
>
> -	val = dw_edma_v0_core_status_abort_int(dw, dir);
> +	val = FIELD_GET(EDMA_V0_ABORT_INT_MASK, sts);
>  	val &= mask;
>  	for_each_set_bit(pos, &val, total) {
>  		chan = &dw->chan[pos + off];
> --
> 2.51.0
>

  reply	other threads:[~2026-07-11 14:45 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-10  8:08 [PATCH 0/7] dmaengine: dw-edma: Fixes and interrupt-path groundwork Koichiro Den
2026-07-10  8:08 ` [PATCH 1/7] dmaengine: dw-edma: Fix HDMA channel status register access Koichiro Den
2026-07-10  8:19   ` sashiko-bot
2026-07-10 21:26   ` Frank Li
2026-07-13  5:17     ` Koichiro Den
2026-07-10  8:08 ` [PATCH 2/7] dmaengine: dw-edma: Terminate STOP requests without callbacks Koichiro Den
2026-07-10  8:26   ` sashiko-bot
2026-07-11 14:27   ` Frank Li
2026-07-10  8:08 ` [PATCH 3/7] dmaengine: dw-edma: Clean up vchan descriptors on termination Koichiro Den
2026-07-10  8:24   ` sashiko-bot
2026-07-11 14:39   ` Frank Li
2026-07-10  8:09 ` [PATCH 4/7] dmaengine: dw-edma: Serialize channel state checks Koichiro Den
2026-07-10  8:28   ` sashiko-bot
2026-07-10  8:09 ` [PATCH 5/7] dmaengine: dw-edma-pcie: Drop redundant pci_free_irq_vectors() Koichiro Den
2026-07-11 14:41   ` Frank Li
2026-07-10  8:09 ` [PATCH 6/7] dmaengine: dw-edma: Snapshot the v0 interrupt status once per handler pass Koichiro Den
2026-07-11 14:44   ` Frank Li [this message]
2026-07-10  8:09 ` [PATCH 7/7] dmaengine: dw-edma: Defer channel IRQ handling to workqueue Koichiro Den
2026-07-10  8:24   ` sashiko-bot
2026-07-11 14:55   ` 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=alJW5hjfWklqPgzf@SMW015318 \
    --to=frank.li@oss.nxp.com \
    --cc=Frank.Li@kernel.org \
    --cc=Gustavo.Pimentel@synopsys.com \
    --cc=cai.huoqing@linux.dev \
    --cc=den@valinux.co.jp \
    --cc=devendra.verma@amd.com \
    --cc=dmaengine@vger.kernel.org \
    --cc=fancer.lancer@gmail.com \
    --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.