diff options
author | Marek Vasut | 2023-05-12 18:47:36 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2023-07-19 16:21:59 +0200 |
commit | 61aad933e53d5ad2284401b2d0de02aaabcad9e2 (patch) | |
tree | 558c37f4645906d78c0b335996b15fdc8dec3925 /drivers/pwm/sysfs.c | |
parent | c8fa254b77a3238b9e6c489022095556652d353f (diff) |
pwm: sysfs: Do not apply state to already disabled PWMs
[ Upstream commit 38ba83598633373f47951384cfc389181c8d1bed ]
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: 7fd4edc57bbae ("pwm: sysfs: Add suspend/resume support")
Signed-off-by: Marek Vasut <marex@denx.de>
Fixes: ef2bf4997f7d ("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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/pwm/sysfs.c')
-rw-r--r-- | drivers/pwm/sysfs.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index e7db8e45001c..ba125253857e 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -424,6 +424,13 @@ static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm) if (!export) 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; ret = pwm_class_apply_state(export, pwm, &state); if (ret < 0) @@ -448,7 +455,17 @@ static int pwm_class_suspend(struct device *parent) if (!export) continue; + /* + * If pwmchip was not enabled before suspend, save + * state for resume time and do nothing else. + */ export->suspend = state; + if (!state.enabled) { + /* release lock taken in pwm_class_get_state */ + mutex_unlock(&export->lock); + continue; + } + state.enabled = false; ret = pwm_class_apply_state(export, pwm, &state); if (ret < 0) { |