Re: [PATCH 4/5] gpiolib: don't overwrite the entire flags field in gpiod_free_commit()

From: Kent Gibson

Date: Wed Nov 04 2026 - 23:30:04 EST


On Wed, Nov 04, 2026 at 04:36:59PM +0100, Bartosz Golaszewski wrote:
> 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@xxxxxxxxxxxxxxx
> Fixes: 35b545332b80 ("gpio: remove gpio_lock")
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
> ---
> 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
>

Not directly related to your change, but the debounce_period_us is
protected by the GPIOD_FLAG_REQUESTED flag, so it should be cleared
before the flag, else it could potentially race with a new request.
Not sure if you want to fix it here or in a separate patch.

Cheers,
Kent.