* [PATCH 0/5] gpiolib: improve concurrent access to the flags field of struct gpio_desc
@ 2026-11-04 15:36 Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 1/5] gpiolib: don't overwrite the entire flags field in gpiod_get_direction() Bartosz Golaszewski
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 15:36 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Andy Shevchenko, Kent Gibson,
Adrian Ambrozewicz
Cc: linux-gpio, linux-kernel, Bartosz Golaszewski, stable
This is a follow-up to our discussion[1] about desc->flags and possible
races with users who don't/can't synchronize with other means.
It's an attempt to use try_cmpxchg() to update only the required flags
atomically where needed + minor fixes using atomic variants of bitops
where it makes sense.
[1] https://lore.kernel.org/all/20261015153714.GA105746@rigel/
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
Bartosz Golaszewski (5):
gpiolib: don't overwrite the entire flags field in gpiod_get_direction()
gpio: shared: use atomic set_bit() for descriptor flags
gpiolib: provide gpiod_update_flags()
gpiolib: don't overwrite the entire flags field in gpiod_free_commit()
gpio: cdev: don't overwrite the whole flags field when configuring lines
drivers/gpio/gpiolib-cdev.c | 118 +++++++++++++++++++++++-------------------
drivers/gpio/gpiolib-shared.c | 6 +--
drivers/gpio/gpiolib.c | 29 +++++------
drivers/gpio/gpiolib.h | 21 ++++++++
4 files changed, 103 insertions(+), 71 deletions(-)
---
base-commit: f1fa734d14164cddc063dbf2138c2feb38baab42
change-id: 20261104-gpio-desc-flags-atomic-cc963a1ccfd0
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/5] gpiolib: don't overwrite the entire flags field in gpiod_get_direction()
2026-11-04 15:36 [PATCH 0/5] gpiolib: improve concurrent access to the flags field of struct gpio_desc Bartosz Golaszewski
@ 2026-11-04 15:36 ` Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 2/5] gpio: shared: use atomic set_bit() for descriptor flags Bartosz Golaszewski
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 15:36 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Andy Shevchenko, Kent Gibson,
Adrian Ambrozewicz
Cc: linux-gpio, linux-kernel, Bartosz Golaszewski, stable
gpiod_get_direction() snapshots desc->flags with READ_ONCE(), updates
FLAG_IS_OUT in the local copy and writes the whole word back with
WRITE_ONCE(). Any bit that a concurrent user sets or clears atomically in
between - for instance: FLAG_USED_AS_IRQ from gpiochip_lock_as_irq() - is
silently lost.
Update FLAG_IS_OUT with a single atomic assign_bit() directly on
desc->flags. The earlier READ_ONCE() snapshot is only used for the
open-drain check and stays.
Cc: stable@vger.kernel.org
Fixes: 2559f2e09211 ("gpio: reinforce desc->flags handling")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/gpio/gpiolib.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index fbdeda2f278713a47c2e3d2a6640f387f6d92227..63b65b646fbcfa9ea0f724d1d3e1ac22ba28f638 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -486,8 +486,7 @@ int gpiod_get_direction(struct gpio_desc *desc)
if (ret > 0)
ret = 1;
- assign_bit(GPIOD_FLAG_IS_OUT, &flags, !ret);
- WRITE_ONCE(desc->flags, flags);
+ assign_bit(GPIOD_FLAG_IS_OUT, &desc->flags, !ret);
return ret;
}
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/5] gpio: shared: use atomic set_bit() for descriptor flags
2026-11-04 15:36 [PATCH 0/5] gpiolib: improve concurrent access to the flags field of struct gpio_desc Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 1/5] gpiolib: don't overwrite the entire flags field in gpiod_get_direction() Bartosz Golaszewski
@ 2026-11-04 15:36 ` Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 3/5] gpiolib: provide gpiod_update_flags() Bartosz Golaszewski
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 15:36 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Andy Shevchenko, Kent Gibson,
Adrian Ambrozewicz
Cc: linux-gpio, linux-kernel, Bartosz Golaszewski, stable
Use the atomic set_bit() instead of __set_bit() on desc->flags so that
every modification of the field uses atomic bitops. No functional change
as these run before any line of the chip can be requested.
Cc: stable@vger.kernel.org
Fixes: eb374f764a70 ("gpio: provide gpiod_is_shared()")
Fixes: 310a4a9cbb17 ("gpio: shared: shorten the critical section in gpiochip_setup_shared()")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/gpio/gpiolib-shared.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index 8c9ac9d9330490b17fb3936b8758beb97a308a15..d94fb94f31c2f487d2e45924e11c33570466a0f1 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -532,8 +532,8 @@ int gpiochip_setup_shared(struct gpio_chip *gc)
* This is a shared GPIO proxy. Mark its
* descriptor as such and return here.
*/
- __set_bit(GPIOD_FLAG_SHARED_PROXY,
- &gdev->descs[0].flags);
+ set_bit(GPIOD_FLAG_SHARED_PROXY,
+ &gdev->descs[0].flags);
return 0;
}
}
@@ -573,7 +573,7 @@ int gpiochip_setup_shared(struct gpio_chip *gc)
desc = &gdev->descs[entry->offset];
- __set_bit(GPIOD_FLAG_SHARED, &desc->flags);
+ set_bit(GPIOD_FLAG_SHARED, &desc->flags);
/*
* Shared GPIOs are not requested via the normal path. Make
* them inaccessible to anyone even before we register the
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/5] gpiolib: provide gpiod_update_flags()
2026-11-04 15:36 [PATCH 0/5] gpiolib: improve concurrent access to the flags field of struct gpio_desc Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 1/5] gpiolib: don't overwrite the entire flags field in gpiod_get_direction() Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 2/5] gpio: shared: use atomic set_bit() for descriptor flags Bartosz Golaszewski
@ 2026-11-04 15:36 ` Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 4/5] gpiolib: don't overwrite the entire flags field in gpiod_free_commit() Bartosz Golaszewski
2026-11-04 15:37 ` [PATCH 5/5] gpio: cdev: don't overwrite the whole flags field when configuring lines Bartosz Golaszewski
4 siblings, 0 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 15:36 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Andy Shevchenko, Kent Gibson,
Adrian Ambrozewicz
Cc: linux-gpio, linux-kernel, Bartosz Golaszewski
We have several places in GPIO core where we copy the desc->flags field,
change several bits in the copy and write back the whole word with
WRITE_ONCE(). Concurrent updates of flags that modify other bits are
lost.
Add gpiod_update_flags() - it replaces a masked set of bits with
try_cmpxchg() loop. All bits are updated in one atomic step so no other
thread can observe it half-done. Unmasked bits are not rewritten with
stale values.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/gpio/gpiolib.h | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 650a702741dfb938fbdf11db65a46ac85b6af512..10659ffcf2baef9d4a7584858cda1849b26c12e8 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -9,6 +9,7 @@
#ifndef GPIOLIB_H
#define GPIOLIB_H
+#include <linux/atomic.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/err.h>
@@ -223,6 +224,26 @@ struct gpio_desc {
#endif
};
+/**
+ * gpiod_update_flags() - Atomically update several descriptor flags at once
+ * @desc: GPIO descriptor to update.
+ * @mask: Bits (not bit numbers) to modify.
+ * @val: New values for the bits selected by @mask.
+ *
+ * Replace the bits in @mask with the corresponding bits of @val in a single
+ * atomic step, so that no other context can observe a half-updated state of
+ * these bits. Bits outside of @mask are never rewritten with stale values, so
+ * concurrent atomic bit operations on them are preserved.
+ */
+static inline void gpiod_update_flags(struct gpio_desc *desc,
+ unsigned long mask, unsigned long val)
+{
+ unsigned long old = READ_ONCE(desc->flags);
+
+ while (!try_cmpxchg(&desc->flags, &old, (old & ~mask) | (val & mask)))
+ ;
+}
+
#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
struct gpio_chip_guard {
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4/5] gpiolib: don't overwrite the entire flags field in gpiod_free_commit()
2026-11-04 15:36 [PATCH 0/5] gpiolib: improve concurrent access to the flags field of struct gpio_desc Bartosz Golaszewski
` (2 preceding siblings ...)
2026-11-04 15:36 ` [PATCH 3/5] gpiolib: provide gpiod_update_flags() Bartosz Golaszewski
@ 2026-11-04 15:36 ` Bartosz Golaszewski
2026-11-04 15:37 ` [PATCH 5/5] gpio: cdev: don't overwrite the whole flags field when configuring lines Bartosz Golaszewski
4 siblings, 0 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 15:36 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Andy Shevchenko, Kent Gibson,
Adrian Ambrozewicz
Cc: linux-gpio, linux-kernel, Bartosz Golaszewski, stable
Use gpiod_update_flags() to clear all request-related flags in one go
instead of risking racing with concurrent users and overwriting any
changes they could have done between READ_ONCE() and WRITE_ONCE().
Cc: stable@vger.kernel.org
Fixes: 35b545332b80 ("gpio: remove gpio_lock")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/gpio/gpiolib.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 63b65b646fbcfa9ea0f724d1d3e1ac22ba28f638..28d4cf0cef70f437dc4271f82975d09dc55125ea 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2693,23 +2693,23 @@ void gpiod_free_commit(struct gpio_desc *desc)
if (guard.gc->free)
guard.gc->free(guard.gc, gpiod_hwgpio(desc));
- clear_bit(GPIOD_FLAG_ACTIVE_LOW, &flags);
- clear_bit(GPIOD_FLAG_REQUESTED, &flags);
- clear_bit(GPIOD_FLAG_OPEN_DRAIN, &flags);
- clear_bit(GPIOD_FLAG_OPEN_SOURCE, &flags);
- clear_bit(GPIOD_FLAG_PULL_UP, &flags);
- clear_bit(GPIOD_FLAG_PULL_DOWN, &flags);
- clear_bit(GPIOD_FLAG_BIAS_DISABLE, &flags);
- clear_bit(GPIOD_FLAG_EDGE_RISING, &flags);
- clear_bit(GPIOD_FLAG_EDGE_FALLING, &flags);
- clear_bit(GPIOD_FLAG_EVENT_CLOCK_REALTIME, &flags);
- clear_bit(GPIOD_FLAG_EVENT_CLOCK_HTE, &flags);
- clear_bit(GPIOD_FLAG_IS_HOGGED, &flags);
#ifdef CONFIG_OF_DYNAMIC
WRITE_ONCE(desc->hog, NULL);
#endif
desc_set_label(desc, NULL);
- WRITE_ONCE(desc->flags, flags);
+ gpiod_update_flags(desc,
+ BIT(GPIOD_FLAG_ACTIVE_LOW) |
+ BIT(GPIOD_FLAG_REQUESTED) |
+ BIT(GPIOD_FLAG_OPEN_DRAIN) |
+ BIT(GPIOD_FLAG_OPEN_SOURCE) |
+ BIT(GPIOD_FLAG_PULL_UP) |
+ BIT(GPIOD_FLAG_PULL_DOWN) |
+ BIT(GPIOD_FLAG_BIAS_DISABLE) |
+ BIT(GPIOD_FLAG_EDGE_RISING) |
+ BIT(GPIOD_FLAG_EDGE_FALLING) |
+ BIT(GPIOD_FLAG_EVENT_CLOCK_REALTIME) |
+ BIT(GPIOD_FLAG_EVENT_CLOCK_HTE) |
+ BIT(GPIOD_FLAG_IS_HOGGED), 0);
#ifdef CONFIG_GPIO_CDEV
WRITE_ONCE(desc->debounce_period_us, 0);
#endif
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 5/5] gpio: cdev: don't overwrite the whole flags field when configuring lines
2026-11-04 15:36 [PATCH 0/5] gpiolib: improve concurrent access to the flags field of struct gpio_desc Bartosz Golaszewski
` (3 preceding siblings ...)
2026-11-04 15:36 ` [PATCH 4/5] gpiolib: don't overwrite the entire flags field in gpiod_free_commit() Bartosz Golaszewski
@ 2026-11-04 15:37 ` Bartosz Golaszewski
4 siblings, 0 replies; 6+ messages in thread
From: Bartosz Golaszewski @ 2026-11-04 15:37 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Andy Shevchenko, Kent Gibson,
Adrian Ambrozewicz
Cc: linux-gpio, linux-kernel, Bartosz Golaszewski, stable
linehandle_flags_to_desc_flags() and
gpio_v2_line_config_flags_to_desc_flags() read the flags word with
READ_ONCE(), modify the local copy and write it back with WRITE_ONCE().
The per-request config_mutex does not exclude sysfs, the irq core or
drivers touching the same descriptor, so bits they set or clear
concurrently can be lost.
Build the mask of bits owned by the line configuration and their new
values locally and apply them with gpiod_update_flags(). The whole
group changes in a single atomic step.
Cc: stable@vger.kernel.org
Fixes: b7adfb6076ff ("gpio: cdev: update flags at once when reconfiguring from user-space")
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/gpio/gpiolib-cdev.c | 118 ++++++++++++++++++++++++--------------------
1 file changed, 65 insertions(+), 53 deletions(-)
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 3f1f8c9acfc3c10d5b3e86b70009f1226793cbc7..b7f0aec12c8551e39d042a1999fdfb5683ae97d7 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -140,24 +140,30 @@ static int linehandle_validate_flags(u32 flags)
return 0;
}
-static void linehandle_flags_to_desc_flags(u32 lflags, unsigned long *flagsp)
-{
- unsigned long flags = READ_ONCE(*flagsp);
-
- assign_bit(GPIOD_FLAG_ACTIVE_LOW, &flags,
- lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW);
- assign_bit(GPIOD_FLAG_OPEN_DRAIN, &flags,
- lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN);
- assign_bit(GPIOD_FLAG_OPEN_SOURCE, &flags,
- lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
- assign_bit(GPIOD_FLAG_PULL_UP, &flags,
- lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP);
- assign_bit(GPIOD_FLAG_PULL_DOWN, &flags,
- lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN);
- assign_bit(GPIOD_FLAG_BIAS_DISABLE, &flags,
- lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE);
-
- WRITE_ONCE(*flagsp, flags);
+static void linehandle_flags_to_desc_flags(u32 lflags, struct gpio_desc *desc)
+{
+ const unsigned long mask = BIT(GPIOD_FLAG_ACTIVE_LOW) |
+ BIT(GPIOD_FLAG_OPEN_DRAIN) |
+ BIT(GPIOD_FLAG_OPEN_SOURCE) |
+ BIT(GPIOD_FLAG_PULL_UP) |
+ BIT(GPIOD_FLAG_PULL_DOWN) |
+ BIT(GPIOD_FLAG_BIAS_DISABLE);
+ unsigned long val = 0;
+
+ __assign_bit(GPIOD_FLAG_ACTIVE_LOW, &val,
+ lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW);
+ __assign_bit(GPIOD_FLAG_OPEN_DRAIN, &val,
+ lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN);
+ __assign_bit(GPIOD_FLAG_OPEN_SOURCE, &val,
+ lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
+ __assign_bit(GPIOD_FLAG_PULL_UP, &val,
+ lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP);
+ __assign_bit(GPIOD_FLAG_PULL_DOWN, &val,
+ lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN);
+ __assign_bit(GPIOD_FLAG_BIAS_DISABLE, &val,
+ lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE);
+
+ gpiod_update_flags(desc, mask, val);
}
static long linehandle_set_config(struct linehandle_state *lh,
@@ -182,7 +188,7 @@ static long linehandle_set_config(struct linehandle_state *lh,
for (i = 0; i < lh->num_descs; i++) {
desc = lh->descs[i];
- linehandle_flags_to_desc_flags(lflags, &desc->flags);
+ linehandle_flags_to_desc_flags(lflags, desc);
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
int val = !!gcnf.default_values[i];
@@ -346,7 +352,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
if (ret)
return ret;
lh->descs[i] = desc;
- linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
+ linehandle_flags_to_desc_flags(handlereq.flags, desc);
ret = gpiod_set_transitory(desc, false);
if (ret < 0)
@@ -1224,36 +1230,42 @@ static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc,
}
static void gpio_v2_line_config_flags_to_desc_flags(u64 lflags,
- unsigned long *flagsp)
-{
- unsigned long flags = READ_ONCE(*flagsp);
-
- assign_bit(GPIOD_FLAG_ACTIVE_LOW, &flags,
- lflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW);
-
- assign_bit(GPIOD_FLAG_EDGE_RISING, &flags,
- lflags & GPIO_V2_LINE_FLAG_EDGE_RISING);
- assign_bit(GPIOD_FLAG_EDGE_FALLING, &flags,
- lflags & GPIO_V2_LINE_FLAG_EDGE_FALLING);
-
- assign_bit(GPIOD_FLAG_OPEN_DRAIN, &flags,
- lflags & GPIO_V2_LINE_FLAG_OPEN_DRAIN);
- assign_bit(GPIOD_FLAG_OPEN_SOURCE, &flags,
- lflags & GPIO_V2_LINE_FLAG_OPEN_SOURCE);
-
- assign_bit(GPIOD_FLAG_PULL_UP, &flags,
- lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP);
- assign_bit(GPIOD_FLAG_PULL_DOWN, &flags,
- lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN);
- assign_bit(GPIOD_FLAG_BIAS_DISABLE, &flags,
- lflags & GPIO_V2_LINE_FLAG_BIAS_DISABLED);
-
- assign_bit(GPIOD_FLAG_EVENT_CLOCK_REALTIME, &flags,
- lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME);
- assign_bit(GPIOD_FLAG_EVENT_CLOCK_HTE, &flags,
- lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE);
-
- WRITE_ONCE(*flagsp, flags);
+ struct gpio_desc *desc)
+{
+ const unsigned long mask = BIT(GPIOD_FLAG_ACTIVE_LOW) |
+ BIT(GPIOD_FLAG_EDGE_RISING) |
+ BIT(GPIOD_FLAG_EDGE_FALLING) |
+ BIT(GPIOD_FLAG_OPEN_DRAIN) |
+ BIT(GPIOD_FLAG_OPEN_SOURCE) |
+ BIT(GPIOD_FLAG_PULL_UP) |
+ BIT(GPIOD_FLAG_PULL_DOWN) |
+ BIT(GPIOD_FLAG_BIAS_DISABLE) |
+ BIT(GPIOD_FLAG_EVENT_CLOCK_REALTIME) |
+ BIT(GPIOD_FLAG_EVENT_CLOCK_HTE);
+ unsigned long val = 0;
+
+ __assign_bit(GPIOD_FLAG_ACTIVE_LOW, &val,
+ lflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW);
+ __assign_bit(GPIOD_FLAG_EDGE_RISING, &val,
+ lflags & GPIO_V2_LINE_FLAG_EDGE_RISING);
+ __assign_bit(GPIOD_FLAG_EDGE_FALLING, &val,
+ lflags & GPIO_V2_LINE_FLAG_EDGE_FALLING);
+ __assign_bit(GPIOD_FLAG_OPEN_DRAIN, &val,
+ lflags & GPIO_V2_LINE_FLAG_OPEN_DRAIN);
+ __assign_bit(GPIOD_FLAG_OPEN_SOURCE, &val,
+ lflags & GPIO_V2_LINE_FLAG_OPEN_SOURCE);
+ __assign_bit(GPIOD_FLAG_PULL_UP, &val,
+ lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP);
+ __assign_bit(GPIOD_FLAG_PULL_DOWN, &val,
+ lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN);
+ __assign_bit(GPIOD_FLAG_BIAS_DISABLE, &val,
+ lflags & GPIO_V2_LINE_FLAG_BIAS_DISABLED);
+ __assign_bit(GPIOD_FLAG_EVENT_CLOCK_REALTIME, &val,
+ lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME);
+ __assign_bit(GPIOD_FLAG_EVENT_CLOCK_HTE, &val,
+ lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE);
+
+ gpiod_update_flags(desc, mask, val);
}
static long linereq_get_values(struct linereq *lr, void __user *ip)
@@ -1411,7 +1423,7 @@ static long linereq_set_config(struct linereq *lr, void __user *ip)
*/
if (!(flags & GPIO_V2_LINE_DIRECTION_FLAGS))
continue;
- gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags);
+ gpio_v2_line_config_flags_to_desc_flags(flags, desc);
edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS;
if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
int val = gpio_v2_line_config_output_value(&lc, i);
@@ -1667,7 +1679,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
lr->lines[i].desc = desc;
flags = gpio_v2_line_config_flags(lc, i);
- gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags);
+ gpio_v2_line_config_flags_to_desc_flags(flags, desc);
ret = gpiod_set_transitory(desc, false);
if (ret < 0)
@@ -2062,7 +2074,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
le->desc = desc;
le->eflags = eflags;
- linehandle_flags_to_desc_flags(lflags, &desc->flags);
+ linehandle_flags_to_desc_flags(lflags, desc);
ret = gpiod_direction_input(desc);
if (ret)
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-11-04 15:37 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04 15:36 [PATCH 0/5] gpiolib: improve concurrent access to the flags field of struct gpio_desc Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 1/5] gpiolib: don't overwrite the entire flags field in gpiod_get_direction() Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 2/5] gpio: shared: use atomic set_bit() for descriptor flags Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 3/5] gpiolib: provide gpiod_update_flags() Bartosz Golaszewski
2026-11-04 15:36 ` [PATCH 4/5] gpiolib: don't overwrite the entire flags field in gpiod_free_commit() Bartosz Golaszewski
2026-11-04 15:37 ` [PATCH 5/5] gpio: cdev: don't overwrite the whole flags field when configuring lines Bartosz Golaszewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®