]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ACPI: button: Rework device verification during probe
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 1 Jun 2026 17:03:24 +0000 (19:03 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 2 Jun 2026 19:06:35 +0000 (21:06 +0200)
Instead of manually comparing the primary ID of the device (retuned
by _HID) with each of the device IDs supported by the driver, use
acpi_match_acpi_device() (which includes the ACPI companion device
pointer check against NULL) and store the ACPI button type as
driver_data in button_device_ids[], which allows a multi-branch
conditional statement to be replaced with a switch () one.  However,
to continue preventing successful probing of devices that only have
one of the supported device IDs in their _CID lists, compare the
matched device ID with the primary ID of the device and return an
error if they don't match.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/7960518.EvYhyI6sBW@rafael.j.wysocki
[ rjw: Fixed button memory leak on probe failure ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/button.c

index 9fe8d212b606c70f02754d7162a9b3881acbdcac..00c56f840744bfef616fe4eb8586a373d40758cd 100644 (file)
@@ -59,11 +59,11 @@ MODULE_DESCRIPTION("ACPI Button Driver");
 MODULE_LICENSE("GPL");
 
 static const struct acpi_device_id button_device_ids[] = {
-       {ACPI_BUTTON_HID_LID,    0},
-       {ACPI_BUTTON_HID_SLEEP,  0},
-       {ACPI_BUTTON_HID_SLEEPF, 0},
-       {ACPI_BUTTON_HID_POWER,  0},
-       {ACPI_BUTTON_HID_POWERF, 0},
+       {ACPI_BUTTON_HID_LID, ACPI_BUTTON_TYPE_LID},
+       {ACPI_BUTTON_HID_SLEEP, ACPI_BUTTON_TYPE_SLEEP},
+       {ACPI_BUTTON_HID_SLEEPF, ACPI_BUTTON_TYPE_SLEEP},
+       {ACPI_BUTTON_HID_POWER, ACPI_BUTTON_TYPE_POWER},
+       {ACPI_BUTTON_HID_POWERF, ACPI_BUTTON_TYPE_POWER},
        {"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, button_device_ids);
@@ -542,22 +542,23 @@ static int acpi_lid_input_open(struct input_dev *input)
 static int acpi_button_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
+       struct acpi_device *device = ACPI_COMPANION(dev);
+       const struct acpi_device_id *id;
        acpi_notify_handler handler;
-       struct acpi_device *device;
        struct acpi_button *button;
        struct input_dev *input;
        acpi_status status;
        char *name, *class;
-       const char *hid;
+       u8 button_type;
        int error = 0;
 
-       device = ACPI_COMPANION(dev);
-       if (!device)
-               return -ENODEV;
+       id = acpi_match_acpi_device(button_device_ids, device);
+       if (!id || strcmp(acpi_device_hid(device), id->id))
+               return dev_err_probe(dev, -ENODEV, "Unsupported device\n");
 
-       hid = acpi_device_hid(device);
-       if (!strcmp(hid, ACPI_BUTTON_HID_LID) &&
-            lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED)
+       button_type = id->driver_data;
+       if (button_type == ACPI_BUTTON_TYPE_LID &&
+           lid_init_state == ACPI_BUTTON_LID_INIT_DISABLED)
                return -ENODEV;
 
        button = kzalloc_obj(struct acpi_button);
@@ -568,57 +569,60 @@ static int acpi_button_probe(struct platform_device *pdev)
 
        button->dev = dev;
        button->adev = device;
-       button->input = input = input_allocate_device();
+       input = input_allocate_device();
        if (!input) {
                error = -ENOMEM;
                goto err_free_button;
        }
+       button->input = input;
+       button->type = button_type;
 
        class = acpi_device_class(device);
 
-       if (!strcmp(hid, ACPI_BUTTON_HID_POWER) ||
-           !strcmp(hid, ACPI_BUTTON_HID_POWERF)) {
-               button->type = ACPI_BUTTON_TYPE_POWER;
+       switch (button_type) {
+       case ACPI_BUTTON_TYPE_LID:
+               handler = acpi_lid_notify;
+               name = ACPI_BUTTON_DEVICE_NAME_LID;
+               sprintf(class, "%s/%s",
+                       ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
+               input->open = acpi_lid_input_open;
+               break;
+
+       case ACPI_BUTTON_TYPE_POWER:
                handler = acpi_button_notify;
                name = ACPI_BUTTON_DEVICE_NAME_POWER;
                sprintf(class, "%s/%s",
                        ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER);
-       } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) ||
-                  !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) {
-               button->type = ACPI_BUTTON_TYPE_SLEEP;
+               break;
+
+       case ACPI_BUTTON_TYPE_SLEEP:
                handler = acpi_button_notify;
                name = ACPI_BUTTON_DEVICE_NAME_SLEEP;
                sprintf(class, "%s/%s",
                        ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP);
-       } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) {
-               button->type = ACPI_BUTTON_TYPE_LID;
-               handler = acpi_lid_notify;
-               name = ACPI_BUTTON_DEVICE_NAME_LID;
-               sprintf(class, "%s/%s",
-                       ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID);
-               input->open = acpi_lid_input_open;
-       } else {
-               pr_info("Unsupported hid [%s]\n", hid);
-               error = -ENODEV;
-       }
+               break;
 
-       if (!error)
-               error = acpi_button_add_fs(button);
+       default:
+               input_free_device(input);
+               error = dev_err_probe(dev, -ENODEV, "Unrecognized button type\n");
+               goto err_free_button;
+       }
 
+       error = acpi_button_add_fs(button);
        if (error) {
                input_free_device(input);
                goto err_free_button;
        }
 
-       snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
+       snprintf(button->phys, sizeof(button->phys), "%s/button/input0", id->id);
 
        input->name = name;
        input->phys = button->phys;
        input->id.bustype = BUS_HOST;
-       input->id.product = button->type;
+       input->id.product = button_type;
        input->dev.parent = dev;
 
-       switch (button->type) {
+       switch (button_type) {
        case ACPI_BUTTON_TYPE_POWER:
                input_set_capability(input, EV_KEY, KEY_POWER);
                input_set_capability(input, EV_KEY, KEY_WAKEUP);
@@ -679,7 +683,7 @@ static int acpi_button_probe(struct platform_device *pdev)
                goto err_input_unregister;
        }
 
-       if (button->type == ACPI_BUTTON_TYPE_LID) {
+       if (button_type == ACPI_BUTTON_TYPE_LID) {
                /*
                 * This assumes there's only one lid device, or if there are
                 * more we only care about the last one...