All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Mathias Nyman <mathias.nyman@linux.intel.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Sasha Levin <sashal@kernel.org>,
	mathias.nyman@intel.com, evgreen@chromium.org,
	yj84.jang@samsung.com, stern@rowland.harvard.edu,
	bhelgaas@google.com, heikki.krogerus@linux.intel.com,
	christophe.leroy@csgroup.eu, linux-usb@vger.kernel.org
Subject: [PATCH AUTOSEL 6.1 21/26] xhci: disable U3 suspended ports in S4 hibernate poweroff_late stage
Date: Fri, 23 Dec 2022 20:29:25 -0500	[thread overview]
Message-ID: <20221224012930.392358-21-sashal@kernel.org> (raw)
In-Reply-To: <20221224012930.392358-1-sashal@kernel.org>

From: Mathias Nyman <mathias.nyman@linux.intel.com>

[ Upstream commit c3bbacd61baace2f4fbab17012c3d149df2d50f1 ]

Disable U3 suspended ports in hibernate S4 poweroff_late for systems
with XHCI_RESET_TO_DEFAULT quirk, if wakeup is not enabled.

This reduces the number of self-powered usb devices from surviving in
U3 suspended state into next reboot.

Bootloader/firmware on these systems can't handle usb ports in U3, and
will timeout, causing extra delay during reboot/restore from S4.

Add pci_poweroff_late() callback to struct usb_hcd to get this done at
the correct stage in hibernate.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20221130091944.2171610-5-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/usb/core/hcd-pci.c  | 13 ++++++++++
 drivers/usb/host/xhci-pci.c | 52 +++++++++++++++++++++++++++++++++++++
 include/linux/usb/hcd.h     |  3 +++
 3 files changed, 68 insertions(+)

diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 9b77f49b3560..ab2f3737764e 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -558,6 +558,17 @@ static int hcd_pci_suspend_noirq(struct device *dev)
 	return retval;
 }
 
+static int hcd_pci_poweroff_late(struct device *dev)
+{
+	struct pci_dev		*pci_dev = to_pci_dev(dev);
+	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
+
+	if (hcd->driver->pci_poweroff_late && !HCD_DEAD(hcd))
+		return hcd->driver->pci_poweroff_late(hcd, device_may_wakeup(dev));
+
+	return 0;
+}
+
 static int hcd_pci_resume_noirq(struct device *dev)
 {
 	powermac_set_asic(to_pci_dev(dev), 1);
@@ -578,6 +589,7 @@ static int hcd_pci_restore(struct device *dev)
 
 #define hcd_pci_suspend		NULL
 #define hcd_pci_suspend_noirq	NULL
+#define hcd_pci_poweroff_late	NULL
 #define hcd_pci_resume_noirq	NULL
 #define hcd_pci_resume		NULL
 #define hcd_pci_restore		NULL
@@ -615,6 +627,7 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = {
 	.thaw_noirq	= NULL,
 	.thaw		= hcd_pci_resume,
 	.poweroff	= hcd_pci_suspend,
+	.poweroff_late	= hcd_pci_poweroff_late,
 	.poweroff_noirq	= hcd_pci_suspend_noirq,
 	.restore_noirq	= hcd_pci_resume_noirq,
 	.restore	= hcd_pci_restore,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 7bccbe50bab1..f8100aa2f5d0 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -620,6 +620,57 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 	return retval;
 }
 
+static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
+{
+	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+	struct xhci_port	*port;
+	struct usb_device	*udev;
+	unsigned int		slot_id;
+	u32			portsc;
+	int			i;
+
+	/*
+	 * Systems with XHCI_RESET_TO_DEFAULT quirk have boot firmware that
+	 * cause significant boot delay if usb ports are in suspended U3 state
+	 * during boot. Some USB devices survive in U3 state over S4 hibernate
+	 *
+	 * Disable ports that are in U3 if remote wake is not enabled for either
+	 * host controller or connected device
+	 */
+
+	if (!(xhci->quirks & XHCI_RESET_TO_DEFAULT))
+		return 0;
+
+	for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
+		port = &xhci->hw_ports[i];
+		portsc = readl(port->addr);
+
+		if ((portsc & PORT_PLS_MASK) != XDEV_U3)
+			continue;
+
+		slot_id = xhci_find_slot_id_by_port(port->rhub->hcd, xhci,
+						    port->hcd_portnum + 1);
+		if (!slot_id || !xhci->devs[slot_id]) {
+			xhci_err(xhci, "No dev for slot_id %d for port %d-%d in U3\n",
+				 slot_id, port->rhub->hcd->self.busnum, port->hcd_portnum + 1);
+			continue;
+		}
+
+		udev = xhci->devs[slot_id]->udev;
+
+		/* if wakeup is enabled then don't disable the port */
+		if (udev->do_remote_wakeup && do_wakeup)
+			continue;
+
+		xhci_dbg(xhci, "port %d-%d in U3 without wakeup, disable it\n",
+			 port->rhub->hcd->self.busnum, port->hcd_portnum + 1);
+		portsc = xhci_port_state_to_neutral(portsc);
+		writel(portsc | PORT_PE, port->addr);
+	}
+
+	return 0;
+}
+
 static void xhci_pci_shutdown(struct usb_hcd *hcd)
 {
 	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
@@ -686,6 +737,7 @@ static int __init xhci_pci_init(void)
 #ifdef CONFIG_PM
 	xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
 	xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
+	xhci_pci_hc_driver.pci_poweroff_late = xhci_pci_poweroff_late;
 	xhci_pci_hc_driver.shutdown = xhci_pci_shutdown;
 #endif
 	return pci_register_driver(&xhci_pci_driver);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 78cd566ee238..b51c07111729 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -269,6 +269,9 @@ struct hc_driver {
 	/* called after entering D0 (etc), before resuming the hub */
 	int	(*pci_resume)(struct usb_hcd *hcd, bool hibernated);
 
+	/* called just before hibernate final D3 state, allows host to poweroff parts */
+	int	(*pci_poweroff_late)(struct usb_hcd *hcd, bool do_wakeup);
+
 	/* cleanly make HCD stop writing memory and doing I/O */
 	void	(*stop) (struct usb_hcd *hcd);
 
-- 
2.35.1


  parent reply	other threads:[~2022-12-24  1:32 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-24  1:29 [PATCH AUTOSEL 6.1 01/26] gpiolib: of: add a quirk for legacy names in Mediatek mt2701-cs42448 Sasha Levin
2022-12-24  1:29 ` Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 02/26] gpiolib: of: consolidate simple renames into a single quirk Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 03/26] gpiolib: of: tighten selection of gpio renaming quirks Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 04/26] gpiolib: of: add quirk for locating reset lines with legacy bindings Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 05/26] gpiolib: of: add a quirk for reset line for Marvell NFC controller Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 06/26] gpiolib: of: add a quirk for reset line for Cirrus CS42L56 codec Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 07/26] gpiolib: of: add a quirk for legacy names in MOXA ART RTC Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 08/26] kset: fix memory leak when kset_register() returns error Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 09/26] USB: core: Change configuration warnings to notices Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 10/26] usb: core: stop USB enumeration if too many retries Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 11/26] usb: gadget: aspeed: fix buffer overflow Sasha Levin
2022-12-24  1:29   ` Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 12/26] usb: gadget: u_ether: Do not make UDC parent of the net device Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 13/26] usb: gadget: f_ecm: Always set current gadget in ecm_bind() Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 14/26] devres: Use kmalloc_size_roundup() to match ksize() usage Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 15/26] chardev: Fix potential memory leak when cdev_add() failed Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 16/26] usb/usbip: Fix v_recv_cmd_submit() to use PIPE_BULK define Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 17/26] char: xillybus: Prevent use-after-free due to race condition Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 18/26] habanalabs: zero ts registration buff when allocated Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 19/26] char: xillybus: Fix trivial bug with mutex Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 20/26] iio: filter: admv8818: close potential out-of-bounds read in __admv8818_read_[h|l]pf_freq() Sasha Levin
2022-12-24  1:29 ` Sasha Levin [this message]
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 22/26] ACPICA: Fix operand resolution Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 23/26] ksmbd: Fix resource leak in smb2_lock() Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 24/26] writeback: Add asserts for adding freed inode to lists Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 25/26] exfat: fix overflow in sector and cluster conversion Sasha Levin
2022-12-24  1:29 ` [PATCH AUTOSEL 6.1 26/26] fbdev: smscufx: fix error handling code in ufx_usb_probe Sasha Levin
2022-12-24  1:29   ` Sasha Levin

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=20221224012930.392358-21-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=bhelgaas@google.com \
    --cc=christophe.leroy@csgroup.eu \
    --cc=evgreen@chromium.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@intel.com \
    --cc=mathias.nyman@linux.intel.com \
    --cc=stable@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=yj84.jang@samsung.com \
    /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.