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

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: 82467a5a88 ("cpuidle: simplify multiple driver support")
Cc: 3.11+ <stable@vger.kernel.org> # 3.11+
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@oracle.com>
[ rjw: Subject & changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Zhenzhong Duan 2019-10-23 09:57:14 +08:00 committed by Rafael J. Wysocki
parent 2c2a83d329
commit 918c1fe9fb

View File

@ -62,25 +62,24 @@ 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;
}
per_cpu(cpuidle_drivers, cpu) = drv;
}
for_each_cpu(cpu, drv->cpumask)
per_cpu(cpuidle_drivers, cpu) = drv;
return 0;
}