[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20250311-gpio-set-check-output-v1-1-d971bca9e6fa@linaro.org>
Date: Tue, 11 Mar 2025 15:19:51 +0100
From: Bartosz Golaszewski <brgl@...ev.pl>
To: Bartosz Golaszewski <brgl@...ev.pl>, Kent Gibson <warthog618@...il.com>,
Linus Walleij <linus.walleij@...aro.org>,
Matti Vaittinen <mazziesaccount@...il.com>
Cc: linux-gpio@...r.kernel.org, linux-kernel@...r.kernel.org,
Bartosz Golaszewski <bartosz.golaszewski@...aro.org>
Subject: [PATCH] gpiolib: don't allow setting values on input lines
From: Bartosz Golaszewski <bartosz.golaszewski@...aro.org>
Some drivers as well as the character device and sysfs code check
whether the line actually is in output mode before allowing the user to
set a value.
However, GPIO value setters now return integer values and can indicate
failures. This allows us to move these checks into the core code.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@...aro.org>
---
drivers/gpio/gpiolib-cdev.c | 3 ---
drivers/gpio/gpiolib-sysfs.c | 12 +++++-------
drivers/gpio/gpiolib.c | 12 ++++++++++++
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 40f76a90fd7d..8da9c28d57f6 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -1366,9 +1366,6 @@ static long linereq_set_values(struct linereq *lr, void __user *ip)
/* scan requested lines to determine the subset to be set */
for (num_set = 0, i = 0; i < lr->num_lines; i++) {
if (lv.mask & BIT_ULL(i)) {
- /* setting inputs is not allowed */
- if (!test_bit(FLAG_IS_OUT, &lr->lines[i].desc->flags))
- return -EPERM;
/* add to compacted values */
if (lv.bits & BIT_ULL(i))
__set_bit(num_set, vals);
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 1acfa43bf1ab..4a3aa09dad9d 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -134,16 +134,14 @@ static ssize_t value_store(struct device *dev,
long value;
status = kstrtol(buf, 0, &value);
-
- guard(mutex)(&data->mutex);
-
- if (!test_bit(FLAG_IS_OUT, &desc->flags))
- return -EPERM;
-
if (status)
return status;
- gpiod_set_value_cansleep(desc, value);
+ guard(mutex)(&data->mutex);
+
+ status = gpiod_set_value_cansleep(desc, value);
+ if (status)
+ return status;
return size;
}
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index e5eb3f0ee071..a4b746e80e57 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3592,6 +3592,9 @@ static int gpio_set_open_source_value_commit(struct gpio_desc *desc, bool value)
static int gpiod_set_raw_value_commit(struct gpio_desc *desc, bool value)
{
+ if (unlikely(!test_bit(FLAG_IS_OUT, &desc->flags)))
+ return -EPERM;
+
CLASS(gpio_chip_guard, guard)(desc);
if (!guard.gc)
return -ENODEV;
@@ -3663,6 +3666,12 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
if (!can_sleep)
WARN_ON(array_info->gdev->can_sleep);
+ for (i = 0; i < array_size; i++) {
+ if (unlikely(!test_bit(FLAG_IS_OUT,
+ &desc_array[i]->flags)))
+ return -EPERM;
+ }
+
guard(srcu)(&array_info->gdev->srcu);
gc = srcu_dereference(array_info->gdev->chip,
&array_info->gdev->srcu);
@@ -3722,6 +3731,9 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
int hwgpio = gpio_chip_hwgpio(desc);
int value = test_bit(i, value_bitmap);
+ if (unlikely(!test_bit(FLAG_IS_OUT, &desc->flags)))
+ return -EPERM;
+
/*
* Pins applicable for fast input but not for
* fast output processing may have been already
---
base-commit: 0a2f889128969dab41861b6e40111aa03dc57014
change-id: 20250311-gpio-set-check-output-8321c1859ae3
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@...aro.org>
Powered by blists - more mailing lists