mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user