Skip to content

Commit 9f75893

Browse files
roychl666gregkh
authored andcommitted
Revert "usb: xhci: Implement xhci_handshake_check_state() helper"
commit 7aed153 upstream. This reverts commit 6ccb83d. Commit 6ccb83d ("usb: xhci: Implement xhci_handshake_check_state() helper") was introduced to workaround watchdog timeout issues on some platforms, allowing xhci_reset() to bail out early without waiting for the reset to complete. Skipping the xhci handshake during a reset is a dangerous move. The xhci specification explicitly states that certain registers cannot be accessed during reset in section 5.4.1 USB Command Register (USBCMD), Host Controller Reset (HCRST) field: "This bit is cleared to '0' by the Host Controller when the reset process is complete. Software cannot terminate the reset process early by writinga '0' to this bit and shall not write any xHC Operational or Runtime registers until while HCRST is '1'." This behavior causes a regression on SNPS DWC3 USB controller with dual-role capability. When the DWC3 controller exits host mode and removes xhci while a reset is still in progress, and then tries to configure its hardware for device mode, the ongoing reset leads to register access issues; specifically, all register reads returns 0. These issues extend beyond the xhci register space (which is expected during a reset) and affect the entire DWC3 IP block, causing the DWC3 device mode to malfunction. Cc: stable <stable@kernel.org> Fixes: 6ccb83d ("usb: xhci: Implement xhci_handshake_check_state() helper") Signed-off-by: Roy Luo <royluo@google.com> Link: https://lore.kernel.org/r/20250522190912.457583-3-royluo@google.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8caccd2 commit 9f75893

File tree

3 files changed

+3
-30
lines changed

3 files changed

+3
-30
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,8 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
461461
* In the future we should distinguish between -ENODEV and -ETIMEDOUT
462462
* and try to recover a -ETIMEDOUT with a host controller reset.
463463
*/
464-
ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
465-
CMD_RING_RUNNING, 0, 5 * 1000 * 1000,
466-
XHCI_STATE_REMOVING);
464+
ret = xhci_handshake(&xhci->op_regs->cmd_ring,
465+
CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
467466
if (ret < 0) {
468467
xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret);
469468
xhci_halt(xhci);

drivers/usb/host/xhci.c

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -82,29 +82,6 @@ int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)
8282
return ret;
8383
}
8484

85-
/*
86-
* xhci_handshake_check_state - same as xhci_handshake but takes an additional
87-
* exit_state parameter, and bails out with an error immediately when xhc_state
88-
* has exit_state flag set.
89-
*/
90-
int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
91-
u32 mask, u32 done, int usec, unsigned int exit_state)
92-
{
93-
u32 result;
94-
int ret;
95-
96-
ret = readl_poll_timeout_atomic(ptr, result,
97-
(result & mask) == done ||
98-
result == U32_MAX ||
99-
xhci->xhc_state & exit_state,
100-
1, usec);
101-
102-
if (result == U32_MAX || xhci->xhc_state & exit_state)
103-
return -ENODEV;
104-
105-
return ret;
106-
}
107-
10885
/*
10986
* Disable interrupts and begin the xHCI halting process.
11087
*/
@@ -225,8 +202,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
225202
if (xhci->quirks & XHCI_INTEL_HOST)
226203
udelay(1000);
227204

228-
ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
229-
CMD_RESET, 0, timeout_us, XHCI_STATE_REMOVING);
205+
ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us);
230206
if (ret)
231207
return ret;
232208

drivers/usb/host/xhci.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,8 +1846,6 @@ void xhci_remove_secondary_interrupter(struct usb_hcd
18461846
/* xHCI host controller glue */
18471847
typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
18481848
int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us);
1849-
int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr,
1850-
u32 mask, u32 done, int usec, unsigned int exit_state);
18511849
void xhci_quiesce(struct xhci_hcd *xhci);
18521850
int xhci_halt(struct xhci_hcd *xhci);
18531851
int xhci_start(struct xhci_hcd *xhci);

0 commit comments

Comments
 (0)