From 0670b9ad4d9c17461ce63761b02b4b594bec8916 Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Fri, 24 Oct 2025 20:38:22 +0200 Subject: [PATCH] ACPI: fan: Add basic notification support 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 Link: https://patch.msgid.link/20251024183824.5656-2-W_Armin@gmx.de Signed-off-by: Rafael J. Wysocki --- 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 46e7fe7a506d5..9ee4ef2d6dbcd 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 @@ err: 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.47.3