[RFC PATCH 2/7] regulator: Add devm helpers for get and enable

Matti Vaittinen posted 7 patches 3 years, 8 months ago
There is a newer version of this series
[RFC PATCH 2/7] regulator: Add devm helpers for get and enable
Posted by Matti Vaittinen 3 years, 8 months ago
A few regulator consumer drivers seem to be just getting a regulator,
enabling it and registering a devm-action to disable the regulator at
the driver detach and then forget about it.

We can simplify this a bit by adding a devm-helper for this pattern.
Add devm_regulator_get_enable() and devm_regulator_get_enable_optional()

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 drivers/regulator/devres.c         | 59 ++++++++++++++++++++++++++++++
 include/linux/regulator/consumer.h | 13 +++++++
 2 files changed, 72 insertions(+)

diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
index 9113233f41cd..61b0facc975b 100644
--- a/drivers/regulator/devres.c
+++ b/drivers/regulator/devres.c
@@ -70,6 +70,65 @@ struct regulator *devm_regulator_get_exclusive(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
 
+static void regulator_action_disable(void *d)
+{
+	struct regulator *r = (struct regulator *)d;
+
+	regulator_disable(r);
+}
+
+static int _devm_regulator_get_enable(struct device *dev, const char *id,
+				      int get_type)
+{
+	struct regulator *r;
+	int ret;
+
+	r = _devm_regulator_get(dev, id, get_type);
+	if (IS_ERR(r))
+		return PTR_ERR(r);
+
+	ret = regulator_enable(r);
+	if (!ret)
+		ret = devm_add_action_or_reset(dev, &regulator_action_disable, r);
+
+	if (ret)
+		devm_regulator_put(r);
+
+	return ret;
+}
+
+/**
+ * devm_regulator_get_enable_optional - Resource managed regulator get and enable
+ * @dev: device to supply
+ * @id:  supply name or regulator ID.
+ *
+ * Get and enable regulator for duration of the device life-time.
+ * regulator_disable() and regulator_put() are automatically called on driver
+ * detach. See regulator_get_optional() and regulator_enable() for more
+ * information.
+ */
+int devm_regulator_get_enable_optional(struct device *dev, const char *id)
+{
+	return _devm_regulator_get_enable(dev, id, OPTIONAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_enable_optional);
+
+/**
+ * devm_regulator_get_enable - Resource managed regulator get and enable
+ * @dev: device to supply
+ * @id:  supply name or regulator ID.
+ *
+ * Get and enable regulator for duration of the device life-time.
+ * regulator_disable() and regulator_put() are automatically called on driver
+ * detach. See regulator_get() and regulator_enable() for more
+ * information.
+ */
+int devm_regulator_get_enable(struct device *dev, const char *id)
+{
+	return _devm_regulator_get_enable(dev, id, NORMAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_enable);
+
 /**
  * devm_regulator_get_optional - Resource managed regulator_get_optional()
  * @dev: device to supply
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index bbf6590a6dec..58e3dbcddb12 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -203,6 +203,8 @@ struct regulator *__must_check regulator_get_optional(struct device *dev,
 						      const char *id);
 struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
 							   const char *id);
+int devm_regulator_get_enable(struct device *dev, const char *id);
+int devm_regulator_get_enable_optional(struct device *dev, const char *id);
 void regulator_put(struct regulator *regulator);
 void devm_regulator_put(struct regulator *regulator);
 
@@ -346,6 +348,17 @@ devm_regulator_get_exclusive(struct device *dev, const char *id)
 	return ERR_PTR(-ENODEV);
 }
 
+static inline int devm_regulator_get_enable(struct device *dev, const char *id)
+{
+	return -ENODEV;
+}
+
+static inline int devm_regulator_get_enable_optional(struct device *dev,
+						     const char *id)
+{
+	return -ENODEV;
+}
+
 static inline struct regulator *__must_check
 regulator_get_optional(struct device *dev, const char *id)
 {
-- 
2.37.1


-- 
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
Simon says - in Latin please.
~~~ "non cogito me" dixit Rene Descarte, deinde evanescavit ~~~
Thanks to Simon Glass for the translation =] 
Re: [RFC PATCH 2/7] regulator: Add devm helpers for get and enable
Posted by Mark Brown 3 years, 8 months ago
On Wed, Aug 10, 2022 at 02:29:55PM +0300, Matti Vaittinen wrote:
> A few regulator consumer drivers seem to be just getting a regulator,
> enabling it and registering a devm-action to disable the regulator at
> the driver detach and then forget about it.
> 
> We can simplify this a bit by adding a devm-helper for this pattern.
> Add devm_regulator_get_enable() and devm_regulator_get_enable_optional()

I'm really not keen on the idea of a devm managed enable, it's too prone
to bugs when someone gets round to implementing runtime PM.
Re: [RFC PATCH 2/7] regulator: Add devm helpers for get and enable
Posted by Matti Vaittinen 3 years, 8 months ago
Hi deee Ho Mark,

Long time no chat. Glad that you had the time to check this series :)

On 8/10/22 14:56, Mark Brown wrote:
> On Wed, Aug 10, 2022 at 02:29:55PM +0300, Matti Vaittinen wrote:
>> A few regulator consumer drivers seem to be just getting a regulator,
>> enabling it and registering a devm-action to disable the regulator at
>> the driver detach and then forget about it.
>>
>> We can simplify this a bit by adding a devm-helper for this pattern.
>> Add devm_regulator_get_enable() and devm_regulator_get_enable_optional()
> 
> I'm really not keen on the idea of a devm managed enable, it's too prone
> to bugs when someone gets round to implementing runtime PM.

I see. And I agree the devm-based regulator disable can cause problems 
when combined with manual disable/enable.

In order to tackle the issue the suggested API does not return handle to 
the regulators - it really just provides the "get'n enable, then forget" 
solution. The consumers who use the suggested API to "devm get'n enable" 
will have had time manually controlling the regulator afterwards as they 
will not get the handle. I would almost claim that the pattern we 
nowadays see (devm_get, enable, add_action_or_reset(disable())) is more 
error prone as users seem to in many case be storing the regulator 
handle w/o any comment about the automated disable at detach.

-- 
Matti Vaittinen
Linux kernel developer at ROHM Semiconductors
Oulu Finland

~~ When things go utterly wrong vim users can always type :help! ~~

Discuss - Estimate - Plan - Report and finally accomplish this:
void do_work(int time) __attribute__ ((const));
Re: [RFC PATCH 2/7] regulator: Add devm helpers for get and enable
Posted by Mark Brown 3 years, 8 months ago
On Wed, Aug 10, 2022 at 03:19:05PM +0300, Matti Vaittinen wrote:

> In order to tackle the issue the suggested API does not return handle to the
> regulators - it really just provides the "get'n enable, then forget"
> solution. The consumers who use the suggested API to "devm get'n enable"
> will have had time manually controlling the regulator afterwards as they
> will not get the handle. I would almost claim that the pattern we nowadays
> see (devm_get, enable, add_action_or_reset(disable())) is more error prone
> as users seem to in many case be storing the regulator handle w/o any
> comment about the automated disable at detach.

Hrm, right - that does help with that case.  However we do need a bulk 
version since that's an obvious problem case.
Re: [RFC PATCH 2/7] regulator: Add devm helpers for get and enable
Posted by Matti Vaittinen 3 years, 8 months ago
On 8/10/22 18:16, Mark Brown wrote:
> On Wed, Aug 10, 2022 at 03:19:05PM +0300, Matti Vaittinen wrote:
> 
>> In order to tackle the issue the suggested API does not return handle to the
>> regulators - it really just provides the "get'n enable, then forget"
>> solution. The consumers who use the suggested API to "devm get'n enable"
>> will have had time manually controlling the regulator afterwards as they
>> will not get the handle. I would almost claim that the pattern we nowadays
>> see (devm_get, enable, add_action_or_reset(disable())) is more error prone
>> as users seem to in many case be storing the regulator handle w/o any
>> comment about the automated disable at detach.
> 
> Hrm, right - that does help with that case.  However we do need a bulk
> version since that's an obvious problem case.
I'll take a look at the bulk APIs and add them if they're not too 
complex. I'm a bit short on time as I was told I should be doing 
something we can show to a customer ;)

As a result of this discussion - not returning the handle to struct 
regulator * sounds like a safest option here. I'll drop the RFC when I 
respin this (hopefully with the bulk-APIs and a few more converted drivers)

Thanks for the input!

Best Regards
	Matti Vaittinen

-- 
Matti Vaittinen
Linux kernel developer at ROHM Semiconductors
Oulu Finland

~~ When things go utterly wrong vim users can always type :help! ~~

Discuss - Estimate - Plan - Report and finally accomplish this:
void do_work(int time) __attribute__ ((const));