Re: [PATCH 3/3] usb: chipidea: udc: make isoc endpoint a bit error tolerant

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Sep 12, 2024 at 01:13:54AM -0400, Frank Li wrote:
> On Thu, Sep 12, 2024 at 11:35:51AM +0800, Xu Yang wrote:
> 
> usb: chipidea: udc: improve error recovery for ISO transfer

Okay.

> 
> > When a endpoint met errors, the usb controller will firstly assert
> > related error bit in status filed of dTD, then ENDPTCOMPLETE will be
> > asserted. Finally, USBSTS.UEI will be set.
> 
> Look like this information is not related with this patch.

I'll remove it.

> 
> >
> > Due to isoc transfers are error-tolerant transfers, we can make isoc
> > endpoint a bit error tolerant on device mode too. In case of error,
> > it's possilbe to resume the endpoint by reprime the corresponding
> > endpoint.
> 
> Impove device mode ISO transfer error tolerant by reprime the corresponding
> endpont.

Okay.

> 
> >
> > When error occurs, this will allow error dTD be deleted from dQH and
> > giveback request to user. Then, a reprime/prime operation is executed
> > depends on whether dQH is empty or not. If dQH is not empty, reprime
> > will be done during dequeue process. If dQH is empty, prime will be
> > done when new dTD is linked. In this way, isoc transfer can be recovered
> > from a small number of errors.
> 
> 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

Okay.

Thanks,
Xu Yang

> 
> >
> > Signed-off-by: Xu Yang <xu.yang_2@xxxxxxx>
> > ---
> >  drivers/usb/chipidea/udc.c | 12 +++++++-----
> >  1 file changed, 7 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
> > index 0ab57b87b07b..b1a1be6439b6 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;
> > @@ -707,7 +708,6 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
> >  		remaining_length >>= __ffs(TD_TOTAL_BYTES);
> >  		actual -= remaining_length;
> >
> > -		hwreq->req.status = tmptoken & TD_STATUS;
> >  		if ((TD_STATUS_HALTED & hwreq->req.status)) {
> >  			hwreq->req.status = -EPIPE;
> >  			break;
> > @@ -715,11 +715,13 @@ 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 = -EILSEQ;
> > +				break;
> > +			}
> >  		}
> >
> > -		if (remaining_length) {
> > +		if (remaining_length && !is_isoc) {
> >  			if (hwep->dir == TX) {
> >  				hwreq->req.status = -EPROTO;
> >  				break;
> > --
> > 2.34.1
> >




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux