From d1cd21427747f15920cd726f5f67a07880e7dee4 Mon Sep 17 00:00:00 2001 From: Jonathan Richardson Date: Fri, 16 Oct 2015 17:40:58 -0700 Subject: pwm: Set enable state properly on failed call to enable The pwm_enable() function didn't clear the enabled bit if a call to the driver's ->enable() callback returned an error. The result was that the state of the PWM core was wrong. Clearing the bit when enable returns an error ensures the state is properly set. Tested-by: Jonathan Richardson Reviewed-by: Dmitry Torokhov Signed-off-by: Jonathan Richardson [thierry.reding@gmail.com: add missing kerneldoc for the lock] Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers/pwm/core.c') diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 3f9df3ea3350..b8f6c309c160 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -269,6 +269,7 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip, pwm->pwm = chip->base + i; pwm->hwpwm = i; pwm->polarity = polarity; + mutex_init(&pwm->lock); radix_tree_insert(&pwm_tree, pwm->pwm, pwm); } @@ -473,16 +474,22 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity) if (!pwm->chip->ops->set_polarity) return -ENOSYS; - if (pwm_is_enabled(pwm)) - return -EBUSY; + mutex_lock(&pwm->lock); + + if (pwm_is_enabled(pwm)) { + err = -EBUSY; + goto unlock; + } err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); if (err) - return err; + goto unlock; pwm->polarity = polarity; - return 0; +unlock: + mutex_unlock(&pwm->lock); + return err; } EXPORT_SYMBOL_GPL(pwm_set_polarity); @@ -494,10 +501,22 @@ EXPORT_SYMBOL_GPL(pwm_set_polarity); */ int pwm_enable(struct pwm_device *pwm) { - if (pwm && !test_and_set_bit(PWMF_ENABLED, &pwm->flags)) - return pwm->chip->ops->enable(pwm->chip, pwm); + int err = 0; + + if (!pwm) + return -EINVAL; + + mutex_lock(&pwm->lock); + + if (!test_and_set_bit(PWMF_ENABLED, &pwm->flags)) { + err = pwm->chip->ops->enable(pwm->chip, pwm); + if (err) + clear_bit(PWMF_ENABLED, &pwm->flags); + } + + mutex_unlock(&pwm->lock); - return pwm ? 0 : -EINVAL; + return err; } EXPORT_SYMBOL_GPL(pwm_enable); -- cgit v1.2.3 From 655a03554cbdf73e8114367441f10858baac59bf Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 5 Oct 2015 14:38:32 +0200 Subject: pwm: Return -ENODEV if no PWM lookup match is found When looking up a PWM using the lookup table, assume that all entries will have been added already, so failure to find a match means that no corresponding entry has been registered. This fixes an issue where -EPROBE_DEFER would be returned if the PWM lookup table is empty. After this fix, -EPROBE_DEFER is reserved for situations where no provider has yet registered for a matching entry. Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/pwm/core.c') diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index b8f6c309c160..d24ca5f281b4 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -738,8 +738,10 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) } } - if (!chosen) + if (!chosen) { + pwm = ERR_PTR(-ENODEV); goto out; + } chip = pwmchip_find_by_name(chosen->provider); if (!chip) -- cgit v1.2.3