All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Stern <stern@rowland.harvard.edu>
To: Felipe Balbi <balbi@kernel.org>
Cc: Baolin Wang <baolin.wang@linaro.org>,
	Greg KH <gregkh@linuxfoundation.org>,
	USB <linux-usb@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Linaro Kernel Mailman List <linaro-kernel@lists.linaro.org>,
	Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH] usb: dwc3: ep0: Fix the possible missed request for handling delay STATUS phase
Date: Mon, 16 Jan 2017 12:53:08 -0500 (EST)	[thread overview]
Message-ID: <Pine.LNX.4.44L0.1701161209560.17898-100000@netrider.rowland.org> (raw)
In-Reply-To: <8760lfmcof.fsf@linux.intel.com>

On Mon, 16 Jan 2017, Felipe Balbi wrote:

> >>>> Another point here is that the really robust way of fixing this is to
> >>>> get rid of USB_GADGET_DELAYED_STATUS altogether and just make sure
> >>>> gadget drivers know how to queue requests for all three phases of a
> >>>> Control Transfer.
> >>>>
> >>>> A lot of code will be removed from all gadget drivers and UDC drivers
> >>>> while combining all of it in a single place in composite.c.

Don't forget the legacy drivers.

> >>>>
> >>>> The reason I'm saying this is that other UDC drivers might have similar
> >>>> races already but they just haven't triggered.

> >> Alright, it's important enough to fix this bug. Can you also have a look
> >> into dropping USB_GADGET_DELAYED_STATUS altogether? If you're too busy,
> >> no issues. It'll stay in my queue.
> >
> > Okay, I will have a look at f_mass_storage driver to see if we can
> > drop USB_GADGET_DELAYED_STATUS. Thanks.
> 
> not only mass storage. It needs to be done for all drivers. The way to
> do that is to teach functions that control transfers are composed of two
> or three phases. If you look at UDC drivers today, they all have
> peculiarities about control transfers to handle stuff that *maybe*
> gadget drivers won't handle.
> 
> What we should do here is make sure that *all* 3 phases always have a
> matching usb_ep_queue() coming from the upper layers. Whether
> composite.c or f_*.c handles it, that's an implementation detail. But
> just to illustrate the problem, we should be able to get rid of
> dwc3_ep0_out_start() and assume that the upper layer will call
> usb_ep_queue() when it wants to receive a new SETUP packet.
> 
> Likewise, we should be able to assume that STATUS phase will only start
> based on a usb_ep_queue() call. That way we can remove
> USB_GADGET_DELAYED_STATUS altogether, because that will *always* be the
> case. There will be no races to handle apart from the normal case where
> XferNotReady can come before or after usb_ep_queue(), but we already
> have proper handling for that too.

It sounds like you're talking about a major change in the way the 
gadget subsystem handles control requests.

We can distinguish three cases.  In the existing implementation, they 
work like this:

    (1) Control-OUT with no data stage.  The gadget driver's setup
	routine either queues a request on ep0, which the UDC driver 
	uses for the status stage transfer (so it should be a length-0 
	IN transfer) and returns 0, or else returns an error, in which
	case the UDC driver sends a protocol STALL for the status 
	stage.

	(What the UDC driver should do if the setup routine queues a
	request on ep0 and then returns an error is undefined.)

    (2) Control-OUT with a data stage.  The gadget driver's setup 
	routine either queues an OUT request on ep0, which the UDC
	driver uses for the data stage transfer, or else returns an
	error, in which case the UDC driver sends a protocol STALL for
	the data stage.  In the first case, the UDC driver 
	automatically queues a 0-length IN request for the status 
	stage; the gadget driver does not get any chance to fail the
	transfer after the host's data has been successfully received.
	(IMO this is a bug in the design of the gadget subsystem.)

    (3) Control-IN with a data stage.  The gadget driver's setup 
	routine either queues an IN request on ep0, which the UDC
	driver uses for the data stage transfer, or else returns an
	error, in which case the UDC driver sends a protocol STALL for
	the data stage.  In the first case, the UDC driver 
	automatically queues a 0-length OUT request for the status 
	stage; the gadget driver does not get any chance to fail the
	transfer after its data has been successfully sent (and I can't 
	think of any reason for doing this).

In the delayed-status or delayed-data case, the setup routine does not
queue a request on ep0 before returning 0; instead the gadget driver
queues this request at a later time in a separate thread.

The gadget driver never calls usb_ep_queue in order to receive the next
SETUP packet; the UDC driver takes care of SETUP handling
automatically.

You are suggesting that status stage requests should not be queued 
automatically by UDC drivers but instead queued explicitly by gadget 
drivers.  This would mean changing every UDC driver and every gadget 
driver.

Also, it won't fix the race that Baolin Wang found.  The setup routine
is always called in interrupt context, so it can't sleep.  Doing
anything non-trivial will require a separate task, and it's possible
that this task will try to enqueue the data-stage or status-stage
request before the UDC driver is ready to handle it (for example, 
before or shortly after the setup routine returns).

To work properly, the UDC driver must be able to accept a request for 
ep0 any time after it invokes the setup callback -- either before the 
callback returns or after.  It seems that this was the real problem 
Baolin wanted to fix.

Alan Stern

  reply	other threads:[~2017-01-16 17:53 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-14  8:40 [PATCH] usb: dwc3: ep0: Fix the possible missed request for handling delay STATUS phase Baolin Wang
2017-01-16 10:56 ` Felipe Balbi
2017-01-16 11:29   ` Baolin Wang
2017-01-16 11:29     ` Felipe Balbi
2017-01-16 12:00       ` Baolin Wang
2017-01-16 12:06         ` Felipe Balbi
2017-01-16 17:53           ` Alan Stern [this message]
2017-01-16 19:18             ` Felipe Balbi
2017-01-17 15:54               ` Alan Stern
2017-01-23 11:57                 ` Felipe Balbi
2017-02-17  5:41                   ` Baolin Wang
2017-02-17  8:04                     ` Felipe Balbi
2017-02-20  2:27                       ` Baolin Wang
2017-02-21  9:18                       ` Baolin Wang
2017-02-27 22:11                         ` Alan Stern
2017-02-28 11:56                           ` Felipe Balbi
2017-02-28 18:34                             ` Alan Stern
2017-03-02 10:43                               ` Felipe Balbi
2017-03-02 10:15                           ` Baolin Wang
2017-03-02 10:48                             ` Felipe Balbi
2017-01-17  7:02           ` Baolin Wang
2017-01-17 10:39             ` Felipe Balbi
2017-01-17 11:40               ` 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=Pine.LNX.4.44L0.1701161209560.17898-100000@netrider.rowland.org \
    --to=stern@rowland.harvard.edu \
    --cc=balbi@kernel.org \
    --cc=baolin.wang@linaro.org \
    --cc=broonie@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linaro-kernel@lists.linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@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 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.