Skip to content

[linux-6.18.y] [Lenovo] [Fromlist] hwmon: (yogafan) Add support for Lenovo Yoga/Legion fan monitoring#1617

Merged
opsiff merged 1 commit intodeepin-community:linux-6.18.yfrom
Avenger-285714:linux-6.18.y
Apr 13, 2026
Merged

[linux-6.18.y] [Lenovo] [Fromlist] hwmon: (yogafan) Add support for Lenovo Yoga/Legion fan monitoring#1617
opsiff merged 1 commit intodeepin-community:linux-6.18.yfrom
Avenger-285714:linux-6.18.y

Conversation

@Avenger-285714
Copy link
Copy Markdown
Member

@Avenger-285714 Avenger-285714 commented Apr 13, 2026

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:

  • Introduce the yogafan hwmon driver to report fan speeds on supported Lenovo Yoga, Legion, and IdeaPad laptops via ACPI EC access.

Enhancements:

  • Wire the yogafan driver into the hwmon subsystem through Kconfig, Makefile, and MAINTAINERS entries.

Documentation:

  • Add user-facing hwmon documentation for the new yogafan driver.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 13, 2026

Reviewer's Guide

Adds 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 probe

sequenceDiagram
    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
Loading

Sequence diagram for yoga_fan RPM read path

sequenceDiagram
    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
Loading

Class diagram for yogafan driver data structures and ops

classDiagram
    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
Loading

File-Level Changes

Change Details Files
Introduce yogafan hwmon driver implementing ACPI-based fan RPM reading with a rate-limited lag (RLLag) filter and DMI-based configuration for Lenovo laptops.
  • Define driver constants, per-platform configuration structures, and runtime state to support up to 8 fans and different EC register widths via multipliers and ACPI paths.
  • Implement apply_rllag_filter to smooth raw EC RPM values over time using a discrete-time first-order lag with slew-rate limiting, including sampling interval guards and autoreset on long gaps or low RPM.
  • Implement yoga_fan_read and yoga_fan_is_visible hwmon callbacks to read ACPI fan values, apply filtering, and expose hwmon fan_input attributes only for detected fans.
  • Declare hwmon channel and chip info to describe up to 8 fan_input channels to the hwmon core.
  • Add a DMI-based quirks table mapping Yoga/Legion/IdeaPad families to specific ACPI object paths, fan counts, and multipliers, and register a MODULE_DEVICE_TABLE for DMI matching.
  • Implement a platform_driver probe that selects the matching DMI config, resolves ACPI handles for configured paths, counts available fans, and registers the hwmon device.
  • Add module init/exit that conditionally registers the platform driver/device only on matching DMI systems, and tears them down on exit.
drivers/hwmon/yogafan.c
Wire the yogafan driver into the hwmon build, configuration, maintainership, and documentation.
  • Add CONFIG_SENSORS_YOGAFAN object line to the hwmon Makefile to build yogafan.o when enabled.
  • Introduce a Kconfig entry for SENSORS_YOGAFAN under drivers/hwmon to allow enabling the driver via menuconfig, referencing the new documentation and describing supported Lenovo systems.
  • Register the new driver and maintainer information in MAINTAINERS so bug reports and patches are routed correctly.
  • Add yogafan.rst and link it from Documentation/hwmon/index.rst to document the driver, its usage, and supported hardware.
drivers/hwmon/Makefile
drivers/hwmon/Kconfig
MAINTAINERS
Documentation/hwmon/index.rst
Documentation/hwmon/yogafan.rst

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from avenger-285714. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

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>
Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • 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.
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.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Avenger-285714 Avenger-285714 changed the title [linux-6.6.y] [Lenovo] [Fromlist] hwmon: (yogafan) Add support for Lenovo Yoga/Legion fan monitoring [linux-6.18.y] [Lenovo] [Fromlist] hwmon: (yogafan) Add support for Lenovo Yoga/Legion fan monitoring Apr 13, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.c implementing ACPI-backed fan RPM reads with an RLLag smoothing filter.
  • Add CONFIG_SENSORS_YOGAFAN and 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.

Comment on lines +96 to +105
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.
Comment on lines +6 to +10
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],
@opsiff opsiff merged commit 17a8324 into deepin-community:linux-6.18.y Apr 13, 2026
10 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants