Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 67807
b: refs/heads/master
c: 9439eb9
h: refs/heads/master
i:
  67805: 664cc81
  67803: 70eb257
  67799: 0528086
  67791: 647d3fd
  67775: f3ac1c9
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Oct 12, 2007
1 parent 3d457c2 commit 81389ad
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d617bc83ff48ebf0df253605529d8b3bef15773a
refs/heads/master: 9439eb94b5c374d5b02699f8897fc43aa3603701
52 changes: 29 additions & 23 deletions trunk/drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -523,13 +524,21 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
}

/* 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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 81389ad

Please sign in to comment.