MLK-23531 usb: dwc3: gadget: add skip_remain_trbs flag

If we're in the middle of series of chained TRBs and we
receive a short transfer along the way, DWC3 will skip
through all TRBs including the last TRB in the chain, DWC3
will avoid clearing HWO bit and SW has to do it manually.
but currect code can't hit the condition when loop sgs of
request in dwc3_gadget_ep_reclaim_trb_sg() if short packet
received for one chained trb, because it only check the HWO
bit of all trbs and then break if it's 1, so the remain trbs
has no chance to be handled by dwc3_gadget_ep_reclaim_completed_trb(),
this patch adds a flag if received a short packet in a chained
trb, and let dwc3_gadget_ep_reclaim_trb_sg() continue handle
all trbs and give back to function driver.

Reviewed-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
This commit is contained in:
Li Jun 2020-03-11 10:11:26 +08:00
parent cc381ad0ff
commit 65512083ef
2 changed files with 11 additions and 3 deletions

View File

@ -888,6 +888,8 @@ struct dwc3_hwparams {
* or unaligned OUT)
* @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped
* @skip_remain_trbs: true if a short packet received so the remain
chained trbs should be skipped.
*/
struct dwc3_request {
struct usb_request request;
@ -916,6 +918,7 @@ struct dwc3_request {
unsigned needs_extra_trb:1;
unsigned direction:1;
unsigned mapped:1;
unsigned skip_remain_trbs:1;
};
/*

View File

@ -180,6 +180,7 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
list_del(&req->list);
req->remaining = 0;
req->needs_extra_trb = false;
req->skip_remain_trbs = false;
if (req->request.status == -EINPROGRESS)
req->request.status = status;
@ -2433,8 +2434,12 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN)
return 1;
if (event->status & DEPEVT_STATUS_SHORT && !chain)
return 1;
if (event->status & DEPEVT_STATUS_SHORT) {
if (chain)
req->skip_remain_trbs = true;
else
return 1;
}
if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
(trb->ctrl & DWC3_TRB_CTRL_LST))
@ -2457,7 +2462,7 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
for_each_sg(sg, s, pending, i) {
trb = &dep->trb_pool[dep->trb_dequeue];
if (trb->ctrl & DWC3_TRB_CTRL_HWO)
if (trb->ctrl & DWC3_TRB_CTRL_HWO && !req->skip_remain_trbs)
break;
req->sg = sg_next(s);