Skip to content

Commit

Permalink
powerpc: Default arch idle could cede processor on pseries
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vaidyanathan Srinivasan authored and Benjamin Herrenschmidt committed Sep 11, 2013
1 parent 88c2d0b commit 363edbe
Showing 1 changed file with 21 additions and 10 deletions.
31 changes: 21 additions & 10 deletions arch/powerpc/platforms/pseries/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,18 +354,30 @@ static int alloc_dispatch_log_kmem_cache(void)
}
early_initcall(alloc_dispatch_log_kmem_cache);

static void pSeries_idle(void)
static void pseries_lpar_idle(void)
{
/* This would call on the cpuidle framework, and the back-end pseries
* driver to go to idle states
*/
if (cpuidle_idle_call()) {
/* On error, execute default handler
* to go into low thread priority and possibly
* low power mode.
* low power mode by cedeing processor to hypervisor
*/
HMT_low();
HMT_very_low();

/* Indicate to hypervisor that we are idle. */
get_lppaca()->idle = 1;

/*
* Yield the processor to the hypervisor. We return if
* an external interrupt occurs (which are driven prior
* to returning here) or if a prod occurs from another
* processor. When returning here, external interrupts
* are enabled.
*/
cede_processor();

get_lppaca()->idle = 0;
}
}

Expand Down Expand Up @@ -456,15 +468,14 @@ static void __init pSeries_setup_arch(void)

pSeries_nvram_init();

if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
if (firmware_has_feature(FW_FEATURE_LPAR)) {
vpa_init(boot_cpuid);
ppc_md.power_save = pSeries_idle;
}

if (firmware_has_feature(FW_FEATURE_LPAR))
ppc_md.power_save = pseries_lpar_idle;
ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
else
} else {
/* No special idle routine */
ppc_md.enable_pmcs = power4_enable_pmcs;
}

ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;

Expand Down

0 comments on commit 363edbe

Please sign in to comment.