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

usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature

On Rasperry Pis without onboard USB hub the power cycle during
power connect init only disable the port but never enabled it again:

usb usb1-port1: attempt power cycle

The port relevant part in dwc2_hcd_hub_control() is skipped in case
port_connect_status = 0 under the assumption the core is or will be soon
in device mode. But this assumption is wrong, because after ClearPortFeature
USB_PORT_FEAT_POWER the port_connect_status will also be 0 and
SetPortFeature (incl. USB_PORT_FEAT_POWER) will be a no-op.

Fix the behavior of dwc2_hcd_hub_control() by replacing the
port_connect_status check with dwc2_is_device_mode().

Link: https://github.com/raspberrypi/linux/issues/6247
Fixes: 7359d482eb4d ("staging: HCD files for the DWC2 driver")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
Link: https://lore.kernel.org/r/20241202001631.75473-3-wahrenst@gmx.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Stefan Wahren and committed by
Greg Kroah-Hartman
a8d3e4a7 336f72d3

+6 -10
+6 -10
drivers/usb/dwc2/hcd.c
··· 3546 3546 port_status |= USB_PORT_STAT_C_OVERCURRENT << 16; 3547 3547 } 3548 3548 3549 - if (!hsotg->flags.b.port_connect_status) { 3549 + if (dwc2_is_device_mode(hsotg)) { 3550 3550 /* 3551 - * The port is disconnected, which means the core is 3552 - * either in device mode or it soon will be. Just 3553 - * return 0's for the remainder of the port status 3551 + * Just return 0's for the remainder of the port status 3554 3552 * since the port register can't be read if the core 3555 3553 * is in device mode. 3556 3554 */ ··· 3618 3620 if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1)) 3619 3621 goto error; 3620 3622 3621 - if (!hsotg->flags.b.port_connect_status) { 3623 + if (dwc2_is_device_mode(hsotg)) { 3622 3624 /* 3623 - * The port is disconnected, which means the core is 3624 - * either in device mode or it soon will be. Just 3625 - * return without doing anything since the port 3626 - * register can't be written if the core is in device 3627 - * mode. 3625 + * Just return 0's for the remainder of the port status 3626 + * since the port register can't be read if the core 3627 + * is in device mode. 3628 3628 */ 3629 3629 break; 3630 3630 }