Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9439eb94b5c374d5b02699f8897fc43aa3603701
Commit:     9439eb94b5c374d5b02699f8897fc43aa3603701
Parent:     d617bc83ff48ebf0df253605529d8b3bef15773a
Author:     Alan Stern <[EMAIL PROTECTED]>
AuthorDate: Thu Aug 2 15:05:45 2007 -0400
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Oct 12 14:55:01 2007 -0700

    USB: update spinlock usage for root-hub URBs
    
    This patch (as952) adjusts the spinlock usage in the root-hub
    emulation part of usbcore, to make it match more closely the pattern
    used by regular host controller drivers.  To wit: The private lock
    (usb_hcd_root_hub_lock) is held throughout the important parts, and it
    is dropped temporarily without re-enabling interrupts around the call
    to usb_hcd_giveback_urb().
    
    A nice side effect is that the code now avoids calling
    local_irq_save(), thereby becoming more RT-friendly.
    
    Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/core/hcd.c |   52 ++++++++++++++++++++++++++---------------------
 1 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 47a055a..f8e7deb 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -356,10 +356,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct 
urb *urb)
        const u8        *bufp = tbuf;
        int             len = 0;
        int             patch_wakeup = 0;
-       unsigned long   flags;
        int             status = 0;
        int             n;
 
+       might_sleep();
+
        cmd = (struct usb_ctrlrequest *) urb->setup_packet;
        typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
        wValue   = le16_to_cpu (cmd->wValue);
@@ -523,13 +524,21 @@ error:
        }
 
        /* any errors get returned through the urb completion */
-       local_irq_save (flags);
-       spin_lock (&urb->lock);
+       spin_lock_irq(&hcd_root_hub_lock);
+       spin_lock(&urb->lock);
        if (urb->status == -EINPROGRESS)
                urb->status = status;
-       spin_unlock (&urb->lock);
-       usb_hcd_giveback_urb (hcd, urb);
-       local_irq_restore (flags);
+       spin_unlock(&urb->lock);
+
+       /* This peculiar use of spinlocks echoes what real HC drivers do.
+        * Avoiding calls to local_irq_disable/enable makes the code
+        * RT-friendly.
+        */
+       spin_unlock(&hcd_root_hub_lock);
+       usb_hcd_giveback_urb(hcd, urb);
+       spin_lock(&hcd_root_hub_lock);
+
+       spin_unlock_irq(&hcd_root_hub_lock);
        return 0;
 }
 
@@ -559,8 +568,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
        if (length > 0) {
 
                /* try to complete the status urb */
-               local_irq_save (flags);
-               spin_lock(&hcd_root_hub_lock);
+               spin_lock_irqsave(&hcd_root_hub_lock, flags);
                urb = hcd->status_urb;
                if (urb) {
                        spin_lock(&urb->lock);
@@ -574,16 +582,16 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
                        } else          /* urb has been unlinked */
                                length = 0;
                        spin_unlock(&urb->lock);
+
+                       spin_unlock(&hcd_root_hub_lock);
+                       usb_hcd_giveback_urb(hcd, urb);
+                       spin_lock(&hcd_root_hub_lock);
                } else
                        length = 0;
-               spin_unlock(&hcd_root_hub_lock);
 
-               /* local irqs are always blocked in completions */
-               if (length > 0)
-                       usb_hcd_giveback_urb (hcd, urb);
-               else
+               if (length <= 0)
                        hcd->poll_pending = 1;
-               local_irq_restore (flags);
+               spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
        }
 
        /* The USB 2.0 spec says 256 ms.  This is close enough and won't
@@ -651,25 +659,23 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, 
struct urb *urb)
 {
        unsigned long   flags;
 
+       spin_lock_irqsave(&hcd_root_hub_lock, flags);
        if (usb_endpoint_num(&urb->ep->desc) == 0) {    /* Control URB */
                ;       /* Do nothing */
 
        } else {                                /* Status URB */
                if (!hcd->uses_new_polling)
                        del_timer (&hcd->rh_timer);
-               local_irq_save (flags);
-               spin_lock (&hcd_root_hub_lock);
                if (urb == hcd->status_urb) {
                        hcd->status_urb = NULL;
                        urb->hcpriv = NULL;
-               } else
-                       urb = NULL;             /* wasn't fully queued */
-               spin_unlock (&hcd_root_hub_lock);
-               if (urb)
-                       usb_hcd_giveback_urb (hcd, urb);
-               local_irq_restore (flags);
-       }
 
+                       spin_unlock(&hcd_root_hub_lock);
+                       usb_hcd_giveback_urb(hcd, urb);
+                       spin_lock(&hcd_root_hub_lock);
+               }
+       }
+       spin_unlock_irqrestore(&hcd_root_hub_lock, flags);
        return 0;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to