UPSTREAM: xhci: re-initialize the HC during resume if HCE was set
(Upstream commit 8b328f8002bcf29ef517ee4bf234e09aabec4d2e) When HCE(Host Controller Error) is set, it means an internal error condition has been detected. Software needs to re-initialize the HC, so add this check in xhci resume. Cc: stable@vger.kernel.org Signed-off-by: Puma Hsu <pumahsu@google.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20220215123320.1253947-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Bug: 210947520 Signed-off-by: Puma Hsu <pumahsu@google.com> Change-Id: If40d9f696972f5da94d0d3c6130e7060bfcae5a3
This commit is contained in:
@@ -1089,6 +1089,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
bool comp_timer_running = false;
|
bool comp_timer_running = false;
|
||||||
bool pending_portevent = false;
|
bool pending_portevent = false;
|
||||||
|
bool reinit_xhc = false;
|
||||||
|
|
||||||
if (!hcd->state)
|
if (!hcd->state)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1105,10 +1106,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
|
||||||
|
|
||||||
spin_lock_irq(&xhci->lock);
|
spin_lock_irq(&xhci->lock);
|
||||||
if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend)
|
|
||||||
hibernated = true;
|
|
||||||
|
|
||||||
if (!hibernated) {
|
if (hibernated || xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend)
|
||||||
|
reinit_xhc = true;
|
||||||
|
|
||||||
|
if (!reinit_xhc) {
|
||||||
/*
|
/*
|
||||||
* Some controllers might lose power during suspend, so wait
|
* Some controllers might lose power during suspend, so wait
|
||||||
* for controller not ready bit to clear, just as in xHC init.
|
* for controller not ready bit to clear, just as in xHC init.
|
||||||
@@ -1141,12 +1143,17 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
|
|||||||
spin_unlock_irq(&xhci->lock);
|
spin_unlock_irq(&xhci->lock);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
temp = readl(&xhci->op_regs->status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If restore operation fails, re-initialize the HC during resume */
|
temp = readl(&xhci->op_regs->status);
|
||||||
if ((temp & STS_SRE) || hibernated) {
|
|
||||||
|
|
||||||
|
/* re-initialize the HC on Restore Error, or Host Controller Error */
|
||||||
|
if (temp & (STS_SRE | STS_HCE)) {
|
||||||
|
reinit_xhc = true;
|
||||||
|
xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reinit_xhc) {
|
||||||
if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
|
if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
|
||||||
!(xhci_all_ports_seen_u0(xhci))) {
|
!(xhci_all_ports_seen_u0(xhci))) {
|
||||||
del_timer_sync(&xhci->comp_mode_recovery_timer);
|
del_timer_sync(&xhci->comp_mode_recovery_timer);
|
||||||
|
Reference in New Issue
Block a user