Commit d9ec0fdc authored by Linus Torvalds's avatar Linus Torvalds

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
parents 20fb1936 3735d524
...@@ -147,6 +147,8 @@ static int rpm_check_suspend_allowed(struct device *dev) ...@@ -147,6 +147,8 @@ static int rpm_check_suspend_allowed(struct device *dev)
|| (dev->power.request_pending || (dev->power.request_pending
&& dev->power.request == RPM_REQ_RESUME)) && dev->power.request == RPM_REQ_RESUME))
retval = -EAGAIN; retval = -EAGAIN;
else if (__dev_pm_qos_read_value(dev) < 0)
retval = -EPERM;
else if (dev->power.runtime_status == RPM_SUSPENDED) else if (dev->power.runtime_status == RPM_SUSPENDED)
retval = 1; retval = 1;
...@@ -388,7 +390,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) ...@@ -388,7 +390,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
goto repeat; goto repeat;
} }
dev->power.deferred_resume = false;
if (dev->power.no_callbacks) if (dev->power.no_callbacks)
goto no_callback; /* Assume success. */ goto no_callback; /* Assume success. */
...@@ -403,12 +404,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) ...@@ -403,12 +404,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
goto out; 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); __update_runtime_status(dev, RPM_SUSPENDING);
if (dev->pm_domain) if (dev->pm_domain)
...@@ -440,6 +435,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) ...@@ -440,6 +435,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
wake_up_all(&dev->power.wait_queue); wake_up_all(&dev->power.wait_queue);
if (dev->power.deferred_resume) { if (dev->power.deferred_resume) {
dev->power.deferred_resume = false;
rpm_resume(dev, 0); rpm_resume(dev, 0);
retval = -EAGAIN; retval = -EAGAIN;
goto out; goto out;
...@@ -584,6 +580,7 @@ static int rpm_resume(struct device *dev, int rpmflags) ...@@ -584,6 +580,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
|| dev->parent->power.runtime_status == RPM_ACTIVE) { || dev->parent->power.runtime_status == RPM_ACTIVE) {
atomic_inc(&dev->parent->power.child_count); atomic_inc(&dev->parent->power.child_count);
spin_unlock(&dev->parent->power.lock); spin_unlock(&dev->parent->power.lock);
retval = 1;
goto no_callback; /* Assume success. */ goto no_callback; /* Assume success. */
} }
spin_unlock(&dev->parent->power.lock); spin_unlock(&dev->parent->power.lock);
...@@ -664,7 +661,7 @@ static int rpm_resume(struct device *dev, int rpmflags) ...@@ -664,7 +661,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
} }
wake_up_all(&dev->power.wait_queue); wake_up_all(&dev->power.wait_queue);
if (!retval) if (retval >= 0)
rpm_idle(dev, RPM_ASYNC); rpm_idle(dev, RPM_ASYNC);
out: out:
......
...@@ -678,10 +678,22 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb, ...@@ -678,10 +678,22 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb,
int cpu = (unsigned long)hcpu; int cpu = (unsigned long)hcpu;
struct cpuidle_device *dev; 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); mutex_lock(&cpuidle_lock);
dev = per_cpu(cpuidle_devices, cpu); dev = per_cpu(cpuidle_devices, cpu);
if (!dev->coupled) if (!dev || !dev->coupled)
goto out; goto out;
switch (action & ~CPU_TASKS_FROZEN) { switch (action & ~CPU_TASKS_FROZEN) {
......
...@@ -606,8 +606,9 @@ static int __init intel_idle_init(void) ...@@ -606,8 +606,9 @@ static int __init intel_idle_init(void)
intel_idle_cpuidle_driver_init(); intel_idle_cpuidle_driver_init();
retval = cpuidle_register_driver(&intel_idle_driver); retval = cpuidle_register_driver(&intel_idle_driver);
if (retval) { if (retval) {
struct cpuidle_driver *drv = cpuidle_get_driver();
printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
cpuidle_get_driver()->name); drv ? drv->name : "none");
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment