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. 3) usbd_transfer_start() is always non-blocking. In other words a single lock is held across the call. This is how it looks until further: As you can see, no other locks are locked unless you want to submit a transfer to the USB host controller. Then you have to aquire "usb_mtx" which is per USB host controller. void usbd_transfer_start(struct usbd_xfer *xfer) { if (xfer == NULL) { /* transfer is gone */ return; } mtx_assert(xfer->priv_mtx, MA_OWNED); if(!(xfer->flags & USBD_DEV_OPEN)) { xfer->flags |= USBD_DEV_OPEN; /* * open transfer */ mtx_lock(xfer->usb_mtx); (xfer->pipe->methods->open)(xfer); mtx_unlock(xfer->usb_mtx); } /* "USBD_DEV_TRANSFERRING" is only changed * when "priv_mtx" is locked */ if(!(xfer->flags & (USBD_DEV_TRANSFERRING))) { /* call callback */ __usbd_callback(xfer); <cut away> } return; } > > 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. > - Dave > > p.s. You mentioned 16 MB/sec bulk transfer rates. Folk often > get over twice that on Linux, and a few years back there > were measurements of around 50 MByte/sec ... limitations > seeming to come from hardware not the driver stack. Yes, hardware and price :-) --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