xhci: re-initialize the HC during resume if HCE was set
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>
This commit is contained in:
parent
d7c93a903f
commit
8b328f8002
1 changed files with 13 additions and 6 deletions
|
@ -1091,6 +1091,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;
|
||||||
|
@ -1107,10 +1108,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.
|
||||||
|
@ -1143,12 +1145,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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue