linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] gpio: sysfs: send character device notifications for sysfs class events
@ 2024-10-24 11:32 Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex Bartosz Golaszewski
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2024-10-24 11:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Kent Gibson
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

This may be a total corner-case but for consistency and completeness I
think it makes sense to also send out line state change events on actions
triggered from the GPIO sysfs class.

The first two patches use cleanup helpers in sysfs code. The next three
change the code to emit notifications on line export (unexport is
already handled) and active_low & edge changes.

One last thing I considered was also notifying user-space whenever
gpiochip_un/lock_as_irq() is called but that doesn't make much sense as
it's largely independent from the GPIO core and can be called for both
requested and available lines whenever someone requests an interrupt
from a GPIO controller.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
Bartosz Golaszewski (5):
      gpio: sysfs: use cleanup guards for gpiod_data::mutex
      gpio: sysfs: use cleanup guards for the sysfs_lock mutex
      gpio: sysfs: emit chardev line-state events on GPIO export
      gpio: sysfs: emit chardev line-state events on active-low changes
      gpio: sysfs: emit chardev line-state events on edge store

 drivers/gpio/gpiolib-sysfs.c | 143 +++++++++++++++++++------------------------
 1 file changed, 62 insertions(+), 81 deletions(-)
---
base-commit: fd21fa4a912ebbf8a6a341c31d8456f61e7d4170
change-id: 20241022-gpio-notify-sysfs-3bddf9ecca9f

Best regards,
-- 
Bartosz Golaszewski <bartosz.golaszewski@linaro.org>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex
  2024-10-24 11:32 [PATCH 0/5] gpio: sysfs: send character device notifications for sysfs class events Bartosz Golaszewski
@ 2024-10-24 11:32 ` Bartosz Golaszewski
  2024-10-25  2:53   ` Kent Gibson
  2024-10-24 11:32 ` [PATCH 2/5] gpio: sysfs: use cleanup guards for the sysfs_lock mutex Bartosz Golaszewski
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Bartosz Golaszewski @ 2024-10-24 11:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Kent Gibson
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

Shrink the code and drop some goto labels by using lock guards around
gpiod_data::mutex.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 drivers/gpio/gpiolib-sysfs.c | 57 +++++++++++++-------------------------------
 1 file changed, 17 insertions(+), 40 deletions(-)

diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 0c713baa7784..3ccb41a93ea7 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -77,12 +77,10 @@ static ssize_t direction_show(struct device *dev,
 	struct gpio_desc *desc = data->desc;
 	int value;
 
-	mutex_lock(&data->mutex);
-
-	gpiod_get_direction(desc);
-	value = !!test_bit(FLAG_IS_OUT, &desc->flags);
-
-	mutex_unlock(&data->mutex);
+	scoped_guard(mutex, &data->mutex) {
+		gpiod_get_direction(desc);
+		value = !!test_bit(FLAG_IS_OUT, &desc->flags);
+	}
 
 	return sysfs_emit(buf, "%s\n", value ? "out" : "in");
 }
@@ -94,7 +92,7 @@ static ssize_t direction_store(struct device *dev,
 	struct gpio_desc *desc = data->desc;
 	ssize_t			status;
 
-	mutex_lock(&data->mutex);
+	guard(mutex)(&data->mutex);
 
 	if (sysfs_streq(buf, "high"))
 		status = gpiod_direction_output_raw(desc, 1);
@@ -105,8 +103,6 @@ static ssize_t direction_store(struct device *dev,
 	else
 		status = -EINVAL;
 
-	mutex_unlock(&data->mutex);
-
 	return status ? : size;
 }
 static DEVICE_ATTR_RW(direction);
@@ -118,11 +114,8 @@ static ssize_t value_show(struct device *dev,
 	struct gpio_desc *desc = data->desc;
 	ssize_t			status;
 
-	mutex_lock(&data->mutex);
-
-	status = gpiod_get_value_cansleep(desc);
-
-	mutex_unlock(&data->mutex);
+	scoped_guard(mutex, &data->mutex)
+		status = gpiod_get_value_cansleep(desc);
 
 	if (status < 0)
 		return status;
@@ -140,7 +133,7 @@ static ssize_t value_store(struct device *dev,
 
 	status = kstrtol(buf, 0, &value);
 
-	mutex_lock(&data->mutex);
+	guard(mutex)(&data->mutex);
 
 	if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
 		status = -EPERM;
@@ -149,8 +142,6 @@ static ssize_t value_store(struct device *dev,
 		status = size;
 	}
 
-	mutex_unlock(&data->mutex);
-
 	return status;
 }
 static DEVICE_ATTR_PREALLOC(value, S_IWUSR | S_IRUGO, value_show, value_store);
@@ -253,11 +244,8 @@ static ssize_t edge_show(struct device *dev,
 	struct gpiod_data *data = dev_get_drvdata(dev);
 	int flags;
 
-	mutex_lock(&data->mutex);
-
-	flags = data->irq_flags;
-
-	mutex_unlock(&data->mutex);
+	scoped_guard(mutex, &data->mutex)
+		flags = data->irq_flags;
 
 	if (flags >= ARRAY_SIZE(trigger_names))
 		return 0;
@@ -276,12 +264,10 @@ static ssize_t edge_store(struct device *dev,
 	if (flags < 0)
 		return flags;
 
-	mutex_lock(&data->mutex);
+	guard(mutex)(&data->mutex);
 
-	if (flags == data->irq_flags) {
-		status = size;
-		goto out_unlock;
-	}
+	if (flags == data->irq_flags)
+		return size;
 
 	if (data->irq_flags)
 		gpio_sysfs_free_irq(dev);
@@ -292,9 +278,6 @@ static ssize_t edge_store(struct device *dev,
 			status = size;
 	}
 
-out_unlock:
-	mutex_unlock(&data->mutex);
-
 	return status;
 }
 static DEVICE_ATTR_RW(edge);
@@ -330,11 +313,8 @@ static ssize_t active_low_show(struct device *dev,
 	struct gpio_desc *desc = data->desc;
 	int value;
 
-	mutex_lock(&data->mutex);
-
-	value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags);
-
-	mutex_unlock(&data->mutex);
+	scoped_guard(mutex, &data->mutex)
+		value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags);
 
 	return sysfs_emit(buf, "%d\n", value);
 }
@@ -350,11 +330,8 @@ static ssize_t active_low_store(struct device *dev,
 	if (status)
 		return status;
 
-	mutex_lock(&data->mutex);
-
-	status = gpio_sysfs_set_active_low(dev, value);
-
-	mutex_unlock(&data->mutex);
+	scoped_guard(mutex, &data->mutex)
+		status = gpio_sysfs_set_active_low(dev, value);
 
 	return status ? : size;
 }

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] gpio: sysfs: use cleanup guards for the sysfs_lock mutex
  2024-10-24 11:32 [PATCH 0/5] gpio: sysfs: send character device notifications for sysfs class events Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex Bartosz Golaszewski
@ 2024-10-24 11:32 ` Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 3/5] gpio: sysfs: emit chardev line-state events on GPIO export Bartosz Golaszewski
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2024-10-24 11:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Kent Gibson
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

Shrink the code and remove some goto labels by using guards around the
sysfs_lock mutex. While at it: use __free(kfree) when allocating sysfs
callback data.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 drivers/gpio/gpiolib-sysfs.c | 64 ++++++++++++++++++--------------------------
 1 file changed, 26 insertions(+), 38 deletions(-)

diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 3ccb41a93ea7..096f79bbfe42 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -550,7 +550,6 @@ static const struct class gpio_class = {
 int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
 {
 	struct gpio_device *gdev;
-	struct gpiod_data *data;
 	struct device *dev;
 	int status;
 
@@ -574,24 +573,25 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
 
 	gdev = desc->gdev;
 
-	mutex_lock(&sysfs_lock);
+	guard(mutex)(&sysfs_lock);
 
 	/* check if chip is being removed */
 	if (!gdev->mockdev) {
 		status = -ENODEV;
-		goto err_unlock;
+		goto err_clear_bit;
 	}
 
 	if (!test_bit(FLAG_REQUESTED, &desc->flags)) {
 		gpiod_dbg(desc, "%s: unavailable (not requested)\n", __func__);
 		status = -EPERM;
-		goto err_unlock;
+		goto err_clear_bit;
 	}
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	struct gpiod_data *data __free(kfree) = kzalloc(sizeof(*data),
+							GFP_KERNEL);
 	if (!data) {
 		status = -ENOMEM;
-		goto err_unlock;
+		goto err_clear_bit;
 	}
 
 	data->desc = desc;
@@ -606,16 +606,13 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
 					"gpio%u", desc_to_gpio(desc));
 	if (IS_ERR(dev)) {
 		status = PTR_ERR(dev);
-		goto err_free_data;
+		goto err_clear_bit;
 	}
 
-	mutex_unlock(&sysfs_lock);
+	data = NULL;
 	return 0;
 
-err_free_data:
-	kfree(data);
-err_unlock:
-	mutex_unlock(&sysfs_lock);
+err_clear_bit:
 	clear_bit(FLAG_EXPORT, &desc->flags);
 	gpiod_dbg(desc, "%s: status %d\n", __func__, status);
 	return status;
@@ -679,36 +676,28 @@ void gpiod_unexport(struct gpio_desc *desc)
 		return;
 	}
 
-	mutex_lock(&sysfs_lock);
+	scoped_guard(mutex, &sysfs_lock) {
+		if (!test_bit(FLAG_EXPORT, &desc->flags))
+			return;
 
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
-		goto err_unlock;
+		dev = class_find_device(&gpio_class, NULL, desc, match_export);
+		if (!dev)
+			return;
 
-	dev = class_find_device(&gpio_class, NULL, desc, match_export);
-	if (!dev)
-		goto err_unlock;
+		data = dev_get_drvdata(dev);
+		clear_bit(FLAG_EXPORT, &desc->flags);
+		device_unregister(dev);
 
-	data = dev_get_drvdata(dev);
-
-	clear_bit(FLAG_EXPORT, &desc->flags);
-
-	device_unregister(dev);
-
-	/*
-	 * Release irq after deregistration to prevent race with edge_store.
-	 */
-	if (data->irq_flags)
-		gpio_sysfs_free_irq(dev);
-
-	mutex_unlock(&sysfs_lock);
+		/*
+		 * Release irq after deregistration to prevent race with
+		 * edge_store.
+		 */
+		if (data->irq_flags)
+			gpio_sysfs_free_irq(dev);
+	}
 
 	put_device(dev);
 	kfree(data);
-
-	return;
-
-err_unlock:
-	mutex_unlock(&sysfs_lock);
 }
 EXPORT_SYMBOL_GPL(gpiod_unexport);
 
@@ -749,9 +738,8 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
 	if (IS_ERR(dev))
 		return PTR_ERR(dev);
 
-	mutex_lock(&sysfs_lock);
+	guard(mutex)(&sysfs_lock);
 	gdev->mockdev = dev;
-	mutex_unlock(&sysfs_lock);
 
 	return 0;
 }

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] gpio: sysfs: emit chardev line-state events on GPIO export
  2024-10-24 11:32 [PATCH 0/5] gpio: sysfs: send character device notifications for sysfs class events Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 2/5] gpio: sysfs: use cleanup guards for the sysfs_lock mutex Bartosz Golaszewski
@ 2024-10-24 11:32 ` Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 4/5] gpio: sysfs: emit chardev line-state events on active-low changes Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 5/5] gpio: sysfs: emit chardev line-state events on edge store Bartosz Golaszewski
  4 siblings, 0 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2024-10-24 11:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Kent Gibson
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

We already emit a CONFIG_RELEASED event when a line is unexported over
sysfs (this is handled by gpiod_free()) but we don't do the opposite
when it's exported. This adds the missing call to
gpiod_line_state_notify().

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 drivers/gpio/gpiolib-sysfs.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 096f79bbfe42..3f24bf278b77 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -21,6 +21,8 @@
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/driver.h>
 
+#include <uapi/linux/gpio.h>
+
 #include "gpiolib.h"
 #include "gpiolib-sysfs.h"
 
@@ -470,10 +472,12 @@ static ssize_t export_store(const struct class *class,
 	}
 
 	status = gpiod_export(desc, true);
-	if (status < 0)
+	if (status < 0) {
 		gpiod_free(desc);
-	else
+	} else {
 		set_bit(FLAG_SYSFS, &desc->flags);
+		gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
+	}
 
 done:
 	if (status)

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] gpio: sysfs: emit chardev line-state events on active-low changes
  2024-10-24 11:32 [PATCH 0/5] gpio: sysfs: send character device notifications for sysfs class events Bartosz Golaszewski
                   ` (2 preceding siblings ...)
  2024-10-24 11:32 ` [PATCH 3/5] gpio: sysfs: emit chardev line-state events on GPIO export Bartosz Golaszewski
@ 2024-10-24 11:32 ` Bartosz Golaszewski
  2024-10-24 11:32 ` [PATCH 5/5] gpio: sysfs: emit chardev line-state events on edge store Bartosz Golaszewski
  4 siblings, 0 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2024-10-24 11:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Kent Gibson
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

The sysfs active_low attribute doesn't go through the usual paths so it
doesn't emit the line-state event. Add the missing call to
gpiod_line_state_notify() to gpio_sysfs_set_active_low().

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 drivers/gpio/gpiolib-sysfs.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 3f24bf278b77..b967b76ea046 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -305,6 +305,8 @@ static int gpio_sysfs_set_active_low(struct device *dev, int value)
 		status = gpio_sysfs_request_irq(dev, flags);
 	}
 
+	gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
 	return status;
 }
 

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] gpio: sysfs: emit chardev line-state events on edge store
  2024-10-24 11:32 [PATCH 0/5] gpio: sysfs: send character device notifications for sysfs class events Bartosz Golaszewski
                   ` (3 preceding siblings ...)
  2024-10-24 11:32 ` [PATCH 4/5] gpio: sysfs: emit chardev line-state events on active-low changes Bartosz Golaszewski
@ 2024-10-24 11:32 ` Bartosz Golaszewski
  4 siblings, 0 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2024-10-24 11:32 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Kent Gibson
  Cc: linux-gpio, linux-kernel, Bartosz Golaszewski

From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

In order to emit line-state events on edge changes in sysfs, update the
EDGE flags in the descriptor in gpio_sysfs_request_irq() and emit the
event on a successful store.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
---
 drivers/gpio/gpiolib-sysfs.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index b967b76ea046..87f27a0288f9 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -178,12 +178,16 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
 		return -ENODEV;
 
 	irq_flags = IRQF_SHARED;
-	if (flags & GPIO_IRQF_TRIGGER_FALLING)
+	if (flags & GPIO_IRQF_TRIGGER_FALLING) {
 		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
 			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
-	if (flags & GPIO_IRQF_TRIGGER_RISING)
+		set_bit(FLAG_EDGE_FALLING, &desc->flags);
+	}
+	if (flags & GPIO_IRQF_TRIGGER_RISING) {
 		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
 			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+		set_bit(FLAG_EDGE_RISING, &desc->flags);
+	}
 
 	/*
 	 * FIXME: This should be done in the irq_request_resources callback
@@ -209,6 +213,8 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
 err_unlock:
 	gpiochip_unlock_as_irq(guard.gc, gpio_chip_hwgpio(desc));
 err_put_kn:
+	clear_bit(FLAG_EDGE_RISING, &desc->flags);
+	clear_bit(FLAG_EDGE_FALLING, &desc->flags);
 	sysfs_put(data->value_kn);
 
 	return ret;
@@ -230,6 +236,8 @@ static void gpio_sysfs_free_irq(struct device *dev)
 	data->irq_flags = 0;
 	free_irq(data->irq, data);
 	gpiochip_unlock_as_irq(guard.gc, gpio_chip_hwgpio(desc));
+	clear_bit(FLAG_EDGE_RISING, &desc->flags);
+	clear_bit(FLAG_EDGE_FALLING, &desc->flags);
 	sysfs_put(data->value_kn);
 }
 
@@ -280,6 +288,8 @@ static ssize_t edge_store(struct device *dev,
 			status = size;
 	}
 
+	gpiod_line_state_notify(data->desc, GPIO_V2_LINE_CHANGED_CONFIG);
+
 	return status;
 }
 static DEVICE_ATTR_RW(edge);

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex
  2024-10-24 11:32 ` [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex Bartosz Golaszewski
@ 2024-10-25  2:53   ` Kent Gibson
  2024-10-25  7:33     ` Bartosz Golaszewski
  0 siblings, 1 reply; 8+ messages in thread
From: Kent Gibson @ 2024-10-25  2:53 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Linus Walleij, linux-gpio, linux-kernel, Bartosz Golaszewski

On Thu, Oct 24, 2024 at 01:32:44PM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>
> Shrink the code and drop some goto labels by using lock guards around
> gpiod_data::mutex.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
> ---
>  drivers/gpio/gpiolib-sysfs.c | 57 +++++++++++++-------------------------------
>  1 file changed, 17 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
> index 0c713baa7784..3ccb41a93ea7 100644
> --- a/drivers/gpio/gpiolib-sysfs.c
> +++ b/drivers/gpio/gpiolib-sysfs.c
> @@ -77,12 +77,10 @@ static ssize_t direction_show(struct device *dev,
>  	struct gpio_desc *desc = data->desc;
>  	int value;
>
> -	mutex_lock(&data->mutex);
> -
> -	gpiod_get_direction(desc);
> -	value = !!test_bit(FLAG_IS_OUT, &desc->flags);
> -
> -	mutex_unlock(&data->mutex);
> +	scoped_guard(mutex, &data->mutex) {
> +		gpiod_get_direction(desc);
> +		value = !!test_bit(FLAG_IS_OUT, &desc->flags);
> +	}
>
>  	return sysfs_emit(buf, "%s\n", value ? "out" : "in");
>  }
> @@ -94,7 +92,7 @@ static ssize_t direction_store(struct device *dev,
>  	struct gpio_desc *desc = data->desc;
>  	ssize_t			status;
>
> -	mutex_lock(&data->mutex);
> +	guard(mutex)(&data->mutex);
>
>  	if (sysfs_streq(buf, "high"))
>  		status = gpiod_direction_output_raw(desc, 1);
> @@ -105,8 +103,6 @@ static ssize_t direction_store(struct device *dev,
>  	else
>  		status = -EINVAL;
>
> -	mutex_unlock(&data->mutex);
> -
>  	return status ? : size;
>  }
>  static DEVICE_ATTR_RW(direction);
> @@ -118,11 +114,8 @@ static ssize_t value_show(struct device *dev,
>  	struct gpio_desc *desc = data->desc;
>  	ssize_t			status;
>
> -	mutex_lock(&data->mutex);
> -
> -	status = gpiod_get_value_cansleep(desc);
> -
> -	mutex_unlock(&data->mutex);
> +	scoped_guard(mutex, &data->mutex)
> +		status = gpiod_get_value_cansleep(desc);
>
>  	if (status < 0)
>  		return status;
> @@ -140,7 +133,7 @@ static ssize_t value_store(struct device *dev,
>
>  	status = kstrtol(buf, 0, &value);
>
> -	mutex_lock(&data->mutex);
> +	guard(mutex)(&data->mutex);
>
>  	if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
>  		status = -EPERM;
> @@ -149,8 +142,6 @@ static ssize_t value_store(struct device *dev,
>  		status = size;
>  	}
>
> -	mutex_unlock(&data->mutex);
> -
>  	return status;
>  }


With the guard, this can be further simplified by returning immediately
and collapsing the if-else chain:

@@ -135,14 +135,14 @@ static ssize_t value_store(struct device *dev,

        guard(mutex)(&data->mutex);

-       if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
-               status = -EPERM;
-       } else if (status == 0) {
-               gpiod_set_value_cansleep(desc, value);
-               status = size;
-       }
+       if (!test_bit(FLAG_IS_OUT, &desc->flags))
+               return -EPERM;

-       return status;
+       if (status)
+               return status;
+
+       gpiod_set_value_cansleep(desc, value);
+       return size;
 }

That also removes the overloading of status, previously containing a status
OR a size, which is no longer necessary.

>  static DEVICE_ATTR_PREALLOC(value, S_IWUSR | S_IRUGO, value_show, value_store);
> @@ -253,11 +244,8 @@ static ssize_t edge_show(struct device *dev,
>  	struct gpiod_data *data = dev_get_drvdata(dev);
>  	int flags;
>
> -	mutex_lock(&data->mutex);
> -
> -	flags = data->irq_flags;
> -
> -	mutex_unlock(&data->mutex);
> +	scoped_guard(mutex, &data->mutex)
> +		flags = data->irq_flags;
>
>  	if (flags >= ARRAY_SIZE(trigger_names))
>  		return 0;
> @@ -276,12 +264,10 @@ static ssize_t edge_store(struct device *dev,
>  	if (flags < 0)
>  		return flags;
>
> -	mutex_lock(&data->mutex);
> +	guard(mutex)(&data->mutex);
>
> -	if (flags == data->irq_flags) {
> -		status = size;
> -		goto out_unlock;
> -	}
> +	if (flags == data->irq_flags)
> +		return size;
>
>  	if (data->irq_flags)
>  		gpio_sysfs_free_irq(dev);
> @@ -292,9 +278,6 @@ static ssize_t edge_store(struct device *dev,
>  			status = size;
>  	}
>
> -out_unlock:
> -	mutex_unlock(&data->mutex);
> -
>  	return status;
>  }


Similarly drop the overloading of status:

@@ -257,7 +257,7 @@ static ssize_t edge_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t size)
 {
        struct gpiod_data *data = dev_get_drvdata(dev);
-       ssize_t status = size;
+       ssize_t status;
        int flags;

        flags = sysfs_match_string(trigger_names, buf);
@@ -274,11 +274,11 @@ static ssize_t edge_store(struct device *dev,

        if (flags) {
                status = gpio_sysfs_request_irq(dev, flags);
-               if (!status)
-                       status = size;
+               if (status)
+                       return status;
        }

-       return status;
+       return size;
 }

>  static DEVICE_ATTR_RW(edge);
> @@ -330,11 +313,8 @@ static ssize_t active_low_show(struct device *dev,
>  	struct gpio_desc *desc = data->desc;
>  	int value;
>
> -	mutex_lock(&data->mutex);
> -
> -	value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags);
> -
> -	mutex_unlock(&data->mutex);
> +	scoped_guard(mutex, &data->mutex)
> +		value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags);
>
>  	return sysfs_emit(buf, "%d\n", value);
>  }
> @@ -350,11 +330,8 @@ static ssize_t active_low_store(struct device *dev,
>  	if (status)
>  		return status;
>
> -	mutex_lock(&data->mutex);
> -
> -	status = gpio_sysfs_set_active_low(dev, value);
> -
> -	mutex_unlock(&data->mutex);
> +	scoped_guard(mutex, &data->mutex)
> +		status = gpio_sysfs_set_active_low(dev, value);
>
>  	return status ? : size;
>  }
>

Doesn't need to be scoped:

-       scoped_guard(mutex, &data->mutex)
-               status = gpio_sysfs_set_active_low(dev, value);
+       guard(mutex, &data->mutex);
+
+       status = gpio_sysfs_set_active_low(dev, value);

        return status ? : size;
 }


No issues with the other patches.

Cheers,
Kent.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex
  2024-10-25  2:53   ` Kent Gibson
@ 2024-10-25  7:33     ` Bartosz Golaszewski
  0 siblings, 0 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2024-10-25  7:33 UTC (permalink / raw)
  To: Kent Gibson; +Cc: Linus Walleij, linux-gpio, linux-kernel, Bartosz Golaszewski

On Fri, Oct 25, 2024 at 4:54 AM Kent Gibson <warthog618@gmail.com> wrote:
>
> > @@ -140,7 +133,7 @@ static ssize_t value_store(struct device *dev,
> >
> >       status = kstrtol(buf, 0, &value);
> >
> > -     mutex_lock(&data->mutex);
> > +     guard(mutex)(&data->mutex);
> >
> >       if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
> >               status = -EPERM;
> > @@ -149,8 +142,6 @@ static ssize_t value_store(struct device *dev,
> >               status = size;
> >       }
> >
> > -     mutex_unlock(&data->mutex);
> > -
> >       return status;
> >  }
>
>
> With the guard, this can be further simplified by returning immediately
> and collapsing the if-else chain:
>

Ah, right, it's the whole goal of this change after all.

Bart

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-10-25  7:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-24 11:32 [PATCH 0/5] gpio: sysfs: send character device notifications for sysfs class events Bartosz Golaszewski
2024-10-24 11:32 ` [PATCH 1/5] gpio: sysfs: use cleanup guards for gpiod_data::mutex Bartosz Golaszewski
2024-10-25  2:53   ` Kent Gibson
2024-10-25  7:33     ` Bartosz Golaszewski
2024-10-24 11:32 ` [PATCH 2/5] gpio: sysfs: use cleanup guards for the sysfs_lock mutex Bartosz Golaszewski
2024-10-24 11:32 ` [PATCH 3/5] gpio: sysfs: emit chardev line-state events on GPIO export Bartosz Golaszewski
2024-10-24 11:32 ` [PATCH 4/5] gpio: sysfs: emit chardev line-state events on active-low changes Bartosz Golaszewski
2024-10-24 11:32 ` [PATCH 5/5] gpio: sysfs: emit chardev line-state events on edge store Bartosz Golaszewski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).