[RFC 3/3] EHCI: enable interrupts during URB giveback

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch modifies the usb_hcd_giveback_urb() routine in usbcore to
insure that interrupts will be disabled when an URB's completion
handler is called, even if they were enabled initially.

It also modifies ehci-hcd to enable interrupts when giving back URBs,
if possible.  Unfortunately it isn't always possible, because there
are pathways that can give back URBs in hardirq context (during the
I/O watchdog hrtimer routine, for example).

Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

---


 drivers/usb/core/hcd.c    |    4 ++++
 drivers/usb/host/ehci-q.c |   12 ++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

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
@@ -1667,6 +1667,8 @@ int usb_hcd_unlink_urb (struct urb *urb,
  */
 void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status)
 {
+	unsigned long		flags;
+
 	urb->hcpriv = NULL;
 	if (unlikely(urb->unlinked))
 		status = urb->unlinked;
@@ -1681,7 +1683,9 @@ void usb_hcd_giveback_urb(struct usb_hcd
 
 	/* pass ownership to the completion handler */
 	urb->status = status;
+	local_irq_save(flags);
 	urb->complete (urb);
+	local_irq_restore(flags);
 	atomic_dec (&urb->use_count);
 	if (unlikely(atomic_read(&urb->reject)))
 		wake_up (&usb_kill_urb_queue);
Index: usb-3.11/drivers/usb/host/ehci-q.c
===================================================================
--- usb-3.11.orig/drivers/usb/host/ehci-q.c
+++ usb-3.11/drivers/usb/host/ehci-q.c
@@ -257,6 +257,8 @@ ehci_urb_done(struct ehci_hcd *ehci, str
 __releases(ehci->lock)
 __acquires(ehci->lock)
 {
+	bool	enable_ints = !in_irq();
+
 	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
 		/* ... update hc-wide periodic stats */
 		ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -283,9 +285,15 @@ __acquires(ehci->lock)
 
 	/* complete() can reenter this HCD */
 	usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
-	spin_unlock (&ehci->lock);
+
+	/* This routine can be called from hardirq or softirq context */
+	spin_unlock(&ehci->lock);
+	if (enable_ints)
+		local_irq_enable();
 	usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status);
-	spin_lock (&ehci->lock);
+	if (enable_ints)
+		local_irq_disable();
+	spin_lock(&ehci->lock);
 }
 
 static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);

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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux