From f7500fc269b33549e0122bebf1c8984904d4d469 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Tue, 1 Apr 2025 09:33:20 +0800 Subject: [PATCH 1/5] hwmon: (acpi_power_meter) Fix fail to load module on platform without _PMD method mainline inclusion from mainline-v6.7-rc5 commit fabb1f813ec05975fd3428e72a62ef9f855fd3b4 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBVB4K CVE: NA Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fabb1f813ec05975fd3428e72a62ef9f855fd3b4 --------------------------------------------------------------------- According to the ACPI specification, the _PMD method is optional. The acpi_power_meter driver shouldn't fail to load if the platform has no _PMD method. Signed-off-by: Huisong Li Message-ID: <20241112021228.22914-1-lihuisong@huawei.com> [groeck: Reworded commit description] Signed-off-by: Guenter Roeck Signed-off-by: Xinghai Cen --- drivers/hwmon/acpi_power_meter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index b772c076a5ae..262e503ff17f 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -680,8 +680,9 @@ static int setup_attrs(struct acpi_power_meter_resource *resource) { int res = 0; + /* _PMD method is optional. */ res = read_domain_devices(resource); - if (res) + if (res != -ENODEV) return res; if (resource->caps.flags & POWER_METER_CAN_MEASURE) { -- Gitee From 18f55e8fad5ed50f8211c0dff361e4899ec49be0 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Tue, 1 Apr 2025 09:33:21 +0800 Subject: [PATCH 2/5] hwmon: (acpi_power_meter) Fix uninitialized variables mainline inclusion from mainline-v6.7-rc5 commit 7532e68f5d8f05353765d7585a791a14985d68b7 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBVB4K CVE: NA Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7532e68f5d8f05353765d7585a791a14985d68b7 --------------------------------------------------------------------- The 'power1_alarm' attribute uses the 'power' and 'cap' in the acpi_power_meter_resource structure. Currently, these two fields are just updated when user query 'power' and 'cap' attribute. If user directly query the 'power1_alarm' attribute without queryng above two attributes, driver will use uninitialized variables to judge. So this patch adds the setting of alarm state and update 'cap' in the notification callback and update 'power' and 'cap' if needed to show the real alarm state. Signed-off-by: Huisong Li Link: https://lore.kernel.org/r/20250109081708.27366-2-lihuisong@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Xinghai Cen --- drivers/hwmon/acpi_power_meter.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 262e503ff17f..9b54f0b87066 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -84,6 +84,7 @@ struct acpi_power_meter_resource { u64 power; u64 cap; u64 avg_interval; + bool power_alarm; int sensors_valid; unsigned long sensors_last_updated; struct sensor_device_attribute sensors[NUM_SENSORS]; @@ -396,6 +397,9 @@ static ssize_t show_val(struct device *dev, struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_power_meter_resource *resource = acpi_dev->driver_data; u64 val = 0; + int ret; + + guard(mutex)(&resource->lock); switch (attr->index) { case 0: @@ -423,10 +427,17 @@ static ssize_t show_val(struct device *dev, val = 0; break; case 6: - if (resource->power > resource->cap) - val = 1; - else - val = 0; + ret = update_meter(resource); + if (ret) + return ret; + /* need to update cap if not to support the notification. */ + if (!(resource->caps.flags & POWER_METER_CAN_NOTIFY)) { + ret = update_cap(resource); + if (ret) + return ret; + } + val = resource->power_alarm || resource->power > resource->cap; + resource->power_alarm = resource->power > resource->cap; break; case 7: case 8: @@ -848,12 +859,20 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event) sysfs_notify(&device->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"); + mutex_unlock(&resource->lock); sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME); break; case METER_NOTIFY_INTERVAL: sysfs_notify(&device->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"); break; -- Gitee From 3f1c5b4d2ed5a868c74818663356ff1263616594 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Tue, 1 Apr 2025 09:33:22 +0800 Subject: [PATCH 3/5] hwmon: (acpi_power_meter) Fix update the power trip points on failure mainline inclusion from mainline-v6.7-rc5 commit 02f1a5911550bd6b39526d18282b10d441e04ed1 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBVB4K CVE: NA Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=02f1a5911550bd6b39526d18282b10d441e04ed1 -------------------------------------------------------------------- The power trip points maintained in local should not be updated when '_PTP' method fails to evaluate. Signed-off-by: Huisong Li Link: https://lore.kernel.org/r/20250109081708.27366-3-lihuisong@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Xinghai Cen --- drivers/hwmon/acpi_power_meter.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 9b54f0b87066..8381f4405978 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -293,8 +293,8 @@ static ssize_t set_trip(struct device *dev, struct device_attribute *devattr, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct acpi_device *acpi_dev = to_acpi_device(dev); struct acpi_power_meter_resource *resource = acpi_dev->driver_data; + unsigned long temp, trip_bk; int res; - unsigned long temp; res = kstrtoul(buf, 10, &temp); if (res) @@ -302,13 +302,15 @@ static ssize_t set_trip(struct device *dev, struct device_attribute *devattr, temp = DIV_ROUND_CLOSEST(temp, 1000); - mutex_lock(&resource->lock); + guard(mutex)(&resource->lock); + + trip_bk = resource->trip[attr->index - 7]; resource->trip[attr->index - 7] = temp; res = set_acpi_trip(resource); - mutex_unlock(&resource->lock); - - if (res) + if (res) { + resource->trip[attr->index - 7] = trip_bk; return res; + } return count; } -- Gitee From b9feed5d17f0da9c4022aa20b99792b1d961dd85 Mon Sep 17 00:00:00 2001 From: Kazuhiro Abe Date: Tue, 1 Apr 2025 09:33:23 +0800 Subject: [PATCH 4/5] hwmon: (acpi_power_meter) Fix a check for the return value of read_domain_devices(). mainline inclusion from mainline-v6.7-rc5 commit 8d6bf2e1055fa2cca4bf233f46d4d1e2086cc5ff category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBVB4K CVE: NA Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8d6bf2e1055fa2cca4bf233f46d4d1e2086cc5ff --------------------------------------------------------------------- After commit fabb1f813ec0 ("hwmon: (acpi_power_meter) Fix fail to load module on platform without _PMD method"), the acpi_power_meter driver fails to load if the platform has _PMD method. To address this, add a check for successful read_domain_devices(). Tested on Nvidia Grace machine. Fixes: fabb1f813ec0 ("hwmon: (acpi_power_meter) Fix fail to load module on platform without _PMD method") Signed-off-by: Kazuhiro Abe Link: https://lore.kernel.org/r/20250115073532.3211000-1-fj1078ii@aa.jp.fujitsu.com [groeck: Dropped unnecessary () from expression] Signed-off-by: Guenter Roeck Signed-off-by: Xinghai Cen --- drivers/hwmon/acpi_power_meter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 8381f4405978..5bac41ef41fc 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -695,7 +695,7 @@ static int setup_attrs(struct acpi_power_meter_resource *resource) /* _PMD method is optional. */ res = read_domain_devices(resource); - if (res != -ENODEV) + if (res && res != -ENODEV) return res; if (resource->caps.flags & POWER_METER_CAN_MEASURE) { -- Gitee From ceb0c2b59625c14ec5bbeb4b15deb0c713c7d7c7 Mon Sep 17 00:00:00 2001 From: Huisong Li Date: Tue, 1 Apr 2025 09:33:24 +0800 Subject: [PATCH 5/5] hwmon: (acpi_power_meter) Fix the fake power alarm reporting mainline inclusion from mainline-v6.7-rc5 commit 0ea627381eb527a0ebd262c690c3992085b87ff4 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBVB4K CVE: NA Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0ea627381eb527a0ebd262c690c3992085b87ff4 --------------------------------------------------------------------- We encountered a problem that a fake power alarm is reported to user on the platform unsupported notifications at the second step below: 1> Query 'power1_alarm' attribute when the power capping occurs. 2> Query 'power1_alarm' attribute when the power capping is over and the current average power is less then power cap value. The root cause is that the resource->power_alarm is set to true at the first step. And power meter use this old value to show the power alarm state instead of the current the comparison value. Signed-off-by: Huisong Li Link: https://lore.kernel.org/r/20250220030832.2976-1-lihuisong@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Xinghai Cen --- drivers/hwmon/acpi_power_meter.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c index 5bac41ef41fc..f951bbc05a2f 100644 --- a/drivers/hwmon/acpi_power_meter.c +++ b/drivers/hwmon/acpi_power_meter.c @@ -437,9 +437,13 @@ static ssize_t show_val(struct device *dev, ret = update_cap(resource); if (ret) return ret; + resource->power_alarm = resource->power > resource->cap; + val = resource->power_alarm; + } else { + val = resource->power_alarm || + resource->power > resource->cap; + resource->power_alarm = resource->power > resource->cap; } - val = resource->power_alarm || resource->power > resource->cap; - resource->power_alarm = resource->power > resource->cap; break; case 7: case 8: -- Gitee