Skip to content

usb: typec: tipd: keep a dock's USB when the display pipeline is taken - #163

Open
invaliddayta wants to merge 1 commit into
omacom:integration/aurorafrom
invaliddayta:tipd-display-taken-enospc
Open

invaliddayta wants to merge 1 commit into
omacom:integration/aurorafrom
invaliddayta:tipd-display-taken-enospc

Conversation

@invaliddayta

Copy link
Copy Markdown

I declared it at 7 am and you had it evaluated by lunch. Most reproducible wish I've ever made.

On a MacBook Air M2 (J413, T8112), a USB-C monitor in one port leaves a DP Alt Mode dock in the other port without USB. The dock's hub (VIA Labs 2109:2817/0817) enumerates for a moment and then disappears, and the port never gets a USB role back:

xhci-hcd xhci-hcd.3.auto: remove, state 1
phy-apple-atc 383000000.phy: Pipehandler lock not acked.
phy-apple-atc 383000000.phy: Failed to lock pipehandler
tps6598x 0-0038: failed to configure Type-C connection: -28
tps6598x 0-0038: failed to configure Type-C connection: -28
tps6598x 0-0038: failed to configure Type-C connection: -28
tps6598x 0-0038: cable revalidation failed after 3 attempts

Cause:

  • T8112 has one external display pipeline, and the monitor holds it. The DCP fabric reports that as -ENOSPC on every SoC (dcp_typec_route_set()).
  • c1ef888 made -ENOSPC the error that means "display taken": tipd then sets up the port's USB without the display and does not retry.
  • dea3f3b kept that on T8140/T8142 only, and made -EBUSY the taken display on every other SoC. So on T8112, -ENOSPC is retried until revalidation gives up, and usb_role_switch_set_role() is never reached.

Fix: go back to the one meaning on every SoC: cd321x_display_taken() is ret == -ENOSPC again, and the KUnit case expects that. I could not find a route in this tree that still reports a taken pipeline as -EBUSY. The remaining -EBUSY sources on that mux chain are the ATC PHY's transitions, which c1ef888 wants retried. h17_display stays, because the H17 HPD rules use it.

If the -EBUSY branch for the older SoCs was there for a reason I missed, the narrower alternative is ret == -ENOSPC || (!h17 && ret == -EBUSY). That keeps it and still fixes the dock.

Tested on J413 (MacBook Air M2, T8112):

  • Kernel: 7.2.10 at 1b4997b (what aurora-silicon/nixos-aurora pins) plus this patch, built with aurora-silicon/nixos-aurora's kernel derivation (its nixpkgs, config and LLVM 22). Without the patch, it evaluates to the same derivation as the kernel in their cache.
  • Distribution: NixOS. m1n1 omacom d05ba17, sway.
  • Devices:
    • a USB-C monitor (5120x1440 at 60 Hz, DP Alt Mode, with its own USB hub);
    • a USB-C dock (VIA Labs hub, DP Alt Mode, no display on it) with a mouse, a keyboard and Ethernet.
  • Before: with the monitor already plugged in, the dock got no USB in 3 of 3 plugs, on either port. Each time: cable revalidation failed after 3 attempts.
  • After (one boot, about 4 minutes of replugging in both orders and on both ports):
    • 10 of 10 -28 events were followed by USB on that port within 3 s;
    • no revalidation gave up;
    • the dock's keyboard, mouse and Ethernet worked;
    • the monitor stayed at 5120x1440.
  • Known limit, not changed here: each plug brings the dock's USB up, tears it down for the DP mode switch about a second later, then brings it up again. In 3 of those cycles, a mouse that was enumerating behind the dock's hub got stuck (device descriptor read/64, error -32, then device not accepting address 6, error -71) until it was replugged.
  • KUnit (tools/aurora-ci/run-kunit.py on 34c7dfe plus this patch, arm64 under QEMU TCG): 1396 pass, 0 fail, 3 skip, which matches kunit-expected.json.
  • checkpatch.pl --strict: 0 errors, 0 warnings.

Written with an AI assistant (Assisted-by trailer). I reviewed it and tested it on the machine above.

On a MacBook Air M2 (J413, T8112), a USB-C monitor in one port leaves a
dock that offers DisplayPort Alt Mode in the other port without USB.
The dock's hub enumerates for a moment, the PHY switches to the DP
mode, and the port then never gets a USB role back. Keyboard, mouse and
everything else behind the dock stay dead until the monitor is
unplugged:

  tps6598x 0-0038: failed to configure Type-C connection: -28
  tps6598x 0-0038: failed to configure Type-C connection: -28
  tps6598x 0-0038: failed to configure Type-C connection: -28
  tps6598x 0-0038: cable revalidation failed after 3 attempts

T8112 has one external display pipeline, and the monitor holds it. The
DCP fabric reports that as -ENOSPC on every SoC (dcp_typec_route_set()).
cd321x_typec_update_mode() is meant to flag that error as a busy
display, so that cd321x_update_work() sets the USB role without the
display and does not retry.

Commit c1ef888 ("usb: typec: tipd: Retry a display mux that is
only busy") gave -ENOSPC that meaning and made -EBUSY a transient error
to retry. Commit dea3f3b ("usb: typec: keep the H17 display route
handshake") kept that on T8140 and T8142 only, and made -EBUSY the busy
display everywhere else. On the other SoCs, -ENOSPC is now retried like
any failure. Every attempt fails the same way, and cd321x_update_work()
never reaches usb_role_switch_set_role().

No route in this tree reports a taken pipeline as -EBUSY any more, so
go back to the single meaning on every SoC. h17_display stays for the
H17 HPD rules.

Fixes: dea3f3b ("usb: typec: keep the H17 display route handshake")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Paul Mairhofer <86946817+invaliddayta@users.noreply.github.com>
@joshuaswarren

Copy link
Copy Markdown

Rebased this branch locally against 186's head (2a37f6f): the two PRs collide in the same function.

Overlap:

  • drivers/usb/typec/tipd/cd321x-pm.h, cd321x_display_taken(): 186 rewrites the same hunk 163 touches (186 keeps the bool enospc parameter and accepts -ENOSPC || (!enospc && -EBUSY); 163 drops the parameter entirely and returns ret == -ENOSPC).
  • drivers/usb/typec/tipd/cd321x-pm-test.c, cd321x_display_taken_test(): 163 deletes the two-argument expectations and rewrites them single-argument; 186 changes one two-argument expectation in the same test. The rewrites are semantically different (163 retries -EBUSY on every SoC; 186 keeps -EBUSY retried only outside the H17 gate).

So this PR was not boot-tested and will need a rebase onto (or with) 186 whichever lands first.

Not tested here: no boot run (conflict above), no CI checks reported on this branch yet.

@chriskearney chriskearney left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head b8930ad8c5d319d74f9c284c764b7df29d879881, all four changes and current DCP/mux/ATC error producers plus DP/USB-role callers. Source/host PASS, subject to required CI and full MQ.

Current no-pipeline/no-free-route errors are ENOSPC. EBUSY can instead mean generic mux-transaction contention or a PHY transition, so keeping the bounded retry for EBUSY is correct. ENOSPC reaches the existing USB continuation without claiming a display route is active. Ownership, PM/removal and retry budgets are unchanged.

115 extracted header/caller assertions pass; the actual base predicate fails 18 intended cases; three compiled semantic mutants are caught. The four changed-component baselines are byte-identical to the author's J413 before/after setup (0/3 vs 10/10 reported dock plugs). No new physical boot is needed solely for this errno correction, and QEMU is not dock/display qualification. Existing USB re-enumeration/mouse-replug limitations remain.

#186 contains an alternative overlapping predicate/test change and is not a dependency. Do not merge both current heads unchanged; its overlapping tipd portion needs resolution preserving the current ENOSPC contract, with its separate DCP changes reviewed independently.

@ericjuta

ericjuta commented Nov 8, 2026

Copy link
Copy Markdown

J615 combined-stack field observation: the user reports stable unplug/replug and lid-open/closed use on local 7.2.11-dcpexp-usb-recovery-20261108. Its dirty source carries the same -ENOSPC-only cd321x_display_taken() policy, plus deferred routing for no-HPD DP-alt ports (overlapping #186), #357 idle-route reclaim, J615 display/brightness and thermal work. The installed Image matches the local build artifact. This is not an exact-PR-branch build/boot test and does not isolate which change produced the improvement.

Current read-only USB inspection shows functioning enumerated HID and UVC devices on USB2 (480M); USB3 root hubs are present but empty. SuperSpeed recovery, provider-order variations and fault injection are not established by this observation. A source-level reclaim-error interaction needing review is documented at #357 (comment) . No duplicate USB PR is being opened.

@josipjelic

Copy link
Copy Markdown

Same failure on a second SoC and Type-C controller: MacBook Pro 14" M3 Pro (Mac15,6, T6030), sn201202x driver, packaged linux-aurora 7.2.11.aurora14-1 (Omarchy 4.5.0-3). This build does not have this PR's patch.

Setup: two Dell U2412M monitors on two of the three USB-C ports (DP Alt Mode) take both external pipelines. The third port gets a USB-C hub that has a video output, with only a USB keyboard plugged into it.

Result: the hub never gets USB, on either free port, every time it is plugged in. No USB device enumerates beyond the root hubs, and the port's xHCI (702280000.usb / f02280000.usb) is never created:

apple-dcp 2d2c00000.dcp: display on USB-C Left Back waits for a free external display pipeline (each one drives another display); it lights up on its own when one of those displays is unplugged
sn201202x 1-0c: failed to configure Type-C connection: -28
sn201202x 1-0c: failed to configure Type-C connection: -28
sn201202x 1-0c: failed to configure Type-C connection: -28
sn201202x 1-0c: cable revalidation failed after 3 attempts

The same thing happened after I moved the hub to the right port (sn201202x 2-08, same four lines).

Workaround that did not help: writing no to the port's DP altmode active (/sys/class/typec/portN/portN.0/active, svid ff01) before replugging made no difference. The -28 retries and the revalidation give-up were unchanged.

So on T6030, -ENOSPC is also retried until revalidation gives up and the port never gets a USB role. That matches the T8112 analysis above, which suggests the fix belongs on every SoC and not only T8140/T8142. I haven't built or booted this branch yet. If a test build of 163 is available for aurora on Arch/Omarchy, I can test it on this machine.

Filed by Claude Opus 5.5 via Claude Code.

@RaoulBrueker

Copy link
Copy Markdown

Same failure on M1 (MacBook Pro 13" 2020, J293, apple,t8103), packaged linux-aurora 7.2.11.aurora14-1 (Omarchy 4.5.0-3). Applying the one-line change from this PR locally fixes it.

Setup: LG 16MR70 USB-C monitor (DP alt mode) on one port. A USB-C hub with DP alt mode and no display attached (GenesysLogic 05e3:0610/0625) on the other, carrying a C920 webcam and storage. This worked on 7.1.12.aurora2-7 and broke with the move to 7.2.11.

Before: whichever device connects second gets no USB at all, in either plug order:

tps6598x 0-0038: failed to configure Type-C connection: -28
tps6598x 0-0038: failed to configure Type-C connection: -28
tps6598x 0-0038: failed to configure Type-C connection: -28
tps6598x 0-0038: failed to configure Type-C connection: -28
tps6598x 0-0038: cable revalidation failed after 3 attempts

Patch: I rebuilt only tps6598x-core.ko from 4fdd0fc (the aurora14 pin) with cd321x_display_taken() changed to ret == -ENOSPC || ret == -EBUSY, i.e. accepting -ENOSPC as this PR does (I kept -EBUSY as well, so the old non-H17 meaning still holds). I put it in updates/ and rebuilt the initramfs.

After: the monitor was plugged in at boot and the hub afterwards:

apple-display-crossbar 50304c000.mux: Switched dpphy to dispext0,0
xhci-hcd xhci-hcd.2.auto: irq 131, io mem 0x502280000
tps6598x 0-0038: failed to configure Type-C connection: -28
xhci-hcd xhci-hcd.3.auto: irq 132, io mem 0x382280000

There was no revalidation loop. The hub and its devices enumerate, and the monitor stays up. I've only run one session on it so far.

This adds t8103 to T8112 (#163), t600x (#186) and T6030 (comment above). integration/aurora HEAD (bed544b, aurora16) still has the H17-only check.

Diagnosed and drafted with Claude Code; patch built and verified on my machine.

@ericjuta

ericjuta commented Nov 13, 2026 •

Copy link
Copy Markdown

Confirming the same -28 loop on a fifth machine: MacBook Air 15" M3 (J615, apple,t8122, sn201202x), which follows up my earlier field note with the actual before/after from this machine's journal.

Setup: Samsung G9 (DP alt mode) on one left port, a Genesys Logic USB-C hub (05e3:0626) with a webcam and mouse on the other.

Before: local 7.2.11 builds on the aurora base that still carry the H17-gated check (ret == (enospc ? -ENOSPC : -EBUSY)). Four of eight boots hit it, 43 -28 lines in total, and one boot gave up on revalidation 10 times:

sn201202x 1-0a: failed to configure Type-C connection: -28
sn201202x 1-0a: failed to configure Type-C connection: -28
sn201202x 1-0a: failed to configure Type-C connection: -28
sn201202x 1-0a: failed to configure Type-C connection: -28
sn201202x 1-0a: cable revalidation failed after 3 attempts

It repeats on both controllers (1-0a and 1-0c) on each replug.

After: local builds where cd321x_display_taken() is ret == -ENOSPC, as in this PR. 15 boots, several with the same monitor and hub attached and exercised through replugs and port swaps: zero -28 lines and zero revalidation failures.

Limits: the "after" kernels are not this PR's branch. They also carry #186-style deferred routing, #357 and J615 display work (#356), so this confirms the failure on T8122 and that it is gone with the -ENOSPC-only policy in the stack, without isolating this one-line change. A separate intermittent problem (hub sometimes returns at 480M instead of 5000M after a replug) is still open here and is not claimed as fixed.

With T8103, T8112, T6000-family and T6030 above, that is every SoC generation reported so far, which supports dropping the H17 gate.

Drafted with Claude Code from this machine's kernel logs.

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.

6 participants