summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Hsu <davidhsu@google.com>2016-08-09 14:57:46 -0700
committerBen Hutchings <ben@decadent.org.uk>2017-02-23 03:53:57 +0000
commit1eb985ab574b02b637bcc0aa94f00b795855ac6a (patch)
treee1e9ad9cd0585631e25b039918cfb690aef0e8a6
parentf25fec22d4cbc3b921356f4600f48e4eea8a0f7d (diff)
downloadlinux-stable-1eb985ab574b02b637bcc0aa94f00b795855ac6a.tar.gz
linux-stable-1eb985ab574b02b637bcc0aa94f00b795855ac6a.tar.bz2
linux-stable-1eb985ab574b02b637bcc0aa94f00b795855ac6a.zip
pwm: Unexport children before chip removal
commit 0733424c9ba9f42242409d1ece780777272f7ea1 upstream. Exported pwm channels aren't removed before the pwmchip and are leaked. This results in invalid sysfs files. This fix removes all exported pwm channels before chip removal. Signed-off-by: David Hsu <davidhsu@google.com> Fixes: 76abbdde2d95 ("pwm: Add sysfs interface") Signed-off-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--drivers/pwm/core.c2
-rw-r--r--drivers/pwm/sysfs.c18
-rw-r--r--include/linux/pwm.h5
3 files changed, 25 insertions, 0 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index d2c35920ff08..825b5e48be08 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -293,6 +293,8 @@ int pwmchip_remove(struct pwm_chip *chip)
unsigned int i;
int ret = 0;
+ pwmchip_sysfs_unexport_children(chip);
+
mutex_lock(&pwm_lock);
for (i = 0; i < chip->npwm; i++) {
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 4bd0c639e16d..6c88e1adf637 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -340,6 +340,24 @@ void pwmchip_sysfs_unexport(struct pwm_chip *chip)
}
}
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+ struct device *parent;
+ unsigned int i;
+
+ parent = class_find_device(&pwm_class, NULL, chip,
+ pwmchip_sysfs_match);
+ if (!parent)
+ return;
+
+ for (i = 0; i < chip->npwm; i++) {
+ struct pwm_device *pwm = &chip->pwms[i];
+
+ if (test_bit(PWMF_EXPORTED, &pwm->flags))
+ pwm_unexport_child(parent, pwm);
+ }
+}
+
static int __init pwm_sysfs_init(void)
{
return class_register(&pwm_class);
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index e90628cac8fa..84e526a12def 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -299,6 +299,7 @@ static inline void pwm_add_table(struct pwm_lookup *table, size_t num)
#ifdef CONFIG_PWM_SYSFS
void pwmchip_sysfs_export(struct pwm_chip *chip);
void pwmchip_sysfs_unexport(struct pwm_chip *chip);
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip);
#else
static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
{
@@ -307,6 +308,10 @@ static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip)
{
}
+
+static inline void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+}
#endif /* CONFIG_PWM_SYSFS */
#endif /* __LINUX_PWM_H */