Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 188469
b: refs/heads/master
c: 0b39db2
h: refs/heads/master
i:
  188467: 7250141
v: v3
  • Loading branch information
Graf Yang authored and Mike Frysinger committed Mar 9, 2010
1 parent 4f3143c commit b15d142
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 14 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: 0d152c27e336b5fd777da7dd3e814617e7305afd
refs/heads/master: 0b39db28b953945232719e7ff6fb802aa8a2be5f
6 changes: 5 additions & 1 deletion trunk/arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ config NR_CPUS
depends on SMP
default 2 if BF561

config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs"
depends on SMP && HOTPLUG
default y

config IRQ_PER_CPU
bool
depends on SMP
Expand Down Expand Up @@ -1130,7 +1135,6 @@ source "fs/Kconfig.binfmt"
endmenu

menu "Power management options"
depends on !SMP

source "kernel/power/Kconfig"

Expand Down
7 changes: 7 additions & 0 deletions trunk/arch/blackfin/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,12 @@ struct corelock_slot {

void smp_icache_flush_range_others(unsigned long start,
unsigned long end);
#ifdef CONFIG_HOTPLUG_CPU
void coreb_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
void cpu_die(void);
void platform_cpu_die(void);
int __cpu_disable(void);
int __cpu_die(unsigned int cpu);
#endif

#endif /* !__ASM_BLACKFIN_SMP_H */
1 change: 1 addition & 0 deletions trunk/arch/blackfin/mach-bf561/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ obj-y := ints-priority.o dma.o

obj-$(CONFIG_BF561_COREB) += coreb.o
obj-$(CONFIG_SMP) += smp.o secondary.o atomic.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
32 changes: 32 additions & 0 deletions trunk/arch/blackfin/mach-bf561/hotplug.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2007-2009 Analog Devices Inc.
* Graff Yang <graf.yang@analog.com>
*
* Licensed under the GPL-2 or later.
*/

#include <asm/blackfin.h>
#include <asm/smp.h>
#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))

int hotplug_coreb;

void platform_cpu_die(void)
{
unsigned long iwr[2] = {0, 0};
unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32;
unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32);

hotplug_coreb = 1;

iwr[bank] = bit;

/* disable core timer */
bfin_write_TCNTL(0);

/* clear ipi interrupt IRQ_SUPPLE_0 */
bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1)));
SSYNC();

coreb_sleep(iwr[0], iwr[1], 0);
}
50 changes: 48 additions & 2 deletions trunk/arch/blackfin/mach-bf561/secondary.S
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/init.h>
#include <asm/blackfin.h>
#include <asm/asm-offsets.h>
#include <asm/trace.h>

__INIT

Expand Down Expand Up @@ -62,6 +63,8 @@ ENTRY(_coreb_trampoline_start)
M2 = r0;
M3 = r0;

trace_buffer_init(p0,r0);

/* Turn off the icache */
p0.l = LO(IMEM_CONTROL);
p0.h = HI(IMEM_CONTROL);
Expand Down Expand Up @@ -159,6 +162,41 @@ ENTRY(_coreb_trampoline_start)
ENDPROC(_coreb_trampoline_start)
ENTRY(_coreb_trampoline_end)

.section ".text"
ENTRY(_set_sicb_iwr)
P0.H = hi(SICB_IWR0);
P0.L = lo(SICB_IWR0);
P1.H = hi(SICB_IWR1);
P1.L = lo(SICB_IWR1);
[P0] = R0;
[P1] = R1;
SSYNC;
RTS;
ENDPROC(_set_sicb_iwr)

ENTRY(_coreb_sleep)
sp.l = lo(INITIAL_STACK);
sp.h = hi(INITIAL_STACK);
fp = sp;
usp = sp;

call _set_sicb_iwr;

CLI R2;
SSYNC;
IDLE;
STI R2;

R0 = IWR_DISABLE_ALL;
R1 = IWR_DISABLE_ALL;
call _set_sicb_iwr;

p0.h = hi(COREB_L1_CODE_START);
p0.l = lo(COREB_L1_CODE_START);
jump (p0);
ENDPROC(_coreb_sleep)

__CPUINIT
ENTRY(_coreb_start)
[--sp] = reti;

Expand All @@ -176,12 +214,20 @@ ENTRY(_coreb_start)
sp = [p0];
usp = sp;
fp = sp;
#ifdef CONFIG_HOTPLUG_CPU
p0.l = _hotplug_coreb;
p0.h = _hotplug_coreb;
r0 = [p0];
cc = BITTST(r0, 0);
if cc jump 3f;
#endif
sp += -12;
call _init_pda
sp += 12;
#ifdef CONFIG_HOTPLUG_CPU
3:
#endif
call _secondary_start_kernel;
.L_exit:
jump.s .L_exit;
ENDPROC(_coreb_start)

__FINIT
17 changes: 10 additions & 7 deletions trunk/arch/blackfin/mach-bf561/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
bfin_write_SICB_IAR5(bfin_read_SICA_IAR5());
bfin_write_SICB_IAR6(bfin_read_SICA_IAR6());
bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
bfin_write_SICB_IWR0(IWR_DISABLE_ALL);
bfin_write_SICB_IWR1(IWR_DISABLE_ALL);
SSYNC();

/* Store CPU-private information to the cpu_data array. */
Expand All @@ -80,17 +82,18 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle
{
unsigned long timeout;

/* CoreB already running?! */
BUG_ON((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0);

printk(KERN_INFO "Booting Core B.\n");

spin_lock(&boot_lock);

/* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
SSYNC();
bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
SSYNC();
if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0) {
/* CoreB already running, sending ipi to wakeup it */
platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
} else {
/* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
SSYNC();
}

timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
Expand Down
38 changes: 35 additions & 3 deletions trunk/arch/blackfin/mach-common/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,11 @@ void smp_send_stop(void)

int __cpuinit __cpu_up(unsigned int cpu)
{
struct task_struct *idle;
int ret;
static struct task_struct *idle;

if (idle)
free_task(idle);

idle = fork_idle(cpu);
if (IS_ERR(idle)) {
Expand All @@ -354,7 +357,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
}

secondary_stack = task_stack_page(idle) + THREAD_SIZE;
smp_wmb();

ret = platform_boot_secondary(cpu, idle);

Expand Down Expand Up @@ -413,7 +415,6 @@ void __cpuinit secondary_start_kernel(void)
atomic_inc(&mm->mm_users);
atomic_inc(&mm->mm_count);
current->active_mm = mm;
BUG_ON(current->mm); /* Can't be, but better be safe than sorry. */

preempt_disable();

Expand Down Expand Up @@ -495,3 +496,34 @@ void resync_core_dcache(void)
}
EXPORT_SYMBOL(resync_core_dcache);
#endif

#ifdef CONFIG_HOTPLUG_CPU
int __cpuexit __cpu_disable(void)
{
unsigned int cpu = smp_processor_id();

if (cpu == 0)
return -EPERM;

set_cpu_online(cpu, false);
return 0;
}

static DECLARE_COMPLETION(cpu_killed);

int __cpuexit __cpu_die(unsigned int cpu)
{
return wait_for_completion_timeout(&cpu_killed, 5000);
}

void cpu_die(void)
{
complete(&cpu_killed);

atomic_dec(&init_mm.mm_users);
atomic_dec(&init_mm.mm_count);

local_irq_disable();
platform_cpu_die();
}
#endif

0 comments on commit b15d142

Please sign in to comment.