[v2,3/3] pwm: core: add consumer device link

Message ID 1549901522-15071-4-git-send-email-fabrice.gasnier@st.com
State Superseded
Headers show
Series
  • Add PM support to STM32 LP Timer drivers
Related show

Commit Message

Fabrice Gasnier Feb. 11, 2019, 4:12 p.m.
Add a device link between the PWM consumer and the PWM provider. This
enforces the PWM user to get suspended before the PWM provider. It
allows proper synchronization of suspend/resume sequences: the PWM user
is responsible for properly stopping PWM, before the provider gets
suspended: see [1]. Add the device link in:
- pwm_get()
- devm_pwm_get()
- devm_of_pwm_get()
as it requires a reference to the device for the PWM consumer.

[1] https://lkml.org/lkml/2019/2/5/770

Suggested-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
 drivers/pwm/core.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

Comments

Uwe Kleine-König Feb. 11, 2019, 7:06 p.m. | #1
Hello Fabrice,

On Mon, Feb 11, 2019 at 05:12:02PM +0100, Fabrice Gasnier wrote:
> Add a device link between the PWM consumer and the PWM provider. This
> enforces the PWM user to get suspended before the PWM provider. It
> allows proper synchronization of suspend/resume sequences: the PWM user
> is responsible for properly stopping PWM, before the provider gets
> suspended: see [1]. Add the device link in:
> - pwm_get()
> - devm_pwm_get()
> - devm_of_pwm_get()
> as it requires a reference to the device for the PWM consumer.
> 
> [1] https://lkml.org/lkml/2019/2/5/770
> 
> Suggested-by: Thierry Reding <thierry.reding@gmail.com>
> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
> ---
>  drivers/pwm/core.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
> index 1581f6a..2835e27 100644
> --- a/drivers/pwm/core.c
> +++ b/drivers/pwm/core.c
> @@ -770,8 +770,13 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
>  	int err;
>  
>  	/* look up via DT first */
> -	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
> -		return of_pwm_get(dev->of_node, con_id);
> +	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) {
> +		pwm = of_pwm_get(dev->of_node, con_id);
> +		if (!IS_ERR(pwm))
> +			device_link_add(dev, pwm->chip->dev,
> +					DL_FLAG_AUTOREMOVE_CONSUMER);
> +		return pwm;
> +	}
>  
>  	/*
>  	 * We look up the provider in the static table typically provided by
> @@ -851,6 +856,8 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
>  	pwm->args.period = chosen->period;
>  	pwm->args.polarity = chosen->polarity;
>  
> +	device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
> +
>  	return pwm;
>  }
>  EXPORT_SYMBOL_GPL(pwm_get);
> @@ -943,6 +950,8 @@ struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np,
>  	if (!IS_ERR(pwm)) {
>  		*ptr = pwm;
>  		devres_add(dev, ptr);
> +		device_link_add(dev, pwm->chip->dev,
> +				DL_FLAG_AUTOREMOVE_CONSUMER);

IMHO it's surprising that devm_of_pwm_get() does more than of_pwm_get()
+ devres stuff. I'd put device_link_add() into of_pwm_get().

Best regards
Uwe
Fabrice Gasnier Feb. 12, 2019, 8:31 a.m. | #2
On 2/11/19 8:06 PM, Uwe Kleine-König wrote:
> Hello Fabrice,
> 
> On Mon, Feb 11, 2019 at 05:12:02PM +0100, Fabrice Gasnier wrote:
>> Add a device link between the PWM consumer and the PWM provider. This
>> enforces the PWM user to get suspended before the PWM provider. It
>> allows proper synchronization of suspend/resume sequences: the PWM user
>> is responsible for properly stopping PWM, before the provider gets
>> suspended: see [1]. Add the device link in:
>> - pwm_get()
>> - devm_pwm_get()
>> - devm_of_pwm_get()
>> as it requires a reference to the device for the PWM consumer.
>>
>> [1] https://lkml.org/lkml/2019/2/5/770
>>
>> Suggested-by: Thierry Reding <thierry.reding@gmail.com>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> ---
>>  drivers/pwm/core.c | 13 +++++++++++--
>>  1 file changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
>> index 1581f6a..2835e27 100644
>> --- a/drivers/pwm/core.c
>> +++ b/drivers/pwm/core.c
>> @@ -770,8 +770,13 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
>>  	int err;
>>  
>>  	/* look up via DT first */
>> -	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
>> -		return of_pwm_get(dev->of_node, con_id);
>> +	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) {
>> +		pwm = of_pwm_get(dev->of_node, con_id);
>> +		if (!IS_ERR(pwm))
>> +			device_link_add(dev, pwm->chip->dev,
>> +					DL_FLAG_AUTOREMOVE_CONSUMER);
>> +		return pwm;
>> +	}
>>  
>>  	/*
>>  	 * We look up the provider in the static table typically provided by
>> @@ -851,6 +856,8 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id)
>>  	pwm->args.period = chosen->period;
>>  	pwm->args.polarity = chosen->polarity;
>>  
>> +	device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
>> +
>>  	return pwm;
>>  }
>>  EXPORT_SYMBOL_GPL(pwm_get);
>> @@ -943,6 +950,8 @@ struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np,
>>  	if (!IS_ERR(pwm)) {
>>  		*ptr = pwm;
>>  		devres_add(dev, ptr);
>> +		device_link_add(dev, pwm->chip->dev,
>> +				DL_FLAG_AUTOREMOVE_CONSUMER);
> 
> IMHO it's surprising that devm_of_pwm_get() does more than of_pwm_get()
> + devres stuff. I'd put device_link_add() into of_pwm_get().

Hi Uwe,

I also agree with this. But I think this implies modifying the API for
of_pwm_get():
 /**
  * of_pwm_get() - request a PWM via the PWM framework
+ * @dev: device for PWM consumer
  * @np: device node to get the PWM from
  * @con_id: consumer name

It seems there aren't much of_pwm_get() users currently.
Does this look sensible ?

Best regards,
Fabrice

> 
> Best regards
> Uwe
>
Uwe Kleine-König Feb. 12, 2019, 9:03 a.m. | #3
Hello Fabrice,

On Tue, Feb 12, 2019 at 09:31:37AM +0100, Fabrice Gasnier wrote:
> On 2/11/19 8:06 PM, Uwe Kleine-König wrote:
> > On Mon, Feb 11, 2019 at 05:12:02PM +0100, Fabrice Gasnier wrote:
> >> @@ -943,6 +950,8 @@ struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np,
> >>  	if (!IS_ERR(pwm)) {
> >>  		*ptr = pwm;
> >>  		devres_add(dev, ptr);
> >> +		device_link_add(dev, pwm->chip->dev,
> >> +				DL_FLAG_AUTOREMOVE_CONSUMER);
> > 
> > IMHO it's surprising that devm_of_pwm_get() does more than of_pwm_get()
> > + devres stuff. I'd put device_link_add() into of_pwm_get().
> 
> Hi Uwe,
> 
> I also agree with this. But I think this implies modifying the API for
> of_pwm_get():
>  /**
>   * of_pwm_get() - request a PWM via the PWM framework
> + * @dev: device for PWM consumer
>   * @np: device node to get the PWM from
>   * @con_id: consumer name
> 
> It seems there aren't much of_pwm_get() users currently.
> Does this look sensible ?

In my eyes this looks sensible, yes.

Best regards
Uwe
Fabrice Gasnier Feb. 13, 2019, 10:51 a.m. | #4
On 2/12/19 10:03 AM, Uwe Kleine-König wrote:
> Hello Fabrice,
> 
> On Tue, Feb 12, 2019 at 09:31:37AM +0100, Fabrice Gasnier wrote:
>> On 2/11/19 8:06 PM, Uwe Kleine-König wrote:
>>> On Mon, Feb 11, 2019 at 05:12:02PM +0100, Fabrice Gasnier wrote:
>>>> @@ -943,6 +950,8 @@ struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np,
>>>>  	if (!IS_ERR(pwm)) {
>>>>  		*ptr = pwm;
>>>>  		devres_add(dev, ptr);
>>>> +		device_link_add(dev, pwm->chip->dev,
>>>> +				DL_FLAG_AUTOREMOVE_CONSUMER);
>>>
>>> IMHO it's surprising that devm_of_pwm_get() does more than of_pwm_get()
>>> + devres stuff. I'd put device_link_add() into of_pwm_get().
>>
>> Hi Uwe,
>>
>> I also agree with this. But I think this implies modifying the API for
>> of_pwm_get():
>>  /**
>>   * of_pwm_get() - request a PWM via the PWM framework
>> + * @dev: device for PWM consumer
>>   * @np: device node to get the PWM from
>>   * @con_id: consumer name
>>
>> It seems there aren't much of_pwm_get() users currently.
>> Does this look sensible ?
> 
> In my eyes this looks sensible, yes.

Hello Uwe,

I just sent a v3 with that change,

Thanks
Fabrice
> 
> Best regards
> Uwe
>

Patch

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 1581f6a..2835e27 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -770,8 +770,13 @@  struct pwm_device *pwm_get(struct device *dev, const char *con_id)
 	int err;
 
 	/* look up via DT first */
-	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
-		return of_pwm_get(dev->of_node, con_id);
+	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) {
+		pwm = of_pwm_get(dev->of_node, con_id);
+		if (!IS_ERR(pwm))
+			device_link_add(dev, pwm->chip->dev,
+					DL_FLAG_AUTOREMOVE_CONSUMER);
+		return pwm;
+	}
 
 	/*
 	 * We look up the provider in the static table typically provided by
@@ -851,6 +856,8 @@  struct pwm_device *pwm_get(struct device *dev, const char *con_id)
 	pwm->args.period = chosen->period;
 	pwm->args.polarity = chosen->polarity;
 
+	device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+
 	return pwm;
 }
 EXPORT_SYMBOL_GPL(pwm_get);
@@ -943,6 +950,8 @@  struct pwm_device *devm_of_pwm_get(struct device *dev, struct device_node *np,
 	if (!IS_ERR(pwm)) {
 		*ptr = pwm;
 		devres_add(dev, ptr);
+		device_link_add(dev, pwm->chip->dev,
+				DL_FLAG_AUTOREMOVE_CONSUMER);
 	} else {
 		devres_free(ptr);
 	}