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:
@@ -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_filemap_folio_mapped);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_remove_rmap_ptes);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_remove_rmap_ptes);
|
||||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_pageset_update);
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_pageset_update);
|
||||||
|
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_xhci_full_reset_on_remove);
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <trace/hooks/usb.h>
|
||||||
|
|
||||||
#include "xhci.h"
|
#include "xhci.h"
|
||||||
#include "xhci-trace.h"
|
#include "xhci-trace.h"
|
||||||
@@ -196,6 +197,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
|
|||||||
u32 command;
|
u32 command;
|
||||||
u32 state;
|
u32 state;
|
||||||
int ret;
|
int ret;
|
||||||
|
bool full_reset = 0;
|
||||||
|
|
||||||
state = readl(&xhci->op_regs->status);
|
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)
|
if (xhci->quirks & XHCI_INTEL_HOST)
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
|
|
||||||
|
trace_android_vh_xhci_full_reset_on_remove(&full_reset);
|
||||||
|
|
||||||
ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command,
|
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@@ -31,6 +31,10 @@ DECLARE_HOOK(android_vh_usb_new_device_added,
|
|||||||
TP_PROTO(struct usb_device *udev, int *err),
|
TP_PROTO(struct usb_device *udev, int *err),
|
||||||
TP_ARGS(udev, 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 */
|
#endif /* _TRACE_HOOK_USB_H */
|
||||||
/* This part must be outside protection */
|
/* This part must be outside protection */
|
||||||
#include <trace/define_trace.h>
|
#include <trace/define_trace.h>
|
||||||
|
Reference in New Issue
Block a user