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

Commit c9678821 authored by Zhenzhong Duan's avatar Zhenzhong Duan Committed by Greg Kroah-Hartman
Browse files

cpuidle: Do not unset the driver if it is there already



commit 918c1fe9fbbe46fcf56837ff21f0ef96424e8b29 upstream.

Fix __cpuidle_set_driver() to check if any of the CPUs in the mask has
a driver different from drv already and, if so, return -EBUSY before
updating any cpuidle_drivers per-CPU pointers.

Fixes: 82467a5a ("cpuidle: simplify multiple driver support")
Cc: 3.11+ <stable@vger.kernel.org> # 3.11+
Signed-off-by: default avatarZhenzhong Duan <zhenzhong.duan@oracle.com>
[ rjw: Subject & changelog ]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent aedc1c75
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -62,24 +62,23 @@ static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)
 * __cpuidle_set_driver - set per CPU driver variables for the given driver.
 * @drv: a valid pointer to a struct cpuidle_driver
 *
 * For each CPU in the driver's cpumask, unset the registered driver per CPU
 * to @drv.
 *
 * Returns 0 on success, -EBUSY if the CPUs have driver(s) already.
 * Returns 0 on success, -EBUSY if any CPU in the cpumask have a driver
 * different from drv already.
 */
static inline int __cpuidle_set_driver(struct cpuidle_driver *drv)
{
	int cpu;

	for_each_cpu(cpu, drv->cpumask) {
		struct cpuidle_driver *old_drv;

		if (__cpuidle_get_cpu_driver(cpu)) {
			__cpuidle_unset_driver(drv);
		old_drv = __cpuidle_get_cpu_driver(cpu);
		if (old_drv && old_drv != drv)
			return -EBUSY;
	}

	for_each_cpu(cpu, drv->cpumask)
		per_cpu(cpuidle_drivers, cpu) = drv;
	}

	return 0;
}