On Thu, Sep 12, 2024 at 11:35:50AM +0800, Xu Yang wrote: > Currently, ATDTW semaphore is used to safety link new dTD to dQH. But this > code has a bug when the endpoint is already in error before polling ATDTW > or just met error during polling ATDTW. In that cases, ATDTW will never > turn to 1 and the cpu will busy loop there. It should be bug fixes, add fixes tag and cc stable. > > When the endpoint met error, ENDPTSTAT will be cleared by HW. Therefore, > ENDPTSTAT should also be considered during this process. In case of > endpoint error, the current dTD should not be pushed to the head of dQH > since some dTDs may be still not executed. Therefore, the link logic is > also improved accordingly. > > Signed-off-by: Xu Yang <xu.yang_2@xxxxxxx> > --- > drivers/usb/chipidea/udc.c | 9 ++++++++- > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c > index b9ccf62e0a50..0ab57b87b07b 100644 > --- a/drivers/usb/chipidea/udc.c > +++ b/drivers/usb/chipidea/udc.c > @@ -612,10 +612,17 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) > do { > hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW); > tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n)); > - } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW)); > + } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW) && tmp_stat); > hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0); > if (tmp_stat) > goto done; > + > + /* In case of error, ENDPTSTAT will also turn into 0, then > + * don't push this dTD to dQH head if current dTD pointer > + * is not the last dTD in previous request. > + */ OP_ENDPTSTAT will be clear by HW when the endpoint met err. This dTD don't push to dQH if current dTD point is not the last one in previous request. > + if (hwep->qh.ptr->curr != prevlastnode->dma) > + goto done; > } > > /* QH configuration */ > -- > 2.34.1 >