Repository navigation
Thunderbolt: M1/M2 Pro display, M1 PCIe and resume recovery - #8
Conversation
A DP tunnel from the host router's DP IN adapter needs a pixel clock from the ATC's AUSPLL. Type-C DP alt mode sets it up together with the lanes; a tunnel has no lanes to set up, and the PHY stays in Thunderbolt/USB4 mode. Export apple_atc_dp_tunnel_rate(). It keeps the PHY blocks awake, enables DPTX PCLK1 with a per-rate selector and programs a fixed AUSPLL descriptor, without touching the lane mux. Rate 0 stops the clock: PLL output drivers off, then an APB power-down command. The sleep/clamp overrides and TX_DP_CTRL0 are left as they are; the next start programs them again. A start is refused while PLL outputs are live or a PLL request is pending, and DP alt mode configuration is refused while the tunnel clock runs, so the two never share the PLL. The clock is stopped before any PHY mode change. Only t8103 is supported: the descriptor and selectors are for that SoC. Name the TX/RX sleep and clamp value fields next to their override fields, and add include/linux/soc/apple/dp-tunnel.h for the functions the Thunderbolt glue, appledrm, the ATC PHY and the display crossbar call on each other. They are looked up with symbol_get(), so none of these modules depends on another. Based on Oliver Lukschander's t6020 tunnel clock work. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
When DCP retrains a link through a Thunderbolt DP tunnel, the crossbar connection has to follow it. Add apple_dpxbar_link_down() and apple_dpxbar_link_up(). They gate and ungate the clocks and enables of an already selected output. The mux selection is left alone; link_down() also leaves the ATC output enable set, and link_up() re-asserts it. The caller keeps the output selected around both; the selection is read under the crossbar lock. Also let the clock gates release before enabling the clocks behind them, both when an output is selected and in link_up(), and warn if they do not. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
On Apple silicon the display engine is not wired to the host router's DP IN adapters; the NHI glue has to route it there. Add an NHI op, dp_tunnel_changed, called when a DP tunnel from a host DP IN adapter comes up, before one is torn down, and when the connection manager stops with such a tunnel in place. Every "down" is paired with an earlier "up", so a tunnel released twice (at tb_stop() and by a late DPRX failure) is only reported once. System and runtime suspend release all DP tunnels through the normal teardown, so the glue hears about them; they come back through plug events after resume, which take the full path again. Only hosts whose glue provides the op get the extra handling, and only for their own DP IN adapters: - after activation, pulse the DP IN adapter's HPD propagation bit (ADP_DP_CS_3 bit 10) and wait for ADP_DP_CS_2_HPD, at most 2 s under tb->lock; - the DP IN video hop gets 5 NFC credits, including on USB4 routers; - no LTTPR non-transparent mode on Titan Ridge DP OUT; the host DPTX trains the sink through the tunnel; - the DP OUT adapter must not start link training on its own (ADP_DP_CS_3 bit 8) while the tunnel is up; the bit is restored on teardown, also when disabling the adapter fails. The check is safe for routers without a domain, as built by the KUnit tests. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
Implement dp_tunnel_changed. It is only registered when thunderbolt_apple.dp_display=1 is given and the machine is a t8103, so the connection manager's Apple DP handling stays off otherwise. When a DP tunnel from a host DP IN adapter comes up: 1. Map the adapter's register block non-posted; posted writes to it take an SError. 2. Acknowledge and enable its interrupts. 3. Ask appledrm to route a display pipeline to it. If appledrm is still probing (a dock present at boot), wait for it for up to 30 s. The adapter's DPTX_INACTIVE handshake is run from DCP's link activation (the adapter may only be woken while DCP drives the DPTX), within one 500 ms budget per call. Before a tunnel is torn down the adapter is put to sleep and masked synchronously, and nothing touches it after that. Each adapter has one work item on an ordered queue that brings the display side in line with the tunnel state, so nothing is allocated on the way down and whatever was handed to appledrm is always taken back. When the ACIO is stopped, the display side is released before it powers off. The parameter is read-only at runtime. Not covered yet: the DP IN block is found at a fixed offset from the ACIO "rc" region (there is no device tree node for it), its interrupts have no handler, and suspend with an active tunnel has not been validated. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
Add apple_dcp_tb_dp_tunnel() for the Thunderbolt glue. It picks a free display pipeline for the port and routes it to the crossbar's dpin0/dpin1 output. It then out-of-band connects DPTX with the DFP port (1/2) and the DP IN role (attribute bit 0), and reports the display as attached. During link setup: - SetLinkRate starts or stops the ATC tunnel pixel clock. - After DidChangeLinkConfiguration the crossbar connection is brought up and DP IN is activated. The first time this is the mux selection; after that only the clocks are brought back. - Before WillChangeLinkConfiguration DP IN goes inactive and the crossbar clocks go down. Failures are logged and keep the crossbar down, so no stream is started without a clock. Tunnel state, the clock and the crossbar are handled under one lock, so teardown cannot race a link change, and DCP calls never block on the mux. The lock (and hpd_mutex, which the tunnel path also reaches before the DRM device binds) is initialized at probe. While a tunnel owns a Type-C port, alt mode state for it is not acted on; the tunnel teardown drops the recorded state and reconnects a fixed HDMI output if one is live. The Type-C DP alt mode path is unchanged: DFP port 0, role 0 and a strict check of DCP's connection reply. Tested on a MacBook Pro 13" M1 (j293) with a CalDigit TS3 Plus and a Kensington SD5560T: 3840x2160 at 60 Hz over HBR2 and HBR3, unplug and replug, monitor cable replug behind the dock, and a dock present at boot. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
1c0dfa6 to
fead9c8
Compare
|
Updated the series after running two kernel review tools on it: the review-prompts Fixed:
Not changed: a few suggestions would change the register sequence that was validated on hardware:
Those are left as they are, with the reasoning in comments and commit messages. Suspend with an active tunnel is listed as not yet validated. Every commit builds on its own with no warnings and passes checkpatch. These fixes are build- and KUnit-tested only; the previous revision is the one that was tested on the hardware listed in the description. |
|
Hardware retest of this revision (fead9c8) on the MacBook Pro 13" M1 (j293), with a CalDigit TS3 Plus on the second USB-C port (ACIO1). The tests before this update all ran on the first port.
There were no warnings from the tunnel path. |
t8103 boots with the Thunderbolt PCIe port held in reset. Bring the port up when the tunnel activates, and do it before the port's IOMMU probes: that IOMMU's invalidate command does not finish while the port clock is still gated. Program the port tunables and the reset table, release PERST, enable the port clock, then program the root-port configuration tunables. Link training stays in the host driver. If the port is already running, the host does not replay the reset table. Endpoint memory on t8103 is left posted. The PCIe-C IOMMU uses the 64-stream USB4 register block: 16 KiB pages, a 32-bit IOVA and a 36-bit physical address. The 42-bit four-level geometry remains on T8110, which is the hardware that walks it. An xHCI early handoff no longer faults when the capability length read from a BAR is shorter than 16 bytes or not dword-aligned. Tested on a MacBook Pro 13" M1 (j293) with a CalDigit TS3 Plus on USB-1. The tunnel enumerated the dock bridges, four USB host controllers and an I210. The USB devices and a gigabit link came up, and the display on the same port still comes up. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
Cable removal quiesces the PCIe tunnel and then removes the IOMMU. The IOMMU's runtime resume and remove both issue a command, and that command cannot complete once the port clock is gated. Every dock unplug logged that timeout, then a follow-up quiesce skipped the port and reported success. Tell the IOMMU to stop issuing commands before the clock is turned off, and let it issue them again only after the port is back up. An acknowledgment timeout from a cable that is already gone is no longer a failed quiesce when the local port has left the running state. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
Some USB-C display adapters answer the first hotplug with a 128-byte EDID whose product name is "Non-PnP" and whose preferred mode is 1024x768. The panel timings, including 3840x2160 at 120 Hz, show up only after HPD drops and returns. macOS ends up with the panel mode. The first Linux modeset was keeping the placeholder. When a Type-C output copies that EDID, pulse HPD once. A second placeholder is left as-is, so a display that really is that mode does not loop. The pulse is cancelled when the cable goes away. Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
…kConfiguration Found via aurora-silicon/linux#8, a real hardware-tested reference implementation for a different SoC, built on Oliver's own earlier t6020 tunnel-clock work. Reverts 0120's wrong-mental-model DP-AUX approach entirely (phy-apple-atc.ko now byte-identical to 0119's known-good hash) and 0118's speculative supportsHPD changes, keeping only what the reference implementation confirms: attach a real PHY, and defer crossbar activation until DCP has actually set a link rate. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…figuration Found via aurora-silicon#8, a real, hardware-tested (three docks, multiple monitors) DisplayPort-over-Thunderbolt-tunnel implementation for a different SoC, explicitly built on this project's own earlier t6020 tunnel-clock work. It never touches DP AUX or any PLL-common register (0120's whole approach was the wrong mental model); the real difference is ordering: its Activate handler only wakes the DP IN adapter, and defers crossbar mux selection to DidChangeLinkConfiguration, gated on SetLinkRate having already started the tunnel pixel clock. Our own dptxport_call_did_change_link_config() already has this exact mechanism, already correctly gated on dptx->link_rate, with a comment that already states the right idea -- but dptxport_call_activate() also, unconditionally, brought up the crossbar and ACIO DPIN0 handshake immediately, before any link rate existed. This routed a real analog signal path through the crossbar with no pixel clock behind it every time, all session -- consistent with DCP's own AUX probe finding nothing coherent (INACTIVE_SINK_DETECTED, confirmed in the 0119 test) and never proceeding to SET_LINK_RATE, so dptxport_tunnel_clock() (already wired up correctly) never got a chance to run. Remove the eager call from Activate. Revert 0118's GET_SUPPORTS_HPD/ supports_hpd changes (the reference implementation keeps supportsHPD set for a tunnel route too; what actually distinguishes it is a separate role bit this driver doesn't have yet, not supportsHPD). Fully remove 0120's DP-AUX-enable additions -- phy-apple-atc.ko now hashes byte-identical to 0119's already-known-good build, confirmed. Keep 0118's PHY attachment and 0119's guard relaxation, both of which match the reference implementation's own pattern. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nect 0119, 0121 and 0122 all reached the identical INACTIVE_SINK_DETECTED/ DPRX-timeout outcome tonight despite substantially different Activate/ crossbar ordering -- pointing at a signal we are not sending at all rather than a timing issue reorderable on our end. The reference implementation (aurora-silicon#8) packs a "role" bit (0 = direct PHY, 1 = Thunderbolt/USB4 DP IN) into both validate_connection's and connect's attributes field, alongside supportsHPD. Our analog-DPIN path has never set it, always sending a plain direct-PHY value even though this is a genuinely USB4-tunneled connection. If DCP firmware's tolerance for a failed AUX probe depends on this bit, that would explain the consistent outcome regardless of ordering. Set it via dcp_is_usb4_output(), our existing equivalent of the reference implementation's dedicated dptx_tunnel flag, and relax validate_connection's reply check the same way theirs does (only the role bit is allowed to differ in the echoed reply). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The analog-DPIN USB4 connect path (dcp_dptx_connect()) has unconditionally called phy_set_mode_ext(dp_route->phy, PHY_MODE_DP, dcp->index) at connect time since candidate 0118, before DCP ever gets to ACTIVATE/SET_LINK_RATE. This is a genuine Thunderbolt tunnel, not a direct PHY connection -- both the aurora-silicon#8 reference implementation and this project's own tunnel-clock code (apple_atc_right_usb4_tunnel_rate(), gated on atcphy->mode == APPLE_ATCPHY_MODE_USB4) require the ATC PHY to stay in USB4/TBT mode for the whole connection. Switching it to DP mode reconfigures the SERDES lanes for direct DisplayPort signaling instead of USB4 tunneling. Traced while scoping a full PR#8 port: our own tunnel.c already polls the generic, non-Apple-specific DP_COMMON_CAP_DPRX_DONE hardware bit (tb_dp_dprx_start()/tb_dp_wait_dprx()) -- the same bit stuck at DPRX=0 in every capture through candidate 0125. That bit is set by the PHY hardware based on real AUX electrical activity, downstream of DCP's software protocol. Forcing the tunnel's PHY out of USB4 mode before that AUX/DPRX negotiation can complete is a plausible direct cause, independent of anything DCP-protocol-level (which 0124 already confirmed is clean end-to-end). The dptxport[bind].atcphy assignment is kept -- it only tells DCP firmware which PHY object to answer GET_MAX_LANE_COUNT against, and is unrelated to the PHY's own runtime mode. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Found while scoping the aurora-silicon/linux#8 port: the analog-DPIN connect path has switched the tunnel's ATC PHY into PHY_MODE_DP at connect time since 0118, in every candidate since. Both the reference PR and our own tunnel-clock code require the PHY to stay in USB4/TBT mode for a genuine tunnel. Also traced DPRX detection to a generic, non-Apple-specific mechanism in our own tunnel.c that polls a real hardware bit downstream of DCP's protocol -- forcing the PHY out of USB4 mode before that can complete is a plausible direct cause. Tested as a quick, low-risk fix before the much larger architectural port. Full reasoning in notes/2026-09-23-0126-stop-phy-mode-dp-switch.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t DP tunnel routing from aurora-silicon#8 Every candidate through 0126 relied on faking a USB4 tunnel route through the Type-C alt-mode mux-state machinery (dcp_typec_route_set() scoring a "usb4_xbar" candidate on a TBT-SVID mux notification) rather than a genuine "a Thunderbolt DP tunnel just came up" trigger. DCP's own AFK/EPIC protocol handling was already confirmed completely clean (candidate 0124: zero retcode errors, zero reply mismatches) through ACTIVATE, but nothing ever got DCP past that point to SET_LINK_RATE. Ported the real mechanism from aurora-silicon#8 ("DisplayPort and PCIe over Thunderbolt for M1 (t8103)", hardware-validated on a CalDigit TS3 Plus, Kensington SD5560T and CalDigit TS4), adapted from t8103 to T602X/j416s: - New cross-module interface (include/linux/soc/apple/dp-tunnel.h): apple_dcp_tb_dp_tunnel(), apple_atc_dp_tunnel_rate(), apple_dpxbar_link_up/down(), found via symbol_get() so none of the four modules requires the others to be loaded. - drivers/gpu/drm/apple/dcp.c: dcp_typec_route_activate()/deactivate() now take an explicit crossbar controller and defer a tunnel's mux selection to DidChangeLinkConfiguration instead of selecting immediately; dcp_typec_route_set() no longer creates tunnel routes from Type-C mux notifications, only tears down an alt-mode owner and ignores state while a tunnel owns the port; new apple_dcp_tb_dp_tunnel() entry point plus dcp_tunnel_crossbar_up/down()/set_rate()/dpin_activate() helpers (verbatim port, this side is SoC-agnostic); dcp_dptx_connect() collapsed from three USB4-specific branches (protocol-connect, analog-DPIN bind loop, lpdptxphy path) to the same single connect path used for a direct alt-mode PHY, differing only in dcp->dptx_dfp_port (0=dpphy, 1/2=dpin0/dpin1) and dcp->phy already being the route's own ATC PHY. Removed ~400 lines of superseded experimental scaffolding (dcp_usb4_arm_typec/auto_arm_work, dcp_usb4_protocol_connect, the analog-DPIN branch, lpdptxphy instantiation, and their module params). - drivers/gpu/drm/apple/dptxep.c: SetLinkRate/Activate/Deactivate wired to the new dcp_tunnel_*() calls instead of the removed dptxport_tunnel_clock()/dptxport_native_dpin(); WillChange/DidChange crossbar hooks moved into the apcall dispatcher, matching the reference's own structure; the ATC PHY is no longer switched to PHY_MODE_DP for a tunnel (already fixed standalone in 0126, folded in here); dptxport_remote_target() drops the DPIN target field, using the same plain CORE|ATC|DIE|CONNECTED encoding as a direct PHY. - drivers/thunderbolt/apple.c: the confirmed-ineffective dpin_aux "analog AUX serializer" mechanism (2026-09-21 candidates 0054-0056, reconfirmed 2026-09-23 candidate 0125 after everything else was independently fixed) is replaced by a new apple_dpin_ctx/ apple_dpin_connect() mechanism, reusing this file's own confirmed- working DPTX_INACTIVE handshake (apple_dpin_handshake(), unchanged) generalized to whichever DP IN adapter (0 or 1) a tunnel actually lands on. Wired into the *existing* dp_tunnel_pre_activate/ post_activate/deactivate hooks (already safely integrated into tunnel.c's tb_dp_activate() at the right lifecycle points) rather than adding the reference's own separate dp_tunnel_changed NHI hook, so this needed zero changes to shared Thunderbolt connection-manager code (drivers/thunderbolt/{tb,tunnel}.c are untouched, byte-identical thunderbolt.ko). The connector_np graph lookup (ACIO port@1 -> the Type-C PD controller's connector node) needed no device-tree change: confirmed present on this exact hardware by walking the live phandle before writing any code. - drivers/phy/apple/atc.c: apple_atc_right_usb4_tunnel_rate() renamed to apple_atc_dp_tunnel_rate() to match the reference's cross-module symbol name, keeping this project's own T602X-specific implementation (the reference's own version hard-fails off t8103's fixed AUSPLL descriptor); now also accepts TBT mode, not just USB4. - drivers/mux/apple-display-crossbar.c: apple_dpxbar_right_dpin0_bring_up() (kept, unchanged) generalized into apple_dpxbar_link_up()/link_down(), parameterized on whichever index/dispext is actually selected instead of always dpin0/source-2, for dcp_tunnel_crossbar_up/down()'s re-link path. drivers/gpu/drm/apple/iomfb_template.c: one leftover reference to the removed route->usb4_xbar field (right_frame_snapshot(), a diagnostic) fixed to use route->active_xbar ?: route->xbar. usb4_native_dpin/usb4_protocol_probe/dcp_usb4_native_route() are left in place: still load-bearing in iomfb.c/iomfb_template.c/apple_drv.c for USB4-tunnel-specific swap-completion and CRTC-candidate logic outside this port's scope, and dcp_is_usb4_output() (which they compose with) still correctly reflects route->tunnel under the new mechanism. Full reasoning, the two-agent scoping analysis, and per-file porting checklists in the asahi-j416s-display repo (not committed here -- scratch analysis, not project history). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ux#8 Full architectural port after 0126's quick fix landed a clean negative. Every candidate through 0126 relied on faking a USB4 tunnel route through Type-C alt-mode mux-state notifications, never a genuine tunnel-came-up trigger -- DCP's own AFK protocol was already confirmed clean end-to-end through ACTIVATE (0124), but nothing ever got it further. Spans dcp.c/dptxep.c, drivers/thunderbolt/apple.c (reusing this project's own existing, already-safe hooks instead of the reference's separate NHI op -- zero shared Thunderbolt code touched), atc.c and apple-display-crossbar.c. Full reasoning in notes/2026-09-24-0127-port-thunderbolt-dp-tunnel-routing.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ported from aurora-silicon#8 (t8103, hardware-tested on three docks/multiple monitors: CalDigit TS3 Plus, Kensington SD5560T, CalDigit TS4). Its dp_tunnel_changed() pulses ADP_DP_CS_3_HPD_PROPAGATE on the DP IN adapter right after tunnel activation and waits for ADP_DP_CS_2_HPD -- an Apple host's DP IN adapter has no real physical DP connector wired to it, so nothing else ever sets that bit, and every downstream USB4 DP tunnel mechanism (AUX/DPCD, DPRX) is gated on it. Found by comparing this project's own driver against that reference: our port (0127) deliberately reused the existing dp_tunnel_pre/post_ activate/deactivate hooks instead of the reference's separate NHI op to avoid touching shared tb.c/tunnel.c -- but in doing so, this one specific register-level step from the same commit was never carried over. Confirmed absent: zero references to ADP_DP_CS_3_HPD_PROPAGATE, tb_dp_tunnel_notify, or an HPD-propagate pulse anywhere in this tree before this commit. This project's own diagnostic poller (apple_dp_aux_work(), drivers/ thunderbolt/apple.c) independently samples the DP IN adapter's CS0-CS13 registers every 500ms and logs any change; across all four dcpext1 failures so far (0128 x2, 0129, 0130 -- 96 samples total) it logs zero changes, versus exactly one (the DPRX transition) on the one dcpext0 success (0127). That is consistent with the adapter's AUX engine never being kicked into motion at all on this pipeline/port, which an unpropagated HPD is a plausible, concrete explanation for. Added tb_dp_apple_pulse_hpd(), called from tb_dp_activate() right before this project's own dp_tunnel_post_activate hook (so the DCP glue routes a display only after HPD has actually propagated, preserving the reference's own ordering even though our hook lives one level deeper than its dp_tunnel_changed callsite). Gated on tb_nhi_is_apple() (already used elsewhere in this file) and tb_port_is_dpin(), both pre-existing checks -- zero effect on non-Apple hosts or non-DP-IN tunnels. A failed pulse is logged and the tunnel setup continues regardless, matching the reference's own non-fatal handling. Deliberately not ported this candidate: the reference's ADP_DP_CS_3_ NO_AUTO_LT hold-off on the DP OUT (hub) adapter, and its 5-NFC-credit override for the DP IN video hop. Both are real, separate pieces of the same hardware-tested commit, but this keeps the current test to one variable; see notes/2026-09-24-0131-*.md for the reasoning and what they would target if this alone is not enough. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…silicon/linux#8 Comprehensive comparison against the reference PR (t8103, hardware-tested on three docks/multiple monitors), done at Oliver's request. The DCP-side port (0127) already matches closely. But its Thunderbolt-side commit does one more thing in generic tb.c/tunnel.c, gated behind an Apple-host check, that never got carried over: pulsing ADP_DP_CS_3_HPD_PROPAGATE on the DP IN adapter and waiting for ADP_DP_CS_2_HPD, because an Apple host's DP IN adapter has no real physical connector wired to it. This lines up exactly with the CS0-13-never-changes finding logged after 0130 -- an unpropagated HPD directly explains registers that never move. Also corrects the "currently installed" trailer, which had drifted after logging 0130's confirmed result. Full comparison and reasoning in notes/2026-09-24-0131-pulse-hpd-propagation-apple-host-dpin.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…Apple host) Direct follow-up to 0131. That candidate ported the HPD-propagate pulse from aurora-silicon#8 alone: HPD now confirmed propagates ("Apple: HPD propagated"), but DPRX still never asserts, and the failure shape is otherwise identical (DEVICE_NOT_RESPONDING/DEVICE_NOT_STARTED at ~5s, "DPRX timeout, keeping DP tunnel" at 12s). Ports the other two pieces of the same hardware-tested commit (4a7fd72), held back from 0131 to keep that a single-variable test: - ADP_DP_CS_3_NO_AUTO_LT on the hub's DP OUT adapter while the tunnel is up, in tb_dp_activate(). Without it, the hub is free to run its own link training at the same time our host DPTX tries to train the sink through the tunnel -- a plausible, concrete reason AUX/DPCD would never produce a coherent reply even after HPD is asserted correctly. - 5 NFC credits for the DP IN video hop, in tb_dp_init_video_credits() (this project's own captures have shown credits=1/credits=0 on this hop every run; the reference fixes it at 5 for any Apple host DP IN adapter). Both gated on tb_nhi_is_apple() + tb_port_is_dpin() (the same checks 0131 already introduced), plus !tb_route() for the credits hop-iteration case specifically (multiple hops are visited per path there, unlike the tunnel-endpoint-only pulse/NO_AUTO_LT code, so the extra host-router check guards against ever matching a downstream port by coincidence). Zero effect on non-Apple hosts or non-DP-IN tunnels either way. Full reasoning in notes/2026-09-24-0132-*.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nfirmed HPD fix
0131's HPD-propagate pulse is confirmed working on real hardware ("Apple:
HPD propagated" fires correctly) but wasn't sufficient alone -- DPRX still
never asserted, monitor still dark. Ports the other two pieces of the same
hardware-tested aurora-silicon/linux#8 commit, held back from 0131
specifically to isolate the pulse as its own test: NO_AUTO_LT on the hub's
DP OUT adapter (stop it racing its own link training against our host's),
and 5 NFC credits for the DP IN video hop (ours has read 1/0 every run).
Full reasoning in notes/2026-09-24-0132-*.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… a correction 0132's HPD-propagate + NO_AUTO_LT changes applied cleanly but DPRX still never asserted -- Oliver confirmed, monitor still dark. Also corrects the record on 0132's video-hop credit change, which targeted port-level NFC buffer bookkeeping (hop->nfc_credits) rather than the hop table's own initial_credits field that apple_dp_dump_hop() actually prints -- harmless but not the fix it was described as, and not relevant to AUX/DPRX anyway. The full aurora-silicon/linux#8 Apple-host register comparison is now exhausted without a picture. DCP's own ~5-second wait before DEVICE_NOT_ RESPONDING/DEVICE_NOT_STARTED has been unmoved by every host-side change across eight connect attempts. 0133 is a pure diagnostic (zero behavior change): dumps the ACIO analog block every 500ms instead of once at the end, to finally see whether its internal state ever moves during DCP's own attempt -- evidence this project has never actually gathered. Full reasoning in notes/2026-09-24-0133-*.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…lved upstream for any Apple Silicon chip The write-1-to-clear ack fired exactly as designed and had zero effect (0x80000000 before and after); failure shape unchanged, Oliver confirmed still no picture. That specific hypothesis is closed. Web research (not previously done this project): Sven Peter's actual upstream Asahi Linux Thunderbolt series (covering this exact SoC family, t8103/t600x/t8112/t602x) explicitly states DisplayPort tunneling is not yet implemented -- "requires additional work and reverse engineering that is not done yet." The only place DP tunneling has ever been shown working on real Apple Silicon hardware is aurora-silicon/linux#8, for t8103 (M1) specifically, a different SoC generation than this machine. Ruled out along the way: CONFIG_RESET_APPLE_CIO is enabled, this project's own driver already correctly deasserts the ACIO reset controller, and the ACIO's Cortex-M3 coprocessor is confirmed alive via RTKit. This reframes the effort: not a missed foundational piece, but genuinely unsolved territory for this chip generation. Full context in notes/ACTION-LOG.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
0136 installed and confirmed on hardware: the -22 crossbar failure is gone (captures/2026-09-24-0136-boot-kernel.log shows a real "Switched dpin0 to dispext0,0" enable, no crossbar-up failure, DPRX_DONE=1 reached, SET_ACTIVE_LANE_COUNT 4 accepted) -- but dcp_dptx_connect still timed out waiting for link configuration. Root-caused that timeout: dptxport_call_set_active_lane_count() only completed linkcfg_completion for a USB4 tunnel if dcp_usb4_drm_allowed() (usb4_force_dptx) was true, a flag with no way to ever be set true since commit 0dc9f50 removed the old manual-training sysfs knob that used to set it, without removing this now-dead gate. The hardware-validated aurora-silicon/linux#8 reference completes linkcfg_completion here unconditionally. Every USB4-tunneled connect attempt since 0127 has been structurally unable to complete this wait -- a fourth, independent defect alongside the port/pipeline confound, the crossbar -22, and dcpext1's own firmware-silence problem. Fixed and built in linux-aurora-pr (branch j416s-usb4-dpin, commit 992ff65b5, not pushed -- no origin tracking ref for this branch, matching every prior candidate). scripts/manage-0137.py stages the same module set as 0135/0136 except a rebuilt appledrm.ko. check already run (no sudo); install needs sudo and a reboot to test, not yet run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… count dcp_dptx_connect()'s wait_for_completion_timeout() on linkcfg_completion is now shared by both the alt-mode and USB4-tunnel connect paths (since 0dc9f50's port from aurora-silicon#8). For a USB4 tunnel, dptxport_call_set_active_lane_count() only completed it if dcp_usb4_drm_allowed() (usb4_force_dptx) was true -- a flag that used to be a live, writable knob (module_param_cb usb4_dptx_train) for a manual training workflow that 0dc9f50 removed wholesale when apple_dcp_tb_dp_tunnel() replaced it with automatic tunnel detection. usb4_force_dptx itself, and this gate, were left behind with no way left to ever set it true. Confirmed on real hardware (candidate 0136, right port, dcpext0 forced via usb4_route_prefer_fixed_diag): request_display succeeds, the crossbar selects cleanly (0136's own fix), DPRX_DONE=1 is reached, and SET_ACTIVE_LANE_COUNT 4 is accepted -- but dcp_dptx_connect() still times out 8s later, because linkcfg_completion is never completed (firmware does not send FORCE_HOTPLUG_DETECT, the only other completion site, for a tunnel). This has been happening on every candidate since 0127. The reference completes linkcfg_completion here unconditionally whenever lane_count > 0, with no such gate. usb4_lane_completion (also USB4-specific, always completed alongside the gated linkcfg_completion call) has no wait_for_completion() anywhere in this tree -- a fully dead completion. Match the reference: complete linkcfg_completion unconditionally, and remove the now-fully-dead usb4_force_dptx / dcp_usb4_drm_allowed() / usb4_lane_completion. Built and verified (make in src/appledrm/, vermagic 7.1.12-2.5-1-ARCH, no new warnings). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
tb_dp_activate(tunnel, false) returns early on tb_dp_port_enable() failure for either port. When a physical unplug tears down a DP tunnel, tb_handle_hotplug() calls tb_sw_set_unplugged() on the departing switch before tb_free_invalid_tunnels() -> tb_tunnel_deactivate() runs, so tb_dp_port_enable(dst_port, false) hits tb_port_read/write's "if (port->sw->is_unplugged) return -ENODEV" short-circuit -- a deterministic, zero-I/O failure, not a hardware timing issue. That trips "if (ret) return ret;" before ops->dp_tunnel_deactivate() ever runs. On this hardware, ops->dp_tunnel_deactivate is apple_nhi_dp_tunnel_deactivate() (drivers/thunderbolt/apple.c), which is the only place that clears apple_dpin_ctx's "alive" latch. With it skipped, "handed" never clears either, so a fresh dp_tunnel_post_activate() on a later replug hits apple_dpin_work_fn()'s "if (c->handed) return;" guard and never re-enters apple_dcp_tb_dp_tunnel() -- the physical tunnel reforms but DCP's own connect flow is never re-armed. Confirmed: a live unplug/replug during this session's testing produced a fresh Thunderbolt tunnel (new device enumeration, "DP tunnel paths up") but zero new dcp_dptx_connect/ request_display/"display routed" log lines. tb_tunnel_deactivate() (this file's only caller of tunnel->activate on the deactivate path) already discards the return value entirely, so nothing observes tb_dp_activate()'s return code when active=false. Change both "if (ret) return ret;" checks to "if (ret && active)": the activate (active=true) path is byte-for-byte unchanged, and on deactivate this guarantees ops->dp_tunnel_deactivate() always runs regardless of whether the departing port's register I/O could still succeed. The reference (aurora-silicon#8) doesn't have this gap: it notifies through a dedicated, unconditional tb_dp_tunnel_notify() called before any register I/O, not folded into the generic activate/deactivate register-programming path this tree uses. Built and verified (make in src/thunderbolt/, vermagic 7.1.12-2.5-1-ARCH, no new warnings; thunderbolt_apple.ko unchanged). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add a second mux-control entry (index 1) per Type-C PHY crossbar to both dcpext0's and dcpext1's mux-controls/mux-control-names, named "typecN-usb4" alongside the existing "typecN" (direct alt-mode) entry. These are the devicetree handles the display crossbar driver resolves by name to select a USB4/Thunderbolt DP tunnel route (dpin0/dpin1) rather than a direct Type-C alt-mode route, on T602X (M2 Pro) j414/j416 machines. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… display With only the SoC checks widened, a Thunderbolt display on the MacBook Pro 14" M1 Pro (j314s) got as far as an active DP IN adapter. DCP then stayed silent for 5 s after Activate, every DPTX call timed out, and it reported link faults 22 and 24 without ever sending SET_LINK_RATE. All three Type-C routes of j314s use dcpext1 (apple,typec-mux-indices = <2 2 2>), while the DP IN output idles at dispext0. Point the output at the pipeline that takes the tunnel and wake the ATC's DP clock path before the DPTX connect, and put the output back at its idle source when the route goes away without the crossbar having come up. Both helpers return -EOPNOTSUPP where they do not apply, so t8103 and T602X behave as before. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Christian Bartels <christian@thebartels.de> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> [Chris Kearney: ported onto aurora-silicon#8 on top of the dual DP tunnel series; the tunnel is prepared once its slot is taken.] Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
The M1 Pro/Max ATC has the t8103 DP IN adapter registers, the same
crossbar and the same tunnel pixel clock sequence. Install the DP tunnel
hook there too, and clear the DP IN interrupt status the way t8103 does.
Tested on a MacBook Pro 14" M1 Pro (j314s) with an LG UltraFine 5K on
both left ports: 3840x2160@60 at cold boot, on hotplug and after
suspend-to-idle. t6001 is untested.
apple-display-crossbar 70304c000.mux: dpin0: source preselected, MUX_CTRL=00002002
phy-apple-atc 703000000.phy: DP tunnel open (CFG0=11833fef SLEEP_CTRL=15570cff TX_DP_CTRL0=0000e00d)
apple-dcp 28cc00000.dcp: display routed to Thunderbolt DP tunnel dpin0
apple-dcp 28cc00000.dcp: DPTXPort: SET_LINK_RATE 0x14
apple-display-crossbar 70304c000.mux: Switched dpin0 to dispext1,0
apple-dcp 28cc00000.dcp: dcp_hotplug() connected:1 valid_mode:0 nr_modes:5
The second DP tunnel of the display is still refused ("port already
routed"), so it runs as a single 4K stream, not as two 5K tiles.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Christian Bartels <christian@thebartels.de>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
[Chris Kearney: ported onto aurora-silicon#8, where dp_display
defaults to on; t600x takes that default too.]
Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
iomfb_poweroff() waits 50 ms for the clear swap and sets dcp->crashed when that times out. When a Thunderbolt display is unplugged, the firmware is busy powering the external pipe down on its own and answers the swap a little later. Nothing logs the timeout, but from then on dcp_crtc_atomic_check() fails every commit with -EINVAL, so a replugged display stays dark until reboot: [CRTC:73] atomic driver check failed A real firmware crash is reported through the RTKit crash callback. Wait 500 ms, warn on a timeout and carry on with the power-off. Seen on j314s with an LG UltraFine 5K: unplug, then replug. With this change the unplug logs "dcp_poweroff() done" and the display comes back on replug. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Christian Bartels <christian@thebartels.de> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> [Chris Kearney: ported onto aurora-silicon#8, where DjDeveloperr's "preserve Type-C routes across blanking and detach" already stopped setting crashed but returned early; this carries on with the power-off. This is also the DCP unplug wedge Oliver Lukschander reported on #8.] Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
The per-port Type-C connectors carry DisplayPort (DP alt mode or a Thunderbolt/USB4 DP tunnel), but were registered as DRM_MODE_CONNECTOR_USB, which DRM reserves for USB display adapters (gud, appletbdrm). Userspace keys on the type: systemd-logind only counts VGA/DVI/DP/HDMI/TV connectors as external displays, so a docked lid close suspended the machine instead of honoring HandleLidSwitchDocked=ignore. Register them as DisplayPort. The driver's internal "is Type-C" checks use dcp->connector_type / fixed_connector_type and are unaffected. Connectors are now named DP-N instead of USB-N. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: RJ Skerry-Ryan <rryan@alum.mit.edu>
A Type-C port's encoder spans every pipeline that can drive the port, and routing narrows its possible_crtcs to the pipeline actually chosen, relying on userspace to re-read them on the following hotplug. Compositors that read possible_crtcs once when the connector appears (aquamarine, used by Hyprland) never see that. With a USB4 dock carrying two streams, whichever connector connects first takes the lowest free CRTC. When that is the DPIN1 connector, it gets dcpext0's CRTC while the stream is routed to dcpext1, every modeset fails the atomic check with -EINVAL, and both dock displays stay dark until the dock is replugged and happens to connect in the other order. possible_crtcs is meant to be static. On the dual-stream machines (J414s, J416c): - Fix the DPIN1 connector to the lowest-indexed Type-C-only pipeline (dcpext1), where DPIN1 is always routed, and route DPIN1 only within the connector's possible_crtcs. - Leave the primary connector spanning all its pipelines and stop narrowing or restoring possible_crtcs at runtime. - Route direct DP-alt displays to the lowest free CRTC, which is what a compositor picks from the port's fixed possible_crtcs, instead of steering them away from dcpext0. A direct DP-alt display now takes dcpext0 when it is free, so a single-stream dock on another port lands on the next free pipeline. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: RJ Skerry-Ryan <rryan@alum.mit.edu> [Chris Kearney: ported onto aurora-silicon#8. dcp_typec_dual_stream() is apple_dp_tunnel_t602x() here, so j414c and j416s are dual-stream too; they share the j414/j416 device tree and the dcpext0/dcpext1 layout.] Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
|
New head Two displays through one dock on every M2 Pro/Max laptop (DjDeveloperr's #46, 6 commits):
Thunderbolt display on M1 Pro/Max (@cb2206's #64, 5 commits): t600x runs the t8103 tunnel clock and crossbar flow, with the DP IN source preselected before DCP probes AUX. His clear-swap fix (wait 500 ms, warn, carry on with the power-off) replaces #46's early return. That's the DCP unplug wedge from Oliver's report. From rryan's #50: Type-C connectors are Tested: the head builds, and it boots on a J313 with dock displays on, both CIO controllers bound,
|
Pin linux-aurora 7.1.12.aurora2-11.17, which adds to 11.16: - two independent displays through one dock on every M2 Pro/Max laptop (DjDeveloperr's #46, ported onto aurora-silicon#8), with live USB3 bandwidth accounting so the second tunnel is admitted; - Thunderbolt display on M1 Pro/Max (cb2206's #64), and a clear-swap timeout at power-off no longer wedges the display until reboot; - Type-C display connectors reported as DisplayPort (DP-N), so a docked lid close does not suspend, and fixed possible_crtcs for the second stream, which Hyprland reads once (rryan's #50); - Touch ID enrol and verify refused with EROFS instead of wedging the enclave when xART writes are off (aurora-silicon#69); - EDIDs longer than the base block announces are accepted (#67). Type-C display connectors are now named DP-N instead of USB-N. The other packages are unchanged from 11.16. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwdG63dRaMrRbYrUBkSa1i
Resolves the conflicts with the T8140 PCIe root-port bring-up (AsahiLinux#151). Both sides only add: this branch's PCIe-C tunnel state and properties (resets, apple,pciec-kernel-init, apple,tunable-*) and the T8140 PIODMA bootstrap (apple,piodma, map_bus gating, Neo enumeration) are all kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwdG63dRaMrRbYrUBkSa1i
|
Merged aurora-wip Status of the two related PRs:
|
|
Rerun of
Works
New: a hub replug can take 14 s instead of 2–3 s This happened on 2 of 3 replugs:
Result: pictures 13.8–14.1 s after the Thunderbolt attach. In the replug where Why it can't recover sooner, from reading the code:
This is the same wait as the
Two side effects of the first-come pairing
|
|
Run of The kernel is built from a tree whose #8 Thunderbolt code is identical to Boot with the LG attached
Unplug and replug
s2idle, 22 s, LG attached
|
On the M2 Pro/Max 14" and 16" laptops (J414s/c, J416s/c) the Type-C ports share the external pipelines: dcpext0 (which also drives HDMI) and dcpext1, plus dcpext2/3 on the M2 Max boards. Since "drm/apple: Keep dual-stream Type-C possible_crtcs fixed", every port's connector offers all of them. Compositors read possible_crtcs once and pair connectors with CRTCs themselves: aquamarine (Hyprland) walks the CRTCs in index order and gives each to the first connected connector, in connector order, that can use it. The fabric instead hands out pipelines in whatever order the Type-C and Thunderbolt events arrive. That is a regression from the commit above on a J416c with two direct DP-alt monitors at boot: when port 1's event was handled first, port 1 took dcpext0 and port 0 dcpext1, and Hyprland paired them the other way round. Each connector's modes were then checked against the other monitor's list, native modes failed the atomic check with -EINVAL, and only modes both monitors share could be set. fbdev, which pairs every connected display afresh on each hotplug, and a dock's DPIN0 stream attaching after a direct display cross the same way. Until a compositor owns the display, keep the routes equal to that pairing computed from scratch: pipelines in CRTC index order, each to the first stream that wants one and has it in its possible_crtcs, with the primary connectors in port order ahead of the DPIN1 ones. A hybrid pipeline whose HDMI output is live is left to it, unless a tunnel holds it. A direct DP-alt stream wants a pipeline while its sink asserts HPD, as only then can its connector read connected. Only direct routes move, each to exactly its planned pipeline. A Thunderbolt tunnel never moves once set up. A direct stream planned onto a pipeline a tunnel holds stays unrouted and reads disconnected, since putting it anywhere else would have the compositor cross it with another display; it is then left out and the pass re-run, so the streams after it are not planned one pipeline off. A move is a disconnect and reconnect: every route that moves is taken down before any comes up, so two never share a pipeline, HPD is replayed on the new pipeline, and the hotplugs make fbdev and userspace re-probe. The pass runs on every DP-alt and tunnel attach, detach and HPD change, when HDMI is plugged in while a Type-C route has its pipeline, once DRM is registered, and from postclose when a file that was DRM master is closed; drm_release() has taken that file off the file list by then. A compositor owns the display while any open file has been DRM master: it pairs its connectors when it starts and keeps that pairing across a VT switch, where it drops master but keeps the device open. Until the last such file is closed routing stays as it was, the lowest free pipeline on DP entry with preferred_route honoured, and nothing moves. The check walks the file list under filelist_mutex, taken inside the fabric lock; nothing takes the two the other way round. cd321x does not report an unchanged DP state again, so a port left without a pipeline used to stay dark for the session. When a route lets its pipeline go while a compositor owns the display, such a port now goes back to the pipeline it last had if that is free, as the compositor keeps a reconnected connector's CRTC, and otherwise takes the lowest free one, the CRTC it gives a newly connected connector. Hotplug and retrain work queued for a Type-C connector can run after its route is gone and connector->dcp is NULL; check for that instead of dereferencing it. possible_crtcs stay static, since compositors read them only once, and the DPIN1 connector stays fixed to dcpext1. Single-stream machines take none of the new paths. Signed-off-by: Chris Kearney <chris@kearneymail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FwdG63dRaMrRbYrUBkSa1i
|
Added 581d7e3, "drm/apple: route Type-C displays in compositor pairing order". It fixes a regression from "Keep dual-stream Type-C possible_crtcs fixed", which this branch carries: on J414/J416, two monitors plugged straight into two USB-C ports at boot could each be paired by Hyprland with the other's pipeline, leaving both on the one mode they share.
It ships in iconidentify/aurora-linux 11.23. It's boot-tested for regressions on M1, but not yet run on M2 Pro/Max hardware, so J414/J416 test reports are very welcome. |
j416c (MacBook Pro 16" M2 Max) results for
|
|
j314s (14" M1 Pro) report with a TB4 dock-monitor, the Dell U4025QW, on
Tested with the help of Claude Code. |
|
@rryan thanks, I tried your Setup: #8 at
No hard reset or link failure with the t8103 order on t600x. So my separate T600x sequence (tunables before APPCLK, Intr2AXI pulse, modelled on #50) isn't needed, and I'll drop it. Your resume guard wasn't exercised: the tunnel survived the sleep. What t600x still needs is the device tree, which j314s's DT doesn't have yet. I add it at runtime for now:
If that's useful, I can send a t600x DT commit like your |
Great to hear! Feel free to open a PR against https://github.com/rryan/linux/tree/j416c-pr8 if you'd like. |
Or actually, @iconidentify could you recommend the best path forward? I have added more commits to my branch that fix some more issues I am having but may be out of scope for this PR:
|
|
@rryan one thing I only saw after my last comment: iconidentify/aurora-linux 11.32+ already has PCIe-C cold init for T600x and T602x, from Wesley Grimes's work (iconidentify#10):
Ports whose DART has no tunables are refused, so the device-tree values matter. 11.34 adds an ASPM L1 replug fix for these tunnels on top (iconidentify#15). On j314s, 11.34 does everything your commit plus my runtime DT did: boot with the LG attached, replug including with idle USB, One correction to my comment above: 11.32's t600x DART values aren't your J416c ones. They're |
|
For anyone with an LG UltraFine 5K: it now runs at full 5120x2880@60 on a 14" M1 Pro, with iconidentify#22 on top of the Thunderbolt display code here.
|
A dock unplug while receiver discovery is pending cancels the worker and releases its tunnel reference, but omits the callback that owns a domain reference. The M3 Type-C worker then waits indefinitely in apple_nhi_remove, blocking subsequent events on that port. Observed on J516S with a TS3 Plus. Backport the serialized cancellation and callback lifetime fix from Aurora PR aurora-silicon#8. Drain DPRX before tb_stop releases router ports, complete cancellation once, and release worker references under the domain lock. The M3 tree's existing host notification API is retained via a small DPRX-only helper. Carry both upstream KUnit cases for pending and running cancellation. Source: iconidentify@477d56b Source: iconidentify@d0bc506 Related: iconidentify/m3-roadmap#59 Signed-off-by: Chris Kearney <303316+iconidentify@users.noreply.github.com>
…-20260927 Integrate September 27 M3 GPU, display and device fixes
Preserve the original review commits and retain subsequent published repairs where superseded. Contributor credit; Signed-off-by outstanding: - 99a5545: Chris Kearney <303316+iconidentify@users.noreply.github.com> - b4e5e4c: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 508384b: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 46b9e80: Oliver Lukschander <oliver.lukschander@golf.at> - b9a6a94: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 749ac04: Chris Kearney <303316+iconidentify@users.noreply.github.com> - d04e476: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 67fdc27: Chris Kearney <303316+iconidentify@users.noreply.github.com> - cf5f7d1: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 8f576eb: Oliver Lukschander <oliver.lukschander@golf.at> - 69893ec: Oliver Lukschander <oliver.lukschander@golf.at> - 85d6d84: Oliver Lukschander <oliver.lukschander@golf.at> - 85fbf65: Oliver Lukschander <oliver.lukschander@golf.at> - e557722: Oliver Lukschander <oliver.lukschander@golf.at> - 0daeb8e: Oliver Lukschander <oliver.lukschander@golf.at> - cc895f2: Oliver Lukschander <oliver.lukschander@golf.at> - f8cec39: Oliver Lukschander <oliver.lukschander@golf.at> - 81eee7b: Oliver Lukschander <oliver.lukschander@golf.at> - 45c34d5: Oliver Lukschander <oliver.lukschander@golf.at> - 6f0468f: Oliver Lukschander <oliver.lukschander@golf.at> Ryan integrates these contributions under DCO (b); no author signature is forged. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
[follow-up to #8] drm/apple: expose and enforce the routed Type-C CRTC Original contributor commits are preserved. Conflict resolutions retain the audited shared driver APIs and their integrated review fixes. Contributor credit; Signed-off-by outstanding: - 99a5545: Chris Kearney <303316+iconidentify@users.noreply.github.com> - b4e5e4c: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 508384b: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 46b9e80: Oliver Lukschander <oliver.lukschander@golf.at> - b9a6a94: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 749ac04: Chris Kearney <303316+iconidentify@users.noreply.github.com> - d04e476: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 67fdc27: Chris Kearney <303316+iconidentify@users.noreply.github.com> - cf5f7d1: Chris Kearney <303316+iconidentify@users.noreply.github.com> - 8f576eb: Oliver Lukschander <oliver.lukschander@golf.at> - 69893ec: Oliver Lukschander <oliver.lukschander@golf.at> - 85d6d84: Oliver Lukschander <oliver.lukschander@golf.at> - 85fbf65: Oliver Lukschander <oliver.lukschander@golf.at> - e557722: Oliver Lukschander <oliver.lukschander@golf.at> - 0daeb8e: Oliver Lukschander <oliver.lukschander@golf.at> - cc895f2: Oliver Lukschander <oliver.lukschander@golf.at> - f8cec39: Oliver Lukschander <oliver.lukschander@golf.at> - 81eee7b: Oliver Lukschander <oliver.lukschander@golf.at> - 45c34d5: Oliver Lukschander <oliver.lukschander@golf.at> - 6f0468f: Oliver Lukschander <oliver.lukschander@golf.at> Ryan integrates these contributions under DCO (b); no author signature is forged. Assisted-by: LLM Signed-off-by: Ryan Murray <ryan@aurorasilicon.org>
This PR combines the M1 Thunderbolt display/PCIe series with the M2 Pro display work from #14 and the suspend recovery work from #25, and now also carries the open Thunderbolt display PRs #46, #64 and part of #50. It targets
aurora-wip, merges cleanly into it, and keeps every original author.Status (2026-10-01, head
947026902232):DP-N, so logind counts them and a docked lid close doesn't suspend, and the second stream'spossible_crtcsis fixed for compositors that read it once (Hyprland). J416c: dual dock DP streams, DP connector type, and PCIe-C for Thunderbolt 3 docks (stacked on #46) #50's PCIe-C cold init for T602X is not in yet.DP-1/DP-2connectors, and no omarchy-m-test regressions. A test release built from this series, booted on a 13" M1 Pro with a TB dock, kept the dock display, and logind honoured docked mode on lid close. Oliver's smoke test of3fcb3823b49eon j416s passed (boot, DPMS 5/5, output disable 3/3, hub replug). A combined run on j416s with two displays, including s2idle, is pending.Earlier status (2026-09-28): first-boot and cross-port USB2/display checks passed on the final USB2 follow-up. On 2026-09-28,
7.1.12-tbpr8-usb2fix2brought up the TS4 USB2 devices on the first session after reboot and after subsequent manual hotplugs, including first attach on the other controller. The user reports everything working across the port moves. TS4 suspend-to-idle also passed at 32.1 s and 128.8 s, with USB/display functionality confirmed after each wake and Ethernet gateway traffic verified. Hotplug checks also passed functionally on the Kensington SD5560T and CalDigit TS3 Plus, as reported by the user and supported by device/display enumeration. Kensington long sleep remains to be checked on this kernel.Earlier hardware results: on M1/j293, suspend-to-idle worked with the CalDigit TS3 Plus, CalDigit TS4 and Kensington SD5560T, displays included, at the revisions and sleep durations listed in the hardware matrix.
c2514e492d2e: a TS3 Plus suspend hung the machine until it reset. The Kensington lost its link after every resume. Any sleep longer than about 40 s lost the dock.USB2 first-session fix
The first TS4 attach on each Type-C port after boot could bring up USB3, display
and Ethernet while leaving USB2 keyboards and mice disconnected until replug.
Commit
0ab0ac187140made the Apple DWC3 glue select USB2 host mode beforereleasing the controller reset. The final fix leaves host-mode selection to the
xHCI root hub after reset; device-mode selection still runs before reset.
154e31b133ab; KUnit helper tests:d9de49ad1c84.usb2fix2kernel, the TS4 USB2 side enumerated 0.39 secondsafter the first dock attach in the boot. The Magic Keyboard and both mice
enumerated; the user confirmed USB and display operation. The external Sony
display was active at 3840×2160 @ 120 Hz. There was one dock attach and no
USB/dock disconnect before the initial capture.
this boot brought up USB2, at +0.39 s, +0.41 s and +0.38 s. The initial
controller was
502280000.usb; the final capture shows382280000.usb, soboth machine ports have first-session coverage. The keyboard, both mice and
4K/120 Hz display are present after the moves, consistent with the user report.
0.40 seconds after attach; the final-kernel result above now supersedes it.
d9de49ad1c84: 91/91 passed, with lockdep anddebug atomic-sleep enabled. This includes 19 Type-C PM tests omitted from the
earlier 72-test run. Suites: DART 10, IOMFB state 7, AFK lifetime 6, DWC3 role
choice 3, CD321x PM 19, Thunderbolt 46.
attached-cable role swaps, dock/display recovery, and long sleeps still need
hardware validation. Device-to-host and host-to-device swaps are untested.
fallback, reset ordering, retained device-mode selection, fixed-hub PHY setup,
invalid-state rejection and error paths. No blocking issue was identified in
these two commits. A fresh whole-series Sashiko review was not completed.
evidence. In-place role swaps may follow different Type-C mux/PHY power
sequencing; both role-swap directions remain a separate validation item.
Included support
14cc7c907e6ae9e52e6dc932ebbf4cb22add3075f5503a325d524a478c92DP-Nconnector type, fixed dual-streampossible_crtcs9dc79fb25c92aurora-wipat9220af926e67.7cc32163f5f1);thunderbolt_apple.dp_display=0turns them off. PCIe support needs no module parameter.3fcb3823b49e). Only j416s has been tested. The M2 Pro and M2 Max desktops have no crossbar tunnel routes in their device tree yet.Suspend-to-idle with Thunderbolt docks (7 commits on
c2514e492d2e)On Apple silicon the host router, ACIO and the tunneled PCIe controller all stay powered in suspend-to-idle. The previous code treated the sleep as a power-down anyway. It stopped every tunnel, asked the routers to sleep and reset the dock's PCIe hierarchy, then rebuilt everything on resume. That caused the failures seen at
c2514e492d2e:c2514e492d2erecovered from, and it meant a suspend longer than about 40 s lost the dock while asleep.The seven commits:
PCI: apple: resume tunneled functions as if from D3coldthunderbolt: keep routers awake across system sleep on Apple hostsQUIRK_NO_SYSTEM_SLEEP. Routers aren't asked to sleep when the host keeps the link up, which removes the 40.8 s link failure.thunderbolt: restore DP resources after resume when routers stayed awakethunderbolt: keep M1 PCIe tunnels up through suspend-to-idlethunderbolt: keep DP tunnels through suspend-to-idle with kept tunnelsdrm/apple: keep the Type-C cable state across system sleepdrm/apple: recover Type-C outputs whose swaps DCP dropsflip_donetimeouts.Test parameters. Both are meant to be dropped before upstreaming:
pcie_apple.s2idle_keep_link=0restores stop/reset/restart of the tunneled PCIe port;thunderbolt_apple.router_sleep=1restores the router sleep request.Validation of the current source
7.1.12-tbpr8-usb2fix2; the installed module matches the saved final build artifact byte-for-byte.W=1; the pre-existing kernel-doc warnings indrivers/gpu/drm/apple/dcp.care unchanged.checkpatch.pl --stricton the seven patches: 0 errors, 0 checks. The warnings are theCo-Authored-Bytrailer form and two quoted kernel log lines.checkpatch.pl --strictwith zero errors/checks and only the existing co-author trailer capitalization warnings;git diff --checkpasses.d9de49ad1c84): 91/91 pass under arm64 QEMU with lockdep, including the CD321x PM suite.7.1.12-tbpr8-usb2fix2, boot05145ba1-c851-4df1-becd-52bdf97372f0, TS4 on controller502280000.usb. First-session USB2 enumeration and user-reported USB/display operation passed. The Ethernet driver reported a 1 Gbps link, but traffic was not tested. The installed final module remained intact after the boot cleanup service ran successfully.Final USB2 follow-up hardware results (M1/j293)
Kernel
7.1.12-tbpr8-usb2fix2, sourced9de49ad1c84, 2026-09-28.Boot ID
05145ba1-c851-4df1-becd-52bdf97372f0. Manual wake was used because themachine's RTC has no wake alarm. Sleep durations were measured from the change
in
CLOCK_BOOTTIME - CLOCK_MONOTONIC.382280000.usbRaw journals also retain display firmware diagnostics and Wi-Fi errors; these
results establish the tested dock functions, not an error-free system log.
Earlier hardware matrix (M1/j293)
"Head" in this historical table is
d607bbfd1265, before the USB2 follow-up. "Rev A" is this series up to003225676c30(PCIe/Thunderbolt keep, without the DP and DCP commits). "Rev B" is up to337af62b6e56. The Thunderbolt and PCIe sleep code is identical in Rev A, Rev B and the head except for the DP-tunnel keep in commit 5.At Rev B (without commit 7), the Kensington + TV case froze the compositor on
flip_donetimeouts. Atc2514e492d2e, the TS3 Plus front-port display suspend hung the machine until it reset. Both are fixed by the commits above.Known issues
Pipehandler lock not acked/Failed to lock pipehandlerfrom the PHY driver. Subsequent USB2/display attaches passed, with no kernel WARNING/Oops observed in the captured journal. The diagnostic cause is not yet triaged.Hardware test progress on
d9de49ad1c84Use the installed
7.1.12-tbpr8-usb2fix2kernel and record the dock, port, boot ID,sleep duration, observed input/display/network health and kernel journal.
display operation on 2026-09-28, as recorded above.
the other controller. All three attaches passed USB2 enumeration, and the
user reports working USB/display across the moves.
with the user reporting normal operation on both. Logs confirm USB input
device enumeration and completed display modesets. The current TS3 Plus
session also passed an Ethernet gateway ping (3/3). Kensington Ethernet
enumerated but traffic was not tested. These TB3 docks use their own PCIe
USB controllers; their coverage comes from device/display evidence and the
user report, not the TS4 attach checker.
topology and device numbers were retained through both cycles; no USB/dock
disconnect or new-device enumeration was logged during either cycle. The
user confirmed input/display functionality, the external display returned
at 3840×2160 @ 120 Hz, and Ethernet gateway ping passed 3/3 after each wake.
Short resume had no USB reset events; long resume had the five downstream
reset events noted above. No kernel WARNING/Oops/Call Trace was observed in
either captured interval. Kensington long-sleep testing remains pending.
The attach checker validates enumeration events, not resume health. An INFO/SKIP
result is not a hardware pass, and an earlier attach PASS does not establish
successful recovery after sleep.
Earlier hardware results
c2514e492d2e: Kensington SD5560T rear, two USB-only suspends and one display suspend passed functionally, recovered by late link-loss notification. CalDigit TS3 Plus front-port display suspend failed: the machine hung after wake and reset.67761b89689e(TS4): passed boot, same-port and cross-port hotplug, Sony 3840×2160@120 through the TS4 DP-to-HDMI adapter, and wired connectivity. It exposed a suspend regression.44bcebd4fabe: passed one TS4 display/network suspend recovery cycle after the PCIe ownership/PM fix. Kensington suspend still failed at44bcebd4fabeand5eb7f83a961a.🤖 Generated with Claude Code
https://claude.ai/code/session_01PA1D59hehGmwnpSxrYcDbk