From: Koichiro Den <den@valinux.co.jp>
To: Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>,
Manivannan Sadhasivam <mani@kernel.org>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>,
Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v4 03/14] dmaengine: dw-edma: Add core quiesce operations
Date: Fri, 10 Jul 2026 17:15:07 +0900 [thread overview]
Message-ID: <20260710081518.2394357-4-den@valinux.co.jp> (raw)
In-Reply-To: <20260710081518.2394357-1-den@valinux.co.jp>
Add core operations that quiesce only the resources represented by a
dw-edma instance, separate from the existing full controller off path.
For v0 eDMA and HDMA compatible register layouts, quiescing one channel
must quiesce the whole direction because the enable and interrupt
mask/clear registers are direction-wide. For HDMA native, the operation
can quiesce the represented per-channel registers directly.
No caller is added yet, so this is a no-functional-change preparation
for delegated channel reclaim and partial-owned remove paths.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v4:
- Mask and disable v0 eDMA/HDMA channels before clearing interrupt
status, so quiesce drains status raised during disable and avoids
stale DONE/ABORT/STOP bits firing on a later re-enable.
- Drop R-b tag due to the change. @Frank, please take another look.
- Document at the v0 ch_quiesce() implementation that quiescing is
direction-wide and callers must own the whole direction.
drivers/dma/dw-edma/dw-edma-core.h | 14 +++++++++++
drivers/dma/dw-edma/dw-edma-v0-core.c | 34 +++++++++++++++++++++++++++
drivers/dma/dw-edma/dw-hdma-v0-core.c | 28 ++++++++++++++++++++++
3 files changed, 76 insertions(+)
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index 3ea384706b1b..8657275d2484 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -134,6 +134,8 @@ typedef void (*dw_edma_handler_t)(struct dw_edma_chan *);
struct dw_edma_core_ops {
void (*off)(struct dw_edma *dw);
+ void (*quiesce)(struct dw_edma *dw);
+ void (*ch_quiesce)(struct dw_edma_chan *chan);
u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir);
enum dma_status (*ch_status)(struct dw_edma_chan *chan);
irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
@@ -186,6 +188,18 @@ void dw_edma_core_off(struct dw_edma *dw)
dw->core->off(dw);
}
+static inline
+void dw_edma_core_quiesce(struct dw_edma *dw)
+{
+ dw->core->quiesce(dw);
+}
+
+static inline
+void dw_edma_core_ch_quiesce(struct dw_edma_chan *chan)
+{
+ chan->dw->core->ch_quiesce(chan);
+}
+
static inline
u16 dw_edma_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
{
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 14700ac42fa8..32df5d13ba8b 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -160,6 +160,20 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
readl_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name))
/* eDMA management callbacks */
+static void dw_edma_v0_core_dir_off(struct dw_edma *dw, enum dw_edma_dir dir)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&dw->lock, flags);
+ SET_RW_32(dw, dir, int_mask,
+ EDMA_V0_DONE_INT_MASK | EDMA_V0_ABORT_INT_MASK);
+ raw_spin_unlock_irqrestore(&dw->lock, flags);
+
+ SET_RW_32(dw, dir, engine_en, 0);
+ SET_RW_32(dw, dir, int_clear,
+ EDMA_V0_DONE_INT_MASK | EDMA_V0_ABORT_INT_MASK);
+}
+
static void dw_edma_v0_core_off(struct dw_edma *dw)
{
SET_BOTH_32(dw, int_mask,
@@ -169,6 +183,24 @@ static void dw_edma_v0_core_off(struct dw_edma *dw)
SET_BOTH_32(dw, engine_en, 0);
}
+static void dw_edma_v0_core_quiesce(struct dw_edma *dw)
+{
+ if (dw->wr_ch_cnt)
+ dw_edma_v0_core_dir_off(dw, EDMA_DIR_WRITE);
+ if (dw->rd_ch_cnt)
+ dw_edma_v0_core_dir_off(dw, EDMA_DIR_READ);
+}
+
+/*
+ * The v0 register layout shares interrupt control per direction, so the
+ * whole direction is quiesced. Callers must own the direction entirely;
+ * partial ownership mode validates direction granularity for this layout.
+ */
+static void dw_edma_v0_core_ch_quiesce(struct dw_edma_chan *chan)
+{
+ dw_edma_v0_core_dir_off(chan->dw, chan->dir);
+}
+
static u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
{
u32 num_ch;
@@ -554,6 +586,8 @@ static resource_size_t dw_edma_v0_core_db_offset(struct dw_edma *dw)
static const struct dw_edma_core_ops dw_edma_v0_core = {
.off = dw_edma_v0_core_off,
+ .quiesce = dw_edma_v0_core_quiesce,
+ .ch_quiesce = dw_edma_v0_core_ch_quiesce,
.ch_count = dw_edma_v0_core_ch_count,
.ch_status = dw_edma_v0_core_ch_status,
.handle_int = dw_edma_v0_core_handle_int,
diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c
index cc908ca24061..be22f9f811ca 100644
--- a/drivers/dma/dw-edma/dw-hdma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c
@@ -73,6 +73,17 @@ static u32 dw_hdma_v0_core_int_setup(struct dw_edma_chan *chan, u32 val)
HDMA_V0_LOCAL_STOP_INT_EN;
}
+/* HDMA management callbacks */
+static void dw_hdma_v0_core_ch_off(struct dw_edma *dw, enum dw_edma_dir dir,
+ u16 id)
+{
+ SET_CH_32(dw, dir, id, int_setup,
+ HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK);
+ SET_CH_32(dw, dir, id, ch_en, 0);
+ SET_CH_32(dw, dir, id, int_clear,
+ HDMA_V0_STOP_INT_MASK | HDMA_V0_ABORT_INT_MASK);
+}
+
static void dw_hdma_v0_core_off(struct dw_edma *dw)
{
int id;
@@ -86,6 +97,21 @@ static void dw_hdma_v0_core_off(struct dw_edma *dw)
}
}
+static void dw_hdma_v0_core_quiesce(struct dw_edma *dw)
+{
+ int id;
+
+ for (id = 0; id < dw->wr_ch_cnt; id++)
+ dw_hdma_v0_core_ch_off(dw, EDMA_DIR_WRITE, id);
+ for (id = 0; id < dw->rd_ch_cnt; id++)
+ dw_hdma_v0_core_ch_off(dw, EDMA_DIR_READ, id);
+}
+
+static void dw_hdma_v0_core_ch_quiesce(struct dw_edma_chan *chan)
+{
+ dw_hdma_v0_core_ch_off(chan->dw, chan->dir, chan->id);
+}
+
static u16 dw_hdma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
{
/*
@@ -365,6 +391,8 @@ static resource_size_t dw_hdma_v0_core_db_offset(struct dw_edma *dw)
static const struct dw_edma_core_ops dw_hdma_v0_core = {
.off = dw_hdma_v0_core_off,
+ .quiesce = dw_hdma_v0_core_quiesce,
+ .ch_quiesce = dw_hdma_v0_core_ch_quiesce,
.ch_count = dw_hdma_v0_core_ch_count,
.ch_status = dw_hdma_v0_core_ch_status,
.handle_int = dw_hdma_v0_core_handle_int,
--
2.51.0
next prev parent reply other threads:[~2026-07-10 8:15 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-10 8:15 [PATCH v4 00/14] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3) Koichiro Den
2026-07-10 8:15 ` [PATCH v4 01/14] dmaengine: dw-edma: Factor out HDMA interrupt setup helper Koichiro Den
2026-07-10 8:15 ` [PATCH v4 02/14] dmaengine: dw-edma: Add per-channel interrupt routing control Koichiro Den
2026-07-10 8:15 ` Koichiro Den [this message]
2026-07-14 19:23 ` [PATCH v4 03/14] dmaengine: dw-edma: Add core quiesce operations Frank Li
2026-07-10 8:15 ` [PATCH v4 04/14] dmaengine: dw-edma: Initialize IRQ data before requesting IRQs Koichiro Den
2026-07-10 8:15 ` [PATCH v4 05/14] dmaengine: dw-edma: Add partial channel ownership mode Koichiro Den
2026-07-14 19:29 ` Frank Li
2026-07-16 15:52 ` Koichiro Den
2026-07-10 8:15 ` [PATCH v4 06/14] dmaengine: dw-edma-pcie: Track non-LL mode in DMA data Koichiro Den
2026-07-10 8:15 ` [PATCH v4 07/14] dmaengine: dw-edma-pcie: Add capability match data Koichiro Den
2026-07-10 8:15 ` [PATCH v4 08/14] dmaengine: dw-edma-pcie: Rename vsec_data to dma_data Koichiro Den
2026-07-10 8:15 ` [PATCH v4 09/14] dmaengine: dw-edma-pcie: Add platform ops to match data Koichiro Den
2026-07-10 8:15 ` [PATCH v4 10/14] dmaengine: dw-edma-pcie: Add register offset match flag Koichiro Den
2026-07-10 8:15 ` [PATCH v4 11/14] dmaengine: dw-edma-pcie: Factor out descriptor block address lookup Koichiro Den
2026-07-10 8:15 ` [PATCH v4 12/14] dmaengine: dw-edma-pcie: Handle optional data blocks Koichiro Den
2026-07-10 8:15 ` [PATCH v4 13/14] dmaengine: dw-edma-pcie: Add chip flags to match data Koichiro Den
2026-07-10 8:15 ` [PATCH v4 14/14] dmaengine: dw-edma: Program endpoint function numbers Koichiro Den
2026-07-14 19:32 ` 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=20260710081518.2394357-4-den@valinux.co.jp \
--to=den@valinux.co.jp \
--cc=Frank.Li@kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mani@kernel.org \
--cc=marek.vasut+renesas@mailbox.org \
--cc=vkoul@kernel.org \
--cc=yoshihiro.shimoda.uh@renesas.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox