Re: [PATCH v2] usb: dwc3: core: resume xHCI child on runtime resume in host mode

From: Junzhong Pan

Date: Wed Sep 09 2026 - 08:39:43 EST


On 9/8/2026 10:16 PM, Troy Mitchell wrote:
> On Tue Sep 8, 2026 at 10:01 PM +08, Junzhong Pan wrote:
>> USB controller runtime suspend halts the controller on disconnection.
>> It relies on platforms with custom connection notification to start
>> the controller again.
>>
>> The host branch of dwc3_runtime_resume() does nothing currently. There
>> are two paths that can trigger a runtime resume of the dwc3 core in
>> host mode:
>>
>> (a) Wake lands on the xHCI child (DT platforms, e.g. Qualcomm, i.MX8MP)
>> A platform wakeup IRQ fires and the glue handler calls
>> pm_runtime_resume(&xhci->dev). Runtime PM walks upward, resumes
>> the dwc3 parent first, then resumes xHCI. Both wake correctly.
>>
>> (b) Wake lands on the dwc3 parent (ACPI platforms)
>> When an ACPI Notify(ACPI_NOTIFY_DEVICE_WAKE) targets the dwc3
>> parent device -- for example via a Generic Event Device on a
>> hardware-reduced platform where dwc3 is enumerated as an ACPI
>> device without a glue driver -- the ACPI core turns this into
>> pm_request_resume(dwc3_dev). Runtime PM does not propagate resume
>> downward, so the xHCI child stays suspended. Root hub polling is
>> never re-armed, and a device plugged in while suspended is silently
>> dropped.
>>
>> This patch fills in the host branch to cover case (b) by requesting an
>> async resume of the xHCI child so xhci_resume() can restore the port
>> state machine and re-arm root hub polling. Glue drivers in case (a)
>> resume xHCI directly, an extra call introduced by this change, but
>> runtime PM can serialize those requests and skip device already active,
>> so the extra resume call is safe. Those calls can be replaced with
>> resume calls to dwc3 device later.
>>
>> Tested on SpacemiT K3 Pico-ITX, covering both wakeup paths: an ACPI
>> boot with a GED device notifying the dwc3 node (HID 808622B7), and a
>> DT boot with a modified dwc3-generic-plat driver exposing a wakeup IRQ
>> similar to dwc3-qcom.c and dwc3-imx8mp.c. This is not validation on
>> actual Qualcomm or i.MX8MP hardware, changing those drivers would still
>> need platform-specific testing.
>>
>> Acked-by: Thinh Nguyen <Thinh.Nguyen@xxxxxxxxxxxx>
>> Assisted-by: Opencode:claude-opus-5
>> Signed-off-by: Junzhong Pan <panjunzhong@xxxxxxxxxxxxxxxxxx>
>> ---
>> Changes since RFC:
>> - add Assisted-By tag and collect tag
>> - refine the commit message and comments as suggested
>>
>> Link to RFC: https://lore.kernel.org/linux-usb/20260811090817.109350-1-panjunzhong@xxxxxxxxxxxxxxxxxx/
>> ---
>> drivers/usb/dwc3/core.c | 12 ++++++++++++
>> 1 file changed, 12 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index fd5c2cd36c59..76883dc6184c 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -2739,6 +2739,18 @@ int dwc3_runtime_resume(struct dwc3 *dwc)
>> }
>> break;
>> case DWC3_GCTL_PRTCAP_HOST:
>> + /*
>> + * Only the xHCI child's resume re-arms root hub polling, which
>> + * is what rediscovers a device plugged in while suspended.
>> + * Runtime PM doesn't resume children, so request it here.
>> + * Keep it asynchronous to avoid waiting for the parent's resume
>> + * callback to finish from inside it. Glue drivers may also
>> + * resume xHCI directly, but runtime PM will serialize those
>> + * requests and skips an already-active device.
>> + */
>> + if (dwc->xhci)
>> + pm_request_resume(&dwc->xhci->dev);
>> + break;
> Could we also check a parent-only resume with no USB wake event? For
> example, reading the DWC3 debugfs lsp_dump file calls
> pm_runtime_resume_and_get(dwc->dev). With both devices suspended, this
> change would wake xHCI too.
>

Thanks for pointing out, I did missed those paths before, I will do some
investigation and testing on the two non-wakeup path:debugfs attr access
and the dwc3_set_mode() path then report back.

> Would both devices return to autosuspend after the read and still
> detect a subsequent plug-in? This would help cover the non-wakeup
> case.
>> default:
>> /* do nothing */
>> break;
>>
>> ---
>> base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
>> change-id: 20260908-resume-xhci-0fa34ff9b332
>>
>> Best regards,
>
>