Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 10758
b: refs/heads/master
c: 390a8c3
h: refs/heads/master
v: v3
  • Loading branch information
David Brownell authored and Greg Kroah-Hartman committed Oct 28, 2005
1 parent 3d13046 commit 855022f
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 20 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: c9f89fa40cf274130b56475175a35af961d4b165
refs/heads/master: 390a8c345e6415cbf811232feedac70b56c9fc8d
34 changes: 21 additions & 13 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -1323,11 +1323,9 @@ int usb_new_device(struct usb_device *udev)
* (Includes HNP test device.)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
static int __usb_suspend_device (struct usb_device *,
int port1, pm_message_t state);
err = __usb_suspend_device(udev,
udev->bus->otg_port,
PMSG_SUSPEND);
static int __usb_suspend_device(struct usb_device *,
int port1);
err = __usb_suspend_device(udev, udev->bus->otg_port);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
}
Expand Down Expand Up @@ -1517,7 +1515,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
/* FIXME let caller ask to power down the port:
* - some devices won't enumerate without a VBUS power cycle
* - SRP saves power that way
* - usb_suspend_device(dev, PMSG_SUSPEND)
* - ... new call, TBD ...
* That's easy if this hub can switch power per-port, and
* khubd reactivates the port later (timer, SRP, etc).
* Powerdown must be optional, because of reset/DFU.
Expand Down Expand Up @@ -1599,9 +1597,12 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
* Other than re-initializing the hub (plug/unplug, except for root hubs),
* Linux (2.6) currently has NO mechanisms to initiate that: no khubd
* timer, no SRP, no requests through sysfs.
*
* If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
* the root hub for their bus goes into global suspend ... so we don't
* (falsely) update the device power state to say it suspended.
*/
static int __usb_suspend_device (struct usb_device *udev, int port1,
pm_message_t state)
static int __usb_suspend_device (struct usb_device *udev, int port1)
{
int status;

Expand Down Expand Up @@ -1648,14 +1649,13 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
udev);

if (status == 0)
udev->dev.power.power_state = state;
udev->dev.power.power_state = PMSG_SUSPEND;
return status;
}

/**
* usb_suspend_device - suspend a usb device
* @udev: device that's no longer in active use
* @state: PMSG_SUSPEND to suspend
* Context: must be able to sleep; device not locked
*
* Suspends a USB device that isn't in active use, conserving power.
Expand All @@ -1664,26 +1664,32 @@ static int __usb_suspend_device (struct usb_device *udev, int port1,
* suspend by the host, using usb_resume_device(). It's also routine
* to disconnect devices while they are suspended.
*
* This only affects the USB hardware for a device; its interfaces
* (and, for hubs, child devices) must already have been suspended.
*
* Suspending OTG devices may trigger HNP, if that's been enabled
* between a pair of dual-role devices. That will change roles, such
* as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
*
* Returns 0 on success, else negative errno.
*/
int usb_suspend_device(struct usb_device *udev, pm_message_t state)
int usb_suspend_device(struct usb_device *udev)
{
int port1, status;

port1 = locktree(udev);
if (port1 < 0)
return port1;

status = __usb_suspend_device(udev, port1, state);
status = __usb_suspend_device(udev, port1);
usb_unlock_device(udev);
return status;
}

/*
* If the USB "suspend" state is in use (rather than "global suspend"),
* many devices will be individually taken out of suspend state using
* special" resume" signaling. These routines kick in shortly after
* hardware resume signaling is finished, either because of selective
* resume (by host) or remote wakeup (by device) ... now see what changed
* in the tree that's rooted at this device.
Expand Down Expand Up @@ -1986,13 +1992,15 @@ void usb_resume_root_hub(struct usb_device *hdev)

#else /* !CONFIG_USB_SUSPEND */

int usb_suspend_device(struct usb_device *udev, pm_message_t state)
int usb_suspend_device(struct usb_device *udev)
{
/* state does NOT lie by saying it's USB_STATE_SUSPENDED! */
return 0;
}

int usb_resume_device(struct usb_device *udev)
{
udev->dev.power_state.event = PM_EVENT_ON;
return 0;
}

Expand Down
23 changes: 21 additions & 2 deletions trunk/drivers/usb/core/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1414,14 +1414,33 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}

static int verify_suspended(struct device *dev, void *unused)
{
return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
}

static int usb_generic_suspend(struct device *dev, pm_message_t message)
{
struct usb_interface *intf;
struct usb_driver *driver;
int status;

if (dev->driver == &usb_generic_driver)
return usb_suspend_device (to_usb_device(dev), message);
/* USB devices enter SUSPEND state through their hubs, but can be
* marked for FREEZE as soon as their children are already idled.
*/
if (dev->driver == &usb_generic_driver) {
if (dev->power.power_state.event == message.event)
return 0;
/* we need to rule out bogus requests through sysfs */
status = device_for_each_child(dev, NULL, verify_suspended);
if (status)
return status;
if (message.event == PM_EVENT_FREEZE) {
dev->power.power_state = message;
return 0;
}
return usb_suspend_device (to_usb_device(dev));
}

if ((dev->driver == NULL) ||
(dev->driver_data == &usb_generic_driver_data))
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ static int ehci_suspend (struct usb_hcd *hcd, pm_message_t message)
msleep (100);

#ifdef CONFIG_USB_SUSPEND
(void) usb_suspend_device (hcd->self.root_hub, message);
(void) usb_suspend_device (hcd->self.root_hub);
#else
usb_lock_device (hcd->self.root_hub);
(void) ehci_hub_suspend (hcd);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/usb/host/isp116x-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1781,7 +1781,7 @@ static int isp116x_suspend(struct device *dev, pm_message_t state)

VDBG("%s: state %x\n", __func__, state);

ret = usb_suspend_device(hcd->self.root_hub, state);
ret = usb_suspend_device(hcd->self.root_hub);
if (!ret) {
dev->power.power_state = state;
INFO("%s suspended\n", hcd_name);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/usb/host/ohci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
msleep (100);

#ifdef CONFIG_USB_SUSPEND
(void) usb_suspend_device (hcd->self.root_hub, message);
(void) usb_suspend_device (hcd->self.root_hub);
#else
usb_lock_device (hcd->self.root_hub);
(void) ohci_hub_suspend (hcd);
Expand Down
2 changes: 1 addition & 1 deletion trunk/include/linux/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
int timeout);

/* selective suspend/resume */
extern int usb_suspend_device(struct usb_device *dev, pm_message_t message);
extern int usb_suspend_device(struct usb_device *dev);
extern int usb_resume_device(struct usb_device *dev);


Expand Down

0 comments on commit 855022f

Please sign in to comment.