From: Felipe Balbi <balbi@kernel.org>
To: Anurag Kumar Vulisha <anuragku@xilinx.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "v.anuragkumar@gmail.com" <v.anuragkumar@gmail.com>,
Ajay Yugalkishore Pandey <APANDEY@xilinx.com>,
"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: usb: dwc3: gadget: Correct the logic for queuing sgs
Date: Fri, 23 Mar 2018 13:29:08 +0200 [thread overview]
Message-ID: <87lgejni7v.fsf@linux.intel.com> (raw)
(please configure your email client to break lines at 80 columns ;-)
Hi,
Anurag Kumar Vulisha <anuragku@xilinx.com> writes:
> Hi Felipe,
>
> Thanks for reviewing the patch , please find my comments inline
no issues :-)
>>Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com> writes:
>>> This patch fixes two issues
>>>
>>> 1. The code logic in dwc3_prepare_one_trb() incorrectly uses the
>>> address and length given in req packet even for scattergather lists.
>>> This patch correct's the code to use sg->address and sg->length when
>>> scattergather lists are present.
>>>
>>> 2. The present code correctly fetches the req's which were not queued
>>> from the started_list but fails to start from the sg where it
>>> previously stopped queuing because of the unavailable TRB's. This
>>> patch correct's the code to start queuing from the correct sg in sglist.
>>
>>these two should be in separate patches, then.
>>
> Will create separate patches in next version
thanks, that helps :-)
>>> Signed-off-by: Anurag Kumar Vulisha <anuragku@xilinx.com>
>>> ---
>>> drivers/usb/dwc3/core.h | 4 ++++
>>> drivers/usb/dwc3/gadget.c | 42
>>> ++++++++++++++++++++++++++++++++++++------
>>> 2 files changed, 40 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index
>>> 860d2bc..2779e58 100644
>>> --- a/drivers/usb/dwc3/core.h
>>> +++ b/drivers/usb/dwc3/core.h
>>> @@ -718,7 +718,9 @@ struct dwc3_hwparams {
>>> * @list: a list_head used for request queueing
>>> * @dep: struct dwc3_ep owning this request
>>> * @sg: pointer to first incomplete sg
>>> + * @sg_to_start: pointer to the sg which should be queued next
>>> * @num_pending_sgs: counter to pending sgs
>>> + * @num_queued_sgs: counter to the number of sgs which already got
>>> + queued
>>
>>this is the same as num_pending_sgs.
>
> num_pending_sgs is initially pointing to num_mapped_sgs, which gets
> decremented in dwc3_cleanup_done_reqs().
>
> Consider a case where the driver failed to queue all sgs into TRBs
> because of insufficient TRB number. For example, lets assume req has 5
> sgs and only 3 got queued. In this scenario ,when the
> dwc3_cleanup_done_reqs() gets called the value of num_pending_sgs =
> 5. Since the value of num_pending_sgs is greater than 0,
> __dwc3_gadget_kick_transfer() gets called with num_pending_sgs = 5-1 =
> 4.
>
> Eventually __dwc3_gadget_kick_transfer() calls
> dwc3_prepare_one_trb_sg() which has for_each_sg() call which loops for
> num_pending_sgs times (4 times in our example). This is incorrect,
> ideally it should be called only for 2 times because we have only 2
> sgs which previously were not queued.
>
> So, we added an extra flag num_queued_sgs which counts the number of
> sgs that got queued successfully and make for_each_sg() loop for
> num_mapped_sgs - num_queued_sgs times only . In our example case with
> the updated logic, it will loop for 5 - 3 = 2 times only. Because of
> this reason added num_queued_sgs flag. Please correct me if I am
> wrong.
That's true. Seems like we do need a new counter.
>>> static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep
>>> *dep,
>>>
>>> req->request.actual = length - req->remaining;
>>>
>>> - if ((req->request.actual < length) && req->num_pending_sgs)
>>> - return __dwc3_gadget_kick_transfer(dep);
>>> + if (req->request.actual < length ||
>>> + req->num_pending_sgs) {
>>
>>why do you think this needs to be || instead of &&? If actual == length we're
>>done, there's nothing more left to do. If there is either host sent more data than
>>it should, or we miscalculated num_pending_sgs, or we had the wrong length
>>somewhere in some TRBs. Either of those cases is an error condition we don't
>>want to hide. We want things to fail in that case.
>>
>
> Consider the same example that we had previously discussed, among the
> 5 sgs only 3 sgs got queued and all 3 sgs got completed
> successfully. The req->remaining field represents the size of TRB
> which was not transferred. In this example , as 3 sgs got completed
> successfully the req-> remaining = 0. So , request.actual = length - 0
> (req->remaining) which means request.actual == length. Because of
> this , the condition check if ((req->request.actual < length) &&
> req->num_pending_sgs) ) fails even though we have req->num_pending_sgs
> > 0. So, corrected the logic to always kick transfer for two
> conditions 1) if req->num_pending_sgs > 0 2) if ((req->request.actual
> < length) && req->num_pending_sgs)) condition satisfies. Please
> correct me If my understanding is wrong.
fair enough, but then we miss an important (IMO, that is) error case. If
req->num_pending_sgs > 0 && actual == length, then something is super
wrong. We may just add it as an extra check:
dev_WARN_ONCE(.... actual == len && num_pending_sgs);
next reply other threads:[~2018-03-23 11:29 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-23 11:29 Felipe Balbi [this message]
-- strict thread matches above, loose matches on Subject: below --
2018-03-24 17:53 usb: dwc3: gadget: Correct the logic for queuing sgs Anurag Kumar Vulisha
2018-03-19 14:12 Anurag Kumar Vulisha
2018-03-19 8:50 Felipe Balbi
2018-03-19 6:50 Anurag Kumar Vulisha
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87lgejni7v.fsf@linux.intel.com \
--to=balbi@kernel.org \
--cc=APANDEY@xilinx.com \
--cc=anuragku@xilinx.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=v.anuragkumar@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).