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 <[email protected]>
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