* [PATCH v2 1/4] dma: Add devm_dma_request_chan()
[not found] <20250124085221.766303-4-csokas.bence@prolan.hu>
@ 2025-01-24 8:52 ` Bence Csókás
2025-02-03 12:27 ` Alexander Dahl
2025-01-24 8:52 ` [PATCH v2 2/4] pm: runtime: Add new devm functions Bence Csókás
` (2 subsequent siblings)
3 siblings, 1 reply; 6+ messages in thread
From: Bence Csókás @ 2025-01-24 8:52 UTC (permalink / raw)
To: dmaengine, linux-kernel
Cc: Bence Csókás, Mark Brown, Vinod Koul,
Rafael J . Wysocki, linux-spi, linux-arm-kernel, linux-pm
Expand the arsenal of devm functions for DMA
devices, this time for requesting channels.
Signed-off-by: Bence Csókás <csokas.bence@prolan.hu>
---
drivers/dma/dmaengine.c | 30 ++++++++++++++++++++++++++++++
include/linux/dmaengine.h | 7 +++++++
2 files changed, 37 insertions(+)
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index c1357d7f3dc6..02c29d26ac85 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -926,6 +926,36 @@ void dma_release_channel(struct dma_chan *chan)
}
EXPORT_SYMBOL_GPL(dma_release_channel);
+static void dmaenginem_release_channel(void *chan)
+{
+ dma_release_channel(chan);
+}
+
+/**
+ * devm_dma_request_chan - try to allocate an exclusive slave channel
+ * @dev: pointer to client device structure
+ * @name: slave channel name
+ *
+ * Returns pointer to appropriate DMA channel on success or an error pointer.
+ *
+ * The operation is managed and will be undone on driver detach.
+ */
+
+struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name)
+{
+ struct dma_chan *chan = dma_request_chan(dev, name);
+ int ret = 0;
+
+ if (!IS_ERR(chan))
+ ret = devm_add_action_or_reset(dev, dmaenginem_release_channel, chan);
+
+ if (ret)
+ return ERR_PTR(ret);
+
+ return chan;
+}
+EXPORT_SYMBOL_GPL(devm_dma_request_chan);
+
/**
* dmaengine_get - register interest in dma_channels
*/
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 346251bf1026..ffb54b52ef0c 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -1528,6 +1528,7 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
struct dma_chan *dma_request_chan(struct device *dev, const char *name);
struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask);
+struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name);
void dma_release_channel(struct dma_chan *chan);
int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps);
@@ -1564,6 +1565,12 @@ static inline struct dma_chan *dma_request_chan_by_mask(
{
return ERR_PTR(-ENODEV);
}
+
+static inline struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline void dma_release_channel(struct dma_chan *chan)
{
}
--
2.48.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 2/4] pm: runtime: Add new devm functions
[not found] <20250124085221.766303-4-csokas.bence@prolan.hu>
2025-01-24 8:52 ` [PATCH v2 1/4] dma: Add devm_dma_request_chan() Bence Csókás
@ 2025-01-24 8:52 ` Bence Csókás
2025-01-24 8:52 ` [PATCH v2 3/4] spi: atmel-quadspi: Use `devm_dma_request_chan()` Bence Csókás
2025-01-24 8:52 ` [PATCH v2 4/4] spi: atmel-quadspi: Fix unbalanced pm_runtime by using devm_ API Bence Csókás
3 siblings, 0 replies; 6+ messages in thread
From: Bence Csókás @ 2025-01-24 8:52 UTC (permalink / raw)
To: linux-pm, linux-kernel
Cc: Bence Csókás, Mark Brown, Vinod Koul,
Rafael J . Wysocki, linux-spi, linux-arm-kernel, dmaengine,
Pavel Machek, Len Brown, Greg Kroah-Hartman
Add `devm_pm_runtime_set_active()` and
`devm_pm_runtime_get_noresume()` for
simplifying common use cases in drivers.
Signed-off-by: Bence Csókás <csokas.bence@prolan.hu>
---
drivers/base/power/runtime.c | 36 ++++++++++++++++++++++++++++++++++++
include/linux/pm_runtime.h | 4 ++++
2 files changed, 40 insertions(+)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 2ee45841486b..f0a6c64bec19 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1545,6 +1545,24 @@ void pm_runtime_enable(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_runtime_enable);
+static void pm_runtime_set_suspended_action(void *data)
+{
+ pm_runtime_set_suspended(data);
+}
+
+/**
+ * devm_pm_runtime_set_active - devres-enabled version of pm_runtime_set_active.
+ *
+ * @dev: Device to handle.
+ */
+int devm_pm_runtime_set_active(struct device *dev)
+{
+ pm_runtime_set_active(dev);
+
+ return devm_add_action_or_reset(dev, pm_runtime_set_suspended_action, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_runtime_set_active);
+
static void pm_runtime_disable_action(void *data)
{
pm_runtime_dont_use_autosuspend(data);
@@ -1567,6 +1585,24 @@ int devm_pm_runtime_enable(struct device *dev)
}
EXPORT_SYMBOL_GPL(devm_pm_runtime_enable);
+static void pm_runtime_put_noidle_action(void *data)
+{
+ pm_runtime_put_noidle(data);
+}
+
+/**
+ * devm_pm_runtime_get_noresume - devres-enabled version of pm_runtime_get_noresume.
+ *
+ * @dev: Device to handle.
+ */
+int devm_pm_runtime_get_noresume(struct device *dev)
+{
+ pm_runtime_get_noresume(dev);
+
+ return devm_add_action_or_reset(dev, pm_runtime_put_noidle_action, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_runtime_get_noresume);
+
/**
* pm_runtime_forbid - Block runtime PM of a device.
* @dev: Device to handle.
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index d39dc863f612..d7eca86150b8 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -93,7 +93,9 @@ extern void pm_runtime_new_link(struct device *dev);
extern void pm_runtime_drop_link(struct device_link *link);
extern void pm_runtime_release_supplier(struct device_link *link);
+int devm_pm_runtime_set_active(struct device *dev);
extern int devm_pm_runtime_enable(struct device *dev);
+int devm_pm_runtime_get_noresume(struct device *dev);
/**
* pm_suspend_ignore_children - Set runtime PM behavior regarding children.
@@ -276,7 +278,9 @@ static inline void __pm_runtime_disable(struct device *dev, bool c) {}
static inline void pm_runtime_allow(struct device *dev) {}
static inline void pm_runtime_forbid(struct device *dev) {}
+static inline int devm_pm_runtime_set_active(struct device *dev) { return 0; }
static inline int devm_pm_runtime_enable(struct device *dev) { return 0; }
+static inline int devm_pm_runtime_get_noresume(struct device *dev) { return 0; }
static inline void pm_suspend_ignore_children(struct device *dev, bool enable) {}
static inline void pm_runtime_get_noresume(struct device *dev) {}
--
2.48.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 3/4] spi: atmel-quadspi: Use `devm_dma_request_chan()`
[not found] <20250124085221.766303-4-csokas.bence@prolan.hu>
2025-01-24 8:52 ` [PATCH v2 1/4] dma: Add devm_dma_request_chan() Bence Csókás
2025-01-24 8:52 ` [PATCH v2 2/4] pm: runtime: Add new devm functions Bence Csókás
@ 2025-01-24 8:52 ` Bence Csókás
2025-01-24 8:52 ` [PATCH v2 4/4] spi: atmel-quadspi: Fix unbalanced pm_runtime by using devm_ API Bence Csókás
3 siblings, 0 replies; 6+ messages in thread
From: Bence Csókás @ 2025-01-24 8:52 UTC (permalink / raw)
To: linux-spi, linux-arm-kernel, linux-kernel
Cc: Bence Csókás, Mark Brown, Vinod Koul,
Rafael J . Wysocki, dmaengine, linux-pm, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea
Leave releasing of DMA channels up to the devm
facilities. This way we can eliminate the rest
of the "goto ladder".
Signed-off-by: Bence Csókás <csokas.bence@prolan.hu>
---
drivers/spi/atmel-quadspi.c | 44 ++++++++++---------------------------
1 file changed, 11 insertions(+), 33 deletions(-)
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index abdc49d9d940..b1fb4426c78d 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -1288,18 +1288,20 @@ static int atmel_qspi_dma_init(struct spi_controller *ctrl)
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
int ret;
- aq->rx_chan = dma_request_chan(&aq->pdev->dev, "rx");
+ aq->rx_chan = devm_dma_request_chan(&aq->pdev->dev, "rx");
if (IS_ERR(aq->rx_chan)) {
aq->rx_chan = NULL;
return dev_err_probe(&aq->pdev->dev, PTR_ERR(aq->rx_chan),
"RX DMA channel is not available\n");
}
- aq->tx_chan = dma_request_chan(&aq->pdev->dev, "tx");
+ aq->tx_chan = devm_dma_request_chan(&aq->pdev->dev, "tx");
if (IS_ERR(aq->tx_chan)) {
ret = dev_err_probe(&aq->pdev->dev, PTR_ERR(aq->tx_chan),
"TX DMA channel is not available\n");
- goto release_rx_chan;
+ aq->rx_chan = NULL;
+ aq->tx_chan = NULL;
+ return ret;
}
ctrl->dma_rx = aq->rx_chan;
@@ -1310,20 +1312,6 @@ static int atmel_qspi_dma_init(struct spi_controller *ctrl)
dma_chan_name(aq->tx_chan), dma_chan_name(aq->rx_chan));
return 0;
-
-release_rx_chan:
- dma_release_channel(aq->rx_chan);
- aq->rx_chan = NULL;
- aq->tx_chan = NULL;
- return ret;
-}
-
-static void atmel_qspi_dma_release(struct atmel_qspi *aq)
-{
- if (aq->rx_chan)
- dma_release_channel(aq->rx_chan);
- if (aq->tx_chan)
- dma_release_channel(aq->tx_chan);
}
static const struct atmel_qspi_ops atmel_qspi_ops = {
@@ -1428,14 +1416,13 @@ static int atmel_qspi_probe(struct platform_device *pdev)
/* Request the IRQ */
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- err = irq;
- goto dma_release;
- }
+ if (irq < 0)
+ return irq;
+
err = devm_request_irq(&pdev->dev, irq, atmel_qspi_interrupt,
0, dev_name(&pdev->dev), aq);
if (err)
- goto dma_release;
+ return err;
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -1445,7 +1432,7 @@ static int atmel_qspi_probe(struct platform_device *pdev)
err = atmel_qspi_init(aq);
if (err)
- goto dma_release;
+ return err;
err = spi_register_controller(ctrl);
if (err) {
@@ -1453,18 +1440,12 @@ static int atmel_qspi_probe(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
- goto dma_release;
+ return err;
}
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
return 0;
-
-dma_release:
- if (aq->caps->has_dma)
- atmel_qspi_dma_release(aq);
-
- return err;
}
static int atmel_qspi_sama7g5_suspend(struct atmel_qspi *aq)
@@ -1514,9 +1495,6 @@ static void atmel_qspi_remove(struct platform_device *pdev)
ret = pm_runtime_get_sync(&pdev->dev);
if (ret >= 0) {
- if (aq->caps->has_dma)
- atmel_qspi_dma_release(aq);
-
if (aq->caps->has_gclk) {
ret = atmel_qspi_sama7g5_suspend(aq);
if (ret)
--
2.48.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 4/4] spi: atmel-quadspi: Fix unbalanced pm_runtime by using devm_ API
[not found] <20250124085221.766303-4-csokas.bence@prolan.hu>
` (2 preceding siblings ...)
2025-01-24 8:52 ` [PATCH v2 3/4] spi: atmel-quadspi: Use `devm_dma_request_chan()` Bence Csókás
@ 2025-01-24 8:52 ` Bence Csókás
3 siblings, 0 replies; 6+ messages in thread
From: Bence Csókás @ 2025-01-24 8:52 UTC (permalink / raw)
To: Csókás, Bence, Mark Brown, Varshini Rajendran,
Tudor Ambarus, linux-spi, linux-arm-kernel, linux-kernel
Cc: Vinod Koul, Rafael J . Wysocki, Krzysztof Kozlowski, dmaengine,
linux-pm, Alexander Dahl, Nicolas Ferre, Alexandre Belloni,
Claudiu Beznea
Fix unbalanced PM in error path of `atmel_qspi_probe()`
by using `devm_pm_runtime_*()` functions.
Reported-by: Alexander Dahl <ada@thorsis.com>
Closes: https://lore.kernel.org/linux-spi/20250110-paycheck-irregular-bcddab1276c7@thorsis.com/
Fixes: 5af42209a4d2 ("spi: atmel-quadspi: Add support for sama7g5 QSPI")
Signed-off-by: Bence Csókás <csokas.bence@prolan.hu>
---
drivers/spi/atmel-quadspi.c | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index b1fb4426c78d..f2164685d3d5 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -1426,22 +1426,18 @@ static int atmel_qspi_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
- pm_runtime_get_noresume(&pdev->dev);
+ devm_pm_runtime_set_active(&pdev->dev);
+ devm_pm_runtime_enable(&pdev->dev);
+ devm_pm_runtime_get_noresume(&pdev->dev);
err = atmel_qspi_init(aq);
if (err)
return err;
err = spi_register_controller(ctrl);
- if (err) {
- pm_runtime_put_noidle(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- pm_runtime_set_suspended(&pdev->dev);
- pm_runtime_dont_use_autosuspend(&pdev->dev);
+ if (err)
return err;
- }
+
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
@@ -1511,10 +1507,6 @@ static void atmel_qspi_remove(struct platform_device *pdev)
*/
dev_warn(&pdev->dev, "Failed to resume device on remove\n");
}
-
- pm_runtime_disable(&pdev->dev);
- pm_runtime_dont_use_autosuspend(&pdev->dev);
- pm_runtime_put_noidle(&pdev->dev);
}
static int __maybe_unused atmel_qspi_suspend(struct device *dev)
--
2.48.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/4] dma: Add devm_dma_request_chan()
2025-01-24 8:52 ` [PATCH v2 1/4] dma: Add devm_dma_request_chan() Bence Csókás
@ 2025-02-03 12:27 ` Alexander Dahl
2025-02-03 13:09 ` Csókás Bence
0 siblings, 1 reply; 6+ messages in thread
From: Alexander Dahl @ 2025-02-03 12:27 UTC (permalink / raw)
To: Bence Csókás
Cc: dmaengine, linux-kernel, Mark Brown, Vinod Koul,
Rafael J . Wysocki, linux-spi, linux-arm-kernel, linux-pm
Hello,
Am Fri, Jan 24, 2025 at 09:52:20AM +0100 schrieb Bence Csókás:
> Expand the arsenal of devm functions for DMA
> devices, this time for requesting channels.
>
> Signed-off-by: Bence Csókás <csokas.bence@prolan.hu>
> ---
> drivers/dma/dmaengine.c | 30 ++++++++++++++++++++++++++++++
> include/linux/dmaengine.h | 7 +++++++
> 2 files changed, 37 insertions(+)
>
> diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
> index c1357d7f3dc6..02c29d26ac85 100644
> --- a/drivers/dma/dmaengine.c
> +++ b/drivers/dma/dmaengine.c
> @@ -926,6 +926,36 @@ void dma_release_channel(struct dma_chan *chan)
> }
> EXPORT_SYMBOL_GPL(dma_release_channel);
>
> +static void dmaenginem_release_channel(void *chan)
> +{
> + dma_release_channel(chan);
> +}
> +
> +/**
> + * devm_dma_request_chan - try to allocate an exclusive slave channel
> + * @dev: pointer to client device structure
> + * @name: slave channel name
> + *
> + * Returns pointer to appropriate DMA channel on success or an error pointer.
> + *
> + * The operation is managed and will be undone on driver detach.
> + */
> +
> +struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name)
> +{
> + struct dma_chan *chan = dma_request_chan(dev, name);
> + int ret = 0;
> +
> + if (!IS_ERR(chan))
> + ret = devm_add_action_or_reset(dev, dmaenginem_release_channel, chan);
Why not using dma_release_channel() directly here? What's the point
of introducing dmaenginem_release_channel() further above?
Greets
Alex
> +
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return chan;
> +}
> +EXPORT_SYMBOL_GPL(devm_dma_request_chan);
> +
> /**
> * dmaengine_get - register interest in dma_channels
> */
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index 346251bf1026..ffb54b52ef0c 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -1528,6 +1528,7 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
>
> struct dma_chan *dma_request_chan(struct device *dev, const char *name);
> struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask);
> +struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name);
>
> void dma_release_channel(struct dma_chan *chan);
> int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps);
> @@ -1564,6 +1565,12 @@ static inline struct dma_chan *dma_request_chan_by_mask(
> {
> return ERR_PTR(-ENODEV);
> }
> +
> +static inline struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name)
> +{
> + return ERR_PTR(-ENODEV);
> +}
> +
> static inline void dma_release_channel(struct dma_chan *chan)
> {
> }
> --
> 2.48.1
>
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/4] dma: Add devm_dma_request_chan()
2025-02-03 12:27 ` Alexander Dahl
@ 2025-02-03 13:09 ` Csókás Bence
0 siblings, 0 replies; 6+ messages in thread
From: Csókás Bence @ 2025-02-03 13:09 UTC (permalink / raw)
To: dmaengine, linux-kernel, Mark Brown, Vinod Koul,
Rafael J . Wysocki, linux-spi, linux-arm-kernel, linux-pm
Hi,
On 2025. 02. 03. 13:27, Alexander Dahl wrote:
>> + if (!IS_ERR(chan))
>> + ret = devm_add_action_or_reset(dev, dmaenginem_release_channel, chan);
>
> Why not using dma_release_channel() directly here? What's the point
> of introducing dmaenginem_release_channel() further above?
I followed the existing practice, used by
`dmaenginem_async_device_unregister()`. I suspect it was done like this
because the devm callback function's signature takes a `void *` and not
`struct dma_chan *`.
Bence
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-02-03 13:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20250124085221.766303-4-csokas.bence@prolan.hu>
2025-01-24 8:52 ` [PATCH v2 1/4] dma: Add devm_dma_request_chan() Bence Csókás
2025-02-03 12:27 ` Alexander Dahl
2025-02-03 13:09 ` Csókás Bence
2025-01-24 8:52 ` [PATCH v2 2/4] pm: runtime: Add new devm functions Bence Csókás
2025-01-24 8:52 ` [PATCH v2 3/4] spi: atmel-quadspi: Use `devm_dma_request_chan()` Bence Csókás
2025-01-24 8:52 ` [PATCH v2 4/4] spi: atmel-quadspi: Fix unbalanced pm_runtime by using devm_ API Bence Csókás
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®