From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Add a Kconfig switch allowing to disable the legacy parts of the GPIO
sysfs interface. This means that even though we keep the
/sys/class/gpio/ directory, it no longer contains the global
export/unexport attribute pair (instead, the user should use the
per-chip export/unpexport) nor the gpiochip$BASE entries. This option
default to y if GPIO sysfs is enabled but we'll default it to n at some
point in the future.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
drivers/gpio/Kconfig | 8 ++++++++
drivers/gpio/gpiolib-sysfs.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 44f922e10db2f8dcbdacf79ccd27b0fd9cd93564..d040fdd95ee4b19851057fbedbb023f277149c9c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -69,6 +69,14 @@ config GPIO_SYSFS
use the character device /dev/gpiochipN with the appropriate
ioctl() operations instead.
+config GPIO_SYSFS_LEGACY
+ bool "Enable legacy functionalities of the sysfs interface"
+ depends on GPIO_SYSFS
+ default y if GPIO_SYSFS
+ help
+ Say Y here if you want to enable the legacy, global GPIO
+ numberspace-based functionalities of the sysfs interface.
+
config GPIO_CDEV
bool "Character device (/dev/gpiochipN) support" if EXPERT
default y
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 37d58009a51333f7d6a8d600dbeaeb333df27ac3..0e7605fee3bd9edbe4e90d8e466742df11a8d579 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -46,7 +46,9 @@ struct gpiod_data {
struct device *dev;
struct mutex mutex;
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
struct kernfs_node *value_class_node;
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
struct kernfs_node *value_chip_node;
int irq;
unsigned char irq_flags;
@@ -67,7 +69,9 @@ struct gpiod_data {
struct gpiodev_data {
struct gpio_device *gdev;
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
struct device *cdev_base; /* Class device by GPIO base */
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
struct device *cdev_id; /* Class device by GPIO device ID */
struct list_head exported_lines;
};
@@ -181,7 +185,9 @@ static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
{
struct gpiod_data *data = priv;
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
sysfs_notify_dirent(data->value_class_node);
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
kernfs_notify(data->value_chip_node);
return IRQ_HANDLED;
@@ -416,6 +422,7 @@ static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
* /ngpio ... matching gpio_chip.ngpio
*/
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
static ssize_t base_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -424,6 +431,7 @@ static ssize_t base_show(struct device *dev, struct device_attribute *attr,
return sysfs_emit(buf, "%u\n", data->gdev->base);
}
static DEVICE_ATTR_RO(base);
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
static ssize_t label_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -548,6 +556,7 @@ static struct device_attribute dev_attr_unexport = __ATTR(unexport, 0200,
NULL,
chip_unexport_store);
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
static struct attribute *gpiochip_attrs[] = {
&dev_attr_base.attr,
&dev_attr_label.attr,
@@ -555,6 +564,7 @@ static struct attribute *gpiochip_attrs[] = {
NULL,
};
ATTRIBUTE_GROUPS(gpiochip);
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
static struct attribute *gpiochip_ext_attrs[] = {
&dev_attr_label.attr,
@@ -565,6 +575,7 @@ static struct attribute *gpiochip_ext_attrs[] = {
};
ATTRIBUTE_GROUPS(gpiochip_ext);
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
/*
* /sys/class/gpio/export ... write-only
* integer N ... number of GPIO to export (full access)
@@ -629,10 +640,13 @@ static struct attribute *gpio_class_attrs[] = {
NULL,
};
ATTRIBUTE_GROUPS(gpio_class);
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
static const struct class gpio_class = {
.name = "gpio",
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
.class_groups = gpio_class_groups,
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
};
static int match_gdev(struct device *dev, const void *desc)
@@ -763,6 +777,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
* at least one known user of gpiod_export_link() in the tree. This
* function still uses class_find_device() internally.
*/
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
desc_data->dev = device_create_with_groups(&gpio_class, &gdev->dev,
MKDEV(0, 0), desc_data,
desc_data->attr_groups,
@@ -779,6 +794,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
status = -ENODEV;
goto err_unregister_device;
}
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
gdev_data = gdev_get_data(gdev);
if (!gdev_data) {
@@ -822,10 +838,12 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
err_free_name:
kfree(desc_data->attr_group.name);
err_put_dirent:
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
sysfs_put(desc_data->value_class_node);
err_unregister_device:
device_unregister(desc_data->dev);
err_free_data:
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
kfree(desc_data);
err_clear_bit:
clear_bit(FLAG_EXPORT, &desc->flags);
@@ -834,12 +852,14 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
}
EXPORT_SYMBOL_GPL(gpiod_export);
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
static int match_export(struct device *dev, const void *desc)
{
struct gpiod_data *data = dev_get_drvdata(dev);
return data->desc == desc;
}
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
/**
* gpiod_export_link - create a sysfs link to an exported GPIO node
@@ -856,6 +876,7 @@ static int match_export(struct device *dev, const void *desc)
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc)
{
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
struct device *cdev;
int ret;
@@ -872,6 +893,9 @@ int gpiod_export_link(struct device *dev, const char *name,
put_device(cdev);
return ret;
+#else
+ return -EOPNOTSUPP;
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
}
EXPORT_SYMBOL_GPL(gpiod_export_link);
@@ -910,8 +934,10 @@ void gpiod_unexport(struct gpio_desc *desc)
list_del(&desc_data->list);
clear_bit(FLAG_EXPORT, &desc->flags);
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
sysfs_put(desc_data->value_class_node);
device_unregister(desc_data->dev);
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
sysfs_remove_groups(desc_data->parent, desc_data->attr_groups);
kernfs_put(desc_data->value_chip_node);
@@ -968,6 +994,7 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
guard(mutex)(&sysfs_lock);
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
/* use chip->base for the ID; it's already known to be unique */
data->cdev_base = device_create_with_groups(&gpio_class, parent,
MKDEV(0, 0), data,
@@ -979,13 +1006,16 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
kfree(data);
return err;
}
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
data->cdev_id = device_create_with_groups(&gpio_class, parent,
MKDEV(0, 0), data,
gpiochip_ext_groups,
"chip%d", gdev->id);
if (IS_ERR(data->cdev_id)) {
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
device_unregister(data->cdev_base);
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
kfree(data);
return PTR_ERR(data->cdev_id);
}
@@ -1004,7 +1034,9 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
if (!data)
return;
+#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
device_unregister(data->cdev_base);
+#endif /* CONFIG_GPIO_SYSFS_LEGACY */
device_unregister(data->cdev_id);
kfree(data);
}
--
2.48.1
Hi Bartosz,
kernel test robot noticed the following build warnings:
[auto build test WARNING on cb908f3699fb137e28017a8fdf506c35762b3eb6]
url: https://github.com/intel-lab-lkp/linux/commits/Bartosz-Golaszewski/gpio-sysfs-add-a-parallel-class-device-for-each-GPIO-chip-using-device-IDs/20250623-170412
base: cb908f3699fb137e28017a8fdf506c35762b3eb6
patch link: https://lore.kernel.org/r/20250623-gpio-sysfs-chip-export-v2-8-d592793f8964%40linaro.org
patch subject: [PATCH v2 8/9] gpio: sysfs: allow disabling the legacy parts of the GPIO sysfs interface
config: s390-randconfig-002-20250627 (https://download.01.org/0day-ci/archive/20250627/202506271940.T2QaCrba-lkp@intel.com/config)
compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project e04c938cc08a90ae60440ce22d072ebc69d67ee8)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250627/202506271940.T2QaCrba-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506271940.T2QaCrba-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/gpio/gpiolib-sysfs.c:818:3: error: cannot jump from this goto statement to its label
818 | goto err_free_name;
| ^
drivers/gpio/gpiolib-sysfs.c:820:8: note: jump bypasses initialization of variable with __attribute__((cleanup))
820 | char *path __free(kfree) = kasprintf(GFP_KERNEL, "gpio%u/value",
| ^
drivers/gpio/gpiolib-sysfs.c:811:3: error: cannot jump from this goto statement to its label
811 | goto err_put_dirent;
| ^
drivers/gpio/gpiolib-sysfs.c:820:8: note: jump bypasses initialization of variable with __attribute__((cleanup))
820 | char *path __free(kfree) = kasprintf(GFP_KERNEL, "gpio%u/value",
| ^
drivers/gpio/gpiolib-sysfs.c:802:3: error: cannot jump from this goto statement to its label
802 | goto err_put_dirent;
| ^
drivers/gpio/gpiolib-sysfs.c:820:8: note: jump bypasses initialization of variable with __attribute__((cleanup))
820 | char *path __free(kfree) = kasprintf(GFP_KERNEL, "gpio%u/value",
| ^
drivers/gpio/gpiolib-sysfs.c:747:3: error: cannot jump from this goto statement to its label
747 | goto err_clear_bit;
| ^
drivers/gpio/gpiolib-sysfs.c:820:8: note: jump bypasses initialization of variable with __attribute__((cleanup))
820 | char *path __free(kfree) = kasprintf(GFP_KERNEL, "gpio%u/value",
| ^
drivers/gpio/gpiolib-sysfs.c:741:3: error: cannot jump from this goto statement to its label
741 | goto err_clear_bit;
| ^
drivers/gpio/gpiolib-sysfs.c:820:8: note: jump bypasses initialization of variable with __attribute__((cleanup))
820 | char *path __free(kfree) = kasprintf(GFP_KERNEL, "gpio%u/value",
| ^
>> drivers/gpio/gpiolib-sysfs.c:962:6: warning: unused variable 'err' [-Wunused-variable]
962 | int err;
| ^~~
1 warning and 5 errors generated.
vim +/err +962 drivers/gpio/gpiolib-sysfs.c
65fbd24108991d Bartosz Golaszewski 2025-06-23 798
574194e59098d9 Bartosz Golaszewski 2025-06-23 799 gdev_data = gdev_get_data(gdev);
574194e59098d9 Bartosz Golaszewski 2025-06-23 800 if (!gdev_data) {
574194e59098d9 Bartosz Golaszewski 2025-06-23 801 status = -ENODEV;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 802 goto err_put_dirent;
574194e59098d9 Bartosz Golaszewski 2025-06-23 803 }
574194e59098d9 Bartosz Golaszewski 2025-06-23 804
574194e59098d9 Bartosz Golaszewski 2025-06-23 805 list_add(&desc_data->list, &gdev_data->exported_lines);
574194e59098d9 Bartosz Golaszewski 2025-06-23 806
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 807 desc_data->attr_group.name = kasprintf(GFP_KERNEL, "gpio%u",
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 808 gpio_chip_hwgpio(desc));
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 809 if (!desc_data->attr_group.name) {
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 810 status = -ENOMEM;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 811 goto err_put_dirent;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 812 }
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 813
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 814 desc_data->parent = &gdev_data->cdev_id->kobj;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 815 status = sysfs_create_groups(desc_data->parent,
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 816 desc_data->attr_groups);
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 817 if (status)
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 818 goto err_free_name;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 819
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 @820 char *path __free(kfree) = kasprintf(GFP_KERNEL, "gpio%u/value",
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 821 gpio_chip_hwgpio(desc));
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 822 if (!path) {
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 823 status = -ENOMEM;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 824 goto err_remove_groups;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 825 }
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 826
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 827 desc_data->value_chip_node = kernfs_walk_and_get(desc_data->parent->sd,
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 828 path);
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 829 if (!desc_data->value_chip_node) {
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 830 status = -ENODEV;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 831 goto err_remove_groups;
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 832 }
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 833
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 834 return 0;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 835
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 836 err_remove_groups:
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 837 sysfs_remove_groups(desc_data->parent, desc_data->attr_groups);
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 838 err_free_name:
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 839 kfree(desc_data->attr_group.name);
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 840 err_put_dirent:
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 841 #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 842 sysfs_put(desc_data->value_class_node);
65fbd24108991d Bartosz Golaszewski 2025-06-23 843 err_unregister_device:
574194e59098d9 Bartosz Golaszewski 2025-06-23 844 device_unregister(desc_data->dev);
c43960fbcc514b Johan Hovold 2015-05-04 845 err_free_data:
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 846 #endif /* CONFIG_GPIO_SYSFS_LEGACY */
d54627a4c4f9a8 Bartosz Golaszewski 2025-06-23 847 kfree(desc_data);
f4af1671c28854 Bartosz Golaszewski 2024-10-31 848 err_clear_bit:
35b545332b809a Bartosz Golaszewski 2024-01-12 849 clear_bit(FLAG_EXPORT, &desc->flags);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 850 gpiod_dbg(desc, "%s: status %d\n", __func__, status);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 851 return status;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 852 }
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 853 EXPORT_SYMBOL_GPL(gpiod_export);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 854
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 855 #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
c43960fbcc514b Johan Hovold 2015-05-04 856 static int match_export(struct device *dev, const void *desc)
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 857 {
c43960fbcc514b Johan Hovold 2015-05-04 858 struct gpiod_data *data = dev_get_drvdata(dev);
c43960fbcc514b Johan Hovold 2015-05-04 859
c43960fbcc514b Johan Hovold 2015-05-04 860 return data->desc == desc;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 861 }
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 862 #endif /* CONFIG_GPIO_SYSFS_LEGACY */
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 863
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 864 /**
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 865 * gpiod_export_link - create a sysfs link to an exported GPIO node
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 866 * @dev: device under which to create symlink
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 867 * @name: name of the symlink
2d9d05192e7d1a Thierry Reding 2017-07-24 868 * @desc: GPIO to create symlink to, already exported
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 869 *
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 870 * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 871 * node. Caller is responsible for unlinking.
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 872 *
94bd9ce16063a2 Andy Shevchenko 2024-08-28 873 * Returns:
94bd9ce16063a2 Andy Shevchenko 2024-08-28 874 * 0 on success, or negative errno on failure.
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 875 */
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 876 int gpiod_export_link(struct device *dev, const char *name,
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 877 struct gpio_desc *desc)
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 878 {
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 879 #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
56d30ec14c1330 Johan Hovold 2015-05-04 880 struct device *cdev;
56d30ec14c1330 Johan Hovold 2015-05-04 881 int ret;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 882
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 883 if (!desc) {
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 884 pr_warn("%s: invalid GPIO\n", __func__);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 885 return -EINVAL;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 886 }
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 887
56d30ec14c1330 Johan Hovold 2015-05-04 888 cdev = class_find_device(&gpio_class, NULL, desc, match_export);
56d30ec14c1330 Johan Hovold 2015-05-04 889 if (!cdev)
56d30ec14c1330 Johan Hovold 2015-05-04 890 return -ENODEV;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 891
56d30ec14c1330 Johan Hovold 2015-05-04 892 ret = sysfs_create_link(&dev->kobj, &cdev->kobj, name);
56d30ec14c1330 Johan Hovold 2015-05-04 893 put_device(cdev);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 894
56d30ec14c1330 Johan Hovold 2015-05-04 895 return ret;
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 896 #else
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 897 return -EOPNOTSUPP;
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 898 #endif /* CONFIG_GPIO_SYSFS_LEGACY */
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 899 }
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 900 EXPORT_SYMBOL_GPL(gpiod_export_link);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 901
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 902 /**
31963eb039b7d5 Amitesh Singh 2016-09-08 903 * gpiod_unexport - reverse effect of gpiod_export()
2d9d05192e7d1a Thierry Reding 2017-07-24 904 * @desc: GPIO to make unavailable
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 905 *
31963eb039b7d5 Amitesh Singh 2016-09-08 906 * This is implicit on gpiod_free().
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 907 */
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 908 void gpiod_unexport(struct gpio_desc *desc)
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 909 {
574194e59098d9 Bartosz Golaszewski 2025-06-23 910 struct gpiod_data *desc_data = NULL;
574194e59098d9 Bartosz Golaszewski 2025-06-23 911 struct gpiodev_data *gdev_data;
574194e59098d9 Bartosz Golaszewski 2025-06-23 912 struct gpio_device *gdev;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 913
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 914 if (!desc) {
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 915 pr_warn("%s: invalid GPIO\n", __func__);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 916 return;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 917 }
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 918
f4af1671c28854 Bartosz Golaszewski 2024-10-31 919 scoped_guard(mutex, &sysfs_lock) {
72eba6f66a0017 Johan Hovold 2015-05-04 920 if (!test_bit(FLAG_EXPORT, &desc->flags))
f4af1671c28854 Bartosz Golaszewski 2024-10-31 921 return;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 922
574194e59098d9 Bartosz Golaszewski 2025-06-23 923 gdev = gpiod_to_gpio_device(desc);
574194e59098d9 Bartosz Golaszewski 2025-06-23 924 gdev_data = gdev_get_data(gdev);
574194e59098d9 Bartosz Golaszewski 2025-06-23 925 if (!gdev_data)
574194e59098d9 Bartosz Golaszewski 2025-06-23 926 return;
574194e59098d9 Bartosz Golaszewski 2025-06-23 927
574194e59098d9 Bartosz Golaszewski 2025-06-23 928 list_for_each_entry(desc_data, &gdev_data->exported_lines, list)
574194e59098d9 Bartosz Golaszewski 2025-06-23 929 if (desc == desc_data->desc)
574194e59098d9 Bartosz Golaszewski 2025-06-23 930 break;
574194e59098d9 Bartosz Golaszewski 2025-06-23 931
574194e59098d9 Bartosz Golaszewski 2025-06-23 932 if (!desc_data)
f4af1671c28854 Bartosz Golaszewski 2024-10-31 933 return;
72eba6f66a0017 Johan Hovold 2015-05-04 934
574194e59098d9 Bartosz Golaszewski 2025-06-23 935 list_del(&desc_data->list);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 936 clear_bit(FLAG_EXPORT, &desc->flags);
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 937 #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
d54627a4c4f9a8 Bartosz Golaszewski 2025-06-23 938 sysfs_put(desc_data->value_class_node);
574194e59098d9 Bartosz Golaszewski 2025-06-23 939 device_unregister(desc_data->dev);
d6fe296d76af3f Bartosz Golaszewski 2025-06-23 940 #endif /* CONFIG_GPIO_SYSFS_LEGACY */
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 941 sysfs_remove_groups(desc_data->parent, desc_data->attr_groups);
d65a6b43cccca4 Bartosz Golaszewski 2025-06-23 942 kernfs_put(desc_data->value_chip_node);
72eba6f66a0017 Johan Hovold 2015-05-04 943
54d9acd7540995 Johan Hovold 2015-05-04 944 /*
f4af1671c28854 Bartosz Golaszewski 2024-10-31 945 * Release irq after deregistration to prevent race with
f4af1671c28854 Bartosz Golaszewski 2024-10-31 946 * edge_store.
54d9acd7540995 Johan Hovold 2015-05-04 947 */
d54627a4c4f9a8 Bartosz Golaszewski 2025-06-23 948 if (desc_data->irq_flags)
d54627a4c4f9a8 Bartosz Golaszewski 2025-06-23 949 gpio_sysfs_free_irq(desc_data);
f4af1671c28854 Bartosz Golaszewski 2024-10-31 950 }
72eba6f66a0017 Johan Hovold 2015-05-04 951
d54627a4c4f9a8 Bartosz Golaszewski 2025-06-23 952 mutex_destroy(&desc_data->mutex);
d54627a4c4f9a8 Bartosz Golaszewski 2025-06-23 953 kfree(desc_data);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 954 }
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 955 EXPORT_SYMBOL_GPL(gpiod_unexport);
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 956
afbc4f312b5e6e Linus Walleij 2016-02-09 957 int gpiochip_sysfs_register(struct gpio_device *gdev)
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 958 {
fd19792851db77 Bartosz Golaszewski 2025-06-10 959 struct gpiodev_data *data;
d83cee3d2bb131 Bartosz Golaszewski 2024-01-23 960 struct gpio_chip *chip;
513246a34b8dc5 Bartosz Golaszewski 2023-12-21 961 struct device *parent;
e6bb78570f7d53 Antonio Quartulli 2025-06-23 @962 int err;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 963
426577bd8846d6 Johan Hovold 2015-05-04 964 /*
426577bd8846d6 Johan Hovold 2015-05-04 965 * Many systems add gpio chips for SOC support very early,
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 966 * before driver model support is available. In those cases we
426577bd8846d6 Johan Hovold 2015-05-04 967 * register later, in gpiolib_sysfs_init() ... here we just
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 968 * verify that _some_ field of gpio_class got initialized.
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 969 */
6f14c02220c791 Greg Kroah-Hartman 2023-03-31 970 if (!class_is_registered(&gpio_class))
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 971 return 0;
0eb4c6c2671ca0 Alexandre Courbot 2014-07-01 972
d83cee3d2bb131 Bartosz Golaszewski 2024-01-23 973 guard(srcu)(&gdev->srcu);
d83cee3d2bb131 Bartosz Golaszewski 2024-01-23 974
d82b9e0887e69d Bartosz Golaszewski 2024-02-14 975 chip = srcu_dereference(gdev->chip, &gdev->srcu);
d83cee3d2bb131 Bartosz Golaszewski 2024-01-23 976 if (!chip)
d83cee3d2bb131 Bartosz Golaszewski 2024-01-23 977 return -ENODEV;
d83cee3d2bb131 Bartosz Golaszewski 2024-01-23 978
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 979 /*
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 980 * For sysfs backward compatibility we need to preserve this
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 981 * preferred parenting to the gpio_chip parent field, if set.
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 982 */
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 983 if (chip->parent)
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 984 parent = chip->parent;
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 985 else
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 986 parent = &gdev->dev;
d27c17285eb7eb Bamvor Jian Zhang 2016-02-24 987
fd19792851db77 Bartosz Golaszewski 2025-06-10 988 data = kmalloc(sizeof(*data), GFP_KERNEL);
fd19792851db77 Bartosz Golaszewski 2025-06-10 989 if (!data)
fd19792851db77 Bartosz Golaszewski 2025-06-10 990 return -ENOMEM;
fd19792851db77 Bartosz Golaszewski 2025-06-10 991
fd19792851db77 Bartosz Golaszewski 2025-06-10 992 data->gdev = gdev;
574194e59098d9 Bartosz Golaszewski 2025-06-23 993 INIT_LIST_HEAD(&data->exported_lines);
3ff74be5c1a72d Johan Hovold 2015-05-04 994
f4af1671c28854 Bartosz Golaszewski 2024-10-31 995 guard(mutex)(&sysfs_lock);
fd19792851db77 Bartosz Golaszewski 2025-06-10 996
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On Mon, Jun 23, 2025 at 11:00 AM Bartosz Golaszewski <brgl@bgdev.pl> wrote: > From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> > > Add a Kconfig switch allowing to disable the legacy parts of the GPIO > sysfs interface. This means that even though we keep the > /sys/class/gpio/ directory, it no longer contains the global > export/unexport attribute pair (instead, the user should use the > per-chip export/unpexport) nor the gpiochip$BASE entries. This option > default to y if GPIO sysfs is enabled but we'll default it to n at some > point in the future. > > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> This is great. Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Yours, Linus Walleij
Hi Bartosz,
On Mon, 23 Jun 2025 at 11:01, Bartosz Golaszewski <brgl@bgdev.pl> wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Add a Kconfig switch allowing to disable the legacy parts of the GPIO
> sysfs interface. This means that even though we keep the
> /sys/class/gpio/ directory, it no longer contains the global
> export/unexport attribute pair (instead, the user should use the
> per-chip export/unpexport) nor the gpiochip$BASE entries. This option
> default to y if GPIO sysfs is enabled but we'll default it to n at some
> point in the future.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Thanks for your patch!
> --- a/drivers/gpio/gpiolib-sysfs.c
> +++ b/drivers/gpio/gpiolib-sysfs.c
> @@ -968,6 +994,7 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
>
> guard(mutex)(&sysfs_lock);
>
> +#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
> /* use chip->base for the ID; it's already known to be unique */
> data->cdev_base = device_create_with_groups(&gpio_class, parent,
> MKDEV(0, 0), data,
> @@ -979,13 +1006,16 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
> kfree(data);
> return err;
> }
> +#endif /* CONFIG_GPIO_SYSFS_LEGACY */
"err" is always declared, but only used in this block.
Hence if CONFIG_GPIO_SYSFS_LEGACY=n:
drivers/gpio/gpiolib-sysfs.c: In function ‘gpiochip_sysfs_register’:
drivers/gpio/gpiolib-sysfs.c:962:13: error: unused variable ‘err’
[-Werror=unused-variable]
962 | int err;
| ^~~
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
© 2016 - 2026 Red Hat, Inc.