From: Amelie Delaunay <amelie.delaunay@foss.st.com>
To: Vinod Koul <vkoul@kernel.org>,
Maxime Coquelin <mcoquelin.stm32@gmail.com>,
Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: <dmaengine@vger.kernel.org>,
<linux-stm32@st-md-mailman.stormreply.com>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>,
Amelie Delaunay <amelie.delaunay@foss.st.com>
Subject: [PATCH 3/4] dmaengine: stm32-dma3: restore channel semaphore status after suspend
Date: Mon, 3 Nov 2025 11:15:12 +0100 [thread overview]
Message-ID: <20251103-dma3_improv-v1-3-57f048bf2877@foss.st.com> (raw)
In-Reply-To: <20251103-dma3_improv-v1-0-57f048bf2877@foss.st.com>
Depending on the power state reached during suspend, the CxSEMCR register
could have been reset, and the semaphore released.
On resume, try to take the semaphore again. If the semaphore cannot be
taken, an error log displaying the channel number and channel user is
generated.
This requires introducing two new functions:
stm32_dma3_pm_suspend(), where the status of each channel is checked
because suspension is not allowed if a channel is still running;
stm32_dma3_pm_resume(), where the channel semaphore is restored if it was
taken before suspend.
Signed-off-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
---
drivers/dma/stm32/stm32-dma3.c | 75 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c
index a1583face7ec..29ea510fa539 100644
--- a/drivers/dma/stm32/stm32-dma3.c
+++ b/drivers/dma/stm32/stm32-dma3.c
@@ -1237,6 +1237,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_memcpy(struct dma_cha
bool prevent_refactor = !!FIELD_GET(STM32_DMA3_DT_NOPACK, chan->dt_config.tr_conf) ||
!!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf);
+ /* Semaphore could be lost during suspend/resume */
+ if (chan->semaphore_mode && !chan->semaphore_taken)
+ return NULL;
+
count = stm32_dma3_get_ll_count(chan, len, prevent_refactor);
swdesc = stm32_dma3_chan_desc_alloc(chan, count);
@@ -1297,6 +1301,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan
!!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf);
int ret;
+ /* Semaphore could be lost during suspend/resume */
+ if (chan->semaphore_mode && !chan->semaphore_taken)
+ return NULL;
+
count = 0;
for_each_sg(sgl, sg, sg_len, i)
count += stm32_dma3_get_ll_count(chan, sg_dma_len(sg), prevent_refactor);
@@ -1383,6 +1391,10 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_cyclic(struct dma_cha
u32 count, i, ctr1, ctr2;
int ret;
+ /* Semaphore could be lost during suspend/resume */
+ if (chan->semaphore_mode && !chan->semaphore_taken)
+ return NULL;
+
if (!buf_len || !period_len || period_len > STM32_DMA3_MAX_BLOCK_SIZE) {
dev_err(chan2dev(chan), "Invalid buffer/period length\n");
return NULL;
@@ -1932,8 +1944,69 @@ static int stm32_dma3_runtime_resume(struct device *dev)
return ret;
}
+static int stm32_dma3_pm_suspend(struct device *dev)
+{
+ struct stm32_dma3_ddata *ddata = dev_get_drvdata(dev);
+ struct dma_device *dma_dev = &ddata->dma_dev;
+ struct dma_chan *c;
+ int ccr, ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ return ret;
+
+ list_for_each_entry(c, &dma_dev->channels, device_node) {
+ struct stm32_dma3_chan *chan = to_stm32_dma3_chan(c);
+
+ ccr = readl_relaxed(ddata->base + STM32_DMA3_CCR(chan->id));
+ if (ccr & CCR_EN) {
+ dev_warn(dev, "Suspend is prevented: %s still in use by %s\n",
+ dma_chan_name(c), dev_name(c->slave));
+ pm_runtime_put_sync(dev);
+ return -EBUSY;
+ }
+ }
+
+ pm_runtime_put_sync(dev);
+
+ pm_runtime_force_suspend(dev);
+
+ return 0;
+}
+
+static int stm32_dma3_pm_resume(struct device *dev)
+{
+ struct stm32_dma3_ddata *ddata = dev_get_drvdata(dev);
+ struct dma_device *dma_dev = &ddata->dma_dev;
+ struct dma_chan *c;
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Channel semaphores need to be restored in case of registers reset during low power.
+ * stm32_dma3_get_chan_sem() will prior check the semaphore status.
+ */
+ list_for_each_entry(c, &dma_dev->channels, device_node) {
+ struct stm32_dma3_chan *chan = to_stm32_dma3_chan(c);
+
+ if (chan->semaphore_mode && chan->semaphore_taken)
+ stm32_dma3_get_chan_sem(chan);
+ }
+
+ pm_runtime_put_sync(dev);
+
+ return 0;
+}
+
static const struct dev_pm_ops stm32_dma3_pm_ops = {
- SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+ SYSTEM_SLEEP_PM_OPS(stm32_dma3_pm_suspend, stm32_dma3_pm_resume)
RUNTIME_PM_OPS(stm32_dma3_runtime_suspend, stm32_dma3_runtime_resume, NULL)
};
--
2.43.0
next prev parent reply other threads:[~2025-11-03 10:15 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-03 10:15 [PATCH 0/4] dmaengine: stm32-dma3: improvements and helper functions Amelie Delaunay
2025-11-03 10:15 ` [PATCH 1/4] dmaengine: stm32-dma3: use module_platform_driver Amelie Delaunay
2025-11-03 10:15 ` [PATCH 2/4] dmaengine: stm32-dma3: introduce channel semaphore helpers Amelie Delaunay
2025-11-03 10:15 ` Amelie Delaunay [this message]
2025-11-03 10:15 ` [PATCH 4/4] dmaengine: stm32-dma3: introduce ddata2dev helper Amelie Delaunay
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=20251103-dma3_improv-v1-3-57f048bf2877@foss.st.com \
--to=amelie.delaunay@foss.st.com \
--cc=alexandre.torgue@foss.st.com \
--cc=dmaengine@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=mcoquelin.stm32@gmail.com \
--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;
as well as URLs for NNTP newsgroup(s).