diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/bios32.c | 5 | ||||
-rw-r--r-- | arch/arm/kernel/devtree.c | 5 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 3 | ||||
-rw-r--r-- | arch/arm/kernel/fiq.c | 9 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 21 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 10 | ||||
-rw-r--r-- | arch/arm/kernel/topology.c | 61 |
9 files changed, 66 insertions, 60 deletions
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 261fcc82616..88e14d74b6d 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -525,11 +525,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw) * Assign resources. */ pci_bus_assign_resources(bus); - - /* - * Enable bridges - */ - pci_enable_bridges(bus); } /* diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c index 5859c8bc727..2ee8a17d2b0 100644 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@ -169,6 +169,11 @@ void __init arm_dt_init_cpu_maps(void) } } +bool arch_match_cpu_phys_id(int cpu, u64 phys_id) +{ + return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu); +} + /** * setup_machine_fdt - Machine setup when an dtb was passed to the kernel * @dt_phys: physical address of dt blob diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index d40d0ef389d..9cbe70c8b0e 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -357,7 +357,8 @@ ENDPROC(__pabt_svc) .endm .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) +#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \ + !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) #ifndef CONFIG_MMU #warning "NPTL on non MMU needs fixing" #else diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 25442f45114..918875d96d5 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -84,17 +84,14 @@ int show_fiq_list(struct seq_file *p, int prec) void set_fiq_handler(void *start, unsigned int length) { -#if defined(CONFIG_CPU_USE_DOMAINS) - void *base = (void *)0xffff0000; -#else void *base = vectors_page; -#endif unsigned offset = FIQ_OFFSET; memcpy(base + offset, start, length); + if (!cache_is_vipt_nonaliasing()) + flush_icache_range((unsigned long)base + offset, offset + + length); flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length); - if (!vectors_high()) - flush_icache_range(offset, offset + length); } int claim_fiq(struct fiq_handler *f) diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 4fb074c446b..57221e349a7 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -15,6 +15,7 @@ #include <asm/mmu_context.h> #include <asm/cacheflush.h> #include <asm/mach-types.h> +#include <asm/smp_plat.h> #include <asm/system_misc.h> extern const unsigned char relocate_new_kernel[]; @@ -39,6 +40,14 @@ int machine_kexec_prepare(struct kimage *image) int i, err; /* + * Validate that if the current HW supports SMP, then the SW supports + * and implements CPU hotplug for the current HW. If not, we won't be + * able to kexec reliably, so fail the prepare operation. + */ + if (num_possible_cpus() > 1 && !platform_can_cpu_hotplug()) + return -EINVAL; + + /* * No segment at default ATAGs address. try to locate * a dtb using magic. */ @@ -73,6 +82,7 @@ void machine_crash_nonpanic_core(void *unused) crash_save_cpu(®s, smp_processor_id()); flush_cache_all(); + set_cpu_online(smp_processor_id(), false); atomic_dec(&waiting_for_crash_ipi); while (1) cpu_relax(); @@ -134,10 +144,13 @@ void machine_kexec(struct kimage *image) unsigned long reboot_code_buffer_phys; void *reboot_code_buffer; - if (num_online_cpus() > 1) { - pr_err("kexec: error: multiple CPUs still online\n"); - return; - } + /* + * This can only happen if machine_shutdown() failed to disable some + * CPU, and that can only happen if the checks in + * machine_kexec_prepare() were not correct. If this fails, we can't + * reliably kexec anyway, so BUG_ON is appropriate. + */ + BUG_ON(num_online_cpus() > 1); page_list = image->head & PAGE_MASK; diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index d9f5cd4e533..e186ee1e63f 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -53,7 +53,12 @@ armpmu_map_cache_event(const unsigned (*cache_map) static int armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) { - int mapping = (*event_map)[config]; + int mapping; + + if (config >= PERF_COUNT_HW_MAX) + return -EINVAL; + + mapping = (*event_map)[config]; return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; } @@ -253,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events, struct arm_pmu *armpmu = to_arm_pmu(event->pmu); struct pmu *leader_pmu = event->group_leader->pmu; + if (is_software_event(event)) + return 1; + if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) return 1; diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 536c85fe72a..94f6b05f9e2 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -462,7 +462,7 @@ int in_gate_area_no_mm(unsigned long addr) { return in_gate_area(NULL, addr); } -#define is_gate_vma(vma) ((vma) = &gate_vma) +#define is_gate_vma(vma) ((vma) == &gate_vma) #else #define is_gate_vma(vma) 0 #endif diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index c2b4f8f0be9..2dc19349eb1 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -145,6 +145,16 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle) return -ENOSYS; } +int platform_can_cpu_hotplug(void) +{ +#ifdef CONFIG_HOTPLUG_CPU + if (smp_ops.cpu_kill) + return 1; +#endif + + return 0; +} + #ifdef CONFIG_HOTPLUG_CPU static void percpu_timer_stop(void); diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index c5a59546a25..85a87370f14 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -74,12 +74,8 @@ struct cpu_efficiency table_efficiency[] = { {NULL, }, }; -struct cpu_capacity { - unsigned long hwid; - unsigned long capacity; -}; - -struct cpu_capacity *cpu_capacity; +unsigned long *__cpu_capacity; +#define cpu_capacity(cpu) __cpu_capacity[cpu] unsigned long middle_capacity = 1; @@ -100,15 +96,19 @@ static void __init parse_dt_topology(void) unsigned long capacity = 0; int alloc_size, cpu = 0; - alloc_size = nr_cpu_ids * sizeof(struct cpu_capacity); - cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT); + alloc_size = nr_cpu_ids * sizeof(*__cpu_capacity); + __cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT); - while ((cn = of_find_node_by_type(cn, "cpu"))) { - const u32 *rate, *reg; + for_each_possible_cpu(cpu) { + const u32 *rate; int len; - if (cpu >= num_possible_cpus()) - break; + /* too early to use cpu->of_node */ + cn = of_get_cpu_node(cpu, NULL); + if (!cn) { + pr_err("missing device node for CPU %d\n", cpu); + continue; + } for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++) if (of_device_is_compatible(cn, cpu_eff->compatible)) @@ -124,12 +124,6 @@ static void __init parse_dt_topology(void) continue; } - reg = of_get_property(cn, "reg", &len); - if (!reg || len != 4) { - pr_err("%s missing reg property\n", cn->full_name); - continue; - } - capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; /* Save min capacity of the system */ @@ -140,13 +134,9 @@ static void __init parse_dt_topology(void) if (capacity > max_capacity) max_capacity = capacity; - cpu_capacity[cpu].capacity = capacity; - cpu_capacity[cpu++].hwid = be32_to_cpup(reg); + cpu_capacity(cpu) = capacity; } - if (cpu < num_possible_cpus()) - cpu_capacity[cpu].hwid = (unsigned long)(-1); - /* If min and max capacities are equals, we bypass the update of the * cpu_scale because all CPUs have the same capacity. Otherwise, we * compute a middle_capacity factor that will ensure that the capacity @@ -154,9 +144,7 @@ static void __init parse_dt_topology(void) * SCHED_POWER_SCALE, which is the default value, but with the * constraint explained near table_efficiency[]. */ - if (min_capacity == max_capacity) - cpu_capacity[0].hwid = (unsigned long)(-1); - else if (4*max_capacity < (3*(max_capacity + min_capacity))) + if (4*max_capacity < (3*(max_capacity + min_capacity))) middle_capacity = (min_capacity + max_capacity) >> (SCHED_POWER_SHIFT+1); else @@ -170,23 +158,12 @@ static void __init parse_dt_topology(void) * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the * function returns directly for SMP system. */ -void update_cpu_power(unsigned int cpu, unsigned long hwid) +void update_cpu_power(unsigned int cpu) { - unsigned int idx = 0; - - /* look for the cpu's hwid in the cpu capacity table */ - for (idx = 0; idx < num_possible_cpus(); idx++) { - if (cpu_capacity[idx].hwid == hwid) - break; - - if (cpu_capacity[idx].hwid == -1) - return; - } - - if (idx == num_possible_cpus()) + if (!cpu_capacity(cpu)) return; - set_power_scale(cpu, cpu_capacity[idx].capacity / middle_capacity); + set_power_scale(cpu, cpu_capacity(cpu) / middle_capacity); printk(KERN_INFO "CPU%u: update cpu_power %lu\n", cpu, arch_scale_freq_power(NULL, cpu)); @@ -194,7 +171,7 @@ void update_cpu_power(unsigned int cpu, unsigned long hwid) #else static inline void parse_dt_topology(void) {} -static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {} +static inline void update_cpu_power(unsigned int cpuid) {} #endif /* @@ -281,7 +258,7 @@ void store_cpu_topology(unsigned int cpuid) update_siblings_masks(cpuid); - update_cpu_power(cpuid, mpidr & MPIDR_HWID_BITMASK); + update_cpu_power(cpuid); printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", cpuid, cpu_topology[cpuid].thread_id, |