On Thu, Sep 12, 2024 at 12:54:53AM -0400, Frank Li wrote: > 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. Okay. > > > > > 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. Okay, will replace with it. Thanks, Xu Yang