* [PATCH v2 1/6] ACPI: fan: Use ACPI handle when retrieving _FST
2025-10-07 23:41 [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
@ 2025-10-07 23:41 ` Armin Wolf
2025-10-07 23:41 ` [PATCH v2 2/6] ACPI: fan: Workaround for 64-bit firmware bug Armin Wolf
` (5 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Armin Wolf @ 2025-10-07 23:41 UTC (permalink / raw)
To: rafael, lenb; +Cc: linux-acpi, linux-kernel
Usage of the ACPI device should be phased out in the future, as
the driver itself is now using the platform bus. Replace any usage
of struct acpi_device in acpi_fan_get_fst() to allow users to drop
usage of struct acpi_device.
Also extend the integer check to all three package elements.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/acpi/fan.h | 3 ++-
drivers/acpi/fan_attr.c | 2 +-
drivers/acpi/fan_core.c | 34 ++++++++++++++++++++++------------
drivers/acpi/fan_hwmon.c | 3 +--
4 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h
index 8a28a72a7c6a..d39bb6fd1326 100644
--- a/drivers/acpi/fan.h
+++ b/drivers/acpi/fan.h
@@ -49,6 +49,7 @@ struct acpi_fan_fst {
};
struct acpi_fan {
+ acpi_handle handle;
bool acpi4;
bool has_fst;
struct acpi_fan_fif fif;
@@ -59,7 +60,7 @@ struct acpi_fan {
struct device_attribute fine_grain_control;
};
-int acpi_fan_get_fst(struct acpi_device *device, struct acpi_fan_fst *fst);
+int acpi_fan_get_fst(acpi_handle handle, struct acpi_fan_fst *fst);
int acpi_fan_create_attributes(struct acpi_device *device);
void acpi_fan_delete_attributes(struct acpi_device *device);
diff --git a/drivers/acpi/fan_attr.c b/drivers/acpi/fan_attr.c
index c1afb7b5ed3d..9b7fa52f3c2a 100644
--- a/drivers/acpi/fan_attr.c
+++ b/drivers/acpi/fan_attr.c
@@ -55,7 +55,7 @@ static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr,
struct acpi_fan_fst fst;
int status;
- status = acpi_fan_get_fst(acpi_dev, &fst);
+ status = acpi_fan_get_fst(acpi_dev->handle, &fst);
if (status)
return status;
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index 04ff608f2ff0..ea2c646c470c 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -44,25 +44,30 @@ static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long
return 0;
}
-int acpi_fan_get_fst(struct acpi_device *device, struct acpi_fan_fst *fst)
+int acpi_fan_get_fst(acpi_handle handle, struct acpi_fan_fst *fst)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
acpi_status status;
int ret = 0;
- status = acpi_evaluate_object(device->handle, "_FST", NULL, &buffer);
- if (ACPI_FAILURE(status)) {
- dev_err(&device->dev, "Get fan state failed\n");
- return -ENODEV;
- }
+ status = acpi_evaluate_object(handle, "_FST", NULL, &buffer);
+ if (ACPI_FAILURE(status))
+ return -EIO;
obj = buffer.pointer;
- if (!obj || obj->type != ACPI_TYPE_PACKAGE ||
- obj->package.count != 3 ||
- obj->package.elements[1].type != ACPI_TYPE_INTEGER) {
- dev_err(&device->dev, "Invalid _FST data\n");
- ret = -EINVAL;
+ if (!obj)
+ return -ENODATA;
+
+ if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 3) {
+ ret = -EPROTO;
+ goto err;
+ }
+
+ if (obj->package.elements[0].type != ACPI_TYPE_INTEGER ||
+ obj->package.elements[1].type != ACPI_TYPE_INTEGER ||
+ obj->package.elements[2].type != ACPI_TYPE_INTEGER) {
+ ret = -EPROTO;
goto err;
}
@@ -81,7 +86,7 @@ static int fan_get_state_acpi4(struct acpi_device *device, unsigned long *state)
struct acpi_fan_fst fst;
int status, i;
- status = acpi_fan_get_fst(device, &fst);
+ status = acpi_fan_get_fst(device->handle, &fst);
if (status)
return status;
@@ -311,11 +316,16 @@ static int acpi_fan_probe(struct platform_device *pdev)
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
char *name;
+ if (!device)
+ return -ENODEV;
+
fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
if (!fan) {
dev_err(&device->dev, "No memory for fan\n");
return -ENOMEM;
}
+
+ fan->handle = device->handle;
device->driver_data = fan;
platform_set_drvdata(pdev, fan);
diff --git a/drivers/acpi/fan_hwmon.c b/drivers/acpi/fan_hwmon.c
index e8d90605106e..4209a9923efc 100644
--- a/drivers/acpi/fan_hwmon.c
+++ b/drivers/acpi/fan_hwmon.c
@@ -93,13 +93,12 @@ static umode_t acpi_fan_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_
static int acpi_fan_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
int channel, long *val)
{
- struct acpi_device *adev = to_acpi_device(dev->parent);
struct acpi_fan *fan = dev_get_drvdata(dev);
struct acpi_fan_fps *fps;
struct acpi_fan_fst fst;
int ret;
- ret = acpi_fan_get_fst(adev, &fst);
+ ret = acpi_fan_get_fst(fan->handle, &fst);
if (ret < 0)
return ret;
--
2.39.5
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v2 2/6] ACPI: fan: Workaround for 64-bit firmware bug
2025-10-07 23:41 [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
2025-10-07 23:41 ` [PATCH v2 1/6] ACPI: fan: Use ACPI handle when retrieving _FST Armin Wolf
@ 2025-10-07 23:41 ` Armin Wolf
2025-10-07 23:41 ` [PATCH v2 3/6] ACPI: fan: Use platform device for devres-related actions Armin Wolf
` (4 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Armin Wolf @ 2025-10-07 23:41 UTC (permalink / raw)
To: rafael, lenb; +Cc: linux-acpi, linux-kernel
Some firmware implementations use the "Ones" ASL opcode to produce
an integer with all bits set in order to indicate missing speed or
power readings. This however only works when using 32-bit intgers,
as the ACPI spec requires a 32-bit integer (0xFFFFFFFF) to be
returned for missing speed/power readings. With 64-bit integers the
"Ones" opcode produces a 64-bit integer with all bits set, violating
the ACPI spec regarding the placeholder value for missing readings.
Work around such buggy firmware implementation by also checking for
64-bit integers with all bits set when reading _FST.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/acpi/fan.h | 33 +++++++++++++++++++++++++++++++++
drivers/acpi/fan_hwmon.c | 10 +++-------
2 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h
index d39bb6fd1326..022bc215cdbc 100644
--- a/drivers/acpi/fan.h
+++ b/drivers/acpi/fan.h
@@ -11,6 +11,7 @@
#define _ACPI_FAN_H_
#include <linux/kconfig.h>
+#include <linux/limits.h>
#define ACPI_FAN_DEVICE_IDS \
{"INT3404", }, /* Fan */ \
@@ -60,6 +61,38 @@ struct acpi_fan {
struct device_attribute fine_grain_control;
};
+/**
+ * acpi_fan_speed_valid - Check if fan speed value is valid
+ * @speeed: Speed value returned by the ACPI firmware
+ *
+ * Check if the fan speed value returned by the ACPI firmware is valid. This function is
+ * necessary as ACPI firmware implementations can return 0xFFFFFFFF to signal that the
+ * ACPI fan does not support speed reporting. Additionally, some buggy ACPI firmware
+ * implementations return a value larger than the 32-bit integer value defined by
+ * the ACPI specification when using placeholder values. Such invalid values are also
+ * detected by this function.
+ *
+ * Returns: True if the fan speed value is valid, false otherwise.
+ */
+static inline bool acpi_fan_speed_valid(u64 speed)
+{
+ return speed < U32_MAX;
+}
+
+/**
+ * acpi_fan_power_valid - Check if fan power value is valid
+ * @power: Power value returned by the ACPI firmware
+ *
+ * Check if the fan power value returned by the ACPI firmware is valid.
+ * See acpi_fan_speed_valid() for details.
+ *
+ * Returns: True if the fan power value is valid, false otherwise.
+ */
+static inline bool acpi_fan_power_valid(u64 power)
+{
+ return power < U32_MAX;
+}
+
int acpi_fan_get_fst(acpi_handle handle, struct acpi_fan_fst *fst);
int acpi_fan_create_attributes(struct acpi_device *device);
void acpi_fan_delete_attributes(struct acpi_device *device);
diff --git a/drivers/acpi/fan_hwmon.c b/drivers/acpi/fan_hwmon.c
index 4209a9923efc..5581aa6fdfa0 100644
--- a/drivers/acpi/fan_hwmon.c
+++ b/drivers/acpi/fan_hwmon.c
@@ -15,10 +15,6 @@
#include "fan.h"
-/* Returned when the ACPI fan does not support speed reporting */
-#define FAN_SPEED_UNAVAILABLE U32_MAX
-#define FAN_POWER_UNAVAILABLE U32_MAX
-
static struct acpi_fan_fps *acpi_fan_get_current_fps(struct acpi_fan *fan, u64 control)
{
unsigned int i;
@@ -77,7 +73,7 @@ static umode_t acpi_fan_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_
* when the associated attribute should not be created.
*/
for (i = 0; i < fan->fps_count; i++) {
- if (fan->fps[i].power != FAN_POWER_UNAVAILABLE)
+ if (acpi_fan_power_valid(fan->fps[i].power))
return 0444;
}
@@ -106,7 +102,7 @@ static int acpi_fan_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
case hwmon_fan:
switch (attr) {
case hwmon_fan_input:
- if (fst.speed == FAN_SPEED_UNAVAILABLE)
+ if (!acpi_fan_speed_valid(fst.speed))
return -ENODEV;
if (fst.speed > LONG_MAX)
@@ -134,7 +130,7 @@ static int acpi_fan_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
if (!fps)
return -EIO;
- if (fps->power == FAN_POWER_UNAVAILABLE)
+ if (!acpi_fan_power_valid(fps->power))
return -ENODEV;
if (fps->power > LONG_MAX / MICROWATT_PER_MILLIWATT)
--
2.39.5
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v2 3/6] ACPI: fan: Use platform device for devres-related actions
2025-10-07 23:41 [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
2025-10-07 23:41 ` [PATCH v2 1/6] ACPI: fan: Use ACPI handle when retrieving _FST Armin Wolf
2025-10-07 23:41 ` [PATCH v2 2/6] ACPI: fan: Workaround for 64-bit firmware bug Armin Wolf
@ 2025-10-07 23:41 ` Armin Wolf
2025-10-23 19:03 ` Rafael J. Wysocki
2025-10-07 23:41 ` [PATCH v2 4/6] ACPI: fan: Add basic notification support Armin Wolf
` (3 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Armin Wolf @ 2025-10-07 23:41 UTC (permalink / raw)
To: rafael, lenb; +Cc: linux-acpi, linux-kernel
Device-managed resources are cleaned up when the driver unbinds from
the underlying device. In our case this is the platform device as this
driver is a platform driver. Registering device-managed resources on
the associated ACPI device will thus result in a resource leak when
this driver unbinds.
Ensure that any device-managed resources are only registered on the
platform device to ensure that they are cleaned up during removal.
Fixes: 35c50d853adc ("ACPI: fan: Add hwmon support")
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/acpi/fan.h | 4 ++--
drivers/acpi/fan_core.c | 2 +-
drivers/acpi/fan_hwmon.c | 8 ++++----
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h
index 022bc215cdbc..0d73433c3889 100644
--- a/drivers/acpi/fan.h
+++ b/drivers/acpi/fan.h
@@ -98,9 +98,9 @@ int acpi_fan_create_attributes(struct acpi_device *device);
void acpi_fan_delete_attributes(struct acpi_device *device);
#if IS_REACHABLE(CONFIG_HWMON)
-int devm_acpi_fan_create_hwmon(struct acpi_device *device);
+int devm_acpi_fan_create_hwmon(struct device *dev);
#else
-static inline int devm_acpi_fan_create_hwmon(struct acpi_device *device) { return 0; };
+static inline int devm_acpi_fan_create_hwmon(struct device *dev) { return 0; };
#endif
#endif
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index ea2c646c470c..46e7fe7a506d 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -347,7 +347,7 @@ static int acpi_fan_probe(struct platform_device *pdev)
}
if (fan->has_fst) {
- result = devm_acpi_fan_create_hwmon(device);
+ result = devm_acpi_fan_create_hwmon(&pdev->dev);
if (result)
return result;
diff --git a/drivers/acpi/fan_hwmon.c b/drivers/acpi/fan_hwmon.c
index 5581aa6fdfa0..47a02ef5a606 100644
--- a/drivers/acpi/fan_hwmon.c
+++ b/drivers/acpi/fan_hwmon.c
@@ -162,12 +162,12 @@ static const struct hwmon_chip_info acpi_fan_hwmon_chip_info = {
.info = acpi_fan_hwmon_info,
};
-int devm_acpi_fan_create_hwmon(struct acpi_device *device)
+int devm_acpi_fan_create_hwmon(struct device *dev)
{
- struct acpi_fan *fan = acpi_driver_data(device);
+ struct acpi_fan *fan = dev_get_drvdata(dev);
struct device *hdev;
- hdev = devm_hwmon_device_register_with_info(&device->dev, "acpi_fan", fan,
- &acpi_fan_hwmon_chip_info, NULL);
+ hdev = devm_hwmon_device_register_with_info(dev, "acpi_fan", fan, &acpi_fan_hwmon_chip_info,
+ NULL);
return PTR_ERR_OR_ZERO(hdev);
}
--
2.39.5
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 3/6] ACPI: fan: Use platform device for devres-related actions
2025-10-07 23:41 ` [PATCH v2 3/6] ACPI: fan: Use platform device for devres-related actions Armin Wolf
@ 2025-10-23 19:03 ` Rafael J. Wysocki
0 siblings, 0 replies; 13+ messages in thread
From: Rafael J. Wysocki @ 2025-10-23 19:03 UTC (permalink / raw)
To: Armin Wolf; +Cc: rafael, lenb, linux-acpi, linux-kernel
On Wed, Oct 8, 2025 at 1:42 AM Armin Wolf <W_Armin@gmx.de> wrote:
>
> Device-managed resources are cleaned up when the driver unbinds from
> the underlying device. In our case this is the platform device as this
> driver is a platform driver. Registering device-managed resources on
> the associated ACPI device will thus result in a resource leak when
> this driver unbinds.
>
> Ensure that any device-managed resources are only registered on the
> platform device to ensure that they are cleaned up during removal.
>
> Fixes: 35c50d853adc ("ACPI: fan: Add hwmon support")
> Signed-off-by: Armin Wolf <W_Armin@gmx.de>
> ---
> drivers/acpi/fan.h | 4 ++--
> drivers/acpi/fan_core.c | 2 +-
> drivers/acpi/fan_hwmon.c | 8 ++++----
> 3 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h
> index 022bc215cdbc..0d73433c3889 100644
> --- a/drivers/acpi/fan.h
> +++ b/drivers/acpi/fan.h
> @@ -98,9 +98,9 @@ int acpi_fan_create_attributes(struct acpi_device *device);
> void acpi_fan_delete_attributes(struct acpi_device *device);
>
> #if IS_REACHABLE(CONFIG_HWMON)
> -int devm_acpi_fan_create_hwmon(struct acpi_device *device);
> +int devm_acpi_fan_create_hwmon(struct device *dev);
> #else
> -static inline int devm_acpi_fan_create_hwmon(struct acpi_device *device) { return 0; };
> +static inline int devm_acpi_fan_create_hwmon(struct device *dev) { return 0; };
> #endif
>
> #endif
> diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
> index ea2c646c470c..46e7fe7a506d 100644
> --- a/drivers/acpi/fan_core.c
> +++ b/drivers/acpi/fan_core.c
> @@ -347,7 +347,7 @@ static int acpi_fan_probe(struct platform_device *pdev)
> }
>
> if (fan->has_fst) {
> - result = devm_acpi_fan_create_hwmon(device);
> + result = devm_acpi_fan_create_hwmon(&pdev->dev);
> if (result)
> return result;
>
> diff --git a/drivers/acpi/fan_hwmon.c b/drivers/acpi/fan_hwmon.c
> index 5581aa6fdfa0..47a02ef5a606 100644
> --- a/drivers/acpi/fan_hwmon.c
> +++ b/drivers/acpi/fan_hwmon.c
> @@ -162,12 +162,12 @@ static const struct hwmon_chip_info acpi_fan_hwmon_chip_info = {
> .info = acpi_fan_hwmon_info,
> };
>
> -int devm_acpi_fan_create_hwmon(struct acpi_device *device)
> +int devm_acpi_fan_create_hwmon(struct device *dev)
> {
> - struct acpi_fan *fan = acpi_driver_data(device);
> + struct acpi_fan *fan = dev_get_drvdata(dev);
> struct device *hdev;
>
> - hdev = devm_hwmon_device_register_with_info(&device->dev, "acpi_fan", fan,
> - &acpi_fan_hwmon_chip_info, NULL);
> + hdev = devm_hwmon_device_register_with_info(dev, "acpi_fan", fan, &acpi_fan_hwmon_chip_info,
> + NULL);
> return PTR_ERR_OR_ZERO(hdev);
> }
> --
Applied as 6.18-rc material, thanks!
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 4/6] ACPI: fan: Add basic notification support
2025-10-07 23:41 [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
` (2 preceding siblings ...)
2025-10-07 23:41 ` [PATCH v2 3/6] ACPI: fan: Use platform device for devres-related actions Armin Wolf
@ 2025-10-07 23:41 ` Armin Wolf
2025-10-07 23:41 ` [PATCH v2 5/6] ACPI: fan: Add hwmon " Armin Wolf
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Armin Wolf @ 2025-10-07 23:41 UTC (permalink / raw)
To: rafael, lenb; +Cc: linux-acpi, linux-kernel
The ACPI specification states that the platform firmware can notify
the ACPI fan device that the fan speed has changed an that the _FST
control method should be reevaluated. Add support for this mechanism
to prepare for future changes.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/acpi/fan_core.c | 50 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index 46e7fe7a506d..9ee4ef2d6dbc 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -19,6 +19,8 @@
#include "fan.h"
+#define ACPI_FAN_NOTIFY_STATE_CHANGED 0x80
+
static const struct acpi_device_id fan_device_ids[] = {
ACPI_FAN_DEVICE_IDS,
{"", 0},
@@ -308,6 +310,50 @@ static int acpi_fan_get_fps(struct acpi_device *device)
return status;
}
+static void acpi_fan_notify_handler(acpi_handle handle, u32 event, void *context)
+{
+ struct device *dev = context;
+ struct acpi_fan_fst fst;
+ int ret;
+
+ switch (event) {
+ case ACPI_FAN_NOTIFY_STATE_CHANGED:
+ /*
+ * The ACPI specification says that we must evaluate _FST when we
+ * receive an ACPI event indicating that the fan state has changed.
+ */
+ ret = acpi_fan_get_fst(handle, &fst);
+ if (ret < 0)
+ dev_err(dev, "Error retrieving current fan status: %d\n", ret);
+
+ acpi_bus_generate_netlink_event("fan", dev_name(dev), event, 0);
+ break;
+ default:
+ dev_dbg(dev, "Unsupported ACPI notification 0x%x\n", event);
+ break;
+ }
+}
+
+static void acpi_fan_notify_remove(void *data)
+{
+ struct acpi_fan *fan = data;
+
+ acpi_remove_notify_handler(fan->handle, ACPI_DEVICE_NOTIFY, acpi_fan_notify_handler);
+}
+
+static int devm_acpi_fan_notify_init(struct device *dev)
+{
+ struct acpi_fan *fan = dev_get_drvdata(dev);
+ acpi_status status;
+
+ status = acpi_install_notify_handler(fan->handle, ACPI_DEVICE_NOTIFY,
+ acpi_fan_notify_handler, dev);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ return devm_add_action_or_reset(dev, acpi_fan_notify_remove, fan);
+}
+
static int acpi_fan_probe(struct platform_device *pdev)
{
int result = 0;
@@ -351,6 +397,10 @@ static int acpi_fan_probe(struct platform_device *pdev)
if (result)
return result;
+ result = devm_acpi_fan_notify_init(&pdev->dev);
+ if (result)
+ return result;
+
result = acpi_fan_create_attributes(device);
if (result)
return result;
--
2.39.5
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v2 5/6] ACPI: fan: Add hwmon notification support
2025-10-07 23:41 [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
` (3 preceding siblings ...)
2025-10-07 23:41 ` [PATCH v2 4/6] ACPI: fan: Add basic notification support Armin Wolf
@ 2025-10-07 23:41 ` Armin Wolf
2025-10-07 23:41 ` [PATCH v2 6/6] ACPI: fan: Add support for Microsoft fan extensions Armin Wolf
2025-10-22 21:41 ` [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
6 siblings, 0 replies; 13+ messages in thread
From: Armin Wolf @ 2025-10-07 23:41 UTC (permalink / raw)
To: rafael, lenb; +Cc: linux-acpi, linux-kernel
The platform firmware can notify the ACPI fan device that the fan
speed has changed. Relay this notification to the hwmon device if
present so that userspace applications can react to it.
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/acpi/fan.h | 5 +++++
drivers/acpi/fan_core.c | 1 +
drivers/acpi/fan_hwmon.c | 15 +++++++++++----
3 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h
index 0d73433c3889..dcc1ad3118ff 100644
--- a/drivers/acpi/fan.h
+++ b/drivers/acpi/fan.h
@@ -56,6 +56,9 @@ struct acpi_fan {
struct acpi_fan_fif fif;
struct acpi_fan_fps *fps;
int fps_count;
+#if IS_REACHABLE(CONFIG_HWMON)
+ struct device *hdev;
+#endif
struct thermal_cooling_device *cdev;
struct device_attribute fst_speed;
struct device_attribute fine_grain_control;
@@ -99,8 +102,10 @@ void acpi_fan_delete_attributes(struct acpi_device *device);
#if IS_REACHABLE(CONFIG_HWMON)
int devm_acpi_fan_create_hwmon(struct device *dev);
+void acpi_fan_notify_hwmon(struct device *dev);
#else
static inline int devm_acpi_fan_create_hwmon(struct device *dev) { return 0; };
+static inline void acpi_fan_notify_hwmon(struct device *dev) { };
#endif
#endif
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index 9ee4ef2d6dbc..7be22c52670c 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -326,6 +326,7 @@ static void acpi_fan_notify_handler(acpi_handle handle, u32 event, void *context
if (ret < 0)
dev_err(dev, "Error retrieving current fan status: %d\n", ret);
+ acpi_fan_notify_hwmon(dev);
acpi_bus_generate_netlink_event("fan", dev_name(dev), event, 0);
break;
default:
diff --git a/drivers/acpi/fan_hwmon.c b/drivers/acpi/fan_hwmon.c
index 47a02ef5a606..d3374f8f524b 100644
--- a/drivers/acpi/fan_hwmon.c
+++ b/drivers/acpi/fan_hwmon.c
@@ -162,12 +162,19 @@ static const struct hwmon_chip_info acpi_fan_hwmon_chip_info = {
.info = acpi_fan_hwmon_info,
};
+void acpi_fan_notify_hwmon(struct device *dev)
+{
+ struct acpi_fan *fan = dev_get_drvdata(dev);
+
+ hwmon_notify_event(fan->hdev, hwmon_fan, hwmon_fan_input, 0);
+}
+
int devm_acpi_fan_create_hwmon(struct device *dev)
{
struct acpi_fan *fan = dev_get_drvdata(dev);
- struct device *hdev;
- hdev = devm_hwmon_device_register_with_info(dev, "acpi_fan", fan, &acpi_fan_hwmon_chip_info,
- NULL);
- return PTR_ERR_OR_ZERO(hdev);
+ fan->hdev = devm_hwmon_device_register_with_info(dev, "acpi_fan", fan,
+ &acpi_fan_hwmon_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(fan->hdev);
}
--
2.39.5
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v2 6/6] ACPI: fan: Add support for Microsoft fan extensions
2025-10-07 23:41 [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
` (4 preceding siblings ...)
2025-10-07 23:41 ` [PATCH v2 5/6] ACPI: fan: Add hwmon " Armin Wolf
@ 2025-10-07 23:41 ` Armin Wolf
2025-10-22 21:41 ` [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
6 siblings, 0 replies; 13+ messages in thread
From: Armin Wolf @ 2025-10-07 23:41 UTC (permalink / raw)
To: rafael, lenb; +Cc: linux-acpi, linux-kernel
Microsoft has designed a set of extensions for the ACPI fan device
allowing the OS to specify a set of fan speed trip points. The
platform firmware will then notify the ACPI fan device when one
of the trip points is triggered.
Unfortunatly, some device manufacturers (like HP) blindly assume
that the OS will use said extensions and thus only update the values
returned by the _FST control method when receiving such a
notification. As a result the ACPI fan driver is currently unusable
on such machines, always reporting a constant value.
Fix this by adding support for the Microsoft extensions. During probe
and when resuming from suspend the driver will attempt to trigger an
initial notification that will update the values returned by _FST.
Said trip points will be updated each time a notification is received
from the platform firmware to ensure that the values returned by
the _FST control method are updated.
Closes: https://github.com/lm-sensors/lm-sensors/issues/506
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
---
drivers/acpi/fan.h | 2 +
drivers/acpi/fan_core.c | 169 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 169 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h
index dcc1ad3118ff..f85f9a0fbfcd 100644
--- a/drivers/acpi/fan.h
+++ b/drivers/acpi/fan.h
@@ -56,6 +56,8 @@ struct acpi_fan {
struct acpi_fan_fif fif;
struct acpi_fan_fps *fps;
int fps_count;
+ /* A value of 0 means that trippoint-related functions are not supported */
+ u32 fan_trip_granularity;
#if IS_REACHABLE(CONFIG_HWMON)
struct device *hdev;
#endif
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index 7be22c52670c..cfef767d3459 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -7,11 +7,16 @@
* Copyright (C) 2022 Intel Corporation. All rights reserved.
*/
+#include <linux/bits.h>
#include <linux/kernel.h>
+#include <linux/limits.h>
+#include <linux/math.h>
+#include <linux/math64.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/uaccess.h>
+#include <linux/uuid.h>
#include <linux/thermal.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
@@ -21,6 +26,20 @@
#define ACPI_FAN_NOTIFY_STATE_CHANGED 0x80
+static const guid_t acpi_fan_microsoft_guid = GUID_INIT(0xA7611840, 0x99FE, 0x41AE, 0xA4, 0x88,
+ 0x35, 0xC7, 0x59, 0x26, 0xC8, 0xEB);
+#define ACPI_FAN_DSM_GET_TRIP_POINT_GRANULARITY 1
+#define ACPI_FAN_DSM_SET_TRIP_POINTS 2
+#define ACPI_FAN_DSM_GET_OPERATING_RANGES 3
+
+/*
+ * Ensures that fans with a very low trip point granularity
+ * do not send too many notifications.
+ */
+static uint min_trip_distance = 100;
+module_param(min_trip_distance, uint, 0);
+MODULE_PARM_DESC(min_trip_distance, "Minimum distance between fan speed trip points in RPM");
+
static const struct acpi_device_id fan_device_ids[] = {
ACPI_FAN_DEVICE_IDS,
{"", 0},
@@ -310,6 +329,131 @@ static int acpi_fan_get_fps(struct acpi_device *device)
return status;
}
+static int acpi_fan_dsm_init(struct device *dev)
+{
+ union acpi_object dummy = {
+ .package = {
+ .type = ACPI_TYPE_PACKAGE,
+ .count = 0,
+ .elements = NULL,
+ },
+ };
+ struct acpi_fan *fan = dev_get_drvdata(dev);
+ union acpi_object *obj;
+ int ret = 0;
+
+ if (!acpi_check_dsm(fan->handle, &acpi_fan_microsoft_guid, 0,
+ BIT(ACPI_FAN_DSM_GET_TRIP_POINT_GRANULARITY) |
+ BIT(ACPI_FAN_DSM_SET_TRIP_POINTS)))
+ return 0;
+
+ dev_info(dev, "Using Microsoft fan extensions\n");
+
+ obj = acpi_evaluate_dsm_typed(fan->handle, &acpi_fan_microsoft_guid, 0,
+ ACPI_FAN_DSM_GET_TRIP_POINT_GRANULARITY, &dummy,
+ ACPI_TYPE_INTEGER);
+ if (!obj)
+ return -EIO;
+
+ if (obj->integer.value > U32_MAX)
+ ret = -EOVERFLOW;
+ else
+ fan->fan_trip_granularity = obj->integer.value;
+
+ kfree(obj);
+
+ return ret;
+}
+
+static int acpi_fan_dsm_set_trip_points(struct device *dev, u64 upper, u64 lower)
+{
+ union acpi_object args[2] = {
+ {
+ .integer = {
+ .type = ACPI_TYPE_INTEGER,
+ .value = lower,
+ },
+ },
+ {
+ .integer = {
+ .type = ACPI_TYPE_INTEGER,
+ .value = upper,
+ },
+ },
+ };
+ struct acpi_fan *fan = dev_get_drvdata(dev);
+ union acpi_object in = {
+ .package = {
+ .type = ACPI_TYPE_PACKAGE,
+ .count = ARRAY_SIZE(args),
+ .elements = args,
+ },
+ };
+ union acpi_object *obj;
+
+ obj = acpi_evaluate_dsm(fan->handle, &acpi_fan_microsoft_guid, 0,
+ ACPI_FAN_DSM_SET_TRIP_POINTS, &in);
+ kfree(obj);
+
+ return 0;
+}
+
+static int acpi_fan_dsm_start(struct device *dev)
+{
+ struct acpi_fan *fan = dev_get_drvdata(dev);
+ int ret;
+
+ if (!fan->fan_trip_granularity)
+ return 0;
+
+ /*
+ * Some firmware implementations only update the values returned by the
+ * _FST control method when a notification is received. This usually works
+ * with Microsoft Windows as setting up trip points will keep triggering
+ * said notifications, but will cause issues when using _FST without the
+ * Microsoft-specific trip point extension.
+ *
+ * Because of this we have to ensure that an initial notification is triggered
+ * to start the cycle of trip points updates. We achive this by setting the trip
+ * points sequencially to two separate ranges. As by the Microsoft specification
+ * the firmware should trigger a notification immediately if the fan speed is outside
+ * of the trip point range. This _should_ result in at least one notification as both
+ * ranges do not overlap, meaning that the current fan speed needs to be outside of
+ * at least one range.
+ */
+ ret = acpi_fan_dsm_set_trip_points(dev, fan->fan_trip_granularity, 0);
+ if (ret < 0)
+ return ret;
+
+ return acpi_fan_dsm_set_trip_points(dev, fan->fan_trip_granularity * 3,
+ fan->fan_trip_granularity * 2);
+}
+
+static int acpi_fan_dsm_update_trips_points(struct device *dev, struct acpi_fan_fst *fst)
+{
+ struct acpi_fan *fan = dev_get_drvdata(dev);
+ u64 upper, lower;
+
+ if (!fan->fan_trip_granularity)
+ return 0;
+
+ if (!acpi_fan_speed_valid(fst->speed))
+ return -EINVAL;
+
+ upper = roundup_u64(fst->speed + min_trip_distance, fan->fan_trip_granularity);
+ if (fst->speed <= min_trip_distance) {
+ lower = 0;
+ } else {
+ /*
+ * Valid fan speed values cannot be larger than 32 bit, so
+ * we can safely assume that no overflow will happen here.
+ */
+ lower = rounddown((u32)fst->speed - min_trip_distance, fan->fan_trip_granularity);
+ }
+
+ return acpi_fan_dsm_set_trip_points(dev, upper, lower);
+}
+
static void acpi_fan_notify_handler(acpi_handle handle, u32 event, void *context)
{
struct device *dev = context;
@@ -323,8 +467,13 @@ static void acpi_fan_notify_handler(acpi_handle handle, u32 event, void *context
* receive an ACPI event indicating that the fan state has changed.
*/
ret = acpi_fan_get_fst(handle, &fst);
- if (ret < 0)
+ if (ret < 0) {
dev_err(dev, "Error retrieving current fan status: %d\n", ret);
+ } else {
+ ret = acpi_fan_dsm_update_trips_points(dev, &fst);
+ if (ret < 0)
+ dev_err(dev, "Failed to update trip points: %d\n", ret);
+ }
acpi_fan_notify_hwmon(dev);
acpi_bus_generate_netlink_event("fan", dev_name(dev), event, 0);
@@ -394,6 +543,10 @@ static int acpi_fan_probe(struct platform_device *pdev)
}
if (fan->has_fst) {
+ result = acpi_fan_dsm_init(&pdev->dev);
+ if (result)
+ return result;
+
result = devm_acpi_fan_create_hwmon(&pdev->dev);
if (result)
return result;
@@ -402,6 +555,12 @@ static int acpi_fan_probe(struct platform_device *pdev)
if (result)
return result;
+ result = acpi_fan_dsm_start(&pdev->dev);
+ if (result) {
+ dev_err(&pdev->dev, "Failed to start Microsoft fan extensions\n");
+ return result;
+ }
+
result = acpi_fan_create_attributes(device);
if (result)
return result;
@@ -487,8 +646,14 @@ static int acpi_fan_suspend(struct device *dev)
static int acpi_fan_resume(struct device *dev)
{
- int result;
struct acpi_fan *fan = dev_get_drvdata(dev);
+ int result;
+
+ if (fan->has_fst) {
+ result = acpi_fan_dsm_start(dev);
+ if (result)
+ dev_err(dev, "Failed to start Microsoft fan extensions: %d\n", result);
+ }
if (fan->acpi4)
return 0;
--
2.39.5
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 0/6] ACPI fan _DSM support
2025-10-07 23:41 [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
` (5 preceding siblings ...)
2025-10-07 23:41 ` [PATCH v2 6/6] ACPI: fan: Add support for Microsoft fan extensions Armin Wolf
@ 2025-10-22 21:41 ` Armin Wolf
2025-10-23 9:59 ` Rafael J. Wysocki
6 siblings, 1 reply; 13+ messages in thread
From: Armin Wolf @ 2025-10-22 21:41 UTC (permalink / raw)
To: rafael, lenb; +Cc: linux-acpi, linux-kernel
Am 08.10.25 um 01:41 schrieb Armin Wolf:
> Microsoft has designed a _DSM interface for the ACPI fan device [1]
> that allows the OS to set fan speed trip points. The ACPI firmware
> will notify the ACPI fan device when said trip points are triggered.
>
> Unfortunately some device manufacturers (like HP) blindly assume that
> the OS will use this _DSM interface and thus only update the fan speed
> value returned by the _FST control method when sending a notification
> to the ACPI fan device. This results in stale fan speed values being
> reported by the ACPI fan driver [2].
>
> The first patch performs a simple cleanup in order to reduce the usage
> of the acpi_device struct. The second patch fixes an issue with some
> 64-bit ACPI implementations where an invalid value was reported
> instead of the standard ACPI placeholder value (0xFFFFFFFF). The third
> patch fixes an unrelated issue inside the hwmon support code while the
> next two patches add support for the ACPI fan notifications as
> specified in ACPI 11.2.3. The last patch finally adds support for the
> Microsoft _DSM interface.
>
> All patches where tested with a custom SSDT [3] and the acpi_call [4]
> kernel module and appear to work just fine.
Any thought on this? I tested it with a custom SSDT, so i can prove that
those patches work.
Thanks,
Armin Wolf
> [1] https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/design-guide
> [2] https://github.com/lm-sensors/lm-sensors/issues/506
> [3] https://github.com/Wer-Wolf/acpi-fan-ssdt/blob/master/ssdt-dsm.asl
> [4] https://github.com/nix-community/acpi_call
>
> Changes since v1:
> - use acpi_evaluate_dsm_typed() during _DSM initialization
> - send ACPI netlink event when after handling a ACPI notification
>
> Armin Wolf (6):
> ACPI: fan: Use ACPI handle when retrieving _FST
> ACPI: fan: Workaround for 64-bit firmware bug
> ACPI: fan: Use platform device for devres-related actions
> ACPI: fan: Add basic notification support
> ACPI: fan: Add hwmon notification support
> ACPI: fan: Add support for Microsoft fan extensions
>
> drivers/acpi/fan.h | 47 +++++++-
> drivers/acpi/fan_attr.c | 2 +-
> drivers/acpi/fan_core.c | 254 ++++++++++++++++++++++++++++++++++++---
> drivers/acpi/fan_hwmon.c | 32 ++---
> 4 files changed, 302 insertions(+), 33 deletions(-)
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v2 0/6] ACPI fan _DSM support
2025-10-22 21:41 ` [PATCH v2 0/6] ACPI fan _DSM support Armin Wolf
@ 2025-10-23 9:59 ` Rafael J. Wysocki
2025-10-23 19:22 ` Rafael J. Wysocki
0 siblings, 1 reply; 13+ messages in thread
From: Rafael J. Wysocki @ 2025-10-23 9:59 UTC (permalink / raw)
To: Armin Wolf; +Cc: rafael, lenb, linux-acpi, linux-kernel
On Wed, Oct 22, 2025 at 11:41 PM Armin Wolf <W_Armin@gmx.de> wrote:
>
> Am 08.10.25 um 01:41 schrieb Armin Wolf:
>
> > Microsoft has designed a _DSM interface for the ACPI fan device [1]
> > that allows the OS to set fan speed trip points. The ACPI firmware
> > will notify the ACPI fan device when said trip points are triggered.
> >
> > Unfortunately some device manufacturers (like HP) blindly assume that
> > the OS will use this _DSM interface and thus only update the fan speed
> > value returned by the _FST control method when sending a notification
> > to the ACPI fan device. This results in stale fan speed values being
> > reported by the ACPI fan driver [2].
> >
> > The first patch performs a simple cleanup in order to reduce the usage
> > of the acpi_device struct. The second patch fixes an issue with some
> > 64-bit ACPI implementations where an invalid value was reported
> > instead of the standard ACPI placeholder value (0xFFFFFFFF). The third
> > patch fixes an unrelated issue inside the hwmon support code while the
> > next two patches add support for the ACPI fan notifications as
> > specified in ACPI 11.2.3. The last patch finally adds support for the
> > Microsoft _DSM interface.
> >
> > All patches where tested with a custom SSDT [3] and the acpi_call [4]
> > kernel module and appear to work just fine.
>
> Any thought on this?
Not yet, but I'm going to get to it today.
> I tested it with a custom SSDT, so i can prove that those patches work.
OK
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 0/6] ACPI fan _DSM support
2025-10-23 9:59 ` Rafael J. Wysocki
@ 2025-10-23 19:22 ` Rafael J. Wysocki
2025-10-23 20:13 ` Armin Wolf
0 siblings, 1 reply; 13+ messages in thread
From: Rafael J. Wysocki @ 2025-10-23 19:22 UTC (permalink / raw)
To: Armin Wolf; +Cc: lenb, linux-acpi, linux-kernel
On Thu, Oct 23, 2025 at 11:59 AM Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Wed, Oct 22, 2025 at 11:41 PM Armin Wolf <W_Armin@gmx.de> wrote:
> >
> > Am 08.10.25 um 01:41 schrieb Armin Wolf:
> >
> > > Microsoft has designed a _DSM interface for the ACPI fan device [1]
> > > that allows the OS to set fan speed trip points. The ACPI firmware
> > > will notify the ACPI fan device when said trip points are triggered.
> > >
> > > Unfortunately some device manufacturers (like HP) blindly assume that
> > > the OS will use this _DSM interface and thus only update the fan speed
> > > value returned by the _FST control method when sending a notification
> > > to the ACPI fan device. This results in stale fan speed values being
> > > reported by the ACPI fan driver [2].
> > >
> > > The first patch performs a simple cleanup in order to reduce the usage
> > > of the acpi_device struct. The second patch fixes an issue with some
> > > 64-bit ACPI implementations where an invalid value was reported
> > > instead of the standard ACPI placeholder value (0xFFFFFFFF). The third
> > > patch fixes an unrelated issue inside the hwmon support code while the
> > > next two patches add support for the ACPI fan notifications as
> > > specified in ACPI 11.2.3. The last patch finally adds support for the
> > > Microsoft _DSM interface.
> > >
> > > All patches where tested with a custom SSDT [3] and the acpi_call [4]
> > > kernel module and appear to work just fine.
> >
> > Any thought on this?
>
> Not yet, but I'm going to get to it today.
>
> > I tested it with a custom SSDT, so i can prove that those patches work.
>
> OK
I've applied two first patches for 6.19 and the third one for 6.18-rc, as a fix.
My understanding is that patches [4-5/6] are preparations for the last
one that needs a pointer to the MSFT documentation it is based on.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 0/6] ACPI fan _DSM support
2025-10-23 19:22 ` Rafael J. Wysocki
@ 2025-10-23 20:13 ` Armin Wolf
2025-10-24 8:35 ` Rafael J. Wysocki
0 siblings, 1 reply; 13+ messages in thread
From: Armin Wolf @ 2025-10-23 20:13 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: lenb, linux-acpi, linux-kernel
Am 23.10.25 um 21:22 schrieb Rafael J. Wysocki:
> On Thu, Oct 23, 2025 at 11:59 AM Rafael J. Wysocki <rafael@kernel.org> wrote:
>> On Wed, Oct 22, 2025 at 11:41 PM Armin Wolf <W_Armin@gmx.de> wrote:
>>> Am 08.10.25 um 01:41 schrieb Armin Wolf:
>>>
>>>> Microsoft has designed a _DSM interface for the ACPI fan device [1]
>>>> that allows the OS to set fan speed trip points. The ACPI firmware
>>>> will notify the ACPI fan device when said trip points are triggered.
>>>>
>>>> Unfortunately some device manufacturers (like HP) blindly assume that
>>>> the OS will use this _DSM interface and thus only update the fan speed
>>>> value returned by the _FST control method when sending a notification
>>>> to the ACPI fan device. This results in stale fan speed values being
>>>> reported by the ACPI fan driver [2].
>>>>
>>>> The first patch performs a simple cleanup in order to reduce the usage
>>>> of the acpi_device struct. The second patch fixes an issue with some
>>>> 64-bit ACPI implementations where an invalid value was reported
>>>> instead of the standard ACPI placeholder value (0xFFFFFFFF). The third
>>>> patch fixes an unrelated issue inside the hwmon support code while the
>>>> next two patches add support for the ACPI fan notifications as
>>>> specified in ACPI 11.2.3. The last patch finally adds support for the
>>>> Microsoft _DSM interface.
>>>>
>>>> All patches where tested with a custom SSDT [3] and the acpi_call [4]
>>>> kernel module and appear to work just fine.
>>> Any thought on this?
>> Not yet, but I'm going to get to it today.
>>
>>> I tested it with a custom SSDT, so i can prove that those patches work.
>> OK
> I've applied two first patches for 6.19 and the third one for 6.18-rc, as a fix.
Please note that the third patch depends on the first patch! Otherwise you will
get a runtime error when acpi_fan_hwmon_read() tries to cast the platform device
to a ACPI device.
> My understanding is that patches [4-5/6] are preparations for the last
> one that needs a pointer to the MSFT documentation it is based on.
I understand, i will send a v3 series without the first three patch and this
issue being addressed.
Thanks,
Armin Wolf
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 0/6] ACPI fan _DSM support
2025-10-23 20:13 ` Armin Wolf
@ 2025-10-24 8:35 ` Rafael J. Wysocki
0 siblings, 0 replies; 13+ messages in thread
From: Rafael J. Wysocki @ 2025-10-24 8:35 UTC (permalink / raw)
To: Armin Wolf; +Cc: Rafael J. Wysocki, lenb, linux-acpi, linux-kernel
On Thu, Oct 23, 2025 at 10:13 PM Armin Wolf <W_Armin@gmx.de> wrote:
>
> Am 23.10.25 um 21:22 schrieb Rafael J. Wysocki:
>
> > On Thu, Oct 23, 2025 at 11:59 AM Rafael J. Wysocki <rafael@kernel.org> wrote:
> >> On Wed, Oct 22, 2025 at 11:41 PM Armin Wolf <W_Armin@gmx.de> wrote:
> >>> Am 08.10.25 um 01:41 schrieb Armin Wolf:
> >>>
> >>>> Microsoft has designed a _DSM interface for the ACPI fan device [1]
> >>>> that allows the OS to set fan speed trip points. The ACPI firmware
> >>>> will notify the ACPI fan device when said trip points are triggered.
> >>>>
> >>>> Unfortunately some device manufacturers (like HP) blindly assume that
> >>>> the OS will use this _DSM interface and thus only update the fan speed
> >>>> value returned by the _FST control method when sending a notification
> >>>> to the ACPI fan device. This results in stale fan speed values being
> >>>> reported by the ACPI fan driver [2].
> >>>>
> >>>> The first patch performs a simple cleanup in order to reduce the usage
> >>>> of the acpi_device struct. The second patch fixes an issue with some
> >>>> 64-bit ACPI implementations where an invalid value was reported
> >>>> instead of the standard ACPI placeholder value (0xFFFFFFFF). The third
> >>>> patch fixes an unrelated issue inside the hwmon support code while the
> >>>> next two patches add support for the ACPI fan notifications as
> >>>> specified in ACPI 11.2.3. The last patch finally adds support for the
> >>>> Microsoft _DSM interface.
> >>>>
> >>>> All patches where tested with a custom SSDT [3] and the acpi_call [4]
> >>>> kernel module and appear to work just fine.
> >>> Any thought on this?
> >> Not yet, but I'm going to get to it today.
> >>
> >>> I tested it with a custom SSDT, so i can prove that those patches work.
> >> OK
> > I've applied two first patches for 6.19 and the third one for 6.18-rc, as a fix.
>
> Please note that the third patch depends on the first patch! Otherwise you will
> get a runtime error when acpi_fan_hwmon_read() tries to cast the platform device
> to a ACPI device.
Ah, good to know, I've missed that dependency, thanks for pointing it out.
> > My understanding is that patches [4-5/6] are preparations for the last
> > one that needs a pointer to the MSFT documentation it is based on.
>
> I understand, i will send a v3 series without the first three patch and this
> issue being addressed.
Thanks!
^ permalink raw reply [flat|nested] 13+ messages in thread