[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <SN6PR07MB53927E089EB9CEC843E7FD00DD049@SN6PR07MB5392.namprd07.prod.outlook.com>
Date: Tue, 15 Nov 2022 09:31:48 +0000
From: Pawel Laszczak <pawell@...ence.com>
To: Peter Chen <hzpeterchen@...il.com>
CC: Peter Chen <peter.chen@...nel.org>,
"gregkh@...uxfoundation.org" <gregkh@...uxfoundation.org>,
"linux-usb@...r.kernel.org" <linux-usb@...r.kernel.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"stable@...r.kernel.org" <stable@...r.kernel.org>
Subject: RE: [PATCH v2] usb: cdnsp: fix issue with ZLP - added TD_SIZE = 1
>On Thu, Nov 10, 2022 at 1:38 PM Pawel Laszczak <pawell@...ence.com>
>wrote:
>>
>> >On Mon, Nov 7, 2022 at 1:39 PM Pawel Laszczak <pawell@...ence.com>
>> >wrote:
>> >>
>> >> >
>> >> >
>> >> >On 22-10-27 08:46:17, Pawel Laszczak wrote:
>> >> >>
>> >> >> >
>> >> >> >On 22-10-24 10:04:35, Pawel Laszczak 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@...r.kernel.org>
>> >> >> >> Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of
>> >> >> >> Cadence USBSSP DRD Driver")
>> >> >> >> Signed-off-by: Pawel Laszczak <pawell@...ence.com>
>> >> >> >>
>> >> >> >> ---
>> >> >> >> Changelog:
>> >> >> >> v2:
>> >> >> >> - returned value for last TRB must be 0
>> >> >> >>
>> >> >> >> drivers/usb/cdns3/cdnsp-ring.c | 7 ++++++-
>> >> >> >> 1 file changed, 6 insertions(+), 1 deletion(-)
>> >> >> >>
>> >> >> >> diff --git a/drivers/usb/cdns3/cdnsp-ring.c
>> >> >> >> b/drivers/usb/cdns3/cdnsp-ring.c index
>> >> >> >> 04dfcaa08dc4..aa79bce89d8a
>> >> >> >> 100644
>> >> >> >> --- a/drivers/usb/cdns3/cdnsp-ring.c
>> >> >> >> +++ b/drivers/usb/cdns3/cdnsp-ring.c
>> >> >> >> @@ -1769,8 +1769,13 @@ static u32 cdnsp_td_remainder(struct
>> >> >> >> cdnsp_device *pdev,
>> >> >> >>
>> >> >> >> /* One TRB with a zero-length data packet. */
>> >> >> >> if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0)
>||
>> >> >> >> - trb_buff_len == td_total_len)
>> >> >> >> + trb_buff_len == td_total_len) {
>> >> >> >> + /* Before ZLP driver needs set TD_SIZE=1. */
>> >> >> >> + if (more_trbs_coming)
>> >> >> >> + return 1;
>> >> >> >> +
>> >> >> >> return 0;
>> >> >> >> + }
>> >> >> >
>> >> >> >Does that fix the issue you want at bulk transfer, which has
>> >> >> >zero-length packet at the last packet? It seems not align with
>> >> >> >your previous
>> >> >fix.
>> >> >> >Would you mind explaining more?
>> >> >>
>> >> >> Value returned by function cdnsp_td_remainder is used as TD_SIZE
>> >> >> in TRB.
>> >> >>
>> >> >> The last TRB in TD should have TD_SIZE=0, so trb for ZLP should
>> >> >> have set also TD_SIZE=0. If driver set TD_SIZE=0 on before the
>> >> >> last one TRB then the controller stops the transfer and ignore
>> >> >> trb for ZLP
>> >packet.
>> >> >>
>> >> >> To fix this, the driver in such case must set TD_SIZE = 1 before
>> >> >> the last TRB.
>> >> >
>> >> > if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0)
>||
>> >> > - trb_buff_len == td_total_len)
>> >> > + trb_buff_len == td_total_len) {
>> >> > + /* Before ZLP driver needs set TD_SIZE=1. */
>> >> > + if (more_trbs_coming)
>> >> > + return 1;
>> >> > +
>> >> > return 0;
>> >> > + }
>> >> >
>> >> >How your above fix could return TD_SIZE as 1 for last non-ZLP TRB?
>> >> >Which conditions are satisfied?
>> >>
>> >> For last non-ZLP TRB TD_SIZE should be 0 or 1.
>> >>
>> >> We have three casess:
>> >> 1.
>> >> TRB1 - length > 1
>> >> TRb2 - ZLP
>> >>
>> >> In this case TRB1 should have set TD_SIZE = 1. In this case the condition
>> >> if (more_trbs_coming)
>> >> return 1;
>> >>
>> >> returns TD_SIZE=1. In this case more_trb_comming for TRB1 is 1 and
>> >> for
>> >> TRB2 is 0
>> >>
>> >
>> >This one is my question. How below condition is true for your case 1:
>> >
>> > if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0) ||
>> > trb_buff_len == td_total_len)
>>
>> For TRB1:
>> more_trbs_coming = true
>> transferred == 0 && trb_buff_len == 0 - false - it does not matter in this
>case
>> trb_buff_len == td_total_len - true
>
>Why trb_buff_len equals to td_total_length? Considering the bulk transfer
>with request length larger than 64KB.
>
You have right, there might still be a problem with ZLP.
I've posted the v3 implemented a little differently.
Thanks
Pawel
>
>> so whole condition is true.
>>
>> Because more_trb_comming = true so:
>> if (more_trbs_coming)
>> return 1;
>> returns TD_SIZE = 1
>>
>> For TRB2 - ZLP:
>> more_trbs_coming = false
>> transferred == 0 && trb_buff_len == 0 - false - it does not matter in this
>case
>> trb_buff_len == td_total_len - true
>>
>> Because more_trb_comming = false so function returns TD_SIZE = 0 for
>last ZLP trb.
>>
>> Pawel
Powered by blists - more mailing lists