From: Felipe Balbi <balbi@kernel.org>
To: Baolin Wang <baolin.wang@linaro.org>, gregkh@linuxfoundation.org
Cc: peter@hurleysoftware.com, broonie@kernel.org,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
baolin.wang@linaro.org
Subject: Re: [PATCH] usb: dwc3: gadget: Add disconnect checking when changing function dynamically
Date: Thu, 08 Sep 2016 15:00:50 +0300 [thread overview]
Message-ID: <87oa3yha8d.fsf@linux.intel.com> (raw)
In-Reply-To: <2cb239ba53679a6fae1f4e1f14968e63fcd59e6b.1473334354.git.baolin.wang@linaro.org>
[-- Attachment #1: Type: text/plain, Size: 4253 bytes --]
Hi,
Baolin Wang <baolin.wang@linaro.org> writes:
> When we change the USB function with configfs dynamically, we possibly met this
> situation: one core is doing the control transfer, another core is trying to
> unregister the USB gadget from userspace, we must wait for completing this
> control tranfer, or it will hang the controller to set the DEVCTRLHLT flag.
>
> Also adding some disconnect checking to avoid queuing any requests when the
> gadget is stopped.
>
> Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
> ---
> drivers/usb/dwc3/ep0.c | 8 ++++++++
> drivers/usb/dwc3/gadget.c | 32 +++++++++++++++++++++++++++-----
> 2 files changed, 35 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
> index fe79d77..11519d7 100644
> --- a/drivers/usb/dwc3/ep0.c
> +++ b/drivers/usb/dwc3/ep0.c
> @@ -228,6 +228,14 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
> int ret;
>
> spin_lock_irqsave(&dwc->lock, flags);
> + if (dwc->pullups_connected == false) {
> + dwc3_trace(trace_dwc3_ep0,
> + "queuing request %p to %s when gadget is disconnected",
> + request, dep->name);
> + ret = -ESHUTDOWN;
> + goto out;
> + }
this could go on its own patch, however we can use if
(!dwc->pullups_connected) instead.
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 1783406..bbac8f5 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1040,6 +1040,13 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
> struct dwc3 *dwc = dep->dwc;
> int ret;
>
> + if (dwc->pullups_connected == false) {
> + dwc3_trace(trace_dwc3_gadget,
> + "queuing request %p to %s when gadget is disconnected",
> + &req->request, dep->endpoint.name);
> + return -ESHUTDOWN;
> + }
ditto
> @@ -1434,6 +1441,13 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
> if (pm_runtime_suspended(dwc->dev))
> return 0;
>
> + /*
> + * Per databook, when we want to stop the gadget, if a control transfer
> + * is still in process, complete it and get the core into setup phase.
> + */
Do you have the section reference for this? Which databook version are
you reading?
> + if (!is_on && dwc->ep0state != EP0_SETUP_PHASE)
> + return -EBUSY;
> +
> reg = dwc3_readl(dwc->regs, DWC3_DCTL);
> if (is_on) {
> if (dwc->revision <= DWC3_REVISION_187A) {
> @@ -1481,12 +1495,20 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
> struct dwc3 *dwc = gadget_to_dwc(g);
> unsigned long flags;
> int ret;
> + int timeout = 500;
>
> is_on = !!is_on;
>
> - spin_lock_irqsave(&dwc->lock, flags);
> - ret = dwc3_gadget_run_stop(dwc, is_on, false);
> - spin_unlock_irqrestore(&dwc->lock, flags);
> + do {
> + spin_lock_irqsave(&dwc->lock, flags);
> + ret = dwc3_gadget_run_stop(dwc, is_on, false);
> + spin_unlock_irqrestore(&dwc->lock, flags);
> +
> + if (ret != -EBUSY)
> + break;
> +
> + udelay(10);
> + } while (--timeout);
no, this is not a good idea at all. I'd rather see:
wait_event_timeout(dwc->wq, dwc->ep0state == EP0_SETUP_PHASE,
jiffies + msecs_to_jiffies(500));
or, perhaps, a wait_for_completion_timeout(). Then, ep0.c needs to call
complete() everytime Status Phase completes. That's probably a better
idea ;-)
> @@ -1990,7 +2012,7 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
> * dwc3_gadget_giveback(). If that happens, we're just gonna return 1
> * early on so DWC3_EP_BUSY flag gets cleared
> */
> - if (!dep->endpoint.desc)
> + if (!dep->endpoint.desc || dwc->pullups_connected == false)
is this really necessary? Can we really get pullups_connect set to false
with dep->endpoint.desc still valid?
> @@ -2064,7 +2086,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
> * dwc3_gadget_giveback(). If that happens, we're just gonna return 1
> * early on so DWC3_EP_BUSY flag gets cleared
> */
> - if (!dep->endpoint.desc)
> + if (!dep->endpoint.desc || dwc->pullups_connected == false)
ditto
--
balbi
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 800 bytes --]
next prev parent reply other threads:[~2016-09-08 12:01 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-08 11:36 [PATCH] usb: dwc3: gadget: Add disconnect checking when changing function dynamically Baolin Wang
2016-09-08 12:00 ` Felipe Balbi [this message]
2016-09-09 2:07 ` Baolin Wang
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=87oa3yha8d.fsf@linux.intel.com \
--to=balbi@kernel.org \
--cc=baolin.wang@linaro.org \
--cc=broonie@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=peter@hurleysoftware.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.