[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <0e7dfebcaa4509e907faa7b43fc8d49ca6729ca2.camel@rong.moe>
Date: Fri, 16 Jan 2026 22:18:36 +0800
From: Rong Zhang <i@...g.moe>
To: Kurt Borja <kuurtb@...il.com>
Cc: "Derek J. Clark" <derekjohn.clark@...il.com>, Mark Pearson
<mpearson-lenovo@...ebb.ca>, Armin Wolf <W_Armin@....de>, Hans de Goede
<hansg@...nel.org>, Ilpo Järvinen
<ilpo.jarvinen@...ux.intel.com>, Guenter Roeck <linux@...ck-us.net>,
platform-driver-x86@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-hwmon@...r.kernel.org
Subject: Re: [PATCH v9 7/7] platform/x86: lenovo-wmi-other: Add HWMON for
fan reporting/tuning
Hi Kurt,
On Thu, 2026-01-15 at 14:09 -0500, Kurt Borja wrote:
> On Thu Jan 15, 2026 at 11:57 AM -05, Rong Zhang wrote:
> > Hi Kurt,
> >
> > On Thu, 2026-01-15 at 08:58 -0500, Kurt Borja wrote:
> > > On Thu Jan 15, 2026 at 8:03 AM -05, Rong Zhang wrote:
> > > > Hi Kurt,
> > > >
> > > > On Wed, 2026-01-14 at 19:16 -0500, Kurt Borja wrote:
> > > > > Hi Rong,
> > > > >
> > > > > On Wed Jan 14, 2026 at 7:27 AM -05, Rong Zhang wrote:
> > > > > > Register an HWMON device for fan reporting/tuning according to
> > > > > > Capability Data 00 (capdata00) and Fan Test Data (capdata_fan) provided
> > > > > > by lenovo-wmi-capdata. The corresponding HWMON nodes are:
> > > > > >
> > > > > > - fanX_enable: enable/disable the fan (tunable)
> > > > > > - fanX_input: current RPM
> > > > > > - fanX_max: maximum RPM
> > > > > > - fanX_min: minimum RPM
> > > > > > - fanX_target: target RPM (tunable)
> > > > > >
> > > > > > Information from capdata00 and capdata_fan are used to control the
> > > > > > visibility and constraints of HWMON attributes. Fan info from capdata00
> > > > > > is collected on bind, while fan info from capdata_fan is collected in a
> > > > > > callback. Once all fan info is collected, register the HWMON device.
> > > > > >
> > > > > > Signed-off-by: Rong Zhang <i@...g.moe>
> > > > > > Reviewed-by: Derek J. Clark <derekjohn.clark@...il.com>
> > > > > > ---
> > > > >
> > > > > ...
> > > > >
> > > > > > diff --git a/Documentation/wmi/devices/lenovo-wmi-other.rst b/Documentation/wmi/devices/lenovo-wmi-other.rst
> > > > > > index 821282e07d93c..bd1d733ff286d 100644
> > > > > > --- a/Documentation/wmi/devices/lenovo-wmi-other.rst
> > > > > > +++ b/Documentation/wmi/devices/lenovo-wmi-other.rst
> > > > > > @@ -31,6 +31,8 @@ under the following path:
> > > > > >
> > > > > > /sys/class/firmware-attributes/lenovo-wmi-other/attributes/<attribute>/
> > > > > >
> > > > > > +Additionally, this driver also exports attributes to HWMON.
> > > > > > +
> > > > > > LENOVO_CAPABILITY_DATA_00
> > > > > > -------------------------
> > > > > >
> > > > > > @@ -39,6 +41,11 @@ WMI GUID ``362A3AFE-3D96-4665-8530-96DAD5BB300E``
> > > > > > The LENOVO_CAPABILITY_DATA_00 interface provides various information that
> > > > > > does not rely on the gamezone thermal mode.
> > > > > >
> > > > > > +The following HWMON attributes are implemented:
> > > > > > + - fanX_enable: enable/disable the fan (tunable)
> > > > >
> > > > > I was testing this series and I'm a bit confused about fanX_enable.
> > > >
> > > > Thanks for testing!
> > >
> > > Thanks for working on this!
> > >
> > > >
> > > > > Judging by this comment and also by taking a quick look at the code, it
> > > > > looks like writting 0 to this attribute disables the fan.
> > > > >
> > > > > This is however (per hwmon ABI documentation [1]) not how this attribute
> > > > > should work. IIUC, it is intended for devices which can disable the fan
> > > > > sensor, not the actual fan.
> > > >
> > > > Hmm, what a confusing name :-/
> > > >
> > > > > I fail to see how this feature is useful and I also find it dangerous
> > > > > for this to be exposed by default, considering the same could be
> > > > > achieved with the relaxed module parameter, which at least tells the
> > > > > user to be careful.
> > > >
> > > > Makes sense. I will remove the attribute and mention such behavior in
> > > > the module parameter.
> > >
> > > Also, it would be worth to mention that writting 0 to the fanY_target
> > > attribute is auto mode, right?
> >
> > Ah, yes.
> >
> > > I was testing the fanX_target attribute and it does work as intended,
> > > i.e. the fan speed changes to the desired speed. However, every time I
> > > write to this attribute I'm getting -EIO error and it always reads 0.
> > >
> > > For example:
> > >
> > > $ echo 3550 | sudo tee fan*_target
> > > 3550
> > > tee: fan1_target: Input/output error
> > > tee: fan2_target: Input/output error
> > > $ cat fan*_target
> > > 0
> > > 0
> > >
> > > But as I said, the fans do reach the desired speed (an approximation of
> > > it):
> > >
> > > $ cat fan*_input
> > > 3500
> > > 3500
> > >
> > > This is a bit weird, but I haven't look in depth into it. I will find
> > > some time to do it later. This happens on a 83KY (Legion 7 16IAX1)
> > > laptop.
> >
> > I'd like to fix it in the next revision. Looking forward to your
> > progress in debugging :-)
> >
> > It seems to me that the corresponding ACPI method did not return 1 on
> > success. There should be some clues in the decompiled ASL code. Could
> > you attach it in your reply? The HWMON implementation was developed
> > mostly based on my understanding on the decompiled ASL code of my
> > device. I'd like to check the one of your device as a cross-reference
> > to see if there are more potential bugs.
>
> Yep, the ACPI method retval is 0 instead of 1.
Given the divergence between your device and mine, I think we could
just accept both 0 and 1. That should be fine considering that we've
strictly checked LENOVO_CAPABILITY_DATA_00 and LENOVO_FAN_TEST_DATA
before exposing fan channels.
> Here is a snippet of what I believe is the fan control stuff on my
> device (L: 50393):
>
>
> If ((SFV0 == 0x04030001))
> {
> Local0 = (SFV1 / 0x64)
> ^^PC00.LPCB.EC0.LECR (0xD1, One, Local0, 0x02)
> Return (Zero)
> }
>
> If ((SFV0 == 0x04030002))
> {
> Local0 = (SFV1 / 0x64)
> ^^PC00.LPCB.EC0.LECR (0xD1, 0x02, Local0, 0x02)
> Return (Zero)
> }
>
> If ((SFV0 == 0x04030004))
> {
> Local0 = (SFV1 / 0x64)
> ^^PC00.LPCB.EC0.LECR (0xD1, 0x03, Local0, 0x02)
> Return (Zero)
> }
On my device, 0x04030001 always returns 1 after writing to EC
registers. 0x04030002 is a stub and always returns 0. That was the
reason why I assumed 1 => success and 0 => failure. Here's the
corresponding code snippet on my device:
If ((DEV1 == 0x04))
{
If ((FEA1 == 0x03))
{
Local0 = Buffer (0x06){}
Local0 [Zero] = 0x46
If ((TYP1 == One))
{
Local1 = ToInteger (DAT1)
If ((Local1 == Zero))
{
Local0 [One] = 0x84
}
Else
{
MBGS ("Fan1S")
Local0 [One] = 0x85
Divide (Local1, 0x64, Local2, Local1)
Local0 [0x02] = Local1
}
}
If ((TYP1 == 0x02))
{
MBGS ("Fan2S")
Return (Zero)
}
\_SB.PCI0.LPC0.EC0.ERCD (Local0)
Return (One)
}
If ((FEA1 == 0x04))
{
MBGS ("wSet FanNoise")
DB2H (DAT1)
\_SB.FANL = DAT1 /* \_SB_.GZFD.WMAE.DAT1 */
Notify (\_TZ.VFAN, 0x80) // Status Change
}
}
> You can find the full acpidump attached in this email.
Thanks for that.
> Do you have any idea of what 0x04030004 might be?
It's "system fan". See
https://lore.kernel.org/all/CAFqHKTkOZUfDb8cGbGnVPCS9wNbOBsiyOk_MkZR-2_Za6ZPMng@mail.gmail.com/
> This laptop only has 2
> fans. FW bug?
Nope, that's not a bug as long as LENOVO_CAPABILITY_DATA_00 or
LENOVO_FAN_TEST_DATA only indicates the presence of fan 1&2. Lenovo
usually reuses a lot of ASL code among different SKUs, with some other
mechanism to gate inapplicable functionalities.
So I quickly glanced at the decompiled ASL code of your device...
Method WQA9 is LENOVO_CAPABILITY_DATA_00, and it only exposes fan 4 on
specific SKUs (L: 47975):
If (((GSKU == 0x02) || (GSKU == 0x03)))
{
Return (Buffer (0x0C)
{
/* 0000 */ 0x04, 0x00, 0x03, 0x04, 0x07, 0x00, 0x00, 0x00,
/* 0008 */ 0x01, 0x00, 0x00, 0x00
})
}
Else
{
Return (Buffer (0x0C)
{
/* 0000 */ 0x04, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
/* 0008 */ 0x00, 0x00, 0x00, 0x00
})
}
I assume your device should return the latter buffer, indicating fan 4
does not exist. That being said, it won't be surprising if the former
one is returned -- my device's LENOVO_CAPABILITY_DATA_00 indicates the
presence of fan 1&2 while LENOVO_FAN_TEST_DATA only exposes fan 1.
Method WQAB is LENOVO_FAN_TEST_DATA (L: 48195). It exposes fan 1&2,
declaring their RPM range to be [1700,5700].
Return (Buffer (0x1C)
{
/* 0000 */ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
/* 0008 */ 0x02, 0x00, 0x00, 0x00, 0x44, 0x16, 0x00, 0x00,
/* 0010 */ 0x44, 0x16, 0x00, 0x00, 0xA4, 0x06, 0x00, 0x00,
/* 0018 */ 0xA4, 0x06, 0x00, 0x00
})
So these WMI interfaces on your device are implemented mostly well.
LENOVO_FAN_TEST_DATA is enough to prevent fan 4 from being exposed on
your device.
Thanks,
Rong
Powered by blists - more mailing lists