In dwc3_remove_requests(), the while loops clearing out request
lists req_queued and request_list may loop infinitely as the last
remaining elements in these lists end up not pointing to their
respective list_head structures. This workaround detects and
replaces the last element with the expected list_head to break out
of these loops. No memory is leaked as the previous last element gets
reused.

This issue occurs when Netconsole is active over Ethernet gadget,
and the cause it is still unclear. Any ideas?

Signed-off-by: Niel Fourie <lu...@denx.de>
Cc: Marek Vasut <ma...@denx.de>
---
 drivers/usb/dwc3/gadget.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index eb416b832a..61f3e367cb 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -538,6 +538,14 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct 
dwc3_ep *dep)
                        req = next_request(&dep->req_queued);
 
                        dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
+                       /* FIXME! */
+                       if (dep->req_queued.next == dep->req_queued.prev &&
+                           dep->req_queued.next != &dep->req_queued) {
+                               printf("Stuck? Emptying req_queued... head=%lx, 
next=%lx;\n",
+                                      (ulong)&dep->req_queued, 
(ulong)dep->req_queued.next);
+                               dep->req_queued.next = &dep->req_queued;
+                               dep->req_queued.prev = &dep->req_queued;
+                       }
                }
        }
 
@@ -545,6 +553,14 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct 
dwc3_ep *dep)
                req = next_request(&dep->request_list);
 
                dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
+               /* FIXME! */
+               if (dep->request_list.next == dep->request_list.prev &&
+                   dep->request_list.next != &dep->request_list) {
+                       printf("Stuck? Emptying request_list... head=%lx, 
next=%lx;\n",
+                              (ulong)&dep->request_list, 
(ulong)dep->request_list.next);
+                       dep->request_list.next = &dep->request_list;
+                       dep->request_list.prev = &dep->request_list;
+               }
        }
 }
 
-- 
2.39.0

Reply via email to