Framework 16 + Anker Prime dock: the USB-PD loop behind the 'USB 3 never comes up' problem
Symptom: an Anker Prime Docking Station (A83B3, DisplayLink DL7400) on a Framework
Laptop 16 (AMD Ryzen AI 300) either flaps constantly or comes up USB 2.0 only (480 Mbps),
with device not accepting address, error -71 repeating in the kernel log. Three 1080p
DisplayLink monitors at 480 Mbps lag badly.
Cause: the dock advertises USB-PD Extended Power Range (EPR) capability. The Framework EC tries to enter EPR, the dock never completes the handshake, the PD controller hard-resets the port, and the EC’s “give up after 4 tries” counter is cleared by that same hard reset. The port is reset every 1.4 seconds, forever. USB 3 never survives long enough to enumerate.
Workaround: put the dock in a front expansion slot (3 or 6). Those slots have no PD controller, so no contract, no EPR attempt, no loop. 10 Gbps, all three monitors, no lag. The dock won’t charge the laptop from there.
Fix: a small EC firmware change; patch and bug report at willhwig/framework-ec-epr-fix.
What Linux showed
Two different slot types, two different failure shapes:
USB4 slot (1 or 4): the dock’s USB 2 hub enumerated and vanished every second or two, with a UCSI connector-change event each time:
usb 7-1: new high-speed USB device number 23 using xhci_hcd
usb 7-1: New USB device found, idVendor=2109, idProduct=2822
hub 7-1:1.0: 5 ports detected
ucsi_acpi USBC000:00: unknown error 256
usb 7-1: USB disconnect, device number 23
ucsi_acpi USBC000:00: UCSI_GET_PDOS failed (-95)
usb 8-1: device not accepting address 8, error -71
usb 7-1-port2: attempt power cycle
Middle slot (USB 3.2 Gen 2 with DisplayPort): the USB 2 side stayed up at 480M, but the USB 3 side trained to 10 Gbps and then failed its first command, over and over:
usb 4-1: new SuperSpeed Plus Gen 2x1 USB device number 17 using xhci_hcd
usb 4-1: Device not responding to setup address.
usb 4-1: device not accepting address 20, error -71
Fifteen successful link trainings and 116 -71 failures in about 15 minutes. -71 is EPROTO, a
USB transaction error, which usually gets blamed on cables. That was a red herring here: the
link trained fine; the dock just got reset before it could answer.
Things that were not the cause, each tested: USB autosuspend and xHCI runtime PM (disabled, no change), USB 3 link power management (disabled, no change), the expansion card (two different ones), the host controller (both xHCI controllers failed the same way), the DisplayLink driver, system memory pressure, and a full power-cycle of the dock. The only components common to every failure were the dock, its cable, and the laptop’s PD stack.
One more clue from sysfs: the laptop saw the dock as a plain 5 V / 3 A source with no PD contract, even though the dock is rated to charge the laptop at 100 W.
What the EC showed
Framework publishes framework_tool, which can read the embedded controller’s console:
sudo framework_tool --console follow
With the dock in a middle slot, this repeats every 1.4 seconds:
[417651.7597 CYPD_RESPONSE_PD_CONTRACT_NEGOTIATION_COMPLETE 2]
[417651.8718 set AP throttling type 1 to on (0x00000010)]
[417652.0286 CCG_RESPONSE_HARD_RESET_SENT]
[417652.1008 C2 enter EPR stuck, retry!]
[417652.3691 set AP throttling type 1 to off (0x00000000)]
[417653.0701 P2 EPR mode capable]
[417653.1739 CYPD_RESPONSE_PD_CONTRACT_NEGOTIATION_COMPLETE 2]
Eleven hard resets in 15 seconds. Unplugging the Framework charger changed nothing;
unplugging the dock stopped it. Note the AP throttling lines: each cycle asserts PROCHOT, so
the CPU was being throttled on and off continuously while the dock was attached.
The mechanism in the EC source
Framework’s EC firmware is open source
(FrameworkComputer/EmbeddedController,
branch fwk-tulip-29169 for this board). The relevant code is in
zephyr/program/framework/src/:
cypress_pd_common.c, onCCG_RESPONSE_SOURCE_CAP_MSG_RX: if the first PDO has the EPR-capable bit, setepr_support = 1and logP2 EPR mode capable.- On
CCG_RESPONSE_PD_CONTRACT_NEGOTIATION_COMPLETE: scheduleenter_epr_mode()in 100 ms. cypd_ccg8.c,enter_epr_mode(): for every sink port withepr_support, send the PD chipCCG_PD_CMD_INITIATE_EPR_ENTRY, drop the input current limit to 0, assert PMF/PROCHOT, and arm a 200 ms timer.- The dock never answers. The timer fires
epr_flow_pending_deferred(), which logsenter EPR stuck, retry!and tries again. The CCG8 PD chip ends the failed entry with a hard reset. - The hard-reset handler calls
clear_port_state(), which zeroesepr_supportandepr_retry_count. - The contract renegotiates, the source capabilities arrive again, back to step 1.
epr_flow_pending_deferred() does have a guard: after epr_retry_count > 4 it gives up on
EPR for that port. It can never fire, because step 5 resets the counter on every cycle.
Nothing in the EC remembers that EPR entry on this connection has already failed.
The dock is also at fault: it claims EPR capability on a 100 W port and then doesn’t complete
the handshake. A spec-following source would answer with EPR_Mode Fail. But the EC should
not loop forever on a misbehaving partner either, and it is the side that can be fixed in
software.
What I tried from the OS before giving up on a software-only fix
The EC only attempts EPR when the laptop is the power sink. Framework’s EC passes UCSI
SET_PDR through to the PD chip, and Linux exposes that as a sysfs write, so in principle
the laptop could become the source on the dock port and sidestep EPR entirely:
echo source | sudo tee /sys/class/typec/port2/power_role
The EC refused all three attempts (-70 ECOMM, -95 EOPNOTSUPP). No OS-level fix.
The workaround
The Framework 16 EC has five PD ports for six expansion slots. The front slots sit behind an internal USB hub and have no PD controller. With a USB-C expansion card in a front slot:
usb 4-2.3.3: new SuperSpeed Plus Gen 2x1 USB device number 42 using xhci_hcd
usb 4-2.3.3: Product: A83B3_A1
No Type-C partner, no contract, no EPR, no hard resets. Everything on the dock came up in four seconds. 10 Gbps is the dock’s maximum anyway, so nothing is lost versus the USB4 slots except laptop charging through the dock.
One GNOME wrinkle after a re-plug: only one of the three DisplayLink monitors came on.
The evdi connector names (DVI-I-N) shift on each enumeration and ~/.config/monitors.xml
is keyed by name plus serial, so the saved layout didn’t match.
sudo systemctl restart displaylink-driver, then Settings → Displays, fixed it.
The fix
The patch adds a per-port counter of hard resets caused by the EC’s own EPR entry attempts.
clear_port_state() leaves it alone; only a physical disconnect clears it. enter_epr_mode()
skips the port after two such resets, logs once, and stays on the SPR contract (100 W here).
EPR is tried again on the next plug-in. 42 lines, three files:
willhwig/framework-ec-epr-fix.
I have not built or flashed it; flashing a self-built EC on a production laptop is a brick risk, and the right path is review by Framework and a BIOS release.
If you have this problem
lsusb -t | grep -i usbfs— if the DisplayLink device shows480M, you’re in the fallback.sudo framework_tool --console followfor 15 s and countHARD_RESET_SENT. If it’s more than zero and you seeenter EPR stuck, retry!, it’s this loop.- Move the dock to a front slot.
A Framework 13 Pro owner hit what looks like the same thing with an Anker DL7400 dock (community thread) and ended up replacing the dock. If your laptop has a slot without PD, you may not have to.