On 24-09-26 10:29:05, 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. > > 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> Acked-by: Peter Chen <peter.chen@xxxxxxxxxx> > > --- > Changes in v2: > - modify comments > - fix kernel test robot build warning by using cpu_to_le32 > - add fix tag and cc stable > Changes in v3: > - remove fixes tag and stable maillist > --- > 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..0132bb25c9b5 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; > + > + /* 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 != cpu_to_le32(prevlastnode->dma)) > + goto done; > } > > /* QH configuration */ > -- > 2.34.1 >