提交 63defa73 编写于 作者: M Ming Lei 提交者: Greg Kroah-Hartman

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: NMing Lei <tom.leiming@gmail.com>
Reviewed-by: NAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 f646cf94
...@@ -1612,18 +1612,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface); ...@@ -1612,18 +1612,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
*/ */
int usb_autopm_get_interface_async(struct usb_interface *intf) int usb_autopm_get_interface_async(struct usb_interface *intf)
{ {
int status = 0; int status;
enum rpm_status s;
/* Don't request a resume unless the interface is already suspending
* or suspended. Doing so would force a running suspend timer to be
* cancelled.
*/
pm_runtime_get_noresume(&intf->dev);
s = ACCESS_ONCE(intf->dev.power.runtime_status);
if (s == RPM_SUSPENDING || s == RPM_SUSPENDED)
status = pm_request_resume(&intf->dev);
status = pm_runtime_get(&intf->dev);
if (status < 0 && status != -EINPROGRESS) if (status < 0 && status != -EINPROGRESS)
pm_runtime_put_noidle(&intf->dev); pm_runtime_put_noidle(&intf->dev);
else else
...@@ -1717,71 +1708,56 @@ static int autosuspend_check(struct usb_device *udev) ...@@ -1717,71 +1708,56 @@ static int autosuspend_check(struct usb_device *udev)
static int usb_runtime_suspend(struct device *dev) static int usb_runtime_suspend(struct device *dev)
{ {
int status = 0; struct usb_device *udev = to_usb_device(dev);
int status;
/* A USB device can be suspended if it passes the various autosuspend /* A USB device can be suspended if it passes the various autosuspend
* checks. Runtime suspend for a USB device means suspending all the * checks. Runtime suspend for a USB device means suspending all the
* interfaces and then the device itself. * interfaces and then the device itself.
*/ */
if (is_usb_device(dev)) { if (autosuspend_check(udev) != 0)
struct usb_device *udev = to_usb_device(dev); return -EAGAIN;
if (autosuspend_check(udev) != 0)
return -EAGAIN;
status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
/* If an interface fails the suspend, adjust the last_busy status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
* time so that we don't get another suspend attempt right
* away.
*/
if (status) {
udev->last_busy = jiffies +
(udev->autosuspend_delay == 0 ?
HZ/2 : 0);
}
/* Prevent the parent from suspending immediately after */ /* If an interface fails the suspend, adjust the last_busy
else if (udev->parent) * time so that we don't get another suspend attempt right
udev->parent->last_busy = jiffies; * away.
*/
if (status) {
udev->last_busy = jiffies +
(udev->autosuspend_delay == 0 ? HZ/2 : 0);
} }
/* Runtime suspend for a USB interface doesn't mean anything. */ /* Prevent the parent from suspending immediately after */
else if (udev->parent)
udev->parent->last_busy = jiffies;
return status; return status;
} }
static int usb_runtime_resume(struct device *dev) static int usb_runtime_resume(struct device *dev)
{ {
struct usb_device *udev = to_usb_device(dev);
int status;
/* Runtime resume for a USB device means resuming both the device /* Runtime resume for a USB device means resuming both the device
* and all its interfaces. * and all its interfaces.
*/ */
if (is_usb_device(dev)) { status = usb_resume_both(udev, PMSG_AUTO_RESUME);
struct usb_device *udev = to_usb_device(dev); udev->last_busy = jiffies;
int status; return status;
status = usb_resume_both(udev, PMSG_AUTO_RESUME);
udev->last_busy = jiffies;
return status;
}
/* Runtime resume for a USB interface doesn't mean anything. */
return 0;
} }
static int usb_runtime_idle(struct device *dev) static int usb_runtime_idle(struct device *dev)
{ {
struct usb_device *udev = to_usb_device(dev);
/* An idle USB device can be suspended if it passes the various /* An idle USB device can be suspended if it passes the various
* autosuspend checks. An idle interface can be suspended at * autosuspend checks.
* any time.
*/ */
if (is_usb_device(dev)) { if (autosuspend_check(udev) == 0)
struct usb_device *udev = to_usb_device(dev); pm_runtime_suspend(dev);
if (autosuspend_check(udev) != 0)
return 0;
}
pm_runtime_suspend(dev);
return 0; return 0;
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/nls.h> #include <linux/nls.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/pm_runtime.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/usb/quirks.h> #include <linux/usb/quirks.h>
#include <linux/usb/hcd.h> /* for usbcore internals */ #include <linux/usb/hcd.h> /* for usbcore internals */
...@@ -1804,6 +1805,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1804,6 +1805,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
intf->minor = -1; intf->minor = -1;
device_initialize(&intf->dev); device_initialize(&intf->dev);
pm_runtime_no_callbacks(&intf->dev);
dev_set_name(&intf->dev, "%d-%s:%d.%d", dev_set_name(&intf->dev, "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath, dev->bus->busnum, dev->devpath,
configuration, alt->desc.bInterfaceNumber); configuration, alt->desc.bInterfaceNumber);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册