Impove device mode ISO transfer error tolerant by reprime the corresponding endpoint. The recovery steps when error occurs: - Delete the error dTD from dQH and giveback request to user. - Do reprime if dQH is not empty. - Do prime when new dTD is queued if dQH is empty Acked-by: Peter Chen <peter.chen@xxxxxxxxxx> Signed-off-by: Xu Yang <xu.yang_2@xxxxxxx> --- Changes in v2: - modify commit message - keep "hwreq->req.status = tmptoken & TD_STATUS" - giveback status 0 to user for isoc error case Changes in v3: - add Acked-by tag --- drivers/usb/chipidea/udc.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 0132bb25c9b5..18c1882cf088 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -683,6 +683,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) unsigned remaining_length; unsigned actual = hwreq->req.length; struct ci_hdrc *ci = hwep->ci; + bool is_isoc = hwep->type == USB_ENDPOINT_XFER_ISOC; if (hwreq->req.status != -EALREADY) return -EINVAL; @@ -696,7 +697,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) int n = hw_ep_bit(hwep->num, hwep->dir); if (ci->rev == CI_REVISION_24 || - ci->rev == CI_REVISION_22) + ci->rev == CI_REVISION_22 || is_isoc) if (!hw_read(ci, OP_ENDPTSTAT, BIT(n))) reprime_dtd(ci, hwep, node); hwreq->req.status = -EALREADY; @@ -715,11 +716,15 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) hwreq->req.status = -EPROTO; break; } else if ((TD_STATUS_TR_ERR & hwreq->req.status)) { - hwreq->req.status = -EILSEQ; - break; + if (is_isoc) { + hwreq->req.status = 0; + } else { + hwreq->req.status = -EILSEQ; + break; + } } - if (remaining_length) { + if (remaining_length && !is_isoc) { if (hwep->dir == TX) { hwreq->req.status = -EPROTO; break; -- 2.34.1