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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html