diff mbox series

pwm: core: Permit unset period when applying configuration of disabled PWMs

Message ID 20230511181853.185685-1-marex@denx.de
State Rejected
Headers show
Series pwm: core: Permit unset period when applying configuration of disabled PWMs | expand

Commit Message

Marek Vasut May 11, 2023, 6:18 p.m. UTC
In case the PWM is not enabled, the period can still be left unconfigured,
i.e. zero . Currently the pwm_class_apply_state() errors out in such a case.
This e.g. makes suspend fail on systems where pwmchip has been exported via
sysfs interface, but left unconfigured before suspend occurred.

Failing case:
"
$ echo 1 > /sys/class/pwm/pwmchip4/export
$ echo mem > /sys/power/state
...
pwm pwmchip4: PM: dpm_run_callback(): pwm_class_suspend+0x1/0xa8 returns -22
pwm pwmchip4: PM: failed to suspend: error -22
PM: Some devices failed to suspend, or early wake event detected
"

Working case:
"
$ echo 1 > /sys/class/pwm/pwmchip4/export
$ echo 100 > /sys/class/pwm/pwmchip4/pwm1/period
$ echo 10 > /sys/class/pwm/pwmchip4/pwm1/duty_cycle
$ echo mem > /sys/power/state
...
"

Permit unset period in pwm_class_apply_state() in case the PWM is disabled
to fix this issue.

Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
Signed-off-by: Marek Vasut <marex@denx.de>
---
Cc: Brian Norris <briannorris@chromium.org>
Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Cc: linux-pwm@vger.kernel.org
---
 drivers/pwm/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Brian Norris May 11, 2023, 9:08 p.m. UTC | #1
Hi,

On Thu, May 11, 2023 at 08:18:53PM +0200, Marek Vasut wrote:
> In case the PWM is not enabled, the period can still be left unconfigured,
> i.e. zero . Currently the pwm_class_apply_state() errors out in such a case.
> This e.g. makes suspend fail on systems where pwmchip has been exported via
> sysfs interface, but left unconfigured before suspend occurred.
> 
> Failing case:
> "
> $ echo 1 > /sys/class/pwm/pwmchip4/export
> $ echo mem > /sys/power/state
> ...
> pwm pwmchip4: PM: dpm_run_callback(): pwm_class_suspend+0x1/0xa8 returns -22
> pwm pwmchip4: PM: failed to suspend: error -22
> PM: Some devices failed to suspend, or early wake event detected
> "
> 
> Working case:
> "
> $ echo 1 > /sys/class/pwm/pwmchip4/export
> $ echo 100 > /sys/class/pwm/pwmchip4/pwm1/period
> $ echo 10 > /sys/class/pwm/pwmchip4/pwm1/duty_cycle
> $ echo mem > /sys/power/state
> ...
> "
> 
> Permit unset period in pwm_class_apply_state() in case the PWM is disabled
> to fix this issue.
> 
> Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
> Signed-off-by: Marek Vasut <marex@denx.de>
> ---
> Cc: Brian Norris <briannorris@chromium.org>
> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: linux-pwm@vger.kernel.org
> ---
>  drivers/pwm/core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
> index 3dacceaef4a9b..87252b70f1c81 100644
> --- a/drivers/pwm/core.c
> +++ b/drivers/pwm/core.c
> @@ -510,8 +510,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
>  	 */
>  	might_sleep();
>  
> -	if (!pwm || !state || !state->period ||
> -	    state->duty_cycle > state->period)
> +	if (!pwm || !state || (state->enabled &&
> +	    (!state->period || state->duty_cycle > state->period)))
>  		return -EINVAL;
>  
>  	chip = pwm->chip;

By making the period assertions conditional, you're allowing people to
write garbage period values via sysfs. However you fix the (legitimate)
bug you point out, you shouldn't regress that. (Now, that's sounding
like we could use some unit tests for the PWM framework...)

You could, for example, also add the bounds checks to
drviers/pwm/sysfs.c's period_store().

Or perhaps you could teach the suspend/resume functions to not bother
calling pwm_apply_state() on a disabled PWM.

Brian
Marek Vasut May 11, 2023, 11:32 p.m. UTC | #2
On 5/11/23 23:08, Brian Norris wrote:
> Hi,

Hi,

> On Thu, May 11, 2023 at 08:18:53PM +0200, Marek Vasut wrote:
>> In case the PWM is not enabled, the period can still be left unconfigured,
>> i.e. zero . Currently the pwm_class_apply_state() errors out in such a case.
>> This e.g. makes suspend fail on systems where pwmchip has been exported via
>> sysfs interface, but left unconfigured before suspend occurred.
>>
>> Failing case:
>> "
>> $ echo 1 > /sys/class/pwm/pwmchip4/export
>> $ echo mem > /sys/power/state
>> ...
>> pwm pwmchip4: PM: dpm_run_callback(): pwm_class_suspend+0x1/0xa8 returns -22
>> pwm pwmchip4: PM: failed to suspend: error -22
>> PM: Some devices failed to suspend, or early wake event detected
>> "
>>
>> Working case:
>> "
>> $ echo 1 > /sys/class/pwm/pwmchip4/export
>> $ echo 100 > /sys/class/pwm/pwmchip4/pwm1/period
>> $ echo 10 > /sys/class/pwm/pwmchip4/pwm1/duty_cycle
>> $ echo mem > /sys/power/state
>> ...
>> "
>>
>> Permit unset period in pwm_class_apply_state() in case the PWM is disabled
>> to fix this issue.
>>
>> Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> ---
>> Cc: Brian Norris <briannorris@chromium.org>
>> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
>> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
>> Cc: Thierry Reding <thierry.reding@gmail.com>
>> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>> Cc: linux-pwm@vger.kernel.org
>> ---
>>   drivers/pwm/core.c | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
>> index 3dacceaef4a9b..87252b70f1c81 100644
>> --- a/drivers/pwm/core.c
>> +++ b/drivers/pwm/core.c
>> @@ -510,8 +510,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
>>   	 */
>>   	might_sleep();
>>   
>> -	if (!pwm || !state || !state->period ||
>> -	    state->duty_cycle > state->period)
>> +	if (!pwm || !state || (state->enabled &&
>> +	    (!state->period || state->duty_cycle > state->period)))
>>   		return -EINVAL;
>>   
>>   	chip = pwm->chip;
> 
> By making the period assertions conditional, you're allowing people to
> write garbage period values via sysfs. However you fix the (legitimate)
> bug you point out, you shouldn't regress that.

I wanted to say, it might be best to fix userspace so that it wouldn't 
export pwmchip and then suspend without configuring it. But (!) this 
actually allows userspace to export pwmchip and that way, block suspend 
completely, because with pwmchip exported and not configured, the system 
just would not suspend. So, yes, this is a legitimate fix for a real 
bug, right ?

> (Now, that's sounding
> like we could use some unit tests for the PWM framework...)

Not just the PWM framework ...

> You could, for example, also add the bounds checks to
> drviers/pwm/sysfs.c's period_store().
> 
> Or perhaps you could teach the suspend/resume functions to not bother
> calling pwm_apply_state() on a disabled PWM.

Right, I think it boils down to -- should this be fixed on the sysfs ABI 
side, or in the pwm core ?
Brian Norris May 12, 2023, 12:51 a.m. UTC | #3
On Fri, May 12, 2023 at 01:32:49AM +0200, Marek Vasut wrote:
> On 5/11/23 23:08, Brian Norris wrote:
> > On Thu, May 11, 2023 at 08:18:53PM +0200, Marek Vasut wrote:
> > > Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
> > > Signed-off-by: Marek Vasut <marex@denx.de>
> > > ---
> > > Cc: Brian Norris <briannorris@chromium.org>
> > > Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> > > Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> > > Cc: Thierry Reding <thierry.reding@gmail.com>
> > > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> > > Cc: linux-pwm@vger.kernel.org
> > > ---
> > >   drivers/pwm/core.c | 4 ++--
> > >   1 file changed, 2 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
> > > index 3dacceaef4a9b..87252b70f1c81 100644
> > > --- a/drivers/pwm/core.c
> > > +++ b/drivers/pwm/core.c
> > > @@ -510,8 +510,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
> > >   	 */
> > >   	might_sleep();
> > > -	if (!pwm || !state || !state->period ||
> > > -	    state->duty_cycle > state->period)
> > > +	if (!pwm || !state || (state->enabled &&
> > > +	    (!state->period || state->duty_cycle > state->period)))
> > >   		return -EINVAL;
> > >   	chip = pwm->chip;
> > 
> > By making the period assertions conditional, you're allowing people to
> > write garbage period values via sysfs. However you fix the (legitimate)
> > bug you point out, you shouldn't regress that.
> 
> I wanted to say, it might be best to fix userspace so that it wouldn't
> export pwmchip and then suspend without configuring it. But (!) this
> actually allows userspace to export pwmchip and that way, block suspend
> completely, because with pwmchip exported and not configured, the system
> just would not suspend. So, yes, this is a legitimate fix for a real bug,
> right ?

It's a real bug, yes. (Quoting myself, "(legitimate) bug you point
out".)

But you're introducing the old one again, so I wouldn't call it a
"legitimate fix."

commit ef2bf4997f7da6efa8540d9cf726c44bf2b863af
[...]
    In particular, I noted that we are now allowing invalid period
    selections, e.g.:

      # echo 1 > /sys/class/pwm/pwmchip0/export
      # cat /sys/class/pwm/pwmchip0/pwm1/period
      100
      # echo 101 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
      [... driver may or may not reject the value, or trigger some logic bug ...]

The only difference is that we'll still *eventually* reject it somewhere
(probably when we try to enable the PWM), but just not at the
"echo 101 > .../duty_cycle" phase.

> > (Now, that's sounding
> > like we could use some unit tests for the PWM framework...)
> 
> Not just the PWM framework ...
> 
> > You could, for example, also add the bounds checks to
> > drviers/pwm/sysfs.c's period_store().
> > 
> > Or perhaps you could teach the suspend/resume functions to not bother
> > calling pwm_apply_state() on a disabled PWM.
> 
> Right, I think it boils down to -- should this be fixed on the sysfs ABI
> side, or in the pwm core ?

I don't know if I have a strong preference (I haven't tried to write it
out to see what looks cleaner / has the fewest holes), I just would
prefer that this isn't allowed:

      # echo 1 > /sys/class/pwm/pwmchip0/export
      # echo 100 > /sys/class/pwm/pwmchip0/pwm1/period
      ### Should fail with EINVAL:
      # echo 101 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle

Brian
Uwe Kleine-König May 12, 2023, 6:22 a.m. UTC | #4
Hello Marek,

On Thu, May 11, 2023 at 08:18:53PM +0200, Marek Vasut wrote:
> In case the PWM is not enabled, the period can still be left unconfigured,
> i.e. zero . Currently the pwm_class_apply_state() errors out in such a case.
> This e.g. makes suspend fail on systems where pwmchip has been exported via
> sysfs interface, but left unconfigured before suspend occurred.
> 
> Failing case:
> "
> $ echo 1 > /sys/class/pwm/pwmchip4/export
> $ echo mem > /sys/power/state
> ...
> pwm pwmchip4: PM: dpm_run_callback(): pwm_class_suspend+0x1/0xa8 returns -22
> pwm pwmchip4: PM: failed to suspend: error -22
> PM: Some devices failed to suspend, or early wake event detected
> "
> 
> Working case:
> "
> $ echo 1 > /sys/class/pwm/pwmchip4/export
> $ echo 100 > /sys/class/pwm/pwmchip4/pwm1/period
> $ echo 10 > /sys/class/pwm/pwmchip4/pwm1/duty_cycle
> $ echo mem > /sys/power/state
> ...
> "
> 
> Permit unset period in pwm_class_apply_state() in case the PWM is disabled
> to fix this issue.
> 
> Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
> Signed-off-by: Marek Vasut <marex@denx.de>
> ---
> Cc: Brian Norris <briannorris@chromium.org>
> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: linux-pwm@vger.kernel.org
> ---
>  drivers/pwm/core.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
> index 3dacceaef4a9b..87252b70f1c81 100644
> --- a/drivers/pwm/core.c
> +++ b/drivers/pwm/core.c
> @@ -510,8 +510,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
>  	 */
>  	might_sleep();
>  
> -	if (!pwm || !state || !state->period ||
> -	    state->duty_cycle > state->period)
> +	if (!pwm || !state || (state->enabled &&
> +	    (!state->period || state->duty_cycle > state->period)))

While I tend to agree that the checks about period and duty_cycle are
(somewhat) irrelevant if enabled == false, I fear we'd break assumptions
here as some drivers configure duty_cycle/period in hardware even with
.enabled == false, and so proably rely on period > 0 and duty_cycle <=
period.

Another approach would be to skip pwm_apply_state() in
pwm_class_suspend() if the state is already disabled. That one sounds
safer.

Best regards
Uwe
Marek Vasut May 12, 2023, 12:20 p.m. UTC | #5
On 5/12/23 08:22, Uwe Kleine-König wrote:
> Hello Marek,
> 
> On Thu, May 11, 2023 at 08:18:53PM +0200, Marek Vasut wrote:
>> In case the PWM is not enabled, the period can still be left unconfigured,
>> i.e. zero . Currently the pwm_class_apply_state() errors out in such a case.
>> This e.g. makes suspend fail on systems where pwmchip has been exported via
>> sysfs interface, but left unconfigured before suspend occurred.
>>
>> Failing case:
>> "
>> $ echo 1 > /sys/class/pwm/pwmchip4/export
>> $ echo mem > /sys/power/state
>> ...
>> pwm pwmchip4: PM: dpm_run_callback(): pwm_class_suspend+0x1/0xa8 returns -22
>> pwm pwmchip4: PM: failed to suspend: error -22
>> PM: Some devices failed to suspend, or early wake event detected
>> "
>>
>> Working case:
>> "
>> $ echo 1 > /sys/class/pwm/pwmchip4/export
>> $ echo 100 > /sys/class/pwm/pwmchip4/pwm1/period
>> $ echo 10 > /sys/class/pwm/pwmchip4/pwm1/duty_cycle
>> $ echo mem > /sys/power/state
>> ...
>> "
>>
>> Permit unset period in pwm_class_apply_state() in case the PWM is disabled
>> to fix this issue.
>>
>> Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> ---
>> Cc: Brian Norris <briannorris@chromium.org>
>> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
>> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
>> Cc: Thierry Reding <thierry.reding@gmail.com>
>> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>> Cc: linux-pwm@vger.kernel.org
>> ---
>>   drivers/pwm/core.c | 4 ++--
>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
>> index 3dacceaef4a9b..87252b70f1c81 100644
>> --- a/drivers/pwm/core.c
>> +++ b/drivers/pwm/core.c
>> @@ -510,8 +510,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
>>   	 */
>>   	might_sleep();
>>   
>> -	if (!pwm || !state || !state->period ||
>> -	    state->duty_cycle > state->period)
>> +	if (!pwm || !state || (state->enabled &&
>> +	    (!state->period || state->duty_cycle > state->period)))
> 
> While I tend to agree that the checks about period and duty_cycle are
> (somewhat) irrelevant if enabled == false, I fear we'd break assumptions
> here as some drivers configure duty_cycle/period in hardware even with
> .enabled == false, and so proably rely on period > 0 and duty_cycle <=
> period.
> 
> Another approach would be to skip pwm_apply_state() in
> pwm_class_suspend() if the state is already disabled. That one sounds
> safer.

I am not convinced that would be identical behavior.

If we skip apply_state call on PWMs exported via sysfs interface which 
are enabled=false , then the drivers wouldn't have their apply_state 
callback called to disable the PWM before suspend ... I think ... which 
seems like a problem to me ?
Marek Vasut May 12, 2023, 4:50 p.m. UTC | #6
On 5/12/23 02:51, Brian Norris wrote:
> On Fri, May 12, 2023 at 01:32:49AM +0200, Marek Vasut wrote:
>> On 5/11/23 23:08, Brian Norris wrote:
>>> On Thu, May 11, 2023 at 08:18:53PM +0200, Marek Vasut wrote:
>>>> Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
>>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>>> ---
>>>> Cc: Brian Norris <briannorris@chromium.org>
>>>> Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
>>>> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
>>>> Cc: Thierry Reding <thierry.reding@gmail.com>
>>>> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
>>>> Cc: linux-pwm@vger.kernel.org
>>>> ---
>>>>    drivers/pwm/core.c | 4 ++--
>>>>    1 file changed, 2 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
>>>> index 3dacceaef4a9b..87252b70f1c81 100644
>>>> --- a/drivers/pwm/core.c
>>>> +++ b/drivers/pwm/core.c
>>>> @@ -510,8 +510,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
>>>>    	 */
>>>>    	might_sleep();
>>>> -	if (!pwm || !state || !state->period ||
>>>> -	    state->duty_cycle > state->period)
>>>> +	if (!pwm || !state || (state->enabled &&
>>>> +	    (!state->period || state->duty_cycle > state->period)))
>>>>    		return -EINVAL;
>>>>    	chip = pwm->chip;
>>>
>>> By making the period assertions conditional, you're allowing people to
>>> write garbage period values via sysfs. However you fix the (legitimate)
>>> bug you point out, you shouldn't regress that.
>>
>> I wanted to say, it might be best to fix userspace so that it wouldn't
>> export pwmchip and then suspend without configuring it. But (!) this
>> actually allows userspace to export pwmchip and that way, block suspend
>> completely, because with pwmchip exported and not configured, the system
>> just would not suspend. So, yes, this is a legitimate fix for a real bug,
>> right ?
> 
> It's a real bug, yes. (Quoting myself, "(legitimate) bug you point
> out".)
> 
> But you're introducing the old one again, so I wouldn't call it a
> "legitimate fix."
> 
> commit ef2bf4997f7da6efa8540d9cf726c44bf2b863af
> [...]
>      In particular, I noted that we are now allowing invalid period
>      selections, e.g.:
> 
>        # echo 1 > /sys/class/pwm/pwmchip0/export
>        # cat /sys/class/pwm/pwmchip0/pwm1/period
>        100
>        # echo 101 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
>        [... driver may or may not reject the value, or trigger some logic bug ...]
> 
> The only difference is that we'll still *eventually* reject it somewhere
> (probably when we try to enable the PWM), but just not at the
> "echo 101 > .../duty_cycle" phase.
> 
>>> (Now, that's sounding
>>> like we could use some unit tests for the PWM framework...)
>>
>> Not just the PWM framework ...
>>
>>> You could, for example, also add the bounds checks to
>>> drviers/pwm/sysfs.c's period_store().
>>>
>>> Or perhaps you could teach the suspend/resume functions to not bother
>>> calling pwm_apply_state() on a disabled PWM.
>>
>> Right, I think it boils down to -- should this be fixed on the sysfs ABI
>> side, or in the pwm core ?
> 
> I don't know if I have a strong preference (I haven't tried to write it
> out to see what looks cleaner / has the fewest holes), I just would
> prefer that this isn't allowed:
> 
>        # echo 1 > /sys/class/pwm/pwmchip0/export
>        # echo 100 > /sys/class/pwm/pwmchip0/pwm1/period
>        ### Should fail with EINVAL:
>        # echo 101 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle

So, I sent the sysfs variant of this patch just now. I think maybe that 
is the better option.
Thierry Reding May 16, 2023, 9:42 a.m. UTC | #7
On Fri, May 12, 2023 at 02:20:12PM +0200, Marek Vasut wrote:
> On 5/12/23 08:22, Uwe Kleine-König wrote:
> > Hello Marek,
> > 
> > On Thu, May 11, 2023 at 08:18:53PM +0200, Marek Vasut wrote:
> > > In case the PWM is not enabled, the period can still be left unconfigured,
> > > i.e. zero . Currently the pwm_class_apply_state() errors out in such a case.
> > > This e.g. makes suspend fail on systems where pwmchip has been exported via
> > > sysfs interface, but left unconfigured before suspend occurred.
> > > 
> > > Failing case:
> > > "
> > > $ echo 1 > /sys/class/pwm/pwmchip4/export
> > > $ echo mem > /sys/power/state
> > > ...
> > > pwm pwmchip4: PM: dpm_run_callback(): pwm_class_suspend+0x1/0xa8 returns -22
> > > pwm pwmchip4: PM: failed to suspend: error -22
> > > PM: Some devices failed to suspend, or early wake event detected
> > > "
> > > 
> > > Working case:
> > > "
> > > $ echo 1 > /sys/class/pwm/pwmchip4/export
> > > $ echo 100 > /sys/class/pwm/pwmchip4/pwm1/period
> > > $ echo 10 > /sys/class/pwm/pwmchip4/pwm1/duty_cycle
> > > $ echo mem > /sys/power/state
> > > ...
> > > "
> > > 
> > > Permit unset period in pwm_class_apply_state() in case the PWM is disabled
> > > to fix this issue.
> > > 
> > > Fixes: ef2bf4997f7d ("pwm: Improve args checking in pwm_apply_state()")
> > > Signed-off-by: Marek Vasut <marex@denx.de>
> > > ---
> > > Cc: Brian Norris <briannorris@chromium.org>
> > > Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
> > > Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> > > Cc: Thierry Reding <thierry.reding@gmail.com>
> > > Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> > > Cc: linux-pwm@vger.kernel.org
> > > ---
> > >   drivers/pwm/core.c | 4 ++--
> > >   1 file changed, 2 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
> > > index 3dacceaef4a9b..87252b70f1c81 100644
> > > --- a/drivers/pwm/core.c
> > > +++ b/drivers/pwm/core.c
> > > @@ -510,8 +510,8 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
> > >   	 */
> > >   	might_sleep();
> > > -	if (!pwm || !state || !state->period ||
> > > -	    state->duty_cycle > state->period)
> > > +	if (!pwm || !state || (state->enabled &&
> > > +	    (!state->period || state->duty_cycle > state->period)))
> > 
> > While I tend to agree that the checks about period and duty_cycle are
> > (somewhat) irrelevant if enabled == false, I fear we'd break assumptions
> > here as some drivers configure duty_cycle/period in hardware even with
> > .enabled == false, and so proably rely on period > 0 and duty_cycle <=
> > period.
> > 
> > Another approach would be to skip pwm_apply_state() in
> > pwm_class_suspend() if the state is already disabled. That one sounds
> > safer.
> 
> I am not convinced that would be identical behavior.
> 
> If we skip apply_state call on PWMs exported via sysfs interface which are
> enabled=false , then the drivers wouldn't have their apply_state callback
> called to disable the PWM before suspend ... I think ... which seems like a
> problem to me ?

If a PWM exported via sysfs has enabled=false, then it should already be
disabled, so calling pwm_apply_state() on them to disable them should be
a no-op.

Thierry
diff mbox series

Patch

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 3dacceaef4a9b..87252b70f1c81 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -510,8 +510,8 @@  int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
 	 */
 	might_sleep();
 
-	if (!pwm || !state || !state->period ||
-	    state->duty_cycle > state->period)
+	if (!pwm || !state || (state->enabled &&
+	    (!state->period || state->duty_cycle > state->period)))
 		return -EINVAL;
 
 	chip = pwm->chip;