Commit 34cca0ce authored by Théo Lebrun's avatar Théo Lebrun Committed by Greg Kroah-Hartman
Browse files

usb: xhci: change xhci_resume() parameters to explicit the desired info



Previous signature was:

        int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg);

Internally, it extracted two information out of the message:
 - whether we are after hibernation: msg.event == PM_EVENT_RESTORE,
 - whether this is an auto resume: msg.event == PM_EVENT_AUTO_RESUME.

First bulletpoint is somewhat wrong: driver wants to know if the device
did lose power, it doesn't care about hibernation per se. Knowing that,
refactor to ask upper layers the right questions: (1) "did we lose
power?" and, (2) "is this an auto resume?". Change the signature to:

        int xhci_resume(struct xhci_hcd *xhci, bool power_lost,
                        bool is_auto_resume);

The goal is to allow some upper layers (cdns3-plat) to tell us when
power was lost after system-wise suspend.

Note that lost_power is ORed at the start of xhci_resume() to
xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend. It is
simpler to keep those checks inside of xhci_resume() instead of doing
them at each caller of xhci_resume().

Signed-off-by: default avatarThéo Lebrun <theo.lebrun@bootlin.com>
Link: https://lore.kernel.org/r/20250205-s2r-cdns-v7-7-13658a271c3c@bootlin.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9925aa4b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -355,7 +355,7 @@ static int __maybe_unused xhci_histb_resume(struct device *dev)
	if (!device_may_wakeup(dev))
		xhci_histb_host_enable(histb);

	return xhci_resume(xhci, PMSG_RESUME);
	return xhci_resume(xhci, false, false);
}

static const struct dev_pm_ops xhci_histb_pm_ops = {
+5 −3
Original line number Diff line number Diff line
@@ -809,6 +809,8 @@ static int xhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg)
{
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
	struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
	bool power_lost = msg.event == PM_EVENT_RESTORE;
	bool is_auto_resume = msg.event == PM_EVENT_AUTO_RESUME;

	reset_control_reset(xhci->reset);

@@ -839,7 +841,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg)
	if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
		xhci_pme_quirk(hcd);

	return xhci_resume(xhci, msg);
	return xhci_resume(xhci, power_lost, is_auto_resume);
}

static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
+5 −5
Original line number Diff line number Diff line
@@ -479,7 +479,7 @@ static int xhci_plat_suspend(struct device *dev)
	return 0;
}

static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg)
static int xhci_plat_resume_common(struct device *dev, bool power_lost)
{
	struct usb_hcd	*hcd = dev_get_drvdata(dev);
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
@@ -501,7 +501,7 @@ static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg)
	if (ret)
		goto disable_clks;

	ret = xhci_resume(xhci, pmsg);
	ret = xhci_resume(xhci, power_lost, false);
	if (ret)
		goto disable_clks;

@@ -522,12 +522,12 @@ static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg)

static int xhci_plat_resume(struct device *dev)
{
	return xhci_plat_resume_common(dev, PMSG_RESUME);
	return xhci_plat_resume_common(dev, false);
}

static int xhci_plat_restore(struct device *dev)
{
	return xhci_plat_resume_common(dev, PMSG_RESTORE);
	return xhci_plat_resume_common(dev, true);
}

static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev)
@@ -548,7 +548,7 @@ static int __maybe_unused xhci_plat_runtime_resume(struct device *dev)
	struct usb_hcd  *hcd = dev_get_drvdata(dev);
	struct xhci_hcd *xhci = hcd_to_xhci(hcd);

	return xhci_resume(xhci, PMSG_AUTO_RESUME);
	return xhci_resume(xhci, false, true);
}

const struct dev_pm_ops xhci_plat_pm_ops = {
+1 −1
Original line number Diff line number Diff line
@@ -2287,7 +2287,7 @@ static int tegra_xusb_exit_elpg(struct tegra_xusb *tegra, bool is_auto_resume)
	if (wakeup)
		tegra_xhci_disable_phy_sleepwalk(tegra);

	err = xhci_resume(xhci, is_auto_resume ? PMSG_AUTO_RESUME : PMSG_RESUME);
	err = xhci_resume(xhci, false, is_auto_resume);
	if (err < 0) {
		dev_err(tegra->dev, "failed to resume XHCI: %d\n", err);
		goto disable_phy;
+8 −11
Original line number Diff line number Diff line
@@ -994,16 +994,14 @@ EXPORT_SYMBOL_GPL(xhci_suspend);
 * This is called when the machine transition from S3/S4 mode.
 *
 */
int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume)
{
	bool			hibernated = (msg.event == PM_EVENT_RESTORE);
	u32			command, temp = 0;
	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
	int			retval = 0;
	bool			comp_timer_running = false;
	bool			pending_portevent = false;
	bool			suspended_usb3_devs = false;
	bool			reinit_xhc = false;

	if (!hcd->state)
		return 0;
@@ -1022,10 +1020,10 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)

	spin_lock_irq(&xhci->lock);

	if (hibernated || xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend)
		reinit_xhc = true;
	if (xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend)
		power_lost = true;

	if (!reinit_xhc) {
	if (!power_lost) {
		/*
		 * Some controllers might lose power during suspend, so wait
		 * for controller not ready bit to clear, just as in xHC init.
@@ -1065,12 +1063,12 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
	/* re-initialize the HC on Restore Error, or Host Controller Error */
	if ((temp & (STS_SRE | STS_HCE)) &&
	    !(xhci->xhc_state & XHCI_STATE_REMOVING)) {
		reinit_xhc = true;
		if (!xhci->broken_suspend)
		if (!power_lost)
			xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp);
		power_lost = true;
	}

	if (reinit_xhc) {
	if (power_lost) {
		if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
				!(xhci_all_ports_seen_u0(xhci))) {
			del_timer_sync(&xhci->comp_mode_recovery_timer);
@@ -1168,8 +1166,7 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)

		pending_portevent = xhci_pending_portevent(xhci);

		if (suspended_usb3_devs && !pending_portevent &&
		    msg.event == PM_EVENT_AUTO_RESUME) {
		if (suspended_usb3_devs && !pending_portevent && is_auto_resume) {
			msleep(120);
			pending_portevent = xhci_pending_portevent(xhci);
		}
Loading