Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 235396
b: refs/heads/master
c: 9b37596
h: refs/heads/master
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Mar 7, 2011
1 parent 3fef05d commit a86a80d
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 22 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: e4738e29bef8ed9bdd8a0606d0561557b4547649
refs/heads/master: 9b37596a2e860404503a3f2a6513db60c296bfdc
13 changes: 6 additions & 7 deletions trunk/drivers/usb/core/hcd-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,7 @@ static int check_root_hub_suspended(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
struct usb_hcd *hcd = pci_get_drvdata(pci_dev);

if (!(hcd->state == HC_STATE_SUSPENDED ||
hcd->state == HC_STATE_HALT)) {
if (HCD_RH_RUNNING(hcd)) {
dev_warn(dev, "Root hub is not suspended\n");
return -EBUSY;
}
Expand All @@ -386,7 +385,7 @@ static int suspend_common(struct device *dev, bool do_wakeup)
if (retval)
return retval;

if (hcd->driver->pci_suspend) {
if (hcd->driver->pci_suspend && !HCD_DEAD(hcd)) {
/* Optimization: Don't suspend if a root-hub wakeup is
* pending and it would cause the HCD to wake up anyway.
*/
Expand Down Expand Up @@ -427,7 +426,7 @@ static int resume_common(struct device *dev, int event)
struct usb_hcd *hcd = pci_get_drvdata(pci_dev);
int retval;

if (hcd->state != HC_STATE_SUSPENDED) {
if (HCD_RH_RUNNING(hcd)) {
dev_dbg(dev, "can't resume, not suspended!\n");
return 0;
}
Expand All @@ -442,7 +441,7 @@ static int resume_common(struct device *dev, int event)

clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);

if (hcd->driver->pci_resume) {
if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
if (event != PM_EVENT_AUTO_RESUME)
wait_for_companions(pci_dev, hcd);

Expand Down Expand Up @@ -475,10 +474,10 @@ static int hcd_pci_suspend_noirq(struct device *dev)

pci_save_state(pci_dev);

/* If the root hub is HALTed rather than SUSPENDed,
/* If the root hub is dead rather than suspended,
* disallow remote wakeup.
*/
if (hcd->state == HC_STATE_HALT)
if (HCD_DEAD(hcd))
device_set_wakeup_enable(dev, 0);
dev_dbg(dev, "wakeup: %d\n", device_may_wakeup(dev));

Expand Down
55 changes: 41 additions & 14 deletions trunk/drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ static int register_root_hub(struct usb_hcd *hcd)
spin_unlock_irq (&hcd_root_hub_lock);

/* Did the HC die before the root hub was registered? */
if (hcd->state == HC_STATE_HALT)
if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
usb_hc_died (hcd); /* This time clean up */
}

Expand Down Expand Up @@ -1089,13 +1089,10 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
* Check the host controller's state and add the URB to the
* endpoint's queue.
*/
switch (hcd->state) {
case HC_STATE_RUNNING:
case HC_STATE_RESUMING:
if (HCD_RH_RUNNING(hcd)) {
urb->unlinked = 0;
list_add_tail(&urb->urb_list, &urb->ep->urb_list);
break;
default:
} else {
rc = -ESHUTDOWN;
goto done;
}
Expand Down Expand Up @@ -1931,7 +1928,7 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);

if (!HC_IS_RUNNING (hcd->state))
if (!HCD_RH_RUNNING(hcd))
return -ESHUTDOWN;
return hcd->driver->get_frame_number (hcd);
}
Expand All @@ -1948,17 +1945,28 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)

dev_dbg(&rhdev->dev, "bus %s%s\n",
(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
if (HCD_DEAD(hcd)) {
dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
return 0;
}

if (!hcd->driver->bus_suspend) {
status = -ENOENT;
} else {
clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
hcd->state = HC_STATE_QUIESCING;
status = hcd->driver->bus_suspend(hcd);
}
if (status == 0) {
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
} else {
hcd->state = old_state;
spin_lock_irq(&hcd_root_hub_lock);
if (!HCD_DEAD(hcd)) {
set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
hcd->state = old_state;
}
spin_unlock_irq(&hcd_root_hub_lock);
dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
"suspend", status);
}
Expand All @@ -1973,9 +1981,13 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)

dev_dbg(&rhdev->dev, "usb %s%s\n",
(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
if (HCD_DEAD(hcd)) {
dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
return 0;
}
if (!hcd->driver->bus_resume)
return -ENOENT;
if (hcd->state == HC_STATE_RUNNING)
if (HCD_RH_RUNNING(hcd))
return 0;

hcd->state = HC_STATE_RESUMING;
Expand All @@ -1984,10 +1996,15 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
if (status == 0) {
/* TRSMRCY = 10 msec */
msleep(10);
usb_set_device_state(rhdev, rhdev->actconfig
? USB_STATE_CONFIGURED
: USB_STATE_ADDRESS);
hcd->state = HC_STATE_RUNNING;
spin_lock_irq(&hcd_root_hub_lock);
if (!HCD_DEAD(hcd)) {
usb_set_device_state(rhdev, rhdev->actconfig
? USB_STATE_CONFIGURED
: USB_STATE_ADDRESS);
set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
hcd->state = HC_STATE_RUNNING;
}
spin_unlock_irq(&hcd_root_hub_lock);
} else {
hcd->state = old_state;
dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
Expand Down Expand Up @@ -2098,7 +2115,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
*/
local_irq_save(flags);

if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
rc = IRQ_NONE;
} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
rc = IRQ_NONE;
Expand Down Expand Up @@ -2132,6 +2149,8 @@ void usb_hc_died (struct usb_hcd *hcd)
dev_err (hcd->self.controller, "HC died; cleaning up\n");

spin_lock_irqsave (&hcd_root_hub_lock, flags);
clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
set_bit(HCD_FLAG_DEAD, &hcd->flags);
if (hcd->rh_registered) {
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);

Expand Down Expand Up @@ -2274,6 +2293,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
*/
device_init_wakeup(&rhdev->dev, 1);

/* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is
* registered. But since the controller can die at any time,
* let's initialize the flag before touching the hardware.
*/
set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);

/* "reset" is misnamed; its role is now one-time init. the controller
* should already have been reset (and boot firmware kicked off etc).
*/
Expand Down Expand Up @@ -2341,6 +2366,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
return retval;

error_create_attr_group:
clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
if (HC_IS_RUNNING(hcd->state))
hcd->state = HC_STATE_QUIESCING;
spin_lock_irq(&hcd_root_hub_lock);
Expand Down Expand Up @@ -2393,6 +2419,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_get_dev(rhdev);
sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);

clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
if (HC_IS_RUNNING (hcd->state))
hcd->state = HC_STATE_QUIESCING;

Expand Down
4 changes: 4 additions & 0 deletions trunk/include/linux/usb/hcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ struct usb_hcd {
#define HCD_FLAG_POLL_RH 2 /* poll for rh status? */
#define HCD_FLAG_POLL_PENDING 3 /* status has changed? */
#define HCD_FLAG_WAKEUP_PENDING 4 /* root hub is resuming? */
#define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */
#define HCD_FLAG_DEAD 6 /* controller has died? */

/* The flags can be tested using these macros; they are likely to
* be slightly faster than test_bit().
Expand All @@ -108,6 +110,8 @@ struct usb_hcd {
#define HCD_POLL_RH(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
#define HCD_POLL_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
#define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
#define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
#define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD))

/* Flags that get set only during HCD registration or removal. */
unsigned rh_registered:1;/* is root hub registered? */
Expand Down

0 comments on commit a86a80d

Please sign in to comment.