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: Théo Lebrun <theo.lebrun@bootlin.com>
Link: https://lore.kernel.org/r/20250205-s2r-cdns-v7-7-13658a271c3c@bootlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Théo Lebrun 2025-02-05 18:36:52 +01:00 committed by Greg Kroah-Hartman
parent 9925aa4b02
commit 34cca0ceab
6 changed files with 21 additions and 22 deletions

View File

@ -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 = {

View File

@ -807,8 +807,10 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
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);
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)

View File

@ -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 @@ disable_clks:
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 = {

View File

@ -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;

View File

@ -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);
}

View File

@ -1880,7 +1880,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
int xhci_ext_cap_init(struct xhci_hcd *xhci);
int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup);
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);
irqreturn_t xhci_irq(struct usb_hcd *hcd);
irqreturn_t xhci_msi_irq(int irq, void *hcd);