aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile4
-rw-r--r--arch/arm/kernel/ecard.c31
-rw-r--r--arch/arm/kernel/ecard.h56
-rw-r--r--arch/arm/kernel/head.S6
-rw-r--r--arch/arm/kernel/process.c3
-rw-r--r--arch/arm/kernel/ptrace.c6
-rw-r--r--arch/arm/kernel/stacktrace.c73
-rw-r--r--arch/arm/kernel/stacktrace.h9
-rw-r--r--arch/arm/kernel/time.c4
-rw-r--r--arch/arm/kernel/traps.c5
10 files changed, 174 insertions, 23 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index bb28087bf818..593b56509f4f 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -7,8 +7,8 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
7# Object file lists. 7# Object file lists.
8 8
9obj-y := compat.o entry-armv.o entry-common.o irq.o \ 9obj-y := compat.o entry-armv.o entry-common.o irq.o \
10 process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \ 10 process.o ptrace.o semaphore.o setup.o signal.o \
11 time.o traps.o 11 sys_arm.o stacktrace.o time.o traps.o
12 12
13obj-$(CONFIG_ISA_DMA_API) += dma.o 13obj-$(CONFIG_ISA_DMA_API) += dma.o
14obj-$(CONFIG_ARCH_ACORN) += ecard.o 14obj-$(CONFIG_ARCH_ACORN) += ecard.o
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index f1c0fb974177..bdbd7da99286 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -40,6 +40,7 @@
40#include <linux/device.h> 40#include <linux/device.h>
41#include <linux/init.h> 41#include <linux/init.h>
42#include <linux/mutex.h> 42#include <linux/mutex.h>
43#include <linux/kthread.h>
43 44
44#include <asm/dma.h> 45#include <asm/dma.h>
45#include <asm/ecard.h> 46#include <asm/ecard.h>
@@ -50,6 +51,8 @@
50#include <asm/mach/irq.h> 51#include <asm/mach/irq.h>
51#include <asm/tlbflush.h> 52#include <asm/tlbflush.h>
52 53
54#include "ecard.h"
55
53#ifndef CONFIG_ARCH_RPC 56#ifndef CONFIG_ARCH_RPC
54#define HAVE_EXPMASK 57#define HAVE_EXPMASK
55#endif 58#endif
@@ -123,7 +126,7 @@ static void ecard_task_reset(struct ecard_request *req)
123 126
124 res = ec->slot_no == 8 127 res = ec->slot_no == 8
125 ? &ec->resource[ECARD_RES_MEMC] 128 ? &ec->resource[ECARD_RES_MEMC]
126 : ec->type == ECARD_EASI 129 : ec->easi
127 ? &ec->resource[ECARD_RES_EASI] 130 ? &ec->resource[ECARD_RES_EASI]
128 : &ec->resource[ECARD_RES_IOCSYNC]; 131 : &ec->resource[ECARD_RES_IOCSYNC];
129 132
@@ -178,7 +181,7 @@ static void ecard_task_readbytes(struct ecard_request *req)
178 index += 1; 181 index += 1;
179 } 182 }
180 } else { 183 } else {
181 unsigned long base = (ec->type == ECARD_EASI 184 unsigned long base = (ec->easi
182 ? &ec->resource[ECARD_RES_EASI] 185 ? &ec->resource[ECARD_RES_EASI]
183 : &ec->resource[ECARD_RES_IOCSYNC])->start; 186 : &ec->resource[ECARD_RES_IOCSYNC])->start;
184 void __iomem *pbase = (void __iomem *)base; 187 void __iomem *pbase = (void __iomem *)base;
@@ -263,8 +266,6 @@ static int ecard_init_mm(void)
263static int 266static int
264ecard_task(void * unused) 267ecard_task(void * unused)
265{ 268{
266 daemonize("kecardd");
267
268 /* 269 /*
269 * Allocate a mm. We're not a lazy-TLB kernel task since we need 270 * Allocate a mm. We're not a lazy-TLB kernel task since we need
270 * to set page table entries where the user space would be. Note 271 * to set page table entries where the user space would be. Note
@@ -727,7 +728,7 @@ static int ecard_prints(char *buffer, ecard_t *ec)
727 char *start = buffer; 728 char *start = buffer;
728 729
729 buffer += sprintf(buffer, " %d: %s ", ec->slot_no, 730 buffer += sprintf(buffer, " %d: %s ", ec->slot_no,
730 ec->type == ECARD_EASI ? "EASI" : " "); 731 ec->easi ? "EASI" : " ");
731 732
732 if (ec->cid.id == 0) { 733 if (ec->cid.id == 0) {
733 struct in_chunk_dir incd; 734 struct in_chunk_dir incd;
@@ -814,7 +815,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
814 } 815 }
815 816
816 ec->slot_no = slot; 817 ec->slot_no = slot;
817 ec->type = type; 818 ec->easi = type == ECARD_EASI;
818 ec->irq = NO_IRQ; 819 ec->irq = NO_IRQ;
819 ec->fiq = NO_IRQ; 820 ec->fiq = NO_IRQ;
820 ec->dma = NO_DMA; 821 ec->dma = NO_DMA;
@@ -825,6 +826,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
825 ec->dev.bus = &ecard_bus_type; 826 ec->dev.bus = &ecard_bus_type;
826 ec->dev.dma_mask = &ec->dma_mask; 827 ec->dev.dma_mask = &ec->dma_mask;
827 ec->dma_mask = (u64)0xffffffff; 828 ec->dma_mask = (u64)0xffffffff;
829 ec->dev.coherent_dma_mask = ec->dma_mask;
828 830
829 if (slot < 4) { 831 if (slot < 4) {
830 ec_set_resource(ec, ECARD_RES_MEMC, 832 ec_set_resource(ec, ECARD_RES_MEMC,
@@ -907,7 +909,7 @@ static ssize_t ecard_show_device(struct device *dev, struct device_attribute *at
907static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf) 909static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
908{ 910{
909 struct expansion_card *ec = ECARD_DEV(dev); 911 struct expansion_card *ec = ECARD_DEV(dev);
910 return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC"); 912 return sprintf(buf, "%s\n", ec->easi ? "EASI" : "IOC");
911} 913}
912 914
913static struct device_attribute ecard_dev_attrs[] = { 915static struct device_attribute ecard_dev_attrs[] = {
@@ -1058,13 +1060,14 @@ ecard_probe(int slot, card_type_t type)
1058 */ 1060 */
1059static int __init ecard_init(void) 1061static int __init ecard_init(void)
1060{ 1062{
1061 int slot, irqhw, ret; 1063 struct task_struct *task;
1062 1064 int slot, irqhw;
1063 ret = kernel_thread(ecard_task, NULL, CLONE_KERNEL); 1065
1064 if (ret < 0) { 1066 task = kthread_run(ecard_task, NULL, "kecardd");
1065 printk(KERN_ERR "Ecard: unable to create kernel thread: %d\n", 1067 if (IS_ERR(task)) {
1066 ret); 1068 printk(KERN_ERR "Ecard: unable to create kernel thread: %ld\n",
1067 return ret; 1069 PTR_ERR(task));
1070 return PTR_ERR(task);
1068 } 1071 }
1069 1072
1070 printk("Probing expansion cards\n"); 1073 printk("Probing expansion cards\n");
diff --git a/arch/arm/kernel/ecard.h b/arch/arm/kernel/ecard.h
new file mode 100644
index 000000000000..d7c2dacf935d
--- /dev/null
+++ b/arch/arm/kernel/ecard.h
@@ -0,0 +1,56 @@
1/*
2 * ecard.h
3 *
4 * Copyright 2007 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11/* Definitions internal to ecard.c - for it's use only!!
12 *
13 * External expansion card header as read from the card
14 */
15struct ex_ecid {
16 unsigned char r_irq:1;
17 unsigned char r_zero:1;
18 unsigned char r_fiq:1;
19 unsigned char r_id:4;
20 unsigned char r_a:1;
21
22 unsigned char r_cd:1;
23 unsigned char r_is:1;
24 unsigned char r_w:2;
25 unsigned char r_r1:4;
26
27 unsigned char r_r2:8;
28
29 unsigned char r_prod[2];
30
31 unsigned char r_manu[2];
32
33 unsigned char r_country;
34
35 unsigned char r_fiqmask;
36 unsigned char r_fiqoff[3];
37
38 unsigned char r_irqmask;
39 unsigned char r_irqoff[3];
40};
41
42/*
43 * Chunk directory entry as read from the card
44 */
45struct ex_chunk_dir {
46 unsigned char r_id;
47 unsigned char r_len[3];
48 unsigned long r_start;
49 union {
50 char string[256];
51 char data[1];
52 } d;
53#define c_id(x) ((x)->r_id)
54#define c_len(x) ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16))
55#define c_start(x) ((x)->r_start)
56};
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 66db0a9bf0bc..1d35edacc011 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -257,7 +257,9 @@ __create_page_tables:
257 * Map some ram to cover our .data and .bss areas. 257 * Map some ram to cover our .data and .bss areas.
258 */ 258 */
259 orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000) 259 orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000)
260 .if (KERNEL_RAM_PADDR & 0x00f00000)
260 orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000) 261 orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
262 .endif
261 add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 263 add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18
262 str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! 264 str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
263 ldr r6, =(_end - 1) 265 ldr r6, =(_end - 1)
@@ -274,7 +276,9 @@ __create_page_tables:
274 */ 276 */
275 add r0, r4, #PAGE_OFFSET >> 18 277 add r0, r4, #PAGE_OFFSET >> 18
276 orr r6, r7, #(PHYS_OFFSET & 0xff000000) 278 orr r6, r7, #(PHYS_OFFSET & 0xff000000)
277 orr r6, r6, #(PHYS_OFFSET & 0x00e00000) 279 .if (PHYS_OFFSET & 0x00f00000)
280 orr r6, r6, #(PHYS_OFFSET & 0x00f00000)
281 .endif
278 str r6, [r0] 282 str r6, [r0]
279 283
280#ifdef CONFIG_DEBUG_LL 284#ifdef CONFIG_DEBUG_LL
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 8afd83d0cbdd..5d6e6523598b 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -27,6 +27,7 @@
27#include <linux/cpu.h> 27#include <linux/cpu.h>
28#include <linux/elfcore.h> 28#include <linux/elfcore.h>
29#include <linux/pm.h> 29#include <linux/pm.h>
30#include <linux/tick.h>
30 31
31#include <asm/leds.h> 32#include <asm/leds.h>
32#include <asm/processor.h> 33#include <asm/processor.h>
@@ -159,9 +160,11 @@ void cpu_idle(void)
159 if (!idle) 160 if (!idle)
160 idle = default_idle; 161 idle = default_idle;
161 leds_event(led_idle_start); 162 leds_event(led_idle_start);
163 tick_nohz_stop_sched_tick();
162 while (!need_resched()) 164 while (!need_resched())
163 idle(); 165 idle();
164 leds_event(led_idle_end); 166 leds_event(led_idle_end);
167 tick_nohz_restart_sched_tick();
165 preempt_enable_no_resched(); 168 preempt_enable_no_resched();
166 schedule(); 169 schedule();
167 preempt_disable(); 170 preempt_disable();
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index e594b84cca83..13af4006a40f 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -779,8 +779,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
779 break; 779 break;
780 780
781 case PTRACE_SET_SYSCALL: 781 case PTRACE_SET_SYSCALL:
782 task_thread_info(child)->syscall = data;
782 ret = 0; 783 ret = 0;
783 child->ptrace_message = data;
784 break; 784 break;
785 785
786#ifdef CONFIG_CRUNCH 786#ifdef CONFIG_CRUNCH
@@ -817,7 +817,7 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
817 ip = regs->ARM_ip; 817 ip = regs->ARM_ip;
818 regs->ARM_ip = why; 818 regs->ARM_ip = why;
819 819
820 current->ptrace_message = scno; 820 current_thread_info()->syscall = scno;
821 821
822 /* the 0x80 provides a way for the tracing parent to distinguish 822 /* the 0x80 provides a way for the tracing parent to distinguish
823 between a syscall stop and SIGTRAP delivery */ 823 between a syscall stop and SIGTRAP delivery */
@@ -834,5 +834,5 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
834 } 834 }
835 regs->ARM_ip = ip; 835 regs->ARM_ip = ip;
836 836
837 return current->ptrace_message; 837 return current_thread_info()->syscall;
838} 838}
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
new file mode 100644
index 000000000000..77ef35efaa8d
--- /dev/null
+++ b/arch/arm/kernel/stacktrace.c
@@ -0,0 +1,73 @@
1#include <linux/sched.h>
2#include <linux/stacktrace.h>
3
4#include "stacktrace.h"
5
6int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
7 int (*fn)(struct stackframe *, void *), void *data)
8{
9 struct stackframe *frame;
10
11 do {
12 /*
13 * Check current frame pointer is within bounds
14 */
15 if ((fp - 12) < low || fp + 4 >= high)
16 break;
17
18 frame = (struct stackframe *)(fp - 12);
19
20 if (fn(frame, data))
21 break;
22
23 /*
24 * Update the low bound - the next frame must always
25 * be at a higher address than the current frame.
26 */
27 low = fp + 4;
28 fp = frame->fp;
29 } while (fp);
30
31 return 0;
32}
33
34#ifdef CONFIG_STACKTRACE
35struct stack_trace_data {
36 struct stack_trace *trace;
37 unsigned int skip;
38};
39
40static int save_trace(struct stackframe *frame, void *d)
41{
42 struct stack_trace_data *data = d;
43 struct stack_trace *trace = data->trace;
44
45 if (data->skip) {
46 data->skip--;
47 return 0;
48 }
49
50 trace->entries[trace->nr_entries++] = frame->lr;
51
52 return trace->nr_entries >= trace->max_entries;
53}
54
55void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
56{
57 struct stack_trace_data data;
58 unsigned long fp, base;
59
60 data.trace = trace;
61 data.skip = trace->skip;
62
63 if (task) {
64 base = (unsigned long)task_stack_page(task);
65 fp = 0; /* FIXME */
66 } else {
67 base = (unsigned long)task_stack_page(current);
68 asm("mov %0, fp" : "=r" (fp));
69 }
70
71 walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
72}
73#endif
diff --git a/arch/arm/kernel/stacktrace.h b/arch/arm/kernel/stacktrace.h
new file mode 100644
index 000000000000..e9fd20cb5662
--- /dev/null
+++ b/arch/arm/kernel/stacktrace.h
@@ -0,0 +1,9 @@
1struct stackframe {
2 unsigned long fp;
3 unsigned long sp;
4 unsigned long lr;
5 unsigned long pc;
6};
7
8int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
9 int (*fn)(struct stackframe *, void *), void *data);
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index f61decb89ba2..d0540e4eaf5b 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -327,6 +327,7 @@ void restore_time_delta(struct timespec *delta, struct timespec *rtc)
327} 327}
328EXPORT_SYMBOL(restore_time_delta); 328EXPORT_SYMBOL(restore_time_delta);
329 329
330#ifndef CONFIG_GENERIC_CLOCKEVENTS
330/* 331/*
331 * Kernel system timer support. 332 * Kernel system timer support.
332 */ 333 */
@@ -340,8 +341,9 @@ void timer_tick(void)
340 update_process_times(user_mode(get_irq_regs())); 341 update_process_times(user_mode(get_irq_regs()));
341#endif 342#endif
342} 343}
344#endif
343 345
344#ifdef CONFIG_PM 346#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
345static int timer_suspend(struct sys_device *dev, pm_message_t state) 347static int timer_suspend(struct sys_device *dev, pm_message_t state)
346{ 348{
347 struct sys_timer *timer = container_of(dev, struct sys_timer, dev); 349 struct sys_timer *timer = container_of(dev, struct sys_timer, dev);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6055ab4b58d9..f05e66b0f868 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -286,6 +286,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
286 struct undef_hook *hook; 286 struct undef_hook *hook;
287 siginfo_t info; 287 siginfo_t info;
288 void __user *pc; 288 void __user *pc;
289 unsigned long flags;
289 290
290 /* 291 /*
291 * According to the ARM ARM, PC is 2 or 4 bytes ahead, 292 * According to the ARM ARM, PC is 2 or 4 bytes ahead,
@@ -304,7 +305,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
304 get_user(instr, (u32 __user *)pc); 305 get_user(instr, (u32 __user *)pc);
305 } 306 }
306 307
307 spin_lock_irq(&undef_lock); 308 spin_lock_irqsave(&undef_lock, flags);
308 list_for_each_entry(hook, &undef_hook, node) { 309 list_for_each_entry(hook, &undef_hook, node) {
309 if ((instr & hook->instr_mask) == hook->instr_val && 310 if ((instr & hook->instr_mask) == hook->instr_val &&
310 (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { 311 (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) {
@@ -314,7 +315,7 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
314 } 315 }
315 } 316 }
316 } 317 }
317 spin_unlock_irq(&undef_lock); 318 spin_unlock_irqrestore(&undef_lock, flags);
318 319
319#ifdef CONFIG_DEBUG_USER 320#ifdef CONFIG_DEBUG_USER
320 if (user_debug & UDBG_UNDEFINED) { 321 if (user_debug & UDBG_UNDEFINED) {