diff options
author | Ming Lei <tom.leiming@gmail.com> | 2010-11-15 15:56:54 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-16 17:02:00 -0500 |
commit | 63defa73c8c1193c1273474440c30d34c2524597 (patch) | |
tree | 3d7cbe9351e507ca2e55a874e496398979602ec1 | |
parent | f646cf94520e22cb11eb5d2e9a35b33bfe4bea1b (diff) |
USB: use the no_callbacks flag for interfaces
Call pm_runtime_no_callbacks to set no_callbacks flag for USB
interfaces. Since interfaces cannot be power-managed separately from
their parent devices, there's no reason for the runtime-PM core to
invoke any callbacks for them.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/core/driver.c | 82 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 2 |
2 files changed, 31 insertions, 53 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index c0e60fbcb048..eda2d2c25459 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -1612,18 +1612,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface); | |||
1612 | */ | 1612 | */ |
1613 | int usb_autopm_get_interface_async(struct usb_interface *intf) | 1613 | int usb_autopm_get_interface_async(struct usb_interface *intf) |
1614 | { | 1614 | { |
1615 | int status = 0; | 1615 | int status; |
1616 | enum rpm_status s; | ||
1617 | |||
1618 | /* Don't request a resume unless the interface is already suspending | ||
1619 | * or suspended. Doing so would force a running suspend timer to be | ||
1620 | * cancelled. | ||
1621 | */ | ||
1622 | pm_runtime_get_noresume(&intf->dev); | ||
1623 | s = ACCESS_ONCE(intf->dev.power.runtime_status); | ||
1624 | if (s == RPM_SUSPENDING || s == RPM_SUSPENDED) | ||
1625 | status = pm_request_resume(&intf->dev); | ||
1626 | 1616 | ||
1617 | status = pm_runtime_get(&intf->dev); | ||
1627 | if (status < 0 && status != -EINPROGRESS) | 1618 | if (status < 0 && status != -EINPROGRESS) |
1628 | pm_runtime_put_noidle(&intf->dev); | 1619 | pm_runtime_put_noidle(&intf->dev); |
1629 | else | 1620 | else |
@@ -1717,71 +1708,56 @@ static int autosuspend_check(struct usb_device *udev) | |||
1717 | 1708 | ||
1718 | static int usb_runtime_suspend(struct device *dev) | 1709 | static int usb_runtime_suspend(struct device *dev) |
1719 | { | 1710 | { |
1720 | int status = 0; | 1711 | struct usb_device *udev = to_usb_device(dev); |
1712 | int status; | ||
1721 | 1713 | ||
1722 | /* A USB device can be suspended if it passes the various autosuspend | 1714 | /* A USB device can be suspended if it passes the various autosuspend |
1723 | * checks. Runtime suspend for a USB device means suspending all the | 1715 | * checks. Runtime suspend for a USB device means suspending all the |
1724 | * interfaces and then the device itself. | 1716 | * interfaces and then the device itself. |
1725 | */ | 1717 | */ |
1726 | if (is_usb_device(dev)) { | 1718 | if (autosuspend_check(udev) != 0) |
1727 | struct usb_device *udev = to_usb_device(dev); | 1719 | return -EAGAIN; |
1728 | |||
1729 | if (autosuspend_check(udev) != 0) | ||
1730 | return -EAGAIN; | ||
1731 | |||
1732 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); | ||
1733 | 1720 | ||
1734 | /* If an interface fails the suspend, adjust the last_busy | 1721 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); |
1735 | * time so that we don't get another suspend attempt right | ||
1736 | * away. | ||
1737 | */ | ||
1738 | if (status) { | ||
1739 | udev->last_busy = jiffies + | ||
1740 | (udev->autosuspend_delay == 0 ? | ||
1741 | HZ/2 : 0); | ||
1742 | } | ||
1743 | 1722 | ||
1744 | /* Prevent the parent from suspending immediately after */ | 1723 | /* If an interface fails the suspend, adjust the last_busy |
1745 | else if (udev->parent) | 1724 | * time so that we don't get another suspend attempt right |
1746 | udev->parent->last_busy = jiffies; | 1725 | * away. |
1726 | */ | ||
1727 | if (status) { | ||
1728 | udev->last_busy = jiffies + | ||
1729 | (udev->autosuspend_delay == 0 ? HZ/2 : 0); | ||
1747 | } | 1730 | } |
1748 | 1731 | ||
1749 | /* Runtime suspend for a USB interface doesn't mean anything. */ | 1732 | /* Prevent the parent from suspending immediately after */ |
1733 | else if (udev->parent) | ||
1734 | udev->parent->last_busy = jiffies; | ||
1735 | |||
1750 | return status; | 1736 | return status; |
1751 | } | 1737 | } |
1752 | 1738 | ||
1753 | static int usb_runtime_resume(struct device *dev) | 1739 | static int usb_runtime_resume(struct device *dev) |
1754 | { | 1740 | { |
1741 | struct usb_device *udev = to_usb_device(dev); | ||
1742 | int status; | ||
1743 | |||
1755 | /* Runtime resume for a USB device means resuming both the device | 1744 | /* Runtime resume for a USB device means resuming both the device |
1756 | * and all its interfaces. | 1745 | * and all its interfaces. |
1757 | */ | 1746 | */ |
1758 | if (is_usb_device(dev)) { | 1747 | status = usb_resume_both(udev, PMSG_AUTO_RESUME); |
1759 | struct usb_device *udev = to_usb_device(dev); | 1748 | udev->last_busy = jiffies; |
1760 | int status; | 1749 | return status; |
1761 | |||
1762 | status = usb_resume_both(udev, PMSG_AUTO_RESUME); | ||
1763 | udev->last_busy = jiffies; | ||
1764 | return status; | ||
1765 | } | ||
1766 | |||
1767 | /* Runtime resume for a USB interface doesn't mean anything. */ | ||
1768 | return 0; | ||
1769 | } | 1750 | } |
1770 | 1751 | ||
1771 | static int usb_runtime_idle(struct device *dev) | 1752 | static int usb_runtime_idle(struct device *dev) |
1772 | { | 1753 | { |
1754 | struct usb_device *udev = to_usb_device(dev); | ||
1755 | |||
1773 | /* An idle USB device can be suspended if it passes the various | 1756 | /* An idle USB device can be suspended if it passes the various |
1774 | * autosuspend checks. An idle interface can be suspended at | 1757 | * autosuspend checks. |
1775 | * any time. | ||
1776 | */ | 1758 | */ |
1777 | if (is_usb_device(dev)) { | 1759 | if (autosuspend_check(udev) == 0) |
1778 | struct usb_device *udev = to_usb_device(dev); | 1760 | pm_runtime_suspend(dev); |
1779 | |||
1780 | if (autosuspend_check(udev) != 0) | ||
1781 | return 0; | ||
1782 | } | ||
1783 | |||
1784 | pm_runtime_suspend(dev); | ||
1785 | return 0; | 1761 | return 0; |
1786 | } | 1762 | } |
1787 | 1763 | ||
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index d6e3e410477e..f377e49fcb30 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
13 | #include <linux/nls.h> | 13 | #include <linux/nls.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/pm_runtime.h> | ||
15 | #include <linux/scatterlist.h> | 16 | #include <linux/scatterlist.h> |
16 | #include <linux/usb/quirks.h> | 17 | #include <linux/usb/quirks.h> |
17 | #include <linux/usb/hcd.h> /* for usbcore internals */ | 18 | #include <linux/usb/hcd.h> /* for usbcore internals */ |
@@ -1804,6 +1805,7 @@ free_interfaces: | |||
1804 | INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); | 1805 | INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); |
1805 | intf->minor = -1; | 1806 | intf->minor = -1; |
1806 | device_initialize(&intf->dev); | 1807 | device_initialize(&intf->dev); |
1808 | pm_runtime_no_callbacks(&intf->dev); | ||
1807 | dev_set_name(&intf->dev, "%d-%s:%d.%d", | 1809 | dev_set_name(&intf->dev, "%d-%s:%d.%d", |
1808 | dev->bus->busnum, dev->devpath, | 1810 | dev->bus->busnum, dev->devpath, |
1809 | configuration, alt->desc.bInterfaceNumber); | 1811 | configuration, alt->desc.bInterfaceNumber); |