diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-05 17:54:18 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-05 17:54:18 -0700 |
commit | 8110efc64c4790cd1bf7e30f080e5ba3faa7cb85 (patch) | |
tree | 708c2a1ef6bebce8eda9676c554bea366547678e /drivers | |
parent | 06d8eb1b7d1eb34c76538dab791bc14136ebbc8f (diff) | |
parent | d6cc76856d353a3a9c43bead33210b9216dce332 (diff) |
Merge branch 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
* 'pm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM / Freezer: Revert 27920651fe "PM / Freezer: Make fake_signal_wake_up() wake TASK_KILLABLE tasks too"
PM / Freezer: Reimplement wait_event_freezekillable using freezer_do_not_count/freezer_count
USB: Update last_busy time after autosuspend fails
PM / Runtime: Automatically retry failed autosuspends
PM / QoS: Remove redundant check
PM / OPP: Fix build when CONFIG_PM_OPP is not set
PM / Runtime: Fix runtime accounting calculation error
PM / Sleep: Update freezer documentation
PM / Sleep: Remove unused symbol 'suspend_cpu_hotplug'
PM / Sleep: Fix race between CPU hotplug and freezer
ACPI / PM: Add Sony VPCEB17FX to nonvs blacklist
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/sleep.c | 8 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 23 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 5 |
3 files changed, 30 insertions, 6 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 0e46faef1d3..6d9a3ab58db 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -398,6 +398,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, { .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB17FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), + }, + }, + { + .callback = init_nvs_nosave, .ident = "Sony Vaio VGN-SR11M", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 6bb3aafa85e..124dbf60c9b 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -29,13 +29,10 @@ static int rpm_suspend(struct device *dev, int rpmflags); void update_pm_runtime_accounting(struct device *dev) { unsigned long now = jiffies; - int delta; + unsigned long delta; delta = now - dev->power.accounting_timestamp; - if (delta < 0) - delta = 0; - dev->power.accounting_timestamp = now; if (dev->power.disable_depth > 0) @@ -296,6 +293,9 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev) * the callback was running then carry it out, otherwise send an idle * notification for its parent (if the suspend succeeded and both * ignore_children of parent->power and irq_safe of dev->power are not set). + * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO + * flag is set and the next autosuspend-delay expiration time is in the + * future, schedule another autosuspend attempt. * * This function must be called under dev->power.lock with interrupts disabled. */ @@ -416,10 +416,21 @@ static int rpm_suspend(struct device *dev, int rpmflags) if (retval) { __update_runtime_status(dev, RPM_ACTIVE); dev->power.deferred_resume = false; - if (retval == -EAGAIN || retval == -EBUSY) + if (retval == -EAGAIN || retval == -EBUSY) { dev->power.runtime_error = 0; - else + + /* + * If the callback routine failed an autosuspend, and + * if the last_busy time has been updated so that there + * is a new autosuspend expiration time, automatically + * reschedule another autosuspend. + */ + if ((rpmflags & RPM_AUTO) && + pm_runtime_autosuspend_expiration(dev) != 0) + goto repeat; + } else { pm_runtime_cancel_pending(dev); + } wake_up_all(&dev->power.wait_queue); goto out; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 3b029a0a478..c2c0ae57e7f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1667,6 +1667,11 @@ int usb_runtime_suspend(struct device *dev) return -EAGAIN; status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); + + /* Allow a retry if autosuspend failed temporarily */ + if (status == -EAGAIN || status == -EBUSY) + usb_mark_last_busy(udev); + /* The PM core reacts badly unless the return code is 0, * -EAGAIN, or -EBUSY, so always return -EBUSY on an error. */ |