Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9ec0fdc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+5 −8
Original line number Diff line number Diff line
@@ -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:
+13 −1
Original line number Diff line number Diff line
@@ -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) {
+2 −1
Original line number Diff line number Diff line
@@ -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;
	}