mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-05 08:38:28 -04:00
Merge tag 'pm-for-3.6-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael J. Wysocki: - Fixes for three obscure problems in the runtime PM core code found recently. - Two fixes for the new "coupled" cpuidle code from Colin Cross and Jon Medhurst. - intel_idle driver fix from Konrad Rzeszutek Wilk. * tag 'pm-for-3.6-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: intel_idle: Check cpu_idle_get_driver() for NULL before dereferencing it. cpuidle: Prevent null pointer dereference in cpuidle_coupled_cpu_notify cpuidle: coupled: fix sleeping while atomic in cpu notifier PM / Runtime: Check device PM QoS setting before "no callbacks" check PM / Runtime: Clear power.deferred_resume on success in rpm_suspend() PM / Runtime: Fix rpm_resume() return value for power.no_callbacks set
This commit is contained in:
@@ -147,6 +147,8 @@ static int rpm_check_suspend_allowed(struct device *dev)
|
||||
|| (dev->power.request_pending
|
||||
&& dev->power.request == RPM_REQ_RESUME))
|
||||
retval = -EAGAIN;
|
||||
else if (__dev_pm_qos_read_value(dev) < 0)
|
||||
retval = -EPERM;
|
||||
else if (dev->power.runtime_status == RPM_SUSPENDED)
|
||||
retval = 1;
|
||||
|
||||
@@ -388,7 +390,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
dev->power.deferred_resume = false;
|
||||
if (dev->power.no_callbacks)
|
||||
goto no_callback; /* Assume success. */
|
||||
|
||||
@@ -403,12 +404,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (__dev_pm_qos_read_value(dev) < 0) {
|
||||
/* Negative PM QoS constraint means "never suspend". */
|
||||
retval = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
__update_runtime_status(dev, RPM_SUSPENDING);
|
||||
|
||||
if (dev->pm_domain)
|
||||
@@ -440,6 +435,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
|
||||
wake_up_all(&dev->power.wait_queue);
|
||||
|
||||
if (dev->power.deferred_resume) {
|
||||
dev->power.deferred_resume = false;
|
||||
rpm_resume(dev, 0);
|
||||
retval = -EAGAIN;
|
||||
goto out;
|
||||
@@ -584,6 +580,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
|
||||
|| dev->parent->power.runtime_status == RPM_ACTIVE) {
|
||||
atomic_inc(&dev->parent->power.child_count);
|
||||
spin_unlock(&dev->parent->power.lock);
|
||||
retval = 1;
|
||||
goto no_callback; /* Assume success. */
|
||||
}
|
||||
spin_unlock(&dev->parent->power.lock);
|
||||
@@ -664,7 +661,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
|
||||
}
|
||||
wake_up_all(&dev->power.wait_queue);
|
||||
|
||||
if (!retval)
|
||||
if (retval >= 0)
|
||||
rpm_idle(dev, RPM_ASYNC);
|
||||
|
||||
out:
|
||||
|
||||
@@ -678,10 +678,22 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb,
|
||||
int cpu = (unsigned long)hcpu;
|
||||
struct cpuidle_device *dev;
|
||||
|
||||
switch (action & ~CPU_TASKS_FROZEN) {
|
||||
case CPU_UP_PREPARE:
|
||||
case CPU_DOWN_PREPARE:
|
||||
case CPU_ONLINE:
|
||||
case CPU_DEAD:
|
||||
case CPU_UP_CANCELED:
|
||||
case CPU_DOWN_FAILED:
|
||||
break;
|
||||
default:
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
mutex_lock(&cpuidle_lock);
|
||||
|
||||
dev = per_cpu(cpuidle_devices, cpu);
|
||||
if (!dev->coupled)
|
||||
if (!dev || !dev->coupled)
|
||||
goto out;
|
||||
|
||||
switch (action & ~CPU_TASKS_FROZEN) {
|
||||
|
||||
@@ -606,8 +606,9 @@ static int __init intel_idle_init(void)
|
||||
intel_idle_cpuidle_driver_init();
|
||||
retval = cpuidle_register_driver(&intel_idle_driver);
|
||||
if (retval) {
|
||||
struct cpuidle_driver *drv = cpuidle_get_driver();
|
||||
printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
|
||||
cpuidle_get_driver()->name);
|
||||
drv ? drv->name : "none");
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user