Skip to content

[fairydust] M1 Pro: USB-C DP hot-plug stops working until reboot when a second USB-C dock is attached #634

Description

@makhov

System

  • MacBookPro18,3 / J314s (14" M1 Pro), Arch Linux ARM
  • Kernel: fairydust ce9f2eba72c0 (7.1.13-fd-1-ARCH)
  • Monitor: HP M24fd on USB-C Left Front (the only port wired for DP, typec1 → atcphy1 b03000000 → dcpext1 28cc00000). It supplies power and has a Genesys USB hub.
  • Second device: VIA Labs USB-C dock (2109:2817/0817, advertises Billboard) on Left Back (hpm0 0x38, atcphy0)

Symptom

Hot-plugging the monitor works on a fresh boot. Sometimes, usually with the dock attached, it stops working: every later replug stays black until reboot. I found two separate causes.

1. Slow poweroff clear swap marks the DCP crashed (fix in PR)

On unplug, iomfb_poweroff() waits 50 ms for the clear swap and sets dcp->crashed on timeout, without logging anything. The firmware first does its own teardown (display HPD removed, power_down_M3, set_device_enabled_gated: 1 -> 0) and only then swallows the clear swap, measured at ~53 ms. From then on dcp_crtc_atomic_check() returns -EINVAL for every commit. The monitor is detected on replug but never gets a mode, and the compositor cannot even disable the output. I saw this in 3 separate boots.

PR: #635

2. The DP port's cd321x ends up in a state where it never enters DP altmode (under investigation)

In one boot, after the dock went through a USB collapse (-71, device not accepting address, usb4-port1: config error, re-enumeration), replugs on the DP port never reached the DCP at all. tps6598x only sends oob_hotplug disconnect events. tipd trace on 0x3f after replug:

cd321x_irq: event=PLUG_EVENT|STATUS_UPDATE
tps6598x_status: conn: conn-no-Ra, pp_ext: in, pp_cable: out, pwr-src: vbus ...
cd321x_data_status: DATA_CONNECTION|USB2_CONNECTION|USB3_CONNECTION|USB3_GEN2|USB_DATA_ROLE

The Mac sinks power and stays UFP. There is no PD contract (typec: pd never shows up), no DR swap, no DP_CONNECTION/HPD_LEVEL. On a working plug the same monitor goes typec: pd → DR swap → DP_CONNECTION, DP pinout DHPD_LEVEL within ~300 ms.

Hints that the controller was reset behind the driver:

  • 0x3f raises STATUS_UPDATE (bit 8), which is not in the driver's irq_mask1, and never POWER_STATUS_UPDATE. The other ports in the same boot, and 0x3f after reboot, only raise the masked events.
  • The monitor's USB hub disconnected ~4.5 s before 0x3f reported anything. On normal unplugs the order is the other way around.
  • SMC logs aceElec: Elec Cause 0x8020 right before the failure and on every failed replug afterwards. It never shows up in working captures, where plugs log 0x8000 and 0x20 separately.

My guess: the reset also drops the system power state set with SSPS at probe, so the firmware behaves as if the system is asleep. I have a patch that rewrites the mask and switches back to S0 when that happens (makhov@786234429285), but I haven't caught a reset with it yet. Healthy register state for reference: MODE APP , SYS_PWR_STATE 00, INT_MASK1 0x602.

Possibly related: #571 (VIA Labs hub, DP link bouncing).

Minor, noticed on the way

dcp_dptx_connect() logs waited 2000 ms for link on every plug, so linkcfg_completion never fires and each hot-plug waits the full timeout. Also wait_for_completion_timeout() returns 0 on timeout, so its ret < 0 warning can never trigger.

Logs and tipd traces available on request.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions