[PATCH v2 2/7] usb: dwc3: qcom: Distinguish PM and runtime suspend/resume paths

From: Faisal Hassan

Date: Thu Sep 03 2026 - 12:26:10 EST


The dwc3_qcom_suspend() and dwc3_qcom_resume() functions
handle both system PM and runtime PM paths but cannot
differentiate between them, preventing distinct power
management strategies.

Refactor suspend/resume functions to accept pm_message_t
instead of boolean wakeup flags. Use PMSG_IS_AUTO()
to identify runtime PM (PMSG_AUTO_SUSPEND/RESUME) versus
system PM (PMSG_SUSPEND/RESUME) paths.

Preserve existing wakeup behavior: always enable wakeup
for runtime suspend, check device_may_wakeup() for system
suspend.

Follow dwc3/core.c pattern to enable future per-path
strategies like differentiated power states.

Co-developed-by: Sriram Dash <sriram.dash@xxxxxxxxxxxxxxxx>
Signed-off-by: Sriram Dash <sriram.dash@xxxxxxxxxxxxxxxx>
Signed-off-by: Faisal Hassan <faisal.hassan@xxxxxxxxxxxxxxxx>
---
drivers/usb/dwc3/dwc3-qcom.c | 34 ++++++++++++++++++++++++++--------
1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 49698a31b2f4..6d25f81800a7 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -335,14 +335,24 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom)
dwc3_qcom_enable_port_interrupts(&qcom->ports[i]);
}

-static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
+static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, pm_message_t msg)
{
u32 val;
int i, ret;
+ bool wakeup;

if (qcom->is_suspended)
return 0;

+ /*
+ * For runtime suspend, always enable wakeup.
+ * For system suspend, check device wakeup capability.
+ */
+ if (PMSG_IS_AUTO(msg))
+ wakeup = true;
+ else
+ wakeup = device_may_wakeup(qcom->dev);
+
for (i = 0; i < qcom->num_ports; i++) {
val = readl(qcom->qscratch_base + pwr_evnt_irq_stat_reg[i]);
if (!(val & PWR_EVNT_LPM_IN_L2_MASK))
@@ -369,14 +379,24 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup)
return 0;
}

-static int dwc3_qcom_resume(struct dwc3_qcom *qcom, bool wakeup)
+static int dwc3_qcom_resume(struct dwc3_qcom *qcom, pm_message_t msg)
{
int ret;
int i;
+ bool wakeup;

if (!qcom->is_suspended)
return 0;

+ /*
+ * For runtime resume, always assume wakeup was enabled.
+ * For system resume, check device wakeup capability.
+ */
+ if (PMSG_IS_AUTO(msg))
+ wakeup = true;
+ else
+ wakeup = device_may_wakeup(qcom->dev);
+
if (dwc3_qcom_is_host(qcom) && wakeup)
dwc3_qcom_disable_interrupts(qcom);

@@ -759,14 +779,13 @@ static int dwc3_qcom_pm_suspend(struct device *dev)
{
struct dwc3 *dwc = dev_get_drvdata(dev);
struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
- bool wakeup = device_may_wakeup(dev);
int ret;

ret = dwc3_pm_suspend(&qcom->dwc);
if (ret)
return ret;

- ret = dwc3_qcom_suspend(qcom, wakeup);
+ ret = dwc3_qcom_suspend(qcom, PMSG_SUSPEND);
if (ret)
return ret;

@@ -779,10 +798,9 @@ static int dwc3_qcom_pm_resume(struct device *dev)
{
struct dwc3 *dwc = dev_get_drvdata(dev);
struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
- bool wakeup = device_may_wakeup(dev);
int ret;

- ret = dwc3_qcom_resume(qcom, wakeup);
+ ret = dwc3_qcom_resume(qcom, PMSG_RESUME);
if (ret)
return ret;

@@ -819,7 +837,7 @@ static int dwc3_qcom_runtime_suspend(struct device *dev)
if (ret)
return ret;

- return dwc3_qcom_suspend(qcom, true);
+ return dwc3_qcom_suspend(qcom, PMSG_AUTO_SUSPEND);
}

static int dwc3_qcom_runtime_resume(struct device *dev)
@@ -828,7 +846,7 @@ static int dwc3_qcom_runtime_resume(struct device *dev)
struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
int ret;

- ret = dwc3_qcom_resume(qcom, true);
+ ret = dwc3_qcom_resume(qcom, PMSG_AUTO_RESUME);
if (ret)
return ret;

--
2.34.1