]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
658c76b55d19457aaeb77ed52c0db41434d1f2b0
[thirdparty/kernel/stable-queue.git] /
1 From 7838de15bb700c2898a7d741db9b1f3cbc86c136 Mon Sep 17 00:00:00 2001
2 From: Meng Li <Meng.Li@windriver.com>
3 Date: Tue, 18 Jun 2024 11:19:18 +0800
4 Subject: usb: dwc3: core: remove lock of otg mode during gadget suspend/resume to avoid deadlock
5
6 From: Meng Li <Meng.Li@windriver.com>
7
8 commit 7838de15bb700c2898a7d741db9b1f3cbc86c136 upstream.
9
10 When config CONFIG_USB_DWC3_DUAL_ROLE is selected, and trigger system
11 to enter suspend status with below command:
12 echo mem > /sys/power/state
13 There will be a deadlock issue occurring. Detailed invoking path as
14 below:
15 dwc3_suspend_common()
16 spin_lock_irqsave(&dwc->lock, flags); <-- 1st
17 dwc3_gadget_suspend(dwc);
18 dwc3_gadget_soft_disconnect(dwc);
19 spin_lock_irqsave(&dwc->lock, flags); <-- 2nd
20 This issue is exposed by commit c7ebd8149ee5 ("usb: dwc3: gadget: Fix
21 NULL pointer dereference in dwc3_gadget_suspend") that removes the code
22 of checking whether dwc->gadget_driver is NULL or not. It causes the
23 following code is executed and deadlock occurs when trying to get the
24 spinlock. In fact, the root cause is the commit 5265397f9442("usb: dwc3:
25 Remove DWC3 locking during gadget suspend/resume") that forgot to remove
26 the lock of otg mode. So, remove the redundant lock of otg mode during
27 gadget suspend/resume.
28
29 Fixes: 5265397f9442 ("usb: dwc3: Remove DWC3 locking during gadget suspend/resume")
30 Cc: Xu Yang <xu.yang_2@nxp.com>
31 Cc: stable@vger.kernel.org
32 Signed-off-by: Meng Li <Meng.Li@windriver.com>
33 Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
34 Link: https://lore.kernel.org/r/20240618031918.2585799-1-Meng.Li@windriver.com
35 Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
36 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
37 ---
38 drivers/usb/dwc3/core.c | 6 ------
39 1 file changed, 6 deletions(-)
40
41 --- a/drivers/usb/dwc3/core.c
42 +++ b/drivers/usb/dwc3/core.c
43 @@ -1735,7 +1735,6 @@ assert_reset:
44
45 static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
46 {
47 - unsigned long flags;
48 u32 reg;
49
50 switch (dwc->current_dr_role) {
51 @@ -1773,9 +1772,7 @@ static int dwc3_suspend_common(struct dw
52 break;
53
54 if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
55 - spin_lock_irqsave(&dwc->lock, flags);
56 dwc3_gadget_suspend(dwc);
57 - spin_unlock_irqrestore(&dwc->lock, flags);
58 synchronize_irq(dwc->irq_gadget);
59 }
60
61 @@ -1792,7 +1789,6 @@ static int dwc3_suspend_common(struct dw
62
63 static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
64 {
65 - unsigned long flags;
66 int ret;
67 u32 reg;
68
69 @@ -1841,9 +1837,7 @@ static int dwc3_resume_common(struct dwc
70 if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
71 dwc3_otg_host_init(dwc);
72 } else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
73 - spin_lock_irqsave(&dwc->lock, flags);
74 dwc3_gadget_resume(dwc);
75 - spin_unlock_irqrestore(&dwc->lock, flags);
76 }
77
78 break;