From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
To: "fei.yang@intel.com" <fei.yang@intel.com>,
"felipe.balbi@linux.intel.com" <felipe.balbi@linux.intel.com>,
"john.stultz@linaro.org" <john.stultz@linaro.org>,
"andrzej.p@collabora.com" <andrzej.p@collabora.com>,
"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>,
"stable@vger.kernel.org" <stable@vger.kernel.org>
Subject: Re: [PATCH v3] usb: dwc3: gadget: trb_dequeue is not updated properly
Date: Fri, 19 Jul 2019 01:12:24 +0000 [thread overview]
Message-ID: <CY4PR1201MB003708ADAD79BF4FD24D3445AACB0@CY4PR1201MB0037.namprd12.prod.outlook.com> (raw)
In-Reply-To: 1563497183-7114-1-git-send-email-fei.yang@intel.com
Hi,
fei.yang@intel.com wrote:
> From: Fei Yang <fei.yang@intel.com>
>
> If scatter-gather operation is allowed, a large USB request is split into
> multiple TRBs. These TRBs are chained up by setting DWC3_TRB_CTRL_CHN bit
> except the last one which has DWC3_TRB_CTRL_IOC bit set instead.
> Since only the last TRB has IOC set for the whole USB request, the
> dwc3_gadget_ep_reclaim_trb_sg() gets called only once after the last TRB
> completes and all the TRBs allocated for this request are supposed to be
> reclaimed. However that is not what the current code does.
>
> dwc3_gadget_ep_reclaim_trb_sg() is trying to reclaim all the TRBs in the
> following for-loop,
> for_each_sg(sg, s, pending, i) {
> trb = &dep->trb_pool[dep->trb_dequeue];
>
> if (trb->ctrl & DWC3_TRB_CTRL_HWO)
> break;
>
> req->sg = sg_next(s);
> req->num_pending_sgs--;
>
> ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req,
> trb, event, status, chain);
> if (ret)
> break;
> }
> but since the interrupt comes only after the last TRB completes, the
> event->status has DEPEVT_STATUS_IOC bit set, so that the for-loop ends for
> the first TRB due to dwc3_gadget_ep_reclaim_completed_trb() returns 1.
> if (event->status & DEPEVT_STATUS_IOC)
> return 1;
>
> This patch addresses the issue by checking each TRB in function
> dwc3_gadget_ep_reclaim_trb_sg() and maing sure the chained ones are properly
> reclaimed. dwc3_gadget_ep_reclaim_completed_trb() will return 1 Only for the
> last TRB.
>
> Signed-off-by: Fei Yang <fei.yang@intel.com>
> Cc: stable <stable@vger.kernel.org>
> ---
> v2: Better solution is to reclaim chained TRBs in dwc3_gadget_ep_reclaim_trb_sg()
> and leave the last TRB to the dwc3_gadget_ep_reclaim_completed_trb().
> v3: Checking DWC3_TRB_CTRL_CHN bit for each TRB instead, and making sure that
> dwc3_gadget_ep_reclaim_completed_trb() returns 1 only for the last TRB.
> ---
> drivers/usb/dwc3/gadget.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 173f532..88eed49 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -2394,7 +2394,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
> if (event->status & DEPEVT_STATUS_SHORT && !chain)
> return 1;
>
> - if (event->status & DEPEVT_STATUS_IOC)
> + if (event->status & DEPEVT_STATUS_IOC && !chain)
> return 1;
>
> return 0;
> @@ -2404,11 +2404,12 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
> struct dwc3_request *req, const struct dwc3_event_depevt *event,
> int status)
> {
> - struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue];
> + struct dwc3_trb *trb;
> struct scatterlist *sg = req->sg;
> struct scatterlist *s;
> unsigned int pending = req->num_pending_sgs;
> unsigned int i;
> + int chain = false;
> int ret = 0;
>
> for_each_sg(sg, s, pending, i) {
> @@ -2419,9 +2420,13 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
>
> req->sg = sg_next(s);
> req->num_pending_sgs--;
> + if (trb->ctrl & DWC3_TRB_CTRL_CHN)
> + chain = true;
> + else
> + chain = false;
>
> ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req,
> - trb, event, status, true);
> + trb, event, status, chain);
> if (ret)
> break;
> }
There was already a fix a long time ago by Anurag. But it never made it
to the kernel mainline. You can check this out:
https://patchwork.kernel.org/patch/10640137/
Hi Felipe,
Maybe you can review and cherry-pick that patch?
Thanks,
Thinh
next prev parent reply other threads:[~2019-07-19 1:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-19 0:46 [PATCH v3] usb: dwc3: gadget: trb_dequeue is not updated properly fei.yang
2019-07-19 1:12 ` Thinh Nguyen [this message]
2019-07-23 18:51 ` John Stultz
2019-08-08 12:43 ` Felipe Balbi
2019-07-23 20:27 ` [PATCH] usb: dwc3: Check for IOC/LST bit in both event->status and TRB->ctrl fields John Stultz
2019-07-29 18:34 ` John Stultz
2019-07-19 7:32 ` [PATCH v3] usb: dwc3: gadget: trb_dequeue is not updated properly Felipe Balbi
2019-07-23 18:53 ` Yang, Fei
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=CY4PR1201MB003708ADAD79BF4FD24D3445AACB0@CY4PR1201MB0037.namprd12.prod.outlook.com \
--to=thinh.nguyen@synopsys.com \
--cc=andrzej.p@collabora.com \
--cc=fei.yang@intel.com \
--cc=felipe.balbi@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=john.stultz@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=stable@vger.kernel.org \
/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).