Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Théo Lebrun and committed by
Greg Kroah-Hartman
34cca0ce 9925aa4b

+21 -22
+1 -1
drivers/usb/host/xhci-histb.c
··· 355 355 if (!device_may_wakeup(dev)) 356 356 xhci_histb_host_enable(histb); 357 357 358 - return xhci_resume(xhci, PMSG_RESUME); 358 + return xhci_resume(xhci, false, false); 359 359 } 360 360 361 361 static const struct dev_pm_ops xhci_histb_pm_ops = {
+5 -3
drivers/usb/host/xhci-pci.c
··· 807 807 808 808 static int xhci_pci_resume(struct usb_hcd *hcd, pm_message_t msg) 809 809 { 810 - struct xhci_hcd *xhci = hcd_to_xhci(hcd); 811 - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); 810 + struct xhci_hcd *xhci = hcd_to_xhci(hcd); 811 + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); 812 + bool power_lost = msg.event == PM_EVENT_RESTORE; 813 + bool is_auto_resume = msg.event == PM_EVENT_AUTO_RESUME; 812 814 813 815 reset_control_reset(xhci->reset); 814 816 ··· 841 839 if (xhci->quirks & XHCI_PME_STUCK_QUIRK) 842 840 xhci_pme_quirk(hcd); 843 841 844 - return xhci_resume(xhci, msg); 842 + return xhci_resume(xhci, power_lost, is_auto_resume); 845 843 } 846 844 847 845 static int xhci_pci_poweroff_late(struct usb_hcd *hcd, bool do_wakeup)
+5 -5
drivers/usb/host/xhci-plat.c
··· 479 479 return 0; 480 480 } 481 481 482 - static int xhci_plat_resume_common(struct device *dev, struct pm_message pmsg) 482 + static int xhci_plat_resume_common(struct device *dev, bool power_lost) 483 483 { 484 484 struct usb_hcd *hcd = dev_get_drvdata(dev); 485 485 struct xhci_hcd *xhci = hcd_to_xhci(hcd); ··· 501 501 if (ret) 502 502 goto disable_clks; 503 503 504 - ret = xhci_resume(xhci, pmsg); 504 + ret = xhci_resume(xhci, power_lost, false); 505 505 if (ret) 506 506 goto disable_clks; 507 507 ··· 522 522 523 523 static int xhci_plat_resume(struct device *dev) 524 524 { 525 - return xhci_plat_resume_common(dev, PMSG_RESUME); 525 + return xhci_plat_resume_common(dev, false); 526 526 } 527 527 528 528 static int xhci_plat_restore(struct device *dev) 529 529 { 530 - return xhci_plat_resume_common(dev, PMSG_RESTORE); 530 + return xhci_plat_resume_common(dev, true); 531 531 } 532 532 533 533 static int __maybe_unused xhci_plat_runtime_suspend(struct device *dev) ··· 548 548 struct usb_hcd *hcd = dev_get_drvdata(dev); 549 549 struct xhci_hcd *xhci = hcd_to_xhci(hcd); 550 550 551 - return xhci_resume(xhci, PMSG_AUTO_RESUME); 551 + return xhci_resume(xhci, false, true); 552 552 } 553 553 554 554 const struct dev_pm_ops xhci_plat_pm_ops = {
+1 -1
drivers/usb/host/xhci-tegra.c
··· 2287 2287 if (wakeup) 2288 2288 tegra_xhci_disable_phy_sleepwalk(tegra); 2289 2289 2290 - err = xhci_resume(xhci, is_auto_resume ? PMSG_AUTO_RESUME : PMSG_RESUME); 2290 + err = xhci_resume(xhci, false, is_auto_resume); 2291 2291 if (err < 0) { 2292 2292 dev_err(tegra->dev, "failed to resume XHCI: %d\n", err); 2293 2293 goto disable_phy;
+8 -11
drivers/usb/host/xhci.c
··· 994 994 * This is called when the machine transition from S3/S4 mode. 995 995 * 996 996 */ 997 - int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg) 997 + int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume) 998 998 { 999 - bool hibernated = (msg.event == PM_EVENT_RESTORE); 1000 999 u32 command, temp = 0; 1001 1000 struct usb_hcd *hcd = xhci_to_hcd(xhci); 1002 1001 int retval = 0; 1003 1002 bool comp_timer_running = false; 1004 1003 bool pending_portevent = false; 1005 1004 bool suspended_usb3_devs = false; 1006 - bool reinit_xhc = false; 1007 1005 1008 1006 if (!hcd->state) 1009 1007 return 0; ··· 1020 1022 1021 1023 spin_lock_irq(&xhci->lock); 1022 1024 1023 - if (hibernated || xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend) 1024 - reinit_xhc = true; 1025 + if (xhci->quirks & XHCI_RESET_ON_RESUME || xhci->broken_suspend) 1026 + power_lost = true; 1025 1027 1026 - if (!reinit_xhc) { 1028 + if (!power_lost) { 1027 1029 /* 1028 1030 * Some controllers might lose power during suspend, so wait 1029 1031 * for controller not ready bit to clear, just as in xHC init. ··· 1063 1065 /* re-initialize the HC on Restore Error, or Host Controller Error */ 1064 1066 if ((temp & (STS_SRE | STS_HCE)) && 1065 1067 !(xhci->xhc_state & XHCI_STATE_REMOVING)) { 1066 - reinit_xhc = true; 1067 - if (!xhci->broken_suspend) 1068 + if (!power_lost) 1068 1069 xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp); 1070 + power_lost = true; 1069 1071 } 1070 1072 1071 - if (reinit_xhc) { 1073 + if (power_lost) { 1072 1074 if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && 1073 1075 !(xhci_all_ports_seen_u0(xhci))) { 1074 1076 del_timer_sync(&xhci->comp_mode_recovery_timer); ··· 1166 1168 1167 1169 pending_portevent = xhci_pending_portevent(xhci); 1168 1170 1169 - if (suspended_usb3_devs && !pending_portevent && 1170 - msg.event == PM_EVENT_AUTO_RESUME) { 1171 + if (suspended_usb3_devs && !pending_portevent && is_auto_resume) { 1171 1172 msleep(120); 1172 1173 pending_portevent = xhci_pending_portevent(xhci); 1173 1174 }
+1 -1
drivers/usb/host/xhci.h
··· 1880 1880 int xhci_ext_cap_init(struct xhci_hcd *xhci); 1881 1881 1882 1882 int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); 1883 - int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg); 1883 + int xhci_resume(struct xhci_hcd *xhci, bool power_lost, bool is_auto_resume); 1884 1884 1885 1885 irqreturn_t xhci_irq(struct usb_hcd *hcd); 1886 1886 irqreturn_t xhci_msi_irq(int irq, void *hcd);