mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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®