Re: [PATCH v3 2/2] hwmon: acpi_power_meter: convert to hwmon_device_register_with_info

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Le Sat, May 21, 2022 at 06:52:15AM -0700, Guenter Roeck a écrit :
> On 5/16/22 05:21, Guenter Roeck wrote:
> > On 5/15/22 23:21, LABBE Corentin wrote:
> >> Le Sun, May 15, 2022 at 05:29:54PM -0700, Guenter Roeck a écrit :
> >>> On 5/15/22 12:36, LABBE Corentin wrote:
> >>>> Le Wed, May 11, 2022 at 07:10:29PM -0700, Guenter Roeck a écrit :
> >>>>> Corentin,
> >>>>>
> >>>>> On 5/8/22 23:30, Corentin Labbe wrote:
> >>>>>> Booting lead to a hwmon_device_register() is deprecated. Please convert the driver to use hwmon_device_register_with_info().
> >>>>>> So let's convert the driver to use hwmon_device_register_with_info().
> >>>>>>
> >>>>>> Signed-off-by: Corentin Labbe <clabbe@xxxxxxxxxxxx>
> >>>>>> ---
> >>>>> [ ... ]
> >>>>>
> >>>>>> @@ -836,20 +740,20 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
> >>>>>>             if (res)
> >>>>>>                 break;
> >>>>>> -        remove_attrs(resource);
> >>>>>> +        remove_domain_devices(resource);
> >>>>>>             setup_attrs(resource);
> >>>>>
> >>>>> Zhang Rui found an interesting problem with this code:
> >>>>> It needs a call to sysfs_update_groups(hwmon_dev->groups)
> >>>>> to update sysfs attribute visibility, probably between
> >>>>> remove_domain_devices() and setup_attrs().
> >>>>>
> >>>>>>             break;
> >>>>>>         case METER_NOTIFY_TRIP:
> >>>>>> -        sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
> >>>>>> +        hwmon_notify_event(&device->dev, hwmon_power, hwmon_power_average, 0);
> >>>>>
> >>>>> ... which makes realize: The notification device should be the hwmon device.
> >>>>> That would be resource->hwmon_dev, not the acpi device.
> >>>>>
> >>>>
> >>>> Hello
> >>>>
> >>>> Since my hardware lacks capabilities testing this, I have emulated it on qemu:
> >>>> https://github.com/montjoie/qemu/commit/320f2ddacb954ab308ef699f66fca6313f75bc2b
> >>>>
> >>>> I have added a custom ACPI _DBX method for triggering some ACPI state change. (like config change, like enabling CAP).
> >>>>
> >>>> For testing config change I have tried lot of way:
> >>>>                   res = read_capabilities(resource);
> >>>> @@ -742,18 +758,22 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
> >>>>                   remove_domain_devices(resource);
> >>>>                   setup_attrs(resource);
> >>>> +               res = sysfs_update_groups(&resource->hwmon_dev->kobj, acpi_power_groups);
> >>>> +               res = sysfs_update_groups(&resource->acpi_dev->dev.kobj, acpi_power_groups);
> >>>> +               res = hwmon_notify_event(resource->hwmon_dev, hwmon_power, hwmon_power_cap, 0);
> >>>> +               res = hwmon_notify_event(resource->hwmon_dev, hwmon_power, hwmon_power_average, 0);
> >>>
> >>> Did you add a debug log here ?
> >>
> >> Yes I added debug log to check what is called.
> >>
> >>>
> >>> acpi_power_groups would be the wrong parameter for sysfs_update_groups().
> >>> It would have to be resource->hwmon_dev->groups.
> >>>
> >>
> >> Even with that, no call to is_visible:
> >> @@ -742,18 +758,22 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
> >>                  remove_domain_devices(resource);
> >>                  setup_attrs(resource);
> >> +               res = sysfs_update_groups(&resource->hwmon_dev->kobj, resource->hwmon_dev->groups);
> >> +               res = sysfs_update_groups(&resource->acpi_dev->dev.kobj, resource->hwmon_dev->groups);
> >> +               res = hwmon_notify_event(resource->hwmon_dev, hwmon_power, hwmon_power_cap, 0);
> >> +               res = hwmon_notify_event(resource->hwmon_dev, hwmon_power, hwmon_power_average, 0);
> >>                  break;
> >>
> >> I checked drivers/hwmon/hwmon.c is seems that is_visible is only called by gen_attr/gen_attrs which is only called by __hwmon_create_attrs and then by registers functions.
> >> So perhaps it explain why it is never called.
> > 
> > Ah yes, you are correct. Sorry, it has been too long ago that I wrote that code.
> > Effectively that means we'll have to rework the hwmon core to generate attributes
> > anyway and leave it up to the driver core to call the is_visible function.
> > 
> 
> Attached is an outline of what would be needed in the hwmon core.
> Completely untested. I wonder if it may be easier to always
> create all attributes and have them return -ENODATA if not
> supported.
> 

With your patch, the notify config change lead to new attributes to be displayed.

Your patch just needs:
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -315,7 +315,7 @@ static void hwmon_thermal_notify(struct device *dev, int index)
 }
 
 #else
-static int hwmon_thermal_register_sensors(struct device *dev)
+static int hwmon_thermal_register_sensors(struct device *dev, bool update)
 {
        return 0;
 }

Tested with:
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -40,7 +40,7 @@
 #define METER_NOTIFY_INTERVAL  0x84
 
 static int cap_in_hardware;
-static bool force_cap_on;
+static bool force_cap_on = 1;
 
 static int can_cap_in_hardware(void)
 {
@@ -337,6 +337,16 @@ static ssize_t power1_is_battery_show(struct device *dev,
 {
        struct acpi_power_meter_resource *resource = dev_get_drvdata(dev);
        int val;
+       unsigned long long data;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(resource->acpi_dev->handle, "_DBX",
+                                      NULL, &data);
+       if (ACPI_FAILURE(status)) {
+               acpi_evaluation_failure_warn(resource->acpi_dev->handle, "_DBX",
+                                            status);
+       }
+       pr_info("DBX give %llu\n", data);
 
        if (resource->caps.flags & POWER_METER_IS_BATTERY)
                val = 1;
@@ -570,6 +580,8 @@ static umode_t acpi_power_is_visible(const void *data,
 {
        const struct acpi_power_meter_resource *resource = data;
 
+       pr_info("%s\n", __func__);
+
        switch (attr) {
        case hwmon_power_average_min:
        case hwmon_power_average_max:
@@ -741,7 +753,7 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
 
                remove_domain_devices(resource);
                setup_attrs(resource);
-               res = sysfs_update_groups(&resource->acpi_dev->dev.kobj, resource->hwmon_dev->groups);
+               res = hwmon_update_groups(resource->hwmon_dev);
                break;
        case METER_NOTIFY_TRIP:
On a microvm qemu with my ACPI power meter emulation:
/ # ls /sys/class/hwmon/hwmon0/
device		 power1_average		  power1_is_battery	subsystem
name		 power1_average_interval  power1_model_number	uevent
power		 power1_interval_max	  power1_oem_info
power1_accuracy  power1_interval_min	  power1_serial_number
/ # cat /sys/class/hwmon/hwmon0/
device/                  power1_average_interval  power1_oem_info
name                     power1_interval_max      power1_serial_number
power/                   power1_interval_min      subsystem/
power1_accuracy          power1_is_battery        uevent
power1_average           power1_model_number
/ # cat /sys/class/hwmon/hwmon0/power1_is_battery 
[   14.969697] power_meter ACPI000D:00: Found ACPI power meter.
[   14.970114] acpi_power_is_visible
[   14.970133] acpi_power_is_visible
[   14.970141] acpi_power_is_visible
[   14.970147] acpi_power_is_visible
[   14.970153] acpi_power_is_visible
[   14.970158] acpi_power_is_visible
[   14.970164] acpi_power_is_visible
[   14.970169] acpi_power_is_visible
[   14.970187] acpi_power_is_visible
[   14.970193] acpi_power_is_visible
[   14.970202] acpi_power_is_visible
[   14.970346] DBX give 40
[   14.975185] power_meter ACPI000D:00: Capping in progress.
0
cat: /sys/class/hwmon/hwmon0/power1_is_battery: No such device
/ # ls /sys/class/hwmon/hwmon0/
device			 power1_average_min   power1_is_battery
name			 power1_cap	      power1_model_number
power			 power1_cap_hyst      power1_oem_info
power1_accuracy		 power1_cap_max       power1_serial_number
power1_average		 power1_cap_min       subsystem
power1_average_interval  power1_interval_max  uevent
power1_average_max	 power1_interval_min

Thanks



[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux