pwm: sysfs: Do not apply state to already disabled PWMs

If the PWM is exported but not enabled, do not call pwm_class_apply_state().
First of all, in this case, period may still be unconfigured and this would
make pwm_class_apply_state() return -EINVAL, and then suspend would fail.
Second, it makes little sense to apply state onto PWM that is not enabled
before suspend.

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
...
"

Do not call pwm_class_apply_state() in case the PWM is disabled
to fix this issue.

Fixes: 7fd4edc57b ("pwm: sysfs: Add suspend/resume support")
Signed-off-by: Marek Vasut <marex@denx.de>
Fixes: ef2bf4997f ("pwm: Improve args checking in pwm_apply_state()")
Reviewed-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
This commit is contained in:
Marek Vasut 2023-05-12 18:47:36 +02:00 committed by Thierry Reding
parent 661dfb7f46
commit 38ba835986

View File

@ -424,6 +424,13 @@ static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm)
if (!export) if (!export)
continue; continue;
/* If pwmchip was not enabled before suspend, do nothing. */
if (!export->suspend.enabled) {
/* release lock taken in pwm_class_get_state */
mutex_unlock(&export->lock);
continue;
}
state.enabled = export->suspend.enabled; state.enabled = export->suspend.enabled;
ret = pwm_class_apply_state(export, pwm, &state); ret = pwm_class_apply_state(export, pwm, &state);
if (ret < 0) if (ret < 0)
@ -448,7 +455,17 @@ static int pwm_class_suspend(struct device *parent)
if (!export) if (!export)
continue; continue;
/*
* If pwmchip was not enabled before suspend, save
* state for resume time and do nothing else.
*/
export->suspend = state; export->suspend = state;
if (!state.enabled) {
/* release lock taken in pwm_class_get_state */
mutex_unlock(&export->lock);
continue;
}
state.enabled = false; state.enabled = false;
ret = pwm_class_apply_state(export, pwm, &state); ret = pwm_class_apply_state(export, pwm, &state);
if (ret < 0) { if (ret < 0) {