DMA Engine development
 help / color / mirror / Atom feed
From: Linus Walleij <linusw@kernel.org>
To: Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>
Cc: dmaengine@vger.kernel.org, phone-devel@vger.kernel.org,
	 Linus Walleij <linusw@kernel.org>
Subject: [PATCH v3 06/22] dmaengine: ste_dma40: Handle runtime PM resume errors
Date: Fri, 18 Sep 2026 18:24:25 +0200	[thread overview]
Message-ID: <20260918-dma40-fixes-v3-6-8dd8450669e8@kernel.org> (raw)
In-Reply-To: <20260918-dma40-fixes-v3-0-8dd8450669e8@kernel.org>

Several channel operations use pm_runtime_get_sync() and access DMA40
registers without checking whether runtime resume succeeded. If resume
fails, the registers may be inaccessible. pm_runtime_get_sync() also
increments the usage counter on failure, making error unwinding easy to
unbalance.

Use pm_runtime_resume_and_get() and abort each operation before accessing
hardware when resume fails. Acquire the runtime PM reference before
allocating a channel so failure needs no channel-allocation rollback, and
leave a queued descriptor pending when the controller cannot be resumed.

Fixes: 7fb3e75e1833 ("dmaengine/ste_dma40: support pm in dma40")
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
 drivers/dma/ste_dma40.c | 45 +++++++++++++++++++++++++++++++++------------
 1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 1baee6f4d919..c6f633353f3e 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -1454,11 +1454,14 @@ static int d40_pause(struct dma_chan *chan)
 		return 0;
 
 	spin_lock_irqsave(&d40c->lock, flags);
-	pm_runtime_get_sync(d40c->base->dev);
+	res = pm_runtime_resume_and_get(d40c->base->dev);
+	if (res < 0)
+		goto unlock;
 
 	res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
 
 	pm_runtime_put_autosuspend(d40c->base->dev);
+ unlock:
 	spin_unlock_irqrestore(&d40c->lock, flags);
 	return res;
 }
@@ -1478,13 +1481,16 @@ static int d40_resume(struct dma_chan *chan)
 		return 0;
 
 	spin_lock_irqsave(&d40c->lock, flags);
-	pm_runtime_get_sync(d40c->base->dev);
+	res = pm_runtime_resume_and_get(d40c->base->dev);
+	if (res < 0)
+		goto unlock;
 
 	/* If bytes left to transfer or linked tx resume job */
 	if (d40_residue(d40c) || d40_tx_is_linked(d40c))
 		res = d40_channel_execute_command(d40c, D40_DMA_RUN);
 
 	pm_runtime_put_autosuspend(d40c->base->dev);
+ unlock:
 	spin_unlock_irqrestore(&d40c->lock, flags);
 	return res;
 }
@@ -1521,8 +1527,13 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
 
 	if (d40d != NULL) {
 		if (!d40c->busy) {
+			err = pm_runtime_resume_and_get(d40c->base->dev);
+			if (err < 0) {
+				chan_err(d40c, "Failed to resume DMA: %d\n",
+					 err);
+				return ERR_PTR(err);
+			}
 			d40c->busy = true;
-			pm_runtime_get_sync(d40c->base->dev);
 		}
 
 		/* Remove from queue */
@@ -2042,9 +2053,6 @@ static int d40_free_dma(struct d40_chan *d40c)
 	struct d40_phy_res *phy = d40c->phy_chan;
 	bool is_src;
 
-	/* Terminate all queued and active transfers */
-	d40_term_all(d40c);
-
 	if (phy == NULL) {
 		chan_err(d40c, "phy == null\n");
 		return -EINVAL;
@@ -2066,7 +2074,13 @@ static int d40_free_dma(struct d40_chan *d40c)
 		return -EINVAL;
 	}
 
-	pm_runtime_get_sync(d40c->base->dev);
+	res = pm_runtime_resume_and_get(d40c->base->dev);
+	if (res < 0)
+		return res;
+
+	/* Terminate all queued and active transfers */
+	d40_term_all(d40c);
+
 	res = d40_channel_execute_command(d40c, D40_DMA_STOP);
 	if (res) {
 		chan_err(d40c, "stop failed\n");
@@ -2458,10 +2472,14 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
 		err = d40_config_memcpy(d40c);
 		if (err) {
 			chan_err(d40c, "Failed to configure memcpy channel\n");
-			goto mark_last_busy;
+			goto unlock;
 		}
 	}
 
+	err = pm_runtime_resume_and_get(d40c->base->dev);
+	if (err < 0)
+		goto unlock;
+
 	err = d40_allocate_channel(d40c, &is_free_phy);
 	if (err) {
 		chan_err(d40c, "Failed to allocate channel\n");
@@ -2469,8 +2487,6 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
 		goto mark_last_busy;
 	}
 
-	pm_runtime_get_sync(d40c->base->dev);
-
 	d40_set_prio_realtime(d40c);
 
 	if (chan_is_logical(d40c)) {
@@ -2502,6 +2518,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
 		d40_config_write(d40c);
  mark_last_busy:
 	pm_runtime_put_autosuspend(d40c->base->dev);
+ unlock:
 	spin_unlock_irqrestore(&d40c->lock, flags);
 	return err;
 }
@@ -2658,7 +2675,10 @@ static int d40_terminate_all(struct dma_chan *chan)
 
 	spin_lock_irqsave(&d40c->lock, flags);
 
-	pm_runtime_get_sync(d40c->base->dev);
+	ret = pm_runtime_resume_and_get(d40c->base->dev);
+	if (ret < 0)
+		goto unlock;
+
 	ret = d40_channel_execute_command(d40c, D40_DMA_STOP);
 	if (ret)
 		chan_err(d40c, "Failed to stop channel\n");
@@ -2669,8 +2689,9 @@ static int d40_terminate_all(struct dma_chan *chan)
 		pm_runtime_put_autosuspend(d40c->base->dev);
 	d40c->busy = false;
 
+ unlock:
 	spin_unlock_irqrestore(&d40c->lock, flags);
-	return 0;
+	return ret;
 }
 
 static int

-- 
2.55.0


  parent reply	other threads:[~2026-09-18 16:24 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18 16:24 [PATCH v3 00/22] dmaengine: ste_dma40: Fix numerous accumulated bugs Linus Walleij
2026-09-18 16:24 ` [PATCH v3 01/22] dmaengine: ste_dma40: Fix physical cyclic capability Linus Walleij
2026-09-18 19:57   ` Frank Li
2026-09-18 16:24 ` [PATCH v3 02/22] dmaengine: ste_dma40: Fix cyclic transfer residue Linus Walleij
2026-09-18 16:44   ` sashiko-bot
2026-09-18 21:41   ` Frank Li
2026-09-18 16:24 ` [PATCH v3 03/22] dmaengine: ste_dma40: Fix failed start cleanup Linus Walleij
2026-09-18 16:24 ` [PATCH v3 04/22] dmaengine: ste_dma40: Fix probe runtime PM disable Linus Walleij
2026-09-18 16:24 ` [PATCH v3 05/22] dmaengine: ste_dma40: Check runtime PM in IRQ Linus Walleij
2026-09-18 16:24 ` Linus Walleij [this message]
2026-09-18 16:37   ` [PATCH v3 06/22] dmaengine: ste_dma40: Handle runtime PM resume errors sashiko-bot
2026-09-18 16:24 ` [PATCH v3 07/22] dmaengine: ste_dma40: Return IRQ_NONE without interrupt status Linus Walleij
2026-09-18 16:24 ` [PATCH v3 08/22] dmaengine: ste_dma40: Init hardware before registration Linus Walleij
2026-09-18 16:24 ` [PATCH v3 09/22] dmaengine: ste_dma40: Fix probe IRQ leak Linus Walleij
2026-09-18 16:24 ` [PATCH v3 10/22] dmaengine: ste_dma40: Fix DMA registration unwind Linus Walleij
2026-09-18 16:24 ` [PATCH v3 11/22] dmaengine: ste_dma40: Fix LCLA allocation order Linus Walleij
2026-09-18 16:24 ` [PATCH v3 12/22] dmaengine: ste_dma40: Fix probe LCLA free Linus Walleij
2026-09-18 16:24 ` [PATCH v3 13/22] dmaengine: ste_dma40: Put the LCPA SRAM node Linus Walleij
2026-09-18 16:24 ` [PATCH v3 14/22] dmaengine: ste_dma40: Fix memcpy channel parsing Linus Walleij
2026-09-18 16:24 ` [PATCH v3 15/22] dmaengine: ste_dma40: Validate disabled channel indexes Linus Walleij
2026-09-18 16:24 ` [PATCH v3 16/22] dmaengine: ste_dma40: Validate DMA specifier length Linus Walleij
2026-09-18 16:24 ` [PATCH v3 17/22] dmaengine: ste_dma40: Reject direction changes after allocation Linus Walleij
2026-09-18 16:24 ` [PATCH v3 18/22] dmaengine: ste_dma40: Fix logical channel bounds check Linus Walleij
2026-09-18 16:24 ` [PATCH v3 19/22] dmaengine: ste_dma40: Fix event group bounds Linus Walleij
2026-09-18 16:24 ` [PATCH v3 20/22] dmaengine: ste_dma40: Search all blocks for fixed logical channels Linus Walleij
2026-09-18 16:24 ` [PATCH v3 21/22] dmaengine: ste_dma40: Validate fixed physical channel indexes Linus Walleij
2026-09-18 16:24 ` [PATCH v3 22/22] dmaengine: ste_dma40: Validate memcpy configuration Linus Walleij

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=20260918-dma40-fixes-v3-6-8dd8450669e8@kernel.org \
    --to=linusw@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=phone-devel@vger.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox