summaryrefslogtreecommitdiff
path: root/arch/arc/kernel
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /arch/arc/kernel
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r--arch/arc/kernel/Makefile1
-rw-r--r--arch/arc/kernel/ctx_sw.c13
-rw-r--r--arch/arc/kernel/ctx_sw_asm.S11
-rw-r--r--arch/arc/kernel/devtree.c97
-rw-r--r--arch/arc/kernel/entry.S24
-rw-r--r--arch/arc/kernel/head.S2
-rw-r--r--arch/arc/kernel/irq.c12
-rw-r--r--arch/arc/kernel/kgdb.c12
-rw-r--r--arch/arc/kernel/kprobes.c8
-rw-r--r--arch/arc/kernel/perf_event.c326
-rw-r--r--arch/arc/kernel/reset.c1
-rw-r--r--arch/arc/kernel/setup.c17
-rw-r--r--arch/arc/kernel/smp.c10
-rw-r--r--arch/arc/kernel/stacktrace.c5
-rw-r--r--arch/arc/kernel/time.c11
-rw-r--r--arch/arc/kernel/traps.c3
16 files changed, 123 insertions, 430 deletions
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index 8004b4f..c242ef0 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o
-obj-$(CONFIG_PERF_EVENTS) += perf_event.o
obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o
CFLAGS_fpu.o += -mdpfp
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c
index c14a5be..34410eb 100644
--- a/arch/arc/kernel/ctx_sw.c
+++ b/arch/arc/kernel/ctx_sw.c
@@ -17,8 +17,6 @@
#include <asm/asm-offsets.h>
#include <linux/sched.h>
-#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4)
-
struct task_struct *__sched
__switch_to(struct task_struct *prev_task, struct task_struct *next_task)
{
@@ -47,16 +45,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
#endif
/* set ksp of outgoing task in tsk->thread.ksp */
-#if KSP_WORD_OFF <= 255
"st.as sp, [%3, %1] \n\t"
-#else
- /*
- * Workaround for NR_CPUS=4k
- * %1 is bigger than 255 (S9 offset for st.as)
- */
- "add2 r24, %3, %1 \n\t"
- "st sp, [r24] \n\t"
-#endif
"sync \n\t"
@@ -108,7 +97,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
/* FP/BLINK restore generated by gcc (standard func epilogue */
: "=r"(tmp)
- : "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
+ : "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev)
: "blink"
);
diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S
index 65690e7..d897234 100644
--- a/arch/arc/kernel/ctx_sw_asm.S
+++ b/arch/arc/kernel/ctx_sw_asm.S
@@ -14,8 +14,6 @@
#include <asm/asm-offsets.h>
#include <asm/linkage.h>
-#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4)
-
;################### Low Level Context Switch ##########################
.section .sched.text,"ax",@progbits
@@ -30,13 +28,8 @@ __switch_to:
SAVE_CALLEE_SAVED_KERNEL
/* Save the now KSP in task->thread.ksp */
-#if KSP_WORD_OFF <= 255
- st.as sp, [r0, KSP_WORD_OFF]
-#else
- /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */
- add2 r24, r0, KSP_WORD_OFF
- st sp, [r24]
-#endif
+ st.as sp, [r0, (TASK_THREAD + THREAD_KSP)/4]
+
/*
* Return last task in r0 (return reg)
* On ARC, Return reg = First Arg reg = r0.
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index b6dc4e2..2340af0 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -14,22 +14,10 @@
#include <linux/memblock.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
+#include <asm/prom.h>
#include <asm/clk.h>
#include <asm/mach_desc.h>
-static const void * __init arch_get_next_mach(const char *const **match)
-{
- static const struct machine_desc *mdesc = __arch_info_begin;
- const struct machine_desc *m = mdesc;
-
- if (m >= __arch_info_end)
- return NULL;
-
- mdesc++;
- *match = m->dt_compat;
- return m;
-}
-
/**
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
* @dt: virtual address pointer to dt blob
@@ -37,24 +25,93 @@ static const void * __init arch_get_next_mach(const char *const **match)
* If a dtb was passed to the kernel, then use it to choose the correct
* machine_desc and to setup the system.
*/
-const struct machine_desc * __init setup_machine_fdt(void *dt)
+struct machine_desc * __init setup_machine_fdt(void *dt)
{
- const struct machine_desc *mdesc;
+ struct boot_param_header *devtree = dt;
+ struct machine_desc *mdesc = NULL, *mdesc_best = NULL;
+ unsigned int score, mdesc_score = ~1;
unsigned long dt_root;
+ const char *model, *compat;
void *clk;
+ char manufacturer[16];
unsigned long len;
- if (!early_init_dt_scan(dt))
+ /* check device tree validity */
+ if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
return NULL;
- mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
- if (!mdesc)
+ initial_boot_params = devtree;
+ dt_root = of_get_flat_dt_root();
+
+ /*
+ * The kernel could be multi-platform enabled, thus could have many
+ * "baked-in" machine descriptors. Search thru all for the best
+ * "compatible" string match.
+ */
+ for_each_machine_desc(mdesc) {
+ score = of_flat_dt_match(dt_root, mdesc->dt_compat);
+ if (score > 0 && score < mdesc_score) {
+ mdesc_best = mdesc;
+ mdesc_score = score;
+ }
+ }
+ if (!mdesc_best) {
+ const char *prop;
+ long size;
+
+ pr_err("\n unrecognized device tree list:\n[ ");
+
+ prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
+ if (prop) {
+ while (size > 0) {
+ printk("'%s' ", prop);
+ size -= strlen(prop) + 1;
+ prop += strlen(prop) + 1;
+ }
+ }
+ printk("]\n\n");
+
machine_halt();
+ }
+
+ /* compat = "<manufacturer>,<model>" */
+ compat = mdesc_best->dt_compat[0];
+
+ model = strchr(compat, ',');
+ if (model)
+ model++;
+
+ strlcpy(manufacturer, compat, model ? model - compat : strlen(compat));
+
+ pr_info("Board \"%s\" from %s (Manufacturer)\n", model, manufacturer);
+
+ /* Retrieve various information from the /chosen node */
+ of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
+
+ /* Initialize {size,address}-cells info */
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
+ /* Setup memory, calling early_init_dt_add_memory_arch */
+ of_scan_flat_dt(early_init_dt_scan_memory, NULL);
- dt_root = of_get_flat_dt_root();
clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len);
if (clk)
arc_set_core_freq(of_read_ulong(clk, len/4));
- return mdesc;
+ return mdesc_best;
+}
+
+/*
+ * Copy the flattened DT out of .init since unflattening doesn't copy strings
+ * and the normal DT APIs refs them from orig flat DT
+ */
+void __init copy_devtree(void)
+{
+ void *alloc = early_init_dt_alloc_memory_arch(
+ be32_to_cpu(initial_boot_params->totalsize), 64);
+ if (alloc) {
+ memcpy(alloc, initial_boot_params,
+ be32_to_cpu(initial_boot_params->totalsize));
+ initial_boot_params = alloc;
+ }
}
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 47d09d0..b908dde 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -250,14 +250,6 @@ ARC_ENTRY handle_interrupt_level1
lr r0, [icause1]
and r0, r0, 0x1f
-#ifdef CONFIG_TRACE_IRQFLAGS
- ; icause1 needs to be read early, before calling tracing, which
- ; can clobber scratch regs, hence use of stack to stash it
- push r0
- TRACE_ASM_IRQ_DISABLE
- pop r0
-#endif
-
bl.d @arch_do_IRQ
mov r1, sp
@@ -345,9 +337,9 @@ ARC_ENTRY EV_TLBProtV
; vineetg: Mar 6th: Random Seg Fault issue #1
; ecr and efa were not saved in case an Intr sneaks in
; after fake rtie
-
+ ;
lr r2, [ecr]
- lr r0, [efa] ; Faulting Data address
+ lr r1, [efa] ; Faulting Data address
; --------(4) Return from CPU Exception Mode ---------
; Fake a rtie, but rtie to next label
@@ -356,8 +348,6 @@ ARC_ENTRY EV_TLBProtV
FAKE_RET_FROM_EXCPN r9
- mov r1, sp
-
;------ (5) Type of Protection Violation? ----------
;
; ProtV Hardware Exception is triggered for Access Faults of 2 types
@@ -368,12 +358,16 @@ ARC_ENTRY EV_TLBProtV
bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
;========= (6a) Access Violation Processing ========
+ mov r0, sp ; pt_regs
bl do_page_fault
b ret_from_exception
;========== (6b) Non aligned access ============
4:
+ mov r0, r1
+ mov r1, sp ; pt_regs
+#ifdef CONFIG_ARC_MISALIGN_ACCESS
SAVE_CALLEE_SAVED_USER
mov r2, sp ; callee_regs
@@ -382,6 +376,9 @@ ARC_ENTRY EV_TLBProtV
; TBD: optimize - do this only if a callee reg was involved
; either a dst of emulated LD/ST or src with address-writeback
RESTORE_CALLEE_SAVED_USER
+#else
+ bl do_misaligned_error
+#endif
b ret_from_exception
@@ -578,7 +575,6 @@ resume_user_mode_begin:
; --- (Slow Path #2) pending signal ---
mov r0, sp ; pt_regs for arg to do_signal()/do_notify_resume()
- GET_CURR_THR_INFO_FLAGS r9
bbit0 r9, TIF_SIGPENDING, .Lchk_notify_resume
; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs
@@ -644,8 +640,6 @@ resume_kernel_mode:
restore_regs :
- TRACE_ASM_IRQ_ENABLE
-
lr r10, [status32]
; Restore REG File. In case multiple Events outstanding,
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index 2c878e9..0f944f0 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -95,7 +95,7 @@ stext:
;----------------------------------------------------------------
; First lines of code run by secondary before jumping to 'C'
;----------------------------------------------------------------
- .section .text, "ax",@progbits
+ .section .init.text, "ax",@progbits
.type first_lines_of_secondary, @function
.globl first_lines_of_secondary
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index a4b141e..5fc9245 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -39,14 +39,10 @@ void arc_init_IRQ(void)
level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6;
- /*
- * Write to register, even if no LV2 IRQs configured to reset it
- * in case bootloader had mucked with it
- */
- write_aux_reg(AUX_IRQ_LEV, level_mask);
-
- if (level_mask)
+ if (level_mask) {
pr_info("Level-2 interrupts bitset %x\n", level_mask);
+ write_aux_reg(AUX_IRQ_LEV, level_mask);
+ }
}
/*
@@ -150,7 +146,7 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
set_irq_regs(old_regs);
}
-int get_hw_config_num_irq(void)
+int __init get_hw_config_num_irq(void)
{
uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR);
diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c
index a2ff5c5..a7698fb 100644
--- a/arch/arc/kernel/kgdb.c
+++ b/arch/arc/kernel/kgdb.c
@@ -196,18 +196,6 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
instruction_pointer(regs) = ip;
}
-static void kgdb_call_nmi_hook(void *ignored)
-{
- kgdb_nmicallback(raw_smp_processor_id(), NULL);
-}
-
-void kgdb_roundup_cpus(unsigned long flags)
-{
- local_irq_enable();
- smp_call_function(kgdb_call_nmi_hook, NULL, 0);
- local_irq_disable();
-}
-
struct kgdb_arch arch_kgdb_ops = {
/* breakpoint instruction: TRAP_S 0x3 */
#ifdef CONFIG_CPU_BIG_ENDIAN
diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c
index 42b0504..72f9782 100644
--- a/arch/arc/kernel/kprobes.c
+++ b/arch/arc/kernel/kprobes.c
@@ -87,13 +87,13 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
kcb->kprobe_status = kcb->prev_kprobe.status;
}
static inline void __kprobes set_current_kprobe(struct kprobe *p)
{
- __this_cpu_write(current_kprobe, p);
+ __get_cpu_var(current_kprobe) = p;
}
static void __kprobes resume_execution(struct kprobe *p, unsigned long addr,
@@ -237,7 +237,7 @@ int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
return 1;
} else if (kprobe_running()) {
- p = __this_cpu_read(current_kprobe);
+ p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
setup_singlestep(p, regs);
kcb->kprobe_status = KPROBE_HIT_SS;
@@ -327,7 +327,7 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned long trapnr)
*/
/* We increment the nmissed count for accounting,
- * we can also use npre/npostfault count for accounting
+ * we can also use npre/npostfault count for accouting
* these specific fault cases.
*/
kprobes_inc_nmissed_count(cur);
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
deleted file mode 100644
index e46d81f..0000000
--- a/arch/arc/kernel/perf_event.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Linux performance counter support for ARC700 series
- *
- * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
- *
- * This code is inspired by the perf support of various other architectures.
- *
- * 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.
- *
- */
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/perf_event.h>
-#include <linux/platform_device.h>
-#include <asm/arcregs.h>
-
-struct arc_pmu {
- struct pmu pmu;
- int counter_size; /* in bits */
- int n_counters;
- unsigned long used_mask[BITS_TO_LONGS(ARC_PMU_MAX_HWEVENTS)];
- int ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
-};
-
-/* read counter #idx; note that counter# != event# on ARC! */
-static uint64_t arc_pmu_read_counter(int idx)
-{
- uint32_t tmp;
- uint64_t result;
-
- /*
- * ARC supports making 'snapshots' of the counters, so we don't
- * need to care about counters wrapping to 0 underneath our feet
- */
- write_aux_reg(ARC_REG_PCT_INDEX, idx);
- tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
- write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN);
- result = (uint64_t) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
- result |= read_aux_reg(ARC_REG_PCT_SNAPL);
-
- return result;
-}
-
-static void arc_perf_event_update(struct perf_event *event,
- struct hw_perf_event *hwc, int idx)
-{
- struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
- uint64_t prev_raw_count, new_raw_count;
- int64_t delta;
-
- do {
- prev_raw_count = local64_read(&hwc->prev_count);
- new_raw_count = arc_pmu_read_counter(idx);
- } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
- new_raw_count) != prev_raw_count);
-
- delta = (new_raw_count - prev_raw_count) &
- ((1ULL << arc_pmu->counter_size) - 1ULL);
-
- local64_add(delta, &event->count);
- local64_sub(delta, &hwc->period_left);
-}
-
-static void arc_pmu_read(struct perf_event *event)
-{
- arc_perf_event_update(event, &event->hw, event->hw.idx);
-}
-
-static int arc_pmu_cache_event(u64 config)
-{
- unsigned int cache_type, cache_op, cache_result;
- int ret;
-
- cache_type = (config >> 0) & 0xff;
- cache_op = (config >> 8) & 0xff;
- cache_result = (config >> 16) & 0xff;
- if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
- return -EINVAL;
- if (cache_type >= PERF_COUNT_HW_CACHE_OP_MAX)
- return -EINVAL;
- if (cache_type >= PERF_COUNT_HW_CACHE_RESULT_MAX)
- return -EINVAL;
-
- ret = arc_pmu_cache_map[cache_type][cache_op][cache_result];
-
- if (ret == CACHE_OP_UNSUPPORTED)
- return -ENOENT;
-
- return ret;
-}
-
-/* initializes hw_perf_event structure if event is supported */
-static int arc_pmu_event_init(struct perf_event *event)
-{
- struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
- struct hw_perf_event *hwc = &event->hw;
- int ret;
-
- /* ARC 700 PMU does not support sampling events */
- if (is_sampling_event(event))
- return -ENOENT;
-
- switch (event->attr.type) {
- case PERF_TYPE_HARDWARE:
- if (event->attr.config >= PERF_COUNT_HW_MAX)
- return -ENOENT;
- if (arc_pmu->ev_hw_idx[event->attr.config] < 0)
- return -ENOENT;
- hwc->config = arc_pmu->ev_hw_idx[event->attr.config];
- pr_debug("initializing event %d with cfg %d\n",
- (int) event->attr.config, (int) hwc->config);
- return 0;
- case PERF_TYPE_HW_CACHE:
- ret = arc_pmu_cache_event(event->attr.config);
- if (ret < 0)
- return ret;
- hwc->config = arc_pmu->ev_hw_idx[ret];
- return 0;
- default:
- return -ENOENT;
- }
-}
-
-/* starts all counters */
-static void arc_pmu_enable(struct pmu *pmu)
-{
- uint32_t tmp;
- tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
- write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1);
-}
-
-/* stops all counters */
-static void arc_pmu_disable(struct pmu *pmu)
-{
- uint32_t tmp;
- tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
- write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0);
-}
-
-/*
- * Assigns hardware counter to hardware condition.
- * Note that there is no separate start/stop mechanism;
- * stopping is achieved by assigning the 'never' condition
- */
-static void arc_pmu_start(struct perf_event *event, int flags)
-{
- struct hw_perf_event *hwc = &event->hw;
- int idx = hwc->idx;
-
- if (WARN_ON_ONCE(idx == -1))
- return;
-
- if (flags & PERF_EF_RELOAD)
- WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
-
- event->hw.state = 0;
-
- /* enable ARC pmu here */
- write_aux_reg(ARC_REG_PCT_INDEX, idx);
- write_aux_reg(ARC_REG_PCT_CONFIG, hwc->config);
-}
-
-static void arc_pmu_stop(struct perf_event *event, int flags)
-{
- struct hw_perf_event *hwc = &event->hw;
- int idx = hwc->idx;
-
- if (!(event->hw.state & PERF_HES_STOPPED)) {
- /* stop ARC pmu here */
- write_aux_reg(ARC_REG_PCT_INDEX, idx);
-
- /* condition code #0 is always "never" */
- write_aux_reg(ARC_REG_PCT_CONFIG, 0);
-
- event->hw.state |= PERF_HES_STOPPED;
- }
-
- if ((flags & PERF_EF_UPDATE) &&
- !(event->hw.state & PERF_HES_UPTODATE)) {
- arc_perf_event_update(event, &event->hw, idx);
- event->hw.state |= PERF_HES_UPTODATE;
- }
-}
-
-static void arc_pmu_del(struct perf_event *event, int flags)
-{
- struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
-
- arc_pmu_stop(event, PERF_EF_UPDATE);
- __clear_bit(event->hw.idx, arc_pmu->used_mask);
-
- perf_event_update_userpage(event);
-}
-
-/* allocate hardware counter and optionally start counting */
-static int arc_pmu_add(struct perf_event *event, int flags)
-{
- struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
- struct hw_perf_event *hwc = &event->hw;
- int idx = hwc->idx;
-
- if (__test_and_set_bit(idx, arc_pmu->used_mask)) {
- idx = find_first_zero_bit(arc_pmu->used_mask,
- arc_pmu->n_counters);
- if (idx == arc_pmu->n_counters)
- return -EAGAIN;
-
- __set_bit(idx, arc_pmu->used_mask);
- hwc->idx = idx;
- }
-
- write_aux_reg(ARC_REG_PCT_INDEX, idx);
- write_aux_reg(ARC_REG_PCT_CONFIG, 0);
- write_aux_reg(ARC_REG_PCT_COUNTL, 0);
- write_aux_reg(ARC_REG_PCT_COUNTH, 0);
- local64_set(&hwc->prev_count, 0);
-
- hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
- if (flags & PERF_EF_START)
- arc_pmu_start(event, PERF_EF_RELOAD);
-
- perf_event_update_userpage(event);
-
- return 0;
-}
-
-static int arc_pmu_device_probe(struct platform_device *pdev)
-{
- struct arc_pmu *arc_pmu;
- struct arc_reg_pct_build pct_bcr;
- struct arc_reg_cc_build cc_bcr;
- int i, j, ret;
-
- union cc_name {
- struct {
- uint32_t word0, word1;
- char sentinel;
- } indiv;
- char str[9];
- } cc_name;
-
-
- READ_BCR(ARC_REG_PCT_BUILD, pct_bcr);
- if (!pct_bcr.v) {
- pr_err("This core does not have performance counters!\n");
- return -ENODEV;
- }
-
- arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu),
- GFP_KERNEL);
- if (!arc_pmu)
- return -ENOMEM;
-
- arc_pmu->n_counters = pct_bcr.c;
- BUG_ON(arc_pmu->n_counters > ARC_PMU_MAX_HWEVENTS);
-
- arc_pmu->counter_size = 32 + (pct_bcr.s << 4);
- pr_info("ARC PMU found with %d counters of size %d bits\n",
- arc_pmu->n_counters, arc_pmu->counter_size);
-
- READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-
- if (!cc_bcr.v)
- pr_err("Strange! Performance counters exist, but no countable conditions?\n");
-
- pr_info("ARC PMU has %d countable conditions\n", cc_bcr.c);
-
- cc_name.str[8] = 0;
- for (i = 0; i < PERF_COUNT_HW_MAX; i++)
- arc_pmu->ev_hw_idx[i] = -1;
-
- for (j = 0; j < cc_bcr.c; j++) {
- write_aux_reg(ARC_REG_CC_INDEX, j);
- cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
- cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
- for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
- if (arc_pmu_ev_hw_map[i] &&
- !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) &&
- strlen(arc_pmu_ev_hw_map[i])) {
- pr_debug("mapping %d to idx %d with name %s\n",
- i, j, cc_name.str);
- arc_pmu->ev_hw_idx[i] = j;
- }
- }
- }
-
- arc_pmu->pmu = (struct pmu) {
- .pmu_enable = arc_pmu_enable,
- .pmu_disable = arc_pmu_disable,
- .event_init = arc_pmu_event_init,
- .add = arc_pmu_add,
- .del = arc_pmu_del,
- .start = arc_pmu_start,
- .stop = arc_pmu_stop,
- .read = arc_pmu_read,
- };
-
- ret = perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
-
- return ret;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id arc_pmu_match[] = {
- { .compatible = "snps,arc700-pmu" },
- {},
-};
-MODULE_DEVICE_TABLE(of, arc_pmu_match);
-#endif
-
-static struct platform_driver arc_pmu_driver = {
- .driver = {
- .name = "arc700-pmu",
- .of_match_table = of_match_ptr(arc_pmu_match),
- },
- .probe = arc_pmu_device_probe,
-};
-
-module_platform_driver(arc_pmu_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mischa Jonker <mjonker@synopsys.com>");
-MODULE_DESCRIPTION("ARC PMU driver");
diff --git a/arch/arc/kernel/reset.c b/arch/arc/kernel/reset.c
index 2768fa1..e227a2b 100644
--- a/arch/arc/kernel/reset.c
+++ b/arch/arc/kernel/reset.c
@@ -31,4 +31,3 @@ void machine_power_off(void)
}
void (*pm_power_off) (void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 643eae4..2c68bc7e 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -21,6 +21,7 @@
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/irq.h>
+#include <asm/prom.h>
#include <asm/unwind.h>
#include <asm/clk.h>
#include <asm/mach_desc.h>
@@ -30,13 +31,14 @@
int running_on_hw = 1; /* vs. on ISS */
char __initdata command_line[COMMAND_LINE_SIZE];
-const struct machine_desc *machine_desc;
+struct machine_desc *machine_desc;
struct task_struct *_current_task[NR_CPUS]; /* For stack switching */
struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
-static void read_arc_build_cfg_regs(void)
+
+void read_arc_build_cfg_regs(void)
{
struct bcr_perip uncached_space;
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -104,7 +106,7 @@ static const struct cpuinfo_data arc_cpu_tbl[] = {
{ {0x00, NULL } }
};
-static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
+char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
{
int n = 0;
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
@@ -169,7 +171,7 @@ static const struct id_to_str mac_mul_nm[] = {
{0x6, "Dual 16x16 and 32x16"}
};
-static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
+char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
{
int n = 0;
struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
@@ -232,7 +234,7 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
return buf;
}
-static void arc_chk_ccms(void)
+void arc_chk_ccms(void)
{
#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -267,7 +269,7 @@ static void arc_chk_ccms(void)
* hardware has dedicated regs which need to be saved/restored on ctx-sw
* (Single Precision uses core regs), thus kernel is kind of oblivious to it
*/
-static void arc_chk_fpu(void)
+void arc_chk_fpu(void)
{
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -344,7 +346,8 @@ void __init setup_arch(char **cmdline_p)
setup_arch_memory();
/* copy flat DT out of .init and then unflatten it */
- unflatten_and_copy_device_tree();
+ copy_devtree();
+ unflatten_device_tree();
/* Can be issue if someone passes cmd line arg "ro"
* But that is unlikely so keeping it as it is
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index c2f9ebb..bca3052 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -95,7 +95,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
* If it turns out to be elaborate, it's better to code it in assembly
*
*/
-void __weak arc_platform_smp_wait_to_boot(int cpu)
+void __attribute__((weak)) arc_platform_smp_wait_to_boot(int cpu)
{
/*
* As a hack for debugging - since debugger will single-step over the
@@ -128,7 +128,6 @@ void start_kernel_secondary(void)
atomic_inc(&mm->mm_users);
atomic_inc(&mm->mm_count);
current->active_mm = mm;
- cpumask_set_cpu(cpu, mm_cpumask(mm));
notify_cpu_starting(cpu);
set_cpu_online(cpu, true);
@@ -211,6 +210,7 @@ enum ipi_msg_type {
IPI_NOP = 0,
IPI_RESCHEDULE = 1,
IPI_CALL_FUNC,
+ IPI_CALL_FUNC_SINGLE,
IPI_CPU_STOP
};
@@ -254,7 +254,7 @@ void smp_send_stop(void)
void arch_send_call_function_single_ipi(int cpu)
{
- ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC);
+ ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
}
void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -286,6 +286,10 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu)
generic_smp_call_function_interrupt();
break;
+ case IPI_CALL_FUNC_SINGLE:
+ generic_smp_call_function_single_interrupt();
+ break;
+
case IPI_CPU_STOP:
ipi_cpu_stop(cpu);
break;
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c
index 9ce47cf..f8b7d88 100644
--- a/arch/arc/kernel/stacktrace.c
+++ b/arch/arc/kernel/stacktrace.c
@@ -237,14 +237,11 @@ unsigned int get_wchan(struct task_struct *tsk)
*/
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
- /* Assumes @tsk is sleeping so unwinds from __switch_to */
arc_unwind_core(tsk, NULL, __collect_all_but_sched, trace);
}
void save_stack_trace(struct stack_trace *trace)
{
- /* Pass NULL for task so it unwinds the current call frame */
- arc_unwind_core(NULL, NULL, __collect_all, trace);
+ arc_unwind_core(current, NULL, __collect_all, trace);
}
-EXPORT_SYMBOL_GPL(save_stack_trace);
#endif
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index e5f3a83..3fde7de 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -63,10 +63,9 @@
int arc_counter_setup(void)
{
- /*
- * For SMP this needs to be 0. However Kconfig glue doesn't
- * enable this option for SMP configs
- */
+ /* RTSC insn taps into cpu clk, needs no setup */
+
+ /* For SMP, only allowed if cross-core-sync, hence usable as cs */
return 1;
}
@@ -207,7 +206,7 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
static irqreturn_t timer_irq_handler(int irq, void *dev_id)
{
- struct clock_event_device *clk = this_cpu_ptr(&arc_clockevent_device);
+ struct clock_event_device *clk = &__get_cpu_var(arc_clockevent_device);
arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC);
clk->event_handler(clk);
@@ -224,7 +223,7 @@ static struct irqaction arc_timer_irq = {
* Setup the local event timer for @cpu
* N.B. weak so that some exotic ARC SoCs can completely override it
*/
-void __weak arc_local_timer_setup(unsigned int cpu)
+void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu)
{
struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu);
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index 3eadfda..e21692d 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -84,18 +84,19 @@ DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", do_memory_error, BUS_ADRERR)
DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN)
+#ifdef CONFIG_ARC_MISALIGN_ACCESS
/*
* Entry Point for Misaligned Data access Exception, for emulating in software
*/
int do_misaligned_access(unsigned long address, struct pt_regs *regs,
struct callee_regs *cregs)
{
- /* If emulation not enabled, or failed, kill the task */
if (misaligned_fixup(address, regs, cregs) != 0)
return do_misaligned_error(address, regs);
return 0;
}
+#endif
/*
* Entry point for miscll errors such as Nested Exceptions