]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ACPI: video: Switch over to auxiliary bus type
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 9 Mar 2026 20:54:17 +0000 (21:54 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 10 Mar 2026 14:08:21 +0000 (15:08 +0100)
Commit 02c057ddefef ("ACPI: video: Convert the driver to a platform one")
switched over the ACPI video bus driver from an ACPI driver to a platform
driver, but that change introduced an unwanted and unexpected side effect.
Namely, on some systems, the ACPI device object of the ACPI video bus
device is an ACPI companion of multiple platform devices and, after
adding video_device_ids[] as an acpi_match_table to the acpi_video_bus
platform driver, all of those devices started to match that driver and
its probe callback is invoked for all of them (it fails, but it leaves
a confusing message in the log).  Moreover, the MODULE_DEVICE_TABLE()
of the ACPI video driver module matches all of the devices sharing the
ACPI companion with the ACPI video bus device.

To address this, make the core ACPI device enumeration code create an
auxiliary device for the ACPI video bus device object instead of a
platform device and switch over the ACPI video bus driver (once more)
to an auxiliary driver.

Auxiliary driver generally is a better match for ACPI video bus than
platform driver, among other things because the ACPI video bus device
does not require any resources to be allocated for it during
enumeration.  It also allows the ACPI video bus driver to stop abusing
device matching based on ACPI device IDs and it allows a special case
to be dropped from acpi_create_platform_device() because that function
need not worry about the ACPI video bus device any more.

Fixes: 02c057ddefef ("ACPI: video: Convert the driver to a platform one")
Reported-by: Pratap Nirujogi <pratap.nirujogi@amd.com>
Closes: https://lore.kernel.org/linux-acpi/007e3390-6b2b-457e-83c7-c794c5952018@amd.com/
Tested-by: Pratap Nirujogi <pratap.nirujogi@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
[ rjw: Added AUXILIARY_BUS selection to CONFIG_ACPI to fix build issue ]
[ rjw: Fixed error path in acpi_create_video_bus_device() ]
Link: https://patch.msgid.link/5986516.DvuYhMxLoT@rafael.j.wysocki
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/Kconfig
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_video.c
drivers/acpi/scan.c

index df0ff0764d0d52425d1f09b7370ab951af549913..6f4b545f7377ed5d62d15487b64fbe7ae4d30a72 100644 (file)
@@ -9,6 +9,7 @@ config ARCH_SUPPORTS_ACPI
 menuconfig ACPI
        bool "ACPI (Advanced Configuration and Power Interface) Support"
        depends on ARCH_SUPPORTS_ACPI
+       select AUXILIARY_BUS
        select PNP
        select NLS
        select CRC32
index 64199b19ceff6f32534dd2a21bf30623e7f00d7a..a09636a4168ec5e2f66a1e6ec11b708f420211c0 100644 (file)
@@ -135,7 +135,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
                }
        }
 
-       if (adev->device_type == ACPI_BUS_TYPE_DEVICE && !adev->pnp.type.backlight) {
+       if (adev->device_type == ACPI_BUS_TYPE_DEVICE) {
                LIST_HEAD(resource_list);
 
                count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
index 3fa28f1abca38cbd740fed61064e989bc98c7c70..adbaf0226c905905927c42e352f6e5403e0781b3 100644 (file)
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt) "ACPI: video: " fmt
 
+#include <linux/auxiliary_bus.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -21,7 +22,6 @@
 #include <linux/sort.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dmi.h>
 #include <linux/suspend.h>
@@ -77,8 +77,9 @@ static int register_count;
 static DEFINE_MUTEX(register_count_mutex);
 static DEFINE_MUTEX(video_list_lock);
 static LIST_HEAD(video_bus_head);
-static int acpi_video_bus_probe(struct platform_device *pdev);
-static void acpi_video_bus_remove(struct platform_device *pdev);
+static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
+                               const struct auxiliary_device_id *id);
+static void acpi_video_bus_remove(struct auxiliary_device *aux);
 static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data);
 
 /*
@@ -93,19 +94,16 @@ enum acpi_video_level_idx {
        ACPI_VIDEO_FIRST_LEVEL,         /* actual supported levels begin here */
 };
 
-static const struct acpi_device_id video_device_ids[] = {
-       {ACPI_VIDEO_HID, 0},
-       {"", 0},
+static const struct auxiliary_device_id video_bus_auxiliary_id_table[] = {
+       { .name = "acpi.video_bus" },
+       {},
 };
-MODULE_DEVICE_TABLE(acpi, video_device_ids);
+MODULE_DEVICE_TABLE(auxiliary, video_bus_auxiliary_id_table);
 
-static struct platform_driver acpi_video_bus = {
+static struct auxiliary_driver acpi_video_bus = {
        .probe = acpi_video_bus_probe,
        .remove = acpi_video_bus_remove,
-       .driver = {
-               .name = "acpi-video",
-               .acpi_match_table = video_device_ids,
-       },
+       .id_table = video_bus_auxiliary_id_table,
 };
 
 struct acpi_video_bus_flags {
@@ -1885,7 +1883,7 @@ static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device)
 }
 
 static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video,
-                                            struct platform_device *pdev)
+                                            struct device *parent)
 {
        struct input_dev *input;
        struct acpi_video_device *dev;
@@ -1908,7 +1906,7 @@ static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video,
        input->phys = video->phys;
        input->id.bustype = BUS_HOST;
        input->id.product = 0x06;
-       input->dev.parent = &pdev->dev;
+       input->dev.parent = parent;
        input->evbit[0] = BIT(EV_KEY);
        set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
        set_bit(KEY_VIDEO_NEXT, input->keybit);
@@ -1980,9 +1978,10 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
 
 static int instance;
 
-static int acpi_video_bus_probe(struct platform_device *pdev)
+static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
+                               const struct auxiliary_device_id *id_unused)
 {
-       struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+       struct acpi_device *device = ACPI_COMPANION(&aux_dev->dev);
        struct acpi_video_bus *video;
        bool auto_detect;
        int error;
@@ -2019,7 +2018,7 @@ static int acpi_video_bus_probe(struct platform_device *pdev)
                instance++;
        }
 
-       platform_set_drvdata(pdev, video);
+       auxiliary_set_drvdata(aux_dev, video);
 
        video->device = device;
        strscpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
@@ -2068,7 +2067,7 @@ static int acpi_video_bus_probe(struct platform_device *pdev)
            !auto_detect)
                acpi_video_bus_register_backlight(video);
 
-       error = acpi_video_bus_add_notify_handler(video, pdev);
+       error = acpi_video_bus_add_notify_handler(video, &aux_dev->dev);
        if (error)
                goto err_del;
 
@@ -2096,10 +2095,10 @@ err_free_video:
        return error;
 }
 
-static void acpi_video_bus_remove(struct platform_device *pdev)
+static void acpi_video_bus_remove(struct auxiliary_device *aux_dev)
 {
-       struct acpi_video_bus *video = platform_get_drvdata(pdev);
-       struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
+       struct acpi_video_bus *video = auxiliary_get_drvdata(aux_dev);
+       struct acpi_device *device = ACPI_COMPANION(&aux_dev->dev);
 
        acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
                                       acpi_video_bus_notify);
@@ -2163,7 +2162,7 @@ int acpi_video_register(void)
 
        dmi_check_system(video_dmi_table);
 
-       ret = platform_driver_register(&acpi_video_bus);
+       ret = auxiliary_driver_register(&acpi_video_bus);
        if (ret)
                goto leave;
 
@@ -2183,7 +2182,7 @@ void acpi_video_unregister(void)
 {
        mutex_lock(&register_count_mutex);
        if (register_count) {
-               platform_driver_unregister(&acpi_video_bus);
+               auxiliary_driver_unregister(&acpi_video_bus);
                register_count = 0;
                may_report_brightness_keys = false;
        }
index dfdd004fb1a9ccd1deead51120d196932019c4cc..e8cdbdb46fdb46e989ff2f6045904e456c219f8d 100644 (file)
@@ -6,6 +6,7 @@
 #define pr_fmt(fmt) "ACPI: " fmt
 
 #include <linux/async.h>
+#include <linux/auxiliary_bus.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -2192,6 +2193,44 @@ static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used,
        return acpi_bus_check_add(handle, false, (struct acpi_device **)ret_p);
 }
 
+static void acpi_video_bus_device_release(struct device *dev)
+{
+       struct auxiliary_device *aux_dev = to_auxiliary_dev(dev);
+
+       kfree(aux_dev);
+}
+
+static void acpi_create_video_bus_device(struct acpi_device *adev,
+                                        struct acpi_device *parent)
+{
+       struct auxiliary_device *aux_dev;
+       static unsigned int aux_dev_id;
+
+       aux_dev = kzalloc_obj(*aux_dev);
+       if (!aux_dev)
+               return;
+
+       aux_dev->id = aux_dev_id++;
+       aux_dev->name = "video_bus";
+       aux_dev->dev.parent = acpi_get_first_physical_node(parent);
+       if (!aux_dev->dev.parent)
+               goto err;
+
+       aux_dev->dev.release = acpi_video_bus_device_release;
+
+       if (auxiliary_device_init(aux_dev))
+               goto err;
+
+       ACPI_COMPANION_SET(&aux_dev->dev, adev);
+       if (__auxiliary_device_add(aux_dev, "acpi"))
+               auxiliary_device_uninit(aux_dev);
+
+       return;
+
+err:
+       kfree(aux_dev);
+}
+
 struct acpi_scan_system_dev {
        struct list_head node;
        struct acpi_device *adev;
@@ -2229,6 +2268,12 @@ static void acpi_default_enumeration(struct acpi_device *device)
                        sd->adev = device;
                        list_add_tail(&sd->node, &acpi_scan_system_dev_list);
                }
+       } else if (device->pnp.type.backlight) {
+               struct acpi_device *parent;
+
+               parent = acpi_dev_parent(device);
+               if (parent)
+                       acpi_create_video_bus_device(device, parent);
        } else {
                /* For a regular device object, create a platform device. */
                acpi_create_platform_device(device, NULL);