Message ID | 1434403262-24198-3-git-send-email-jonathar@broadcom.com |
---|---|
State | Superseded |
Headers | show |
On 15-06-15 02:21 PM, Jonathan Richardson wrote: > The pwm_enable function didn't clear the enabled bit if a call to a > clients enable function 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 <jonathar@broadcom.com> > Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> > Signed-off-by: Jonathan Richardson <jonathar@broadcom.com> > --- > drivers/pwm/core.c | 19 ++++++++++++++++--- > include/linux/pwm.h | 2 ++ > 2 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c > index 76b0386..c255267 100644 > --- a/drivers/pwm/core.c > +++ b/drivers/pwm/core.c > @@ -263,6 +263,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); > } > @@ -474,10 +475,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; > > - return pwm ? 0 : -EINVAL; > + 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 err; > } > EXPORT_SYMBOL_GPL(pwm_enable); I meant to add the mutex check in disable also, but what about when PWMF_ENABLED is checked in pwm_set_polarity() and pwm_dbg_show()? Thanks. -- To unsubscribe from this list: send the line "unsubscribe linux-pwm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 76b0386..c255267 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -263,6 +263,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); } @@ -474,10 +475,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; - return pwm ? 0 : -EINVAL; + 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 err; } EXPORT_SYMBOL_GPL(pwm_enable); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 9daf0ef..50f28e6 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -3,6 +3,7 @@ #include <linux/err.h> #include <linux/of.h> +#include <linux/mutex.h> struct pwm_device; struct seq_file; @@ -86,6 +87,7 @@ struct pwm_device { unsigned int pwm; struct pwm_chip *chip; void *chip_data; + struct mutex lock; unsigned int period; /* in nanoseconds */ unsigned int duty_cycle; /* in nanoseconds */