[RFC PATCH 2/3] platform/x86: lenovo-wmi-other: Add Legion Go fan RPM fallback
Aditya Dash <[email protected]>
| Newsgroups | org.kernel.vger.linux-hwmon,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.platform-driver-x86 |
|---|---|
| Message-ID | <[email protected]> |
Some Legion Go firmware does not mark fan 1 RPM as readable in Capability Data, although Other Mode feature 0x04030001 returns the current RPM. As a result, lenovo-wmi-other hides fan1_input. When the normal VALID and GET flags are missing on a supported product, try one read from the Other Mode feature. Expose fan1_input as read-only if the read succeeds and does not return 0xffffffff. Treat a later 0xffffffff reply as an unavailable reading. Assisted-by: Pi:gpt-5.6-sol Signed-off-by: Aditya Dash <[email protected]> --- Documentation/wmi/devices/lenovo-wmi-other.rst | 4 ++++ drivers/platform/x86/lenovo/wmi-other.c | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/wmi/devices/lenovo-wmi-other.rst b/Documentation/wmi/devices/lenovo-wmi-other.rst index 75f2deaaef16..c93e9e6f3fd0 100644 --- a/Documentation/wmi/devices/lenovo-wmi-other.rst +++ b/Documentation/wmi/devices/lenovo-wmi-other.rst @@ -56,6 +56,10 @@ On supported Legion Go models, Other Mode feature ``0x04020000`` controls Full Speed mode in firmware. The driver exposes it as ``pwm1_enable``. Value 0 enables Full Speed, and value 2 returns fan control to firmware. +Some Legion Go firmware does not advertise fan 1 RPM through Capability +Data. In that case, the driver reads Other Mode feature ``0x04030001`` for +``fan1_input``. Value ``0xffffffff`` means that RPM is unavailable. + LENOVO_CAPABILITY_DATA_01 ------------------------- diff --git a/drivers/platform/x86/lenovo/wmi-other.c b/drivers/platform/x86/lenovo/wmi-other.c index c180933e1d18..b4be7739b243 100644 --- a/drivers/platform/x86/lenovo/wmi-other.c +++ b/drivers/platform/x86/lenovo/wmi-other.c @@ -98,6 +98,7 @@ enum lwmi_feature_id_psu { #define LWMI_FAN_ID(x) ((x) + LWMI_FAN_ID_BASE) #define LWMI_FAN_DIV 100 +#define LWMI_FAN_RPM_NORMAL_SUPPORT (LWMI_SUPP_VALID | LWMI_SUPP_GET) #define LWMI_CHARGE_BEHAVIOR_DISCHARGE 0x00 #define LWMI_CHARGE_BEHAVIOR_AUTO 0x01 @@ -195,6 +196,7 @@ struct lwmi_om_priv { struct lwmi_fan_info fan_info[LWMI_FAN_NR]; bool fullspeed_supported; + bool fan0_input_fallback; struct { bool capdata00_collected : 1; @@ -343,6 +345,8 @@ static umode_t lwmi_om_hwmon_is_visible(const void *drvdata, enum hwmon_sensor_t return 0644; if (type == hwmon_fan) { + if (channel == 0 && priv->fan0_input_fallback && attr == hwmon_fan_input) + return 0444; if (!(priv->fan_info[channel].supported & LWMI_SUPP_VALID)) return 0; @@ -419,6 +423,8 @@ static int lwmi_om_hwmon_read(struct device *dev, enum hwmon_sensor_types type, err = lwmi_om_fan_get_set(priv, channel, &retval, false); if (err) return err; + if (channel == 0 && priv->fan0_input_fallback && retval == U32_MAX) + return -EIO; *val = retval; return 0; @@ -542,6 +548,7 @@ static const struct hwmon_chip_info lwmi_om_hwmon_chip_info = { */ static void lwmi_om_hwmon_add(struct lwmi_om_priv *priv) { + u32 rpm; long enable; int i, valid; @@ -563,6 +570,11 @@ static void lwmi_om_hwmon_add(struct lwmi_om_priv *priv) priv->fullspeed_supported = lwmi_fan_supported() && !lwmi_om_fullspeed_get(priv, &enable); + priv->fan0_input_fallback = + lwmi_fan_supported() && + (priv->fan_info[0].supported & LWMI_FAN_RPM_NORMAL_SUPPORT) != + LWMI_FAN_RPM_NORMAL_SUPPORT && + !lwmi_om_fan_get_set(priv, 0, &rpm, false) && rpm != U32_MAX; valid = 0; for (i = 0; i < LWMI_FAN_NR; i++) { @@ -580,7 +592,7 @@ static void lwmi_om_hwmon_add(struct lwmi_om_priv *priv) } } - if (valid == 0 && !priv->fullspeed_supported) { + if (valid == 0 && !priv->fullspeed_supported && !priv->fan0_input_fallback) { dev_warn(&priv->wdev->dev, "fan reporting/tuning is unsupported on this device\n"); return; -- 2.55.0