diff mbox series

usb: dwc3: ep0: prevent dwc3_request from being queued twice

Message ID 20250327141630.2085029-1-fisaksen@baylibre.com
State New
Headers show
Series usb: dwc3: ep0: prevent dwc3_request from being queued twice | expand

Commit Message

Frode Isaksen March 27, 2025, 2:15 p.m. UTC
From: Frode Isaksen <frode@meta.com>

Prevent dwc3_request from being queued twice, by checking
req->status.
Similar to commit b2b6d601365a ("usb: dwc3: gadget: prevent
dwc3_request from being queued twice") for non-ep0 endpoints.
Crash log:
list_add double add: new=ffffff87ab2c7950, prev=ffffff87ab2c7950,
 next=ffffff87ab485b60.
kernel BUG at lib/list_debug.c:35!
Call trace:
__list_add_valid+0x70/0xc0
__dwc3_gadget_ep0_queue+0x70/0x224
dwc3_ep0_handle_status+0x118/0x200
dwc3_ep0_inspect_setup+0x144/0x32c
dwc3_ep0_interrupt+0xac/0x340
dwc3_process_event_entry+0x90/0x724
dwc3_process_event_buf+0x7c/0x33c
dwc3_thread_interrupt+0x58/0x8c

Signed-off-by: Frode Isaksen <frode@meta.com>
---
This bug was discovered, tested and fixed (no more crashes seen) on 
Meta Quest 3 device. Also tested on T.I. AM62x board.

 drivers/usb/dwc3/ep0.c    | 5 +++++
 drivers/usb/dwc3/gadget.c | 1 +
 2 files changed, 6 insertions(+)
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 666ac432f52d..e26c3a62d470 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -91,6 +91,11 @@  static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
 {
 	struct dwc3		*dwc = dep->dwc;
 
+	if (WARN(req->status < DWC3_REQUEST_STATUS_COMPLETED,
+				"%s: request %pK already in flight\n",
+				dep->name, &req->request))
+		return -EINVAL;
+
 	req->request.actual	= 0;
 	req->request.status	= -EINPROGRESS;
 	req->epnum		= dep->number;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 89a4dc8ebf94..c34446d8c54f 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -3002,6 +3002,7 @@  static int __dwc3_gadget_start(struct dwc3 *dwc)
 	dwc->ep0_bounced = false;
 	dwc->link_state = DWC3_LINK_STATE_SS_DIS;
 	dwc->delayed_status = false;
+	dwc->ep0_usb_req.status = DWC3_REQUEST_STATUS_UNKNOWN;
 	dwc3_ep0_out_start(dwc);
 
 	dwc3_gadget_enable_irq(dwc);