Skip to content

Commit 0670b9a

Browse files
Wer-Wolfrafaeljw
authored andcommitted
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 <W_Armin@gmx.de> Link: https://patch.msgid.link/20251024183824.5656-2-W_Armin@gmx.de Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 2e00f7a commit 0670b9a

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

drivers/acpi/fan_core.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include "fan.h"
2121

22+
#define ACPI_FAN_NOTIFY_STATE_CHANGED 0x80
23+
2224
static const struct acpi_device_id fan_device_ids[] = {
2325
ACPI_FAN_DEVICE_IDS,
2426
{"", 0},
@@ -308,6 +310,50 @@ static int acpi_fan_get_fps(struct acpi_device *device)
308310
return status;
309311
}
310312

313+
static void acpi_fan_notify_handler(acpi_handle handle, u32 event, void *context)
314+
{
315+
struct device *dev = context;
316+
struct acpi_fan_fst fst;
317+
int ret;
318+
319+
switch (event) {
320+
case ACPI_FAN_NOTIFY_STATE_CHANGED:
321+
/*
322+
* The ACPI specification says that we must evaluate _FST when we
323+
* receive an ACPI event indicating that the fan state has changed.
324+
*/
325+
ret = acpi_fan_get_fst(handle, &fst);
326+
if (ret < 0)
327+
dev_err(dev, "Error retrieving current fan status: %d\n", ret);
328+
329+
acpi_bus_generate_netlink_event("fan", dev_name(dev), event, 0);
330+
break;
331+
default:
332+
dev_dbg(dev, "Unsupported ACPI notification 0x%x\n", event);
333+
break;
334+
}
335+
}
336+
337+
static void acpi_fan_notify_remove(void *data)
338+
{
339+
struct acpi_fan *fan = data;
340+
341+
acpi_remove_notify_handler(fan->handle, ACPI_DEVICE_NOTIFY, acpi_fan_notify_handler);
342+
}
343+
344+
static int devm_acpi_fan_notify_init(struct device *dev)
345+
{
346+
struct acpi_fan *fan = dev_get_drvdata(dev);
347+
acpi_status status;
348+
349+
status = acpi_install_notify_handler(fan->handle, ACPI_DEVICE_NOTIFY,
350+
acpi_fan_notify_handler, dev);
351+
if (ACPI_FAILURE(status))
352+
return -EIO;
353+
354+
return devm_add_action_or_reset(dev, acpi_fan_notify_remove, fan);
355+
}
356+
311357
static int acpi_fan_probe(struct platform_device *pdev)
312358
{
313359
int result = 0;
@@ -351,6 +397,10 @@ static int acpi_fan_probe(struct platform_device *pdev)
351397
if (result)
352398
return result;
353399

400+
result = devm_acpi_fan_notify_init(&pdev->dev);
401+
if (result)
402+
return result;
403+
354404
result = acpi_fan_create_attributes(device);
355405
if (result)
356406
return result;

0 commit comments

Comments
 (0)