+++ /dev/null
-From 9d846b1aebbe488f245f1aa463802ff9c34cc078 Mon Sep 17 00:00:00 2001
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Date: Mon, 10 Feb 2025 11:51:55 +0100
-Subject: gpiolib: check the return value of gpio_chip::get_direction()
-
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-
-commit 9d846b1aebbe488f245f1aa463802ff9c34cc078 upstream.
-
-As per the API contract - gpio_chip::get_direction() may fail and return
-a negative error number. However, we treat it as if it always returned 0
-or 1. Check the return value of the callback and propagate the error
-number up the stack.
-
-Cc: stable@vger.kernel.org
-Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
-Link: https://lore.kernel.org/r/20250210-gpio-sanitize-retvals-v1-1-12ea88506cb2@linaro.org
-Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/gpio/gpiolib.c | 44 +++++++++++++++++++++++++++++---------------
- 1 file changed, 29 insertions(+), 15 deletions(-)
-
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -1059,8 +1059,11 @@ int gpiochip_add_data_with_key(struct gp
- struct gpio_desc *desc = &gdev->descs[desc_index];
-
- if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) {
-- assign_bit(FLAG_IS_OUT,
-- &desc->flags, !gc->get_direction(gc, desc_index));
-+ ret = gc->get_direction(gc, desc_index);
-+ if (ret < 0)
-+ goto err_cleanup_desc_srcu;
-+
-+ assign_bit(FLAG_IS_OUT, &desc->flags, !ret);
- } else {
- assign_bit(FLAG_IS_OUT,
- &desc->flags, !gc->direction_input);
-@@ -2702,13 +2705,18 @@ int gpiod_direction_input(struct gpio_de
- if (guard.gc->direction_input) {
- ret = guard.gc->direction_input(guard.gc,
- gpio_chip_hwgpio(desc));
-- } else if (guard.gc->get_direction &&
-- (guard.gc->get_direction(guard.gc,
-- gpio_chip_hwgpio(desc)) != 1)) {
-- gpiod_warn(desc,
-- "%s: missing direction_input() operation and line is output\n",
-- __func__);
-- return -EIO;
-+ } else if (guard.gc->get_direction) {
-+ ret = guard.gc->get_direction(guard.gc,
-+ gpio_chip_hwgpio(desc));
-+ if (ret < 0)
-+ return ret;
-+
-+ if (ret != GPIO_LINE_DIRECTION_IN) {
-+ gpiod_warn(desc,
-+ "%s: missing direction_input() operation and line is output\n",
-+ __func__);
-+ return -EIO;
-+ }
- }
- if (ret == 0) {
- clear_bit(FLAG_IS_OUT, &desc->flags);
-@@ -2746,12 +2754,18 @@ static int gpiod_direction_output_raw_co
- gpio_chip_hwgpio(desc), val);
- } else {
- /* Check that we are in output mode if we can */
-- if (guard.gc->get_direction &&
-- guard.gc->get_direction(guard.gc, gpio_chip_hwgpio(desc))) {
-- gpiod_warn(desc,
-- "%s: missing direction_output() operation\n",
-- __func__);
-- return -EIO;
-+ if (guard.gc->get_direction) {
-+ ret = guard.gc->get_direction(guard.gc,
-+ gpio_chip_hwgpio(desc));
-+ if (ret < 0)
-+ return ret;
-+
-+ if (ret != GPIO_LINE_DIRECTION_OUT) {
-+ gpiod_warn(desc,
-+ "%s: missing direction_output() operation\n",
-+ __func__);
-+ return -EIO;
-+ }
- }
- /*
- * If we can't actively set the direction, we are some
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
-@@ -3082,6 +3082,8 @@ static int gpiod_get_raw_value_commit(co
+@@ -3068,6 +3068,8 @@ static int gpiod_get_raw_value_commit(co
static int gpio_chip_get_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
if (gc->get_multiple)
return gc->get_multiple(gc, mask, bits);
if (gc->get) {
-@@ -3112,6 +3114,7 @@ int gpiod_get_array_value_complex(bool r
+@@ -3098,6 +3100,7 @@ int gpiod_get_array_value_complex(bool r
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
int ret, i = 0;
/*
-@@ -3123,10 +3126,15 @@ int gpiod_get_array_value_complex(bool r
+@@ -3109,10 +3112,15 @@ int gpiod_get_array_value_complex(bool r
array_size <= array_info->size &&
(void *)array_info == desc_array + array_info->size) {
if (!can_sleep)
value_bitmap);
if (ret)
return ret;
-@@ -3407,6 +3415,8 @@ static void gpiod_set_raw_value_commit(s
+@@ -3393,6 +3401,8 @@ static void gpiod_set_raw_value_commit(s
static void gpio_chip_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
if (gc->set_multiple) {
gc->set_multiple(gc, mask, bits);
} else {
-@@ -3424,6 +3434,7 @@ int gpiod_set_array_value_complex(bool r
+@@ -3410,6 +3420,7 @@ int gpiod_set_array_value_complex(bool r
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
int i = 0;
/*
-@@ -3435,14 +3446,19 @@ int gpiod_set_array_value_complex(bool r
+@@ -3421,14 +3432,19 @@ int gpiod_set_array_value_complex(bool r
array_size <= array_info->size &&
(void *)array_info == desc_array + array_info->size) {
if (!can_sleep)
i = find_first_zero_bit(array_info->set_mask, array_size);
if (i == array_size)
-@@ -4698,9 +4714,10 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4684,9 +4700,10 @@ struct gpio_descs *__must_check gpiod_ge
{
struct gpio_desc *desc;
struct gpio_descs *descs;
size_t descs_size;
count = gpiod_count(dev, con_id);
-@@ -4721,7 +4738,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4707,7 +4724,7 @@ struct gpio_descs *__must_check gpiod_ge
descs->desc[descs->ndescs] = desc;
/*
* If pin hardware number of array member 0 is also 0, select
* its chip as a candidate for fast bitmap processing path.
-@@ -4729,8 +4746,8 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4715,8 +4732,8 @@ struct gpio_descs *__must_check gpiod_ge
if (descs->ndescs == 0 && gpio_chip_hwgpio(desc) == 0) {
struct gpio_descs *array;
array = krealloc(descs, descs_size +
struct_size(array_info, invert_mask, 3 * bitmap_size),
-@@ -4750,7 +4767,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4736,7 +4753,7 @@ struct gpio_descs *__must_check gpiod_ge
array_info->desc = descs->desc;
array_info->size = count;
bitmap_set(array_info->get_mask, descs->ndescs,
count - descs->ndescs);
bitmap_set(array_info->set_mask, descs->ndescs,
-@@ -4763,7 +4780,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4749,7 +4766,7 @@ struct gpio_descs *__must_check gpiod_ge
continue;
/* Unmark array members which don't belong to the 'fast' chip */
__clear_bit(descs->ndescs, array_info->get_mask);
__clear_bit(descs->ndescs, array_info->set_mask);
}
-@@ -4786,9 +4803,10 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4772,9 +4789,10 @@ struct gpio_descs *__must_check gpiod_ge
array_info->set_mask);
}
} else {
__clear_bit(descs->ndescs,
array_info->set_mask);
/* Identify 'fast' pins which require invertion */
-@@ -4800,7 +4818,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4786,7 +4804,7 @@ struct gpio_descs *__must_check gpiod_ge
if (array_info)
dev_dbg(dev,
"GPIO array info: chip=%s, size=%d, get_mask=%lx, set_mask=%lx, invert_mask=%lx\n",
drm-i915-gt-use-spin_lock_irqsave-in-interruptible-context.patch
io_uring-rw-forbid-multishot-async-reads.patch
io_uring-prevent-opcode-speculation.patch
-gpiolib-check-the-return-value-of-gpio_chip-get_direction.patch
gpiolib-protect-gpio_chip-with-srcu-in-array_info-paths-in-multi-get-set.patch
tee-optee-fix-supplicant-wait-loop.patch
drop_monitor-fix-incorrect-initialization-order.patch
+++ /dev/null
-From 9d846b1aebbe488f245f1aa463802ff9c34cc078 Mon Sep 17 00:00:00 2001
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Date: Mon, 10 Feb 2025 11:51:55 +0100
-Subject: gpiolib: check the return value of gpio_chip::get_direction()
-
-From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-
-commit 9d846b1aebbe488f245f1aa463802ff9c34cc078 upstream.
-
-As per the API contract - gpio_chip::get_direction() may fail and return
-a negative error number. However, we treat it as if it always returned 0
-or 1. Check the return value of the callback and propagate the error
-number up the stack.
-
-Cc: stable@vger.kernel.org
-Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
-Link: https://lore.kernel.org/r/20250210-gpio-sanitize-retvals-v1-1-12ea88506cb2@linaro.org
-Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/gpio/gpiolib.c | 44 +++++++++++++++++++++++++++++---------------
- 1 file changed, 29 insertions(+), 15 deletions(-)
-
---- a/drivers/gpio/gpiolib.c
-+++ b/drivers/gpio/gpiolib.c
-@@ -1057,8 +1057,11 @@ int gpiochip_add_data_with_key(struct gp
- desc->gdev = gdev;
-
- if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) {
-- assign_bit(FLAG_IS_OUT,
-- &desc->flags, !gc->get_direction(gc, desc_index));
-+ ret = gc->get_direction(gc, desc_index);
-+ if (ret < 0)
-+ goto err_cleanup_desc_srcu;
-+
-+ assign_bit(FLAG_IS_OUT, &desc->flags, !ret);
- } else {
- assign_bit(FLAG_IS_OUT,
- &desc->flags, !gc->direction_input);
-@@ -2728,13 +2731,18 @@ int gpiod_direction_input_nonotify(struc
- if (guard.gc->direction_input) {
- ret = guard.gc->direction_input(guard.gc,
- gpio_chip_hwgpio(desc));
-- } else if (guard.gc->get_direction &&
-- (guard.gc->get_direction(guard.gc,
-- gpio_chip_hwgpio(desc)) != 1)) {
-- gpiod_warn(desc,
-- "%s: missing direction_input() operation and line is output\n",
-- __func__);
-- return -EIO;
-+ } else if (guard.gc->get_direction) {
-+ ret = guard.gc->get_direction(guard.gc,
-+ gpio_chip_hwgpio(desc));
-+ if (ret < 0)
-+ return ret;
-+
-+ if (ret != GPIO_LINE_DIRECTION_IN) {
-+ gpiod_warn(desc,
-+ "%s: missing direction_input() operation and line is output\n",
-+ __func__);
-+ return -EIO;
-+ }
- }
- if (ret == 0) {
- clear_bit(FLAG_IS_OUT, &desc->flags);
-@@ -2771,12 +2779,18 @@ static int gpiod_direction_output_raw_co
- gpio_chip_hwgpio(desc), val);
- } else {
- /* Check that we are in output mode if we can */
-- if (guard.gc->get_direction &&
-- guard.gc->get_direction(guard.gc, gpio_chip_hwgpio(desc))) {
-- gpiod_warn(desc,
-- "%s: missing direction_output() operation\n",
-- __func__);
-- return -EIO;
-+ if (guard.gc->get_direction) {
-+ ret = guard.gc->get_direction(guard.gc,
-+ gpio_chip_hwgpio(desc));
-+ if (ret < 0)
-+ return ret;
-+
-+ if (ret != GPIO_LINE_DIRECTION_OUT) {
-+ gpiod_warn(desc,
-+ "%s: missing direction_output() operation\n",
-+ __func__);
-+ return -EIO;
-+ }
- }
- /*
- * If we can't actively set the direction, we are some
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
-@@ -3143,6 +3143,8 @@ static int gpiod_get_raw_value_commit(co
+@@ -3129,6 +3129,8 @@ static int gpiod_get_raw_value_commit(co
static int gpio_chip_get_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
if (gc->get_multiple)
return gc->get_multiple(gc, mask, bits);
if (gc->get) {
-@@ -3173,6 +3175,7 @@ int gpiod_get_array_value_complex(bool r
+@@ -3159,6 +3161,7 @@ int gpiod_get_array_value_complex(bool r
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
int ret, i = 0;
/*
-@@ -3184,10 +3187,15 @@ int gpiod_get_array_value_complex(bool r
+@@ -3170,10 +3173,15 @@ int gpiod_get_array_value_complex(bool r
array_size <= array_info->size &&
(void *)array_info == desc_array + array_info->size) {
if (!can_sleep)
value_bitmap);
if (ret)
return ret;
-@@ -3468,6 +3476,8 @@ static void gpiod_set_raw_value_commit(s
+@@ -3454,6 +3462,8 @@ static void gpiod_set_raw_value_commit(s
static void gpio_chip_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
if (gc->set_multiple) {
gc->set_multiple(gc, mask, bits);
} else {
-@@ -3485,6 +3495,7 @@ int gpiod_set_array_value_complex(bool r
+@@ -3471,6 +3481,7 @@ int gpiod_set_array_value_complex(bool r
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
int i = 0;
/*
-@@ -3496,14 +3507,19 @@ int gpiod_set_array_value_complex(bool r
+@@ -3482,14 +3493,19 @@ int gpiod_set_array_value_complex(bool r
array_size <= array_info->size &&
(void *)array_info == desc_array + array_info->size) {
if (!can_sleep)
i = find_first_zero_bit(array_info->set_mask, array_size);
if (i == array_size)
-@@ -4765,9 +4781,10 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4751,9 +4767,10 @@ struct gpio_descs *__must_check gpiod_ge
{
struct gpio_desc *desc;
struct gpio_descs *descs;
size_t descs_size;
count = gpiod_count(dev, con_id);
-@@ -4788,7 +4805,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4774,7 +4791,7 @@ struct gpio_descs *__must_check gpiod_ge
descs->desc[descs->ndescs] = desc;
/*
* If pin hardware number of array member 0 is also 0, select
* its chip as a candidate for fast bitmap processing path.
-@@ -4796,8 +4813,8 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4782,8 +4799,8 @@ struct gpio_descs *__must_check gpiod_ge
if (descs->ndescs == 0 && gpio_chip_hwgpio(desc) == 0) {
struct gpio_descs *array;
array = krealloc(descs, descs_size +
struct_size(array_info, invert_mask, 3 * bitmap_size),
-@@ -4817,7 +4834,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4803,7 +4820,7 @@ struct gpio_descs *__must_check gpiod_ge
array_info->desc = descs->desc;
array_info->size = count;
bitmap_set(array_info->get_mask, descs->ndescs,
count - descs->ndescs);
bitmap_set(array_info->set_mask, descs->ndescs,
-@@ -4830,7 +4847,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4816,7 +4833,7 @@ struct gpio_descs *__must_check gpiod_ge
continue;
/* Unmark array members which don't belong to the 'fast' chip */
__clear_bit(descs->ndescs, array_info->get_mask);
__clear_bit(descs->ndescs, array_info->set_mask);
}
-@@ -4853,9 +4870,10 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4839,9 +4856,10 @@ struct gpio_descs *__must_check gpiod_ge
array_info->set_mask);
}
} else {
__clear_bit(descs->ndescs,
array_info->set_mask);
/* Identify 'fast' pins which require invertion */
-@@ -4867,7 +4885,7 @@ struct gpio_descs *__must_check gpiod_ge
+@@ -4853,7 +4871,7 @@ struct gpio_descs *__must_check gpiod_ge
if (array_info)
dev_dbg(dev,
"GPIO array info: chip=%s, size=%d, get_mask=%lx, set_mask=%lx, invert_mask=%lx\n",
drm-i915-dsi-use-trans_ddi_func_ctl-s-own-port-width-macro.patch
io_uring-rw-forbid-multishot-async-reads.patch
io_uring-prevent-opcode-speculation.patch
-gpiolib-check-the-return-value-of-gpio_chip-get_direction.patch
gpiolib-protect-gpio_chip-with-srcu-in-array_info-paths-in-multi-get-set.patch
tee-optee-fix-supplicant-wait-loop.patch
drop_monitor-fix-incorrect-initialization-order.patch