aboutsummaryrefslogtreecommitdiff
path: root/arch/metag/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/metag/kernel')
-rw-r--r--arch/metag/kernel/cachepart.c13
-rw-r--r--arch/metag/kernel/clock.c59
-rw-r--r--arch/metag/kernel/devtree.c83
-rw-r--r--arch/metag/kernel/dma.c9
-rw-r--r--arch/metag/kernel/ftrace.c5
-rw-r--r--arch/metag/kernel/irq.c75
-rw-r--r--arch/metag/kernel/kick.c9
-rw-r--r--arch/metag/kernel/metag_ksyms.c5
-rw-r--r--arch/metag/kernel/perf/perf_event.c8
-rw-r--r--arch/metag/kernel/setup.c33
-rw-r--r--arch/metag/kernel/signal.c48
-rw-r--r--arch/metag/kernel/smp.c70
-rw-r--r--arch/metag/kernel/time.c14
-rw-r--r--arch/metag/kernel/topology.c1
-rw-r--r--arch/metag/kernel/traps.c12
15 files changed, 204 insertions, 240 deletions
diff --git a/arch/metag/kernel/cachepart.c b/arch/metag/kernel/cachepart.c
index 954548b1bea..0a2385fa2a1 100644
--- a/arch/metag/kernel/cachepart.c
+++ b/arch/metag/kernel/cachepart.c
@@ -100,22 +100,23 @@ void check_for_cache_aliasing(int thread_id)
thread_cache_size =
get_thread_cache_size(cache_type, thread_id);
if (thread_cache_size < 0)
- pr_emerg("Can't read %s cache size", \
+ pr_emerg("Can't read %s cache size\n",
cache_type ? "DCACHE" : "ICACHE");
else if (thread_cache_size == 0)
/* Cache is off. No need to check for aliasing */
continue;
if (thread_cache_size / CACHE_ASSOCIATIVITY > PAGE_SIZE) {
- pr_emerg("Cache aliasing detected in %s on Thread %d",
+ pr_emerg("Potential cache aliasing detected in %s on Thread %d\n",
cache_type ? "DCACHE" : "ICACHE", thread_id);
- pr_warn("Total %s size: %u bytes",
- cache_type ? "DCACHE" : "ICACHE ",
+ pr_warn("Total %s size: %u bytes\n",
+ cache_type ? "DCACHE" : "ICACHE",
cache_type ? get_dcache_size()
: get_icache_size());
- pr_warn("Thread %s size: %d bytes",
+ pr_warn("Thread %s size: %d bytes\n",
cache_type ? "CACHE" : "ICACHE",
thread_cache_size);
- pr_warn("Page Size: %lu bytes", PAGE_SIZE);
+ pr_warn("Page Size: %lu bytes\n", PAGE_SIZE);
+ panic("Potential cache aliasing detected");
}
}
}
diff --git a/arch/metag/kernel/clock.c b/arch/metag/kernel/clock.c
index defc84056f1..6339c9c6d0a 100644
--- a/arch/metag/kernel/clock.c
+++ b/arch/metag/kernel/clock.c
@@ -8,8 +8,10 @@
* published by the Free Software Foundation.
*/
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <asm/param.h>
#include <asm/clock.h>
@@ -34,8 +36,63 @@ static unsigned long get_core_freq_default(void)
#endif
}
+static struct clk *clk_core;
+
+/* Clk based get_core_freq callback. */
+static unsigned long get_core_freq_clk(void)
+{
+ return clk_get_rate(clk_core);
+}
+
+/**
+ * init_metag_core_clock() - Set up core clock from devicetree.
+ *
+ * Checks to see if a "core" clock is provided in the device tree, and overrides
+ * the get_core_freq callback to use it.
+ */
+static void __init init_metag_core_clock(void)
+{
+ /*
+ * See if a core clock is provided by the devicetree (and
+ * registered by the init callback above).
+ */
+ struct device_node *node;
+ node = of_find_compatible_node(NULL, NULL, "img,meta");
+ if (!node) {
+ pr_warn("%s: no compatible img,meta DT node found\n",
+ __func__);
+ return;
+ }
+
+ clk_core = of_clk_get_by_name(node, "core");
+ if (IS_ERR(clk_core)) {
+ pr_warn("%s: no core clock found in DT\n",
+ __func__);
+ return;
+ }
+
+ /*
+ * Override the core frequency callback to use
+ * this clk.
+ */
+ _meta_clock.get_core_freq = get_core_freq_clk;
+}
+
+/**
+ * init_metag_clocks() - Set up clocks from devicetree.
+ *
+ * Set up important clocks from device tree. In particular any needed for clock
+ * sources.
+ */
+void __init init_metag_clocks(void)
+{
+ init_metag_core_clock();
+
+ pr_info("Core clock frequency: %lu Hz\n", get_coreclock());
+}
+
/**
- * setup_meta_clocks() - Set up the Meta clock.
+ * setup_meta_clocks() - Early set up of the Meta clock.
* @desc: Clock descriptor usually provided by machine description
*
* Ensures all callbacks are valid.
diff --git a/arch/metag/kernel/devtree.c b/arch/metag/kernel/devtree.c
index 7cd02529636..18dd7aea9fd 100644
--- a/arch/metag/kernel/devtree.c
+++ b/arch/metag/kernel/devtree.c
@@ -34,6 +34,19 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
return alloc_bootmem_align(size, align);
}
+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
@@ -41,74 +54,18 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
* If a dtb was passed to the kernel, then use it to choose the correct
* machine_desc and to setup the system.
*/
-struct machine_desc * __init setup_machine_fdt(void *dt)
+const struct machine_desc * __init setup_machine_fdt(void *dt)
{
- struct boot_param_header *devtree = dt;
- struct machine_desc *mdesc, *mdesc_best = NULL;
- unsigned int score, mdesc_score = ~1;
- unsigned long dt_root;
- const char *model;
+ const struct machine_desc *mdesc;
/* check device tree validity */
- if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
+ if (!early_init_dt_scan(dt))
return NULL;
- /* Search the mdescs for the 'best' compatible value match */
- initial_boot_params = devtree;
- dt_root = of_get_flat_dt_root();
-
- 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("\nError: unrecognized/unsupported device tree compatible 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");
-
+ mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
+ if (!mdesc)
dump_machine_table(); /* does not return */
- }
-
- model = of_get_flat_dt_prop(dt_root, "model", NULL);
- if (!model)
- model = of_get_flat_dt_prop(dt_root, "compatible", NULL);
- if (!model)
- model = "<unknown>";
- pr_info("Machine: %s, model: %s\n", mdesc_best->name, model);
-
- /* Retrieve various information from the /chosen node */
- of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
-
- return mdesc_best;
-}
+ pr_info("Machine name: %s\n", mdesc->name);
-/**
- * copy_fdt - Copy device tree into non-init memory.
- *
- * We must copy the flattened device tree blob into non-init memory because the
- * unflattened device tree will reference the strings in it directly.
- */
-void __init copy_fdt(void)
-{
- void *alloc = early_init_dt_alloc_memory_arch(
- be32_to_cpu(initial_boot_params->totalsize), 0x40);
- if (alloc) {
- memcpy(alloc, initial_boot_params,
- be32_to_cpu(initial_boot_params->totalsize));
- initial_boot_params = alloc;
- }
+ return mdesc;
}
diff --git a/arch/metag/kernel/dma.c b/arch/metag/kernel/dma.c
index 8c00dedadc5..c700d625067 100644
--- a/arch/metag/kernel/dma.c
+++ b/arch/metag/kernel/dma.c
@@ -305,9 +305,7 @@ void dma_free_coherent(struct device *dev, size_t size,
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
- ClearPageReserved(page);
-
- __free_page(page);
+ __free_reserved_page(page);
continue;
}
}
@@ -401,11 +399,6 @@ static int __init dma_alloc_init(void)
pgd = pgd_offset(&init_mm, CONSISTENT_START);
pud = pud_alloc(&init_mm, pgd, CONSISTENT_START);
pmd = pmd_alloc(&init_mm, pud, CONSISTENT_START);
- if (!pmd) {
- pr_err("%s: no pmd tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
WARN_ON(!pmd_none(*pmd));
pte = pte_alloc_kernel(pmd, CONSISTENT_START);
diff --git a/arch/metag/kernel/ftrace.c b/arch/metag/kernel/ftrace.c
index a774f321643..ed1d685157c 100644
--- a/arch/metag/kernel/ftrace.c
+++ b/arch/metag/kernel/ftrace.c
@@ -117,10 +117,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
}
/* run from kstop_machine */
-int __init ftrace_dyn_arch_init(void *data)
+int __init ftrace_dyn_arch_init(void)
{
- /* The return code is returned via data */
- writel(0, data);
-
return 0;
}
diff --git a/arch/metag/kernel/irq.c b/arch/metag/kernel/irq.c
index 87707efeb0a..5385dd1216b 100644
--- a/arch/metag/kernel/irq.c
+++ b/arch/metag/kernel/irq.c
@@ -25,7 +25,7 @@ static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
#endif
-struct irq_domain *root_domain;
+static struct irq_domain *root_domain;
static unsigned int startup_meta_irq(struct irq_data *data)
{
@@ -159,44 +159,30 @@ void irq_ctx_exit(int cpu)
extern asmlinkage void __do_softirq(void);
-asmlinkage void do_softirq(void)
+void do_softirq_own_stack(void)
{
- unsigned long flags;
struct thread_info *curctx;
union irq_ctx *irqctx;
u32 *isp;
- if (in_interrupt())
- return;
-
- local_irq_save(flags);
-
- if (local_softirq_pending()) {
- curctx = current_thread_info();
- irqctx = softirq_ctx[smp_processor_id()];
- irqctx->tinfo.task = curctx->task;
-
- /* build the stack frame on the softirq stack */
- isp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));
-
- asm volatile (
- "MOV D0.5,%0\n"
- "SWAP A0StP,D0.5\n"
- "CALLR D1RtP,___do_softirq\n"
- "MOV A0StP,D0.5\n"
- :
- : "r" (isp)
- : "memory", "cc", "D1Ar1", "D0Ar2", "D1Ar3", "D0Ar4",
- "D1Ar5", "D0Ar6", "D0Re0", "D1Re0", "D0.4", "D1RtP",
- "D0.5"
- );
- /*
- * Shouldn't happen, we returned above if in_interrupt():
- */
- WARN_ON_ONCE(softirq_count());
- }
-
- local_irq_restore(flags);
+ curctx = current_thread_info();
+ irqctx = softirq_ctx[smp_processor_id()];
+ irqctx->tinfo.task = curctx->task;
+
+ /* build the stack frame on the softirq stack */
+ isp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));
+
+ asm volatile (
+ "MOV D0.5,%0\n"
+ "SWAP A0StP,D0.5\n"
+ "CALLR D1RtP,___do_softirq\n"
+ "MOV A0StP,D0.5\n"
+ :
+ : "r" (isp)
+ : "memory", "cc", "D1Ar1", "D0Ar2", "D1Ar3", "D0Ar4",
+ "D1Ar5", "D0Ar6", "D0Re0", "D1Re0", "D0.4", "D1RtP",
+ "D0.5"
+ );
}
#endif
@@ -275,17 +261,6 @@ int __init arch_probe_nr_irqs(void)
}
#ifdef CONFIG_HOTPLUG_CPU
-static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
-{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_chip *chip = irq_data_get_irq_chip(data);
-
- raw_spin_lock_irq(&desc->lock);
- if (chip->irq_set_affinity)
- chip->irq_set_affinity(data, cpumask_of(cpu), false);
- raw_spin_unlock_irq(&desc->lock);
-}
-
/*
* The CPU has been marked offline. Migrate IRQs off this CPU. If
* the affinity settings do not allow other CPUs, force them onto any
@@ -294,10 +269,9 @@ static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
void migrate_irqs(void)
{
unsigned int i, cpu = smp_processor_id();
- struct irq_desc *desc;
- for_each_irq_desc(i, desc) {
- struct irq_data *data = irq_desc_get_irq_data(desc);
+ for_each_active_irq(i) {
+ struct irq_data *data = irq_get_irq_data(i);
unsigned int newcpu;
if (irqd_is_per_cpu(data))
@@ -313,11 +287,8 @@ void migrate_irqs(void)
i, cpu);
cpumask_setall(data->affinity);
- newcpu = cpumask_any_and(data->affinity,
- cpu_online_mask);
}
-
- route_irq(data, i, newcpu);
+ irq_set_affinity(i, data->affinity);
}
}
#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/metag/kernel/kick.c b/arch/metag/kernel/kick.c
index 50fcbec98cd..beb37762132 100644
--- a/arch/metag/kernel/kick.c
+++ b/arch/metag/kernel/kick.c
@@ -26,6 +26,8 @@
* pass it as an argument.
*/
#include <linux/export.h>
+#include <linux/hardirq.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/types.h>
@@ -66,6 +68,7 @@ EXPORT_SYMBOL(kick_unregister_func);
TBIRES
kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
{
+ struct pt_regs *old_regs;
struct kick_irq_handler *kh;
struct list_head *lh;
int handled = 0;
@@ -79,6 +82,9 @@ kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
trace_hardirqs_off();
+ old_regs = set_irq_regs((struct pt_regs *)State.Sig.pCtx);
+ irq_enter();
+
/*
* There is no need to disable interrupts here because we
* can't nest KICK interrupts in a KICK interrupt handler.
@@ -97,5 +103,8 @@ kick_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
WARN_ON(!handled);
+ irq_exit();
+ set_irq_regs(old_regs);
+
return tail_end(ret);
}
diff --git a/arch/metag/kernel/metag_ksyms.c b/arch/metag/kernel/metag_ksyms.c
index ec872ef14eb..215c94ad63a 100644
--- a/arch/metag/kernel/metag_ksyms.c
+++ b/arch/metag/kernel/metag_ksyms.c
@@ -1,5 +1,7 @@
#include <linux/export.h>
+#include <linux/types.h>
+#include <asm/checksum.h>
#include <asm/div64.h>
#include <asm/ftrace.h>
#include <asm/page.h>
@@ -15,6 +17,9 @@ EXPORT_SYMBOL(max_pfn);
EXPORT_SYMBOL(min_low_pfn);
#endif
+/* Network checksum functions */
+EXPORT_SYMBOL(csum_partial);
+
/* TBI symbols */
EXPORT_SYMBOL(__TBI);
EXPORT_SYMBOL(__TBIFindSeg);
diff --git a/arch/metag/kernel/perf/perf_event.c b/arch/metag/kernel/perf/perf_event.c
index 366569425c5..5cc4d4dcf3c 100644
--- a/arch/metag/kernel/perf/perf_event.c
+++ b/arch/metag/kernel/perf/perf_event.c
@@ -813,8 +813,8 @@ static struct metag_pmu _metag_pmu = {
};
/* PMU CPU hotplug notifier */
-static int __cpuinit metag_pmu_cpu_notify(struct notifier_block *b,
- unsigned long action, void *hcpu)
+static int metag_pmu_cpu_notify(struct notifier_block *b, unsigned long action,
+ void *hcpu)
{
unsigned int cpu = (unsigned int)hcpu;
struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
@@ -828,7 +828,7 @@ static int __cpuinit metag_pmu_cpu_notify(struct notifier_block *b,
return NOTIFY_OK;
}
-static struct notifier_block __cpuinitdata metag_pmu_notifier = {
+static struct notifier_block metag_pmu_notifier = {
.notifier_call = metag_pmu_cpu_notify,
};
@@ -882,7 +882,7 @@ static int __init init_hw_perf_events(void)
}
register_cpu_notifier(&metag_pmu_notifier);
- ret = perf_pmu_register(&pmu, (char *)metag_pmu->name, PERF_TYPE_RAW);
+ ret = perf_pmu_register(&pmu, metag_pmu->name, PERF_TYPE_RAW);
out:
return ret;
}
diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c
index 4f5726f1a55..31cf53d0eba 100644
--- a/arch/metag/kernel/setup.c
+++ b/arch/metag/kernel/setup.c
@@ -20,6 +20,7 @@
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
#include <linux/pfn.h>
#include <linux/root_dev.h>
#include <linux/sched.h>
@@ -41,7 +42,6 @@
#include <asm/mmu.h>
#include <asm/mmzone.h>
#include <asm/processor.h>
-#include <asm/prom.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/traps.h>
@@ -105,16 +105,12 @@
extern char _heap_start[];
-#ifdef CONFIG_METAG_BUILTIN_DTB
-extern u32 __dtb_start[];
-#endif
-
#ifdef CONFIG_DA_CONSOLE
/* Our early channel based console driver */
extern struct console dash_console;
#endif
-struct machine_desc *machine_desc __initdata;
+const struct machine_desc *machine_desc __initdata;
/*
* Map a Linux CPU number to a hardware thread ID
@@ -301,13 +297,9 @@ void __init setup_arch(char **cmdline_p)
* rather than the version from the bootloader. This makes call
* stacks easier to understand and may allow us to unmap the
* bootloader at some point.
- *
- * We need to keep the LWK handler that TBI installed in order to
- * be able to do inter-thread comms.
*/
for (i = 0; i <= TBID_SIGNUM_MAX; i++)
- if (i != TBID_SIGNUM_LWK)
- _pTBI->fnSigs[i] = __TBIUnExpXXX;
+ _pTBI->fnSigs[i] = __TBIUnExpXXX;
/* A Meta requirement is that the kernel is loaded (virtually)
* at the PAGE_OFFSET.
@@ -407,9 +399,7 @@ void __init setup_arch(char **cmdline_p)
cpu_2_hwthread_id[smp_processor_id()] = hard_processor_id();
hwthread_id_2_cpu[hard_processor_id()] = smp_processor_id();
- /* Copy device tree blob into non-init memory before unflattening */
- copy_fdt();
- unflatten_device_tree();
+ unflatten_and_copy_device_tree();
#ifdef CONFIG_SMP
smp_init_cpus();
@@ -424,6 +414,9 @@ static int __init customize_machine(void)
/* customizes platform devices, or adds new ones */
if (machine_desc->init_machine)
machine_desc->init_machine();
+ else
+ of_platform_populate(NULL, of_default_bus_match_table, NULL,
+ NULL);
return 0;
}
arch_initcall(customize_machine);
@@ -587,20 +580,20 @@ PTBI pTBI_get(unsigned int cpu)
EXPORT_SYMBOL(pTBI_get);
#if defined(CONFIG_METAG_DSP) && defined(CONFIG_METAG_FPU)
-char capabilites[] = "dsp fpu";
+static char capabilities[] = "dsp fpu";
#elif defined(CONFIG_METAG_DSP)
-char capabilites[] = "dsp";
+static char capabilities[] = "dsp";
#elif defined(CONFIG_METAG_FPU)
-char capabilites[] = "fpu";
+static char capabilities[] = "fpu";
#else
-char capabilites[] = "";
+static char capabilities[] = "";
#endif
static struct ctl_table caps_kern_table[] = {
{
.procname = "capabilities",
- .data = capabilites,
- .maxlen = sizeof(capabilites),
+ .data = capabilities,
+ .maxlen = sizeof(capabilities),
.mode = 0444,
.proc_handler = proc_dostring,
},
diff --git a/arch/metag/kernel/signal.c b/arch/metag/kernel/signal.c
index 3be61cf0b14..b9e4a82d2bd 100644
--- a/arch/metag/kernel/signal.c
+++ b/arch/metag/kernel/signal.c
@@ -152,18 +152,18 @@ static void __user *get_sigframe(struct k_sigaction *ka, unsigned long sp,
return (void __user *)sp;
}
-static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
- int err = -EFAULT;
+ int err;
unsigned long code;
- frame = get_sigframe(ka, regs->REG_SP, sizeof(*frame));
+ frame = get_sigframe(&ksig->ka, regs->REG_SP, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto out;
+ return -EFAULT;
- err = copy_siginfo_to_user(&frame->info, info);
+ err = copy_siginfo_to_user(&frame->info, &ksig->info);
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -174,7 +174,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
- goto out;
+ return -EFAULT;
/* Set up to return from userspace. */
@@ -187,15 +187,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(code, (unsigned long __user *)(&frame->retcode[1]));
if (err)
- goto out;
+ return -EFAULT;
/* Set up registers for signal handler */
regs->REG_RTP = (unsigned long) frame->retcode;
regs->REG_SP = (unsigned long) frame + sizeof(*frame);
- regs->REG_ARG1 = sig;
+ regs->REG_ARG1 = ksig->sig;
regs->REG_ARG2 = (unsigned long) &frame->info;
regs->REG_ARG3 = (unsigned long) &frame->uc;
- regs->REG_PC = (unsigned long) ka->sa.sa_handler;
+ regs->REG_PC = (unsigned long) ksig->ka.sa.sa_handler;
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08x pr=%08x\n",
current->comm, current->pid, frame, regs->REG_PC,
@@ -205,24 +205,19 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* effective cache flush - directed rather than 'full flush'.
*/
flush_cache_sigtramp(regs->REG_RTP, sizeof(frame->retcode));
-out:
- if (err) {
- force_sigsegv(sig, current);
- return -EFAULT;
- }
+
return 0;
}
-static void handle_signal(unsigned long sig, siginfo_t *info,
- struct k_sigaction *ka, struct pt_regs *regs)
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
sigset_t *oldset = sigmask_to_save();
+ int ret;
/* Set up the stack frame */
- if (setup_rt_frame(sig, ka, info, oldset, regs))
- return;
+ ret = setup_rt_frame(ksig, oldset, regs);
- signal_delivered(sig, info, ka, regs, test_thread_flag(TIF_SINGLESTEP));
+ signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
}
/*
@@ -235,10 +230,8 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
static int do_signal(struct pt_regs *regs, int syscall)
{
unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
- struct k_sigaction ka;
- siginfo_t info;
- int signr;
int restart = 0;
+ struct ksignal ksig;
/*
* By the end of rt_sigreturn the context describes the point that the
@@ -275,7 +268,8 @@ static int do_signal(struct pt_regs *regs, int syscall)
* Get the signal to deliver. When running under ptrace, at this point
* the debugger may change all our registers ...
*/
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ get_signal(&ksig);
+
/*
* Depending on the signal settings we may need to revert the decision
* to restart the system call. But skip this if a debugger has chosen to
@@ -283,19 +277,19 @@ static int do_signal(struct pt_regs *regs, int syscall)
*/
if (regs->REG_PC != restart_addr)
restart = 0;
- if (signr > 0) {
+ if (ksig.sig > 0) {
if (unlikely(restart)) {
if (retval == -ERESTARTNOHAND
|| retval == -ERESTART_RESTARTBLOCK
|| (retval == -ERESTARTSYS
- && !(ka.sa.sa_flags & SA_RESTART))) {
+ && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
regs->REG_RETVAL = -EINTR;
regs->REG_PC = continue_addr;
}
}
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, regs);
+ handle_signal(&ksig, regs);
return 0;
}
diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c
index f443ec9a7cb..f006d2276f4 100644
--- a/arch/metag/kernel/smp.c
+++ b/arch/metag/kernel/smp.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
#include <linux/atomic.h>
+#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
@@ -62,10 +63,12 @@ static DEFINE_PER_CPU(struct ipi_data, ipi_data) = {
static DEFINE_SPINLOCK(boot_lock);
+static DECLARE_COMPLETION(cpu_running);
+
/*
* "thread" is assumed to be a valid Meta hardware thread ID.
*/
-int __cpuinit boot_secondary(unsigned int thread, struct task_struct *idle)
+static int boot_secondary(unsigned int thread, struct task_struct *idle)
{
u32 val;
@@ -115,11 +118,9 @@ int __cpuinit boot_secondary(unsigned int thread, struct task_struct *idle)
* If the cache partition has changed, prints a message to the log describing
* those changes.
*/
-static __cpuinit void describe_cachepart_change(unsigned int thread,
- const char *label,
- unsigned int sz,
- unsigned int old,
- unsigned int new)
+static void describe_cachepart_change(unsigned int thread, const char *label,
+ unsigned int sz, unsigned int old,
+ unsigned int new)
{
unsigned int lor1, land1, gor1, gand1;
unsigned int lor2, land2, gor2, gand2;
@@ -167,7 +168,7 @@ static __cpuinit void describe_cachepart_change(unsigned int thread,
* Ensures that coherency is enabled and that the threads share the same cache
* partitions.
*/
-static __cpuinit void setup_smp_cache(unsigned int thread)
+static void setup_smp_cache(unsigned int thread)
{
unsigned int this_thread, lflags;
unsigned int dcsz, dcpart_this, dcpart_old, dcpart_new;
@@ -212,7 +213,7 @@ static __cpuinit void setup_smp_cache(unsigned int thread)
icpart_old, icpart_new);
}
-int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
+int __cpu_up(unsigned int cpu, struct task_struct *idle)
{
unsigned int thread = cpu_2_hwthread_id[cpu];
int ret;
@@ -235,20 +236,12 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
*/
ret = boot_secondary(thread, idle);
if (ret == 0) {
- unsigned long timeout;
-
/*
* CPU was successfully started, wait for it
* to come online or time out.
*/
- timeout = jiffies + HZ;
- while (time_before(jiffies, timeout)) {
- if (cpu_online(cpu))
- break;
-
- udelay(10);
- barrier();
- }
+ wait_for_completion_timeout(&cpu_running,
+ msecs_to_jiffies(1000));
if (!cpu_online(cpu))
ret = -EIO;
@@ -273,10 +266,9 @@ static DECLARE_COMPLETION(cpu_killed);
/*
* __cpu_disable runs on the processor to be shutdown.
*/
-int __cpuexit __cpu_disable(void)
+int __cpu_disable(void)
{
unsigned int cpu = smp_processor_id();
- struct task_struct *p;
/*
* Take this CPU offline. Once we clear this, we can't return,
@@ -296,12 +288,7 @@ int __cpuexit __cpu_disable(void)
flush_cache_all();
local_flush_tlb_all();
- read_lock(&tasklist_lock);
- for_each_process(p) {
- if (p->mm)
- cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
- }
- read_unlock(&tasklist_lock);
+ clear_tasks_mm_cpumask(cpu);
return 0;
}
@@ -310,7 +297,7 @@ int __cpuexit __cpu_disable(void)
* called on the thread which is asking for a CPU to be shutdown -
* waits until shutdown has completed, or it is timed out.
*/
-void __cpuexit __cpu_die(unsigned int cpu)
+void __cpu_die(unsigned int cpu)
{
if (!wait_for_completion_timeout(&cpu_killed, msecs_to_jiffies(1)))
pr_err("CPU%u: unable to kill\n", cpu);
@@ -322,7 +309,7 @@ void __cpuexit __cpu_die(unsigned int cpu)
* Note that we do not return from this function. If this cpu is
* brought online again it will need to run secondary_startup().
*/
-void __cpuexit cpu_die(void)
+void cpu_die(void)
{
local_irq_disable();
idle_task_exit();
@@ -337,7 +324,7 @@ void __cpuexit cpu_die(void)
* Called by both boot and secondaries to move global data into
* per-processor storage.
*/
-void __cpuinit smp_store_cpu_info(unsigned int cpuid)
+void smp_store_cpu_info(unsigned int cpuid)
{
struct cpuinfo_metag *cpu_info = &per_cpu(cpu_data, cpuid);
@@ -385,12 +372,7 @@ asmlinkage void secondary_start_kernel(void)
setup_priv();
- /*
- * Enable local interrupts.
- */
- tbi_startup_interrupt(TBID_SIGNUM_TRT);
notify_cpu_starting(cpu);
- local_irq_enable();
pr_info("CPU%u (thread %u): Booted secondary processor\n",
cpu, cpu_2_hwthread_id[cpu]);
@@ -402,12 +384,13 @@ asmlinkage void secondary_start_kernel(void)
* OK, now it's safe to let the boot CPU continue
*/
set_cpu_online(cpu, true);
+ complete(&cpu_running);
/*
- * Check for cache aliasing.
- * Preemption is disabled
+ * Enable local interrupts.
*/
- check_for_cache_aliasing(cpu);
+ tbi_startup_interrupt(TBID_SIGNUM_TRT);
+ local_irq_enable();
/*
* OK, it's off to the idle thread for us
@@ -508,7 +491,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
void arch_send_call_function_single_ipi(int cpu)
{
- send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+ send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
}
void show_ipi_list(struct seq_file *p)
@@ -534,11 +517,10 @@ static DEFINE_SPINLOCK(stop_lock);
*
* Bit 0 - Inter-processor function call
*/
-static int do_IPI(struct pt_regs *regs)
+static int do_IPI(void)
{
unsigned int cpu = smp_processor_id();
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
- struct pt_regs *old_regs = set_irq_regs(regs);
unsigned long msgs, nextmsg;
int handled = 0;
@@ -563,10 +545,6 @@ static int do_IPI(struct pt_regs *regs)
generic_smp_call_function_interrupt();
break;
- case IPI_CALL_FUNC_SINGLE:
- generic_smp_call_function_single_interrupt();
- break;
-
default:
pr_crit("CPU%u: Unknown IPI message 0x%lx\n",
cpu, nextmsg);
@@ -574,8 +552,6 @@ static int do_IPI(struct pt_regs *regs)
}
}
- set_irq_regs(old_regs);
-
return handled;
}
@@ -641,7 +617,7 @@ static void kick_raise_softirq(cpumask_t callmap, unsigned int irq)
static TBIRES ipi_handler(TBIRES State, int SigNum, int Triggers,
int Inst, PTBI pTBI, int *handled)
{
- *handled = do_IPI((struct pt_regs *)State.Sig.pCtx);
+ *handled = do_IPI();
return State;
}
diff --git a/arch/metag/kernel/time.c b/arch/metag/kernel/time.c
index 17dc10733b2..f1c8c53dace 100644
--- a/arch/metag/kernel/time.c
+++ b/arch/metag/kernel/time.c
@@ -5,11 +5,21 @@
*
*/
-#include <linux/init.h>
-
#include <clocksource/metag_generic.h>
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <asm/clock.h>
void __init time_init(void)
{
+#ifdef CONFIG_COMMON_CLK
+ /* Init clocks from device tree */
+ of_clk_init(NULL);
+#endif
+
+ /* Init meta clocks, particularly the core clock */
+ init_metag_clocks();
+
+ /* Set up the timer clock sources */
metag_generic_timer_init();
}
diff --git a/arch/metag/kernel/topology.c b/arch/metag/kernel/topology.c
index bec3dec4922..4ba595701f7 100644
--- a/arch/metag/kernel/topology.c
+++ b/arch/metag/kernel/topology.c
@@ -19,6 +19,7 @@
DEFINE_PER_CPU(struct cpuinfo_metag, cpu_data);
cpumask_t cpu_core_map[NR_CPUS];
+EXPORT_SYMBOL(cpu_core_map);
static cpumask_t cpu_coregroup_map(unsigned int cpu)
{
diff --git a/arch/metag/kernel/traps.c b/arch/metag/kernel/traps.c
index 2ceeaae5b19..17b2e2e38d5 100644
--- a/arch/metag/kernel/traps.c
+++ b/arch/metag/kernel/traps.c
@@ -33,6 +33,7 @@
#include <asm/siginfo.h>
#include <asm/traps.h>
#include <asm/hwthread.h>
+#include <asm/setup.h>
#include <asm/switch.h>
#include <asm/user_gateway.h>
#include <asm/syscall.h>
@@ -87,8 +88,8 @@ const char *trap_name(int trapno)
static DEFINE_SPINLOCK(die_lock);
-void die(const char *str, struct pt_regs *regs, long err,
- unsigned long addr)
+void __noreturn die(const char *str, struct pt_regs *regs,
+ long err, unsigned long addr)
{
static int die_counter;
@@ -811,15 +812,14 @@ static void set_trigger_mask(unsigned int mask)
}
#endif
-void __cpuinit per_cpu_trap_init(unsigned long cpu)
+void per_cpu_trap_init(unsigned long cpu)
{
TBIRES int_context;
unsigned int thread = cpu_2_hwthread_id[cpu];
set_trigger_mask(TBI_INTS_INIT(thread) | /* interrupts */
TBI_TRIG_BIT(TBID_SIGNUM_LWK) | /* low level kick */
- TBI_TRIG_BIT(TBID_SIGNUM_SW1) |
- TBI_TRIG_BIT(TBID_SIGNUM_SWS));
+ TBI_TRIG_BIT(TBID_SIGNUM_SW1));
/* non-priv - use current stack */
int_context.Sig.pCtx = NULL;
@@ -841,7 +841,7 @@ void __init trap_init(void)
_pTBI->fnSigs[TBID_SIGNUM_SW1] = switch1_handler;
_pTBI->fnSigs[TBID_SIGNUM_SW2] = switchx_handler;
_pTBI->fnSigs[TBID_SIGNUM_SW3] = switchx_handler;
- _pTBI->fnSigs[TBID_SIGNUM_SWK] = kick_handler;
+ _pTBI->fnSigs[TBID_SIGNUM_LWK] = kick_handler;
#ifdef CONFIG_METAG_META21
_pTBI->fnSigs[TBID_SIGNUM_DFR] = __TBIHandleDFR;