--- /dev/null
+From 83810f84ecf11dfc5a9414a8b762c3501b328185 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 23 Jun 2022 14:19:43 +0300
+Subject: xhci: turn off port power in shutdown
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 83810f84ecf11dfc5a9414a8b762c3501b328185 upstream.
+
+If ports are not turned off in shutdown then runtime suspended
+self-powered USB devices may survive in U3 link state over S5.
+
+During subsequent boot, if firmware sends an IPC command to program
+the port in DISCONNECT state, it will time out, causing significant
+delay in the boot time.
+
+Turning off roothub port power is also recommended in xhci
+specification 4.19.4 "Port Power" in the additional note.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20220623111945.1557702-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-hub.c | 2 +-
+ drivers/usb/host/xhci.c | 15 +++++++++++++--
+ drivers/usb/host/xhci.h | 2 ++
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -566,7 +566,7 @@ struct xhci_hub *xhci_get_rhub(struct us
+ * It will release and re-aquire the lock while calling ACPI
+ * method.
+ */
+-static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
++void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd,
+ u16 index, bool on, unsigned long *flags)
+ {
+ struct xhci_hub *rhub;
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -775,6 +775,8 @@ static void xhci_stop(struct usb_hcd *hc
+ void xhci_shutdown(struct usb_hcd *hcd)
+ {
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++ unsigned long flags;
++ int i;
+
+ if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
+ usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
+@@ -790,12 +792,21 @@ void xhci_shutdown(struct usb_hcd *hcd)
+ del_timer_sync(&xhci->shared_hcd->rh_timer);
+ }
+
+- spin_lock_irq(&xhci->lock);
++ spin_lock_irqsave(&xhci->lock, flags);
+ xhci_halt(xhci);
++
++ /* Power off USB2 ports*/
++ for (i = 0; i < xhci->usb2_rhub.num_ports; i++)
++ xhci_set_port_power(xhci, xhci->main_hcd, i, false, &flags);
++
++ /* Power off USB3 ports*/
++ for (i = 0; i < xhci->usb3_rhub.num_ports; i++)
++ xhci_set_port_power(xhci, xhci->shared_hcd, i, false, &flags);
++
+ /* Workaround for spurious wakeups at shutdown with HSW */
+ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
+- spin_unlock_irq(&xhci->lock);
++ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ xhci_cleanup_msix(xhci);
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -2155,6 +2155,8 @@ int xhci_hub_control(struct usb_hcd *hcd
+ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
+ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
+ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd);
++void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, u16 index,
++ bool on, unsigned long *flags);
+
+ void xhci_hc_died(struct xhci_hcd *xhci);
+