Skip to content

soc: apple: mailbox: do not poll a mailbox whose power domain a sleep took (T6050 s2idle panic with the GPU active) - #1843

Closed
axboe wants to merge 1 commit into
aurora-silicon:integration/aurorafrom
axboe:t6050-mbox-sleep-poll
Closed

axboe wants to merge 1 commit into
aurora-silicon:integration/aurorafrom
axboe:t6050-mbox-sleep-poll

Conversation

@axboe

@axboe axboe commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

On the K116s (16" M5 Pro, T6050) a suspend-to-idle entered while the GPU is in use panics in the noirq phase. With the console suspended that looks like a machine that never wakes: no key, power button or lid brings it back. In practice it is every suspend with the lid open (systemctl suspend, the menu's Sleep); a lid-close suspend works because the GPU has idled first.

With no_console_suspend and pm_test=platform:

apple-mailbox 2302600000.mailbox: PM: genpd_suspend_noirq returned 0 after 17 usecs
SError Interrupt on CPU6, code 0x00000000be000000 -- SError
Workqueue: events_highpri apple_mbox_v8_rx_poll_work
pc : el1_abort+0x40/0x64
x0 : 0000002302608114
Call trace:
 ...
 apple_mbox_poll_locked+0xa4/0x1e8 (P)
 apple_mbox_v8_rx_poll_work+0x4c/0x84
 process_scheduled_works+0x1a0/0x308
Kernel panic - not syncing: Asynchronous SError Interrupt

Cause: the T6050 ASCWrap v6 mailboxes are rx_poll_only. They receive from a delayed work on system_highpri_wq and from the fast hrtimer, and a system sleep stops neither. If the consumer (here the GPU) is runtime-active when the sleep starts, the PM core holds it active, so the mailbox stays started. In the noirq phase genpd powers the mailbox's domain off, and 22 us later the poller reads i2a_control of the unpowered block.

Fix: apple_mbox_suspend_noirq() marks the receiver asleep under rx_lock, so a poll in flight finishes before genpd goes on, and apple_mbox_poll_locked() returns without touching the registers until apple_mbox_resume_noirq() clears the mark. Every poll path (work, fast timer, apple_mbox_poll_one()) goes through that function with rx_lock held. The driver's noirq callback runs before genpd's power-off, so the order is right.

Tested on a K116s, 27.2 stub, Linux at EL2

Kernel integration/aurora aa68b3c plus my K116s series, with and without CONFIG_PM_DEBUG. Lid open, desktop session running.

without the change with it
pm_test=devices pass pass
pm_test=platform panic above pass, 3 runs
pm_test=platform with a GL workload running not reached pass (noirq suspend 487 ms against 103 ms idle)
real s2idle, lid open never wakes, 2 of 2 2 of 2: one woken by the space bar after a few seconds, one after 47 s
lid-close s2idle pass pass (9.9 s, woken by lid open)

After each resume the GPU renders correctly (an offscreen GLES scene matches its reference) and the kernel log has no aurora errors.

This branch is that commit cherry-picked onto a34d26c; it applied cleanly and I have not rebuilt it on that tip.

Notes

  • It merges without conflict with soc: apple: mailbox: arm the T6050 fast receive poller with an atomic flag #1739, which touches the same pollers.
  • I have not looked at whether a GPU that is runtime-active across an s2idle should be stopped properly by its own driver instead of having its domain cut under it. It recovered in every run here, but that may be luck with what the firmware was doing. This change only makes the mailbox safe against it.
  • Other poll-only mailboxes take the same path (apple_mbox_has_rx_poller(), so the ASCWrap v8 ones too). I only have a T6050 to test on.
  • checkpatch --strict: one warning, for the log lines quoted in the commit message.

… took

A poll-only mailbox (the T6050 ASCWrap v6 ones) receives from a delayed
work on system_highpri_wq and from an hrtimer. Neither is stopped by a
system sleep: the workqueue is not freezable. If the mailbox's consumer
is runtime-active when the sleep starts, the PM core holds it active,
the mailbox stays started, and in the noirq phase genpd powers the
mailbox's domain off under the poller. The next poll reads the control
register of an unpowered block and takes an SError:

  apple-mailbox 2302600000.mailbox: PM: genpd_suspend_noirq returned 0 after 17 usecs
  SError Interrupt on CPU6, code 0x00000000be000000 -- SError
  Workqueue: events_highpri apple_mbox_v8_rx_poll_work
   apple_mbox_poll_locked+0xa4/0x1e8 (P)
   apple_mbox_v8_rx_poll_work+0x4c/0x84
  Kernel panic - not syncing: Asynchronous SError Interrupt

On the K116s this is the GPU's mailbox, and it happens on every
suspend-to-idle entered while the GPU is in use, which is any suspend
with the lid open: the machine never comes back. With the lid closed
the GPU has idled and stopped its mailbox before the sleep starts.

Mark the receiver asleep in suspend_noirq, under rx_lock so that a poll
in flight finishes first, and have apple_mbox_poll_locked() leave the
registers alone until resume_noirq.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
@axboe

axboe commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Note on #1844 (interrupt receive for the T6050 GPU mailboxes), opened at the same time: the two touch the same function but merge without conflict in either order (checked with git merge-tree against its current head).

This change is still needed with #1844. The once-per-jiffy poller keeps running there as a watchdog, and it is that poller that read the unpowered mailbox in the trace above. The interrupt path of #1844 also receives through apple_mbox_poll_locked(), so it is covered by the same check. I have not run the two together.

@axboe

axboe commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

On @DjDeveloperr's note in #1844 about suspend: agreed. With #1844 the recv interrupt is live on these mailboxes and is IRQF_NO_SUSPEND, so its thread is a third reader after ps_gfx is gated, and with the rx_asleep check here it would count empty runs towards the storm guard.

This PR alone is not affected: today the line is never enabled on the T6050 ascwrap-v6 mailboxes, so the two pollers are the only readers.

For the order of landing:

I can build and run the combination on the K116s. I do not know yet whether the line fires on this board, so it may only exercise the "never fires" side.

@axboe

axboe commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Hardware run for the question in #1844: integration/aurora adb5a7e (with #1844) plus the K116s commits, without this PR, on the K116s (16" M5 Pro OLED, 27.2 stub, Linux at EL2).

  • 2302600000.mailbox-recv delivers (a few thousand interrupts within minutes of desktop use), so the GPU mailbox receives by interrupt here as on the J716c.
  • One s2idle cycle with the desktop running and the lid open, the case that panicked before: 18.1 s asleep, woken by a key, suspend_stats success 1, fail 0. No SError, no GPU recovery, and the mailbox keeps receiving after the wake.

With the T6050 pollers gone there is nothing left for this fence to guard on these mailboxes, so I am closing this. If the T8152 poller stays (i.e. #1851 does not go in) and someone sees the same read-after-power-off there, the fence could be revived with the poller-gated read @DjDeveloperr pointed out.

@axboe axboe closed this Nov 13, 2026
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