Commit 42c85d89 authored by Janne Grunau's avatar Janne Grunau Committed by Greg Kroah-Hartman
Browse files

usb: dwc3: apple: Ignore USB role switches to the active role



Ignore USB role switches if dwc3-apple is already in the desired state.
The USB-C port controller on M2 and M1/M2 Pro/Max/Ultra devices issues
additional interrupts which result in USB role switches to the already
active role.
Ignore these USB role switches to ensure the USB-C port controller and
dwc3-apple are always in a consistent state. This matches the behaviour
in __dwc3_set_mode() in core.c.
Fixes detecting USB 2.0 and 3.x devices on the affected systems. The
reset caused by the additional role switch appears to leave the USB
devices in a state which prevents detection when the phy and dwc3 is
brought back up again.

Fixes: 0ec946d3 ("usb: dwc3: Add Apple Silicon DWC3 glue layer driver")
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarJanne Grunau <j@jannau.net>
Acked-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Reviewed-by: default avatarSven Peter <sven@kernel.org>
Tested-by: Sven Peter <sven@kernel.org> # M1 mac mini and macbook air
Link: https://patch.msgid.link/20260109-apple-dwc3-role-switch-v1-1-11623b0f6222@jannau.net


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d13b6a12
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -357,6 +357,22 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role ro

	guard(mutex)(&appledwc->lock);

	/*
	 * Skip role switches if appledwc is already in the desired state. The
	 * USB-C port controller on M2 and M1/M2 Pro/Max/Ultra devices issues
	 * additional interrupts which results in usb_role_switch_set_role()
	 * calls with the current role.
	 * Ignore those calls here to ensure the USB-C port controller and
	 * appledwc are in a consistent state.
	 * This matches the behaviour in __dwc3_set_mode().
	 * Do no handle USB_ROLE_NONE for DWC3_APPLE_NO_CABLE and
	 * DWC3_APPLE_PROBE_PENDING since that is no-op anyway.
	 */
	if (appledwc->state == DWC3_APPLE_HOST && role == USB_ROLE_HOST)
		return 0;
	if (appledwc->state == DWC3_APPLE_DEVICE && role == USB_ROLE_DEVICE)
		return 0;

	/*
	 * We need to tear all of dwc3 down and re-initialize it every time a cable is
	 * connected or disconnected or when the mode changes. See the documentation for enum