Skip to contentSkip to conversation

pwm: add sysfs interface

PATCH Superseded H Hartley Sweeten 3 participants 11 messages Jun 10, 2013 – Jun 19, 2013

Subsystems (2)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

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
Cc Thierry Reding <[email protected]>
Cc Lars Poeschel <[email protected]>
Cc Ryan Mallon <[email protected]>
Cc Rob Landley <[email protected]>

---
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
new file mode 100644
index 0000000..cb3d034
@@ -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
index 7d2b4c9..95589b1 100644
@@ -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
index 115b644..e77405d 100644
@@ -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
index 94ba21e..a025439 100644
@@ -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
index 32221cb..9e9f5b8 100644
@@ -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
index a4df204..f0feafd 100644
@@ -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
#1 lore raw

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

#2 lore raw
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 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():

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 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.

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

#3 lore raw
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 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():

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 8 lines

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 5 lines

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.

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

#4 lore raw
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 a
Quoted 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 with DEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specific Kconfig option.

Quoted 6 lines

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

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

#5 lore raw
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 a
Quoted 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 with DEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specific Kconfig option.

How about removing the Kconfig option 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_SYSFS is 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.

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

#6 lore raw
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 a
Quoted 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 with DEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specific Kconfig option.

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

Quoted 6 lines
Quoted 2 lines

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.

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

#7 lore raw
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 a
Quoted 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 with DEBUG_FS, only to a lesser degree because it doesn't have an additional PWM-specific Kconfig option.

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

Quoted 6 lines
Quoted 2 lines

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.

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.c file gets compiled whenever CONFIG_SYSFS is enabled even if CONFIG_PWM is 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

#8 lore raw
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_FS support).

Thierry,

So you want a v6 of this patch or are you ok with v5?

Thanks,
Hartley

#9 lore raw
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_FS support).

Thierry,

So you want a v6 of this patch or are you ok with v5?

I'll take v5.

Thierry

#10 lore raw
In reply to Ryan Mallon
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 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;
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_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.

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 Kconfig option 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 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).

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_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?

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_ENABLED method 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