aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorBoris BREZILLON <boris.brezillon@free-electrons.com>2016-03-30 16:03:27 -0400
committerThierry Reding <thierry.reding@gmail.com>2016-05-17 08:44:59 -0400
commit459a25afe97cb3d7f978b90c881f4d7aac8fb755 (patch)
tree233902a29b5d0f418de168ffe531149b997cbcf4 /drivers/pwm
parent4ff66efd59102280a71d432c9f0e89cdaf66b849 (diff)
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 <boris.brezillon@free-electrons.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/core.c19
-rw-r--r--drivers/pwm/sysfs.c24
2 files changed, 24 insertions, 19 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 22cf3959041c..cb762cf51332 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -269,7 +269,6 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip,
269 pwm->pwm = chip->base + i; 269 pwm->pwm = chip->base + i;
270 pwm->hwpwm = i; 270 pwm->hwpwm = i;
271 pwm->polarity = polarity; 271 pwm->polarity = polarity;
272 mutex_init(&pwm->lock);
273 272
274 radix_tree_insert(&pwm_tree, pwm->pwm, pwm); 273 radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
275 } 274 }
@@ -474,22 +473,16 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
474 if (!pwm->chip->ops->set_polarity) 473 if (!pwm->chip->ops->set_polarity)
475 return -ENOSYS; 474 return -ENOSYS;
476 475
477 mutex_lock(&pwm->lock); 476 if (pwm_is_enabled(pwm))
478 477 return -EBUSY;
479 if (pwm_is_enabled(pwm)) {
480 err = -EBUSY;
481 goto unlock;
482 }
483 478
484 err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity); 479 err = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
485 if (err) 480 if (err)
486 goto unlock; 481 return err;
487 482
488 pwm->polarity = polarity; 483 pwm->polarity = polarity;
489 484
490unlock: 485 return 0;
491 mutex_unlock(&pwm->lock);
492 return err;
493} 486}
494EXPORT_SYMBOL_GPL(pwm_set_polarity); 487EXPORT_SYMBOL_GPL(pwm_set_polarity);
495 488
@@ -506,16 +499,12 @@ int pwm_enable(struct pwm_device *pwm)
506 if (!pwm) 499 if (!pwm)
507 return -EINVAL; 500 return -EINVAL;
508 501
509 mutex_lock(&pwm->lock);
510
511 if (!test_and_set_bit(PWMF_ENABLED, &pwm->flags)) { 502 if (!test_and_set_bit(PWMF_ENABLED, &pwm->flags)) {
512 err = pwm->chip->ops->enable(pwm->chip, pwm); 503 err = pwm->chip->ops->enable(pwm->chip, pwm);
513 if (err) 504 if (err)
514 clear_bit(PWMF_ENABLED, &pwm->flags); 505 clear_bit(PWMF_ENABLED, &pwm->flags);
515 } 506 }
516 507
517 mutex_unlock(&pwm->lock);
518
519 return err; 508 return err;
520} 509}
521EXPORT_SYMBOL_GPL(pwm_enable); 510EXPORT_SYMBOL_GPL(pwm_enable);
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 @@
26struct pwm_export { 26struct pwm_export {
27 struct device child; 27 struct device child;
28 struct pwm_device *pwm; 28 struct pwm_device *pwm;
29 struct mutex lock;
29}; 30};
30 31
31static struct pwm_export *child_to_pwm_export(struct device *child) 32static struct pwm_export *child_to_pwm_export(struct device *child)
@@ -53,7 +54,8 @@ static ssize_t period_store(struct device *child,
53 struct device_attribute *attr, 54 struct device_attribute *attr,
54 const char *buf, size_t size) 55 const char *buf, size_t size)
55{ 56{
56 struct pwm_device *pwm = child_to_pwm_device(child); 57 struct pwm_export *export = child_to_pwm_export(child);
58 struct pwm_device *pwm = export->pwm;
57 unsigned int val; 59 unsigned int val;
58 int ret; 60 int ret;
59 61
@@ -61,7 +63,9 @@ static ssize_t period_store(struct device *child,
61 if (ret) 63 if (ret)
62 return ret; 64 return ret;
63 65
66 mutex_lock(&export->lock);
64 ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val); 67 ret = pwm_config(pwm, pwm_get_duty_cycle(pwm), val);
68 mutex_unlock(&export->lock);
65 69
66 return ret ? : size; 70 return ret ? : size;
67} 71}
@@ -79,7 +83,8 @@ static ssize_t duty_cycle_store(struct device *child,
79 struct device_attribute *attr, 83 struct device_attribute *attr,
80 const char *buf, size_t size) 84 const char *buf, size_t size)
81{ 85{
82 struct pwm_device *pwm = child_to_pwm_device(child); 86 struct pwm_export *export = child_to_pwm_export(child);
87 struct pwm_device *pwm = export->pwm;
83 unsigned int val; 88 unsigned int val;
84 int ret; 89 int ret;
85 90
@@ -87,7 +92,9 @@ static ssize_t duty_cycle_store(struct device *child,
87 if (ret) 92 if (ret)
88 return ret; 93 return ret;
89 94
95 mutex_lock(&export->lock);
90 ret = pwm_config(pwm, val, pwm_get_period(pwm)); 96 ret = pwm_config(pwm, val, pwm_get_period(pwm));
97 mutex_unlock(&export->lock);
91 98
92 return ret ? : size; 99 return ret ? : size;
93} 100}
@@ -105,13 +112,16 @@ static ssize_t enable_store(struct device *child,
105 struct device_attribute *attr, 112 struct device_attribute *attr,
106 const char *buf, size_t size) 113 const char *buf, size_t size)
107{ 114{
108 struct pwm_device *pwm = child_to_pwm_device(child); 115 struct pwm_export *export = child_to_pwm_export(child);
116 struct pwm_device *pwm = export->pwm;
109 int val, ret; 117 int val, ret;
110 118
111 ret = kstrtoint(buf, 0, &val); 119 ret = kstrtoint(buf, 0, &val);
112 if (ret) 120 if (ret)
113 return ret; 121 return ret;
114 122
123 mutex_lock(&export->lock);
124
115 switch (val) { 125 switch (val) {
116 case 0: 126 case 0:
117 pwm_disable(pwm); 127 pwm_disable(pwm);
@@ -124,6 +134,8 @@ static ssize_t enable_store(struct device *child,
124 break; 134 break;
125 } 135 }
126 136
137 mutex_unlock(&export->lock);
138
127 return ret ? : size; 139 return ret ? : size;
128} 140}
129 141
@@ -151,7 +163,8 @@ static ssize_t polarity_store(struct device *child,
151 struct device_attribute *attr, 163 struct device_attribute *attr,
152 const char *buf, size_t size) 164 const char *buf, size_t size)
153{ 165{
154 struct pwm_device *pwm = child_to_pwm_device(child); 166 struct pwm_export *export = child_to_pwm_export(child);
167 struct pwm_device *pwm = export->pwm;
155 enum pwm_polarity polarity; 168 enum pwm_polarity polarity;
156 int ret; 169 int ret;
157 170
@@ -162,7 +175,9 @@ static ssize_t polarity_store(struct device *child,
162 else 175 else
163 return -EINVAL; 176 return -EINVAL;
164 177
178 mutex_lock(&export->lock);
165 ret = pwm_set_polarity(pwm, polarity); 179 ret = pwm_set_polarity(pwm, polarity);
180 mutex_unlock(&export->lock);
166 181
167 return ret ? : size; 182 return ret ? : size;
168} 183}
@@ -203,6 +218,7 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm)
203 } 218 }
204 219
205 export->pwm = pwm; 220 export->pwm = pwm;
221 mutex_init(&export->lock);
206 222
207 export->child.release = pwm_export_release; 223 export->child.release = pwm_export_release;
208 export->child.parent = parent; 224 export->child.parent = parent;