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

Reply via email to