>On Tue, Nov 15, 2022 at 5:22 PM Pawel Laszczak <pawell@xxxxxxxxxxx> >wrote: >> >> Patch modifies the TD_SIZE in TRB before ZLP TRB. >> The TD_SIZE in TRB before ZLP TRB must be set to 1 to force processing >> ZLP TRB by controller. >> >> cc: <stable@xxxxxxxxxxxxxxx> >> Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence >> USBSSP DRD Driver") >> Signed-off-by: Pawel Laszczak <pawell@xxxxxxxxxxx> >> --- >> v2: >> - returned value for last TRB must be 0 >> v3: >> - fix issue for request->length > 64KB >> >> drivers/usb/cdns3/cdnsp-ring.c | 14 ++++++++++---- >> 1 file changed, 10 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/usb/cdns3/cdnsp-ring.c >> b/drivers/usb/cdns3/cdnsp-ring.c index 794e413800ae..86e1141e150f >> 100644 >> --- a/drivers/usb/cdns3/cdnsp-ring.c >> +++ b/drivers/usb/cdns3/cdnsp-ring.c >> @@ -1763,10 +1763,15 @@ static u32 cdnsp_td_remainder(struct >cdnsp_device *pdev, >> int trb_buff_len, >> unsigned int td_total_len, >> struct cdnsp_request *preq, >> - bool more_trbs_coming) >> + bool more_trbs_coming, >> + bool zlp) >> { >> u32 maxp, total_packet_count; >> >> + /* Before ZLP driver needs set TD_SIZE = 1. */ >> + if (zlp) >> + return 1; >> + > >Pawel, with your change, the TD_SIZE is 1 or 0, but not like the kernel doc >defined like below: Description is not added in kernel doc but is added before "if (zlp)". I will add as last lines in kernel doc the description: * * TD containing ZLP must have TD size set to one in penultimate TRB in TD. */ Will this patch be correct for you then? Pawel > >/* > * TD size is the number of max packet sized packets remaining in the TD > * (*not* including this TRB). > * > * Total TD packet count = total_packet_count = > * DIV_ROUND_UP(TD size in bytes / wMaxPacketSize) > * > * Packets transferred up to and including this TRB = packets_transferred = > * rounddown(total bytes transferred including this TRB / wMaxPacketSize) > * > * TD size = total_packet_count - packets_transferred > * > * It must fit in bits 21:17, so it can't be bigger than 31. > * This is taken care of in the TRB_TD_SIZE() macro > * > * The last TRB in a TD must have the TD size set to zero. > */ > >Peter > >> /* One TRB with a zero-length data packet. */ >> if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0) || >> trb_buff_len == td_total_len) @@ -1960,7 +1965,8 @@ int >> cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request >*preq) >> /* Set the TRB length, TD size, and interrupter fields. */ >> remainder = cdnsp_td_remainder(pdev, enqd_len, trb_buff_len, >> full_len, preq, >> - more_trbs_coming); >> + more_trbs_coming, >> + zero_len_trb); >> >> length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) | >> TRB_INTR_TARGET(0); @@ -2025,7 +2031,7 @@ int >> cdnsp_queue_ctrl_tx(struct cdnsp_device *pdev, struct cdnsp_request >> *preq) >> >> if (preq->request.length > 0) { >> remainder = cdnsp_td_remainder(pdev, 0, preq->request.length, >> - preq->request.length, preq, 1); >> + preq->request.length, >> + preq, 1, 0); >> >> length_field = TRB_LEN(preq->request.length) | >> TRB_TD_SIZE(remainder) | >> TRB_INTR_TARGET(0); @@ -2225,7 +2231,7 @@ static int >cdnsp_queue_isoc_tx(struct cdnsp_device *pdev, >> /* Set the TRB length, TD size, & interrupter fields. */ >> remainder = cdnsp_td_remainder(pdev, running_total, >> trb_buff_len, td_len, preq, >> - more_trbs_coming); >> + more_trbs_coming, 0); >> >> length_field = TRB_LEN(trb_buff_len) | >> TRB_INTR_TARGET(0); >> >> -- >> 2.25.1 >>