RE: [PATCH] usb: dwc3: core: remove lock of otg mode during gadget suspend/resume to avoid deadlock

From: Li, Meng
Date: Thu Jun 13 2024 - 03:28:36 EST


Sorry! please ignore this patch that is for the linux-stable kernel.
I will create another one for mainline upstream.

Thanks,
LImeng

> -----Original Message-----
> From: Li, Meng <Meng.Li@xxxxxxxxxxxxx>
> Sent: Thursday, June 13, 2024 3:23 PM
> To: Thinh.Nguyen@xxxxxxxxxxxx; gregkh@xxxxxxxxxxxxxxxxxxx;
> quic_uaggarwa@xxxxxxxxxxx; linux-usb@xxxxxxxxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx
> Cc: Li, Meng <Meng.Li@xxxxxxxxxxxxx>
> Subject: [PATCH] usb: dwc3: core: remove lock of otg mode during gadget
> suspend/resume to avoid deadlock
>
> When config CONFIG_USB_DWC3_DUAL_ROLE is selected, and trigger system
> to enter suspend status with below command:
> echo mem > /sys/power/state
> There will be a deadlock issue occurring. Because dwc3_gadget_suspend() also
> try to get the lock again when previous invoked dwc3_suspend_common()
> has got the lock . This issue is introduced by commit c7ebd8149ee5 ("usb:
> dwc3:
> gadget: Fix NULL pointer dereference in dwc3_gadget_suspend") that removes
> the code of checking whether dwc->gadget_driver is NULL or not. It causes the
> following code is executed and deadlock occurs when trying to get the
> spinlock.
> To fix the deadlock issue, refer to commit 5265397f9442("usb: dwc3: Remove
> DWC3 locking during gadget suspend/resume"), remove lock of otg mode
> during gadget suspend/resume.
>
> Fixes: c7ebd8149ee5 ("Fix NULL pointer dereference in
> dwc3_gadget_suspend")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Meng Li <Meng.Li@xxxxxxxxxxxxx>
> ---
> drivers/usb/dwc3/core.c | 6 ------
> 1 file changed, 6 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index
> a8fb10cc65bc..9bb4ab409bbb 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -2112,7 +2112,6 @@ static int dwc3_core_init_for_resume(struct dwc3
> *dwc)
>
> static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) {
> - unsigned long flags;
> u32 reg;
>
> switch (dwc->current_dr_role) {
> @@ -2150,9 +2149,7 @@ static int dwc3_suspend_common(struct dwc3
> *dwc, pm_message_t msg)
> break;
>
> if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
> - spin_lock_irqsave(&dwc->lock, flags);
> dwc3_gadget_suspend(dwc);
> - spin_unlock_irqrestore(&dwc->lock, flags);
> synchronize_irq(dwc->irq_gadget);
> }
>
> @@ -2169,7 +2166,6 @@ static int dwc3_suspend_common(struct dwc3
> *dwc, pm_message_t msg)
>
> static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) {
> - unsigned long flags;
> int ret;
> u32 reg;
>
> @@ -2227,9 +2223,7 @@ static int dwc3_resume_common(struct dwc3
> *dwc, pm_message_t msg)
> if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
> dwc3_otg_host_init(dwc);
> } else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE)
> {
> - spin_lock_irqsave(&dwc->lock, flags);
> dwc3_gadget_resume(dwc);
> - spin_unlock_irqrestore(&dwc->lock, flags);
> }
>
> break;
> --
> 2.34.1