ANDROID: vendor_hooks: Add hooks for xhci reset

Commit 6ccb83d6c497 ("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.

This behavior can cause issues 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.

An upstream fix [1] has been sent and is in review. Currently
maintainers are still debating the best way to fix the issue without
re-introducing the watchdog problem. Introduce this vendor hook for
the time being to meet the project timeline. The vendor hook allows
forcing a full xhci reset on removal, which can be set on DWC3
platforms to avoid the issue.

[1] https://lore.kernel.org/r/20250522190912.457583-1-royluo@google.com/

Bug: 399762532
Test: xhci removal succeeds
Change-Id: I3c7d82f20323fb298425c7f77d0031ed448334a1
Signed-off-by: Roy Luo <royluo@google.com>
This commit is contained in:
Roy Luo
2025-05-27 23:19:10 +00:00
parent dd8fcb5398
commit 32288ce2f2
3 changed files with 11 additions and 1 deletions

View File

@@ -676,3 +676,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_fault_pre_folio_locked);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_filemap_folio_mapped);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_remove_rmap_ptes);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_pageset_update);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_xhci_full_reset_on_remove);

View File

@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/dma-mapping.h>
#include <trace/hooks/usb.h>
#include "xhci.h"
#include "xhci-trace.h"
@@ -196,6 +197,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
u32 command;
u32 state;
int ret;
bool full_reset = 0;
state = readl(&xhci->op_regs->status);
@@ -224,8 +226,11 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
if (xhci->quirks & XHCI_INTEL_HOST)
udelay(1000);
trace_android_vh_xhci_full_reset_on_remove(&full_reset);
ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
CMD_RESET, 0, timeout_us, XHCI_STATE_REMOVING);
CMD_RESET, 0, timeout_us,
full_reset ? 0 : XHCI_STATE_REMOVING);
if (ret)
return ret;

View File

@@ -31,6 +31,10 @@ DECLARE_HOOK(android_vh_usb_new_device_added,
TP_PROTO(struct usb_device *udev, int *err),
TP_ARGS(udev, err));
DECLARE_HOOK(android_vh_xhci_full_reset_on_remove,
TP_PROTO(bool *full_reset),
TP_ARGS(full_reset));
#endif /* _TRACE_HOOK_USB_H */
/* This part must be outside protection */
#include <trace/define_trace.h>