Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 351196
b: refs/heads/master
c: d329de3
h: refs/heads/master
v: v3
  • Loading branch information
Marc Zyngier authored and Catalin Marinas committed Jan 29, 2013
1 parent 467806b commit 40cfc87
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 24 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: 75e424620a4f8247e8877c224d0457efadf88201
refs/heads/master: d329de3f2ada413c7cd16e1dc1d70d4abc7309e9
10 changes: 10 additions & 0 deletions trunk/arch/arm64/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,14 @@ extern volatile unsigned long secondary_holding_pen_release;
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);

struct device_node;

struct smp_enable_ops {
const char *name;
int (*init_cpu)(struct device_node *, int);
int (*prepare_cpu)(int);
};

extern const struct smp_enable_ops smp_spin_table_ops;

#endif /* ifndef __ASM_SMP_H */
2 changes: 1 addition & 1 deletion trunk/arch/arm64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
sys_compat.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
arm64-obj-$(CONFIG_SMP) += smp.o
arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o
arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
Expand Down
68 changes: 46 additions & 22 deletions trunk/arch/arm64/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,27 @@ void __init smp_prepare_boot_cpu(void)
}

static void (*smp_cross_call)(const struct cpumask *, unsigned int);
static phys_addr_t cpu_release_addr[NR_CPUS];

static const struct smp_enable_ops *enable_ops[] __initconst = {
&smp_spin_table_ops,
NULL,
};

static const struct smp_enable_ops *smp_enable_ops[NR_CPUS];

static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
{
const struct smp_enable_ops *ops = enable_ops[0];

while (ops) {
if (!strcmp(name, ops->name))
return ops;

ops++;
}

return NULL;
}

/*
* Enumerate the possible CPU set from the device tree.
Expand All @@ -252,22 +272,22 @@ void __init smp_init_cpus(void)
* We currently support only the "spin-table" enable-method.
*/
enable_method = of_get_property(dn, "enable-method", NULL);
if (!enable_method || strcmp(enable_method, "spin-table")) {
pr_err("CPU %d: missing or invalid enable-method property: %s\n",
cpu, enable_method);
if (!enable_method) {
pr_err("CPU %d: missing enable-method property\n", cpu);
goto next;
}

/*
* Determine the address from which the CPU is polling.
*/
if (of_property_read_u64(dn, "cpu-release-addr",
&cpu_release_addr[cpu])) {
pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
cpu);
smp_enable_ops[cpu] = smp_get_enable_ops(enable_method);

if (!smp_enable_ops[cpu]) {
pr_err("CPU %d: invalid enable-method property: %s\n",
cpu, enable_method);
goto next;
}

if (smp_enable_ops[cpu]->init_cpu(dn, cpu))
goto next;

set_cpu_possible(cpu, true);
next:
cpu++;
Expand All @@ -281,8 +301,7 @@ void __init smp_init_cpus(void)

void __init smp_prepare_cpus(unsigned int max_cpus)
{
int cpu;
void **release_addr;
int cpu, err;
unsigned int ncores = num_possible_cpus();

/*
Expand All @@ -291,30 +310,35 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
if (max_cpus > ncores)
max_cpus = ncores;

/* Don't bother if we're effectively UP */
if (max_cpus <= 1)
return;

/*
* Initialise the present map (which describes the set of CPUs
* actually populated at the present time) and release the
* secondaries from the bootloader.
*
* Make sure we online at most (max_cpus - 1) additional CPUs.
*/
max_cpus--;
for_each_possible_cpu(cpu) {
if (max_cpus == 0)
break;

if (!cpu_release_addr[cpu])
if (cpu == smp_processor_id())
continue;

if (!smp_enable_ops[cpu])
continue;

release_addr = __va(cpu_release_addr[cpu]);
release_addr[0] = (void *)__pa(secondary_holding_pen);
__flush_dcache_area(release_addr, sizeof(release_addr[0]));
err = smp_enable_ops[cpu]->prepare_cpu(cpu);
if (err)
continue;

set_cpu_present(cpu, true);
max_cpus--;
}

/*
* Send an event to wake up the secondaries.
*/
sev();
}


Expand Down
66 changes: 66 additions & 0 deletions trunk/arch/arm64/kernel/smp_spin_table.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Spin Table SMP initialisation
*
* Copyright (C) 2013 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <linux/init.h>
#include <linux/of.h>
#include <linux/smp.h>

#include <asm/cacheflush.h>

static phys_addr_t cpu_release_addr[NR_CPUS];

static int __init smp_spin_table_init_cpu(struct device_node *dn, int cpu)
{
/*
* Determine the address from which the CPU is polling.
*/
if (of_property_read_u64(dn, "cpu-release-addr",
&cpu_release_addr[cpu])) {
pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
cpu);

return -1;
}

return 0;
}

static int __init smp_spin_table_prepare_cpu(int cpu)
{
void **release_addr;

if (!cpu_release_addr[cpu])
return -ENODEV;

release_addr = __va(cpu_release_addr[cpu]);
release_addr[0] = (void *)__pa(secondary_holding_pen);
__flush_dcache_area(release_addr, sizeof(release_addr[0]));

/*
* Send an event to wake up the secondary CPU.
*/
sev();

return 0;
}

const struct smp_enable_ops smp_spin_table_ops __initconst = {
.name = "spin-table",
.init_cpu = smp_spin_table_init_cpu,
.prepare_cpu = smp_spin_table_prepare_cpu,
};

0 comments on commit 40cfc87

Please sign in to comment.