Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 10757
b: refs/heads/master
c: c9f89fa
h: refs/heads/master
i:
  10755: 0d7ee60
v: v3
  • Loading branch information
David Brownell authored and Greg Kroah-Hartman committed Oct 28, 2005
1 parent 7f36e56 commit 3d13046
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 65 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: db69087437dd5135a9362da1c37fe072070e8f60
refs/heads/master: c9f89fa40cf274130b56475175a35af961d4b165
76 changes: 12 additions & 64 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ static void hub_quiesce(struct usb_hub *hub)
{
/* stop khubd and related activity */
hub->quiescing = 1;
hub->activating = 0;
usb_kill_urb(hub->urb);
if (hub->has_indicators)
cancel_delayed_work(&hub->leds);
Expand Down Expand Up @@ -1613,68 +1614,21 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
return 0;
}

/* suspend interface drivers; if this is a hub, it
* suspends the child devices
*/
/* all interfaces must already be suspended */
if (udev->actconfig) {
int i;

for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *intf;
struct usb_driver *driver;

intf = udev->actconfig->interface[i];
if (!is_active(intf))
continue;
if (!intf->dev.driver)
continue;
driver = to_usb_driver(intf->dev.driver);

if (driver->suspend) {
status = driver->suspend(intf, state);
if (status == 0)
mark_quiesced(intf);
else
dev_err(&intf->dev,
"suspend error %d\n",
status);
}

/* only drivers with suspend() can ever resume();
* and after power loss, even they won't.
* bus_rescan_devices() can rebind drivers later.
*
* FIXME the PM core self-deadlocks when unbinding
* drivers during suspend/resume ... everything grabs
* dpm_sem (not a spinlock, ugh). we want to unbind,
* since we know every driver's probe/disconnect works
* even for drivers that can't suspend.
*/
if (!driver->suspend || state.event > PM_EVENT_FREEZE) {
#if 1
dev_warn(&intf->dev, "resume is unsafe!\n");
#else
down_write(&usb_bus_type.rwsem);
device_release_driver(&intf->dev);
up_write(&usb_bus_type.rwsem);
#endif
if (is_active(intf)) {
dev_dbg(&intf->dev, "nyet suspended\n");
return -EBUSY;
}
}
}

/*
* FIXME this needs port power off call paths too, to help force
* USB into the "generic" PM model. At least for devices on
* ports that aren't using ganged switching (usually root hubs).
*
* NOTE: SRP-capable links should adopt more aggressive poweroff
* policies (when HNP doesn't apply) once we have mechanisms to
* turn power back on! (Likely not before 2.7...)
*/
if (state.event > PM_EVENT_FREEZE) {
dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
}

/* "global suspend" of the HC-to-USB interface (root hub), or
* "selective suspend" of just one hub-device link.
*/
Expand Down Expand Up @@ -1960,26 +1914,20 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
int status;

/* stop khubd and related activity */
hub_quiesce(hub);

/* then suspend every port */
/* fail if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;

udev = hdev->children [port1-1];
if (!udev)
continue;
down(&udev->serialize);
status = __usb_suspend_device(udev, port1, msg);
up(&udev->serialize);
if (status < 0)
dev_dbg(&intf->dev, "suspend port %d --> %d\n",
port1, status);
if (udev && udev->state != USB_STATE_SUSPENDED) {
dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
return -EBUSY;
}
}

/* stop khubd and related activity */
hub_quiesce(hub);
return 0;
}

Expand Down

0 comments on commit 3d13046

Please sign in to comment.