From d5736c3819d451202b250092e01bd6b84a308ae1 Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 27 Sep 2021 10:35:55 +0800 Subject: [PATCH] usb: dwc3: gadget: fix req list in miss isoc event processing If miss isoc event happens, the current code just move the current req to the tail of the pending list, and then stop the active transfer with cmd DWC3_DEPCMD_ENDTRANSFER. After these operations, the isoc endpoint wait for a XferNotReady event to restart the transfer with the first pending req from the pending_list. If there are already reqs in the pending list when move the miss isoc reqs to the tail of the pending list, some of the reqs are out of order. This patch first moves all of the reqs in the started list to the tail of the cancelled list, and then move all of the reqs in the pending list to the tail of the cancelled list. At last move all of the reqs in the cancelled list to the pending list. This can make sure all of the reqs are in order when restart the isoc transfer later. Signed-off-by: William Wu Change-Id: Idf38d9fd4d483854473c18f792d1996fb5fcab4b --- drivers/usb/dwc3/gadget.c | 24 +++++++++++++++++++++--- drivers/usb/dwc3/gadget.h | 2 -- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 924cd023636d..502262f9f455 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2869,12 +2869,15 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, */ req->remaining = 0; req->needs_extra_trb = false; - dwc3_gadget_move_queued_request(req); - if (req->trb) + dwc3_gadget_move_cancelled_request(req); + if (req->trb) { usb_gadget_unmap_request_by_dev(dwc->sysdev, &req->request, req->direction); - req->trb = NULL; + req->trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + req->trb = NULL; + } + ret = 0; goto out; } @@ -2930,6 +2933,8 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, { struct dwc3 *dwc = dep->dwc; unsigned status = 0; + struct dwc3_request *req; + struct dwc3_request *tmp; dwc3_gadget_endpoint_frame_from_event(dep, event); @@ -2941,6 +2946,19 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep, dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); + if (event->status & DEPEVT_STATUS_MISSED_ISOC && + !list_empty(&dep->cancelled_list) && + !list_empty(&dep->pending_list)) { + list_for_each_entry_safe(req, tmp, &dep->pending_list, list) + dwc3_gadget_move_cancelled_request(req); + } + + if (event->status & DEPEVT_STATUS_MISSED_ISOC && + !list_empty(&dep->cancelled_list)) { + list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) + dwc3_gadget_move_queued_request(req); + } + if (event->status & DEPEVT_STATUS_MISSED_ISOC && list_empty(&dep->started_list)) dwc3_stop_active_transfer(dep, true, true); diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index ba495ace7e51..9ca5ac361175 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -75,8 +75,6 @@ static inline void dwc3_gadget_move_queued_request(struct dwc3_request *req) { struct dwc3_ep *dep = req->dep; - if (req->trb) - req->trb->ctrl &= ~DWC3_TRB_CTRL_HWO; req->status = DWC3_REQUEST_STATUS_QUEUED; list_move_tail(&req->list, &dep->pending_list); }