Skip to content

soc: apple: mailbox: receive ASCWrap v8 mailboxes by interrupt - #1851

Draft
DjDeveloperr wants to merge 3 commits into
integration/aurorafrom
djdev/mailbox-v8-irq
Draft

DjDeveloperr wants to merge 3 commits into
integration/aurorafrom
djdev/mailbox-v8-irq

Conversation

@DjDeveloperr

Copy link
Copy Markdown
Contributor

Follow-up to #1844 and stacked on it: please review only the last commit, soc: apple: mailbox: receive ASCWrap v8 mailboxes by interrupt. After #1844 merges, this PR's diff is that one commit. Draft until a T8152 hardware row passes.

Why

ASC mailboxes are interrupt driven. #1844 makes the T6050 GPU mailboxes receive by interrupt like the other ASC mailboxes. The T8152 ASCWrap v8 GPU mailboxes still default to poll-only receive, and both of their DT nodes describe send-empty and recv-not-empty lines. This applies the same model to them, following the original Asahi ASC mailbox driver:

  • The recv-not-empty line is the threaded, oneshot GPU receive interrupt. apple_mbox_start() enables it and apple_mbox_stop() disables it.
  • The handler drains the post-office RX FIFO until it is empty, one receive budget per pass.
  • A non-atomic sender that finds the TX FIFO full waits for the send-empty interrupt and its completion.

Change

Removed:

  • the v8 receive poller and the poll-only default;
  • the storm guard;
  • the sleeping poll of a full TX FIFO;
  • the provider state and start/stop/removal paths that only served those;
  • the apple_mailbox.ascwrap_v8_rx_irq module parameter. Nothing in the tree sets it. A leftover one on a command line is ignored: silently with the driver built in, with a warning as a module.

Kept:

  • the wrapper, iop-vbar, post-office and PSD windows;
  • ascwrap_v8_cpu_control and the CPU start/stop it gates;
  • the PSD power check before every post-office receive.

The receive interrupt is only enabled when a consumer starts the mailbox. The G18 backend does that only after the PSD services read powered, and only with ascwrap_v8_cpu_control=1.

Comment-only updates: t8152-j873-gpu.dtsi and drivers/gpu/drm/asahi/g18/boot/mod.rs no longer mention the polling default. #1843's receive-poller fence would have nothing left to guard after this.

Testing

  • Code review and audit: independent review and pre-push audit.
    • The removed symbols and the parameter have no users left anywhere in the tree.
    • The KUnit header still builds.
    • The DT interrupt names match the driver's lookups.
  • Not yet run on a T8152 board. A hardware row is requested: boot with this change, check that the GPU mailboxes' recv interrupt counts rise in /proc/interrupts, run a GPU smoke test, and check for no storm, unbalanced-IRQ or GPU-timeout messages. This PR stays a draft until that row passes.

🤖 Generated with Claude Code

erikwb and others added 3 commits November 13, 2026 11:14
… fires

The T6050 GPU mailboxes receive by polling, because the recv-not-empty
interrupt does not reach the AIC on the 14-inch M5 Max MacBook Pro: a
25 us hrtimer for 1 ms after each send, otherwise a once-per-jiffy
poller, and the interrupt is never enabled. On the 16-inch M5 Max
MacBook Pro the interrupt works, and there polling costs about 5% of
GPU throughput in an inference engine's decode step.

Enable the recv-not-empty interrupt on these mailboxes again, and keep
both pollers running beside it until it has delivered a message. From
then on the fast poller stops and sends no longer arm it: the interrupt
receives, as on the other ASC mailboxes. The line is level triggered
and the GPU handler is oneshot, so a message that arrives while it runs
fires it again. Each mailbox start proves the line again.

The jiffy poller keeps running as a watchdog. Where the interrupt
delivers, the poller finds the FIFO empty. A message it does find was
not delivered by the interrupt (or its thread had not run yet): the
poller hands it on and clears the proof, so that the sends after it arm
the fast poller again until the interrupt delivers a message again. A
line that never fires keeps polling exactly as before. A line that
delivers once and then stops, or fires only spuriously, loses no
message: the watchdog takes one that it misses on a following pass,
normally the next, subject to workqueue scheduling and to its budget of
64 messages per pass.

The ASCWrap v8 storm guard now covers these mailboxes too: a line that
fires 1000 times in a row with nothing to read is disabled at the AIC
and receive falls back to polling.

The hardware flag rx_poll_only becomes rx_poll_until_irq. A full send
FIFO is still waited out by sleeping polls, without the send-empty
line, as before.

Tested with KUnit (arm64, QEMU, suite apple_mbox_g17_stall): new cases
cover proof by a delivered message, the watchdog taking the proof back
when the line is silent with a message queued, the storm guard, and
start and stop. They wait on what the pollers receive, and read state
after cancelling them or under rx_lock. On an M5 Max MacBook Pro (J716c,
whose interrupt fires), an inference engine's decode, two runs each
without and with this commit: GPU time of its verification pass 21.93 /
21.93 -> 21.02 / 21.04 ms, single-token decode 62.4 / 63.8 -> 66.4 /
67.2 tok/s, output identical; the GPU mailboxes' recv interrupts count
in /proc/interrupts, the watchdog took the proof back 64 times in ~100 s
of decode (each time the next message proved the line again), and the
storm guard did not trip.

Developed with Claude Code.
Signed-off-by: Erik Bourget <erik@ebourget.net>
ASC mailboxes are interrupt driven; T6050's GPU mailboxes now use the
same paths as the other ASCWrap v6 GPU mailboxes.

The three T6050 GPU compatibles (apple,t6050-ascwrap-v6,
apple,t6050-x1n1-ascwrap-v6 and apple,t6050-j775d-ascwrap-v6) describe
the ASC v4 mailbox block behind the ASCWrap v6 wrapper offset, as the
T8140, T8142 and T6040 GPU mailboxes do. Their hardware descriptions now
differ from those only in the wrapper windows, and they take the same
start, stop, receive and send paths:

 - the recv-not-empty line is the threaded, oneshot GPU receive
   interrupt (IRQF_ONESHOT | IRQF_NO_AUTOEN | IRQF_NO_SUSPEND), enabled
   by apple_mbox_start() and disabled by apple_mbox_stop();
 - its handler drains the I2A FIFO until it is empty, one receive
   budget per pass;
 - a non-atomic sender that finds the A2I FIFO full waits for the
   send-empty interrupt and its completion.

Remove what received them by polling instead:

 - the rx_poll_until_irq hardware flag (rx_poll_only before);
 - the 25 us receive hrtimer, its kick from apple_mbox_send() and its
   deadline;
 - the jiffy receive poller and its watchdog for these mailboxes, and
   the rx_irq_proven state;
 - the storm guard's extension to them;
 - the sleeping poll of a full send FIFO, which left the send-empty
   interrupt unused.

This undoes, for these mailboxes, the receive and send changes of
commits 43c6ca8 ("soc: apple: mailbox: receive T6050 GPU mailboxes
by polling"), a23755c ("soc: apple: mailbox: poll T6050 GPU
receive quickly while a reply is outstanding") and 41c359d ("soc:
apple: mailbox: receive T6050 GPU mailboxes by interrupt once it
fires").

The T8152 ASCWrap v8 provider keeps its receive poller, its poll-only
default, the ascwrap_v8_rx_irq parameter and its storm guard, unchanged.

Drop the KUnit cases that tested the removed receive polling. The
apple_mbox_g17_stall suite keeps its receive budget, send stall and
receive utilization cases. No exported interface changes.

Signed-off-by: Diljit Singh <hey@djdev.me>
ASC mailboxes are interrupt driven. The T8152 GPU ASCWrap v8 mailboxes
now receive and send the same way as the other ASC mailboxes do:

 - the recv-not-empty line, the threaded and oneshot GPU receive
   interrupt, is enabled by apple_mbox_start() and disabled by
   apple_mbox_stop();
 - its handler drains the post-office RX FIFO until it is empty, one
   receive budget per pass;
 - a non-atomic sender that finds the TX FIFO full waits for the
   send-empty interrupt and its completion. Both GPU mailbox nodes
   describe that line.

Remove the receive poller, the poll-only default, the storm guard and
the sleeping poll of a full TX FIFO, with the provider state and the
start, stop and removal paths that only served them. Remove the
ascwrap_v8_rx_irq module parameter: interrupts are the only mode, and
nothing in the tree sets it. A leftover
apple_mailbox.ascwrap_v8_rx_irq= is ignored, silently when the driver
is built in and with an "unknown parameter" warning when it is a
module, so a command line that still passes it keeps booting.
The J873 GPU dtsi and the G18 boot notes no longer mention it.

Keep what is not about polling: the wrapper, iop-vbar, post-office and
PSD windows, the ascwrap_v8_cpu_control parameter and the CPU start and
stop it gates, and the PSD check before every post-office receive. When
that check finds the block unpowered, the receive handler reads nothing.

The receive interrupt is enabled only when a consumer starts the
mailbox; the G18 backend does that only after the PSD services are
powered, and only with ascwrap_v8_cpu_control=1.

This has not been run on a T8152 board yet: the receive and send-empty
interrupt assignment of both GPU mailboxes needs a hardware check
before this is relied on.

Signed-off-by: Diljit Singh <hey@djdev.me>
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.

2 participants