From 89842ae6515c49405e20c0629a6442b6885ad49d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 11 May 2010 11:44:06 -0400 Subject: [PATCH] USB: fix interface runtime-PM settings This patch (as1379) reworks the logic for handling USB interface runtime-PM settings -- hopefully it's right this time! The problem is that when a driver is unbound or binding fails, runtime PM for the interface always gets disabled. But pm_runtime_disable() nests, so it shouldn't be called unless the interface was previously enabled for runtime PM. Signed-off-by: Alan Stern Reported-by: Rob Duncan Tested-by: Rob Duncan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 207146743ea..ded550eda5d 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -334,7 +334,8 @@ static int usb_probe_interface(struct device *dev) usb_cancel_queued_reset(intf); /* Unbound interfaces are always runtime-PM-disabled and -suspended */ - pm_runtime_disable(dev); + if (driver->supports_autosuspend) + pm_runtime_disable(dev); pm_runtime_set_suspended(dev); usb_autosuspend_device(udev); @@ -389,7 +390,8 @@ static int usb_unbind_interface(struct device *dev) intf->needs_remote_wakeup = 0; /* Unbound interfaces are always runtime-PM-disabled and -suspended */ - pm_runtime_disable(dev); + if (driver->supports_autosuspend) + pm_runtime_disable(dev); pm_runtime_set_suspended(dev); /* Undo any residual pm_autopm_get_interface_* calls */ @@ -438,14 +440,17 @@ int usb_driver_claim_interface(struct usb_driver *driver, iface->condition = USB_INTERFACE_BOUND; - /* Claimed interfaces are initially inactive (suspended). They are - * runtime-PM-enabled only if the driver has autosuspend support. - * They are sensitive to their children's power states. + /* Claimed interfaces are initially inactive (suspended) and + * runtime-PM-enabled, but only if the driver has autosuspend + * support. Otherwise they are marked active, to prevent the + * device from being autosuspended, but left disabled. In either + * case they are sensitive to their children's power states. */ - pm_runtime_set_suspended(dev); pm_suspend_ignore_children(dev, false); if (driver->supports_autosuspend) pm_runtime_enable(dev); + else + pm_runtime_set_active(dev); /* if interface was already added, bind now; else let * the future device_add() bind it, bypassing probe() -- 2.20.1