From 459a25afe97cb3d7f978b90c881f4d7aac8fb755 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Wed, 30 Mar 2016 22:03:27 +0200 Subject: pwm: Get rid of pwm->lock PWM devices are not protected against concurrent accesses. The lock in struct pwm_device might let PWM users think it is, but it's actually only protecting the enabled state. Removing this lock should be fine as long as all PWM users are aware that accesses to the PWM device have to be serialized, which seems to be the case for all of them except the sysfs interface. Patch the sysfs code by adding a lock to the pwm_export struct and making sure it's taken for all relevant accesses to the exported PWM device. Signed-off-by: Boris Brezillon Signed-off-by: Thierry Reding --- drivers/pwm/sysfs.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers/pwm/sysfs.c') diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 9c90886f4123..187ca0875cf6 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -26,6 +26,7 @@ struct pwm_export { struct device child; struct pwm_device *pwm; + struct mutex lock; }; static struct pwm_export *child_to_pwm_export(struct device *child) @@ -53,7 +54,8 @@ static ssize_t period_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { - struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_export *export = child_to_pwm_export(child); + struct pwm_device *pwm = export->pwm; unsigned int val; int ret; @@ -61,7 +63,9 @@ static ssize_t period_store(struct device *child, if (ret) return ret; + mutex_lock(&export->lock); ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val); + mutex_unlock(&export->lock); return ret ? : size; } @@ -79,7 +83,8 @@ static ssize_t duty_cycle_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { - struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_export *export = child_to_pwm_export(child); + struct pwm_device *pwm = export->pwm; unsigned int val; int ret; @@ -87,7 +92,9 @@ static ssize_t duty_cycle_store(struct device *child, if (ret) return ret; + mutex_lock(&export->lock); ret = pwm_config(pwm, val, pwm_get_period(pwm)); + mutex_unlock(&export->lock); return ret ? : size; } @@ -105,13 +112,16 @@ static ssize_t enable_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { - struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_export *export = child_to_pwm_export(child); + struct pwm_device *pwm = export->pwm; int val, ret; ret = kstrtoint(buf, 0, &val); if (ret) return ret; + mutex_lock(&export->lock); + switch (val) { case 0: pwm_disable(pwm); @@ -124,6 +134,8 @@ static ssize_t enable_store(struct device *child, break; } + mutex_unlock(&export->lock); + return ret ? : size; } @@ -151,7 +163,8 @@ static ssize_t polarity_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { - struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_export *export = child_to_pwm_export(child); + struct pwm_device *pwm = export->pwm; enum pwm_polarity polarity; int ret; @@ -162,7 +175,9 @@ static ssize_t polarity_store(struct device *child, else return -EINVAL; + mutex_lock(&export->lock); ret = pwm_set_polarity(pwm, polarity); + mutex_unlock(&export->lock); return ret ? : size; } @@ -203,6 +218,7 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) } export->pwm = pwm; + mutex_init(&export->lock); export->child.release = pwm_export_release; export->child.parent = parent; -- cgit v1.2.3-70-g09d2 From 39100ceea79ff2efeb2fb094baf120c73d5ccf47 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 14 Apr 2016 21:17:43 +0200 Subject: pwm: Switch to the atomic API Replace legacy pwm_get/set_xxx() and pwm_config/enable/disable() calls by pwm_get/apply_state(). Signed-off-by: Boris Brezillon Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 5 ++++- drivers/pwm/sysfs.c | 48 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 12 deletions(-) (limited to 'drivers/pwm/sysfs.c') diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 729d457861fd..b0b87b3b52a6 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -948,13 +948,16 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) for (i = 0; i < chip->npwm; i++) { struct pwm_device *pwm = &chip->pwms[i]; + struct pwm_state state; + + pwm_get_state(pwm, &state); seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label); if (test_bit(PWMF_REQUESTED, &pwm->flags)) seq_puts(s, " requested"); - if (pwm_is_enabled(pwm)) + if (state.enabled) seq_puts(s, " enabled"); seq_puts(s, "\n"); diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 187ca0875cf6..d98599249a05 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -46,8 +46,11 @@ static ssize_t period_show(struct device *child, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_state state; - return sprintf(buf, "%u\n", pwm_get_period(pwm)); + pwm_get_state(pwm, &state); + + return sprintf(buf, "%u\n", state.period); } static ssize_t period_store(struct device *child, @@ -56,6 +59,7 @@ static ssize_t period_store(struct device *child, { struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; + struct pwm_state state; unsigned int val; int ret; @@ -64,7 +68,9 @@ static ssize_t period_store(struct device *child, return ret; mutex_lock(&export->lock); - ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val); + pwm_get_state(pwm, &state); + state.period = val; + ret = pwm_apply_state(pwm, &state); mutex_unlock(&export->lock); return ret ? : size; @@ -75,8 +81,11 @@ static ssize_t duty_cycle_show(struct device *child, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_state state; + + pwm_get_state(pwm, &state); - return sprintf(buf, "%u\n", pwm_get_duty_cycle(pwm)); + return sprintf(buf, "%u\n", state.duty_cycle); } static ssize_t duty_cycle_store(struct device *child, @@ -85,6 +94,7 @@ static ssize_t duty_cycle_store(struct device *child, { struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; + struct pwm_state state; unsigned int val; int ret; @@ -93,7 +103,9 @@ static ssize_t duty_cycle_store(struct device *child, return ret; mutex_lock(&export->lock); - ret = pwm_config(pwm, val, pwm_get_period(pwm)); + pwm_get_state(pwm, &state); + state.duty_cycle = val; + ret = pwm_apply_state(pwm, &state); mutex_unlock(&export->lock); return ret ? : size; @@ -104,8 +116,11 @@ static ssize_t enable_show(struct device *child, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); + struct pwm_state state; - return sprintf(buf, "%d\n", pwm_is_enabled(pwm)); + pwm_get_state(pwm, &state); + + return sprintf(buf, "%d\n", state.enabled); } static ssize_t enable_store(struct device *child, @@ -114,6 +129,7 @@ static ssize_t enable_store(struct device *child, { struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; + struct pwm_state state; int val, ret; ret = kstrtoint(buf, 0, &val); @@ -122,20 +138,24 @@ static ssize_t enable_store(struct device *child, mutex_lock(&export->lock); + pwm_get_state(pwm, &state); + switch (val) { case 0: - pwm_disable(pwm); + state.enabled = false; break; case 1: - ret = pwm_enable(pwm); + state.enabled = true; break; default: ret = -EINVAL; - break; + goto unlock; } - mutex_unlock(&export->lock); + pwm_apply_state(pwm, &state); +unlock: + mutex_unlock(&export->lock); return ret ? : size; } @@ -145,8 +165,11 @@ static ssize_t polarity_show(struct device *child, { const struct pwm_device *pwm = child_to_pwm_device(child); const char *polarity = "unknown"; + struct pwm_state state; + + pwm_get_state(pwm, &state); - switch (pwm_get_polarity(pwm)) { + switch (state.polarity) { case PWM_POLARITY_NORMAL: polarity = "normal"; break; @@ -166,6 +189,7 @@ static ssize_t polarity_store(struct device *child, struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; enum pwm_polarity polarity; + struct pwm_state state; int ret; if (sysfs_streq(buf, "normal")) @@ -176,7 +200,9 @@ static ssize_t polarity_store(struct device *child, return -EINVAL; mutex_lock(&export->lock); - ret = pwm_set_polarity(pwm, polarity); + pwm_get_state(pwm, &state); + state.polarity = polarity; + ret = pwm_apply_state(pwm, &state); mutex_unlock(&export->lock); return ret ? : size; -- cgit v1.2.3-70-g09d2