]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
hwmon: (acpi_power_meter) Convert ACPI driver to a platform one
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sun, 1 Mar 2026 13:18:49 +0000 (14:18 +0100)
committerGuenter Roeck <linux@roeck-us.net>
Tue, 31 Mar 2026 02:45:05 +0000 (19:45 -0700)
In all cases in which a struct acpi_driver is used for binding a driver
to an ACPI device object, a corresponding platform device is created by
the ACPI core and that device is regarded as a proper representation of
underlying hardware.  Accordingly, a struct platform_driver should be
used by driver code to bind to that device.  There are multiple reasons
why drivers should not bind directly to ACPI device objects [1].

Overall, it is better to bind drivers to platform devices than to their
ACPI companions, so convert the hwmon ACPI power meter driver to a
platform one.

After this change, the subordinate hwmon device will be registered
under the platform device representing the ACPI power meter, sysfs
notifications will trigger on that device, and diagnostic messages
will be printed relative to it instead of its ACPI companion.

Link: https://lore.kernel.org/all/2396510.ElGaqSPkdT@rafael.j.wysocki/
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://lore.kernel.org/r/1952740.tdWV9SEqCh@rafael.j.wysocki
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/acpi_power_meter.c

index c010f55f7c7ba162080d2fa8837a791bb6454925..be7f702dcde9c0a427f628349d1a281ed9bee3d5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <linux/err.h>
 #include <linux/acpi.h>
+#include <linux/platform_device.h>
 
 #define ACPI_POWER_METER_NAME          "power_meter"
 #define ACPI_POWER_METER_DEVICE_NAME   "Power Meter"
@@ -816,8 +817,8 @@ end:
 /* Handle ACPI event notifications */
 static void acpi_power_meter_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_device *device = data;
-       struct acpi_power_meter_resource *resource = acpi_driver_data(device);
+       struct device *dev = data;
+       struct acpi_power_meter_resource *resource = dev_get_drvdata(dev);
        int res;
 
        guard(mutex)(&acpi_notify_lock);
@@ -833,43 +834,43 @@ static void acpi_power_meter_notify(acpi_handle handle, u32 event, void *data)
                remove_domain_devices(resource);
                res = read_capabilities(resource);
                if (res)
-                       dev_err_once(&device->dev, "read capabilities failed.\n");
+                       dev_err_once(dev, "read capabilities failed.\n");
                res = read_domain_devices(resource);
                if (res && res != -ENODEV)
-                       dev_err_once(&device->dev, "read domain devices failed.\n");
+                       dev_err_once(dev, "read domain devices failed.\n");
 
                mutex_unlock(&resource->lock);
 
                resource->hwmon_dev =
-                       hwmon_device_register_with_info(&device->dev,
+                       hwmon_device_register_with_info(dev,
                                                        ACPI_POWER_METER_NAME,
                                                        resource,
                                                        &power_meter_chip_info,
                                                        power_extra_groups);
                if (IS_ERR(resource->hwmon_dev))
-                       dev_err_once(&device->dev, "register hwmon device failed.\n");
+                       dev_err_once(dev, "register hwmon device failed.\n");
 
                break;
        case METER_NOTIFY_TRIP:
-               sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
+               sysfs_notify(&dev->kobj, NULL, POWER_AVERAGE_NAME);
                break;
        case METER_NOTIFY_CAP:
                mutex_lock(&resource->lock);
                res = update_cap(resource);
                if (res)
-                       dev_err_once(&device->dev, "update cap failed when capping value is changed.\n");
+                       dev_err_once(dev, "update cap failed when capping value is changed.\n");
                mutex_unlock(&resource->lock);
-               sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME);
+               sysfs_notify(&dev->kobj, NULL, POWER_CAP_NAME);
                break;
        case METER_NOTIFY_INTERVAL:
-               sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME);
+               sysfs_notify(&dev->kobj, NULL, POWER_AVG_INTERVAL_NAME);
                break;
        case METER_NOTIFY_CAPPING:
                mutex_lock(&resource->lock);
                resource->power_alarm = true;
                mutex_unlock(&resource->lock);
-               sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME);
-               dev_info(&device->dev, "Capping in progress.\n");
+               sysfs_notify(&dev->kobj, NULL, POWER_ALARM_NAME);
+               dev_info(dev, "Capping in progress.\n");
                break;
        default:
                WARN(1, "Unexpected event %d\n", event);
@@ -877,16 +878,15 @@ static void acpi_power_meter_notify(acpi_handle handle, u32 event, void *data)
        }
 
        acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS,
-                                       dev_name(&device->dev), event, 0);
+                                       dev_name(&resource->acpi_dev->dev),
+                                       event, 0);
 }
 
-static int acpi_power_meter_add(struct acpi_device *device)
+static int acpi_power_meter_probe(struct platform_device *pdev)
 {
-       int res;
+       struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
        struct acpi_power_meter_resource *resource;
-
-       if (!device)
-               return -EINVAL;
+       int res;
 
        resource = kzalloc_obj(*resource);
        if (!resource)
@@ -897,7 +897,8 @@ static int acpi_power_meter_add(struct acpi_device *device)
        mutex_init(&resource->lock);
        strscpy(acpi_device_name(device), ACPI_POWER_METER_DEVICE_NAME);
        strscpy(acpi_device_class(device), ACPI_POWER_METER_CLASS);
-       device->driver_data = resource;
+
+       platform_set_drvdata(pdev, resource);
 
 #if IS_REACHABLE(CONFIG_ACPI_IPMI)
        /*
@@ -910,7 +911,7 @@ static int acpi_power_meter_add(struct acpi_device *device)
                struct acpi_device *ipi_device = acpi_dev_get_first_match_dev("IPI0001", NULL, -1);
 
                if (ipi_device && acpi_wait_for_acpi_ipmi())
-                       dev_warn(&device->dev, "Waiting for ACPI IPMI timeout");
+                       dev_warn(&pdev->dev, "Waiting for ACPI IPMI timeout");
                acpi_dev_put(ipi_device);
        }
 #endif
@@ -928,7 +929,7 @@ static int acpi_power_meter_add(struct acpi_device *device)
                goto exit_free_capability;
 
        resource->hwmon_dev =
-               hwmon_device_register_with_info(&device->dev,
+               hwmon_device_register_with_info(&pdev->dev,
                                                ACPI_POWER_METER_NAME, resource,
                                                &power_meter_chip_info,
                                                power_extra_groups);
@@ -938,7 +939,7 @@ static int acpi_power_meter_add(struct acpi_device *device)
        }
 
        res = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
-                                             acpi_power_meter_notify, device);
+                                             acpi_power_meter_notify, &pdev->dev);
        if (res)
                goto exit_hwmon;
 
@@ -957,11 +958,11 @@ exit:
        return res;
 }
 
-static void acpi_power_meter_remove(struct acpi_device *device)
+static void acpi_power_meter_remove(struct platform_device *pdev)
 {
-       struct acpi_power_meter_resource *resource = acpi_driver_data(device);
+       struct acpi_power_meter_resource *resource = platform_get_drvdata(pdev);
 
-       acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
+       acpi_dev_remove_notify_handler(resource->acpi_dev, ACPI_DEVICE_NOTIFY,
                                       acpi_power_meter_notify);
 
        if (!IS_ERR(resource->hwmon_dev))
@@ -975,9 +976,7 @@ static void acpi_power_meter_remove(struct acpi_device *device)
 
 static int acpi_power_meter_resume(struct device *dev)
 {
-       struct acpi_power_meter_resource *resource;
-
-       resource = acpi_driver_data(to_acpi_device(dev));
+       struct acpi_power_meter_resource *resource = dev_get_drvdata(dev);
 
        free_capabilities(resource);
        read_capabilities(resource);
@@ -988,15 +987,14 @@ static int acpi_power_meter_resume(struct device *dev)
 static DEFINE_SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL,
                                acpi_power_meter_resume);
 
-static struct acpi_driver acpi_power_meter_driver = {
-       .name = "power_meter",
-       .class = ACPI_POWER_METER_CLASS,
-       .ids = power_meter_ids,
-       .ops = {
-               .add = acpi_power_meter_add,
-               .remove = acpi_power_meter_remove,
-               },
-       .drv.pm = pm_sleep_ptr(&acpi_power_meter_pm),
+static struct platform_driver acpi_power_meter_driver = {
+       .probe = acpi_power_meter_probe,
+       .remove = acpi_power_meter_remove,
+       .driver = {
+               .name = "acpi-power-meter",
+               .acpi_match_table = power_meter_ids,
+               .pm = &acpi_power_meter_pm,
+       },
 };
 
 /* Module init/exit routines */
@@ -1025,7 +1023,7 @@ static int __init acpi_power_meter_init(void)
 
        dmi_check_system(pm_dmi_table);
 
-       result = acpi_bus_register_driver(&acpi_power_meter_driver);
+       result = platform_driver_register(&acpi_power_meter_driver);
        if (result < 0)
                return result;
 
@@ -1034,7 +1032,7 @@ static int __init acpi_power_meter_init(void)
 
 static void __exit acpi_power_meter_exit(void)
 {
-       acpi_bus_unregister_driver(&acpi_power_meter_driver);
+       platform_driver_unregister(&acpi_power_meter_driver);
 }
 
 MODULE_AUTHOR("Darrick J. Wong <darrick.wong@oracle.com>");