pwm: add sysfs interface
Subsystems (2)
PATCH v4 1/1 pwm: add sysfs interface
Add a simple sysfs interface to the generic PWM framework.
/sys/class/pwm/
`-- pwmchipN/ for each PWM chip
|-- export (w/o) ask the kernel to export a PWM channel
|-- npwm (r/o) number of PWM channels in this PWM chip
|-- pwmX/ for each exported PWM channel
| |-- duty (r/w) duty cycle (in nanoseconds)
| |-- enable (r/w) enable/disable PWM
| |-- period (r/w) period (in nanoseconds)
| `-- polarity (r/w) polarity of PWM (normal/inversed)
`-- unexport (w/o) return a PWM channel to the kernel---
v4: * address a number of issues pointed out by Thierry Reding
- fix some typos and wording issues in the Documentation
- rename the new source file to sysfs.c
- rename some of the variables in sysfs.c to clarify them
- fix the period store so it does not change the duty cycle
- change the polarity attribute to use a string representation
- add a warning message is the pwmchip_sysfs_export() fails
v3: * fix an issue with the export/unexport of the PWM chip
v2: * add API documentation and update Documentation/pwm.txt
* fix some issues pointed out by Ryan Mallon
* add the pwm attributes to dev.groups so they are created when the device is registered for the exported PWM
v1: * Based on previous work by Lars Poecshel
Documentation/ABI/testing/sysfs-class-pwm | 78 +++++++ Documentation/pwm.txt | 36 +++ drivers/pwm/Kconfig | 12 + drivers/pwm/Makefile | 1 + drivers/pwm/core.c | 25 ++- drivers/pwm/sysfs.c | 351 ++++++++++++++++++++++++++++++ include/linux/pwm.h | 29 ++- 7 files changed, 529 insertions(+), 3 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-pwm create mode 100644 drivers/pwm/sysfs.c
Documentation/ABI/testing/sysfs-class-pwm new file +78 -0
@@ -0,0 +1,78 @@ +What: /sys/class/pwm/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + The pwm/ class sub-directory belongs to the Generic PWM + Framework and provides a sysfs interface for using PWM + channels. + +What: /sys/class/pwm/pwmchipN/ +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + A /sys/class/pwm/pwmchipN directory is created for each + probed PWM controller/chip where N is the base of the + PWM chip. + +What: /sys/class/pwm/pwmchipN/npwm +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + The number of PWM channels supported by the PWM chip. + +What: /sys/class/pwm/pwmchipN/export +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Exports a PWM channel from the PWM chip for sysfs control. + Value is between 0 and /sys/class/pwm/pwmchipN/npwm - 1. + +What: /sys/class/pwm/pwmchipN/unexport +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Unexports a PWM channel. + +What: /sys/class/pwm/pwmchipN/pwmX +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + A /sys/class/pwm/pwmchipN/pwmX directory is created for + each exported PWM channel where X is the exported PWM + channel number. + +What: /sys/class/pwm/pwmchipN/pwmX/period +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Sets the PWM period in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/duty +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Sets the PWM duty cycle in nanoseconds. + +What: /sys/class/pwm/pwmchipN/pwmX/polarity +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Sets the output polarity of the PWM to "normal" or "inversed". + +What: /sys/class/pwm/pwmchipN/pwmX/enable +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Enables/disables the PWM. + 0 is disabled + 1 is enabled
Documentation/pwm.txt +36 -0
@@ -45,6 +45,42 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns); To start/stop toggling the PWM output use pwm_enable()/pwm_disable(). +Using PWMs with the sysfs interface +----------------------------------- + +You have to enable CONFIG_PWM_SYSFS in your kernel configuration to use +the sysfs interface. It is exposed at /sys/class/pwm/. Each probed PWM +controller/chip will be exported as pwmchipN, where N is the base of the +PWM chip. Inside the directory you will find: + +npwm - The number of PWM channels this chip supports (read-only). + +export - Exports a PWM channel for use with sysfs (write-only). + +unexport - Unexports a PWM channel from sysfs (write-only). + +The PWM channels are numbered using a per-chip index from 0 to npwm-1. + +When a PWM channel is exported a pwmX directory will be created in the +pwmchipN directory it is associated with, where X is the number of the +channel that was exported. The following properties will then be available: + +period - The total period of the PWM signal (read/write). + Value is in nanoseconds and is the sum of the active and inactive + time of the PWM. + +duty - The active time of the PWM (read/write). + Value is in nanoseconds and must be less than the period. + +polarity - Changes the polarity of the PWM (read/write). + Writes to this property only work if the PWM chip supports changing + the polarity. The polarity can only be changed if the PWM is not + enabled. Value is the string "normal" or "inversed". + +enable - Enables/disables the PWM (read/write). + 0 - disabled + 1 - enabled + Implementing a PWM driver -------------------------
drivers/pwm/Kconfig +12 -0
@@ -28,6 +28,18 @@ menuconfig PWM if PWM +config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have a + pwmX directory in the pwmchipN it is associated with. + config PWM_AB8500 tristate "AB8500 PWM support" depends on AB8500_CORE && ARCH_U8500
drivers/pwm/Makefile +1 -0
@@ -1,4 +1,5 @@ obj-$(CONFIG_PWM) += core.o +obj-$(CONFIG_PWM_SYSFS) += sysfs.o obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
drivers/pwm/core.c +23 -2
@@ -274,6 +274,8 @@ int pwmchip_add(struct pwm_chip *chip)if (IS_ENABLED (CONFIG_OF ))of_pwmchip_add (chip); +pwmchip_sysfs_export (chip); + out:mutex_unlock (&pwm_lock);return ret;
@@ -310,6 +312,8 @@ int pwmchip_remove(struct pwm_chip *chip)free_pwms (chip); +pwmchip_sysfs_unexport (chip); + out:mutex_unlock (&pwm_lock);return ret;
@@ -402,10 +406,19 @@ EXPORT_SYMBOL_GPL(pwm_free);*/ int pwm_config (struct pwm_device *pwm,int duty_ns,int period_ns) { +int err; +if (!pwm || duty_ns <0 || period_ns <=0 || duty_ns > period_ns)return -EINVAL ; -return pwm->chip->ops->config (pwm->chip, pwm, duty_ns, period_ns); + err = pwm->chip->ops->config (pwm->chip, pwm, duty_ns, period_ns); +if (err) +return err; + + pwm->duty_cycle = duty_ns; + pwm->period = period_ns; + +return 0 ; }EXPORT_SYMBOL_GPL (pwm_config);
@@ -418,6 +431,8 @@ EXPORT_SYMBOL_GPL(pwm_config);*/ int pwm_set_polarity (struct pwm_device *pwm,enum pwm_polarity polarity) { +int err; +if (!pwm || !pwm->chip->ops)return -EINVAL ;
@@ -427,7 +442,13 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)if (test_bit (PWMF_ENABLED , &pwm->flags))return -EBUSY ; -return pwm->chip->ops->set_polarity (pwm->chip, pwm, polarity); + err = pwm->chip->ops->set_polarity (pwm->chip, pwm, polarity); +if (err) +return err; + + pwm->polarity = polarity; + +return 0 ; }EXPORT_SYMBOL_GPL (pwm_set_polarity);
drivers/pwm/sysfs.c new file +351 -0
351 lines not on this page · raw message
include/linux/pwm.h +28 -1
@@ -76,6 +76,7 @@ enum pwm_polarity {enum {PWMF_REQUESTED =1 <<0 ,PWMF_ENABLED =1 <<1 , +PWMF_EXPORTED =1 <<2 , };struct pwm_device {
@@ -86,7 +87,9 @@ struct pwm_device {struct pwm_chip *chip;void *chip_data; -unsigned int period;/* in nanoseconds */ +unsigned int period;/* in nanoseconds */ +unsigned int duty_cycle;/* in nanoseconds */ +enum pwm_polarity polarity; };static inline void pwm_set_period (struct pwm_device *pwm,unsigned int period)
@@ -100,6 +103,17 @@ static inline unsigned int pwm_get_period(struct pwm_device *pwm)return pwm ? pwm->period :0 ; } +static inline void pwm_set_duty_cycle (struct pwm_device *pwm,unsigned int duty) +{ +if (pwm) + pwm->duty_cycle = duty; +} + +static inline unsigned int pwm_get_duty_cycle (struct pwm_device *pwm) +{ +return pwm ? pwm->duty_cycle :0 ; +} +/* * pwm_set_polarity - configure the polarity of a PWM signal */
@@ -278,4 +292,17 @@ static inline void pwm_add_table(struct pwm_lookup *table, size_t num) }#endif +#ifdef CONFIG_PWM_SYSFS +void pwmchip_sysfs_export (struct pwm_chip *chip); +void pwmchip_sysfs_unexport (struct pwm_chip *chip); +#else +static inline void pwmchip_sysfs_export (struct pwm_chip *chip) +{ +} + +static inline void pwmchip_sysfs_unexport (struct pwm_chip *chip) +{ +} +#endif /* CONFIG_PWM_SYSFS */ +#endif /* __LINUX_PWM_H */
Signature · 1 line
1.8.1.4
On Mon, Jun 10, 2013 at 04:12:07PM -0700, H Hartley Sweeten wrote:
[...]
Documentation/ABI/testing/sysfs-class-pwm line 62
Quoted 6 lines
Documentation/ABI/testing/sysfs-class-pwm new file +6
-0+What: /sys/class/pwm/pwmchipN/pwmX/duty +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Sets the PWM duty cycle in nanoseconds.
Sorry, I should've been more specific before. I'd like this to be named duty_cycle. We now have the pwm_{set,get}_duty_cycle() accessors and I'd like to eventually use the spelled-out form consistently.
drivers/pwm/Kconfig menuconfig PWM · line 41
Quoted 11 lines
drivers/pwm/Kconfig +11
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have a + pwmX directory in the pwmchipN it is associated with.
I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the IS_ENABLED() macro. We already have the same issue with DEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specific Kconfig option.
In order not to burden you with too much work, one option for now would be to unconditionally build the sysfs.c file and use something along these lines in pwmchip_sysfs_{,un}export():
if (!IS_ENABLED(CONFIG_PWM_SYSFS)) return;
Which should allow the compiler to throw away all PWM_SYSFS-related code in that file, leaving an empty function. It's not the optimal solution, which would require the sysfs code to go into core.c and be conditionalized there, but it's good enough. I can always go and clean up that code later (maybe doing the same for DEBUG_FS while at it).
The big advantage of this is that we get full compile coverage of the sysfs interface, whether it's enabled or not. Calling an empty function once when the chip is registered is an acceptable overhead.
Quoted 1 line
drivers/pwm/sysfs.c +0
-0
[...]
drivers/pwm/sysfs.c line 151
Quoted 12 lines
drivers/pwm/sysfs.c +12
-0+static ssize_t pwm_polarity_store (struct device *child, +struct device_attribute *attr, +const char *buf,size_t size) +{ +struct pwm_device *pwm =child_to_pwm_device (child); +enum pwm_polarity polarity; +int ret; + +if (strncmp (buf,"normal" ,strlen ("normal" )) ==0 ) { + polarity =PWM_POLARITY_NORMAL ; + }else if (strncmp (buf,"inversed" ,strlen ("inversed" )) ==0 ) { + polarity =PWM_POLARITY_INVERSED ;
I think you can use sysfs_streq() here. And no need for {} on single- line blocks.
drivers/pwm/sysfs.c line 238
Quoted 12 lines
drivers/pwm/sysfs.c +12
-0+static int pwm_unexport_child (struct device *parent,struct pwm_device *pwm) +{ +struct device *child; + +if (!test_and_clear_bit (PWMF_EXPORTED , &pwm->flags)) +return -ENODEV ; + + child =device_find_child (parent, pwm, pwm_unexport_match); +if (!child) +return -ENODEV ; + +put_device (child);/* for device_find_child() */
Nit: can you put the comment on a line of its own above the code, please?
drivers/pwm/sysfs.c line 342
Quoted 8 lines
drivers/pwm/sysfs.c +8
-0+void pwmchip_sysfs_unexport (struct pwm_chip *chip) +{ +struct device *parent; + + parent =class_find_device (&pwm_class,NULL , chip, + pwmchip_sysfs_match); +if (parent) { +put_device (parent);/* for class_find_device() */
Same here.
Thierry
Quoted 36 lines · Thierry Reding
On Mon, Jun 10, 2013 at 04:12:07PM -0700, H Hartley Sweeten wrote:
[...]Documentation/ABI/testing/sysfs-class-pwm line 62
Quoted 6 lines
Documentation/ABI/testing/sysfs-class-pwm new file +6
-0+What: /sys/class/pwm/pwmchipN/pwmX/duty +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Sets the PWM duty cycle in nanoseconds.Sorry, I should've been more specific before. I'd like this to be named
duty_cycle. We now have the pwm_{set,get}_duty_cycle() accessors and I'd like to eventually use the spelled-out form consistently.drivers/pwm/Kconfig menuconfig PWM · line 41
Quoted 11 lines
drivers/pwm/Kconfig +11
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have a + pwmX directory in the pwmchipN it is associated with.I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the
IS_ENABLED()macro. We already have the same issue withDEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specificKconfigoption.In order not to burden you with too much work, one option for now would be to unconditionally build the
sysfs.cfile and use something along these lines in pwmchip_sysfs_{,un}export():
Quoted 5 lines
if (!IS_ENABLED(CONFIG_PWM_SYSFS)) return;Which should allow the compiler to throw away all PWM_SYSFS-related code in that file, leaving an empty function.
Won't that also cause the compiler to spew a bunch of warnings about unreachable code in the !CONFIG_PWM_SYSFS case? We have the unreachable() macro, but that isn't supported nicely by all compilers.
If CONFIG_SYSFS is not enabled and sysfs.c is using functions that now do not exist, that will cause compile errors, since the compiler will still attempt to compile all of the code, even though it will remove most of it after doing so.
Also, any functions that are extern will also end up generating empty functions in the kernel binary (static linkage functions should disappear completely). This is obviously very negligible in size, but using a proper Kconfig option results in zero size if the option is compiled out.
Quoted 10 lines
It's not the optimal
solution, which would require the sysfs code to go intocore.cand be conditionalized there, but it's good enough. I can always go and clean up that code later (maybe doing the same forDEBUG_FSwhile at it).The big advantage of this is that we get full compile coverage of the sysfs interface, whether it's enabled or not. Calling an empty function once when the chip is registered is an acceptable overhead.
Why not just make CONFIG_PWM_SYSFS default y, so that if CONFIG_SYSFS is enabled (which should be true for the vast majority of test configs) that pwm sysfs is also enabled?
The IS_ENABLED method just seems very messy for a very small gain.
~Ryan
Quoted 13 lines · Ryan Mallon
Quoted 12 lines · Thierry Reding
On Mon, Jun 10, 2013 at 04:12:07PM -0700, H Hartley Sweeten wrote:
[...]Documentation/ABI/testing/sysfs-class-pwm line 62
Quoted 6 lines
Documentation/ABI/testing/sysfs-class-pwm new file +6
-0+What: /sys/class/pwm/pwmchipN/pwmX/duty +Date: May 2013 +KernelVersion: 3.11 +Contact: H Hartley Sweeten <[email protected]> +Description: + Sets the PWM duty cycle in nanoseconds.Sorry, I should've been more specific before. I'd like this to be named
duty_cycle. We now have the pwm_{set,get}_duty_cycle() accessors and I'd like to eventually use the spelled-out form consistently.
Ok. I'll change this.
Quoted 54 lines
Quoted 23 lines
drivers/pwm/Kconfig menuconfig PWM · line 41
Quoted 11 lines
drivers/pwm/Kconfig +11
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have a + pwmX directory in the pwmchipN it is associated with.I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the
IS_ENABLED()macro. We already have the same issue withDEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specificKconfigoption.In order not to burden you with too much work, one option for now would be to unconditionally build the
sysfs.cfile and use something along these lines in pwmchip_sysfs_{,un}export():Quoted 5 lines
if (!IS_ENABLED(CONFIG_PWM_SYSFS)) return;Which should allow the compiler to throw away all PWM_SYSFS-related code in that file, leaving an empty function.
Won't that also cause the compiler to spew a bunch of warnings about unreachable code in the !CONFIG_PWM_SYSFS case? We have the
unreachable()macro, but that isn't supported nicely by all compilers.If
CONFIG_SYSFSis not enabled andsysfs.cis using functions that now do not exist, that will cause compile errors, since the compiler will still attempt to compile all of the code, even though it will remove most of it after doing so.Also, any functions that are extern will also end up generating empty functions in the kernel binary (static linkage functions should disappear completely). This is obviously very negligible in size, but using a proper
Kconfigoption results in zero size if the option is compiled out.Quoted 8 lines
It's not the optimal
solution, which would require the sysfs code to go intocore.cand be conditionalized there, but it's good enough. I can always go and clean up that code later (maybe doing the same forDEBUG_FSwhile at it).The big advantage of this is that we get full compile coverage of the sysfs interface, whether it's enabled or not. Calling an empty function once when the chip is registered is an acceptable overhead.
Quoted 5 lines
Why not just make
CONFIG_PWM_SYSFSdefault y, so that ifCONFIG_SYSFSis enabled (which should be true for the vast majority of test configs) that pwm sysfs is also enabled?The
IS_ENABLEDmethod just seems very messy for a very small gain.
How about removing the Kconfig option and just doing:
obj-$(CONFIG_SYSFS) += sysfs.o
This way the PWM sysfs interface is always compiled and included in the build as long as CONFIG_SYSFS is enabled. The check in the header would change to
#ifdef CONFIG_SYSFS
void pwmchip_sysfs_export(struct pwm_chip *chip); void pwmchip_sysfs_unexport(struct pwm_chip *chip); #else
static inline void pwmchip_sysfs_export(struct pwm_chip *chip) {
}
static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip) {
}
#endif /* CONFIG_SYSFS */
So, no IS_ENABLED or #ifdef'ery in the source file.
I'll make the change and post a v5 shortly.
Regards,
Hartley
Quoted 22 lines · H Hartley Sweeten
Quoted 12 lines · Ryan Mallon
Quoted 11 lines · Thierry Reding
Quoted 10 lines · H Hartley Sweeten
drivers/pwm/Kconfig +10
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have aQuoted 8 lines
Quoted 8 lines
drivers/pwm/Kconfig menuconfig PWM · line 41
Quoted 1 line
drivers/pwm/Kconfig +1
-0+ pwmX directory in the pwmchipN it is associated with.I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the
IS_ENABLED()macro. We already have the same issue withDEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specificKconfigoption.
Quoted 6 lines
How about removing the
Kconfigoption and just doing:obj-$(CONFIG_SYSFS) += sysfs.o
This way the PWM sysfs interface is always compiled and included in the build as long as
CONFIG_SYSFSis enabled. The check in the header would change to
That didn't work. As Ryan pointed out we get undefined references due to sysfs.c being compiled but not core.c when CONFIG_PWM is not enabled.
I'll change the PWM_SYSFS to a hidden option and repost the patch to see if that is acceptable. Like Ryan mentioned, most test configs have CONFIG_SYSFS enabled so as long as CONFIG_PWM is enabled we also get the sysfs interface.
Regards,
Hartley
Quoted 25 lines · H Hartley Sweeten
Quoted 24 lines · H Hartley Sweeten
Quoted 12 lines · Ryan Mallon
Quoted 11 lines · Thierry Reding
Quoted 10 lines · H Hartley Sweeten
drivers/pwm/Kconfig +10
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have aQuoted 8 lines
Quoted 8 lines
drivers/pwm/Kconfig menuconfig PWM · line 41
Quoted 1 line
drivers/pwm/Kconfig +1
-0+ pwmX directory in the pwmchipN it is associated with.I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the
IS_ENABLED()macro. We already have the same issue withDEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specificKconfigoption.How about removing the
Kconfigoption and just doing:
Quoted 7 lines
Quoted 4 lines
obj-$(CONFIG_SYSFS) += sysfs.o
This way the PWM sysfs interface is always compiled and included in the build as long as
CONFIG_SYSFSis enabled. The check in the header would change toThat didn't work. As Ryan pointed out we get undefined references due to
sysfs.cbeing compiled but notcore.cwhenCONFIG_PWMis not enabled.
Why not add dummies for the missing functions? It was my impression that we had dummies for all of them already, but if not they should certainly be added to match what other subsystems do.
Thierry
Quoted 31 lines · Thierry Reding
Quoted 30 lines · H Hartley Sweeten
Quoted 28 lines · H Hartley Sweeten
Quoted 12 lines · Ryan Mallon
Quoted 11 lines · Thierry Reding
Quoted 10 lines · H Hartley Sweeten
drivers/pwm/Kconfig +10
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have aQuoted 8 lines
Quoted 8 lines
drivers/pwm/Kconfig menuconfig PWM · line 41
Quoted 1 line
drivers/pwm/Kconfig +1
-0+ pwmX directory in the pwmchipN it is associated with.I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the
IS_ENABLED()macro. We already have the same issue withDEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specificKconfigoption.How about removing the
Kconfigoption and just doing:obj-$(CONFIG_SYSFS) += sysfs.o
This way the PWM sysfs interface is always compiled and included in the build as long as
CONFIG_SYSFSis enabled. The check in the header would change to
Quoted 6 lines
Quoted 2 lines
That didn't work. As Ryan pointed out we get undefined references due to
sysfs.cbeing compiled but notcore.cwhenCONFIG_PWMis not enabled.Why not add dummies for the missing functions? It was my impression that we had dummies for all of them already, but if not they should certainly be added to match what other subsystems do.
I just looked it over and the undefined reference was for pwm_set_polarity(). The dummy for that function is missing.
The other problem with this approach is the sysfs.c file gets compiled whenever CONFIG_SYSFS is enabled even if CONFIG_PWM is not enabled.
Hartley
Quoted 39 lines · H Hartley Sweeten
Quoted 31 lines · Thierry Reding
Quoted 30 lines · H Hartley Sweeten
Quoted 28 lines · H Hartley Sweeten
Quoted 12 lines · Ryan Mallon
Quoted 11 lines · Thierry Reding
Quoted 10 lines · H Hartley Sweeten
(quoted diff) +10
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have aQuoted 8 lines
Quoted 8 lines
Review
Quoted 1 line
(quoted diff) +1
-0+ pwmX directory in the pwmchipN it is associated with.I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the
IS_ENABLED()macro. We already have the same issue withDEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specificKconfigoption.How about removing the
Kconfigoption and just doing:obj-$(CONFIG_SYSFS) += sysfs.o
This way the PWM sysfs interface is always compiled and included in the build as long as
CONFIG_SYSFSis enabled. The check in the header would change toQuoted 6 lines
Quoted 2 lines
That didn't work. As Ryan pointed out we get undefined references due to
sysfs.cbeing compiled but notcore.cwhenCONFIG_PWMis not enabled.Why not add dummies for the missing functions? It was my impression that we had dummies for all of them already, but if not they should certainly be added to match what other subsystems do.
Quoted 5 lines
I just looked it over and the undefined reference was for
pwm_set_polarity(). The dummy for that function is missing.The other problem with this approach is the
sysfs.cfile gets compiled wheneverCONFIG_SYSFSis enabled even ifCONFIG_PWMis not enabled.
Perhaps add something like this to the Makefile:
ifeq ($(CONFIG_PWM),y) obj-$(CONFIG_SYSFS) += sysfs.o endif
That should solve the problem of building sysfs.c if SYSFS && !PWM.
I'm tempted to take your v5 patch and make a note to clean that up separately at some point (along with similar changes for the DEBUG_FS support).
Thierry
Quoted 4 lines · Thierry Reding
I'm tempted to take your v5 patch and make a note to clean that up separately at some point (along with similar changes for the
DEBUG_FSsupport).
Thierry,
So you want a v6 of this patch or are you ok with v5?
Thanks,
Hartley
Quoted 9 lines · H Hartley Sweeten
Quoted 4 lines · Thierry Reding
I'm tempted to take your v5 patch and make a note to clean that up separately at some point (along with similar changes for the
DEBUG_FSsupport).Thierry,
So you want a v6 of this patch or are you ok with v5?
I'll take v5.
Thierry
Quoted 3 lines · Ryan Mallon
Quoted 1 line · Thierry Reding
On Mon, Jun 10, 2013 at 04:12:07PM -0700, H Hartley Sweeten wrote:
[...]
Quoted 26 lines
Quoted 26 lines
drivers/pwm/Kconfig menuconfig PWM · line 41
Quoted 11 lines
drivers/pwm/Kconfig +11
-0+config PWM_SYSFS + bool "/sys/class/pwm/... (sysfs interface)" + depends on SYSFS + help + Say Y here to provide a sysfs interface to control PWMs. + + For every instance of a PWM device there is a pwmchipN directory + created in /sys/class/pwm. Use the export attribute to request + a PWM to be accessible from userspace and the unexport attribute + to return the PWM to the kernel. Each exported PWM will have a + pwmX directory in the pwmchipN it is associated with.I have a small quibble with this. Introducing options like this make it increasingly difficult to compile-test all the various combinations, so I'd like to see this converted to a form that will play well with the
IS_ENABLED()macro. We already have the same issue withDEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specificKconfigoption.In order not to burden you with too much work, one option for now would be to unconditionally build the
sysfs.cfile and use something along these lines in pwmchip_sysfs_{,un}export():if (!IS_ENABLED(CONFIG_PWM_SYSFS)) return;
Quoted 7 lines
Quoted 2 lines
Which should allow the compiler to throw away all PWM_SYSFS-related code in that file, leaving an empty function.
Won't that also cause the compiler to spew a bunch of warnings about unreachable code in the !CONFIG_PWM_SYSFS case? We have the
unreachable()macro, but that isn't supported nicely by all compilers.
No, I don't think it does. We have other code already in the PWM subsystem which uses a similar approach and I haven't seen any such warning.
Quoted 4 lines
If
CONFIG_SYSFSis not enabled andsysfs.cis using functions that now do not exist, that will cause compile errors, since the compiler will still attempt to compile all of the code, even though it will remove most of it after doing so.
include/linux/sysfs.h defines all of the public functions as static inline dummies if CONFIG_SYSFS isn't enabled so everything should be fine.
Quoted 5 lines
Also, any functions that are extern will also end up generating empty functions in the kernel binary (static linkage functions should disappear completely). This is obviously very negligible in size, but using a proper
Kconfigoption results in zero size if the option is compiled out.
That's correct. Ultimately my intention is to move the sysfs.c code back into core.c and use static linkage in order for the unused code to disappear completely. That'll make core.c bigger of course, but I think I can handle that.
Perhaps most of the code can even remain in sysfs.c if we move just the pwmchip_sysfs_export() and pwmchip_sysfs_unexport() into core.c and call into functions from sysfs.c from there. That way we can make them static and the compiler can throw them away if PWM_SYSFS isn't selected. The linker should then be clever enough to notice that none of the code in sysfs.c is actually used and drop it as well.
Quoted 7 lines
Quoted 6 lines
It's not the optimal
solution, which would require the sysfs code to go intocore.cand be conditionalized there, but it's good enough. I can always go and clean up that code later (maybe doing the same forDEBUG_FSwhile at it).
Quoted 8 lines
Quoted 3 lines
The big advantage of this is that we get full compile coverage of the sysfs interface, whether it's enabled or not. Calling an empty function once when the chip is registered is an acceptable overhead.
Why not just make
CONFIG_PWM_SYSFSdefault y, so that ifCONFIG_SYSFSis enabled (which should be true for the vast majority of test configs) that pwm sysfs is also enabled?
In that case there's little sense in using a separate option in the first place. Instead we could just conditionalize on CONFIG_SYSFS.
Quoted 1 line
The
IS_ENABLEDmethod just seems very messy for a very small gain.
Note that I'm not proposing anything new here. IS_ENABLED() has become pretty popular recently precisely because it allows all of the code to be always compiled while at the same time throwing it away if it is unused. This makes life a lot easier for everyone because you get compiler errors immediately, and not only when some randconfig builder decides to build a particular combination that nobody bothered to test.
Thierry