diff options
-rw-r--r-- | drivers/usb/core/driver.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 73 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 3 |
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 | ||
1633 | static int usb_suspend(struct device *dev, pm_message_t message) | 1633 | int 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 | ||
1657 | static int usb_resume(struct device *dev) | 1655 | int 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 | ||
1681 | struct bus_type usb_bus_type = { | 1672 | struct 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 | ||
222 | struct 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 | ||
230 | static int ksuspend_usb_init(void) | 224 | static 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 | |||
248 | static int usb_dev_prepare(struct device *dev) | ||
249 | { | ||
250 | return 0; /* Implement eventually? */ | ||
251 | } | ||
252 | |||
253 | static void usb_dev_complete(struct device *dev) | ||
254 | { | ||
255 | /* Currently used only for rebinding interfaces */ | ||
256 | usb_resume(dev); /* Implement eventually? */ | ||
257 | } | ||
258 | |||
259 | static int usb_dev_suspend(struct device *dev) | ||
260 | { | ||
261 | return usb_suspend(dev, PMSG_SUSPEND); | ||
262 | } | ||
263 | |||
264 | static int usb_dev_resume(struct device *dev) | ||
265 | { | ||
266 | return usb_resume(dev); | ||
267 | } | ||
268 | |||
269 | static int usb_dev_freeze(struct device *dev) | ||
270 | { | ||
271 | return usb_suspend(dev, PMSG_FREEZE); | ||
272 | } | ||
273 | |||
274 | static int usb_dev_thaw(struct device *dev) | ||
275 | { | ||
276 | return usb_resume(dev); | ||
277 | } | ||
278 | |||
279 | static int usb_dev_poweroff(struct device *dev) | ||
280 | { | ||
281 | return usb_suspend(dev, PMSG_HIBERNATE); | ||
282 | } | ||
283 | |||
284 | static int usb_dev_restore(struct device *dev) | ||
285 | { | ||
286 | return usb_resume(dev); | ||
287 | } | ||
288 | |||
289 | static 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 | ||
308 | struct 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 */ |
256 | static unsigned usb_bus_is_wusb(struct usb_bus *bus) | 317 | static 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 | ||
44 | extern int usb_suspend(struct device *dev, pm_message_t msg); | ||
45 | extern int usb_resume(struct device *dev); | ||
46 | |||
44 | extern void usb_autosuspend_work(struct work_struct *work); | 47 | extern void usb_autosuspend_work(struct work_struct *work); |
45 | extern int usb_port_suspend(struct usb_device *dev); | 48 | extern int usb_port_suspend(struct usb_device *dev); |
46 | extern int usb_port_resume(struct usb_device *dev); | 49 | extern int usb_port_resume(struct usb_device *dev); |