From: Armin Wolf Date: Fri, 24 Oct 2025 18:38:22 +0000 (+0200) Subject: ACPI: fan: Add basic notification support X-Git-Tag: v6.19-rc1~204^2~1^3~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0670b9ad4d9c17461ce63761b02b4b594bec8916;p=thirdparty%2Fkernel%2Flinux.git 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 --- 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;