Skip to content

hwmon: macsmc: Retry manual mode while the fan unlock settles - #696

Merged
RyanTheTide merged 1 commit into
aurora-wipfrom
fix/macsmc-stopped-fan-retry-t3834
Oct 31, 2026
Merged

RyanTheTide merged 1 commit into
aurora-wipfrom
fix/macsmc-stopped-fan-retry-t3834

Conversation

@RyanTheTide

@RyanTheTide RyanTheTide commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

A manual fan request now gets only one mode-1 write after unlocking, where the pre-#670 path retried it. This restores bounded EIO/EBUSY retries after Ftst=1, while still reading the mode before each attempt and never deliberately writing mode 1 while it reads 3. The target is written only after mode 1 succeeds; firmware keeps automatic policy until an explicit user request.

The KUnit model now covers a zero-target fan that temporarily refuses mode 1 after leaving system mode, permanent refusal with unlock rollback and no target write, and an already spinning firmware fan. Existing legacy mode-0, write-only mode, two-fan ownership, target-error rollback and lifecycle tests remain.

This is a candidate for the J616s stopped-fan EIO regression. Physical confirmation of the failing key and successful sequence is pending. The removed post-unlock retry is established by source comparison; delayed firmware write readiness is currently a test model, not a measured firmware fact. Keep this draft until that distinction is resolved.

Validation on commit aced8378a80667bca3cbd0ce626ff8a3613efd1a:

  • arm64 QEMU: the unchanged macsmc: Leave SMC policy to firmware and expose J616s/Neo thermal pressure #670 driver plus the new tests fails the delayed-acceptance and exhausted-retry cases (13/15 pass); the candidate passes 15/15 with no skips.
  • arm64 W=1 -j8 driver object compilation passes with zero warnings.
  • Build-source SHA256 values match the committed driver and test files. git diff --check passes; checkpatch reports zero errors/warnings (the SMC FourCC CamelCase style check is excluded).

Lead hardware verification, using approved exclusive fan access and the candidate kernel with its matching DTB:

  • Start with firmware ownership and target/tach zero. Trace Ftst, mode and target operations, request 2500 rpm, require target=2500 and repeated tach samples within 10%, then write zero and verify firmware ownership and target adjustment resume. Repeat for both fans and repeat the cycle.
  • Repeat from a fan already spinning under firmware control. Exercise both fans together and confirm releasing one does not clear the shared unlock until the last manual fan is released.
  • Repeat on T6000 M1 Pro; confirm the direct mode-0 and legacy write-only paths keep their existing behavior without unlock writes or retry delays.

Retain failed writes and rollback results. Roll back the kernel/DTB pair through the normal bootguard workflow if needed. No new parameter, DT change, autonomous fan policy, or persistent override is included.

The firmware-policy change kept the read-side wait for a fan to leave
system mode, but removed the bounded retry of the following manual-mode
write. An EIO from that first write now aborts the user request and
immediately relocks the fans. The previous path could retry it.

Keep the mode read before unlocking and before each attempt, and retry
EIO or EBUSY from the manual-mode write within the existing ten-second
unlock budget. Only write the target after manual mode succeeds. Other
errors still return immediately, and exhausted retries retain the last
error and release the unlock when no other fan is manual.

This does not reinstate the deliberately refused pre-unlock write or
autonomous fan policy. Direct legacy mode writes are unchanged.

Extend the KUnit model to reject manual mode temporarily after leaving
system mode, starting with a zero target. Cover eventual acceptance,
permanent refusal and relock without a target write, and takeover of an
already spinning firmware fan.

Fixes: cc3766d ("hwmon: macsmc: Leave fan policy to firmware until a user requests control")
Assisted-by: LLM
Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
@RyanTheTide

Copy link
Copy Markdown
Contributor Author

Tested on hardware in fleet12e (fleet12d 40e897c plus this PR, 7.3.0-aurora-fleet12e).

J616s, both fans, same machine:

case fleet12d (before) fleet12e
fan1 stopped, write 2500 EIO OK, reads 2525 after 12 s
fan1 spinning under manual, write 3000 EIO OK, reads 3016
fan1 hand back (0) OK OK, reads 0
fan2 stopped, write 2500 EIO OK, reads 2492
fan2 spinning, write 3000 EIO OK, reads 3002
both fans from stopped, 2500 EIO, EIO OK, OK, reads 2479 / 2508

Two things to know, neither a regression:

  • A manual write from stopped blocks for about 8.3 to 8.5 s before it returns, which is the retry loop waiting for the unlock to settle.
  • Taking a fan back within about 5 s of handing it to firmware still fails. Re-take after 1 s and 3 s returned EIO after about 13 s. After 6, 10 and 15 s it worked.

Rest of the J616s one-shot: k -p3 0, all -p3 0, no WARN/DART, all three DCPs bound, Touch ID restored, Wi-Fi/BT/dock LAN up, sinks muted, speakerguardd active. glmark2-es2-gbm 24819 off-screen. glmark2-es2-drm segfaulted in userspace on this boot with the dock now driving DP-1 and DP-3, unrelated to hwmon.

T6000 legacy path (M1 Pro, fleet12e): fan_control=N, fan1_target stays read-only, target 0, input 0, min 1499, same as fleet12d. k -p3 0.

Host tests: run-host-tests 154/154, apple-dcp selftests 81 ok, conv sweep 51 pass / 44 environment fails, the same set as fleet12.

fleet12e is now the default on the J616s and the M1 Pro.

🤖 Generated with Claude Code

@RyanTheTide
RyanTheTide marked this pull request as ready for review October 31, 2026 11:48
@RyanTheTide
RyanTheTide merged commit 23e431a into aurora-wip Oct 31, 2026
@RyanTheTide
RyanTheTide deleted the fix/macsmc-stopped-fan-retry-t3834 branch October 31, 2026 11:48
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.

1 participant