Skip to content

Park masked U3 ports instead of leaving them half-enabled - #200

Merged
frank-w merged 1 commit into
frank-w:7.1-mainfrom
meehien:bpi/xhci-mtk-u3p-dis-msk
Jul 30, 2026
Merged

Park masked U3 ports instead of leaving them half-enabled#200
frank-w merged 1 commit into
frank-w:7.1-mainfrom
meehien:bpi/xhci-mtk-u3p-dis-msk

Conversation

@meehien

Copy link
Copy Markdown

xhci_mtk_host_enable() skips ports listed in mediatek,u3p-dis-msk
entirely — it neither powers them up nor down, so they keep the bootloader
default, which on MediaTek IPPC is powered up and host-selected. But the
mask exists precisely for ports whose U3 PHY is unusable: on the R4 Pro,
ssusb0's U3 lane is muxed to PCIe2, so the DT masks U3 port 0 and omits the
PHY.

The port is therefore powered and host-selected with no initialized PHY and
a MAC clock domain never released from reset, holding the controller's level
interrupt asserted with a status xhci_irq() cannot acknowledge. The
spurious-IRQ detector disables the line, and the perfectly good USB2 bus on
the same controller dies with it — completions never arrive, the first
hub_event needing a command parks in D state holding the hub lock, and
device_shutdown() blocks behind it, hanging reboot.

Explicitly set CTRL_U3_PORT_PDN and CTRL_U3_PORT_DIS for masked ports,
mirroring what host_enable() does in reverse for active ones.

Companion to the clk-mt7988 fix (PR 1) — same board, same symptom class,
independent causes. Both are needed.

xhci_mtk_host_enable() skips ports flagged in "mediatek,u3p-dis-msk"
entirely: it neither powers them up nor powers them down, leaving them
in their power-on/bootloader default state, which on MediaTek IPPC is
powered up and host-selected. The mask exists precisely for ports whose
USB3 PHY is not usable - on BPI-R4 Pro (MT7988A) ssusb0's U3 SerDes
lane is shared with (and muxed to) PCIe2, so the board DT masks U3 port
0 and omits the xphy U3 port from "phys".
The result on that board is a U3 port that is powered and host-selected
but has no initialized PHY and a MAC clock domain that is never
released from reset (the driver deliberately excludes STS1_U3_MAC_RST
from its stability poll for masked ports). This holds the controller's
level interrupt permanently asserted with a status the xHCI interrupt
handler cannot acknowledge:
[ 2.455798] xhci-mtk 11190000.usb: irq 120, io mem 0x11190000
[ 2.861314] irq 120: nobody cared (try booting with the "irqpoll" option)
[ 3.242105] [<0000000014dcb6ae>] usb_hcd_irq
[ 3.246371] Disabling IRQ frank-w#120
Once the spurious-IRQ detector disables the line, the fully functional
USB2 bus on the same controller dies with it: xHC commands are queued
but their completions never interrupt, the first hub_event needing a
command parks in D state holding the hub lock
[ 126.053644] Workqueue: usb_hub_wq hub_event
[ 126.053742] xhci_disable_slot+0xb4/0x188
[ 126.053757] xhci_free_dev+0xfc/0x2a4
[ 126.053771] hub_event+0x1364/0x1a0c
and device_shutdown() blocks behind it on reboot, hanging the system.
Explicitly park masked ports by setting CTRL_U3_PORT_PDN and
CTRL_U3_PORT_DIS, mirroring what host_enable() does in reverse for
active ports. xhci_mtk_host_disable() already skips masked ports, which
remains correct as they are now already down.
Signed-off-by: Mihai Ordean <research@mihaiordean.com>
@frank-w
frank-w merged commit 668d699 into frank-w:7.1-mainJul 30, 2026
@meehien
meehien deleted the bpi/xhci-mtk-u3p-dis-msk branch July 30, 2026 22:41
Sign up for freeto 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.

2 participants

@meehien@frank-w