On Thursday 17 May 2007 16:20, David Brownell wrote:
> > > > > > On FreeBSD it will never happen that you call the equivalent
> > > > > > of "usb_submit_urb()" after that the device has detached! It must
> > > > > > be something terribly wrong in the Linux USB stack if the
> > > > > > callbacks are alive after that you have detached a USB device.
> > > > >
> > > > > How does that work then ... driver must grab a lock, check
> > > > > whether the device has disconnected, then submit the request
> > > > > and drop the lock?  Sounds like needless slowdowns.
> > > >
> > > > Each USB device has its own lock. There are some tricks there.
> > > >
> > > > ...
> > >
> > > So there's a race on SMP, where sc->sc_xfer[x] may be referenced
> > > on one CPU while another is nulling it.
> > >
> > > The lock you showed is inside usbd_transfer_start(), where it
> > > can't do any good.
> >
> > It is an assert statement. The "priv_mtx" lock must be locked before you
> > call usbd_transfer_start(). There is no race on SMP.
>
> I see; I was expecting a response like "yes, driver must grab
> lock" and that step was omitted from your response.
>
> > If you need to do Async stuff, then you have to do it in a separate
> > thread or in a so-called task-queue. Else you are in for great trouble!
> > That was the big "sin" in the old USB stack on FreeBSD: Calling
> > synchronous USB callbacks from everywhere, like ioctl/read/write -
> > callbacks.
> >
> > Is that a problem on Linux also?
>
> All callbacks are async.  At one point there were some bugs associated
> with callers that accidentally placed racey restrictions on when the
> callbacks could occur -- i.e. expected them at some point after a call
> returned, rather than any point after the call was issued -- but such
> bugs seem to be largely fixed now.  (Hard to be sure though.)
>
> > On Linux I see no locks used in the USB drivers,
>
> Look again, then!  Driver-private locks are all over the place.
>
> > so they are solely protected by interrupt-level mechanisms.
>
> Maybe you mean "caller-transparent mechanisms"?  Synchronous
> calls use mutexes (or for old code, semaphores) internally.
> Async ones use spinlocks.
>
> > My rule is that: Synchronous or blocking calls _must_ happen in a config
> > thread that you can wait for. Else asynchronous calls on pre-allocated
> > transfers can happen anywhere.
>
> Well *obviously* blocking calls require a schedulable context,
> and others don't.  We don't restrict things to "config" threads.
>
> > The problem clearly appears on Linux SMP because:
> >
> > a) No locks are in the USB drivers (then they must be all so-called
> > "Giant" locked)
>
> Nope; I don't have an idea why you overlook all the mutex
> and spinlock calls in the drivers.  There's the legacy
> "big kernel lock" but not much uses that any more.
>
> > b) You don't pre-allocate transfers, resulting in synchronous/blocking
> > calls everywhere, and no-one thinks about what can happen then :-)
>
> You should learn more about the stack before making such
> sweeping (and wrong) statements.

Ok, thanks for clearing it up. You obviously know more about the Linux USB 
stack than I do.

In between:

I would like introduce a new USB API call, so that my pre-allocate model will 
work better with your USB API. For example I want something like this:

void
usb_setup_endpoint(struct usb_device *usb, struct usb_interface *ui, struct 
usb_host_endpoint *uhe, uint32_t bufsize, uint32_t unused0, uint32_t unused1, 
uint32_t unused2);

On FreeBSD this function will pre-allocate one or two USB transfers for an 
endpoint using the given "bufsize" argument. Those FreeBSD USB transfers will 
then be used to do all the Linux USB transfers. This function can block and 
must have a context.

On linux you will probably use "uint32_t uhe", hence I will do it like this:

struct usb_host_endpoint *
usb_find_host_endpoint(struct usb_device *dev, uint8_t type, uint8_t dir);

#define usb_sndctrlpipe(dev,endpoint) \
  usb_find_host_endpoint(dev, PIPE_CONTROL, (endpoint) | USB_DIR_OUT)

Whether usb_sndctrlpipe() returns a pointer or uint32_t, will be hidden to the 
USB device drivers.

What do you think?

--HPS

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to