aboutsummaryrefslogtreecommitdiff
path: root/arch/mn10300/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mn10300/kernel')
-rw-r--r--arch/mn10300/kernel/Makefile6
-rw-r--r--arch/mn10300/kernel/asm-offsets.c2
-rw-r--r--arch/mn10300/kernel/cevt-mn10300.c12
-rw-r--r--arch/mn10300/kernel/entry.S42
-rw-r--r--arch/mn10300/kernel/fpu.c1
-rw-r--r--arch/mn10300/kernel/gdb-io-serial.c1
-rw-r--r--arch/mn10300/kernel/gdb-io-ttysm.c1
-rw-r--r--arch/mn10300/kernel/gdb-stub.c53
-rw-r--r--arch/mn10300/kernel/init_task.c39
-rw-r--r--arch/mn10300/kernel/internal.h8
-rw-r--r--arch/mn10300/kernel/irq.c67
-rw-r--r--arch/mn10300/kernel/kernel_execve.S37
-rw-r--r--arch/mn10300/kernel/kgdb.c3
-rw-r--r--arch/mn10300/kernel/kthread.S31
-rw-r--r--arch/mn10300/kernel/mn10300-serial-low.S9
-rw-r--r--arch/mn10300/kernel/mn10300-serial.c234
-rw-r--r--arch/mn10300/kernel/mn10300-serial.h10
-rw-r--r--arch/mn10300/kernel/mn10300-watchdog.c5
-rw-r--r--arch/mn10300/kernel/module.c61
-rw-r--r--arch/mn10300/kernel/process.c208
-rw-r--r--arch/mn10300/kernel/ptrace.c1
-rw-r--r--arch/mn10300/kernel/setup.c58
-rw-r--r--arch/mn10300/kernel/signal.c140
-rw-r--r--arch/mn10300/kernel/smp-low.S2
-rw-r--r--arch/mn10300/kernel/smp.c109
-rw-r--r--arch/mn10300/kernel/traps.c19
-rw-r--r--arch/mn10300/kernel/vmlinux.lds.S3
27 files changed, 388 insertions, 774 deletions
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index 47ed30fe817..561029f7fa4 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -1,14 +1,14 @@
#
# Makefile for the MN10300-specific core kernel code
#
-extra-y := head.o init_task.o vmlinux.lds
+extra-y := head.o vmlinux.lds
fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
obj-y := process.o signal.o entry.o traps.o irq.o \
- ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
- switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \
+ ptrace.o setup.o time.o sys_mn10300.o io.o \
+ switch_to.o mn10300_ksyms.o $(fpu-obj-y) \
csrc-mn10300.o cevt-mn10300.o
obj-$(CONFIG_SMP) += smp.o smp-low.o
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
index 96f24fab7de..47b3bb0c04f 100644
--- a/arch/mn10300/kernel/asm-offsets.c
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -96,7 +96,7 @@ void foo(void)
OFFSET(__rx_outp, mn10300_serial_port, rx_outp);
OFFSET(__uart_state, mn10300_serial_port, uart.state);
OFFSET(__tx_xchar, mn10300_serial_port, tx_xchar);
- OFFSET(__tx_break, mn10300_serial_port, tx_break);
+ OFFSET(__tx_flags, mn10300_serial_port, tx_flags);
OFFSET(__intr_flags, mn10300_serial_port, intr_flags);
OFFSET(__rx_icr, mn10300_serial_port, rx_icr);
OFFSET(__tx_icr, mn10300_serial_port, tx_icr);
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c
index 69cae026078..60f64ca1752 100644
--- a/arch/mn10300/kernel/cevt-mn10300.c
+++ b/arch/mn10300/kernel/cevt-mn10300.c
@@ -70,6 +70,16 @@ static void event_handler(struct clock_event_device *dev)
{
}
+static inline void setup_jiffies_interrupt(int irq,
+ struct irqaction *action)
+{
+ u16 tmp;
+ setup_irq(irq, action);
+ set_intr_level(irq, NUM2GxICR_LEVEL(CONFIG_TIMER_IRQ_LEVEL));
+ GxICR(irq) |= GxICR_ENABLE | GxICR_DETECT | GxICR_REQUEST;
+ tmp = GxICR(irq);
+}
+
int __init init_clockevents(void)
{
struct clock_event_device *cd;
@@ -103,7 +113,7 @@ int __init init_clockevents(void)
cd->set_next_event = next_event;
iact = &per_cpu(timer_irq, cpu);
- iact->flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER;
+ iact->flags = IRQF_SHARED | IRQF_TIMER;
iact->handler = timer_interrupt;
clockevents_register_device(cd);
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index fb93ad720b8..177d61de51c 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -15,7 +15,6 @@
#include <linux/sys.h>
#include <linux/linkage.h>
#include <asm/smp.h>
-#include <asm/system.h>
#include <asm/irqflags.h>
#include <asm/thread_info.h>
#include <asm/intctl-regs.h>
@@ -56,6 +55,16 @@ ENTRY(ret_from_fork)
mov d0,(REG_D0,fp)
jmp syscall_exit
+ENTRY(ret_from_kernel_thread)
+ call schedule_tail[],0
+ mov (REG_D0,fp),d0
+ mov (REG_A0,fp),a0
+ calls (a0)
+ GET_THREAD_INFO a2 # A2 must be set on return from sys_exit()
+ clr d0
+ mov d0,(REG_D0,fp)
+ jmp syscall_exit
+
###############################################################################
#
# system call handler
@@ -95,10 +104,14 @@ restore_all:
###############################################################################
ALIGN
syscall_exit_work:
- btst _TIF_SYSCALL_TRACE,d2
- beq work_pending
+ mov (REG_EPSW,fp),d0
+ and EPSW_nSL,d0
+ beq resume_kernel # returning to supervisor mode
+
LOCAL_IRQ_ENABLE # could let syscall_trace_exit() call
# schedule() instead
+ btst _TIF_SYSCALL_TRACE,d2
+ beq work_pending
mov fp,d0
call syscall_trace_exit[],0 # do_syscall_trace(regs)
jmp resume_userspace
@@ -111,6 +124,7 @@ work_pending:
work_resched:
call schedule[],0
+resume_userspace:
# make sure we don't miss an interrupt setting need_resched or
# sigpending between sampling and the rti
LOCAL_IRQ_DISABLE
@@ -119,6 +133,8 @@ work_resched:
mov (TI_flags,a2),d2
btst _TIF_WORK_MASK,d2
beq restore_all
+
+ LOCAL_IRQ_ENABLE
btst _TIF_NEED_RESCHED,d2
bne work_resched
@@ -155,21 +171,10 @@ ret_from_intr:
mov (REG_EPSW,fp),d0 # need to deliver signals before
# returning to userspace
and EPSW_nSL,d0
- beq resume_kernel # returning to supervisor mode
-
-ENTRY(resume_userspace)
- # make sure we don't miss an interrupt setting need_resched or
- # sigpending between sampling and the rti
- LOCAL_IRQ_DISABLE
-
- # is there any work to be done on int/exception return?
- mov (TI_flags,a2),d2
- btst _TIF_WORK_MASK,d2
- bne work_pending
- jmp restore_all
+ bne resume_userspace # returning to userspace
#ifdef CONFIG_PREEMPT
-ENTRY(resume_kernel)
+resume_kernel:
LOCAL_IRQ_DISABLE
mov (TI_preempt_count,a2),d0 # non-zero preempt_count ?
cmp 0,d0
@@ -184,6 +189,8 @@ need_resched:
bne restore_all
call preempt_schedule_irq[],0
jmp need_resched
+#else
+ jmp resume_kernel
#endif
@@ -589,7 +596,7 @@ ENTRY(sys_call_table)
.long sys_ni_syscall /* vm86 */
.long sys_ni_syscall /* Old sys_query_module */
.long sys_poll
- .long sys_nfsservctl
+ .long sys_ni_syscall /* was nfsservctl */
.long sys_setresgid16 /* 170 */
.long sys_getresgid16
.long sys_prctl
@@ -759,6 +766,7 @@ ENTRY(sys_call_table)
.long sys_rt_tgsigqueueinfo
.long sys_perf_event_open
.long sys_recvmmsg
+ .long sys_setns
nr_syscalls=(.-sys_call_table)/4
diff --git a/arch/mn10300/kernel/fpu.c b/arch/mn10300/kernel/fpu.c
index bb5fa7df6c4..064fa194de2 100644
--- a/arch/mn10300/kernel/fpu.c
+++ b/arch/mn10300/kernel/fpu.c
@@ -12,7 +12,6 @@
#include <asm/fpu.h>
#include <asm/elf.h>
#include <asm/exceptions.h>
-#include <asm/system.h>
#ifdef CONFIG_LAZY_SAVE_FPU
struct task_struct *fpu_state_owner;
diff --git a/arch/mn10300/kernel/gdb-io-serial.c b/arch/mn10300/kernel/gdb-io-serial.c
index f28dc99c6f7..df51242744c 100644
--- a/arch/mn10300/kernel/gdb-io-serial.c
+++ b/arch/mn10300/kernel/gdb-io-serial.c
@@ -18,7 +18,6 @@
#include <linux/nmi.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/gdb-stub.h>
#include <asm/exceptions.h>
#include <asm/serial-regs.h>
diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c
index c859cacbb9c..caae8cac9db 100644
--- a/arch/mn10300/kernel/gdb-io-ttysm.c
+++ b/arch/mn10300/kernel/gdb-io-ttysm.c
@@ -17,7 +17,6 @@
#include <linux/init.h>
#include <linux/tty.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/gdb-stub.h>
#include <asm/exceptions.h>
#include <unit/clock.h>
diff --git a/arch/mn10300/kernel/gdb-stub.c b/arch/mn10300/kernel/gdb-stub.c
index 538266b2c9b..a128c57b586 100644
--- a/arch/mn10300/kernel/gdb-stub.c
+++ b/arch/mn10300/kernel/gdb-stub.c
@@ -130,7 +130,6 @@
#include <linux/bug.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/gdb-stub.h>
#include <asm/exceptions.h>
#include <asm/debugger.h>
@@ -798,7 +797,7 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if ((u32) mem & 1 && count >= 1) {
if (gdbstub_read_byte(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[0]);
mem++;
count--;
}
@@ -806,8 +805,8 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if ((u32) mem & 3 && count >= 2) {
if (gdbstub_read_word(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -815,10 +814,10 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
while (count >= 4) {
if (gdbstub_read_dword(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
- buf = pack_hex_byte(buf, ch[2]);
- buf = pack_hex_byte(buf, ch[3]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[2]);
+ buf = hex_byte_pack(buf, ch[3]);
mem += 4;
count -= 4;
}
@@ -826,8 +825,8 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if (count >= 2) {
if (gdbstub_read_word(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
- buf = pack_hex_byte(buf, ch[1]);
+ buf = hex_byte_pack(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[1]);
mem += 2;
count -= 2;
}
@@ -835,7 +834,7 @@ unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fault)
if (count >= 1) {
if (gdbstub_read_byte(mem, ch) != 0)
return 0;
- buf = pack_hex_byte(buf, ch[0]);
+ buf = hex_byte_pack(buf, ch[0]);
}
*buf = 0;
@@ -1273,13 +1272,13 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
ptr = mem2hex(title, ptr, sizeof(title) - 1, 0);
hx = hex_asc_hi(excep >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(excep >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(excep);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(excep);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
*ptr = 0;
@@ -1291,21 +1290,21 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
ptr = mem2hex(tbcberr, ptr, sizeof(tbcberr) - 1, 0);
hx = hex_asc_hi(bcberr >> 24);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr >> 24);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(bcberr >> 16);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr >> 16);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(bcberr >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr >> 8);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_hi(bcberr);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
hx = hex_asc_lo(bcberr);
- ptr = pack_hex_byte(ptr, hx);
+ ptr = hex_byte_pack(ptr, hx);
ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0);
*ptr = 0;
@@ -1321,12 +1320,12 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
* Send trap type (converted to signal)
*/
*ptr++ = 'T';
- ptr = pack_hex_byte(ptr, sigval);
+ ptr = hex_byte_pack(ptr, sigval);
/*
* Send Error PC
*/
- ptr = pack_hex_byte(ptr, GDB_REGID_PC);
+ ptr = hex_byte_pack(ptr, GDB_REGID_PC);
*ptr++ = ':';
ptr = mem2hex(&regs->pc, ptr, 4, 0);
*ptr++ = ';';
@@ -1334,7 +1333,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
/*
* Send frame pointer
*/
- ptr = pack_hex_byte(ptr, GDB_REGID_FP);
+ ptr = hex_byte_pack(ptr, GDB_REGID_FP);
*ptr++ = ':';
ptr = mem2hex(&regs->a3, ptr, 4, 0);
*ptr++ = ';';
@@ -1343,7 +1342,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
* Send stack pointer
*/
ssp = (unsigned long) (regs + 1);
- ptr = pack_hex_byte(ptr, GDB_REGID_SP);
+ ptr = hex_byte_pack(ptr, GDB_REGID_SP);
*ptr++ = ':';
ptr = mem2hex(&ssp, ptr, 4, 0);
*ptr++ = ';';
diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c
deleted file mode 100644
index a481b043bea..00000000000
--- a/arch/mn10300/kernel/init_task.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* MN10300 Initial task definitions
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is THREAD_SIZE aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
- { INIT_THREAD_INFO(init_task) };
-
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
index a5ac755dd69..561785581f6 100644
--- a/arch/mn10300/kernel/internal.h
+++ b/arch/mn10300/kernel/internal.h
@@ -9,18 +9,16 @@
* 2 of the Licence, or (at your option) any later version.
*/
+#include <linux/irqreturn.h>
+
struct clocksource;
struct clock_event_device;
/*
- * kthread.S
- */
-extern int kernel_thread_helper(int);
-
-/*
* entry.S
*/
extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
+extern void ret_from_kernel_thread(struct task_struct *) __attribute__((noreturn));
/*
* smp-low.S
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index 86af0d7d077..6ab3b73efcf 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -87,7 +87,7 @@ static void mn10300_cpupic_mask_ack(struct irq_data *d)
tmp2 = GxICR(irq);
irq_affinity_online[irq] =
- any_online_cpu(*d->affinity);
+ cpumask_any_and(d->affinity, cpu_online_mask);
CROSS_GxICR(irq, irq_affinity_online[irq]) =
(tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
@@ -124,7 +124,8 @@ static void mn10300_cpupic_unmask_clear(struct irq_data *d)
} else {
tmp = GxICR(irq);
- irq_affinity_online[irq] = any_online_cpu(*d->affinity);
+ irq_affinity_online[irq] = cpumask_any_and(d->affinity,
+ cpu_online_mask);
CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
}
@@ -141,57 +142,11 @@ mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
bool force)
{
unsigned long flags;
- int err;
flags = arch_local_cli_save();
-
- /* check irq no */
- switch (d->irq) {
- case TMJCIRQ:
- case RESCHEDULE_IPI:
- case CALL_FUNC_SINGLE_IPI:
- case LOCAL_TIMER_IPI:
- case FLUSH_CACHE_IPI:
- case CALL_FUNCTION_NMI_IPI:
- case DEBUGGER_NMI_IPI:
-#ifdef CONFIG_MN10300_TTYSM0
- case SC0RXIRQ:
- case SC0TXIRQ:
-#ifdef CONFIG_MN10300_TTYSM0_TIMER8
- case TM8IRQ:
-#elif CONFIG_MN10300_TTYSM0_TIMER2
- case TM2IRQ:
-#endif /* CONFIG_MN10300_TTYSM0_TIMER8 */
-#endif /* CONFIG_MN10300_TTYSM0 */
-
-#ifdef CONFIG_MN10300_TTYSM1
- case SC1RXIRQ:
- case SC1TXIRQ:
-#ifdef CONFIG_MN10300_TTYSM1_TIMER12
- case TM12IRQ:
-#elif CONFIG_MN10300_TTYSM1_TIMER9
- case TM9IRQ:
-#elif CONFIG_MN10300_TTYSM1_TIMER3
- case TM3IRQ:
-#endif /* CONFIG_MN10300_TTYSM1_TIMER12 */
-#endif /* CONFIG_MN10300_TTYSM1 */
-
-#ifdef CONFIG_MN10300_TTYSM2
- case SC2RXIRQ:
- case SC2TXIRQ:
- case TM10IRQ:
-#endif /* CONFIG_MN10300_TTYSM2 */
- err = -1;
- break;
-
- default:
- set_bit(d->irq, irq_affinity_request);
- err = 0;
- break;
- }
-
+ set_bit(d->irq, irq_affinity_request);
arch_local_irq_restore(flags);
- return err;
+ return 0;
}
#endif /* CONFIG_SMP */
@@ -259,7 +214,6 @@ void set_intr_level(int irq, u16 level)
/*
* mark an interrupt to be ACK'd after interrupt handlers have been run rather
* than before
- * - see Documentation/mn10300/features.txt
*/
void mn10300_set_lateack_irq_type(int irq)
{
@@ -366,11 +320,11 @@ void migrate_irqs(void)
if (irqd_is_per_cpu(data))
continue;
- if (cpu_isset(self, data->affinity) &&
- !cpus_intersects(irq_affinity[irq], cpu_online_map)) {
+ if (cpumask_test_cpu(self, &data->affinity) &&
+ !cpumask_intersects(&irq_affinity[irq], cpu_online_mask)) {
int cpu_id;
- cpu_id = first_cpu(cpu_online_map);
- cpu_set(cpu_id, data->affinity);
+ cpu_id = cpumask_first(cpu_online_mask);
+ cpumask_set_cpu(cpu_id, &data->affinity);
}
/* We need to operate irq_affinity_online atomically. */
arch_local_cli_save(flags);
@@ -381,7 +335,8 @@ void migrate_irqs(void)
GxICR(irq) = x & GxICR_LEVEL;
tmp = GxICR(irq);
- new = any_online_cpu(data->affinity);
+ new = cpumask_any_and(&data->affinity,
+ cpu_online_mask);
irq_affinity_online[irq] = new;
CROSS_GxICR(irq, new) =
diff --git a/arch/mn10300/kernel/kernel_execve.S b/arch/mn10300/kernel/kernel_execve.S
deleted file mode 100644
index 86039f10526..00000000000
--- a/arch/mn10300/kernel/kernel_execve.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/* MN10300 In-kernel program execution
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#include <linux/linkage.h>
-#include <asm/unistd.h>
-
-###############################################################################
-#
-# Do a system call from kernel instead of calling sys_execve so we end up with
-# proper pt_regs.
-#
-# int kernel_execve(const char *filename, char *const argv[],
-# char *const envp[])
-#
-# On entry: D0/D1/8(SP): arguments to function
-# On return: D0: syscall return.
-#
-###############################################################################
- .globl kernel_execve
- .type kernel_execve,@function
-kernel_execve:
- mov a3,a1
- mov d0,a0
- mov (12,sp),a3
- mov +__NR_execve,d0
- syscall 0
- mov a1,a3
- rets
-
- .size kernel_execve,.-kernel_execve
diff --git a/arch/mn10300/kernel/kgdb.c b/arch/mn10300/kernel/kgdb.c
index f6c981db2a3..99770823451 100644
--- a/arch/mn10300/kernel/kgdb.c
+++ b/arch/mn10300/kernel/kgdb.c
@@ -397,7 +397,7 @@ static bool kgdb_arch_undo_singlestep(struct pt_regs *regs)
* single-step state is cleared. At this point the breakpoints should have
* been removed by __switch_to().
*/
-void free_thread_info(struct thread_info *ti)
+void arch_release_thread_info(struct thread_info *ti)
{
if (kgdb_sstep_thread == ti) {
kgdb_sstep_thread = NULL;
@@ -407,7 +407,6 @@ void free_thread_info(struct thread_info *ti)
* so force immediate reentry */
kgdb_breakpoint();
}
- kfree(ti);
}
/*
diff --git a/arch/mn10300/kernel/kthread.S b/arch/mn10300/kernel/kthread.S
deleted file mode 100644
index b5ae467ac5e..00000000000
--- a/arch/mn10300/kernel/kthread.S
+++ /dev/null
@@ -1,31 +0,0 @@
-/* MN10300 Kernel thread trampoline function
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by Mark Salter (msalter@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
- .text
-
-###############################################################################
-#
-# kernel_thread_helper - trampoline for kernel_thread()
-#
-# On entry:
-# A2 = address of function to call
-# D2 = function argument
-#
-###############################################################################
- .globl kernel_thread_helper
- .type kernel_thread_helper,@function
-kernel_thread_helper:
- mov do_exit,d1
- mov d1,(sp)
- mov d1,mdr
- mov d2,d0
- jmp (a2)
-
- .size kernel_thread_helper,.-kernel_thread_helper
diff --git a/arch/mn10300/kernel/mn10300-serial-low.S b/arch/mn10300/kernel/mn10300-serial-low.S
index dfc1b6f2fa9..b95e76caf4f 100644
--- a/arch/mn10300/kernel/mn10300-serial-low.S
+++ b/arch/mn10300/kernel/mn10300-serial-low.S
@@ -118,8 +118,8 @@ ENTRY(mn10300_serial_vdma_tx_handler)
movbu d2,(e3) # ACK the interrupt
movhu (e3),d2 # flush
- btst 0x01,(__tx_break,a3) # handle transmit break request
- bne mnsc_vdma_tx_break
+ btst 0xFF,(__tx_flags,a3) # handle transmit flags
+ bne mnsc_vdma_tx_flags
movbu (SCxSTR,e2),d2 # don't try and transmit a char if the
# buffer is not empty
@@ -171,10 +171,13 @@ mnsc_vdma_tx_empty:
bset MNSCx_TX_EMPTY,(__intr_flags,a3)
bra mnsc_vdma_tx_done
-mnsc_vdma_tx_break:
+mnsc_vdma_tx_flags:
+ btst MNSCx_TX_STOP,(__tx_flags,a3)
+ bne mnsc_vdma_tx_stop
movhu (SCxCTR,e2),d2 # turn on break mode
or SC01CTR_BKE,d2
movhu d2,(SCxCTR,e2)
+mnsc_vdma_tx_stop:
mov +(NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL)|GxICR_DETECT),d2
movhu d2,(e3) # disable transmit interrupts on this
# channel
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
index 94901c56baf..7ecf69879e2 100644
--- a/arch/mn10300/kernel/mn10300-serial.c
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -36,7 +36,6 @@ static const char serial_revdate[] = "2007-11-06";
#include <linux/console.h>
#include <linux/sysrq.h>
-#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/bitops.h>
@@ -409,6 +408,34 @@ static struct irq_chip mn10300_serial_pic = {
.irq_unmask = mn10300_serial_nop,
};
+static void mn10300_serial_low_mask(struct irq_data *d)
+{
+ unsigned long flags;
+ u16 tmp;
+
+ flags = arch_local_cli_save();
+ GxICR(d->irq) = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+ tmp = GxICR(d->irq); /* flush write buffer */
+ arch_local_irq_restore(flags);
+}
+
+static void mn10300_serial_low_unmask(struct irq_data *d)
+{
+ unsigned long flags;
+ u16 tmp;
+
+ flags = arch_local_cli_save();
+ GxICR(d->irq) =
+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE;
+ tmp = GxICR(d->irq); /* flush write buffer */
+ arch_local_irq_restore(flags);
+}
+
+static struct irq_chip mn10300_serial_low_pic = {
+ .name = "mnserial-low",
+ .irq_mask = mn10300_serial_low_mask,
+ .irq_unmask = mn10300_serial_low_unmask,
+};
/*
* serial virtual DMA interrupt jump table
@@ -417,25 +444,53 @@ struct mn10300_serial_int mn10300_serial_int_tbl[NR_IRQS];
static void mn10300_serial_dis_tx_intr(struct mn10300_serial_port *port)
{
- unsigned long flags;
+ int retries = 100;
u16 x;
- flags = arch_local_cli_save();
- *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- x = *port->tx_icr;
- arch_local_irq_restore(flags);
+ /* nothing to do if irq isn't set up */
+ if (!mn10300_serial_int_tbl[port->tx_irq].port)
+ return;
+
+ port->tx_flags |= MNSCx_TX_STOP;
+ mb();
+
+ /*
+ * Here we wait for the irq to be disabled. Either it already is
+ * disabled or we wait some number of retries for the VDMA handler
+ * to disable it. The retries give the VDMA handler enough time to
+ * run to completion if it was already in progress. If the VDMA IRQ
+ * is enabled but the handler is not yet running when arrive here,
+ * the STOP flag will prevent the handler from conflicting with the
+ * driver code following this loop.
+ */
+ while ((*port->tx_icr & GxICR_ENABLE) && retries-- > 0)
+ ;
+ if (retries <= 0) {
+ *port->tx_icr =
+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+ x = *port->tx_icr;
+ }
}
static void mn10300_serial_en_tx_intr(struct mn10300_serial_port *port)
{
- unsigned long flags;
u16 x;
- flags = arch_local_cli_save();
+ /* nothing to do if irq isn't set up */
+ if (!mn10300_serial_int_tbl[port->tx_irq].port)
+ return;
+
+ /* stop vdma irq if not already stopped */
+ if (!(port->tx_flags & MNSCx_TX_STOP))
+ mn10300_serial_dis_tx_intr(port);
+
+ port->tx_flags &= ~MNSCx_TX_STOP;
+ mb();
+
*port->tx_icr =
- NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) | GxICR_ENABLE;
+ NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL) |
+ GxICR_ENABLE | GxICR_REQUEST | GxICR_DETECT;
x = *port->tx_icr;
- arch_local_irq_restore(flags);
}
static void mn10300_serial_dis_rx_intr(struct mn10300_serial_port *port)
@@ -469,7 +524,7 @@ static int mask_test_and_clear(volatile u8 *ptr, u8 mask)
static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
{
struct uart_icount *icount = &port->uart.icount;
- struct tty_struct *tty = port->uart.state->port.tty;
+ struct tty_port *tport = &port->uart.state->port;
unsigned ix;
int count;
u8 st, ch, push, status, overrun;
@@ -479,25 +534,26 @@ static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
push = 0;
count = CIRC_CNT(port->rx_inp, port->rx_outp, MNSC_BUFFER_SIZE);
- count = tty_buffer_request_room(tty, count);
+ count = tty_buffer_request_room(tport, count);
if (count == 0) {
- if (!tty->low_latency)
- tty_flip_buffer_push(tty);
+ if (!tport->low_latency)
+ tty_flip_buffer_push(tport);
return;
}
try_again:
/* pull chars out of the hat */
- ix = port->rx_outp;
- if (ix == port->rx_inp) {
- if (push && !tty->low_latency)
- tty_flip_buffer_push(tty);
+ ix = ACCESS_ONCE(port->rx_outp);
+ if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0) {
+ if (push && !tport->low_latency)
+ tty_flip_buffer_push(tport);
return;
}
+ smp_read_barrier_depends();
ch = port->rx_buffer[ix++];
st = port->rx_buffer[ix++];
- smp_rmb();
+ smp_mb();
port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
port->uart.icount.rx++;
@@ -610,19 +666,19 @@ insert:
else
flag = TTY_NORMAL;
- tty_insert_flip_char(tty, ch, flag);
+ tty_insert_flip_char(tport, ch, flag);
}
/* overrun is special, since it's reported immediately, and doesn't
* affect the current character
*/
if (overrun)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_insert_flip_char(tport, 0, TTY_OVERRUN);
count--;
if (count <= 0) {
- if (!tty->low_latency)
- tty_flip_buffer_push(tty);
+ if (!tport->low_latency)
+ tty_flip_buffer_push(tport);
return;
}
@@ -779,8 +835,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
- u16 x;
-
_enter("%s{%lu}",
port->name,
CIRC_CNT(&port->uart.state->xmit.head,
@@ -788,14 +842,7 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
UART_XMIT_SIZE));
/* kick the virtual DMA controller */
- arch_local_cli();
- x = *port->tx_icr;
- x |= GxICR_ENABLE;
-
- if (*port->_status & SC01STR_TBF)
- x &= ~(GxICR_REQUEST | GxICR_DETECT);
- else
- x |= GxICR_REQUEST | GxICR_DETECT;
+ mn10300_serial_en_tx_intr(port);
_debug("CTR=%04hx ICR=%02hx STR=%04x TMD=%02hx TBR=%04hx ICR=%04hx",
*port->_control, *port->_intr, *port->_status,
@@ -803,10 +850,6 @@ static void mn10300_serial_start_tx(struct uart_port *_port)
(port->div_timer == MNSCx_DIV_TIMER_8BIT) ?
*(volatile u8 *)port->_tmxbr : *port->_tmxbr,
*port->tx_icr);
-
- *port->tx_icr = x;
- x = *port->tx_icr;
- arch_local_sti();
}
/*
@@ -816,13 +859,17 @@ static void mn10300_serial_send_xchar(struct uart_port *_port, char ch)
{
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
+ unsigned long flags;
_enter("%s,%02x", port->name, ch);
if (likely(port->gdbstub)) {
port->tx_xchar = ch;
- if (ch)
+ if (ch) {
+ spin_lock_irqsave(&port->uart.lock, flags);
mn10300_serial_en_tx_intr(port);
+ spin_unlock_irqrestore(&port->uart.lock, flags);
+ }
}
}
@@ -883,18 +930,21 @@ static void mn10300_serial_break_ctl(struct uart_port *_port, int ctl)
{
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
+ unsigned long flags;
_enter("%s,%d", port->name, ctl);
+ spin_lock_irqsave(&port->uart.lock, flags);
if (ctl) {
/* tell the virtual DMA handler to assert BREAK */
- port->tx_break = 1;
+ port->tx_flags |= MNSCx_TX_BREAK;
mn10300_serial_en_tx_intr(port);
} else {
- port->tx_break = 0;
+ port->tx_flags &= ~MNSCx_TX_BREAK;
*port->_control &= ~SC01CTR_BKE;
mn10300_serial_en_tx_intr(port);
}
+ spin_unlock_irqrestore(&port->uart.lock, flags);
}
/*
@@ -917,6 +967,7 @@ static int mn10300_serial_startup(struct uart_port *_port)
return -ENOMEM;
port->rx_inp = port->rx_outp = 0;
+ port->tx_flags = 0;
/* finally, enable the device */
*port->_intr = SC01ICR_TI;
@@ -929,22 +980,23 @@ static int mn10300_serial_startup(struct uart_port *_port)
pint->port = port;
pint->vdma = mn10300_serial_vdma_tx_handler;
- set_intr_level(port->rx_irq,
- NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
- set_intr_level(port->tx_irq,
- NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
+ irq_set_chip(port->rx_irq, &mn10300_serial_low_pic);
+ irq_set_chip(port->tx_irq, &mn10300_serial_low_pic);
irq_set_chip(port->tm_irq, &mn10300_serial_pic);
if (request_irq(port->rx_irq, mn10300_serial_interrupt,
- IRQF_DISABLED, port->rx_name, port) < 0)
+ IRQF_NOBALANCING,
+ port->rx_name, port) < 0)
goto error;
if (request_irq(port->tx_irq, mn10300_serial_interrupt,
- IRQF_DISABLED, port->tx_name, port) < 0)
+ IRQF_NOBALANCING,
+ port->tx_name, port) < 0)
goto error2;
if (request_irq(port->tm_irq, mn10300_serial_interrupt,
- IRQF_DISABLED, port->tm_name, port) < 0)
+ IRQF_NOBALANCING,
+ port->tm_name, port) < 0)
goto error3;
mn10300_serial_mask_ack(port->tm_irq);
@@ -965,14 +1017,22 @@ error:
*/
static void mn10300_serial_shutdown(struct uart_port *_port)
{
+ unsigned long flags;
u16 x;
struct mn10300_serial_port *port =
container_of(_port, struct mn10300_serial_port, uart);
_enter("%s", port->name);
+ spin_lock_irqsave(&_port->lock, flags);
+ mn10300_serial_dis_tx_intr(port);
+
+ *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
+ x = *port->rx_icr;
+ port->tx_flags = 0;
+ spin_unlock_irqrestore(&_port->lock, flags);
+
/* disable the serial port and its baud rate timer */
- port->tx_break = 0;
*port->_control &= ~(SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
*port->_tmxmd = 0;
@@ -987,12 +1047,8 @@ static void mn10300_serial_shutdown(struct uart_port *_port)
free_irq(port->rx_irq, port);
free_irq(port->tx_irq, port);
- arch_local_cli();
- *port->rx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- x = *port->rx_icr;
- *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- x = *port->tx_icr;
- arch_local_sti();
+ mn10300_serial_int_tbl[port->tx_irq].port = NULL;
+ mn10300_serial_int_tbl[port->rx_irq].port = NULL;
}
/*
@@ -1318,7 +1374,8 @@ timer_okay:
if ((new->c_cflag & CREAD) == 0)
port->uart.ignore_status_mask |= (1 << TTY_NORMAL);
- scxctr |= *port->_control & (SC01CTR_TXE | SC01CTR_RXE | SC01CTR_BKE);
+ scxctr |= SC01CTR_TXE | SC01CTR_RXE;
+ scxctr |= *port->_control & SC01CTR_BKE;
*port->_control = scxctr;
spin_unlock_irqrestore(&port->uart.lock, flags);
@@ -1520,17 +1577,24 @@ static void mn10300_serial_console_write(struct console *co,
{
struct mn10300_serial_port *port;
unsigned i;
- u16 scxctr, txicr, tmp;
+ u16 scxctr;
u8 tmxmd;
+ unsigned long flags;
+ int locked = 1;
port = mn10300_serial_ports[co->index];
+ local_irq_save(flags);
+ if (port->uart.sysrq) {
+ /* mn10300_serial_interrupt() already took the lock */
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&port->uart.lock);
+ } else
+ spin_lock(&port->uart.lock);
+
/* firstly hijack the serial port from the "virtual DMA" controller */
- arch_local_cli();
- txicr = *port->tx_icr;
- *port->tx_icr = NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL);
- tmp = *port->tx_icr;
- arch_local_sti();
+ mn10300_serial_dis_tx_intr(port);
/* the transmitter may be disabled */
scxctr = *port->_control;
@@ -1566,12 +1630,12 @@ static void mn10300_serial_console_write(struct console *co,
while (*port->_status & SC01STR_TBF)
continue;
- *(u8 *) port->_txb = ch;
+ *port->_txb = ch;
if (ch == 0x0a) {
while (*port->_status & SC01STR_TBF)
continue;
- *(u8 *) port->_txb = 0xd;
+ *port->_txb = 0xd;
}
}
@@ -1584,10 +1648,11 @@ static void mn10300_serial_console_write(struct console *co,
if (!(scxctr & SC01CTR_TXE))
*port->_control = scxctr;
- arch_local_cli();
- *port->tx_icr = txicr;
- tmp = *port->tx_icr;
- arch_local_sti();
+ mn10300_serial_en_tx_intr(port);
+
+ if (locked)
+ spin_unlock(&port->uart.lock);
+ local_irq_restore(flags);
}
/*
@@ -1656,18 +1721,29 @@ static int mn10300_serial_poll_get_char(struct uart_port *_port)
_enter("%s", port->name);
- do {
- /* pull chars out of the hat */
- ix = port->rx_outp;
- if (ix == port->rx_inp)
- return NO_POLL_CHAR;
+ if (mn10300_serial_int_tbl[port->rx_irq].port != NULL) {
+ do {
+ /* pull chars out of the hat */
+ ix = ACCESS_ONCE(port->rx_outp);
+ if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0)
+ return NO_POLL_CHAR;
- ch = port->rx_buffer[ix++];
- st = port->rx_buffer[ix++];
- smp_rmb();
- port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
+ smp_read_barrier_depends();
+ ch = port->rx_buffer[ix++];
+ st = port->rx_buffer[ix++];
+ smp_mb();
+ port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
- } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
+ } while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
+ } else {
+ do {
+ st = *port->_status;
+ if (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF))
+ continue;
+ } while (!(st & SC01STR_RBF));
+
+ ch = *port->_rxb;
+ }
return ch;
}
@@ -1694,12 +1770,12 @@ static void mn10300_serial_poll_put_char(struct uart_port *_port,
tmp = *port->_intr;
if (ch == 0x0a) {
- *(u8 *) port->_txb = 0x0d;
+ *port->_txb = 0x0d;
while (*port->_status & SC01STR_TBF)
continue;
}
- *(u8 *) port->_txb = ch;
+ *port->_txb = ch;
while (*port->_status & SC01STR_TBF)
continue;
diff --git a/arch/mn10300/kernel/mn10300-serial.h b/arch/mn10300/kernel/mn10300-serial.h
index 6796499bf78..01791c68ea1 100644
--- a/arch/mn10300/kernel/mn10300-serial.h
+++ b/arch/mn10300/kernel/mn10300-serial.h
@@ -29,6 +29,10 @@
#define MNSCx_TX_SPACE 0x04
#define MNSCx_TX_EMPTY 0x08
+/* tx_flags bits */
+#define MNSCx_TX_BREAK 0x01
+#define MNSCx_TX_STOP 0x02
+
#ifndef __ASSEMBLY__
struct mn10300_serial_port {
@@ -36,7 +40,7 @@ struct mn10300_serial_port {
unsigned rx_inp; /* pointer to rx input offset */
unsigned rx_outp; /* pointer to rx output offset */
u8 tx_xchar; /* high-priority XON/XOFF buffer */
- u8 tx_break; /* transmit break request */
+ u8 tx_flags; /* transmit break/stop request */
u8 intr_flags; /* interrupt flags */
volatile u16 *rx_icr; /* Rx interrupt control register */
volatile u16 *tx_icr; /* Tx interrupt control register */
@@ -54,8 +58,8 @@ struct mn10300_serial_port {
volatile u16 *_control; /* control register pointer */
volatile u8 *_status; /* status register pointer */
volatile u8 *_intr; /* interrupt register pointer */
- volatile void *_rxb; /* receive buffer register pointer */
- volatile void *_txb; /* transmit buffer register pointer */
+ volatile u8 *_rxb; /* receive buffer register pointer */
+ volatile u8 *_txb; /* transmit buffer register pointer */
volatile u16 *_tmicr; /* timer interrupt control register */
volatile u8 *_tmxmd; /* baud rate timer mode register */
volatile u16 *_tmxbr; /* baud rate timer base register */
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
index c5e12bfd9fc..a2d8e6938d6 100644
--- a/arch/mn10300/kernel/mn10300-watchdog.c
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -18,8 +18,7 @@
#include <linux/kernel_stat.h>
#include <linux/nmi.h>
#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/intctl-regs.h>
#include <asm/rtc-regs.h>
#include <asm/div64.h>
@@ -143,7 +142,7 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
NMICR = NMICR_WDIF;
nmi_count(smp_processor_id())++;
- kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+ kstat_incr_irq_this_cpu(irq);
for_each_online_cpu(cpu) {
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c
index 196a111e2e2..216ad23c957 100644
--- a/arch/mn10300/kernel/module.c
+++ b/arch/mn10300/kernel/module.c
@@ -32,36 +32,6 @@
#define DEBUGP(fmt, ...)
#endif
-/*
- * allocate storage for a module
- */
-void *module_alloc(unsigned long size)
-{
- if (size == 0)
- return NULL;
- return vmalloc_exec(size);
-}
-
-/*
- * free memory returned from module_alloc()
- */
-void module_free(struct module *mod, void *module_region)
-{
- vfree(module_region);
-}
-
-/*
- * allow the arch to fix up the section table
- * - we don't need anything special
- */
-int module_frob_arch_sections(Elf_Ehdr *hdr,
- Elf_Shdr *sechdrs,
- char *secstrings,
- struct module *mod)
-{
- return 0;
-}
-
static void reloc_put16(uint8_t *p, uint32_t val)
{
p[0] = val & 0xff;
@@ -81,20 +51,6 @@ static void reloc_put32(uint8_t *p, uint32_t val)
}
/*
- * apply a REL relocation
- */
-int apply_relocate(Elf32_Shdr *sechdrs,
- const char *strtab,
- unsigned int symindex,
- unsigned int relsec,
- struct module *me)
-{
- printk(KERN_ERR "module %s: RELOCATION unsupported\n",
- me->name);
- return -ENOEXEC;
-}
-
-/*
* apply a RELA relocation
*/
int apply_relocate_add(Elf32_Shdr *sechdrs,
@@ -198,20 +154,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
}
return 0;
}
-
-/*
- * finish loading the module
- */
-int module_finalize(const Elf_Ehdr *hdr,
- const Elf_Shdr *sechdrs,
- struct module *me)
-{
- return 0;
-}
-
-/*
- * finish clearing the module
- */
-void module_arch_cleanup(struct module *mod)
-{
-}
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index 28eec310253..3707da583d0 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -25,9 +25,9 @@
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/slab.h>
+#include <linux/rcupdate.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/mmu_context.h>
@@ -37,12 +37,6 @@
#include "internal.h"
/*
- * power management idle function, if any..
- */
-void (*pm_idle)(void);
-EXPORT_SYMBOL(pm_idle);
-
-/*
* return saved PC of a blocked thread.
*/
unsigned long thread_saved_pc(struct task_struct *tsk)
@@ -56,78 +50,19 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
-#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
-/*
- * we use this if we don't have any better idle routine
- */
-static void default_idle(void)
-{
- local_irq_disable();
- if (!need_resched())
- safe_halt();
- else
- local_irq_enable();
-}
-
-#else /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */
/*
* On SMP it's slightly faster (but much more power-consuming!)
* to poll the ->work.need_resched flag instead of waiting for the
* cross-CPU IPI to arrive. Use this option with caution.
+ *
+ * tglx: No idea why this depends on HOTPLUG_CPU !?!
*/
-static inline void poll_idle(void)
-{
- int oldval;
-
- local_irq_enable();
-
- /*
- * Deal with another CPU just having chosen a thread to
- * run here:
- */
- oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
-
- if (!oldval) {
- set_thread_flag(TIF_POLLING_NRFLAG);
- while (!need_resched())
- cpu_relax();
- clear_thread_flag(TIF_POLLING_NRFLAG);
- } else {
- set_need_resched();
- }
-}
-#endif /* !CONFIG_SMP || CONFIG_HOTPLUG_CPU */
-
-/*
- * the idle thread
- * - there's no useful work to be done, so just try to conserve power and have
- * a low exit latency (ie sit in a loop waiting for somebody to say that
- * they'd like to reschedule)
- */
-void cpu_idle(void)
+#if !defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
+void arch_cpu_idle(void)
{
- /* endless idle loop with no priority at all */
- for (;;) {
- while (!need_resched()) {
- void (*idle)(void);
-
- smp_rmb();
- idle = pm_idle;
- if (!idle) {
-#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
- idle = poll_idle;
-#else /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */
- idle = default_idle;
-#endif /* CONFIG_SMP && !CONFIG_HOTPLUG_CPU */
- }
- idle();
- }
-
- preempt_enable_no_resched();
- schedule();
- preempt_disable();
- }
+ safe_halt();
}
+#endif
void release_segments(struct mm_struct *mm)
{
@@ -162,30 +97,10 @@ void machine_power_off(void)
void show_regs(struct pt_regs *regs)
{
+ show_regs_print_info(KERN_DEFAULT);
}
/*
- * create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
- struct pt_regs regs;
-
- memset(&regs, 0, sizeof(regs));
-
- regs.a2 = (unsigned long) fn;
- regs.d2 = (unsigned long) arg;
- regs.pc = (unsigned long) kernel_thread_helper;
- local_save_flags(regs.epsw);
- regs.epsw |= EPSW_IE | EPSW_IM_7;
-
- /* Ok, create the new process.. */
- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0,
- NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
* free current thread data structures etc..
*/
void exit_thread(void)
@@ -211,12 +126,14 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
}
/*
- * this gets called before we allocate a new thread and copy the current task
- * into it so that we can store lazy state into memory
+ * this gets called so that we can store lazy state into memory and copy the
+ * current task into the new thread.
*/
-void prepare_to_copy(struct task_struct *tsk)
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
- unlazy_fpu(tsk);
+ unlazy_fpu(src);
+ *dst = *src;
+ return 0;
}
/*
@@ -225,95 +142,48 @@ void prepare_to_copy(struct task_struct *tsk)
*/
int copy_thread(unsigned long clone_flags,
unsigned long c_usp, unsigned long ustk_size,
- struct task_struct *p, struct pt_regs *kregs)
+ struct task_struct *p)
{
struct thread_info *ti = task_thread_info(p);
- struct pt_regs *c_uregs, *c_kregs, *uregs;
+ struct pt_regs *c_regs;
unsigned long c_ksp;
- uregs = current->thread.uregs;
-
c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
/* allocate the userspace exception frame and set it up */
c_ksp -= sizeof(struct pt_regs);
- c_uregs = (struct pt_regs *) c_ksp;
-
- p->thread.uregs = c_uregs;
- *c_uregs = *uregs;
- c_uregs->sp = c_usp;
- c_uregs->epsw &= ~EPSW_FE; /* my FPU */
-
+ c_regs = (struct pt_regs *) c_ksp;
c_ksp -= 12; /* allocate function call ABI slack */
- /* the new TLS pointer is passed in as arg #5 to sys_clone() */
- if (clone_flags & CLONE_SETTLS)
- c_uregs->e2 = current_frame()->d3;
-
- /* set up the return kernel frame if called from kernel_thread() */
- c_kregs = c_uregs;
- if (kregs != uregs) {
- c_ksp -= sizeof(struct pt_regs);
- c_kregs = (struct pt_regs *) c_ksp;
- *c_kregs = *kregs;
- c_kregs->sp = c_usp;
- c_kregs->next = c_uregs;
-#ifdef CONFIG_MN10300_CURRENT_IN_E2
- c_kregs->e2 = (unsigned long) p; /* current */
-#endif
-
- c_ksp -= 12; /* allocate function call ABI slack */
- }
-
/* set up things up so the scheduler can start the new task */
- ti->frame = c_kregs;
- p->thread.a3 = (unsigned long) c_kregs;
+ p->thread.uregs = c_regs;
+ ti->frame = c_regs;
+ p->thread.a3 = (unsigned long) c_regs;
p->thread.sp = c_ksp;
- p->thread.pc = (unsigned long) ret_from_fork;
- p->thread.wchan = (unsigned long) ret_from_fork;
+ p->thread.wchan = p->thread.pc;
p->thread.usp = c_usp;
- return 0;
-}
-
-/*
- * clone a process
- * - tlsptr is retrieved by copy_thread() from current_frame()->d3
- */
-asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
- int __user *parent_tidptr, int __user *child_tidptr,
- int __user *tlsptr)
-{
- return do_fork(clone_flags, newsp ?: current_frame()->sp,
- current_frame(), 0, parent_tidptr, child_tidptr);
-}
-
-asmlinkage long sys_fork(void)
-{
- return do_fork(SIGCHLD, current_frame()->sp,
- current_frame(), 0, NULL, NULL);
-}
+ if (unlikely(p->flags & PF_KTHREAD)) {
+ memset(c_regs, 0, sizeof(struct pt_regs));
+ c_regs->a0 = c_usp; /* function */
+ c_regs->d0 = ustk_size; /* argument */
+ local_save_flags(c_regs->epsw);
+ c_regs->epsw |= EPSW_IE | EPSW_IM_7;
+ p->thread.pc = (unsigned long) ret_from_kernel_thread;
+ return 0;
+ }
+ *c_regs = *current_pt_regs();
+ if (c_usp)
+ c_regs->sp = c_usp;
+ c_regs->epsw &= ~EPSW_FE; /* my FPU */
-asmlinkage long sys_vfork(void)
-{
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
- current_frame(), 0, NULL, NULL);
-}
+ /* the new TLS pointer is passed in as arg #5 to sys_clone() */
+ if (clone_flags & CLONE_SETTLS)
+ c_regs->e2 = current_frame()->d3;
-asmlinkage long sys_execve(const char __user *name,
- const char __user *const __user *argv,
- const char __user *const __user *envp)
-{
- char *filename;
- int error;
+ p->thread.pc = (unsigned long) ret_from_fork;
- filename = getname(name);
- error = PTR_ERR(filename);
- if (IS_ERR(filename))
- return error;
- error = do_execve(filename, argv, envp, current_frame());
- putname(filename);
- return error;
+ return 0;
}
unsigned long get_wchan(struct task_struct *p)
diff --git a/arch/mn10300/kernel/ptrace.c b/arch/mn10300/kernel/ptrace.c
index 5c0b07e6100..5bd58514e73 100644
--- a/arch/mn10300/kernel/ptrace.c
+++ b/arch/mn10300/kernel/ptrace.c
@@ -21,7 +21,6 @@
#include <linux/tracehook.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-#include <asm/system.h>
#include <asm/processor.h>
#include <asm/cacheflush.h>
#include <asm/fpu.h>
diff --git a/arch/mn10300/kernel/setup.c b/arch/mn10300/kernel/setup.c
index 9e7a3209a3e..2ad7f32fa12 100644
--- a/arch/mn10300/kernel/setup.c
+++ b/arch/mn10300/kernel/setup.c
@@ -26,7 +26,6 @@
#include <asm/processor.h>
#include <linux/console.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -36,9 +35,7 @@
struct mn10300_cpuinfo boot_cpu_data;
-/* For PCI or other memory-mapped resources */
-unsigned long pci_mem_start = 0x18000000;
-
+static char __initdata cmd_line[COMMAND_LINE_SIZE];
char redboot_command_line[COMMAND_LINE_SIZE] =
"console=ttyS0,115200 root=/dev/mtdblock3 rw";
@@ -75,45 +72,19 @@ static const char *const mn10300_cputypes[] = {
};
/*
- *
+ * Pick out the memory size. We look for mem=size,
+ * where size is "size[KkMm]"
*/
-static void __init parse_mem_cmdline(char **cmdline_p)
+static int __init early_mem(char *p)
{
- char *from, *to, c;
-
- /* save unparsed command line copy for /proc/cmdline */
- strcpy(boot_command_line, redboot_command_line);
-
- /* see if there's an explicit memory size option */
- from = redboot_command_line;
- to = redboot_command_line;
- c = ' ';
-
- for (;;) {
- if (c == ' ' && !memcmp(from, "mem=", 4)) {
- if (to != redboot_command_line)
- to--;
- memory_size = memparse(from + 4, &from);
- }
-
- c = *(from++);
- if (!c)
- break;
-
- *(to++) = c;
- }
-
- *to = '\0';
- *cmdline_p = redboot_command_line;
+ memory_size = memparse(p, &p);
if (memory_size == 0)
panic("Memory size not known\n");
- memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS +
- memory_size;
- if (memory_end > phys_memory_end)
- memory_end = phys_memory_end;
+ return 0;
}
+early_param("mem", early_mem);
/*
* architecture specific setup
@@ -126,7 +97,20 @@ void __init setup_arch(char **cmdline_p)
cpu_init();
unit_setup();
smp_init_cpus();
- parse_mem_cmdline(cmdline_p);
+
+ /* save unparsed command line copy for /proc/cmdline */
+ strlcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE);
+
+ /* populate cmd_line too for later use, preserving boot_command_line */
+ strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = cmd_line;
+
+ parse_early_param();
+
+ memory_end = (unsigned long) CONFIG_KERNEL_RAM_BASE_ADDRESS +
+ memory_size;
+ if (memory_end > phys_memory_end)
+ memory_end = phys_memory_end;
init_mm.start_code = (unsigned long)&_text;
init_mm.end_code = (unsigned long) &_etext;
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
index 690f4e9507d..9dfac5cd16e 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -31,69 +31,6 @@
#define DEBUG_SIG 0
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
-{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- set_thread_flag(TIF_RESTORE_SIGMASK);
- return -ERESTARTNOHAND;
-}
-
-/*
- * set signal action syscall
- */
-asmlinkage long sys_sigaction(int sig,
- const struct old_sigaction __user *act,
- struct old_sigaction __user *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
- __get_user(mask, &act->sa_mask))
- return -EFAULT;
- siginitset(&new_ka.sa.sa_mask, mask);
- }
-
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
- if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
- return -EFAULT;
- }
-
- return ret;
-}
-
-/*
- * set alternate signal stack syscall
- */
-asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
-{
- return do_sigaltstack(uss, uoss, current_frame()->sp);
-}
-
/*
* do a signal return; undo the signal stack.
*/
@@ -171,11 +108,7 @@ asmlinkage long sys_sigreturn(void)
sizeof(frame->extramask)))
goto badframe;
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(current_frame(), &frame->sc, &d0))
goto badframe;
@@ -202,17 +135,12 @@ asmlinkage long sys_rt_sigreturn(void)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
goto badframe;
- if (do_sigaltstack(&frame->uc.uc_stack, NULL, current_frame()->sp) ==
- -EFAULT)
+ if (restore_altstack(&frame->uc.uc_stack))
goto badframe;
return d0;
@@ -335,10 +263,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
regs->d0 = sig;
regs->d1 = (unsigned long) &frame->sc;
- /* the tracer may want to single-step inside the handler */
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-
#if DEBUG_SIG
printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
sig, current->comm, current->pid, frame, regs->pc,
@@ -381,9 +305,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* create the ucontext. */
if (__put_user(0, &frame->uc.uc_flags) ||
__put_user(0, &frame->uc.uc_link) ||
- __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
- __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
- __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size) ||
+ __save_altstack(&frame->uc.uc_stack, regs->sp) ||
setup_sigcontext(&frame->uc.uc_mcontext,
&frame->fpuctx, regs, set->sig[0]) ||
__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
@@ -416,10 +338,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->d0 = sig;
regs->d1 = (long) &frame->info;
- /* the tracer may want to single-step inside the handler */
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-
#if DEBUG_SIG
printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
sig, current->comm, current->pid, frame, regs->pc,
@@ -444,8 +362,9 @@ static inline void stepback(struct pt_regs *regs)
*/
static int handle_signal(int sig,
siginfo_t *info, struct k_sigaction *ka,
- sigset_t *oldset, struct pt_regs *regs)
+ struct pt_regs *regs)
{
+ sigset_t *oldset = sigmask_to_save();
int ret;
/* Are we from a system call? */
@@ -475,18 +394,12 @@ static int handle_signal(int sig,
ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
ret = setup_frame(sig, ka, oldset, regs);
+ if (ret)
+ return ret;
- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
-
- return ret;
+ signal_delivered(sig, info, ka, regs,
+ test_thread_flag(TIF_SINGLESTEP));
+ return 0;
}
/*
@@ -496,31 +409,11 @@ static void do_signal(struct pt_regs *regs)
{
struct k_sigaction ka;
siginfo_t info;
- sigset_t *oldset;
int signr;
- /* we want the common case to go fast, which is why we may in certain
- * cases get here from kernel mode */
- if (!user_mode(regs))
- return;
-
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- oldset = &current->saved_sigmask;
- else
- oldset = &current->blocked;
-
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
- if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
- /* a signal was successfully delivered; the saved
- * sigmask will have been stored in the signal frame,
- * and will be restored by sigreturn, so we can simply
- * clear the TIF_RESTORE_SIGMASK flag */
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- clear_thread_flag(TIF_RESTORE_SIGMASK);
-
- tracehook_signal_handler(signr, &info, &ka, regs,
- test_thread_flag(TIF_SINGLESTEP));
+ if (handle_signal(signr, &info, &ka, regs) == 0) {
}
return;
@@ -546,10 +439,7 @@ static void do_signal(struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask
* back */
- if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- clear_thread_flag(TIF_RESTORE_SIGMASK);
- sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
- }
+ restore_saved_sigmask();
}
/*
@@ -569,13 +459,11 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
}
/* deal with pending signal delivery */
- if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs);
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(current_frame());
- if (current->replacement_session_keyring)
- key_replace_session_keyring();
}
}
diff --git a/arch/mn10300/kernel/smp-low.S b/arch/mn10300/kernel/smp-low.S
index 72938cefc05..71f1b2faaa0 100644
--- a/arch/mn10300/kernel/smp-low.S
+++ b/arch/mn10300/kernel/smp-low.S
@@ -13,9 +13,9 @@
#include <linux/sys.h>
#include <linux/linkage.h>
#include <asm/smp.h>
-#include <asm/system.h>
#include <asm/thread_info.h>
#include <asm/cpu-regs.h>
+#include <asm/intctl-regs.h>
#include <proc/smp-regs.h>
#include <asm/asm-offsets.h>
#include <asm/frame.inc>
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c
index 226c826a219..f984193718b 100644
--- a/arch/mn10300/kernel/smp.c
+++ b/arch/mn10300/kernel/smp.c
@@ -24,8 +24,8 @@
#include <linux/sched.h>
#include <linux/profile.h>
#include <linux/smp.h>
+#include <linux/cpu.h>
#include <asm/tlbflush.h>
-#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/processor.h>
#include <asm/bug.h>
@@ -39,7 +39,6 @@
#include "internal.h"
#ifdef CONFIG_HOTPLUG_CPU
-#include <linux/cpu.h>
#include <asm/cacheflush.h>
static unsigned long sleep_mode[NR_CPUS];
@@ -131,10 +130,12 @@ static irqreturn_t smp_call_function_interrupt(int irq, void *dev_id);
static struct irqaction reschedule_ipi = {
.handler = smp_reschedule_interrupt,
+ .flags = IRQF_NOBALANCING,
.name = "smp reschedule IPI"
};
static struct irqaction call_function_ipi = {
.handler = smp_call_function_interrupt,
+ .flags = IRQF_NOBALANCING,
.name = "smp call function IPI"
};
@@ -142,7 +143,7 @@ static struct irqaction call_function_ipi = {
static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id);
static struct irqaction local_timer_ipi = {
.handler = smp_ipi_timer_interrupt,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_NOBALANCING,
.name = "smp local timer IPI"
};
#endif
@@ -181,6 +182,7 @@ static void init_ipi(void)
#ifdef CONFIG_MN10300_CACHE_ENABLED
/* set up the cache flush IPI */
+ irq_set_chip(FLUSH_CACHE_IPI, &mn10300_ipi_type);
flags = arch_local_cli_save();
__set_intr_stub(NUM2EXCEP_IRQ_LEVEL(FLUSH_CACHE_GxICR_LV),
mn10300_low_ipi_handler);
@@ -190,6 +192,7 @@ static void init_ipi(void)
#endif
/* set up the NMI call function IPI */
+ irq_set_chip(CALL_FUNCTION_NMI_IPI, &mn10300_ipi_type);
flags = arch_local_cli_save();
GxICR(CALL_FUNCTION_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
tmp16 = GxICR(CALL_FUNCTION_NMI_IPI);
@@ -200,6 +203,10 @@ static void init_ipi(void)
__set_intr_stub(NUM2EXCEP_IRQ_LEVEL(SMP_BOOT_GxICR_LV),
mn10300_low_ipi_handler);
arch_local_irq_restore(flags);
+
+#ifdef CONFIG_KERNEL_DEBUGGER
+ irq_set_chip(DEBUGGER_NMI_IPI, &mn10300_ipi_type);
+#endif
}
/**
@@ -309,7 +316,7 @@ static void send_IPI_mask(const cpumask_t *cpumask, int irq)
u16 tmp;
for (i = 0; i < NR_CPUS; i++) {
- if (cpu_isset(i, *cpumask)) {
+ if (cpumask_test_cpu(i, cpumask)) {
/* send IPI */
tmp = CROSS_GxICR(irq, i);
CROSS_GxICR(irq, i) =
@@ -342,8 +349,8 @@ void send_IPI_allbutself(int irq)
{
cpumask_t cpumask;
- cpumask = cpu_online_map;
- cpu_clear(smp_processor_id(), cpumask);
+ cpumask_copy(&cpumask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &cpumask);
send_IPI_mask(&cpumask, irq);
}
@@ -393,8 +400,8 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait)
data.func = func;
data.info = info;
- data.started = cpu_online_map;
- cpu_clear(smp_processor_id(), data.started);
+ cpumask_copy(&data.started, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &data.started);
data.wait = wait;
if (wait)
data.finished = data.started;
@@ -410,14 +417,14 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait)
if (CALL_FUNCTION_NMI_IPI_TIMEOUT > 0) {
for (cnt = 0;
cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT &&
- !cpus_empty(data.started);
+ !cpumask_empty(&data.started);
cnt++)
mdelay(1);
if (wait && cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT) {
for (cnt = 0;
cnt < CALL_FUNCTION_NMI_IPI_TIMEOUT &&
- !cpus_empty(data.finished);
+ !cpumask_empty(&data.finished);
cnt++)
mdelay(1);
}
@@ -428,10 +435,10 @@ int smp_nmi_call_function(smp_call_func_t func, void *info, int wait)
} else {
/* If timeout value is zero, wait until cpumask has been
* cleared */
- while (!cpus_empty(data.started))
+ while (!cpumask_empty(&data.started))
barrier();
if (wait)
- while (!cpus_empty(data.finished))
+ while (!cpumask_empty(&data.finished))
barrier();
}
@@ -472,12 +479,12 @@ void stop_this_cpu(void *unused)
#endif /* CONFIG_GDBSTUB */
flags = arch_local_cli_save();
- cpu_clear(smp_processor_id(), cpu_online_map);
+ set_cpu_online(smp_processor_id(), false);
while (!stopflag)
cpu_relax();
- cpu_set(smp_processor_id(), cpu_online_map);
+ set_cpu_online(smp_processor_id(), true);
arch_local_irq_restore(flags);
}
@@ -494,14 +501,11 @@ void smp_send_stop(void)
* @irq: The interrupt number.
* @dev_id: The device ID.
*
- * We need do nothing here, since the scheduling will be effected on our way
- * back through entry.S.
- *
* Returns IRQ_HANDLED to indicate we handled the interrupt successfully.
*/
static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id)
{
- /* do nothing */
+ scheduler_ipi();
return IRQ_HANDLED;
}
@@ -532,12 +536,13 @@ void smp_nmi_call_function_interrupt(void)
* execute the function
*/
smp_mb();
- cpu_clear(smp_processor_id(), nmi_call_data->started);
+ cpumask_clear_cpu(smp_processor_id(), &nmi_call_data->started);
(*func)(info);
if (wait) {
smp_mb();
- cpu_clear(smp_processor_id(), nmi_call_data->finished);
+ cpumask_clear_cpu(smp_processor_id(),
+ &nmi_call_data->finished);
}
}
@@ -660,7 +665,7 @@ int __init start_secondary(void *unused)
{
smp_cpu_init();
smp_callin();
- while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
+ while (!cpumask_test_cpu(smp_processor_id(), &smp_commenced_mask))
cpu_relax();
local_flush_tlb();
@@ -670,7 +675,7 @@ int __init start_secondary(void *unused)
#ifdef CONFIG_GENERIC_CLOCKEVENTS
init_clockevents();
#endif
- cpu_idle();
+ cpu_startup_entry(CPUHP_ONLINE);
return 0;
}
@@ -783,13 +788,14 @@ static int __init do_boot_cpu(int phy_id)
if (send_status == 0) {
/* Allow AP to start initializing */
- cpu_set(cpu_id, cpu_callout_map);
+ cpumask_set_cpu(cpu_id, &cpu_callout_map);
/* Wait for setting cpu_callin_map */
timeout = 0;
do {
udelay(1000);
- callin_status = cpu_isset(cpu_id, cpu_callin_map);
+ callin_status = cpumask_test_cpu(cpu_id,
+ &cpu_callin_map);
} while (callin_status == 0 && timeout++ < 5000);
if (callin_status == 0)
@@ -799,9 +805,9 @@ static int __init do_boot_cpu(int phy_id)
}
if (send_status == GxICR_REQUEST || callin_status == 0) {
- cpu_clear(cpu_id, cpu_callout_map);
- cpu_clear(cpu_id, cpu_callin_map);
- cpu_clear(cpu_id, cpu_initialized);
+ cpumask_clear_cpu(cpu_id, &cpu_callout_map);
+ cpumask_clear_cpu(cpu_id, &cpu_callin_map);
+ cpumask_clear_cpu(cpu_id, &cpu_initialized);
cpucount--;
return 1;
}
@@ -836,7 +842,7 @@ static void __init smp_callin(void)
cpu = smp_processor_id();
timeout = jiffies + (2 * HZ);
- if (cpu_isset(cpu, cpu_callin_map)) {
+ if (cpumask_test_cpu(cpu, &cpu_callin_map)) {
printk(KERN_ERR "CPU#%d already present.\n", cpu);
BUG();
}
@@ -844,7 +850,7 @@ static void __init smp_callin(void)
/* Wait for AP startup 2s total */
while (time_before(jiffies, timeout)) {
- if (cpu_isset(cpu, cpu_callout_map))
+ if (cpumask_test_cpu(cpu, &cpu_callout_map))
break;
cpu_relax();
}
@@ -864,11 +870,11 @@ static void __init smp_callin(void)
smp_store_cpu_info(cpu);
/* Allow the boot processor to continue */
- cpu_set(cpu, cpu_callin_map);
+ cpumask_set_cpu(cpu, &cpu_callin_map);
}
/**
- * smp_online - Set cpu_online_map
+ * smp_online - Set cpu_online_mask
*/
static void __init smp_online(void)
{
@@ -876,10 +882,11 @@ static void __init smp_online(void)
cpu = smp_processor_id();
- local_irq_enable();
+ notify_cpu_starting(cpu);
- cpu_set(cpu, cpu_online_map);
- smp_wmb();
+ set_cpu_online(cpu, true);
+
+ local_irq_enable();
}
/**
@@ -895,13 +902,13 @@ void __init smp_cpus_done(unsigned int max_cpus)
/*
* smp_prepare_boot_cpu - Set up stuff for the boot processor.
*
- * Set up the cpu_online_map, cpu_callout_map and cpu_callin_map of the boot
+ * Set up the cpu_online_mask, cpu_callout_map and cpu_callin_map of the boot
* processor (CPU 0).
*/
-void __devinit smp_prepare_boot_cpu(void)
+void smp_prepare_boot_cpu(void)
{
- cpu_set(0, cpu_callout_map);
- cpu_set(0, cpu_callin_map);
+ cpumask_set_cpu(0, &cpu_callout_map);
+ cpumask_set_cpu(0, &cpu_callin_map);
current_thread_info()->cpu = 0;
}
@@ -923,27 +930,25 @@ void initialize_secondary(void)
* __cpu_up - Set smp_commenced_mask for the nominated CPU
* @cpu: The target CPU.
*/
-int __devinit __cpu_up(unsigned int cpu)
+int __cpu_up(unsigned int cpu, struct task_struct *tidle)
{
int timeout;
#ifdef CONFIG_HOTPLUG_CPU
- if (num_online_cpus() == 1)
- disable_hlt();
if (sleep_mode[cpu])
run_wakeup_cpu(cpu);
#endif /* CONFIG_HOTPLUG_CPU */
- cpu_set(cpu, smp_commenced_mask);
+ cpumask_set_cpu(cpu, &smp_commenced_mask);
/* Wait 5s total for a response */
for (timeout = 0 ; timeout < 5000 ; timeout++) {
- if (cpu_isset(cpu, cpu_online_map))
+ if (cpu_online(cpu))
break;
udelay(1000);
}
- BUG_ON(!cpu_isset(cpu, cpu_online_map));
+ BUG_ON(!cpu_online(cpu));
return 0;
}
@@ -989,16 +994,13 @@ int __cpu_disable(void)
return -EBUSY;
migrate_irqs();
- cpu_clear(cpu, current->active_mm->cpu_vm_mask);
+ cpumask_clear_cpu(cpu, &mm_cpumask(current->active_mm));
return 0;
}
void __cpu_die(unsigned int cpu)
{
run_sleep_cpu(cpu);
-
- if (num_online_cpus() == 1)
- enable_hlt();
}
#ifdef CONFIG_MN10300_CACHE_ENABLED
@@ -1094,13 +1096,13 @@ static int hotplug_cpu_nmi_call_function(cpumask_t cpumask,
do {
mn10300_local_dcache_inv_range(start, end);
barrier();
- } while (!cpus_empty(nmi_call_func_mask_data.started));
+ } while (!cpumask_empty(&nmi_call_func_mask_data.started));
if (wait) {
do {
mn10300_local_dcache_inv_range(start, end);
barrier();
- } while (!cpus_empty(nmi_call_func_mask_data.finished));
+ } while (!cpumask_empty(&nmi_call_func_mask_data.finished));
}
spin_unlock(&smp_nmi_call_lock);
@@ -1111,9 +1113,9 @@ static void restart_wakeup_cpu(void)
{
unsigned int cpu = smp_processor_id();
- cpu_set(cpu, cpu_callin_map);
+ cpumask_set_cpu(cpu, &cpu_callin_map);
local_flush_tlb();
- cpu_set(cpu, cpu_online_map);
+ set_cpu_online(cpu, true);
smp_wmb();
}
@@ -1144,8 +1146,9 @@ static void sleep_cpu(void *unused)
static void run_sleep_cpu(unsigned int cpu)
{
unsigned long flags;
- cpumask_t cpumask = cpumask_of(cpu);
+ cpumask_t cpumask;
+ cpumask_copy(&cpumask, &cpumask_of(cpu));
flags = arch_local_cli_save();
hotplug_cpu_nmi_call_function(cpumask, prepare_sleep_cpu, NULL, 1);
hotplug_cpu_nmi_call_function(cpumask, sleep_cpu, NULL, 0);
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index f03cb278828..a7a987c7954 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -26,11 +26,11 @@
#include <linux/kdebug.h>
#include <linux/bug.h>
#include <linux/irq.h>
+#include <linux/export.h>
#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
@@ -156,7 +156,7 @@ int die_if_no_fixup(const char *str, struct pt_regs *regs,
case EXCEP_TRAP:
case EXCEP_UNIMPINS:
- if (get_user(opcode, (uint8_t __user *)regs->pc) != 0)
+ if (probe_kernel_read(&opcode, (u8 *)regs->pc, 1) < 0)
break;
if (opcode == 0xff) {
if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
@@ -294,17 +294,6 @@ void show_stack(struct task_struct *task, unsigned long *sp)
}
/*
- * the architecture-independent dump_stack generator
- */
-void dump_stack(void)
-{
- unsigned long stack;
-
- show_stack(current, &stack);
-}
-EXPORT_SYMBOL(dump_stack);
-
-/*
* dump the register file in the specified exception frame
*/
void show_registers_only(struct pt_regs *regs)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 968bcd2cb02..13c4814c29f 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -44,6 +44,7 @@ SECTIONS
RO_DATA(PAGE_SIZE)
/* writeable */
+ _sdata = .; /* Start of rw data section */
RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
_edata = .;
@@ -70,7 +71,7 @@ SECTIONS
.exit.text : { EXIT_TEXT; }
.exit.data : { EXIT_DATA; }
- PERCPU(32, PAGE_SIZE)
+ PERCPU_SECTION(32)
. = ALIGN(PAGE_SIZE);
__init_end = .;
/* freed after init ends here */