From fb1c7d7892141244c8dc7c46943a427d9fcdf435 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 16 May 2026 15:14:50 -0700 Subject: [PATCH] gpio-button-hotplug: accept GPIO buttons with explicit IRQs gpio-button-hotplug skips buttons with button->irq set because it cannot handle true interrupt-only gpio-keys descriptions. That check also skips valid GPIO-backed buttons that provide a separate interrupt specifier, such as the Meraki MX60 reset button. Try to acquire the GPIO descriptor before deciding that an explicit-IRQ button is unsupported. Continue to skip true interrupt-only buttons, and make the IRQ setup and teardown paths ignore skipped entries. Tested on: Cisco Meraki MX60. Reset button now works. Fixes: 23845fa10bc13 ("gpio-button-hotplug: do not error on interrupt attached keys") Assisted-by: Codex:GPT-5.5 Signed-off-by: Rosen Penev Link: https://github.com/openwrt/openwrt/pull/23382 Signed-off-by: Jonas Jelonek --- .../src/gpio-button-hotplug.c | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c index 89cdeea0d93..7c4c23bfc2b 100644 --- a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c +++ b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c @@ -500,13 +500,6 @@ static int gpio_keys_button_probe(struct platform_device *pdev, goto out; } - if (button->irq) { - dev_err(dev, "skipping button %s (only gpio buttons supported)\n", - button->desc); - bdata->b = &pdata->buttons[i]; - continue; - } - if (gpio_is_valid(button->gpio)) { /* legacy platform data... but is it the lookup table? */ bdata->gpiod = devm_gpiod_get_index(dev, desc, i, @@ -541,6 +534,13 @@ static int gpio_keys_button_probe(struct platform_device *pdev, if (IS_ERR_OR_NULL(bdata->gpiod)) { error = IS_ERR(bdata->gpiod) ? PTR_ERR(bdata->gpiod) : -EINVAL; + + if (button->irq && error == -ENOENT) { + dev_err(dev, "skipping button %s (only gpio buttons supported)\n", + button->desc); + continue; + } + goto out; } @@ -598,6 +598,9 @@ static int gpio_keys_probe(struct platform_device *pdev) struct gpio_keys_button_data *bdata = &bdev->data[i]; unsigned long irqflags = IRQF_ONESHOT; + if (!bdata->gpiod) + continue; + INIT_DELAYED_WORK(&bdata->work, gpio_keys_irq_work_func); if (!button->irq) { @@ -662,8 +665,10 @@ static void gpio_keys_irq_close(struct gpio_keys_button_dev *bdev) for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button_data *bdata = &bdev->data[i]; - disable_irq(bdata->irq); - cancel_delayed_work_sync(&bdata->work); + if (bdata->irq) { + disable_irq(bdata->irq); + cancel_delayed_work_sync(&bdata->work); + } } }