]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ACPI: scan: Register platform devices for fixed event buttons
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 15 Dec 2025 13:52:45 +0000 (14:52 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 26 Dec 2025 14:08:56 +0000 (15:08 +0100)
On platforms using ACPI, power and sleep buttons may be so called "fixed
event devices" in which case they are hooked up directly to the Fixed
Events register in the platform via dedicated lines and there are no
corresponding device objects in the ACPI namespace.  Nevertheless, in
Linux they get corresponding struct acpi_device objects with special
device IDs, either LNXPWRBN or LNXSLPBN, which are then used for driver
binding in a ususal way.

However, the function creating those struct acpi_device objects for
"fixed event device" buttons, acpi_bus_scan_fixed(), does not register
platform devices for them, unlike the generic code handling device
enumeration based on the ACPI namespace.  Consequently, if an ACPI power
or sleep button is represented by a device object in the ACPI namespace,
it will get a corresponding platform device, but if it is a "fixed event
device", it will not get one, which is inconsistent and prevents the
ACPI power button driver from being converted into a platform driver.

For the sake of consistency and to allow the ACPI power button driver to
become a platform one going forward, modify acpi_bus_scan_fixed() to
register platform devices for "fixed event device" buttons and update
ACPI platform device registration code to work with non-device ACPI
object types, so it can handle the buttons in question.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/3731144.R56niFO833@rafael.j.wysocki
drivers/acpi/acpi_platform.c
drivers/acpi/scan.c

index 48d15dd785f6eb9fccc13054969f3b7c05cfc694..52c8d602f3a5743d2a8cd0bee50c67064f236773 100644 (file)
@@ -114,10 +114,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
        struct platform_device *pdev = NULL;
        struct platform_device_info pdevinfo;
        const struct acpi_device_id *match;
-       struct resource_entry *rentry;
-       struct list_head resource_list;
        struct resource *resources = NULL;
-       int count;
+       int count = 0;
 
        /* If the ACPI node already has a physical device attached, skip it. */
        if (adev->physical_node_count)
@@ -137,22 +135,28 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
                }
        }
 
-       INIT_LIST_HEAD(&resource_list);
-       count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
-       if (count < 0)
-               return NULL;
-       if (count > 0) {
-               resources = kcalloc(count, sizeof(*resources), GFP_KERNEL);
-               if (!resources) {
+       if (adev->device_type == ACPI_BUS_TYPE_DEVICE) {
+               struct list_head resource_list = LIST_HEAD_INIT(resource_list);
+
+               count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+               if (count < 0)
+                       return ERR_PTR(-ENODATA);
+
+               if (count > 0) {
+                       struct resource_entry *rentry;
+
+                       resources = kcalloc(count, sizeof(*resources), GFP_KERNEL);
+                       if (!resources) {
+                               acpi_dev_free_resource_list(&resource_list);
+                               return ERR_PTR(-ENOMEM);
+                       }
+                       count = 0;
+                       list_for_each_entry(rentry, &resource_list, node)
+                               acpi_platform_fill_resource(adev, rentry->res,
+                                                           &resources[count++]);
+
                        acpi_dev_free_resource_list(&resource_list);
-                       return ERR_PTR(-ENOMEM);
                }
-               count = 0;
-               list_for_each_entry(rentry, &resource_list, node)
-                       acpi_platform_fill_resource(adev, rentry->res,
-                                                   &resources[count++]);
-
-               acpi_dev_free_resource_list(&resource_list);
        }
 
        memset(&pdevinfo, 0, sizeof(pdevinfo));
index 8a895d377e213e7a44fdabc266c67d38739a31cd..da4da565f257449b4d31787a033979b8b9d61ffc 100644 (file)
@@ -2772,6 +2772,8 @@ static void acpi_bus_scan_fixed(void)
                                device_init_wakeup(&adev->dev, true);
                        else
                                dev_dbg(&adev->dev, "No driver\n");
+
+                       acpi_default_enumeration(adev);
                }
        }
 
@@ -2784,6 +2786,8 @@ static void acpi_bus_scan_fixed(void)
                        adev->flags.match_driver = true;
                        if (device_attach(&adev->dev) < 0)
                                dev_dbg(&adev->dev, "No driver\n");
+
+                       acpi_default_enumeration(adev);
                }
        }
 }