aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorVaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>2013-09-05 14:55:06 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-09-10 21:41:54 -0400
commit363edbe2614aa90df706c0f19ccfa2a6c06af0be (patch)
tree447d506fd8a36e14853216a0bbbbb540b10f7304 /arch/powerpc/platforms/pseries
parent88c2d0b6fa753c63047fad92eac94c376ee4e568 (diff)
powerpc: Default arch idle could cede processor on pseries
When adding cpuidle support to pSeries, we introduced two regressions: - The new cpuidle backend driver only works under hypervisors supporting the "SLPLAR" option, which isn't the case of the old POWER4 hypervisor and the HV "light" used on js2x blades - The cpuidle driver registers fairly late, meaning that for a significant portion of the boot process, we end up having all threads spinning. This slows down the boot process and increases the overall resource usage if the hypervisor has shared processors. This fixes both by implementing a "default" idle that will cede to the hypervisor when possible, in a very simple way without all the bells and whisles of cpuidle. Reported-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> Acked-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> CC: <stable@vger.kernel.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/setup.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index d64feb3ea0be..1f97e2b87a62 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -354,7 +354,7 @@ static int alloc_dispatch_log_kmem_cache(void)
354} 354}
355early_initcall(alloc_dispatch_log_kmem_cache); 355early_initcall(alloc_dispatch_log_kmem_cache);
356 356
357static void pSeries_idle(void) 357static void pseries_lpar_idle(void)
358{ 358{
359 /* This would call on the cpuidle framework, and the back-end pseries 359 /* This would call on the cpuidle framework, and the back-end pseries
360 * driver to go to idle states 360 * driver to go to idle states
@@ -362,10 +362,22 @@ static void pSeries_idle(void)
362 if (cpuidle_idle_call()) { 362 if (cpuidle_idle_call()) {
363 /* On error, execute default handler 363 /* On error, execute default handler
364 * to go into low thread priority and possibly 364 * to go into low thread priority and possibly
365 * low power mode. 365 * low power mode by cedeing processor to hypervisor
366 */ 366 */
367 HMT_low(); 367
368 HMT_very_low(); 368 /* Indicate to hypervisor that we are idle. */
369 get_lppaca()->idle = 1;
370
371 /*
372 * Yield the processor to the hypervisor. We return if
373 * an external interrupt occurs (which are driven prior
374 * to returning here) or if a prod occurs from another
375 * processor. When returning here, external interrupts
376 * are enabled.
377 */
378 cede_processor();
379
380 get_lppaca()->idle = 0;
369 } 381 }
370} 382}
371 383
@@ -456,15 +468,14 @@ static void __init pSeries_setup_arch(void)
456 468
457 pSeries_nvram_init(); 469 pSeries_nvram_init();
458 470
459 if (firmware_has_feature(FW_FEATURE_SPLPAR)) { 471 if (firmware_has_feature(FW_FEATURE_LPAR)) {
460 vpa_init(boot_cpuid); 472 vpa_init(boot_cpuid);
461 ppc_md.power_save = pSeries_idle; 473 ppc_md.power_save = pseries_lpar_idle;
462 }
463
464 if (firmware_has_feature(FW_FEATURE_LPAR))
465 ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; 474 ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
466 else 475 } else {
476 /* No special idle routine */
467 ppc_md.enable_pmcs = power4_enable_pmcs; 477 ppc_md.enable_pmcs = power4_enable_pmcs;
478 }
468 479
469 ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; 480 ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
470 481