diff options
-rw-r--r-- | Documentation/usb/power-management.txt | 22 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 86 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 5 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 1 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 1 | ||||
-rw-r--r-- | include/linux/usb.h | 9 |
6 files changed, 117 insertions, 7 deletions
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index e48ea1d51010..ad642615ad4c 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt | |||
@@ -313,11 +313,13 @@ three of the methods listed above. In addition, a driver indicates | |||
313 | that it supports autosuspend by setting the .supports_autosuspend flag | 313 | that it supports autosuspend by setting the .supports_autosuspend flag |
314 | in its usb_driver structure. It is then responsible for informing the | 314 | in its usb_driver structure. It is then responsible for informing the |
315 | USB core whenever one of its interfaces becomes busy or idle. The | 315 | USB core whenever one of its interfaces becomes busy or idle. The |
316 | driver does so by calling these three functions: | 316 | driver does so by calling these five functions: |
317 | 317 | ||
318 | int usb_autopm_get_interface(struct usb_interface *intf); | 318 | int usb_autopm_get_interface(struct usb_interface *intf); |
319 | void usb_autopm_put_interface(struct usb_interface *intf); | 319 | void usb_autopm_put_interface(struct usb_interface *intf); |
320 | int usb_autopm_set_interface(struct usb_interface *intf); | 320 | int usb_autopm_set_interface(struct usb_interface *intf); |
321 | int usb_autopm_get_interface_async(struct usb_interface *intf); | ||
322 | void usb_autopm_put_interface_async(struct usb_interface *intf); | ||
321 | 323 | ||
322 | The functions work by maintaining a counter in the usb_interface | 324 | The functions work by maintaining a counter in the usb_interface |
323 | structure. When intf->pm_usage_count is > 0 then the interface is | 325 | structure. When intf->pm_usage_count is > 0 then the interface is |
@@ -330,10 +332,12 @@ associated with the device itself rather than any of its interfaces. | |||
330 | This field is used only by the USB core.) | 332 | This field is used only by the USB core.) |
331 | 333 | ||
332 | The driver owns intf->pm_usage_count; it can modify the value however | 334 | The driver owns intf->pm_usage_count; it can modify the value however |
333 | and whenever it likes. A nice aspect of the usb_autopm_* routines is | 335 | and whenever it likes. A nice aspect of the non-async usb_autopm_* |
334 | that the changes they make are protected by the usb_device structure's | 336 | routines is that the changes they make are protected by the usb_device |
335 | PM mutex (udev->pm_mutex); however drivers may change pm_usage_count | 337 | structure's PM mutex (udev->pm_mutex); however drivers may change |
336 | without holding the mutex. | 338 | pm_usage_count without holding the mutex. Drivers using the async |
339 | routines are responsible for their own synchronization and mutual | ||
340 | exclusion. | ||
337 | 341 | ||
338 | usb_autopm_get_interface() increments pm_usage_count and | 342 | usb_autopm_get_interface() increments pm_usage_count and |
339 | attempts an autoresume if the new value is > 0 and the | 343 | attempts an autoresume if the new value is > 0 and the |
@@ -348,6 +352,14 @@ without holding the mutex. | |||
348 | is suspended, and it attempts an autosuspend if the value is | 352 | is suspended, and it attempts an autosuspend if the value is |
349 | <= 0 and the device isn't suspended. | 353 | <= 0 and the device isn't suspended. |
350 | 354 | ||
355 | usb_autopm_get_interface_async() and | ||
356 | usb_autopm_put_interface_async() do almost the same things as | ||
357 | their non-async counterparts. The differences are: they do | ||
358 | not acquire the PM mutex, and they use a workqueue to do their | ||
359 | jobs. As a result they can be called in an atomic context, | ||
360 | such as an URB's completion handler, but when they return the | ||
361 | device will not generally not yet be in the desired state. | ||
362 | |||
351 | There also are a couple of utility routines drivers can use: | 363 | There also are a couple of utility routines drivers can use: |
352 | 364 | ||
353 | usb_autopm_enable() sets pm_usage_cnt to 0 and then calls | 365 | usb_autopm_enable() sets pm_usage_cnt to 0 and then calls |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8c081308b0e2..23b3c7e79d4b 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1341,6 +1341,19 @@ void usb_autosuspend_work(struct work_struct *work) | |||
1341 | usb_autopm_do_device(udev, 0); | 1341 | usb_autopm_do_device(udev, 0); |
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | /* usb_autoresume_work - callback routine to autoresume a USB device */ | ||
1345 | void usb_autoresume_work(struct work_struct *work) | ||
1346 | { | ||
1347 | struct usb_device *udev = | ||
1348 | container_of(work, struct usb_device, autoresume); | ||
1349 | |||
1350 | /* Wake it up, let the drivers do their thing, and then put it | ||
1351 | * back to sleep. | ||
1352 | */ | ||
1353 | if (usb_autopm_do_device(udev, 1) == 0) | ||
1354 | usb_autopm_do_device(udev, -1); | ||
1355 | } | ||
1356 | |||
1344 | /** | 1357 | /** |
1345 | * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces | 1358 | * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces |
1346 | * @udev: the usb_device to autosuspend | 1359 | * @udev: the usb_device to autosuspend |
@@ -1492,6 +1505,45 @@ void usb_autopm_put_interface(struct usb_interface *intf) | |||
1492 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface); | 1505 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface); |
1493 | 1506 | ||
1494 | /** | 1507 | /** |
1508 | * usb_autopm_put_interface_async - decrement a USB interface's PM-usage counter | ||
1509 | * @intf: the usb_interface whose counter should be decremented | ||
1510 | * | ||
1511 | * This routine does essentially the same thing as | ||
1512 | * usb_autopm_put_interface(): it decrements @intf's usage counter and | ||
1513 | * queues a delayed autosuspend request if the counter is <= 0. The | ||
1514 | * difference is that it does not acquire the device's pm_mutex; | ||
1515 | * callers must handle all synchronization issues themselves. | ||
1516 | * | ||
1517 | * Typically a driver would call this routine during an URB's completion | ||
1518 | * handler, if no more URBs were pending. | ||
1519 | * | ||
1520 | * This routine can run in atomic context. | ||
1521 | */ | ||
1522 | void usb_autopm_put_interface_async(struct usb_interface *intf) | ||
1523 | { | ||
1524 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1525 | int status = 0; | ||
1526 | |||
1527 | if (intf->condition == USB_INTERFACE_UNBOUND) { | ||
1528 | status = -ENODEV; | ||
1529 | } else { | ||
1530 | udev->last_busy = jiffies; | ||
1531 | --intf->pm_usage_cnt; | ||
1532 | if (udev->autosuspend_disabled || udev->autosuspend_delay < 0) | ||
1533 | status = -EPERM; | ||
1534 | else if (intf->pm_usage_cnt <= 0 && | ||
1535 | !timer_pending(&udev->autosuspend.timer)) { | ||
1536 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | ||
1537 | round_jiffies_relative( | ||
1538 | udev->autosuspend_delay)); | ||
1539 | } | ||
1540 | } | ||
1541 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", | ||
1542 | __func__, status, intf->pm_usage_cnt); | ||
1543 | } | ||
1544 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async); | ||
1545 | |||
1546 | /** | ||
1495 | * usb_autopm_get_interface - increment a USB interface's PM-usage counter | 1547 | * usb_autopm_get_interface - increment a USB interface's PM-usage counter |
1496 | * @intf: the usb_interface whose counter should be incremented | 1548 | * @intf: the usb_interface whose counter should be incremented |
1497 | * | 1549 | * |
@@ -1537,6 +1589,37 @@ int usb_autopm_get_interface(struct usb_interface *intf) | |||
1537 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface); | 1589 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface); |
1538 | 1590 | ||
1539 | /** | 1591 | /** |
1592 | * usb_autopm_get_interface_async - increment a USB interface's PM-usage counter | ||
1593 | * @intf: the usb_interface whose counter should be incremented | ||
1594 | * | ||
1595 | * This routine does much the same thing as | ||
1596 | * usb_autopm_get_interface(): it increments @intf's usage counter and | ||
1597 | * queues an autoresume request if the result is > 0. The differences | ||
1598 | * are that it does not acquire the device's pm_mutex (callers must | ||
1599 | * handle all synchronization issues themselves), and it does not | ||
1600 | * autoresume the device directly (it only queues a request). After a | ||
1601 | * successful call, the device will generally not yet be resumed. | ||
1602 | * | ||
1603 | * This routine can run in atomic context. | ||
1604 | */ | ||
1605 | int usb_autopm_get_interface_async(struct usb_interface *intf) | ||
1606 | { | ||
1607 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1608 | int status = 0; | ||
1609 | |||
1610 | if (intf->condition == USB_INTERFACE_UNBOUND) | ||
1611 | status = -ENODEV; | ||
1612 | else if (udev->autoresume_disabled) | ||
1613 | status = -EPERM; | ||
1614 | else if (++intf->pm_usage_cnt > 0 && udev->state == USB_STATE_SUSPENDED) | ||
1615 | queue_work(ksuspend_usb_wq, &udev->autoresume); | ||
1616 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", | ||
1617 | __func__, status, intf->pm_usage_cnt); | ||
1618 | return status; | ||
1619 | } | ||
1620 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async); | ||
1621 | |||
1622 | /** | ||
1540 | * usb_autopm_set_interface - set a USB interface's autosuspend state | 1623 | * usb_autopm_set_interface - set a USB interface's autosuspend state |
1541 | * @intf: the usb_interface whose state should be set | 1624 | * @intf: the usb_interface whose state should be set |
1542 | * | 1625 | * |
@@ -1563,6 +1646,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_set_interface); | |||
1563 | void usb_autosuspend_work(struct work_struct *work) | 1646 | void usb_autosuspend_work(struct work_struct *work) |
1564 | {} | 1647 | {} |
1565 | 1648 | ||
1649 | void usb_autoresume_work(struct work_struct *work) | ||
1650 | {} | ||
1651 | |||
1566 | #endif /* CONFIG_USB_SUSPEND */ | 1652 | #endif /* CONFIG_USB_SUSPEND */ |
1567 | 1653 | ||
1568 | /** | 1654 | /** |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b19cbfcd51da..95fb3104ba4f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1374,8 +1374,9 @@ static void usb_stop_pm(struct usb_device *udev) | |||
1374 | usb_autosuspend_device(udev->parent); | 1374 | usb_autosuspend_device(udev->parent); |
1375 | usb_pm_unlock(udev); | 1375 | usb_pm_unlock(udev); |
1376 | 1376 | ||
1377 | /* Stop any autosuspend requests already submitted */ | 1377 | /* Stop any autosuspend or autoresume requests already submitted */ |
1378 | cancel_rearming_delayed_work(&udev->autosuspend); | 1378 | cancel_delayed_work_sync(&udev->autosuspend); |
1379 | cancel_work_sync(&udev->autoresume); | ||
1379 | } | 1380 | } |
1380 | 1381 | ||
1381 | #else | 1382 | #else |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 400fa4cc9a34..44f2fc750b6d 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -402,6 +402,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, | |||
402 | #ifdef CONFIG_PM | 402 | #ifdef CONFIG_PM |
403 | mutex_init(&dev->pm_mutex); | 403 | mutex_init(&dev->pm_mutex); |
404 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); | 404 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); |
405 | INIT_WORK(&dev->autoresume, usb_autoresume_work); | ||
405 | dev->autosuspend_delay = usb_autosuspend_delay * HZ; | 406 | dev->autosuspend_delay = usb_autosuspend_delay * HZ; |
406 | dev->connect_time = jiffies; | 407 | dev->connect_time = jiffies; |
407 | dev->active_duration = -jiffies; | 408 | dev->active_duration = -jiffies; |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 9a1a45ac3add..b60ebb4de1a8 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -45,6 +45,7 @@ extern int usb_suspend(struct device *dev, pm_message_t msg); | |||
45 | extern int usb_resume(struct device *dev); | 45 | extern int usb_resume(struct device *dev); |
46 | 46 | ||
47 | extern void usb_autosuspend_work(struct work_struct *work); | 47 | extern void usb_autosuspend_work(struct work_struct *work); |
48 | extern void usb_autoresume_work(struct work_struct *work); | ||
48 | extern int usb_port_suspend(struct usb_device *dev); | 49 | extern int usb_port_suspend(struct usb_device *dev); |
49 | extern int usb_port_resume(struct usb_device *dev); | 50 | extern int usb_port_resume(struct usb_device *dev); |
50 | extern int usb_external_suspend_device(struct usb_device *udev, | 51 | extern int usb_external_suspend_device(struct usb_device *udev, |
diff --git a/include/linux/usb.h b/include/linux/usb.h index f72aa51f7bcd..859a88e6ce9c 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -398,6 +398,7 @@ struct usb_tt; | |||
398 | * @urbnum: number of URBs submitted for the whole device | 398 | * @urbnum: number of URBs submitted for the whole device |
399 | * @active_duration: total time device is not suspended | 399 | * @active_duration: total time device is not suspended |
400 | * @autosuspend: for delayed autosuspends | 400 | * @autosuspend: for delayed autosuspends |
401 | * @autoresume: for autoresumes requested while in_interrupt | ||
401 | * @pm_mutex: protects PM operations | 402 | * @pm_mutex: protects PM operations |
402 | * @last_busy: time of last use | 403 | * @last_busy: time of last use |
403 | * @autosuspend_delay: in jiffies | 404 | * @autosuspend_delay: in jiffies |
@@ -476,6 +477,7 @@ struct usb_device { | |||
476 | 477 | ||
477 | #ifdef CONFIG_PM | 478 | #ifdef CONFIG_PM |
478 | struct delayed_work autosuspend; | 479 | struct delayed_work autosuspend; |
480 | struct work_struct autoresume; | ||
479 | struct mutex pm_mutex; | 481 | struct mutex pm_mutex; |
480 | 482 | ||
481 | unsigned long last_busy; | 483 | unsigned long last_busy; |
@@ -513,6 +515,8 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); | |||
513 | extern int usb_autopm_set_interface(struct usb_interface *intf); | 515 | extern int usb_autopm_set_interface(struct usb_interface *intf); |
514 | extern int usb_autopm_get_interface(struct usb_interface *intf); | 516 | extern int usb_autopm_get_interface(struct usb_interface *intf); |
515 | extern void usb_autopm_put_interface(struct usb_interface *intf); | 517 | extern void usb_autopm_put_interface(struct usb_interface *intf); |
518 | extern int usb_autopm_get_interface_async(struct usb_interface *intf); | ||
519 | extern void usb_autopm_put_interface_async(struct usb_interface *intf); | ||
516 | 520 | ||
517 | static inline void usb_autopm_enable(struct usb_interface *intf) | 521 | static inline void usb_autopm_enable(struct usb_interface *intf) |
518 | { | 522 | { |
@@ -539,8 +543,13 @@ static inline int usb_autopm_set_interface(struct usb_interface *intf) | |||
539 | static inline int usb_autopm_get_interface(struct usb_interface *intf) | 543 | static inline int usb_autopm_get_interface(struct usb_interface *intf) |
540 | { return 0; } | 544 | { return 0; } |
541 | 545 | ||
546 | static inline int usb_autopm_get_interface_async(struct usb_interface *intf) | ||
547 | { return 0; } | ||
548 | |||
542 | static inline void usb_autopm_put_interface(struct usb_interface *intf) | 549 | static inline void usb_autopm_put_interface(struct usb_interface *intf) |
543 | { } | 550 | { } |
551 | static inline void usb_autopm_put_interface_async(struct usb_interface *intf) | ||
552 | { } | ||
544 | static inline void usb_autopm_enable(struct usb_interface *intf) | 553 | static inline void usb_autopm_enable(struct usb_interface *intf) |
545 | { } | 554 | { } |
546 | static inline void usb_autopm_disable(struct usb_interface *intf) | 555 | static inline void usb_autopm_disable(struct usb_interface *intf) |