Power management fixes for 3.6-rc3
* 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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iQIcBAABAgAGBQJQMAOWAAoJEKhOf7ml8uNswp0QAK2pHmZMU8Pg3mY0Qlovvcmn KordhSahzwodvdKMpzGqjk/TO3kJ0dk8YGBY1qIzSySmE6S9qsJKQaaoiNR0Se83 5ZpGVNfJpFBwzrHQkOMkaZzirC5gegKVykM6jlvh3oZqgqGWDawnzOsGCJvYv0lI fSAgIc0CDB2dK5V9zFduXp3Cjv2cGEgW/Dd3ggPYns9JZJTAcHuD6cPdSQVml0JG vk2VA1IjqRYyn9eSIOerezwh7iVCrAF5miiADXkaTD1fQ9ZyHYfxuqwM1jpijlkz PEuICp4FJ4MTPjKYcJgJct0vdc0uD60dvHz9k7PxDIQ35eFiYJYeSU70oNCqULVh lhN0VWqUZI1m7U/jH3f/pCc5x4jVhwQvuEE7yIz8d7nclhWqpBElZgyZ8B3yQiR0 JSChvGtLgYdXYnk6epw4sL6EZpqQW9Xk/JPJpyEy6KAIY45p8q/a972OmGU35ltN qAkeBVcAW836NzgnHPJs17R6VzhxFFegd38NbqRvRsVL0Og9+RoT8P9gt2ZPoQ7O jBGT/iKn1GzMSTpDGbgj9Nf3tm1zs+pvZ2fc/niBZH/72eyLQVs8zgm0TJVrTA26 uKeE7l+R3UrsMhBO28kFsX37q3gOYBjtf2K7u2W1q71aNE6YcXdfJfd2aGDZ1LTQ 1d9MuFjbR6hKQE2Mb7YH =fO1w -----END PGP SIGNATURE----- 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:
Коммит
d9ec0fdc24
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче