diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-25 17:09:41 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-02-25 17:09:41 -0500 |
commit | 2741ecb4ce5c2d430b5c44b0a169038338c21df5 (patch) | |
tree | 4aa71d7551184ee88f32c7f3660d821133058c32 /arch/arm/kernel | |
parent | bc85e585c6d0fab4bde12d60964b2f25802c3163 (diff) | |
parent | 5de813b6cd06460b337f9da9afe316823cf3ef45 (diff) |
Merge branch 'misc2' into devel
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kernel/leds.c | 115 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 53 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 79 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 178 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 35 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 4 |
7 files changed, 207 insertions, 258 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index c76e6d2679b8..26d302c28e13 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -17,6 +17,7 @@ obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \ | |||
17 | process.o ptrace.o return_address.o setup.o signal.o \ | 17 | process.o ptrace.o return_address.o setup.o signal.o \ |
18 | sys_arm.o stacktrace.o time.o traps.o | 18 | sys_arm.o stacktrace.o time.o traps.o |
19 | 19 | ||
20 | obj-$(CONFIG_LEDS) += leds.o | ||
20 | obj-$(CONFIG_OC_ETM) += etm.o | 21 | obj-$(CONFIG_OC_ETM) += etm.o |
21 | 22 | ||
22 | obj-$(CONFIG_ISA_DMA_API) += dma.o | 23 | obj-$(CONFIG_ISA_DMA_API) += dma.o |
diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c new file mode 100644 index 000000000000..31a316c1777b --- /dev/null +++ b/arch/arm/kernel/leds.c | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * LED support code, ripped out of arch/arm/kernel/time.c | ||
3 | * | ||
4 | * Copyright (C) 1994-2001 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 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/sysdev.h> | ||
13 | |||
14 | #include <asm/leds.h> | ||
15 | |||
16 | static void dummy_leds_event(led_event_t evt) | ||
17 | { | ||
18 | } | ||
19 | |||
20 | void (*leds_event)(led_event_t) = dummy_leds_event; | ||
21 | |||
22 | struct leds_evt_name { | ||
23 | const char name[8]; | ||
24 | int on; | ||
25 | int off; | ||
26 | }; | ||
27 | |||
28 | static const struct leds_evt_name evt_names[] = { | ||
29 | { "amber", led_amber_on, led_amber_off }, | ||
30 | { "blue", led_blue_on, led_blue_off }, | ||
31 | { "green", led_green_on, led_green_off }, | ||
32 | { "red", led_red_on, led_red_off }, | ||
33 | }; | ||
34 | |||
35 | static ssize_t leds_store(struct sys_device *dev, | ||
36 | struct sysdev_attribute *attr, | ||
37 | const char *buf, size_t size) | ||
38 | { | ||
39 | int ret = -EINVAL, len = strcspn(buf, " "); | ||
40 | |||
41 | if (len > 0 && buf[len] == '\0') | ||
42 | len--; | ||
43 | |||
44 | if (strncmp(buf, "claim", len) == 0) { | ||
45 | leds_event(led_claim); | ||
46 | ret = size; | ||
47 | } else if (strncmp(buf, "release", len) == 0) { | ||
48 | leds_event(led_release); | ||
49 | ret = size; | ||
50 | } else { | ||
51 | int i; | ||
52 | |||
53 | for (i = 0; i < ARRAY_SIZE(evt_names); i++) { | ||
54 | if (strlen(evt_names[i].name) != len || | ||
55 | strncmp(buf, evt_names[i].name, len) != 0) | ||
56 | continue; | ||
57 | if (strncmp(buf+len, " on", 3) == 0) { | ||
58 | leds_event(evt_names[i].on); | ||
59 | ret = size; | ||
60 | } else if (strncmp(buf+len, " off", 4) == 0) { | ||
61 | leds_event(evt_names[i].off); | ||
62 | ret = size; | ||
63 | } | ||
64 | break; | ||
65 | } | ||
66 | } | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | static SYSDEV_ATTR(event, 0200, NULL, leds_store); | ||
71 | |||
72 | static int leds_suspend(struct sys_device *dev, pm_message_t state) | ||
73 | { | ||
74 | leds_event(led_stop); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int leds_resume(struct sys_device *dev) | ||
79 | { | ||
80 | leds_event(led_start); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int leds_shutdown(struct sys_device *dev) | ||
85 | { | ||
86 | leds_event(led_halted); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static struct sysdev_class leds_sysclass = { | ||
91 | .name = "leds", | ||
92 | .shutdown = leds_shutdown, | ||
93 | .suspend = leds_suspend, | ||
94 | .resume = leds_resume, | ||
95 | }; | ||
96 | |||
97 | static struct sys_device leds_device = { | ||
98 | .id = 0, | ||
99 | .cls = &leds_sysclass, | ||
100 | }; | ||
101 | |||
102 | static int __init leds_init(void) | ||
103 | { | ||
104 | int ret; | ||
105 | ret = sysdev_class_register(&leds_sysclass); | ||
106 | if (ret == 0) | ||
107 | ret = sysdev_register(&leds_device); | ||
108 | if (ret == 0) | ||
109 | ret = sysdev_create_file(&leds_device, &attr_event); | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | device_initcall(leds_init); | ||
114 | |||
115 | EXPORT_SYMBOL(leds_event); | ||
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index a2ea3854cb3c..08f899fb76a6 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = { | |||
499 | .fn = break_trap, | 499 | .fn = break_trap, |
500 | }; | 500 | }; |
501 | 501 | ||
502 | static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr) | ||
503 | { | ||
504 | unsigned int instr2; | ||
505 | void __user *pc; | ||
506 | |||
507 | /* Check the second half of the instruction. */ | ||
508 | pc = (void __user *)(instruction_pointer(regs) + 2); | ||
509 | |||
510 | if (processor_mode(regs) == SVC_MODE) { | ||
511 | instr2 = *(u16 *) pc; | ||
512 | } else { | ||
513 | get_user(instr2, (u16 __user *)pc); | ||
514 | } | ||
515 | |||
516 | if (instr2 == 0xa000) { | ||
517 | ptrace_break(current, regs); | ||
518 | return 0; | ||
519 | } else { | ||
520 | return 1; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static struct undef_hook thumb2_break_hook = { | ||
525 | .instr_mask = 0xffff, | ||
526 | .instr_val = 0xf7f0, | ||
527 | .cpsr_mask = PSR_T_BIT, | ||
528 | .cpsr_val = PSR_T_BIT, | ||
529 | .fn = thumb2_break_trap, | ||
530 | }; | ||
531 | |||
502 | static int __init ptrace_break_init(void) | 532 | static int __init ptrace_break_init(void) |
503 | { | 533 | { |
504 | register_undef_hook(&arm_break_hook); | 534 | register_undef_hook(&arm_break_hook); |
505 | register_undef_hook(&thumb_break_hook); | 535 | register_undef_hook(&thumb_break_hook); |
536 | register_undef_hook(&thumb2_break_hook); | ||
506 | return 0; | 537 | return 0; |
507 | } | 538 | } |
508 | 539 | ||
@@ -669,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data) | |||
669 | union vfp_state *vfp = &thread->vfpstate; | 700 | union vfp_state *vfp = &thread->vfpstate; |
670 | struct user_vfp __user *ufp = data; | 701 | struct user_vfp __user *ufp = data; |
671 | 702 | ||
672 | vfp_sync_state(thread); | 703 | vfp_sync_hwstate(thread); |
673 | 704 | ||
674 | /* copy the floating point registers */ | 705 | /* copy the floating point registers */ |
675 | if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, | 706 | if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, |
@@ -692,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data) | |||
692 | union vfp_state *vfp = &thread->vfpstate; | 723 | union vfp_state *vfp = &thread->vfpstate; |
693 | struct user_vfp __user *ufp = data; | 724 | struct user_vfp __user *ufp = data; |
694 | 725 | ||
695 | vfp_sync_state(thread); | 726 | vfp_sync_hwstate(thread); |
696 | 727 | ||
697 | /* copy the floating point registers */ | 728 | /* copy the floating point registers */ |
698 | if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, | 729 | if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, |
@@ -703,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data) | |||
703 | if (get_user(vfp->hard.fpscr, &ufp->fpscr)) | 734 | if (get_user(vfp->hard.fpscr, &ufp->fpscr)) |
704 | return -EFAULT; | 735 | return -EFAULT; |
705 | 736 | ||
737 | vfp_flush_hwstate(thread); | ||
738 | |||
706 | return 0; | 739 | return 0; |
707 | } | 740 | } |
708 | #endif | 741 | #endif |
@@ -712,26 +745,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
712 | int ret; | 745 | int ret; |
713 | 746 | ||
714 | switch (request) { | 747 | switch (request) { |
715 | /* | ||
716 | * read word at location "addr" in the child process. | ||
717 | */ | ||
718 | case PTRACE_PEEKTEXT: | ||
719 | case PTRACE_PEEKDATA: | ||
720 | ret = generic_ptrace_peekdata(child, addr, data); | ||
721 | break; | ||
722 | |||
723 | case PTRACE_PEEKUSR: | 748 | case PTRACE_PEEKUSR: |
724 | ret = ptrace_read_user(child, addr, (unsigned long __user *)data); | 749 | ret = ptrace_read_user(child, addr, (unsigned long __user *)data); |
725 | break; | 750 | break; |
726 | 751 | ||
727 | /* | ||
728 | * write the word at location addr. | ||
729 | */ | ||
730 | case PTRACE_POKETEXT: | ||
731 | case PTRACE_POKEDATA: | ||
732 | ret = generic_ptrace_pokedata(child, addr, data); | ||
733 | break; | ||
734 | |||
735 | case PTRACE_POKEUSR: | 752 | case PTRACE_POKEUSR: |
736 | ret = ptrace_write_user(child, addr, data); | 753 | ret = ptrace_write_user(child, addr, data); |
737 | break; | 754 | break; |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index c6c57b640b6b..baf5959d639a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/smp.h> | 25 | #include <linux/smp.h> |
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/proc_fs.h> | ||
27 | 28 | ||
28 | #include <asm/unified.h> | 29 | #include <asm/unified.h> |
29 | #include <asm/cpu.h> | 30 | #include <asm/cpu.h> |
@@ -117,7 +118,7 @@ EXPORT_SYMBOL(elf_platform); | |||
117 | 118 | ||
118 | static const char *cpu_name; | 119 | static const char *cpu_name; |
119 | static const char *machine_name; | 120 | static const char *machine_name; |
120 | static char __initdata command_line[COMMAND_LINE_SIZE]; | 121 | static char __initdata cmd_line[COMMAND_LINE_SIZE]; |
121 | 122 | ||
122 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; | 123 | static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; |
123 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; | 124 | static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; |
@@ -417,10 +418,11 @@ static int __init arm_add_memory(unsigned long start, unsigned long size) | |||
417 | * Pick out the memory size. We look for mem=size@start, | 418 | * Pick out the memory size. We look for mem=size@start, |
418 | * where start and size are "size[KkMm]" | 419 | * where start and size are "size[KkMm]" |
419 | */ | 420 | */ |
420 | static void __init early_mem(char **p) | 421 | static int __init early_mem(char *p) |
421 | { | 422 | { |
422 | static int usermem __initdata = 0; | 423 | static int usermem __initdata = 0; |
423 | unsigned long size, start; | 424 | unsigned long size, start; |
425 | char *endp; | ||
424 | 426 | ||
425 | /* | 427 | /* |
426 | * If the user specifies memory size, we | 428 | * If the user specifies memory size, we |
@@ -433,52 +435,15 @@ static void __init early_mem(char **p) | |||
433 | } | 435 | } |
434 | 436 | ||
435 | start = PHYS_OFFSET; | 437 | start = PHYS_OFFSET; |
436 | size = memparse(*p, p); | 438 | size = memparse(p, &endp); |
437 | if (**p == '@') | 439 | if (*endp == '@') |
438 | start = memparse(*p + 1, p); | 440 | start = memparse(endp + 1, NULL); |
439 | 441 | ||
440 | arm_add_memory(start, size); | 442 | arm_add_memory(start, size); |
441 | } | ||
442 | __early_param("mem=", early_mem); | ||
443 | 443 | ||
444 | /* | 444 | return 0; |
445 | * Initial parsing of the command line. | ||
446 | */ | ||
447 | static void __init parse_cmdline(char **cmdline_p, char *from) | ||
448 | { | ||
449 | char c = ' ', *to = command_line; | ||
450 | int len = 0; | ||
451 | |||
452 | for (;;) { | ||
453 | if (c == ' ') { | ||
454 | extern struct early_params __early_begin, __early_end; | ||
455 | struct early_params *p; | ||
456 | |||
457 | for (p = &__early_begin; p < &__early_end; p++) { | ||
458 | int arglen = strlen(p->arg); | ||
459 | |||
460 | if (memcmp(from, p->arg, arglen) == 0) { | ||
461 | if (to != command_line) | ||
462 | to -= 1; | ||
463 | from += arglen; | ||
464 | p->fn(&from); | ||
465 | |||
466 | while (*from != ' ' && *from != '\0') | ||
467 | from++; | ||
468 | break; | ||
469 | } | ||
470 | } | ||
471 | } | ||
472 | c = *from++; | ||
473 | if (!c) | ||
474 | break; | ||
475 | if (COMMAND_LINE_SIZE <= ++len) | ||
476 | break; | ||
477 | *to++ = c; | ||
478 | } | ||
479 | *to = '\0'; | ||
480 | *cmdline_p = command_line; | ||
481 | } | 445 | } |
446 | early_param("mem", early_mem); | ||
482 | 447 | ||
483 | static void __init | 448 | static void __init |
484 | setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) | 449 | setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) |
@@ -739,9 +704,15 @@ void __init setup_arch(char **cmdline_p) | |||
739 | init_mm.end_data = (unsigned long) _edata; | 704 | init_mm.end_data = (unsigned long) _edata; |
740 | init_mm.brk = (unsigned long) _end; | 705 | init_mm.brk = (unsigned long) _end; |
741 | 706 | ||
742 | memcpy(boot_command_line, from, COMMAND_LINE_SIZE); | 707 | /* parse_early_param needs a boot_command_line */ |
743 | boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; | 708 | strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); |
744 | parse_cmdline(cmdline_p, from); | 709 | |
710 | /* populate cmd_line too for later use, preserving boot_command_line */ | ||
711 | strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); | ||
712 | *cmdline_p = cmd_line; | ||
713 | |||
714 | parse_early_param(); | ||
715 | |||
745 | paging_init(mdesc); | 716 | paging_init(mdesc); |
746 | request_standard_resources(&meminfo, mdesc); | 717 | request_standard_resources(&meminfo, mdesc); |
747 | 718 | ||
@@ -782,9 +753,21 @@ static int __init topology_init(void) | |||
782 | 753 | ||
783 | return 0; | 754 | return 0; |
784 | } | 755 | } |
785 | |||
786 | subsys_initcall(topology_init); | 756 | subsys_initcall(topology_init); |
787 | 757 | ||
758 | #ifdef CONFIG_HAVE_PROC_CPU | ||
759 | static int __init proc_cpu_init(void) | ||
760 | { | ||
761 | struct proc_dir_entry *res; | ||
762 | |||
763 | res = proc_mkdir("cpu", NULL); | ||
764 | if (!res) | ||
765 | return -ENOMEM; | ||
766 | return 0; | ||
767 | } | ||
768 | fs_initcall(proc_cpu_init); | ||
769 | #endif | ||
770 | |||
788 | static const char *hwcap_str[] = { | 771 | static const char *hwcap_str[] = { |
789 | "swp", | 772 | "swp", |
790 | "half", | 773 | "half", |
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index d38cdf2c8276..28753805d2d1 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -10,11 +10,6 @@ | |||
10 | * | 10 | * |
11 | * This file contains the ARM-specific time handling details: | 11 | * This file contains the ARM-specific time handling details: |
12 | * reading the RTC at bootup, etc... | 12 | * reading the RTC at bootup, etc... |
13 | * | ||
14 | * 1994-07-02 Alan Modra | ||
15 | * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime | ||
16 | * 1998-12-20 Updated NTP code according to technical memorandum Jan '96 | ||
17 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | ||
18 | */ | 13 | */ |
19 | #include <linux/module.h> | 14 | #include <linux/module.h> |
20 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
@@ -77,11 +72,6 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
77 | EXPORT_SYMBOL(profile_pc); | 72 | EXPORT_SYMBOL(profile_pc); |
78 | #endif | 73 | #endif |
79 | 74 | ||
80 | /* | ||
81 | * hook for setting the RTC's idea of the current time. | ||
82 | */ | ||
83 | int (*set_rtc)(void); | ||
84 | |||
85 | #ifndef CONFIG_GENERIC_TIME | 75 | #ifndef CONFIG_GENERIC_TIME |
86 | static unsigned long dummy_gettimeoffset(void) | 76 | static unsigned long dummy_gettimeoffset(void) |
87 | { | 77 | { |
@@ -89,140 +79,6 @@ static unsigned long dummy_gettimeoffset(void) | |||
89 | } | 79 | } |
90 | #endif | 80 | #endif |
91 | 81 | ||
92 | static unsigned long next_rtc_update; | ||
93 | |||
94 | /* | ||
95 | * If we have an externally synchronized linux clock, then update | ||
96 | * CMOS clock accordingly every ~11 minutes. set_rtc() has to be | ||
97 | * called as close as possible to 500 ms before the new second | ||
98 | * starts. | ||
99 | */ | ||
100 | static inline void do_set_rtc(void) | ||
101 | { | ||
102 | if (!ntp_synced() || set_rtc == NULL) | ||
103 | return; | ||
104 | |||
105 | if (next_rtc_update && | ||
106 | time_before((unsigned long)xtime.tv_sec, next_rtc_update)) | ||
107 | return; | ||
108 | |||
109 | if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) && | ||
110 | xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1)) | ||
111 | return; | ||
112 | |||
113 | if (set_rtc()) | ||
114 | /* | ||
115 | * rtc update failed. Try again in 60s | ||
116 | */ | ||
117 | next_rtc_update = xtime.tv_sec + 60; | ||
118 | else | ||
119 | next_rtc_update = xtime.tv_sec + 660; | ||
120 | } | ||
121 | |||
122 | #ifdef CONFIG_LEDS | ||
123 | |||
124 | static void dummy_leds_event(led_event_t evt) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | void (*leds_event)(led_event_t) = dummy_leds_event; | ||
129 | |||
130 | struct leds_evt_name { | ||
131 | const char name[8]; | ||
132 | int on; | ||
133 | int off; | ||
134 | }; | ||
135 | |||
136 | static const struct leds_evt_name evt_names[] = { | ||
137 | { "amber", led_amber_on, led_amber_off }, | ||
138 | { "blue", led_blue_on, led_blue_off }, | ||
139 | { "green", led_green_on, led_green_off }, | ||
140 | { "red", led_red_on, led_red_off }, | ||
141 | }; | ||
142 | |||
143 | static ssize_t leds_store(struct sys_device *dev, | ||
144 | struct sysdev_attribute *attr, | ||
145 | const char *buf, size_t size) | ||
146 | { | ||
147 | int ret = -EINVAL, len = strcspn(buf, " "); | ||
148 | |||
149 | if (len > 0 && buf[len] == '\0') | ||
150 | len--; | ||
151 | |||
152 | if (strncmp(buf, "claim", len) == 0) { | ||
153 | leds_event(led_claim); | ||
154 | ret = size; | ||
155 | } else if (strncmp(buf, "release", len) == 0) { | ||
156 | leds_event(led_release); | ||
157 | ret = size; | ||
158 | } else { | ||
159 | int i; | ||
160 | |||
161 | for (i = 0; i < ARRAY_SIZE(evt_names); i++) { | ||
162 | if (strlen(evt_names[i].name) != len || | ||
163 | strncmp(buf, evt_names[i].name, len) != 0) | ||
164 | continue; | ||
165 | if (strncmp(buf+len, " on", 3) == 0) { | ||
166 | leds_event(evt_names[i].on); | ||
167 | ret = size; | ||
168 | } else if (strncmp(buf+len, " off", 4) == 0) { | ||
169 | leds_event(evt_names[i].off); | ||
170 | ret = size; | ||
171 | } | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | static SYSDEV_ATTR(event, 0200, NULL, leds_store); | ||
179 | |||
180 | static int leds_suspend(struct sys_device *dev, pm_message_t state) | ||
181 | { | ||
182 | leds_event(led_stop); | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static int leds_resume(struct sys_device *dev) | ||
187 | { | ||
188 | leds_event(led_start); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int leds_shutdown(struct sys_device *dev) | ||
193 | { | ||
194 | leds_event(led_halted); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static struct sysdev_class leds_sysclass = { | ||
199 | .name = "leds", | ||
200 | .shutdown = leds_shutdown, | ||
201 | .suspend = leds_suspend, | ||
202 | .resume = leds_resume, | ||
203 | }; | ||
204 | |||
205 | static struct sys_device leds_device = { | ||
206 | .id = 0, | ||
207 | .cls = &leds_sysclass, | ||
208 | }; | ||
209 | |||
210 | static int __init leds_init(void) | ||
211 | { | ||
212 | int ret; | ||
213 | ret = sysdev_class_register(&leds_sysclass); | ||
214 | if (ret == 0) | ||
215 | ret = sysdev_register(&leds_device); | ||
216 | if (ret == 0) | ||
217 | ret = sysdev_create_file(&leds_device, &attr_event); | ||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | device_initcall(leds_init); | ||
222 | |||
223 | EXPORT_SYMBOL(leds_event); | ||
224 | #endif | ||
225 | |||
226 | #ifdef CONFIG_LEDS_TIMER | 82 | #ifdef CONFIG_LEDS_TIMER |
227 | static inline void do_leds(void) | 83 | static inline void do_leds(void) |
228 | { | 84 | { |
@@ -295,39 +151,6 @@ int do_settimeofday(struct timespec *tv) | |||
295 | EXPORT_SYMBOL(do_settimeofday); | 151 | EXPORT_SYMBOL(do_settimeofday); |
296 | #endif /* !CONFIG_GENERIC_TIME */ | 152 | #endif /* !CONFIG_GENERIC_TIME */ |
297 | 153 | ||
298 | /** | ||
299 | * save_time_delta - Save the offset between system time and RTC time | ||
300 | * @delta: pointer to timespec to store delta | ||
301 | * @rtc: pointer to timespec for current RTC time | ||
302 | * | ||
303 | * Return a delta between the system time and the RTC time, such | ||
304 | * that system time can be restored later with restore_time_delta() | ||
305 | */ | ||
306 | void save_time_delta(struct timespec *delta, struct timespec *rtc) | ||
307 | { | ||
308 | set_normalized_timespec(delta, | ||
309 | xtime.tv_sec - rtc->tv_sec, | ||
310 | xtime.tv_nsec - rtc->tv_nsec); | ||
311 | } | ||
312 | EXPORT_SYMBOL(save_time_delta); | ||
313 | |||
314 | /** | ||
315 | * restore_time_delta - Restore the current system time | ||
316 | * @delta: delta returned by save_time_delta() | ||
317 | * @rtc: pointer to timespec for current RTC time | ||
318 | */ | ||
319 | void restore_time_delta(struct timespec *delta, struct timespec *rtc) | ||
320 | { | ||
321 | struct timespec ts; | ||
322 | |||
323 | set_normalized_timespec(&ts, | ||
324 | delta->tv_sec + rtc->tv_sec, | ||
325 | delta->tv_nsec + rtc->tv_nsec); | ||
326 | |||
327 | do_settimeofday(&ts); | ||
328 | } | ||
329 | EXPORT_SYMBOL(restore_time_delta); | ||
330 | |||
331 | #ifndef CONFIG_GENERIC_CLOCKEVENTS | 154 | #ifndef CONFIG_GENERIC_CLOCKEVENTS |
332 | /* | 155 | /* |
333 | * Kernel system timer support. | 156 | * Kernel system timer support. |
@@ -336,7 +159,6 @@ void timer_tick(void) | |||
336 | { | 159 | { |
337 | profile_tick(CPU_PROFILING); | 160 | profile_tick(CPU_PROFILING); |
338 | do_leds(); | 161 | do_leds(); |
339 | do_set_rtc(); | ||
340 | write_seqlock(&xtime_lock); | 162 | write_seqlock(&xtime_lock); |
341 | do_timer(1); | 163 | do_timer(1); |
342 | write_sequnlock(&xtime_lock); | 164 | write_sequnlock(&xtime_lock); |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3f361a783f43..1621e5327b2a 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -12,15 +12,17 @@ | |||
12 | * 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably | 12 | * 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably |
13 | * kill the offending process. | 13 | * kill the offending process. |
14 | */ | 14 | */ |
15 | #include <linux/module.h> | ||
16 | #include <linux/signal.h> | 15 | #include <linux/signal.h> |
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/personality.h> | 16 | #include <linux/personality.h> |
19 | #include <linux/kallsyms.h> | 17 | #include <linux/kallsyms.h> |
20 | #include <linux/delay.h> | 18 | #include <linux/spinlock.h> |
19 | #include <linux/uaccess.h> | ||
21 | #include <linux/hardirq.h> | 20 | #include <linux/hardirq.h> |
21 | #include <linux/kdebug.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/kexec.h> | ||
24 | #include <linux/delay.h> | ||
22 | #include <linux/init.h> | 25 | #include <linux/init.h> |
23 | #include <linux/uaccess.h> | ||
24 | 26 | ||
25 | #include <asm/atomic.h> | 27 | #include <asm/atomic.h> |
26 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
@@ -224,14 +226,21 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) | |||
224 | #define S_SMP "" | 226 | #define S_SMP "" |
225 | #endif | 227 | #endif |
226 | 228 | ||
227 | static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) | 229 | static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) |
228 | { | 230 | { |
229 | struct task_struct *tsk = thread->task; | 231 | struct task_struct *tsk = thread->task; |
230 | static int die_counter; | 232 | static int die_counter; |
233 | int ret; | ||
231 | 234 | ||
232 | printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", | 235 | printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", |
233 | str, err, ++die_counter); | 236 | str, err, ++die_counter); |
234 | sysfs_printk_last_file(); | 237 | sysfs_printk_last_file(); |
238 | |||
239 | /* trap and error numbers are mostly meaningless on ARM */ | ||
240 | ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); | ||
241 | if (ret == NOTIFY_STOP) | ||
242 | return ret; | ||
243 | |||
235 | print_modules(); | 244 | print_modules(); |
236 | __show_regs(regs); | 245 | __show_regs(regs); |
237 | printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", | 246 | printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", |
@@ -243,6 +252,8 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p | |||
243 | dump_backtrace(regs, tsk); | 252 | dump_backtrace(regs, tsk); |
244 | dump_instr(KERN_EMERG, regs); | 253 | dump_instr(KERN_EMERG, regs); |
245 | } | 254 | } |
255 | |||
256 | return ret; | ||
246 | } | 257 | } |
247 | 258 | ||
248 | DEFINE_SPINLOCK(die_lock); | 259 | DEFINE_SPINLOCK(die_lock); |
@@ -250,16 +261,21 @@ DEFINE_SPINLOCK(die_lock); | |||
250 | /* | 261 | /* |
251 | * This function is protected against re-entrancy. | 262 | * This function is protected against re-entrancy. |
252 | */ | 263 | */ |
253 | NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) | 264 | void die(const char *str, struct pt_regs *regs, int err) |
254 | { | 265 | { |
255 | struct thread_info *thread = current_thread_info(); | 266 | struct thread_info *thread = current_thread_info(); |
267 | int ret; | ||
256 | 268 | ||
257 | oops_enter(); | 269 | oops_enter(); |
258 | 270 | ||
259 | spin_lock_irq(&die_lock); | 271 | spin_lock_irq(&die_lock); |
260 | console_verbose(); | 272 | console_verbose(); |
261 | bust_spinlocks(1); | 273 | bust_spinlocks(1); |
262 | __die(str, err, thread, regs); | 274 | ret = __die(str, err, thread, regs); |
275 | |||
276 | if (regs && kexec_should_crash(thread->task)) | ||
277 | crash_kexec(regs); | ||
278 | |||
263 | bust_spinlocks(0); | 279 | bust_spinlocks(0); |
264 | add_taint(TAINT_DIE); | 280 | add_taint(TAINT_DIE); |
265 | spin_unlock_irq(&die_lock); | 281 | spin_unlock_irq(&die_lock); |
@@ -267,11 +283,10 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) | |||
267 | 283 | ||
268 | if (in_interrupt()) | 284 | if (in_interrupt()) |
269 | panic("Fatal exception in interrupt"); | 285 | panic("Fatal exception in interrupt"); |
270 | |||
271 | if (panic_on_oops) | 286 | if (panic_on_oops) |
272 | panic("Fatal exception"); | 287 | panic("Fatal exception"); |
273 | 288 | if (ret != NOTIFY_STOP) | |
274 | do_exit(SIGSEGV); | 289 | do_exit(SIGSEGV); |
275 | } | 290 | } |
276 | 291 | ||
277 | void arm_notify_die(const char *str, struct pt_regs *regs, | 292 | void arm_notify_die(const char *str, struct pt_regs *regs, |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 4957e13ef55b..b16c07914b55 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -43,10 +43,6 @@ SECTIONS | |||
43 | 43 | ||
44 | INIT_SETUP(16) | 44 | INIT_SETUP(16) |
45 | 45 | ||
46 | __early_begin = .; | ||
47 | *(.early_param.init) | ||
48 | __early_end = .; | ||
49 | |||
50 | INIT_CALLS | 46 | INIT_CALLS |
51 | CON_INITCALL | 47 | CON_INITCALL |
52 | SECURITY_INITCALL | 48 | SECURITY_INITCALL |