linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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 --]

  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 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).