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/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel