This first proposed patch for solving the isochronous stream problem 
adds a mechanism for seeing whether or not an URB is currently being 
given back for a particular endpoint.

The mechanism isn't perfect.  It doesn't use any synchronization, so
it's possible that a CPU may think a giveback is still in progress even
after it has finished.  This shouldn't matter.  If an isochronous queue
empties out and then the driver starts a new stream within a few
milliseconds -- quickly enough that the change to giveback_in_progress
hasn't propagated to all the CPUs -- there won't be any harm in 
scheduling the new stream as a continuation of the old one.

Alan Stern


 drivers/usb/core/hcd.c |    3 +++
 include/linux/usb.h    |    5 +++--
 2 files changed, 6 insertions(+), 2 deletions(-)

Index: usb-3.11/include/linux/usb.h
===================================================================
--- usb-3.11.orig/include/linux/usb.h
+++ usb-3.11/include/linux/usb.h
@@ -68,9 +68,10 @@ struct usb_host_endpoint {
        void                            *hcpriv;
        struct ep_device                *ep_dev;        /* For sysfs info */
 
-       unsigned char *extra;   /* Extra descriptors */
-       int extralen;
-       int enabled;
+       unsigned char                   *extra;         /* Extra descriptors */
+       int                             extralen;
+       int                             enabled;
+       bool                            giveback_in_progress;
 };
 
 /* host-side wrapper for one interface setting's parsed descriptors */
Index: usb-3.11/drivers/usb/core/hcd.c
===================================================================
--- usb-3.11.orig/drivers/usb/core/hcd.c
+++ usb-3.11/drivers/usb/core/hcd.c
@@ -1638,6 +1638,7 @@ int usb_hcd_unlink_urb (struct urb *urb,
 static void __usb_hcd_giveback_urb(struct urb *urb)
 {
        struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
+       struct usb_host_endpoint *ep = urb->ep;
        int status = urb->unlinked;
        unsigned long flags;
 
@@ -1653,6 +1654,7 @@ static void __usb_hcd_giveback_urb(struc
 
        /* pass ownership to the completion handler */
        urb->status = status;
+       ep->giveback_in_progress = true;
 
        /*
         * We disable local IRQs here avoid possible deadlock because
@@ -1668,6 +1670,7 @@ static void __usb_hcd_giveback_urb(struc
        urb->complete(urb);
        local_irq_restore(flags);
 
+       ep->giveback_in_progress = false;
        atomic_dec(&urb->use_count);
        if (unlikely(atomic_read(&urb->reject)))
                wake_up(&usb_kill_urb_queue);


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to