From ac46dac1613a7c971e28e16d3a7a6ad4b1ae6c5a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 15 Oct 2026 14:39:21 -0500 Subject: [PATCH 01/12] gpiolib: acpi: Ignore GPIO 11 interrupt on ThinkPad L13 Gen 2a The ThinkPad L13 Gen 2a firmware declares GPIO 11 as an edge-triggered interrupt in _AEI, but the EC uses the same GPIO as an output to drive the Caps Lock LED. When gpiolib registers the ACPI event, the pin is configured as an input and firmware writes can no longer control the LED. Add a DMI quirk to ignore the erroneous interrupt declaration automatically. Cc: Mark Pearson Reported-by: Nikodem Sanecki Closes: https://lore.kernel.org/linux-gpio/CAAUQFRPW-rbcZV-=qV1NMjF_358sdJTiGvQuRxRqAsehY+J9Qg@mail.gmail.com/ Signed-off-by: Mario Limonciello Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20261015193924.4081906-1-mario.limonciello@amd.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-acpi-quirks.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpio/gpiolib-acpi-quirks.c b/drivers/gpio/gpiolib-acpi-quirks.c index a0116f004975..44ac0fb6f6ad 100644 --- a/drivers/gpio/gpiolib-acpi-quirks.c +++ b/drivers/gpio/gpiolib-acpi-quirks.c @@ -356,6 +356,23 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { .ignore_interrupt = "AMDI0030:00@8", }, }, + { + /* + * ACPI incorrectly declares GPIO 11 as an interrupt in _AEI, + * although the EC uses the pin to control the Caps Lock LED. + * Requesting the interrupt configures the pin as an input and + * prevents the LED from working. + * Found in BIOS R1QET54W (1.40). + * https://lore.kernel.org/linux-gpio/CAAUQFRPW-rbcZV-=qV1NMjF_358sdJTiGvQuRxRqAsehY+J9Qg@mail.gmail.com/ + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "21AB"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_interrupt = "AMDI0030:00@11", + }, + }, { /* * Spurious wakeups from TP_ATTN# pin From c117172a46c5169b28293003a109c0cc7b7588d1 Mon Sep 17 00:00:00 2001 From: Jayaraj Devaraj Date: Fri, 16 Oct 2026 21:12:09 +0530 Subject: [PATCH 02/12] gpio: lpc32xx: check devm_gpiochip_add_data() return value lpc32xx_gpio_probe() registers each gpio chip with devm_gpiochip_add_data() but ignores the return value. If registering a chip fails, probe still returns 0, so the driver binds with a chip missing and no error is reported. Check the return value, print an error naming the failing chip and return the error code. Chips registered earlier in the loop are devm managed and are removed automatically on failure. Signed-off-by: Jayaraj Devaraj Reviewed-by: Vladimir Zapolskiy Link: https://patch.msgid.link/20261016154209.23193-1-jayarajdmit@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-lpc32xx.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 37fc54fc7385..7fb46262e18c 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -510,7 +510,7 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc, static int lpc32xx_gpio_probe(struct platform_device *pdev) { - int i; + int i, ret; void __iomem *reg_base; reg_base = devm_platform_ioremap_resource(pdev, 0); @@ -524,8 +524,11 @@ static int lpc32xx_gpio_probe(struct platform_device *pdev) lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3; lpc32xx_gpiochip[i].reg_base = reg_base; } - devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip, - &lpc32xx_gpiochip[i]); + ret = devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip, + &lpc32xx_gpiochip[i]); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to register gpio chip %d\n", i); } return 0; From 5a088d1b7266249e7701a94fc90fc829d1ad5ba1 Mon Sep 17 00:00:00 2001 From: Abduvaliy Abdulazizov Date: Wed, 7 Oct 2026 17:09:44 +0500 Subject: [PATCH 03/12] gpiolib: acpi: Ignore GPIO 11 interrupt on Acer Nitro 16S AI The Acer Nitro 16S AI (AN16S-61) has the same problem as the Acer Nitro V 16S AI: the firmware powers the internal USB camera (0408:4059) through GPIO 11 of AMDI0030, but also lists that pin in _AEI. Requesting it as an input cuts the power, so the camera never enumerates. On this model the same rail also powers the internal microphones, so they do not work either. Booting with gpiolib_acpi.ignore_interrupt=AMDI0030:00@11 fixes both the camera and the microphones. Add a DMI quirk for this family too. Tested-by: Trijan Koju Assisted-by: LLM Signed-off-by: Abduvaliy Abdulazizov Acked-by: Mika Westerberg Link: https://patch.msgid.link/20261007120944.1705014-1-abduvaliy.hbai@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-acpi-quirks.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpio/gpiolib-acpi-quirks.c b/drivers/gpio/gpiolib-acpi-quirks.c index 44ac0fb6f6ad..c1ce4700e2a4 100644 --- a/drivers/gpio/gpiolib-acpi-quirks.c +++ b/drivers/gpio/gpiolib-acpi-quirks.c @@ -343,6 +343,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { .ignore_interrupt = "AMDI0030:00@11", }, }, + { + /* + * Same camera power enable on GPIO 11 as the Acer Nitro V 16S AI + * above. It also powers the internal microphones. + * Found in BIOS V1.53 + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro 16S AI"), + }, + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { + .ignore_interrupt = "AMDI0030:00@11", + }, + }, { /* * Wakeup only works when keyboard backlight is turned off From 138d7365c20efe47b4caa92c46f086ec39b81f78 Mon Sep 17 00:00:00 2001 From: Kent Gibson Date: Fri, 16 Oct 2026 18:54:42 +0800 Subject: [PATCH 04/12] gpiolib: fix memory leak in gpiod_set_array_value_complex() EPERM error path A drive-by review by Sashiko reports that, where the line has not been configured as an output, gpiod_set_array_value_complex() can return without freeing potentially alloced bitmaps, thus leaking memory. Cleanup the bitmaps before returning. Fixes: 92ac7de3175e ("gpiolib: don't allow setting values on input lines") Reported-by: Sashiko Link: https://lore.kernel.org/linux-gpio/sashiko-outbox-168233@kernel.org/ Signed-off-by: Kent Gibson Link: https://patch.msgid.link/20261016105442.109836-1-warthog618@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c0394c7d6279..334a917e3202 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3842,7 +3842,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, unsigned long *value_bitmap) { struct gpio_chip *gc; - int i = 0, ret; + int i = 0, ret = 0; /* * Validate array_info against desc_array and its size. @@ -3920,8 +3920,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, int hwgpio = gpiod_hwgpio(desc); int value = test_bit(i, value_bitmap); - if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags))) - return -EPERM; + if (unlikely(!test_bit(GPIOD_FLAG_IS_OUT, &desc->flags))) { + ret = -EPERM; + goto cleanup_bitmap; + } /* * Pins applicable for fast input but not for @@ -3954,10 +3956,10 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, } while ((i < array_size) && gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); /* push collected bits to outputs */ - ret = 0; if (count != 0) ret = gpiochip_set_multiple(guard.gc, mask, bits); +cleanup_bitmap: if (mask != fastpath_mask) bitmap_free(mask); if (bits != fastpath_bits) From d35f61581ee67f8d4d58c325bac813cea528b6b9 Mon Sep 17 00:00:00 2001 From: Adrian Ambrozewicz Date: Mon, 12 Oct 2026 16:49:45 +0300 Subject: [PATCH 05/12] gpiolib: clear the event clock flags when a line is released gpiod_free_commit() clears the flags that a request sets on a line, but not GPIOD_FLAG_EVENT_CLOCK_REALTIME and GPIOD_FLAG_EVENT_CLOCK_HTE, which gpio_v2_line_config_flags_to_desc_flags() sets from the uAPI v2 line config. Once a line requested with GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME or GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE is released, GPIO_V2_GET_LINEINFO_IOCTL and the line info changed events, the "released" one included, keep reporting that event clock for the free line: GPIO_V2_GET_LINE_IOCTL, line 1, input, event clock realtime: ok close() GPIO_V2_GET_LINEINFO_IOCTL, line 1: input, event clock realtime The flags are set before edge detection is set up, so a request that fails in hte_ts_get(), for instance because no HTE provider handles the line, leaves GPIOD_FLAG_EVENT_CLOCK_HTE behind as well. The next uAPI v2 request rewrites both flags, but requests through uAPI v1, sysfs exports and in-kernel consumers do not, and the line info then shows the event clock of an earlier user for them too. Clear both flags together with the other flags of the request. Reproduced under QEMU with a test GPIO chip: after a released request with the realtime event clock, and on a kernel with CONFIG_HTE=y but no HTE provider after a failed request with the HTE event clock, the line info of the free line still reports that event clock. With this change it reports none. Fixes: 26d060e47e25 ("gpiolib: cdev: allow edge event timestamps to be configured as REALTIME") Fixes: 2068339a6c35 ("gpiolib: cdev: Add hardware timestamp clock type") Signed-off-by: Adrian Ambrozewicz Link: https://patch.msgid.link/20261012-gpiolib-event-clock-v1-1-aambrozewicz@nvidia.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 334a917e3202..6932278cdb9f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2679,6 +2679,8 @@ void gpiod_free_commit(struct gpio_desc *desc) 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); From 974d2712cb15014019595799b3ed68fef5fe9695 Mon Sep 17 00:00:00 2001 From: Adrian Ambrozewicz Date: Fri, 16 Oct 2026 12:22:58 +0300 Subject: [PATCH 06/12] gpiolib: cdev: don't set GPIOD_FLAG_IS_OUT When a line is requested or reconfigured through the v2 uAPI, gpio_v2_line_config_flags_to_desc_flags() copies the requested configuration into the descriptor flags, GPIOD_FLAG_IS_OUT included, before gpiod_direction_input_nonotify() or gpiod_direction_output_nonotify() asks the driver for the direction. If the driver refuses, for instance with -EOPNOTSUPP from .direction_input() for a line that can only be an output, the ioctl fails but the flag keeps the refused direction. gpiod_free_commit() does not touch GPIOD_FLAG_IS_OUT, so this outlives the failed request, and GPIO_V2_GET_LINEINFO_IOCTL reports the line as an input while the hardware still drives it, until a request without direction flags makes gpiod_request_commit() read the direction back from the driver: GPIO_V2_GET_LINE_IOCTL, line 0, input: -EOPNOTSUPP GPIO_V2_GET_LINEINFO_IOCTL, line 0: input GPIO_V2_GET_LINE_IOCTL, line 0, no direction: ok GPIO_V2_GET_LINEINFO_IOCTL, line 0: output GPIO_V2_LINE_SET_CONFIG_IOCTL updates the flags in the same order. There the line stays requested, and since commit 92ac7de3175e ("gpiolib: don't allow setting values on input lines") GPIO_V2_LINE_SET_VALUES_IOCTL on it then fails with -EPERM, though the line is still an output. A line whose driver refuses to make it an output is likewise reported as one. gpiod_direction_input_nonotify() and gpiod_direction_output_nonotify() set or clear GPIOD_FLAG_IS_OUT themselves once the driver has accepted the direction, emulated open drain and open source included, and nothing between the copy and those calls reads the flag. Leave it to them, as the v1 uAPI already does. The other flags that the helper copies stay as they are. Active low, drive and bias are what gpiod_direction_*() applies, drive and bias possibly before the driver refuses the direction; edges and event clock are the character device's own. None of them is read back from the driver, so there is no earlier state that is more accurate to go back to. A failed request releases the line, which clears them, and a failed reconfiguration leaves the line, like the lines before it, with what was applied up to the failure. Reproduced under QEMU with a test GPIO chip whose line 0 refuses input and line 1 refuses output: both refused requests and both refused reconfigurations leave the line info with the refused direction, and setting the value of the reconfigured output fails with -EPERM. With this change the line info shows the direction of the hardware in all four cases and setting the value works. First seen on real hardware with v6.12. Fixes: 3c0d9c635ae2 ("gpiolib: cdev: support GPIO_V2_GET_LINE_IOCTL and GPIO_V2_LINE_GET_VALUES_IOCTL") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Adrian Ambrozewicz Reviewed-by: Kent Gibson Link: https://patch.msgid.link/20261016-gpiolib-cdev-direction-v2-1-aambrozewicz@nvidia.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-cdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 5d53bfcdf726..f4d78113ade2 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1229,11 +1229,6 @@ static void gpio_v2_line_config_flags_to_desc_flags(u64 lflags, assign_bit(GPIOD_FLAG_ACTIVE_LOW, &flags, lflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW); - if (lflags & GPIO_V2_LINE_FLAG_OUTPUT) - set_bit(GPIOD_FLAG_IS_OUT, &flags); - else if (lflags & GPIO_V2_LINE_FLAG_INPUT) - clear_bit(GPIOD_FLAG_IS_OUT, &flags); - assign_bit(GPIOD_FLAG_EDGE_RISING, &flags, lflags & GPIO_V2_LINE_FLAG_EDGE_RISING); assign_bit(GPIOD_FLAG_EDGE_FALLING, &flags, From 8381e1f15e27087fcb6f07046a526ac8b9b9b2b9 Mon Sep 17 00:00:00 2001 From: "Baek Kyu, Kim" Date: Sun, 18 Oct 2026 13:44:56 +0900 Subject: [PATCH 07/12] gpiolib: Free chip resources when allocating the label fails If desc_set_label() fails after the chip's request callback succeeds, gpiod_request_commit() clears GPIOD_FLAG_REQUESTED without calling the free callback. The caller receives an error and has no GPIO to release, leaving resources acquired by the request callback held. Call the chip's free callback, if present, before clearing the requested bit on label allocation failure. Leave request callback errors on the existing path to avoid freeing a failed request. Cc: stable@vger.kernel.org Fixes: 1f2bcb8c8ccd ("gpio: protect the descriptor label with SRCU") Signed-off-by: Baek Kyu, Kim Link: https://patch.msgid.link/20261018044456.1259250-1-pocj8ur4in@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6932278cdb9f..1438f97d0634 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2627,10 +2627,13 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label) ret = desc_set_label(desc, label ? : "?"); if (ret) - goto out_clear_bit; + goto out_free_gpio; return 0; +out_free_gpio: + if (guard.gc->free) + guard.gc->free(guard.gc, offset); out_clear_bit: clear_bit(GPIOD_FLAG_REQUESTED, &desc->flags); return ret; From 800d7627f552bbf602a1736b638aee0ada3fbf87 Mon Sep 17 00:00:00 2001 From: Sahaj Chaudhari Date: Sun, 18 Oct 2026 22:36:22 +0530 Subject: [PATCH 08/12] gpio: davinci: Clear interrupt status in every bank on suspend davinci_gpio_save_context() saves the registers of each 32-GPIO register bank, but clears interrupt status only after the loop. At that point g refers to the last bank, so pending status in all preceding banks is left uncleared. Move the interrupt-status write into the per-bank loop so that the existing suspend-time clearing covers every register bank. Single-bank controllers retain the same behavior. Fixes: 0651a730924b ("gpio: davinci: Add support for system suspend/resume PM") Cc: stable@vger.kernel.org Signed-off-by: Sahaj Chaudhari Link: https://patch.msgid.link/20261018170622.3406158-1-sahaj123.sc@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-davinci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index cccbaea1dec2..fc2b9bef7efc 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -611,10 +611,10 @@ static void davinci_gpio_save_context(struct davinci_gpio_controller *chips, context->set_data = readl_relaxed(&g->set_data); context->set_rising = readl_relaxed(&g->set_rising); context->set_falling = readl_relaxed(&g->set_falling); - } - /* Clear all interrupt status registers */ - writel_relaxed(GENMASK(31, 0), &g->intstat); + /* Clear stale interrupt status for this bank. */ + writel_relaxed(GENMASK(31, 0), &g->intstat); + } } static void davinci_gpio_restore_context(struct davinci_gpio_controller *chips, From a38bf551726a21c9bcc001b02164f30378b64b64 Mon Sep 17 00:00:00 2001 From: Sahaj Chaudhari Date: Sun, 18 Oct 2026 21:40:42 +0530 Subject: [PATCH 09/12] gpio: pca953x: Preserve wakeup accounting on parent IRQ failure pca953x_irq_set_wake() updates wakeup_path before asking the parent IRQ controller to change its wake state. If irq_set_irq_wake() fails, the IRQ core rolls back its wake state but the driver's counter remains changed. A failed enable can therefore leave the expander marked as part of the wakeup path when no child IRQ has successfully enabled wakeup. A failed disable can make the driver stop retaining power even though wakeup is still enabled. The suspend and resume paths use this counter to decide whether to disable or enable the regulator. Update wakeup_path only after the parent operation succeeds, leaving it unchanged on error. Fixes: f70fbc15bae2 ("gpio: pca953x: Configure wake-up path when wake-up is enabled") Cc: stable@vger.kernel.org Signed-off-by: Sahaj Chaudhari Fixes: f70fbc15bae2c89f ("gpio: pca953x: Configure wake-up path when wake-up is enabled") Reviewed-by: Geert Uytterhoeven Link: https://patch.msgid.link/20261018161042.3298045-1-sahaj123.sc@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index aac9ea7520b6..869ed4264d48 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -838,13 +838,18 @@ static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); + int ret; + + ret = irq_set_irq_wake(chip->client->irq, on); + if (ret) + return ret; if (on) atomic_inc(&chip->wakeup_path); else atomic_dec(&chip->wakeup_path); - return irq_set_irq_wake(chip->client->irq, on); + return 0; } static void pca953x_irq_bus_lock(struct irq_data *d) From a0fe269293509acdd93b9cfb3f46636f7b91b33a Mon Sep 17 00:00:00 2001 From: Sahaj Chaudhari Date: Sun, 18 Oct 2026 22:20:03 +0530 Subject: [PATCH 10/12] gpio: pca953x: Handle direction register read errors in IRQ paths Three IRQ paths ignore the result of reading the direction registers and then use the destination bitmap. pca953x_read_regs() does not populate that bitmap when regmap_bulk_read() fails, leaving the callers to use uninitialized stack data. This can select incorrect GPIOs for direction changes during IRQ bus synchronization, corrupt the saved input state during IRQ setup, or produce incorrect pending interrupt decisions. Check the read result at all three sites. Release irq_lock without changing GPIO directions on failure, leave the IRQ history untouched when pending detection fails, and propagate the error from IRQ setup. The read helper already logs the error. Fixes: 0f25fda840a9 ("gpio: pca953x: Zap ad-hoc reg_direction cache") Cc: stable@vger.kernel.org Signed-off-by: Sahaj Chaudhari Link: https://patch.msgid.link/20261018165003.3372368-1-sahaj123.sc@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-pca953x.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index 869ed4264d48..afec5ec23696 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -867,6 +867,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) DECLARE_BITMAP(irq_mask, MAX_LINE); DECLARE_BITMAP(reg_direction, MAX_LINE); int level; + int ret; guard(mutex)(&chip->i2c_lock); @@ -885,7 +886,9 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) } /* Switch direction to input if needed */ - pca953x_read_regs(chip, chip->regs->direction, reg_direction); + ret = pca953x_read_regs(chip, chip->regs->direction, reg_direction); + if (ret) + goto out; bitmap_or(irq_mask, chip->irq_trig_fall, chip->irq_trig_raise, gc->ngpio); bitmap_or(irq_mask, irq_mask, chip->irq_trig_level_high, gc->ngpio); @@ -895,6 +898,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d) for_each_andnot_bit(level, irq_mask, reg_direction, gc->ngpio) pca953x_gpio_direction_input_unlocked(&chip->gpio_chip, level); +out: mutex_unlock(&chip->irq_lock); } @@ -989,7 +993,9 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin } /* Remove output pins from the equation */ - pca953x_read_regs(chip, chip->regs->direction, reg_direction); + ret = pca953x_read_regs(chip, chip->regs->direction, reg_direction); + if (ret) + return false; bitmap_copy(old_stat, chip->irq_stat, gc->ngpio); @@ -1089,7 +1095,9 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) * interrupt. We have to rely on the previous read for * this purpose. */ - pca953x_read_regs(chip, chip->regs->direction, reg_direction); + ret = pca953x_read_regs(chip, chip->regs->direction, reg_direction); + if (ret) + return ret; bitmap_and(chip->irq_stat, irq_stat, reg_direction, gc->ngpio); mutex_init(&chip->irq_lock); From 15665047024e30f9c2227563d03034061c99ac2c Mon Sep 17 00:00:00 2001 From: "Baek Kyu, Kim" Date: Wed, 21 Oct 2026 02:26:01 +0900 Subject: [PATCH 11/12] gpiolib: Propagate emulated drive errors when setting arrays gpiod_set_array_value_complex() ignores errors from the open-drain and open-source emulation helpers. If a direction change fails, GPIO_V2_LINE_SET_VALUES_IOCTL still reports success, including when updating a single line. Return the first emulation error after freeing the temporary bitmaps. Keep updates already made to earlier lines and stop processing the remaining lines, as for errors from gpiochip_set_multiple(). Fixes: 8ce258f62f90 ("gpiolib: make value setters have return values") Signed-off-by: Link: https://patch.msgid.link/20261020172601.221861-1-pocj8ur4in@gmail.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1438f97d0634..9decee5a95c7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3945,9 +3945,13 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, * open drain and open source outputs are set individually */ if (test_bit(GPIOD_FLAG_OPEN_DRAIN, &desc->flags) && !raw) { - gpio_set_open_drain_value_commit(desc, value); + ret = gpio_set_open_drain_value_commit(desc, value); + if (ret) + goto cleanup_bitmap; } else if (test_bit(GPIOD_FLAG_OPEN_SOURCE, &desc->flags) && !raw) { - gpio_set_open_source_value_commit(desc, value); + ret = gpio_set_open_source_value_commit(desc, value); + if (ret) + goto cleanup_bitmap; } else { __set_bit(hwgpio, mask); __assign_bit(hwgpio, bits, value); From dae739137441667d67fbfcc4d303a0ecc6618662 Mon Sep 17 00:00:00 2001 From: Adrian Ambrozewicz Date: Thu, 22 Oct 2026 11:33:44 +0300 Subject: [PATCH 12/12] gpiolib: don't report -ENOMEM for a requested line without a label gpiod_request_commit() sets GPIOD_FLAG_REQUESTED, calls ->request() and only then sets the label. A line in between has no label, so gpiochip_dup_line_label() passes NULL to kstrdup() and returns ERR_PTR(-ENOMEM), which for_each_hwgpio() then passes to kfree(): BUG: unable to handle page fault for address: ffcc73074355ffc8 Call Trace: gpio_sim_dbg_show gpiolib_seq_show seq_read_iter Return NULL for such a line, as for an unrequested one. Reproduced with gpio-sim: reading /sys/kernel/debug/gpio in a loop while lines are requested and released oopses within seconds; with this change, 100000 cycles pass. Fixes: 35b545332b80 ("gpio: remove gpio_lock") Cc: stable@vger.kernel.org Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20261020-gpiolib-chip-removal-v3-0-aambrozewicz@nvidia.com?part=2 Assisted-by: LLM Signed-off-by: Adrian Ambrozewicz Link: https://patch.msgid.link/20261022083343.3905973-3-aambrozewicz@nvidia.com Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9decee5a95c7..90731a547ed6 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2721,6 +2721,7 @@ void gpiod_free(struct gpio_desc *desc) char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset) { struct gpio_desc *desc; + const char *name; char *label; desc = gpiochip_get_desc(gc, offset); @@ -2732,7 +2733,11 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset) guard(srcu)(&desc->gdev->desc_srcu); - label = kstrdup(gpiod_get_label(desc), GFP_KERNEL); + name = gpiod_get_label(desc); + if (!name) + return NULL; + + label = kstrdup(name, GFP_KERNEL); if (!label) return ERR_PTR(-ENOMEM);