aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2008-08-12 14:34:10 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-08-21 13:26:37 -0400
commitf2189c477c986db47ac7f9cc32d05f6df18bfe9e (patch)
tree7a6e20c8bea0876aa7c4eb17451d627e5839ce83 /drivers/usb/core
parent55151d7daba185f94e9dc561a5a2ba36b5f647dd (diff)
USB: Add new PM callback methods for USB
This patch (as1129) adds support for the new PM callbacks to usbcore. The new callbacks merely invoke the same old USB power management routines as the old ones did. A minor improvement is that the callbacks are present only in the "USB-device" device_type structure, rather than in the bus_type structure. This way they will be invoked only for USB devices, not for USB interfaces. The core USB PM routines automatically handle suspending and resuming interfaces along with their devices. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/driver.c15
-rw-r--r--drivers/usb/core/usb.c73
-rw-r--r--drivers/usb/core/usb.h3
3 files changed, 72 insertions, 19 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 637b2bea5563..2da70b4d33fe 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1630,12 +1630,10 @@ int usb_external_resume_device(struct usb_device *udev)
1630 return status; 1630 return status;
1631} 1631}
1632 1632
1633static int usb_suspend(struct device *dev, pm_message_t message) 1633int usb_suspend(struct device *dev, pm_message_t message)
1634{ 1634{
1635 struct usb_device *udev; 1635 struct usb_device *udev;
1636 1636
1637 if (!is_usb_device(dev)) /* Ignore PM for interfaces */
1638 return 0;
1639 udev = to_usb_device(dev); 1637 udev = to_usb_device(dev);
1640 1638
1641 /* If udev is already suspended, we can skip this suspend and 1639 /* If udev is already suspended, we can skip this suspend and
@@ -1654,12 +1652,10 @@ static int usb_suspend(struct device *dev, pm_message_t message)
1654 return usb_external_suspend_device(udev, message); 1652 return usb_external_suspend_device(udev, message);
1655} 1653}
1656 1654
1657static int usb_resume(struct device *dev) 1655int usb_resume(struct device *dev)
1658{ 1656{
1659 struct usb_device *udev; 1657 struct usb_device *udev;
1660 1658
1661 if (!is_usb_device(dev)) /* Ignore PM for interfaces */
1662 return 0;
1663 udev = to_usb_device(dev); 1659 udev = to_usb_device(dev);
1664 1660
1665 /* If udev->skip_sys_resume is set then udev was already suspended 1661 /* If udev->skip_sys_resume is set then udev was already suspended
@@ -1671,17 +1667,10 @@ static int usb_resume(struct device *dev)
1671 return usb_external_resume_device(udev); 1667 return usb_external_resume_device(udev);
1672} 1668}
1673 1669
1674#else
1675
1676#define usb_suspend NULL
1677#define usb_resume NULL
1678
1679#endif /* CONFIG_PM */ 1670#endif /* CONFIG_PM */
1680 1671
1681struct bus_type usb_bus_type = { 1672struct bus_type usb_bus_type = {
1682 .name = "usb", 1673 .name = "usb",
1683 .match = usb_device_match, 1674 .match = usb_device_match,
1684 .uevent = usb_uevent, 1675 .uevent = usb_uevent,
1685 .suspend = usb_suspend,
1686 .resume = usb_resume,
1687}; 1676};
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 84fcaa6a21ec..be1fa0723f2c 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -219,12 +219,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
219} 219}
220#endif /* CONFIG_HOTPLUG */ 220#endif /* CONFIG_HOTPLUG */
221 221
222struct device_type usb_device_type = {
223 .name = "usb_device",
224 .release = usb_release_dev,
225 .uevent = usb_dev_uevent,
226};
227
228#ifdef CONFIG_PM 222#ifdef CONFIG_PM
229 223
230static int ksuspend_usb_init(void) 224static int ksuspend_usb_init(void)
@@ -244,13 +238,80 @@ static void ksuspend_usb_cleanup(void)
244 destroy_workqueue(ksuspend_usb_wq); 238 destroy_workqueue(ksuspend_usb_wq);
245} 239}
246 240
241/* USB device Power-Management thunks.
242 * There's no need to distinguish here between quiescing a USB device
243 * and powering it down; the generic_suspend() routine takes care of
244 * it by skipping the usb_port_suspend() call for a quiesce. And for
245 * USB interfaces there's no difference at all.
246 */
247
248static int usb_dev_prepare(struct device *dev)
249{
250 return 0; /* Implement eventually? */
251}
252
253static void usb_dev_complete(struct device *dev)
254{
255 /* Currently used only for rebinding interfaces */
256 usb_resume(dev); /* Implement eventually? */
257}
258
259static int usb_dev_suspend(struct device *dev)
260{
261 return usb_suspend(dev, PMSG_SUSPEND);
262}
263
264static int usb_dev_resume(struct device *dev)
265{
266 return usb_resume(dev);
267}
268
269static int usb_dev_freeze(struct device *dev)
270{
271 return usb_suspend(dev, PMSG_FREEZE);
272}
273
274static int usb_dev_thaw(struct device *dev)
275{
276 return usb_resume(dev);
277}
278
279static int usb_dev_poweroff(struct device *dev)
280{
281 return usb_suspend(dev, PMSG_HIBERNATE);
282}
283
284static int usb_dev_restore(struct device *dev)
285{
286 return usb_resume(dev);
287}
288
289static struct pm_ops usb_device_pm_ops = {
290 .prepare = usb_dev_prepare,
291 .complete = usb_dev_complete,
292 .suspend = usb_dev_suspend,
293 .resume = usb_dev_resume,
294 .freeze = usb_dev_freeze,
295 .thaw = usb_dev_thaw,
296 .poweroff = usb_dev_poweroff,
297 .restore = usb_dev_restore,
298};
299
247#else 300#else
248 301
249#define ksuspend_usb_init() 0 302#define ksuspend_usb_init() 0
250#define ksuspend_usb_cleanup() do {} while (0) 303#define ksuspend_usb_cleanup() do {} while (0)
304#define usb_device_pm_ops (*(struct pm_ops *)0)
251 305
252#endif /* CONFIG_PM */ 306#endif /* CONFIG_PM */
253 307
308struct device_type usb_device_type = {
309 .name = "usb_device",
310 .release = usb_release_dev,
311 .uevent = usb_dev_uevent,
312 .pm = &usb_device_pm_ops,
313};
314
254 315
255/* Returns 1 if @usb_bus is WUSB, 0 otherwise */ 316/* Returns 1 if @usb_bus is WUSB, 0 otherwise */
256static unsigned usb_bus_is_wusb(struct usb_bus *bus) 317static unsigned usb_bus_is_wusb(struct usb_bus *bus)
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index d9a6e16dbf84..9a1a45ac3add 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -41,6 +41,9 @@ extern void usb_host_cleanup(void);
41 41
42#ifdef CONFIG_PM 42#ifdef CONFIG_PM
43 43
44extern int usb_suspend(struct device *dev, pm_message_t msg);
45extern int usb_resume(struct device *dev);
46
44extern void usb_autosuspend_work(struct work_struct *work); 47extern void usb_autosuspend_work(struct work_struct *work);
45extern int usb_port_suspend(struct usb_device *dev); 48extern int usb_port_suspend(struct usb_device *dev);
46extern int usb_port_resume(struct usb_device *dev); 49extern int usb_port_resume(struct usb_device *dev);