summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
authorHenry Lin <henryl@nvidia.com>2022-04-08 16:48:22 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-05-12 13:20:19 +0300
commit318f86306de1b8346e89590b26f4735bef86ea68 (patch)
tree56c0574facbae45da687acbc8a08e02724ee3769 /drivers/usb/host/xhci.c
parente0b513c30826265f8310845a64b14b4db58b3566 (diff)
downloadlinux-318f86306de1b8346e89590b26f4735bef86ea68.tar.xz
xhci: stop polling roothubs after shutdown
commit dc92944a014cd6a6f6c94299aaa36164dd2c238a upstream. While rebooting, XHCI controller and its bus device will be shut down in order by .shutdown callback. Stopping roothubs polling in xhci_shutdown() can prevent XHCI driver from accessing port status after its bus device shutdown. Take PCIe XHCI controller as example, if XHCI driver doesn't stop roothubs polling, XHCI driver may access PCIe BAR register for port status after parent PCIe root port driver is shutdown and cause PCIe bus error. [check shared hcd exist before stopping its roothub polling -Mathias] Cc: stable@vger.kernel.org Signed-off-by: Henry Lin <henryl@nvidia.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20220408134823.2527272-3-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index ab255144e5a7..a9e72fee87a7 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -778,6 +778,17 @@ void xhci_shutdown(struct usb_hcd *hcd)
if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
+ /* Don't poll the roothubs after shutdown. */
+ xhci_dbg(xhci, "%s: stopping usb%d port polling.\n",
+ __func__, hcd->self.busnum);
+ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ del_timer_sync(&hcd->rh_timer);
+
+ if (xhci->shared_hcd) {
+ clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
+ del_timer_sync(&xhci->shared_hcd->rh_timer);
+ }
+
spin_lock_irq(&xhci->lock);
xhci_halt(xhci);
/* Workaround for spurious wakeups at shutdown with HSW */