Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 274181
b: refs/heads/master
c: 344eb01
h: refs/heads/master
i:
  274179: 5d56e85
v: v3
  • Loading branch information
Benjamin Herrenschmidt committed Sep 20, 2011
1 parent e5340d3 commit 12fe9ca
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 78b782cb788cadbda151ecb61753c109602a250c
refs/heads/master: 344eb010b2e399069bac474a9fd0ba04908a2601
2 changes: 1 addition & 1 deletion trunk/arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ config SWIOTLB

config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
---help---
Say Y here to be able to disable and re-enable individual
CPUs at runtime on SMP machines.
Expand Down
78 changes: 77 additions & 1 deletion trunk/arch/powerpc/platforms/powernv/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@

#include "powernv.h"

static void __devinit pnv_smp_setup_cpu(int cpu)
#ifdef DEBUG
#include <asm/udbg.h>
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif

static void __cpuinit pnv_smp_setup_cpu(int cpu)
{
if (cpu != boot_cpuid)
xics_setup_cpu();
Expand All @@ -55,13 +62,78 @@ static int pnv_smp_cpu_bootable(unsigned int nr)
return 1;
}

#ifdef CONFIG_HOTPLUG_CPU

static int pnv_smp_cpu_disable(void)
{
int cpu = smp_processor_id();

/* This is identical to pSeries... might consolidate by
* moving migrate_irqs_away to a ppc_md with default to
* the generic fixup_irqs. --BenH.
*/
set_cpu_online(cpu, false);
vdso_data->processorCount--;
if (cpu == boot_cpuid)
boot_cpuid = cpumask_any(cpu_online_mask);
xics_migrate_irqs_away();
return 0;
}

static void pnv_smp_cpu_kill_self(void)
{
unsigned int cpu;

/* If powersave_nap is enabled, use NAP mode, else just
* spin aimlessly
*/
if (!powersave_nap) {
generic_mach_cpu_die();
return;
}

/* Standard hot unplug procedure */
local_irq_disable();
idle_task_exit();
current->active_mm = NULL; /* for sanity */
cpu = smp_processor_id();
DBG("CPU%d offline\n", cpu);
generic_set_cpu_dead(cpu);
smp_wmb();

/* We don't want to take decrementer interrupts while we are offline,
* so clear LPCR:PECE1. We keep PECE2 enabled.
*/
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
while (!generic_check_cpu_restart(cpu)) {
power7_idle();
if (!generic_check_cpu_restart(cpu)) {
DBG("CPU%d Unexpected exit while offline !\n", cpu);
/* We may be getting an IPI, so we re-enable
* interrupts to process it, it will be ignored
* since we aren't online (hopefully)
*/
local_irq_enable();
local_irq_disable();
}
}
mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
DBG("CPU%d coming online...\n", cpu);
}

#endif /* CONFIG_HOTPLUG_CPU */

static struct smp_ops_t pnv_smp_ops = {
.message_pass = smp_muxed_ipi_message_pass,
.cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
.probe = xics_smp_probe,
.kick_cpu = smp_generic_kick_cpu,
.setup_cpu = pnv_smp_setup_cpu,
.cpu_bootable = pnv_smp_cpu_bootable,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_disable = pnv_smp_cpu_disable,
.cpu_die = generic_cpu_die,
#endif /* CONFIG_HOTPLUG_CPU */
};

/* This is called very early during platform setup_arch */
Expand All @@ -80,4 +152,8 @@ void __init pnv_smp_init(void)
smp_ops->take_timebase = rtas_take_timebase;
}
#endif /* CONFIG_PPC_RTAS */

#ifdef CONFIG_HOTPLUG_CPU
ppc_md.cpu_die = pnv_smp_cpu_kill_self;
#endif
}

0 comments on commit 12fe9ca

Please sign in to comment.