mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Re: [BUG] Redmi Book Pro 14 2024 (TM2307): fans never spin under Linux — root cause: EC gates fan engine on OSTP byte (tested workaround)
       [not found] <CAL-my2=5V8Pk+R+aAoJ556-DFR-B0wnMLckRNDbAohdZvB15+Q@mail.gmail.com>
@ 2026-09-15 21:46 ` Armin Wolf
  2026-09-16 10:10   ` 高 俊文
  0 siblings, 1 reply; 3+ messages in thread
From: Armin Wolf @ 2026-09-15 21:46 UTC (permalink / raw)
  To: 高 俊文, platform-driver-x86
  Cc: linux-kernel, qby140326, ilpo.jarvinen, hansg

Am 15.09.26 um 14:09 schrieb 高 俊文:

> Hi,
>
> This follows up on the report from Miloš Vlku about the Redmi Book Pro 14
> 2024 (TM2307), where the fans never spin under Linux although the same
> hardware works fine under Windows:
>
> https://lkml.iu.edu/hypermail/linux/kernel/2608.1/13832.html
>
> We have now root-caused the problem on an identical machine (second 
> TM2307,
> Core Ultra 7 155H) and have a one-byte, experimentally verified 
> workaround.
> Summary: the EC only runs its autonomous fan engine when the OSTP "OS 
> type"
> byte in its shared memory window indicates a detected host OS. Under 
> Windows
> the DSDT _REG handler writes OSTP=6; under Linux nothing writes it, OSTP
> stays 0, and the EC never spins the fans. All OS-side fan paths (MIFS WMI
> fan functions, ACPI PNP0C0B fans) are separately broken on this board, so
> fans are unreachable from Linux even at 100 degC.
>
Nice work, what is the output of "cat /sys/bus/acpi/devices/PNP0C09:*/status"?
Can you share the output of "dmesg"?

> Machine / software
> ==================
>
>   DMI: XIAOMI / Redmi Book Pro 14 2024 / TM2307
>   CPU: Intel Core Ultra 7 155H (Meteor Lake-H)
>   BIOS: XIAOMI RMAMT4B0P0A0A (06/04/2024)
>   Kernel: 7.2.3-arch1-3 (bitland-mifs-wmi incl. d3666875c75e)
>
> Symptoms (all verified)
> =======================
>
>   - Fans physically never spin under Linux, even with the package at
>     101 degC for minutes (verified by microphone recording: no acoustic
>     change; user-confirmed silence; multiple independent load tests).
>   - hwmon (bitland_mifs): fan1/2/3_input always 0, temp1 always 0.0 degC.
>   - fan_boost sysfs attribute (WMI function 20): write succeeds, no 
> effect.
>   - No WMI fan events (26/32) ever fire (no hwmon uevents under load).
>   - Writing cur_state=1 to all five PNP0C0B cooling devices: no effect.
>   - acpitz thermal zone (SSDT23 TZ00) reports a constant ~26.9 degC while
>     coretemp reads 56-101 degC.
>   - Under Windows, fans work normally (per Miloš Vlku's dual-boot test on
>     the same board).
>
> Root cause — DSDT/SSDT evidence chain
> =====================================
>
> 1) The EC's memory window and the OSTP byte
>
>    Under \_SB.PC00.LPCB.Q_EC (PNP0C09):
>
>      OperationRegion (ERAM, SystemMemory, 0xFE0B0300, 0x0100)
>
>    Q_EC._REG (fires when EC region space becomes available) maps the OS
>    version (OSYS) to an OSTP byte and writes it:
>
>      OSYS 0x03E8 -> OSTP = 2      (Linux)
>      OSYS 0x07D9 -> OSTP = 3      (Windows 2009)
>      OSYS 0x07DC -> OSTP = 4      (Windows 2012)
>      OSYS 0x07DD -> OSTP = 5      (Windows 2015)
>      OSYS 0x07DF -> OSTP = 6      (Windows 2021)
>
>    On this machine OSTP (ERAM offset 0x64) reads 0x00 under Linux: the
>    _REG write never happens (verified by dumping the window via /dev/mem;
>    the rest of the window is demonstrably live, e.g. live temperature
>    fields TSR0-TSRB at offsets 0x08-0x13, exposed to Linux via the SENx
>    DPTF sensors whose _TMP read these bytes directly).
>
> 2) OSTP gates the EC's autonomous fan engine — experimentally verified
>
>    Writing OSTP=6 (/dev/mem, single byte) at idle, then running an
>    all-core load:
>
>      OSTP=0 (control):  101 -> 83 degC clamp, fans silent (no airflow)
>      OSTP=6:            fans audibly engage and follow the EC's own
>                         temperature curve; package temperature bends down
>                         mid-load (83 -> 70 degC) instead of plateauing
>      QFAN (ERAM 0x60)=4 ("full speed" performance mode value): fans spin
>                         at full speed regardless of temperature
>
>    After writing OSTP=6 once, fan behavior matches Windows (moderate ramp,
>    full speed only near the EC's high thresholds). A systemd oneshot that
>    writes OSTP=6 at boot and after resume has kept the machine cool and
>    correctly fan-cooled since installation.
>
> 3) The MIFS WMI fan functions are not implemented in this firmware
>
>    The MIFS WMI method is WMAA in SSDT20 (device WMID, _UID "MIFS"; _WDG
>    entry for GUID B60BFB48-3E5B-49E4-A0E9-8CFFE1B3434B, object id "AA").
>    Its GET (0xFA) and SET (0xFB) switches implement only functions 0x08
>    (SystemPerMode), 0x0A (country/kbd, sub 5) and 0x10 (misc). The fan
>    functions used by bitland-mifs-wmi fall through to
>
>      Default { SGER = 0xE000 }        /* unsupported, zeroed buffer */
>
>    i.e. function 0x0D (WMI_FN_FAN_SPEEDS) returns an all-zero buffer
>    (hwmon zeros incl. WMI_FN_CPU_THERMOMETER 0x16), and functions 0x14
>    (WMI_FN_MAX_FAN_SWITCH / fan_boost) and 0x15 (WMI_FN_MAX_FAN_SPEED)
>    are silently ignored — exactly the observed behavior. So this board's
>    firmware is "MIFS reduced" in the same sense as the MIFS v2 machines
>    discussed in Yuming Sun's series, except here the WMI method exists
>    but the fan function cases are absent.
>
> 4) The ACPI fan path is gated on a device this board does not declare
>
>    SSDT23 declares the five PNP0C0B fans (FAN0-FAN4) with PowerResources
>    FN00-FN04. Their _ON/_OFF only set software flags CVF0-4 and call
>    FNCL(), which ends in:
>
>      \_SB.PC00.LPCB.UPFS (ETMD, Local0, Local1)
>
>    and LPCB.UPFS (DSDT) does nothing unless
>
>      If ((CondRefOf (\_SB.PC00.LPCB.H_EC) && Arg0)) ...
>
>    H_EC is not declared anywhere in any table on this machine, so the
>    entire ACPI fan-control path is a silent no-op. This is why writing
>    cur_state=1 to the cooling devices changes nothing.
>
> 5) The ACPI thermal zone yields to the (disabled) firmware controller
>
>    SSDT23 TZ00._TMP:
>
>      If (!ETMD) { Return (0x0BB8) }          /* constant 26.85 degC */
>      Return (\_SB.PC00.LPCB.MXTP ())
>
>    SSDT16 IETM._OSC sets \_TZ.ETMD = Zero when the firmware reports
>    native trip-point capability (CAP1 bit0 | bit1), selecting "firmware
>    manages thermals" mode. Combined with (1), the firmware never enables
>    fan control and the ACPI zone never reports real heat — the kernel
>    never sees a reason to act.
>
> 6) Tachometer caveat for this generation
>
>    The ERAM offsets 0x69/0x6B used by the MIFS v2 fan-tach patch do
>    exist here, but they do NOT live-update on TM2307: they hold stale
>    values (fan1=2, fan2=0) even while the fans audibly spin. Reading
>    tach on this model will need a different mechanism (or none).
>
> Proposed fix
> ============
>
> Short term (upstream): have bitland-mifs-wmi write OSTP=6 (or evaluate/
> replicate the _REG OSYS mapping) at probe time for boards where the
> firmware leaves it at 0 — ideally behind a DMI quirk. Note the pending
> DMI-matching problem reported by Miloš: this board (DMI_SYS_VENDOR
> "XIAOMI", DMI_BOARD_NAME "TM2307") matches neither "Redmi" nor "TIMI"
> entries, so any Redmi-specific quirk table needs an explicit TM2307/XIAOMI
> entry.
>
> Longer term: a hwmon pwm/fan interface for boards with the reduced
> firmware could drive QFAN (0x60) and read the SENx temperatures (ERAM
> 0x08-0x13 / TSR0-TSRB), giving Linux users real fan control on this
> generation.
>
I do not think this would really solve the problem, because any attempt by the
ACPI firmware to access the embedded controller would still result in an error.

The most important thing right now is to determine why the embedded controller
driver fails to probe.

Thanks,
Armin Wolf

> Current workaround in place (for reference):
>
>   systemd oneshot service, runs at boot and after resume:
>
>     python3 - <<'EOF'
>     import os, mmap
>     f = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
>     m = mmap.mmap(f, 0x1000, offset=0xFE0B0000)
>     m[0x300 + 0x64] = 6   # ERAM offset 0x64 = OSTP
>     m.close()
>     EOF
>
> I have full acpidumps (DSDT + all 27 SSDTs, disassembled), the ERAM
> window dumps before/during/after experiments, and the load-test
> temperature logs. Happy to provide any of these, test patches, or help
> however useful.
>
> Thanks
>
> -- 
> @gaojunwen

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [BUG] Redmi Book Pro 14 2024 (TM2307): fans never spin under Linux — root cause: EC gates fan engine on OSTP byte (tested workaround)
  2026-09-15 21:46 ` [BUG] Redmi Book Pro 14 2024 (TM2307): fans never spin under Linux — root cause: EC gates fan engine on OSTP byte (tested workaround) Armin Wolf
@ 2026-09-16 10:10   ` 高 俊文
  0 siblings, 0 replies; 3+ messages in thread
From: 高 俊文 @ 2026-09-16 10:10 UTC (permalink / raw)
  To: Armin Wolf
  Cc: platform-driver-x86, linux-kernel, qby140326, ilpo.jarvinen, hansg

Hi Armin,

Thanks for looking at this. Answers to your two questions first, then a
correction to my original report that your questions prompted — you were
right to be suspicious, though it is not a probe failure on this unit.

> what is the output of "cat /sys/bus/acpi/devices/PNP0C09:*/status"?

  15

(single EC: PNP0C09:00 under \_SB.PC00.LPCB)

> Can you share the output of "dmesg"?

Attached, captured on the current boot (kernel 7.2.5-3-omarchy; the
original report was on 7.2.3, same behavior). EC-relevant excerpt:

  ACPI: EC: EC started
  ACPI: EC: interrupt blocked
  ACPI: EC: EC_CMD/EC_SC=0x66, EC_DATA=0x62
  ACPI: \_SB_.PC00.LPCB.Q_EC: Boot DSDT EC used to handle transactions
  ACPI: EC: interrupt unblocked
  ACPI: EC: event unblocked
  ACPI: EC: EC_CMD/EC_SC=0x66, EC_DATA=0x62
  ACPI: EC: GPE=0x6e
  ACPI: \_SB_.PC00.LPCB.Q_EC: Boot DSDT EC initialization complete
  ACPI: \_SB_.PC00.LPCB.Q_EC: EC: Used to handle transactions and events
  input: Lid Switch as .../0000:00:1f.0/PNP0C09:00/PNP0C0D:00/input/input0

The EC driver probes and binds fine here: PNP0C09:00 has a physical
platform device bound to the acpi-ec driver, there is no ECDT (the EC is
DSDT-only), and EC transactions demonstrably work at runtime (BAT0 _BST
reports live voltage/energy/serial; the lid switch and GPE 0x6e events
work). The only ACPI errors in the log are unrelated _PLD/_UPC failures
in the XHCI/TXHC hubs (AE_AML_TOO_FEW_ARGUMENTS in a RUCC helper).

Your other concern — that any firmware attempt to access the EC would
error out — does not apply to this board, and chasing it down exposed a
real mistake in my original report:

1) No AML anywhere in our tables (DSDT + all 27 SSDTs) uses EC address
   space. All 308 OperationRegions are 242 SystemMemory, 50 PCI_Config,
   14 SystemIO, 2 SystemCMOS. The EC's data surface for AML is a plain
   SystemMemory window:

     OperationRegion (ERAM, SystemMemory, 0xFE0B0300, 0x0100)

2) Consequence: Q_EC._REG can never execute for an EC-space connect,
   because no EC-space region object exists for ACPICA to fire it on —
   on any OS. The OSYS->OSTP mapping inside _REG is dead code (vendor
   cruft from a reference design). Q_EC._INI sets ECAV=1 when
   _REV>=2, and all methods proceed through the ERAM window instead.

3) I misread the window layout in my report. The iasl field layout is:

     Offset (0x60): QFAN, 8
     Offset (0x62): SCFG (0x62), HBPF (0x63), PCMD (0x64), OSTP (0x65)

   The byte I called "OSTP" (0x64) is actually declared "PCMD" in the
   vendor AML — and PCMD is referenced by no AML method anywhere. The
   real OSTP at 0x65 already reads 6 at every Linux boot with no help
   from us (pre-fix dumps: 0x64=0x00, 0x65=0x06), so it is written by
   the EC/UEFI firmware itself, not by AML.

4) Corrected root cause: the EC's autonomous fan engine is gated on
   ERAM+0x64 ("PCMD"), which nothing ever sets under Linux. The
   original experiment stands with cleaner isolation than I realized:
   with OSTP (0x65) already 6 the whole time, control load runs stay
   fan-silent; writing 6 to 0x64 engages the engine and the fans follow
   the EC's own temperature curve; QFAN (0x60)=4 forces full speed.
   That one-byte write has been running as a boot+resume oneshot since
   2026-09-15 and the machine behaves exactly like the Windows side.

So on this unit the EC driver is healthy, and "replicate the _REG
OSYS mapping" (my original proposal) would be the wrong fix — _REG
never runs on this platform regardless of OS. The open question is
narrower now: who sets ERAM+0x64 under Windows? Not AML (no
references on any OS), so presumably EC-internal logic or an SMI
path (there is an event-driven one: _Q35 writes 0xC2 to the port-0xB2
SMI port). If Miloš (dual-boot) could dump ERAM 0x60..0x6C from
Windows — or even just byte 0x64 at idle and under load — that would
pin down what state the EC expects to see.

Happy to test any patch. If a quirk approach is still wanted, the
effective workaround is "write ERAM+0x64=6 at boot/resume", not
"replicate _REG". Full acpidump and the raw ERAM dumps available any
time.

Transparency note: the ACPI analysis, the experiments, and this email
were prepared by an AI coding agent (Claude Code running the GLM 5.3
Flash model) working on this machine. To be honest, I still find much
of the ACPI detail confusing myself — what I can vouch for firsthand
is the hardware behavior: the fans were always silent under Linux, and
after the one-byte write they spin and track the load exactly like on
Windows. For anything deeper than that, please ask and I will relay
it to the agent.

Thanks,
dista

On Wed, Sep 16, 2026 at 5:47 AM Armin Wolf <W_Armin@gmx.de> wrote:
>
> Am 15.09.26 um 14:09 schrieb 高 俊文:
>
> > Hi,
> >
> > This follows up on the report from Miloš Vlku about the Redmi Book Pro 14
> > 2024 (TM2307), where the fans never spin under Linux although the same
> > hardware works fine under Windows:
> >
> > https://lkml.iu.edu/hypermail/linux/kernel/2608.1/13832.html
> >
> > We have now root-caused the problem on an identical machine (second
> > TM2307,
> > Core Ultra 7 155H) and have a one-byte, experimentally verified
> > workaround.
> > Summary: the EC only runs its autonomous fan engine when the OSTP "OS
> > type"
> > byte in its shared memory window indicates a detected host OS. Under
> > Windows
> > the DSDT _REG handler writes OSTP=6; under Linux nothing writes it, OSTP
> > stays 0, and the EC never spins the fans. All OS-side fan paths (MIFS WMI
> > fan functions, ACPI PNP0C0B fans) are separately broken on this board, so
> > fans are unreachable from Linux even at 100 degC.
> >
> Nice work, what is the output of "cat /sys/bus/acpi/devices/PNP0C09:*/status"?
> Can you share the output of "dmesg"?
>
> > Machine / software
> > ==================
> >
> >   DMI: XIAOMI / Redmi Book Pro 14 2024 / TM2307
> >   CPU: Intel Core Ultra 7 155H (Meteor Lake-H)
> >   BIOS: XIAOMI RMAMT4B0P0A0A (06/04/2024)
> >   Kernel: 7.2.3-arch1-3 (bitland-mifs-wmi incl. d3666875c75e)
> >
> > Symptoms (all verified)
> > =======================
> >
> >   - Fans physically never spin under Linux, even with the package at
> >     101 degC for minutes (verified by microphone recording: no acoustic
> >     change; user-confirmed silence; multiple independent load tests).
> >   - hwmon (bitland_mifs): fan1/2/3_input always 0, temp1 always 0.0 degC.
> >   - fan_boost sysfs attribute (WMI function 20): write succeeds, no
> > effect.
> >   - No WMI fan events (26/32) ever fire (no hwmon uevents under load).
> >   - Writing cur_state=1 to all five PNP0C0B cooling devices: no effect.
> >   - acpitz thermal zone (SSDT23 TZ00) reports a constant ~26.9 degC while
> >     coretemp reads 56-101 degC.
> >   - Under Windows, fans work normally (per Miloš Vlku's dual-boot test on
> >     the same board).
> >
> > Root cause — DSDT/SSDT evidence chain
> > =====================================
> >
> > 1) The EC's memory window and the OSTP byte
> >
> >    Under \_SB.PC00.LPCB.Q_EC (PNP0C09):
> >
> >      OperationRegion (ERAM, SystemMemory, 0xFE0B0300, 0x0100)
> >
> >    Q_EC._REG (fires when EC region space becomes available) maps the OS
> >    version (OSYS) to an OSTP byte and writes it:
> >
> >      OSYS 0x03E8 -> OSTP = 2      (Linux)
> >      OSYS 0x07D9 -> OSTP = 3      (Windows 2009)
> >      OSYS 0x07DC -> OSTP = 4      (Windows 2012)
> >      OSYS 0x07DD -> OSTP = 5      (Windows 2015)
> >      OSYS 0x07DF -> OSTP = 6      (Windows 2021)
> >
> >    On this machine OSTP (ERAM offset 0x64) reads 0x00 under Linux: the
> >    _REG write never happens (verified by dumping the window via /dev/mem;
> >    the rest of the window is demonstrably live, e.g. live temperature
> >    fields TSR0-TSRB at offsets 0x08-0x13, exposed to Linux via the SENx
> >    DPTF sensors whose _TMP read these bytes directly).
> >
> > 2) OSTP gates the EC's autonomous fan engine — experimentally verified
> >
> >    Writing OSTP=6 (/dev/mem, single byte) at idle, then running an
> >    all-core load:
> >
> >      OSTP=0 (control):  101 -> 83 degC clamp, fans silent (no airflow)
> >      OSTP=6:            fans audibly engage and follow the EC's own
> >                         temperature curve; package temperature bends down
> >                         mid-load (83 -> 70 degC) instead of plateauing
> >      QFAN (ERAM 0x60)=4 ("full speed" performance mode value): fans spin
> >                         at full speed regardless of temperature
> >
> >    After writing OSTP=6 once, fan behavior matches Windows (moderate ramp,
> >    full speed only near the EC's high thresholds). A systemd oneshot that
> >    writes OSTP=6 at boot and after resume has kept the machine cool and
> >    correctly fan-cooled since installation.
> >
> > 3) The MIFS WMI fan functions are not implemented in this firmware
> >
> >    The MIFS WMI method is WMAA in SSDT20 (device WMID, _UID "MIFS"; _WDG
> >    entry for GUID B60BFB48-3E5B-49E4-A0E9-8CFFE1B3434B, object id "AA").
> >    Its GET (0xFA) and SET (0xFB) switches implement only functions 0x08
> >    (SystemPerMode), 0x0A (country/kbd, sub 5) and 0x10 (misc). The fan
> >    functions used by bitland-mifs-wmi fall through to
> >
> >      Default { SGER = 0xE000 }        /* unsupported, zeroed buffer */
> >
> >    i.e. function 0x0D (WMI_FN_FAN_SPEEDS) returns an all-zero buffer
> >    (hwmon zeros incl. WMI_FN_CPU_THERMOMETER 0x16), and functions 0x14
> >    (WMI_FN_MAX_FAN_SWITCH / fan_boost) and 0x15 (WMI_FN_MAX_FAN_SPEED)
> >    are silently ignored — exactly the observed behavior. So this board's
> >    firmware is "MIFS reduced" in the same sense as the MIFS v2 machines
> >    discussed in Yuming Sun's series, except here the WMI method exists
> >    but the fan function cases are absent.
> >
> > 4) The ACPI fan path is gated on a device this board does not declare
> >
> >    SSDT23 declares the five PNP0C0B fans (FAN0-FAN4) with PowerResources
> >    FN00-FN04. Their _ON/_OFF only set software flags CVF0-4 and call
> >    FNCL(), which ends in:
> >
> >      \_SB.PC00.LPCB.UPFS (ETMD, Local0, Local1)
> >
> >    and LPCB.UPFS (DSDT) does nothing unless
> >
> >      If ((CondRefOf (\_SB.PC00.LPCB.H_EC) && Arg0)) ...
> >
> >    H_EC is not declared anywhere in any table on this machine, so the
> >    entire ACPI fan-control path is a silent no-op. This is why writing
> >    cur_state=1 to the cooling devices changes nothing.
> >
> > 5) The ACPI thermal zone yields to the (disabled) firmware controller
> >
> >    SSDT23 TZ00._TMP:
> >
> >      If (!ETMD) { Return (0x0BB8) }          /* constant 26.85 degC */
> >      Return (\_SB.PC00.LPCB.MXTP ())
> >
> >    SSDT16 IETM._OSC sets \_TZ.ETMD = Zero when the firmware reports
> >    native trip-point capability (CAP1 bit0 | bit1), selecting "firmware
> >    manages thermals" mode. Combined with (1), the firmware never enables
> >    fan control and the ACPI zone never reports real heat — the kernel
> >    never sees a reason to act.
> >
> > 6) Tachometer caveat for this generation
> >
> >    The ERAM offsets 0x69/0x6B used by the MIFS v2 fan-tach patch do
> >    exist here, but they do NOT live-update on TM2307: they hold stale
> >    values (fan1=2, fan2=0) even while the fans audibly spin. Reading
> >    tach on this model will need a different mechanism (or none).
> >
> > Proposed fix
> > ============
> >
> > Short term (upstream): have bitland-mifs-wmi write OSTP=6 (or evaluate/
> > replicate the _REG OSYS mapping) at probe time for boards where the
> > firmware leaves it at 0 — ideally behind a DMI quirk. Note the pending
> > DMI-matching problem reported by Miloš: this board (DMI_SYS_VENDOR
> > "XIAOMI", DMI_BOARD_NAME "TM2307") matches neither "Redmi" nor "TIMI"
> > entries, so any Redmi-specific quirk table needs an explicit TM2307/XIAOMI
> > entry.
> >
> > Longer term: a hwmon pwm/fan interface for boards with the reduced
> > firmware could drive QFAN (0x60) and read the SENx temperatures (ERAM
> > 0x08-0x13 / TSR0-TSRB), giving Linux users real fan control on this
> > generation.
> >
> I do not think this would really solve the problem, because any attempt by the
> ACPI firmware to access the embedded controller would still result in an error.
>
> The most important thing right now is to determine why the embedded controller
> driver fails to probe.
>
> Thanks,
> Armin Wolf
>
> > Current workaround in place (for reference):
> >
> >   systemd oneshot service, runs at boot and after resume:
> >
> >     python3 - <<'EOF'
> >     import os, mmap
> >     f = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
> >     m = mmap.mmap(f, 0x1000, offset=0xFE0B0000)
> >     m[0x300 + 0x64] = 6   # ERAM offset 0x64 = OSTP
> >     m.close()
> >     EOF
> >
> > I have full acpidumps (DSDT + all 27 SSDTs, disassembled), the ERAM
> > window dumps before/during/after experiments, and the load-test
> > temperature logs. Happy to provide any of these, test patches, or help
> > however useful.
> >
> > Thanks
> >
> > --
> > @gaojunwen



-- 
@gaojunwen

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [BUG] Redmi Book Pro 14 2024 (TM2307): fans never spin under Linux — root cause: EC gates fan engine on OSTP byte (tested workaround)
@ 2026-09-15 15:26 高 俊文
  0 siblings, 0 replies; 3+ messages in thread
From: 高 俊文 @ 2026-09-15 15:26 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: linux-kernel, qby140326, W_Armin, ilpo.jarvinen, hansg

Hi,

This follows up on the report from Miloš Vlku about the Redmi Book Pro 14
2024 (TM2307), where the fans never spin under Linux although the same
hardware works fine under Windows:

  https://lkml.iu.edu/hypermail/linux/kernel/2608.1/13832.html

We have now root-caused the problem on an identical machine (second TM2307,
Core Ultra 7 155H) and have a one-byte, experimentally verified workaround.
Summary: the EC only runs its autonomous fan engine when the OSTP "OS type"
byte in its shared memory window indicates a detected host OS. Under Windows
the DSDT _REG handler writes OSTP=6; under Linux nothing writes it, OSTP
stays 0, and the EC never spins the fans. All OS-side fan paths (MIFS WMI
fan functions, ACPI PNP0C0B fans) are separately broken on this board, so
fans are unreachable from Linux even at 100 degC.

Machine / software
==================

  DMI: XIAOMI / Redmi Book Pro 14 2024 / TM2307
  CPU: Intel Core Ultra 7 155H (Meteor Lake-H)
  BIOS: XIAOMI RMAMT4B0P0A0A (06/04/2024)
  Kernel: 7.2.3-arch1-3 (bitland-mifs-wmi incl. d3666875c75e)

Symptoms (all verified)
=======================

  - Fans physically never spin under Linux, even with the package at
    101 degC for minutes (verified by microphone recording: no acoustic
    change; user-confirmed silence; multiple independent load tests).
  - hwmon (bitland_mifs): fan1/2/3_input always 0, temp1 always 0.0 degC.
  - fan_boost sysfs attribute (WMI function 20): write succeeds, no effect.
  - No WMI fan events (26/32) ever fire (no hwmon uevents under load).
  - Writing cur_state=1 to all five PNP0C0B cooling devices: no effect.
  - acpitz thermal zone (SSDT23 TZ00) reports a constant ~26.9 degC while
    coretemp reads 56-101 degC.
  - Under Windows, fans work normally (per Miloš Vlku's dual-boot test on
    the same board).

Root cause — DSDT/SSDT evidence chain
=====================================

1) The EC's memory window and the OSTP byte

   Under \_SB.PC00.LPCB.Q_EC (PNP0C09):

     OperationRegion (ERAM, SystemMemory, 0xFE0B0300, 0x0100)

   Q_EC._REG (fires when EC region space becomes available) maps the OS
   version (OSYS) to an OSTP byte and writes it:

     OSYS 0x03E8 -> OSTP = 2      (Linux)
     OSYS 0x07D9 -> OSTP = 3      (Windows 2009)
     OSYS 0x07DC -> OSTP = 4      (Windows 2012)
     OSYS 0x07DD -> OSTP = 5      (Windows 2015)
     OSYS 0x07DF -> OSTP = 6      (Windows 2021)

   On this machine OSTP (ERAM offset 0x64) reads 0x00 under Linux: the
   _REG write never happens (verified by dumping the window via /dev/mem;
   the rest of the window is demonstrably live, e.g. live temperature
   fields TSR0-TSRB at offsets 0x08-0x13, exposed to Linux via the SENx
   DPTF sensors whose _TMP read these bytes directly).

2) OSTP gates the EC's autonomous fan engine — experimentally verified

   Writing OSTP=6 (/dev/mem, single byte) at idle, then running an
   all-core load:

     OSTP=0 (control):  101 -> 83 degC clamp, fans silent (no airflow)
     OSTP=6:            fans audibly engage and follow the EC's own
                        temperature curve; package temperature bends down
                        mid-load (83 -> 70 degC) instead of plateauing
     QFAN (ERAM 0x60)=4 ("full speed" performance mode value): fans spin
                        at full speed regardless of temperature

   After writing OSTP=6 once, fan behavior matches Windows (moderate ramp,
   full speed only near the EC's high thresholds). A systemd oneshot that
   writes OSTP=6 at boot and after resume has kept the machine cool and
   correctly fan-cooled since installation.

3) The MIFS WMI fan functions are not implemented in this firmware

   The MIFS WMI method is WMAA in SSDT20 (device WMID, _UID "MIFS"; _WDG
   entry for GUID B60BFB48-3E5B-49E4-A0E9-8CFFE1B3434B, object id "AA").
   Its GET (0xFA) and SET (0xFB) switches implement only functions 0x08
   (SystemPerMode), 0x0A (country/kbd, sub 5) and 0x10 (misc). The fan
   functions used by bitland-mifs-wmi fall through to

     Default { SGER = 0xE000 }        /* unsupported, zeroed buffer */

   i.e. function 0x0D (WMI_FN_FAN_SPEEDS) returns an all-zero buffer
   (hwmon zeros incl. WMI_FN_CPU_THERMOMETER 0x16), and functions 0x14
   (WMI_FN_MAX_FAN_SWITCH / fan_boost) and 0x15 (WMI_FN_MAX_FAN_SPEED)
   are silently ignored — exactly the observed behavior. So this board's
   firmware is "MIFS reduced" in the same sense as the MIFS v2 machines
   discussed in Yuming Sun's series, except here the WMI method exists
   but the fan function cases are absent.

4) The ACPI fan path is gated on a device this board does not declare

   SSDT23 declares the five PNP0C0B fans (FAN0-FAN4) with PowerResources
   FN00-FN04. Their _ON/_OFF only set software flags CVF0-4 and call
   FNCL(), which ends in:

     \_SB.PC00.LPCB.UPFS (ETMD, Local0, Local1)

   and LPCB.UPFS (DSDT) does nothing unless

     If ((CondRefOf (\_SB.PC00.LPCB.H_EC) && Arg0)) ...

   H_EC is not declared anywhere in any table on this machine, so the
   entire ACPI fan-control path is a silent no-op. This is why writing
   cur_state=1 to the cooling devices changes nothing.

5) The ACPI thermal zone yields to the (disabled) firmware controller

   SSDT23 TZ00._TMP:

     If (!ETMD) { Return (0x0BB8) }          /* constant 26.85 degC */
     Return (\_SB.PC00.LPCB.MXTP ())

   SSDT16 IETM._OSC sets \_TZ.ETMD = Zero when the firmware reports
   native trip-point capability (CAP1 bit0 | bit1), selecting "firmware
   manages thermals" mode. Combined with (1), the firmware never enables
   fan control and the ACPI zone never reports real heat — the kernel
   never sees a reason to act.

6) Tachometer caveat for this generation

   The ERAM offsets 0x69/0x6B used by the MIFS v2 fan-tach patch do
   exist here, but they do NOT live-update on TM2307: they hold stale
   values (fan1=2, fan2=0) even while the fans audibly spin. Reading
   tach on this model will need a different mechanism (or none).

Proposed fix
============

Short term (upstream): have bitland-mifs-wmi write OSTP=6 (or evaluate/
replicate the _REG OSYS mapping) at probe time for boards where the
firmware leaves it at 0 — ideally behind a DMI quirk. Note the pending
DMI-matching problem reported by Miloš: this board (DMI_SYS_VENDOR
"XIAOMI", DMI_BOARD_NAME "TM2307") matches neither "Redmi" nor "TIMI"
entries, so any Redmi-specific quirk table needs an explicit TM2307/XIAOMI
entry.

Longer term: a hwmon pwm/fan interface for boards with the reduced
firmware could drive QFAN (0x60) and read the SENx temperatures (ERAM
0x08-0x13 / TSR0-TSRB), giving Linux users real fan control on this
generation.

Current workaround in place (for reference):

  systemd oneshot service, runs at boot and after resume:

    python3 - <<'EOF'
    import os, mmap
    f = os.open('/dev/mem', os.O_RDWR | os.O_SYNC)
    m = mmap.mmap(f, 0x1000, offset=0xFE0B0000)
    m[0x300 + 0x64] = 6   # ERAM offset 0x64 = OSTP
    m.close()
    EOF

I have full acpidumps (DSDT + all 27 SSDTs, disassembled), the ERAM
window dumps before/during/after experiments, and the load-test
temperature logs. Happy to provide any of these, test patches, or help
however useful.

Thanks

-- 
@gaojunwen

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-16 10:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CAL-my2=5V8Pk+R+aAoJ556-DFR-B0wnMLckRNDbAohdZvB15+Q@mail.gmail.com>
2026-09-15 21:46 ` [BUG] Redmi Book Pro 14 2024 (TM2307): fans never spin under Linux — root cause: EC gates fan engine on OSTP byte (tested workaround) Armin Wolf
2026-09-16 10:10   ` 高 俊文
2026-09-15 15:26 高 俊文

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®