Skip to content

Commit

Permalink
MIPS: Add arch generic CPU hotplug
Browse files Browse the repository at this point in the history
Each platform has to add support for CPU hotplugging itself by providing
suitable definitions for the cpu_disable and cpu_die of the smp_ops
methods and setting SYS_SUPPORTS_HOTPLUG_CPU.  A platform should only set
SYS_SUPPORTS_HOTPLUG_CPU once all it's smp_ops definitions have the
necessary changes.  This patch contains the changes to the dummy smp_ops
definition for uni-processor systems.

Parts of the code contributed by Cavium Inc.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Ralf Baechle committed Jun 24, 2009
1 parent 4ac4aa5 commit 1b2bc75
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 7 deletions.
11 changes: 10 additions & 1 deletion arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -784,8 +784,17 @@ config SYS_HAS_EARLY_PRINTK
bool

config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs"
depends on SMP && HOTPLUG && SYS_SUPPORTS_HOTPLUG_CPU
help
Say Y here to allow turning CPUs off and on. CPUs can be
controlled through /sys/devices/system/cpu.
(Note: power management support will enable this option
automatically on SMP systems. )
Say N if you want to disable CPU hotplug.

config SYS_SUPPORTS_HOTPLUG_CPU
bool
default n

config I8259
bool
Expand Down
4 changes: 4 additions & 0 deletions arch/mips/include/asm/smp-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ struct plat_smp_ops {
void (*boot_secondary)(int cpu, struct task_struct *idle);
void (*smp_setup)(void);
void (*prepare_cpus)(unsigned int max_cpus);
#ifdef CONFIG_HOTPLUG_CPU
int (*cpu_disable)(void);
void (*cpu_die)(unsigned int cpu);
#endif
};

extern void register_smp_ops(struct plat_smp_ops *ops);
Expand Down
19 changes: 19 additions & 0 deletions arch/mips/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extern int __cpu_logical_map[NR_CPUS];
/* Octeon - Tell another core to flush its icache */
#define SMP_ICACHE_FLUSH 0x4

extern cpumask_t cpu_callin_map;

extern void asmlinkage smp_bootstrap(void);

Expand All @@ -56,6 +57,24 @@ static inline void smp_send_reschedule(int cpu)
mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF);
}

#ifdef CONFIG_HOTPLUG_CPU
static inline int __cpu_disable(void)
{
extern struct plat_smp_ops *mp_ops; /* private */

return mp_ops->cpu_disable();
}

static inline void __cpu_die(unsigned int cpu)
{
extern struct plat_smp_ops *mp_ops; /* private */

mp_ops->cpu_die(cpu);
}

extern void play_dead(void);
#endif

extern asmlinkage void smp_call_function_interrupt(void);

extern void arch_send_call_function_single_ipi(int cpu);
Expand Down
13 changes: 12 additions & 1 deletion arch/mips/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,15 @@
*/
void __noreturn cpu_idle(void)
{
int cpu;

/* CPU is going idle. */
cpu = smp_processor_id();

/* endless idle loop with no priority at all */
while (1) {
tick_nohz_stop_sched_tick(1);
while (!need_resched()) {
while (!need_resched() && cpu_online(cpu)) {
#ifdef CONFIG_MIPS_MT_SMTC
extern void smtc_idle_loop_hook(void);

Expand All @@ -62,6 +67,12 @@ void __noreturn cpu_idle(void)
if (cpu_wait)
(*cpu_wait)();
}
#ifdef CONFIG_HOTPLUG_CPU
if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) &&
(system_state == SYSTEM_RUNNING ||
system_state == SYSTEM_BOOTING))
play_dead();
#endif
tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
Expand Down
16 changes: 16 additions & 0 deletions arch/mips/kernel/smp-up.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ static void __init up_prepare_cpus(unsigned int max_cpus)
{
}

#ifdef CONFIG_HOTPLUG_CPU
static int up_cpu_disable(void)
{
return -ENOSYS;
}

static void up_cpu_die(unsigned int cpu)
{
BUG();
}
#endif

struct plat_smp_ops up_smp_ops = {
.send_ipi_single = up_send_ipi_single,
.send_ipi_mask = up_send_ipi_mask,
Expand All @@ -64,4 +76,8 @@ struct plat_smp_ops up_smp_ops = {
.boot_secondary = up_boot_secondary,
.smp_setup = up_smp_setup,
.prepare_cpus = up_prepare_cpus,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_disable = up_cpu_disable,
.cpu_die = up_cpu_die,
#endif
};
17 changes: 13 additions & 4 deletions arch/mips/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#include <asm/mipsmtregs.h>
#endif /* CONFIG_MIPS_MT_SMTC */

static volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */

Expand Down Expand Up @@ -201,6 +201,8 @@ void __devinit smp_prepare_boot_cpu(void)
* and keep control until "cpu_online(cpu)" is set. Note: cpu is
* physical, not logical.
*/
static struct task_struct *cpu_idle_thread[NR_CPUS];

int __cpuinit __cpu_up(unsigned int cpu)
{
struct task_struct *idle;
Expand All @@ -210,9 +212,16 @@ int __cpuinit __cpu_up(unsigned int cpu)
* The following code is purely to make sure
* Linux can schedule processes on this slave.
*/
idle = fork_idle(cpu);
if (IS_ERR(idle))
panic(KERN_ERR "Fork failed for CPU %d", cpu);
if (!cpu_idle_thread[cpu]) {
idle = fork_idle(cpu);
cpu_idle_thread[cpu] = idle;

if (IS_ERR(idle))
panic(KERN_ERR "Fork failed for CPU %d", cpu);
} else {
idle = cpu_idle_thread[cpu];
init_idle(idle, cpu);
}

mp_ops->boot_secondary(cpu, idle);

Expand Down
5 changes: 4 additions & 1 deletion arch/mips/kernel/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ static int __init topology_init(void)
#endif /* CONFIG_NUMA */

for_each_present_cpu(i) {
ret = register_cpu(&per_cpu(cpu_devices, i), i);
struct cpu *c = &per_cpu(cpu_devices, i);

c->hotpluggable = 1;
ret = register_cpu(c, i);
if (ret)
printk(KERN_WARNING "topology_init: register_cpu %d "
"failed (%d)\n", i, ret);
Expand Down

0 comments on commit 1b2bc75

Please sign in to comment.