Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 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>

authored by

Janne Grunau and committed by
Greg Kroah-Hartman
42c85d89 d13b6a12

+16
+16
drivers/usb/dwc3/dwc3-apple.c
··· 358 358 guard(mutex)(&appledwc->lock); 359 359 360 360 /* 361 + * Skip role switches if appledwc is already in the desired state. The 362 + * USB-C port controller on M2 and M1/M2 Pro/Max/Ultra devices issues 363 + * additional interrupts which results in usb_role_switch_set_role() 364 + * calls with the current role. 365 + * Ignore those calls here to ensure the USB-C port controller and 366 + * appledwc are in a consistent state. 367 + * This matches the behaviour in __dwc3_set_mode(). 368 + * Do no handle USB_ROLE_NONE for DWC3_APPLE_NO_CABLE and 369 + * DWC3_APPLE_PROBE_PENDING since that is no-op anyway. 370 + */ 371 + if (appledwc->state == DWC3_APPLE_HOST && role == USB_ROLE_HOST) 372 + return 0; 373 + if (appledwc->state == DWC3_APPLE_DEVICE && role == USB_ROLE_DEVICE) 374 + return 0; 375 + 376 + /* 361 377 * We need to tear all of dwc3 down and re-initialize it every time a cable is 362 378 * connected or disconnected or when the mode changes. See the documentation for enum 363 379 * dwc3_apple_state for details.