]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
gpio-button-hotplug: accept GPIO buttons with explicit IRQs
authorRosen Penev <rosenp@gmail.com>
Sat, 16 May 2026 22:14:50 +0000 (15:14 -0700)
committerJonas Jelonek <jelonek.jonas@gmail.com>
Mon, 25 May 2026 08:16:49 +0000 (10:16 +0200)
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 <rosenp@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/23382
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c

index 89cdeea0d93cc6b80bb762d130ed852cd3c1528f..7c4c23bfc2b3c18da68f26e4bbdcaa2e3e320874 100644 (file)
@@ -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);
+               }
        }
 }