[linux-6.18.y] [Lenovo] [Fromlist] hwmon: (yogafan) Add support for Lenovo Yoga/Legion fan monitoring#1617
Conversation
Reviewer's GuideAdds a new hwmon driver (yogafan) to expose Lenovo Yoga/Legion/IdeaPad EC fan speeds via ACPI, including a custom rate-limited lag filter and DMI-based quirks, and wires it into the hwmon subsystem, Kconfig, Makefile, MAINTAINERS, and documentation. Sequence diagram for yoga_fan module init and probesequenceDiagram
participant Kernel
participant DMI as DMI_table
participant Platform as platform_core
participant Driver as yoga_fan_driver
participant Dev as yoga_fan_device
Kernel->>Driver: module_init yoga_fan_init()
Driver->>DMI: dmi_check_system(yogafan_quirks)
DMI-->>Driver: match or no match
alt no DMI match
Driver-->>Kernel: return -ENODEV
else DMI match
Driver->>Platform: platform_driver_register(yoga_fan_driver)
Platform-->>Driver: registration result
Driver->>Platform: platform_device_register_simple(DRVNAME)
Platform-->>Dev: create platform_device
Dev-->>Driver: yoga_fan_probe(pdev)
Driver->>DMI: dmi_first_match(yogafan_quirks)
DMI-->>Driver: yogafan_config
Driver->>Driver: devm_kzalloc(yoga_fan_data)
loop for each cfg.paths[i]
Driver->>ACPI: acpi_get_handle(path[i])
ACPI-->>Driver: handle or failure
alt ACPI_SUCCESS
Driver->>Driver: store handle, increment fan_count
end
end
alt fan_count == 0
Driver-->>Platform: return -ENODEV
else
Driver->>hwmon: devm_hwmon_device_register_with_info(DRVNAME, yoga_fan_chip_info)
hwmon-->>Driver: hwmon_dev or error
Driver-->>Platform: PTR_ERR_OR_ZERO(hwmon_dev)
end
end
Kernel-->>Driver: module registered
Sequence diagram for yoga_fan RPM read pathsequenceDiagram
actor User as userspace
participant Sysfs as hwmon_sysfs
participant Core as hwmon_core
participant Driver as yoga_fan_driver
participant ACPI as ACPI_firmware
participant EC as EmbeddedController
User->>Sysfs: read fanX_input
Sysfs->>Core: request fan input value
Core->>Driver: yoga_fan_read(dev, hwmon_fan, hwmon_fan_input, channel, val)
Driver->>ACPI: acpi_evaluate_integer(handle[channel])
ACPI->>EC: read fan tachometer register
EC-->>ACPI: raw_fan_value
ACPI-->>Driver: raw_acpi
Driver->>Driver: apply_rllag_filter(data, channel, raw_acpi * multiplier)
Driver-->>Core: return filtered_val[channel]
Core-->>Sysfs: present RPM value
Sysfs-->>User: filtered RPM
Class diagram for yogafan driver data structures and opsclassDiagram
class yogafan_config {
+int multiplier
+int fan_count
+const char * paths[2]
}
class yoga_fan_data {
+acpi_handle active_handles[8]
+long filtered_val[8]
+ktime_t last_sample[8]
+int multiplier
+int fan_count
}
class hwmon_ops {
+umode_t is_visible(const void * data, enum hwmon_sensor_types type, u32 attr, int channel)
+int read(struct device * dev, enum hwmon_sensor_types type, u32 attr, int channel, long * val)
}
class hwmon_chip_info {
+const struct hwmon_ops * ops
+const struct hwmon_channel_info ** info
}
class platform_driver {
+struct device_driver driver
+int (*probe)(struct platform_device * pdev)
}
class platform_device {
+int id
+struct device dev
}
class yoga_fan_module {
+int yoga_fan_probe(struct platform_device * pdev)
+int yoga_fan_read(struct device * dev, enum hwmon_sensor_types type, u32 attr, int channel, long * val)
+umode_t yoga_fan_is_visible(const void * data, enum hwmon_sensor_types type, u32 attr, int channel)
+void apply_rllag_filter(struct yoga_fan_data * data, int idx, long raw_rpm)
+int yoga_fan_init(void)
+void yoga_fan_exit(void)
}
class dmi_system_id {
+const char * ident
+const struct dmi_strmatch matches[4]
+void * driver_data
}
class yogafan_quirks_table {
+struct dmi_system_id entries[*]
}
yogafan_config <.. dmi_system_id : driver_data
yogafan_quirks_table "1" o-- "*" dmi_system_id : contains
yoga_fan_data <.. yoga_fan_module : uses
hwmon_ops <.. yoga_fan_module : implements
hwmon_chip_info o-- hwmon_ops : has
yoga_fan_module o-- platform_driver : registers
yoga_fan_module o-- platform_device : creates
hwmon_chip_info <.. yoga_fan_module : registers_with
yoga_fan_module ..> yogafan_config : selects_via_DMI
yoga_fan_module ..> yogafan_quirks_table : dmi_first_match
yoga_fan_data o-- acpi_handle : stores
yoga_fan_data o-- ktime_t : stores
yoga_fan_module ..> ACPI : acpi_get_handle, acpi_evaluate_integer
yoga_fan_module ..> hwmon_chip_info : devm_hwmon_device_register_with_info
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
This driver provides fan speed monitoring for Lenovo Yoga, Legion, and IdeaPad laptops by interfacing with the Embedded Controller (EC) via ACPI. To address low-resolution sampling in Lenovo EC firmware, a Rate-Limited Lag (RLLag) filter is implemented. The filter ensures a consistent physical curve regardless of userspace polling frequency. Hardware identification is performed via DMI-based quirk tables, which map specific ACPI object paths and register widths (8-bit vs 16-bit) deterministically. Signed-off-by: Sergio Melas <sergiomelas@gmail.com> Link: https://lore.kernel.org/r/20260327221602.18832-1-sergiomelas@gmail.com [groeck: Dropped double empty line in Kconfig] Signed-off-by: Guenter Roeck <linux@roeck-us.net> Link: https://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git/commit/?h=hwmon-next&id=c67c248ca406a86cf8b20bf1b3af5e7f3e36581f Signed-off-by: WangYuli <wangyl5933@chinaunicom.cn>
83ba128 to
5e6fdc2
Compare
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In
yoga_fan_read(), consider defensively checking thatchannel < data->fan_countbefore indexingactive_handles[channel]to guard against any unexpected hwmon core behavior or future changes toyoga_fan_info. - In
yoga_fan_is_visible(), it would be clearer and more robust to also checkattr == hwmon_fan_input(not justtype == hwmon_fan) before returning a mode, so that only supported fan attributes are exposed if more attributes are added in the future.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `yoga_fan_read()`, consider defensively checking that `channel < data->fan_count` before indexing `active_handles[channel]` to guard against any unexpected hwmon core behavior or future changes to `yoga_fan_info`.
- In `yoga_fan_is_visible()`, it would be clearer and more robust to also check `attr == hwmon_fan_input` (not just `type == hwmon_fan`) before returning a mode, so that only supported fan attributes are exposed if more attributes are added in the future.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
Adds a new hwmon driver (yogafan) for monitoring Lenovo consumer laptop fan speed via ACPI/EC, including documentation and build/maintainer integration.
Changes:
- Introduce
drivers/hwmon/yogafan.cimplementing ACPI-backed fan RPM reads with an RLLag smoothing filter. - Add
CONFIG_SENSORS_YOGAFANand wire the driver into the hwmon Makefile. - Add hwmon documentation (
Documentation/hwmon/yogafan.rst), link it from the hwmon index, and add a MAINTAINERS entry.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| MAINTAINERS | Adds maintainer entry and file patterns for the new driver/docs. |
| drivers/hwmon/yogafan.c | New hwmon driver (ACPI EC reads + rate-limited lag filter + DMI quirks). |
| drivers/hwmon/Makefile | Builds yogafan.o under CONFIG_SENSORS_YOGAFAN. |
| drivers/hwmon/Kconfig | Adds CONFIG_SENSORS_YOGAFAN configuration entry. |
| Documentation/hwmon/yogafan.rst | New user-facing documentation for the driver and filtering behavior. |
| Documentation/hwmon/index.rst | Adds yogafan to the hwmon documentation index. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| delta = raw_rpm - data->filtered_val[idx]; | ||
| if (delta == 0) { | ||
| data->last_sample[idx] = now; | ||
| return; | ||
| } | ||
|
|
||
| temp_num = dt_ms << 12; | ||
| alpha = (long)div64_s64(temp_num, (s64)(TAU_MS + dt_ms)); | ||
| step = (delta * alpha) >> 12; | ||
|
|
| @@ -0,0 +1,275 @@ | |||
| // SPDX-License-Identifier: GPL-2.0-only | |||
| /** | |||
| * yoga_fan.c - Lenovo Yoga/Legion Fan Hardware Monitoring Driver | |||
| depends on ACPI && HWMON && DMI | ||
| help | ||
| If you say yes here you get support for fan speed monitoring | ||
| on Lenovo Yoga, Legion, IdeaPad, Slim and LOQ laptops. |
| Supported chips: | ||
|
|
||
| * Lenovo Yoga, Legion, IdeaPad, Slim, Flex, and LOQ Embedded Controllers | ||
| Prefix: 'yogafan' | ||
| Addresses: ACPI handle (See Database Below) |
| for (i = 0; i < cfg->fan_count; i++) { | ||
| acpi_status status; | ||
|
|
||
| status = acpi_get_handle(NULL, (char *)cfg->paths[i], |
This driver provides fan speed monitoring for Lenovo Yoga, Legion, and IdeaPad laptops by interfacing with the Embedded Controller (EC) via ACPI.
To address low-resolution sampling in Lenovo EC firmware, a Rate-Limited Lag (RLLag) filter is implemented. The filter ensures a consistent physical curve regardless of userspace polling frequency.
Hardware identification is performed via DMI-based quirk tables, which map specific ACPI object paths and register widths (8-bit vs 16-bit) deterministically.
Link: https://lore.kernel.org/r/20260327221602.18832-1-sergiomelas@gmail.com
[groeck: Dropped double empty line in Kconfig]
Summary by Sourcery
Add a new hwmon driver for Lenovo laptops to expose EC-based fan speed monitoring via standard hwmon interfaces.
New Features:
Enhancements:
Documentation: