diff options
author | Fabrice Gasnier <fabrice.gasnier@st.com> | 2018-10-01 09:23:57 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2018-10-12 07:51:33 -0400 |
commit | 552c02e3e7cfe2744b59de285aaea70021ae95c9 (patch) | |
tree | 53a28e6dca26ab1e000c1ae4e6ed1ad8c72e665e | |
parent | c289d6625237aa785b484b4e94c23b3b91ea7e60 (diff) |
pwm: Send a uevent on the pwmchip device upon channel sysfs (un)export
This patch sends a uevent (KOBJ_CHANGE) on the pwmchipN device,
everytime a pwmX channel has been exported/unexported via sysfs. This
allows udev to implement rules on such events, like:
SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
chown -R root:gpio
/sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770
/sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
'"
This is a replacement patch for commit 7e5d1fd75c3d ("pwm: Set class for
exported channels in sysfs"), see [1].
basic testing:
$ udevadm monitor --environment &
$ echo 0 > /sys/class/pwm/pwmchip0/export
KERNEL[197.321736] change /devices/.../pwm/pwmchip0 (pwm)
ACTION=change
DEVPATH=/devices/.../pwm/pwmchip0
EXPORT=pwm0
SEQNUM=2045
SUBSYSTEM=pwm
[1] https://lkml.org/lkml/2018/9/25/713
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Tested-by: Gottfried Haider <gottfried.haider@gmail.com>
Tested-by: Michal Vokáč <michal.vokac@ysoft.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r-- | drivers/pwm/sysfs.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 4726d43aaa0c..ceb233dd6048 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c | |||
@@ -249,6 +249,7 @@ static void pwm_export_release(struct device *child) | |||
249 | static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | 249 | static int pwm_export_child(struct device *parent, struct pwm_device *pwm) |
250 | { | 250 | { |
251 | struct pwm_export *export; | 251 | struct pwm_export *export; |
252 | char *pwm_prop[2]; | ||
252 | int ret; | 253 | int ret; |
253 | 254 | ||
254 | if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) | 255 | if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) |
@@ -276,6 +277,10 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | |||
276 | export = NULL; | 277 | export = NULL; |
277 | return ret; | 278 | return ret; |
278 | } | 279 | } |
280 | pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm); | ||
281 | pwm_prop[1] = NULL; | ||
282 | kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); | ||
283 | kfree(pwm_prop[0]); | ||
279 | 284 | ||
280 | return 0; | 285 | return 0; |
281 | } | 286 | } |
@@ -288,6 +293,7 @@ static int pwm_unexport_match(struct device *child, void *data) | |||
288 | static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) | 293 | static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) |
289 | { | 294 | { |
290 | struct device *child; | 295 | struct device *child; |
296 | char *pwm_prop[2]; | ||
291 | 297 | ||
292 | if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) | 298 | if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) |
293 | return -ENODEV; | 299 | return -ENODEV; |
@@ -296,6 +302,11 @@ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) | |||
296 | if (!child) | 302 | if (!child) |
297 | return -ENODEV; | 303 | return -ENODEV; |
298 | 304 | ||
305 | pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm); | ||
306 | pwm_prop[1] = NULL; | ||
307 | kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); | ||
308 | kfree(pwm_prop[0]); | ||
309 | |||
299 | /* for device_find_child() */ | 310 | /* for device_find_child() */ |
300 | put_device(child); | 311 | put_device(child); |
301 | device_unregister(child); | 312 | device_unregister(child); |