Hi, On Thursday 17 May 2007 06:38, David Brownell wrote: > On Wednesday 16 May 2007, Hans Petter Selasky wrote: > > Hi, > > > > On Wednesday 16 May 2007 20:20, David Brownell wrote: > > > > > > > URB submission has other failure possibilities than lack of > > > > > > > memory. Those other things have to be checked for regardless. > > > > > > > > > > > > Yes, but that is because you allow too many parameters in the URB > > > > > > to be changed between USB transfers. > > > > > > > > > > No; it's because unforeseen events can occur. For example, the > > > > > device may have been unplugged or suspended. > > > > > > > > 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. > > > > 1) usbd_transfer_start() is always called like this: > > usbd_transfer_start(sc->sc_xfer[x]); > > > > 2) sc->sc_xfer[x] is set to zero at detach holding the private lock of > > the USB device driver. All subsequent calls to usbd_transfer_start(), if > > any, will fail. > > 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. > > > 3) usbd_transfer_start() is always non-blocking. In other words a single > > lock is held across the call. > > Like usb_submit_urb() then, except that the disconnect race > is handled by being buggy rather than by reporting a fault > at submit time... Ok. > > > ... > > > > > Because if there's no lock against async disconnect events, > > > then it's trivial to have the disconnect logic underway on > > > one CPU while another CPU does real work, submitting an I/O > > > request. > > > > We solve this in one of two ways: > > > > 1) Using a mutex. At detach we lock the mutex stopping all transfers. > > > > 2) Using a thread. At detach we teardown and wait for the thread to exit. > > But there's that race above, so it's not "solved". > 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? On Linux I see no locks used in the USB drivers, so they are solely protected by interrupt-level mechanisms. 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. 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) b) You don't pre-allocate transfers, resulting in synchronous/blocking calls everywhere, and no-one thinks about what can happen then :-) --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