]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
usb: dwc3: apple: Ignore USB role switches to the active role
authorJanne Grunau <j@jannau.net>
Fri, 9 Jan 2026 10:13:48 +0000 (11:13 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Jan 2026 15:02:54 +0000 (16:02 +0100)
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: 0ec946d32ef7 ("usb: dwc3: Add Apple Silicon DWC3 glue layer driver")
Cc: stable <stable@kernel.org>
Signed-off-by: Janne Grunau <j@jannau.net>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Reviewed-by: Sven 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/dwc3-apple.c

index c2ae8eb21d514e5e493d2927bc12908c308dfe19..40c3ccfddb67027c440e9c8fa528a2599741c83f 100644 (file)
@@ -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