All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathias Nyman <mathias.nyman@linux.intel.com>
To: <linux-usb@vger.kernel.org>, <stern@rowland.harvard.edu>
Cc: evgreen@google.com, shobhit.srivastava@intel.com,
	Mathias Nyman <mathias.nyman@linux.intel.com>
Subject: [RFC PATCH 1/1] xhci: pci: power off roothub ports in hibernate poweroff_late stage
Date: Tue,  7 Jun 2022 16:58:36 +0300	[thread overview]
Message-ID: <20220607135836.627711-2-mathias.nyman@linux.intel.com> (raw)
In-Reply-To: <20220607135836.627711-1-mathias.nyman@linux.intel.com>

Power off roothub ports in hibernate S4 poweroff_late stage to avoid
self-powered usb devices from surviving in U3 suspended state into
next reboot. Bootloader/firmware can't handle usb ports in U3, and
will timeout, causing extra delay during reboot/restore from S4.

Only turn off ports if xhci isn't capable of waking up from S4, as
turning off port power will disable remote wake for connected devices.

This is a bit of a hack, we create a custom non-constant dev_pm_ops
strucure for xhci-pci driver where we first copy the standard
usb_hcd_pci_pm_ops content, and then add the poweroff_late callback
to turn of port power for xhci-pci

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c |  4 ++--
 drivers/usb/host/xhci-pci.c | 32 +++++++++++++++++++++++++++++++-
 drivers/usb/host/xhci.h     |  2 ++
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index c54f2bc23d3f..dc404107f4d9 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -652,8 +652,8 @@ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd)
  * 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,
-				u16 index, bool on, unsigned long *flags)
+void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, u16 index,
+			 bool on, unsigned long *flags)
 	__must_hold(&xhci->lock)
 {
 	struct xhci_hub *rhub;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index fac9492a8bda..89c4c3f07a99 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -85,6 +85,7 @@
 static const char hcd_name[] = "xhci_hcd";
 
 static struct hc_driver __read_mostly xhci_pci_hc_driver;
+static struct dev_pm_ops xhci_hcd_pci_pm_ops;
 
 static int xhci_pci_setup(struct usb_hcd *hcd);
 
@@ -630,6 +631,32 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 	return retval;
 }
 
+static int xhci_pci_poweroff_late(struct device *dev)
+{
+	struct pci_dev          *pci_dev = to_pci_dev(dev);
+	struct usb_hcd          *hcd = pci_get_drvdata(pci_dev);
+	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+	unsigned long		flags;
+	int			i;
+
+	if (!device_may_wakeup(dev)) {
+		spin_lock_irqsave(&xhci->lock, flags);
+
+		/* 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);
+
+		spin_unlock_irqrestore(&xhci->lock, flags);
+	}
+
+	return 0;
+}
+
 static void xhci_pci_shutdown(struct usb_hcd *hcd)
 {
 	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
@@ -685,7 +712,7 @@ static struct pci_driver xhci_pci_driver = {
 	.shutdown = 	usb_hcd_pci_shutdown,
 #ifdef CONFIG_PM
 	.driver = {
-		.pm = &usb_hcd_pci_pm_ops
+		.pm = &xhci_hcd_pci_pm_ops
 	},
 #endif
 };
@@ -697,6 +724,9 @@ static int __init xhci_pci_init(void)
 	xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
 	xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
 	xhci_pci_hc_driver.shutdown = xhci_pci_shutdown;
+
+	xhci_hcd_pci_pm_ops = usb_hcd_pci_pm_ops;
+	xhci_hcd_pci_pm_ops.poweroff_late = xhci_pci_poweroff_late;
 #endif
 	return pci_register_driver(&xhci_pci_driver);
 }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 0bd76c94a4b1..28aaf031f9a8 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -2196,6 +2196,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
 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);
 
-- 
2.25.1


  reply	other threads:[~2022-06-07 13:57 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-07 13:58 [RFC PATCH 0/1] hibernate and roothub port power Mathias Nyman
2022-06-07 13:58 ` Mathias Nyman [this message]
2022-06-08  8:19 ` Oliver Neukum
2022-06-08 11:47   ` Mathias Nyman
2022-06-08 13:43     ` Alan Stern
2022-06-09  7:59       ` Mathias Nyman
2022-06-09 13:48         ` Alan Stern
2022-06-10 10:30           ` Mathias Nyman
2022-06-09 15:08         ` Evan Green
2022-06-14 10:07           ` Mathias Nyman
2022-07-20 21:53             ` Evan Green
2022-08-09 13:49               ` Mathias Nyman
2022-08-15 19:01                 ` Evan Green

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220607135836.627711-2-mathias.nyman@linux.intel.com \
    --to=mathias.nyman@linux.intel.com \
    --cc=evgreen@google.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=shobhit.srivastava@intel.com \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.