Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries/cpuidle: Replace pseries_notify_cpuidle_add call with notifier

The following patch is to remove the pseries_notify_add_cpu() call
and replace it by a hot plug notifier.

This would prevent cpuidle resources being released and allocated each
time cpu comes online on pseries.

The earlier design was causing a lockdep problem
in start_secondary as reported on this thread
-https://lkml.org/lkml/2012/5/17/2

This applies on 3.4-rc7

Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Deepthi Dharwar and committed by
Benjamin Herrenschmidt
16aaaff6 25ebc45b

+19 -9
-2
arch/powerpc/include/asm/processor.h
··· 389 389 390 390 #ifdef CONFIG_PSERIES_IDLE 391 391 extern void update_smt_snooze_delay(int snooze); 392 - extern int pseries_notify_cpuidle_add_cpu(int cpu); 393 392 #else 394 393 static inline void update_smt_snooze_delay(int snooze) {} 395 - static inline int pseries_notify_cpuidle_add_cpu(int cpu) { return 0; } 396 394 #endif 397 395 398 396 extern void flush_instruction_cache(void);
+19 -6
arch/powerpc/platforms/pseries/processor_idle.c
··· 11 11 #include <linux/moduleparam.h> 12 12 #include <linux/cpuidle.h> 13 13 #include <linux/cpu.h> 14 + #include <linux/notifier.h> 14 15 15 16 #include <asm/paca.h> 16 17 #include <asm/reg.h> ··· 187 186 .enter = &shared_cede_loop }, 188 187 }; 189 188 190 - int pseries_notify_cpuidle_add_cpu(int cpu) 189 + static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n, 190 + unsigned long action, void *hcpu) 191 191 { 192 + int hotcpu = (unsigned long)hcpu; 192 193 struct cpuidle_device *dev = 193 - per_cpu_ptr(pseries_cpuidle_devices, cpu); 194 - if (dev && cpuidle_get_driver()) { 195 - cpuidle_disable_device(dev); 196 - cpuidle_enable_device(dev); 194 + per_cpu_ptr(pseries_cpuidle_devices, hotcpu); 195 + 196 + switch (action & 0xf) { 197 + case CPU_ONLINE: 198 + if (dev && cpuidle_get_driver()) { 199 + cpuidle_disable_device(dev); 200 + cpuidle_enable_device(dev); 201 + } 202 + break; 197 203 } 198 - return 0; 204 + return NOTIFY_OK; 199 205 } 206 + 207 + static struct notifier_block setup_hotplug_notifier = { 208 + .notifier_call = pseries_cpuidle_add_cpu_notifier, 209 + }; 200 210 201 211 /* 202 212 * pseries_cpuidle_driver_init() ··· 333 321 return retval; 334 322 } 335 323 324 + register_cpu_notifier(&setup_hotplug_notifier); 336 325 printk(KERN_DEBUG "pseries_idle_driver registered\n"); 337 326 338 327 return 0;
-1
arch/powerpc/platforms/pseries/smp.c
··· 147 147 set_cpu_current_state(cpu, CPU_STATE_ONLINE); 148 148 set_default_offline_state(cpu); 149 149 #endif 150 - pseries_notify_cpuidle_add_cpu(cpu); 151 150 } 152 151 153 152 static int __devinit smp_pSeries_kick_cpu(int nr)