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 <william.wu@rock-chips.com>
Change-Id: Idf38d9fd4d483854473c18f792d1996fb5fcab4b
This commit is contained in:
William Wu
2021-09-27 10:35:55 +08:00
parent 10a836e900
commit d5736c3819
2 changed files with 21 additions and 5 deletions

View File

@@ -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);

View File

@@ -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);
}