From: Frank Li <Frank.li@oss.nxp.com>
To: Golla Nagendra <nagendra.golla@amd.com>
Cc: Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>,
Michal Simek <michal.simek@amd.com>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Kedareswara rao Appana <appana.durga.rao@xilinx.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Michael Tretter <m.tretter@pengutronix.de>,
Harini Katakam <harini.katakam@amd.com>,
Shyam Pandey <radhey.shyam.pandey@amd.com>,
dmaengine@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org,
devicetree@vger.kernel.org, git@amd.com
Subject: Re: [PATCH v4 1/6] dmaengine: zynqmp_dma: Use PM guard for probe-time runtime PM reference
Date: Fri, 9 Oct 2026 22:09:08 -0500 [thread overview]
Message-ID: <asmsVD1RP6FoMN9l@SMW015318> (raw)
In-Reply-To: <20261009-adma-pm-fix-and-per-channel-reset-v4-1-55f5fe409c55@amd.com>
On Fri, Oct 09, 2026 at 09:30:10AM +0530, Golla Nagendra wrote:
> Replace pm_runtime_resume_and_get() with the PM_RUNTIME_ACQUIRE_AUTOSUSPEND
> guard to manage the probe-time runtime PM reference lifecycle. If the guard
> acquire fails, fail probe immediately so a broken device is never
> registered.
>
> When runtime PM is not enabled for the device, call
> zynqmp_dma_runtime_resume() directly after pm_runtime_enable() to bring the
> clocks up for probe.
>
> On probe failure after a successful guard acquire, drop the reference with
> zynqmp_dma_probe_pm_put(), inhibit the guard destructor with
> retain_and_null_ptr(), and gate the clocks through
> zynqmp_dma_probe_fail(). When runtime PM is enabled,
> zynqmp_dma_probe_pm_put() uses pm_runtime_put_sync_suspend(). When runtime
> PM is not enabled for the device, balance the guard usage counter with
> pm_runtime_put_noidle() and gate the clocks with
> zynqmp_dma_runtime_suspend(). Runtime PM does not suspend a device that
> is already disabled, so pair every direct zynqmp_dma_runtime_suspend()
> call with pm_runtime_set_suspended() to keep the runtime PM status in
> sync with the clocks.
>
> On probe success, release the probe-time reference with
> pm_runtime_put_sync_autosuspend() when runtime PM is enabled for the
> device. When runtime PM is not enabled for the device, balance the guard
> usage counter with pm_runtime_put_noidle() only and leave the clocks
> enabled so that later channel allocation can use the hardware. Inhibit the
> guard destructor with retain_and_null_ptr(pm).
>
> Signed-off-by: Golla Nagendra <nagendra.golla@amd.com>
> ---
> drivers/dma/xilinx/zynqmp_dma.c | 68 ++++++++++++++++++++++++++++++-----------
> 1 file changed, 50 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
> index 3b7dfa53f972..a48106e404e7 100644
> --- a/drivers/dma/xilinx/zynqmp_dma.c
> +++ b/drivers/dma/xilinx/zynqmp_dma.c
> @@ -18,6 +18,7 @@
> #include <linux/slab.h>
> #include <linux/clk.h>
> #include <linux/io-64-nonatomic-lo-hi.h>
> +#include <linux/cleanup.h>
> #include <linux/pm_runtime.h>
>
> #include "../dmaengine.h"
> @@ -1077,6 +1078,29 @@ static const struct dev_pm_ops zynqmp_dma_dev_pm_ops = {
> zynqmp_dma_runtime_resume, NULL)
> };
>
> +static void zynqmp_dma_probe_pm_put(struct device *dev)
> +{
> + if (pm_runtime_enabled(dev))
> + pm_runtime_put_sync_suspend(dev);
> + else
> + pm_runtime_put_noidle(dev);
> +}
> +
> +static int zynqmp_dma_probe_fail(struct zynqmp_dma_device *zdev, int ret)
> +{
> + bool rpm_disabled = !pm_runtime_enabled(zdev->dev);
> +
> + zynqmp_dma_chan_remove(zdev->chan);
> + zynqmp_dma_probe_pm_put(zdev->dev);
> + pm_runtime_disable(zdev->dev);
> + if (rpm_disabled || !pm_runtime_status_suspended(zdev->dev)) {
> + zynqmp_dma_runtime_suspend(zdev->dev);
> + pm_runtime_set_suspended(zdev->dev);
> + }
> +
> + return ret;
> +}
> +
> /**
> * zynqmp_dma_probe - Driver probe function
> * @pdev: Pointer to the platform_device structure
> @@ -1087,7 +1111,7 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
> {
> struct zynqmp_dma_device *zdev;
> struct dma_device *p;
> - int ret;
> + int ret, pm_err;
>
> zdev = devm_kzalloc(&pdev->dev, sizeof(*zdev), GFP_KERNEL);
> if (!zdev)
> @@ -1128,21 +1152,30 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
> pm_runtime_set_autosuspend_delay(zdev->dev, ZDMA_PM_TIMEOUT);
> pm_runtime_use_autosuspend(zdev->dev);
> pm_runtime_enable(zdev->dev);
> - ret = pm_runtime_resume_and_get(zdev->dev);
> - if (ret < 0) {
> - dev_err(&pdev->dev, "device wakeup failed.\n");
> - pm_runtime_disable(zdev->dev);
> - }
> if (!pm_runtime_enabled(zdev->dev)) {
> ret = zynqmp_dma_runtime_resume(zdev->dev);
> - if (ret)
> + if (ret) {
> + pm_runtime_disable(zdev->dev);
> return ret;
> + }
> + }
> + PM_RUNTIME_ACQUIRE_AUTOSUSPEND(zdev->dev, pm);
> + pm_err = PM_RUNTIME_ACQUIRE_ERR(&pm);
> + if (pm_err) {
> + retain_and_null_ptr(pm);
Not sure why need call retain_and_null_ptr() here, generally only need
call retain_and_null_ptr() at success pass if you use want to keep
runtime_pm active. at fail case, needn't do that.
> + pm_runtime_disable(zdev->dev);
If use devm_pm_runtime_enable(), needn't this one.
> + if (!pm_runtime_status_suspended(zdev->dev)) {
> + zynqmp_dma_runtime_suspend(zdev->dev);
> + pm_runtime_set_suspended(zdev->dev);
> + }
> + return dev_err_probe(&pdev->dev, pm_err, "device wakeup failed\n");
> }
>
> ret = zynqmp_dma_chan_probe(zdev, pdev);
> if (ret) {
> dev_err_probe(&pdev->dev, ret, "Probing channel failed\n");
> - goto free_chan_resources;
> + retain_and_null_ptr(pm);
> + return zynqmp_dma_probe_fail(zdev, ret);
> }
>
> p->dst_addr_widths = BIT(zdev->chan->bus_width / 8);
> @@ -1151,7 +1184,8 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
> ret = dma_async_device_register(&zdev->common);
> if (ret) {
> dev_err(zdev->dev, "failed to register the dma device\n");
> - goto free_chan_resources;
> + retain_and_null_ptr(pm);
> + return zynqmp_dma_probe_fail(zdev, ret);
> }
>
> ret = of_dma_controller_register(pdev->dev.of_node,
> @@ -1159,19 +1193,17 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
> if (ret) {
> dev_err_probe(&pdev->dev, ret, "Unable to register DMA to DT\n");
> dma_async_device_unregister(&zdev->common);
> - goto free_chan_resources;
> + retain_and_null_ptr(pm);
> + return zynqmp_dma_probe_fail(zdev, ret);
> }
>
> - pm_runtime_put_sync_autosuspend(zdev->dev);
> + if (pm_runtime_enabled(zdev->dev))
> + pm_runtime_put_sync_autosuspend(zdev->dev);
> + else
> + pm_runtime_put_noidle(zdev->dev);
> + retain_and_null_ptr(pm);
You mix use auto cleanup and pm_runtime_put_sync_autosuspen() and
pm_runtime_put_noidle() to make code mess up.
Frank
>
> return 0;
> -
> -free_chan_resources:
> - zynqmp_dma_chan_remove(zdev->chan);
> - if (!pm_runtime_enabled(zdev->dev))
> - zynqmp_dma_runtime_suspend(zdev->dev);
> - pm_runtime_disable(zdev->dev);
> - return ret;
> }
>
> /**
>
> --
> 2.43.7
>
next prev parent reply other threads:[~2026-10-10 3:09 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 4:00 [PATCH v4 0/6] dmaengine: zynqmp_dma: Per-channel reset, IRQ guard improvements, and PM fixes Golla Nagendra
2026-10-09 4:00 ` [PATCH v4 1/6] dmaengine: zynqmp_dma: Use PM guard for probe-time runtime PM reference Golla Nagendra
2026-10-10 3:09 ` Frank Li [this message]
2026-10-09 4:00 ` [PATCH v4 2/6] PM: runtime: Add pm_runtime_if_active guard and conditional variant Golla Nagendra
2026-10-09 4:10 ` sashiko-bot
2026-10-10 2:57 ` Frank Li
2026-10-12 18:44 ` Rafael J. Wysocki (Intel)
2026-10-09 4:00 ` [PATCH v4 3/6] dmaengine: zynqmp_dma: Guard IRQ handler against spurious interrupts Golla Nagendra
2026-10-10 2:59 ` Frank Li
2026-10-09 4:00 ` [PATCH v4 4/6] dt-bindings: dma: xlnx,zynqmp-dma: Add Versal Net compatible support Golla Nagendra
2026-10-09 4:15 ` sashiko-bot
2026-10-09 15:33 ` Conor Dooley
2026-10-09 4:00 ` [PATCH v4 5/6] dmaengine: zynqmp_dma: Add new compatible string for Versal Net Golla Nagendra
2026-10-09 4:00 ` [PATCH v4 6/6] dmaengine: zynqmp_dma: Add per-channel reset support Golla Nagendra
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=asmsVD1RP6FoMN9l@SMW015318 \
--to=frank.li@oss.nxp.com \
--cc=Frank.Li@kernel.org \
--cc=appana.durga.rao@xilinx.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=git@amd.com \
--cc=harini.katakam@amd.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=m.tretter@pengutronix.de \
--cc=michal.simek@amd.com \
--cc=nagendra.golla@amd.com \
--cc=radhey.shyam.pandey@amd.com \
--cc=rafael@kernel.org \
--cc=robh@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.