diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2005-11-03 20:12:52 -0500 |
---|---|---|
committer | Michael Ellerman <michael@ellerman.id.au> | 2005-11-03 20:12:52 -0500 |
commit | dc3a9efb5ee89493a42c3365d219e339e4720c2b (patch) | |
tree | a0d261c2933f3083f351c858b01de7677356d4b7 /arch | |
parent | 30415f6a63f3383a18e9adf7c144acabe6893f63 (diff) | |
parent | d3ab57ebdc6457543b346255fa47b0ecd7671136 (diff) |
Merge with Paulus
Diffstat (limited to 'arch')
21 files changed, 300 insertions, 175 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 1c44a1dac421..3cf03ab46113 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -278,7 +278,6 @@ config PPC_PSERIES | |||
278 | select PPC_I8259 | 278 | select PPC_I8259 |
279 | select PPC_RTAS | 279 | select PPC_RTAS |
280 | select RTAS_ERROR_LOGGING | 280 | select RTAS_ERROR_LOGGING |
281 | select RTAS_FW | ||
282 | default y | 281 | default y |
283 | 282 | ||
284 | config PPC_CHRP | 283 | config PPC_CHRP |
@@ -324,7 +323,6 @@ config PPC_CELL | |||
324 | bool " Cell Broadband Processor Architecture" | 323 | bool " Cell Broadband Processor Architecture" |
325 | depends on PPC_MULTIPLATFORM && PPC64 | 324 | depends on PPC_MULTIPLATFORM && PPC64 |
326 | select PPC_RTAS | 325 | select PPC_RTAS |
327 | select RTAS_FW | ||
328 | select MMIO_NVRAM | 326 | select MMIO_NVRAM |
329 | 327 | ||
330 | config PPC_OF | 328 | config PPC_OF |
@@ -356,10 +354,14 @@ config RTAS_ERROR_LOGGING | |||
356 | depends on PPC_RTAS | 354 | depends on PPC_RTAS |
357 | default n | 355 | default n |
358 | 356 | ||
359 | config RTAS_FW | 357 | config RTAS_PROC |
360 | bool | 358 | bool "Proc interface to RTAS" |
361 | depends on PPC_RTAS | 359 | depends on PPC_RTAS |
362 | default n | 360 | default y |
361 | |||
362 | config RTAS_FLASH | ||
363 | tristate "Firmware flash interface" | ||
364 | depends on PPC64 && RTAS_PROC | ||
363 | 365 | ||
364 | config MMIO_NVRAM | 366 | config MMIO_NVRAM |
365 | bool | 367 | bool |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index abad3059a21a..7a3e1155ac9a 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -13,12 +13,13 @@ endif | |||
13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ | 13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ |
14 | signal_32.o pmc.o | 14 | signal_32.o pmc.o |
15 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 15 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ |
16 | ptrace32.o systbl.o | 16 | signal_64.o ptrace32.o systbl.o |
17 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o | 17 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o |
18 | obj-$(CONFIG_POWER4) += idle_power4.o | 18 | obj-$(CONFIG_POWER4) += idle_power4.o |
19 | obj-$(CONFIG_PPC_OF) += of_device.o | 19 | obj-$(CONFIG_PPC_OF) += of_device.o |
20 | obj-$(CONFIG_PPC_RTAS) += rtas.o | 20 | obj-$(CONFIG_PPC_RTAS) += rtas.o |
21 | obj-$(CONFIG_RTAS_FW) += rtas_fw.o | 21 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
22 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | ||
22 | obj-$(CONFIG_IBMVIO) += vio.o | 23 | obj-$(CONFIG_IBMVIO) += vio.o |
23 | 24 | ||
24 | ifeq ($(CONFIG_PPC_MERGE),y) | 25 | ifeq ($(CONFIG_PPC_MERGE),y) |
diff --git a/arch/powerpc/kernel/ppc32.h b/arch/powerpc/kernel/ppc32.h new file mode 100644 index 000000000000..90e562771791 --- /dev/null +++ b/arch/powerpc/kernel/ppc32.h | |||
@@ -0,0 +1,138 @@ | |||
1 | #ifndef _PPC64_PPC32_H | ||
2 | #define _PPC64_PPC32_H | ||
3 | |||
4 | #include <linux/compat.h> | ||
5 | #include <asm/siginfo.h> | ||
6 | #include <asm/signal.h> | ||
7 | |||
8 | /* | ||
9 | * Data types and macros for providing 32b PowerPC support. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | /* These are here to support 32-bit syscalls on a 64-bit kernel. */ | ||
18 | |||
19 | typedef struct compat_siginfo { | ||
20 | int si_signo; | ||
21 | int si_errno; | ||
22 | int si_code; | ||
23 | |||
24 | union { | ||
25 | int _pad[SI_PAD_SIZE32]; | ||
26 | |||
27 | /* kill() */ | ||
28 | struct { | ||
29 | compat_pid_t _pid; /* sender's pid */ | ||
30 | compat_uid_t _uid; /* sender's uid */ | ||
31 | } _kill; | ||
32 | |||
33 | /* POSIX.1b timers */ | ||
34 | struct { | ||
35 | compat_timer_t _tid; /* timer id */ | ||
36 | int _overrun; /* overrun count */ | ||
37 | compat_sigval_t _sigval; /* same as below */ | ||
38 | int _sys_private; /* not to be passed to user */ | ||
39 | } _timer; | ||
40 | |||
41 | /* POSIX.1b signals */ | ||
42 | struct { | ||
43 | compat_pid_t _pid; /* sender's pid */ | ||
44 | compat_uid_t _uid; /* sender's uid */ | ||
45 | compat_sigval_t _sigval; | ||
46 | } _rt; | ||
47 | |||
48 | /* SIGCHLD */ | ||
49 | struct { | ||
50 | compat_pid_t _pid; /* which child */ | ||
51 | compat_uid_t _uid; /* sender's uid */ | ||
52 | int _status; /* exit code */ | ||
53 | compat_clock_t _utime; | ||
54 | compat_clock_t _stime; | ||
55 | } _sigchld; | ||
56 | |||
57 | /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */ | ||
58 | struct { | ||
59 | unsigned int _addr; /* faulting insn/memory ref. */ | ||
60 | } _sigfault; | ||
61 | |||
62 | /* SIGPOLL */ | ||
63 | struct { | ||
64 | int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ | ||
65 | int _fd; | ||
66 | } _sigpoll; | ||
67 | } _sifields; | ||
68 | } compat_siginfo_t; | ||
69 | |||
70 | #define __old_sigaction32 old_sigaction32 | ||
71 | |||
72 | struct __old_sigaction32 { | ||
73 | compat_uptr_t sa_handler; | ||
74 | compat_old_sigset_t sa_mask; | ||
75 | unsigned int sa_flags; | ||
76 | compat_uptr_t sa_restorer; /* not used by Linux/SPARC yet */ | ||
77 | }; | ||
78 | |||
79 | |||
80 | |||
81 | struct sigaction32 { | ||
82 | compat_uptr_t sa_handler; /* Really a pointer, but need to deal with 32 bits */ | ||
83 | unsigned int sa_flags; | ||
84 | compat_uptr_t sa_restorer; /* Another 32 bit pointer */ | ||
85 | compat_sigset_t sa_mask; /* A 32 bit mask */ | ||
86 | }; | ||
87 | |||
88 | typedef struct sigaltstack_32 { | ||
89 | unsigned int ss_sp; | ||
90 | int ss_flags; | ||
91 | compat_size_t ss_size; | ||
92 | } stack_32_t; | ||
93 | |||
94 | struct pt_regs32 { | ||
95 | unsigned int gpr[32]; | ||
96 | unsigned int nip; | ||
97 | unsigned int msr; | ||
98 | unsigned int orig_gpr3; /* Used for restarting system calls */ | ||
99 | unsigned int ctr; | ||
100 | unsigned int link; | ||
101 | unsigned int xer; | ||
102 | unsigned int ccr; | ||
103 | unsigned int mq; /* 601 only (not used at present) */ | ||
104 | unsigned int trap; /* Reason for being here */ | ||
105 | unsigned int dar; /* Fault registers */ | ||
106 | unsigned int dsisr; | ||
107 | unsigned int result; /* Result of a system call */ | ||
108 | }; | ||
109 | |||
110 | struct sigcontext32 { | ||
111 | unsigned int _unused[4]; | ||
112 | int signal; | ||
113 | compat_uptr_t handler; | ||
114 | unsigned int oldmask; | ||
115 | compat_uptr_t regs; /* 4 byte pointer to the pt_regs32 structure. */ | ||
116 | }; | ||
117 | |||
118 | struct mcontext32 { | ||
119 | elf_gregset_t32 mc_gregs; | ||
120 | elf_fpregset_t mc_fregs; | ||
121 | unsigned int mc_pad[2]; | ||
122 | elf_vrregset_t32 mc_vregs __attribute__((__aligned__(16))); | ||
123 | }; | ||
124 | |||
125 | struct ucontext32 { | ||
126 | unsigned int uc_flags; | ||
127 | unsigned int uc_link; | ||
128 | stack_32_t uc_stack; | ||
129 | int uc_pad[7]; | ||
130 | compat_uptr_t uc_regs; /* points to uc_mcontext field */ | ||
131 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ | ||
132 | /* glibc has 1024-bit signal masks, ours are 64-bit */ | ||
133 | int uc_maskext[30]; | ||
134 | int uc_pad2[3]; | ||
135 | struct mcontext32 uc_mcontext; | ||
136 | }; | ||
137 | |||
138 | #endif /* _PPC64_PPC32_H */ | ||
diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 5bdd5b079d96..5bdd5b079d96 100644 --- a/arch/ppc64/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4d22eeeeb91d..b7fc2d884950 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -43,6 +43,13 @@ char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned; | |||
43 | unsigned long rtas_rmo_buf; | 43 | unsigned long rtas_rmo_buf; |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * If non-NULL, this gets called when the kernel terminates. | ||
47 | * This is done like this so rtas_flash can be a module. | ||
48 | */ | ||
49 | void (*rtas_flash_term_hook)(int); | ||
50 | EXPORT_SYMBOL(rtas_flash_term_hook); | ||
51 | |||
52 | /* | ||
46 | * call_rtas_display_status and call_rtas_display_status_delay | 53 | * call_rtas_display_status and call_rtas_display_status_delay |
47 | * are designed only for very early low-level debugging, which | 54 | * are designed only for very early low-level debugging, which |
48 | * is why the token is hard-coded to 10. | 55 | * is why the token is hard-coded to 10. |
@@ -206,6 +213,7 @@ void rtas_progress(char *s, unsigned short hex) | |||
206 | 213 | ||
207 | spin_unlock(&progress_lock); | 214 | spin_unlock(&progress_lock); |
208 | } | 215 | } |
216 | EXPORT_SYMBOL(rtas_progress); /* needed by rtas_flash module */ | ||
209 | 217 | ||
210 | int rtas_token(const char *service) | 218 | int rtas_token(const char *service) |
211 | { | 219 | { |
@@ -492,6 +500,8 @@ int rtas_set_indicator(int indicator, int index, int new_value) | |||
492 | 500 | ||
493 | void rtas_restart(char *cmd) | 501 | void rtas_restart(char *cmd) |
494 | { | 502 | { |
503 | if (rtas_flash_term_hook) | ||
504 | rtas_flash_term_hook(SYS_RESTART); | ||
495 | printk("RTAS system-reboot returned %d\n", | 505 | printk("RTAS system-reboot returned %d\n", |
496 | rtas_call(rtas_token("system-reboot"), 0, 1, NULL)); | 506 | rtas_call(rtas_token("system-reboot"), 0, 1, NULL)); |
497 | for (;;); | 507 | for (;;); |
@@ -499,6 +509,8 @@ void rtas_restart(char *cmd) | |||
499 | 509 | ||
500 | void rtas_power_off(void) | 510 | void rtas_power_off(void) |
501 | { | 511 | { |
512 | if (rtas_flash_term_hook) | ||
513 | rtas_flash_term_hook(SYS_POWER_OFF); | ||
502 | /* allow power on only with power button press */ | 514 | /* allow power on only with power button press */ |
503 | printk("RTAS power-off returned %d\n", | 515 | printk("RTAS power-off returned %d\n", |
504 | rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1)); | 516 | rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1)); |
@@ -507,7 +519,12 @@ void rtas_power_off(void) | |||
507 | 519 | ||
508 | void rtas_halt(void) | 520 | void rtas_halt(void) |
509 | { | 521 | { |
510 | rtas_power_off(); | 522 | if (rtas_flash_term_hook) |
523 | rtas_flash_term_hook(SYS_HALT); | ||
524 | /* allow power on only with power button press */ | ||
525 | printk("RTAS power-off returned %d\n", | ||
526 | rtas_call(rtas_token("power-off"), 2, 1, NULL, -1, -1)); | ||
527 | for (;;); | ||
511 | } | 528 | } |
512 | 529 | ||
513 | /* Must be in the RMO region, so we place it here */ | 530 | /* Must be in the RMO region, so we place it here */ |
diff --git a/arch/ppc64/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 923e2e201a70..50500093c97f 100644 --- a/arch/ppc64/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/delay.h> | 19 | #include <asm/delay.h> |
20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
21 | #include <asm/rtas.h> | 21 | #include <asm/rtas.h> |
22 | #include <asm/abs_addr.h> | ||
22 | 23 | ||
23 | #define MODULE_VERS "1.0" | 24 | #define MODULE_VERS "1.0" |
24 | #define MODULE_NAME "rtas_flash" | 25 | #define MODULE_NAME "rtas_flash" |
@@ -71,10 +72,36 @@ | |||
71 | #define VALIDATE_BUF_SIZE 4096 | 72 | #define VALIDATE_BUF_SIZE 4096 |
72 | #define RTAS_MSG_MAXLEN 64 | 73 | #define RTAS_MSG_MAXLEN 64 |
73 | 74 | ||
75 | struct flash_block { | ||
76 | char *data; | ||
77 | unsigned long length; | ||
78 | }; | ||
79 | |||
80 | /* This struct is very similar but not identical to | ||
81 | * that needed by the rtas flash update. | ||
82 | * All we need to do for rtas is rewrite num_blocks | ||
83 | * into a version/length and translate the pointers | ||
84 | * to absolute. | ||
85 | */ | ||
86 | #define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) | ||
87 | struct flash_block_list { | ||
88 | unsigned long num_blocks; | ||
89 | struct flash_block_list *next; | ||
90 | struct flash_block blocks[FLASH_BLOCKS_PER_NODE]; | ||
91 | }; | ||
92 | struct flash_block_list_header { /* just the header of flash_block_list */ | ||
93 | unsigned long num_blocks; | ||
94 | struct flash_block_list *next; | ||
95 | }; | ||
96 | |||
97 | static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; | ||
98 | |||
99 | #define FLASH_BLOCK_LIST_VERSION (1UL) | ||
100 | |||
74 | /* Local copy of the flash block list. | 101 | /* Local copy of the flash block list. |
75 | * We only allow one open of the flash proc file and create this | 102 | * We only allow one open of the flash proc file and create this |
76 | * list as we go. This list will be put in the kernel's | 103 | * list as we go. This list will be put in the |
77 | * rtas_firmware_flash_list global var once it is fully read. | 104 | * rtas_firmware_flash_list var once it is fully read. |
78 | * | 105 | * |
79 | * For convenience as we build the list we use virtual addrs, | 106 | * For convenience as we build the list we use virtual addrs, |
80 | * we do not fill in the version number, and the length field | 107 | * we do not fill in the version number, and the length field |
@@ -562,6 +589,86 @@ static int validate_flash_release(struct inode *inode, struct file *file) | |||
562 | return 0; | 589 | return 0; |
563 | } | 590 | } |
564 | 591 | ||
592 | static void rtas_flash_firmware(int reboot_type) | ||
593 | { | ||
594 | unsigned long image_size; | ||
595 | struct flash_block_list *f, *next, *flist; | ||
596 | unsigned long rtas_block_list; | ||
597 | int i, status, update_token; | ||
598 | |||
599 | if (rtas_firmware_flash_list.next == NULL) | ||
600 | return; /* nothing to do */ | ||
601 | |||
602 | if (reboot_type != SYS_RESTART) { | ||
603 | printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); | ||
604 | printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); | ||
605 | return; | ||
606 | } | ||
607 | |||
608 | update_token = rtas_token("ibm,update-flash-64-and-reboot"); | ||
609 | if (update_token == RTAS_UNKNOWN_SERVICE) { | ||
610 | printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot " | ||
611 | "is not available -- not a service partition?\n"); | ||
612 | printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); | ||
613 | return; | ||
614 | } | ||
615 | |||
616 | /* NOTE: the "first" block list is a global var with no data | ||
617 | * blocks in the kernel data segment. We do this because | ||
618 | * we want to ensure this block_list addr is under 4GB. | ||
619 | */ | ||
620 | rtas_firmware_flash_list.num_blocks = 0; | ||
621 | flist = (struct flash_block_list *)&rtas_firmware_flash_list; | ||
622 | rtas_block_list = virt_to_abs(flist); | ||
623 | if (rtas_block_list >= 4UL*1024*1024*1024) { | ||
624 | printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); | ||
625 | return; | ||
626 | } | ||
627 | |||
628 | printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); | ||
629 | /* Update the block_list in place. */ | ||
630 | image_size = 0; | ||
631 | for (f = flist; f; f = next) { | ||
632 | /* Translate data addrs to absolute */ | ||
633 | for (i = 0; i < f->num_blocks; i++) { | ||
634 | f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data); | ||
635 | image_size += f->blocks[i].length; | ||
636 | } | ||
637 | next = f->next; | ||
638 | /* Don't translate NULL pointer for last entry */ | ||
639 | if (f->next) | ||
640 | f->next = (struct flash_block_list *)virt_to_abs(f->next); | ||
641 | else | ||
642 | f->next = NULL; | ||
643 | /* make num_blocks into the version/length field */ | ||
644 | f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); | ||
645 | } | ||
646 | |||
647 | printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); | ||
648 | printk(KERN_ALERT "FLASH: performing flash and reboot\n"); | ||
649 | rtas_progress("Flashing \n", 0x0); | ||
650 | rtas_progress("Please Wait... ", 0x0); | ||
651 | printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); | ||
652 | status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); | ||
653 | switch (status) { /* should only get "bad" status */ | ||
654 | case 0: | ||
655 | printk(KERN_ALERT "FLASH: success\n"); | ||
656 | break; | ||
657 | case -1: | ||
658 | printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); | ||
659 | break; | ||
660 | case -3: | ||
661 | printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); | ||
662 | break; | ||
663 | case -4: | ||
664 | printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); | ||
665 | break; | ||
666 | default: | ||
667 | printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); | ||
668 | break; | ||
669 | } | ||
670 | } | ||
671 | |||
565 | static void remove_flash_pde(struct proc_dir_entry *dp) | 672 | static void remove_flash_pde(struct proc_dir_entry *dp) |
566 | { | 673 | { |
567 | if (dp) { | 674 | if (dp) { |
@@ -701,6 +808,7 @@ int __init rtas_flash_init(void) | |||
701 | if (rc != 0) | 808 | if (rc != 0) |
702 | goto cleanup; | 809 | goto cleanup; |
703 | 810 | ||
811 | rtas_flash_term_hook = rtas_flash_firmware; | ||
704 | return 0; | 812 | return 0; |
705 | 813 | ||
706 | cleanup: | 814 | cleanup: |
@@ -714,6 +822,7 @@ cleanup: | |||
714 | 822 | ||
715 | void __exit rtas_flash_cleanup(void) | 823 | void __exit rtas_flash_cleanup(void) |
716 | { | 824 | { |
825 | rtas_flash_term_hook = NULL; | ||
717 | remove_flash_pde(firmware_flash_pde); | 826 | remove_flash_pde(firmware_flash_pde); |
718 | remove_flash_pde(firmware_update_pde); | 827 | remove_flash_pde(firmware_update_pde); |
719 | remove_flash_pde(validate_pde); | 828 | remove_flash_pde(validate_pde); |
diff --git a/arch/powerpc/kernel/rtas_fw.c b/arch/powerpc/kernel/rtas_fw.c deleted file mode 100644 index 448922e8af1b..000000000000 --- a/arch/powerpc/kernel/rtas_fw.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Procedures for firmware flash updates. | ||
4 | * | ||
5 | * Peter Bergner, IBM March 2001. | ||
6 | * Copyright (C) 2001 IBM. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <stdarg.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/init.h> | ||
20 | |||
21 | #include <asm/prom.h> | ||
22 | #include <asm/rtas.h> | ||
23 | #include <asm/semaphore.h> | ||
24 | #include <asm/machdep.h> | ||
25 | #include <asm/page.h> | ||
26 | #include <asm/param.h> | ||
27 | #include <asm/system.h> | ||
28 | #include <asm/abs_addr.h> | ||
29 | #include <asm/udbg.h> | ||
30 | #include <asm/delay.h> | ||
31 | #include <asm/uaccess.h> | ||
32 | #include <asm/systemcfg.h> | ||
33 | |||
34 | struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; | ||
35 | |||
36 | #define FLASH_BLOCK_LIST_VERSION (1UL) | ||
37 | |||
38 | static void rtas_flash_firmware(void) | ||
39 | { | ||
40 | unsigned long image_size; | ||
41 | struct flash_block_list *f, *next, *flist; | ||
42 | unsigned long rtas_block_list; | ||
43 | int i, status, update_token; | ||
44 | |||
45 | update_token = rtas_token("ibm,update-flash-64-and-reboot"); | ||
46 | if (update_token == RTAS_UNKNOWN_SERVICE) { | ||
47 | printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n"); | ||
48 | printk(KERN_ALERT "FLASH: firmware will not be flashed\n"); | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | /* NOTE: the "first" block list is a global var with no data | ||
53 | * blocks in the kernel data segment. We do this because | ||
54 | * we want to ensure this block_list addr is under 4GB. | ||
55 | */ | ||
56 | rtas_firmware_flash_list.num_blocks = 0; | ||
57 | flist = (struct flash_block_list *)&rtas_firmware_flash_list; | ||
58 | rtas_block_list = virt_to_abs(flist); | ||
59 | if (rtas_block_list >= 4UL*1024*1024*1024) { | ||
60 | printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n"); | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n"); | ||
65 | /* Update the block_list in place. */ | ||
66 | image_size = 0; | ||
67 | for (f = flist; f; f = next) { | ||
68 | /* Translate data addrs to absolute */ | ||
69 | for (i = 0; i < f->num_blocks; i++) { | ||
70 | f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data); | ||
71 | image_size += f->blocks[i].length; | ||
72 | } | ||
73 | next = f->next; | ||
74 | /* Don't translate NULL pointer for last entry */ | ||
75 | if (f->next) | ||
76 | f->next = (struct flash_block_list *)virt_to_abs(f->next); | ||
77 | else | ||
78 | f->next = NULL; | ||
79 | /* make num_blocks into the version/length field */ | ||
80 | f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); | ||
81 | } | ||
82 | |||
83 | printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size); | ||
84 | printk(KERN_ALERT "FLASH: performing flash and reboot\n"); | ||
85 | rtas_progress("Flashing \n", 0x0); | ||
86 | rtas_progress("Please Wait... ", 0x0); | ||
87 | printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n"); | ||
88 | status = rtas_call(update_token, 1, 1, NULL, rtas_block_list); | ||
89 | switch (status) { /* should only get "bad" status */ | ||
90 | case 0: | ||
91 | printk(KERN_ALERT "FLASH: success\n"); | ||
92 | break; | ||
93 | case -1: | ||
94 | printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n"); | ||
95 | break; | ||
96 | case -3: | ||
97 | printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n"); | ||
98 | break; | ||
99 | case -4: | ||
100 | printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n"); | ||
101 | break; | ||
102 | default: | ||
103 | printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status); | ||
104 | break; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | void rtas_flash_bypass_warning(void) | ||
109 | { | ||
110 | printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n"); | ||
111 | printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n"); | ||
112 | } | ||
113 | |||
114 | |||
115 | void rtas_fw_restart(char *cmd) | ||
116 | { | ||
117 | if (rtas_firmware_flash_list.next) | ||
118 | rtas_flash_firmware(); | ||
119 | rtas_restart(cmd); | ||
120 | } | ||
121 | |||
122 | void rtas_fw_power_off(void) | ||
123 | { | ||
124 | if (rtas_firmware_flash_list.next) | ||
125 | rtas_flash_bypass_warning(); | ||
126 | rtas_power_off(); | ||
127 | } | ||
128 | |||
129 | void rtas_fw_halt(void) | ||
130 | { | ||
131 | if (rtas_firmware_flash_list.next) | ||
132 | rtas_flash_bypass_warning(); | ||
133 | rtas_halt(); | ||
134 | } | ||
135 | |||
136 | EXPORT_SYMBOL(rtas_firmware_flash_list); | ||
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 444c3e81884c..876c57c11365 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | #ifdef CONFIG_PPC64 | 45 | #ifdef CONFIG_PPC64 |
46 | #include <asm/ppc32.h> | 46 | #include "ppc32.h" |
47 | #include <asm/ppcdebug.h> | 47 | #include <asm/ppcdebug.h> |
48 | #include <asm/unistd.h> | 48 | #include <asm/unistd.h> |
49 | #include <asm/vdso.h> | 49 | #include <asm/vdso.h> |
diff --git a/arch/ppc64/kernel/signal.c b/arch/powerpc/kernel/signal_64.c index ec9d0984b6a0..ec9d0984b6a0 100644 --- a/arch/ppc64/kernel/signal.c +++ b/arch/powerpc/kernel/signal_64.c | |||
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index d8bdaaf74c9b..80b58c1ec412 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -351,7 +351,7 @@ void __init pmac_setup_arch(void) | |||
351 | find_via_pmu(); | 351 | find_via_pmu(); |
352 | smu_init(); | 352 | smu_init(); |
353 | 353 | ||
354 | #ifdef CONFIG_NVRAM | 354 | #if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64) |
355 | pmac_nvram_init(); | 355 | pmac_nvram_init(); |
356 | #endif | 356 | #endif |
357 | 357 | ||
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 2d57f588151d..e3fc3407bb1f 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -21,15 +21,6 @@ config EEH | |||
21 | depends on PPC_PSERIES | 21 | depends on PPC_PSERIES |
22 | default y if !EMBEDDED | 22 | default y if !EMBEDDED |
23 | 23 | ||
24 | config RTAS_PROC | ||
25 | bool "Proc interface to RTAS" | ||
26 | depends on PPC_RTAS | ||
27 | default y | ||
28 | |||
29 | config RTAS_FLASH | ||
30 | tristate "Firmware flash interface" | ||
31 | depends on PPC64 && RTAS_PROC | ||
32 | |||
33 | config SCANLOG | 24 | config SCANLOG |
34 | tristate "Scanlog dump interface" | 25 | tristate "Scanlog dump interface" |
35 | depends on RTAS_PROC && PPC_PSERIES | 26 | depends on RTAS_PROC && PPC_PSERIES |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 91909a844736..b9938fece781 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ | 1 | obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ |
2 | setup.o iommu.o ras.o | 2 | setup.o iommu.o ras.o rtasd.o |
3 | obj-$(CONFIG_SMP) += smp.o | 3 | obj-$(CONFIG_SMP) += smp.o |
4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 5 | obj-$(CONFIG_XICS) += xics.o |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 9e58a1922109..513e27231493 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -499,7 +499,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti | |||
499 | 499 | ||
500 | switch (action) { | 500 | switch (action) { |
501 | case PSERIES_RECONFIG_REMOVE: | 501 | case PSERIES_RECONFIG_REMOVE: |
502 | if (pci->iommu_table && | 502 | if (pci && pci->iommu_table && |
503 | get_property(np, "ibm,dma-window", NULL)) | 503 | get_property(np, "ibm,dma-window", NULL)) |
504 | iommu_free_table(np); | 504 | iommu_free_table(np); |
505 | break; | 505 | break; |
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index e26b0420b6dd..e26b0420b6dd 100644 --- a/arch/ppc64/kernel/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index d54e1e4c7c63..65bee939eecc 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -602,9 +602,9 @@ struct machdep_calls __initdata pSeries_md = { | |||
602 | .pcibios_fixup = pSeries_final_fixup, | 602 | .pcibios_fixup = pSeries_final_fixup, |
603 | .pci_probe_mode = pSeries_pci_probe_mode, | 603 | .pci_probe_mode = pSeries_pci_probe_mode, |
604 | .irq_bus_setup = pSeries_irq_bus_setup, | 604 | .irq_bus_setup = pSeries_irq_bus_setup, |
605 | .restart = rtas_fw_restart, | 605 | .restart = rtas_restart, |
606 | .power_off = rtas_fw_power_off, | 606 | .power_off = rtas_power_off, |
607 | .halt = rtas_fw_halt, | 607 | .halt = rtas_halt, |
608 | .panic = rtas_os_term, | 608 | .panic = rtas_os_term, |
609 | .cpu_die = pSeries_mach_cpu_die, | 609 | .cpu_die = pSeries_mach_cpu_die, |
610 | .get_boot_time = rtas_get_boot_time, | 610 | .get_boot_time = rtas_get_boot_time, |
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c index b42789f8eb76..579cd40258b9 100644 --- a/arch/ppc/8xx_io/commproc.c +++ b/arch/ppc/8xx_io/commproc.c | |||
@@ -388,9 +388,8 @@ void m8xx_cpm_dpinit(void) | |||
388 | 388 | ||
389 | /* | 389 | /* |
390 | * Allocate the requested size worth of DP memory. | 390 | * Allocate the requested size worth of DP memory. |
391 | * This function used to return an index into the DPRAM area. | 391 | * This function returns an offset into the DPRAM area. |
392 | * Now it returns the actuall physical address of that area. | 392 | * Use cpm_dpram_addr() to get the virtual address of the area. |
393 | * use m8xx_cpm_dpram_offset() to get the index | ||
394 | */ | 393 | */ |
395 | uint cpm_dpalloc(uint size, uint align) | 394 | uint cpm_dpalloc(uint size, uint align) |
396 | { | 395 | { |
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index ae24196d78f6..e0ca61b37f4f 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c | |||
@@ -131,6 +131,11 @@ EXPORT_SYMBOL(outw); | |||
131 | EXPORT_SYMBOL(outl); | 131 | EXPORT_SYMBOL(outl); |
132 | EXPORT_SYMBOL(outsl);*/ | 132 | EXPORT_SYMBOL(outsl);*/ |
133 | 133 | ||
134 | EXPORT_SYMBOL(__ide_mm_insl); | ||
135 | EXPORT_SYMBOL(__ide_mm_outsw); | ||
136 | EXPORT_SYMBOL(__ide_mm_insw); | ||
137 | EXPORT_SYMBOL(__ide_mm_outsl); | ||
138 | |||
134 | EXPORT_SYMBOL(_insb); | 139 | EXPORT_SYMBOL(_insb); |
135 | EXPORT_SYMBOL(_outsb); | 140 | EXPORT_SYMBOL(_outsb); |
136 | EXPORT_SYMBOL(_insw); | 141 | EXPORT_SYMBOL(_insw); |
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index f265b81e7008..16adde6b429d 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c | |||
@@ -606,22 +606,22 @@ int check_bug_trap(struct pt_regs *regs) | |||
606 | if (bug->line & BUG_WARNING_TRAP) { | 606 | if (bug->line & BUG_WARNING_TRAP) { |
607 | /* this is a WARN_ON rather than BUG/BUG_ON */ | 607 | /* this is a WARN_ON rather than BUG/BUG_ON */ |
608 | #ifdef CONFIG_XMON | 608 | #ifdef CONFIG_XMON |
609 | xmon_printf(KERN_ERR "Badness in %s at %s:%d\n", | 609 | xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n", |
610 | bug->function, bug->file, | 610 | bug->function, bug->file, |
611 | bug->line & ~BUG_WARNING_TRAP); | 611 | bug->line & ~BUG_WARNING_TRAP); |
612 | #endif /* CONFIG_XMON */ | 612 | #endif /* CONFIG_XMON */ |
613 | printk(KERN_ERR "Badness in %s at %s:%d\n", | 613 | printk(KERN_ERR "Badness in %s at %s:%ld\n", |
614 | bug->function, bug->file, | 614 | bug->function, bug->file, |
615 | bug->line & ~BUG_WARNING_TRAP); | 615 | bug->line & ~BUG_WARNING_TRAP); |
616 | dump_stack(); | 616 | dump_stack(); |
617 | return 1; | 617 | return 1; |
618 | } | 618 | } |
619 | #ifdef CONFIG_XMON | 619 | #ifdef CONFIG_XMON |
620 | xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%d!\n", | 620 | xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", |
621 | bug->function, bug->file, bug->line); | 621 | bug->function, bug->file, bug->line); |
622 | xmon(regs); | 622 | xmon(regs); |
623 | #endif /* CONFIG_XMON */ | 623 | #endif /* CONFIG_XMON */ |
624 | printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", | 624 | printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", |
625 | bug->function, bug->file, bug->line); | 625 | bug->function, bug->file, bug->line); |
626 | 626 | ||
627 | return 0; | 627 | return 0; |
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c index 97ffbc70574f..1cc3abe6fa43 100644 --- a/arch/ppc/syslib/m8xx_setup.c +++ b/arch/ppc/syslib/m8xx_setup.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/bootinfo.h> | 45 | #include <asm/bootinfo.h> |
46 | #include <asm/time.h> | 46 | #include <asm/time.h> |
47 | #include <asm/xmon.h> | 47 | #include <asm/xmon.h> |
48 | #include <asm/ppc_sys.h> | ||
48 | 49 | ||
49 | #include "ppc8xx_pic.h" | 50 | #include "ppc8xx_pic.h" |
50 | 51 | ||
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index 990df0905c87..430cb3900a07 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile | |||
@@ -12,7 +12,6 @@ obj-y := misc.o prom.o | |||
12 | endif | 12 | endif |
13 | 13 | ||
14 | obj-y += irq.o idle.o dma.o \ | 14 | obj-y += irq.o idle.o dma.o \ |
15 | signal.o \ | ||
16 | align.o pacaData.o \ | 15 | align.o pacaData.o \ |
17 | udbg.o ioctl32.o \ | 16 | udbg.o ioctl32.o \ |
18 | rtc.o \ | 17 | rtc.o \ |
@@ -29,19 +28,17 @@ ifneq ($(CONFIG_PPC_MERGE),y) | |||
29 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o | 28 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o |
30 | endif | 29 | endif |
31 | 30 | ||
32 | obj-$(CONFIG_PPC_PSERIES) += rtasd.o udbg_16550.o | 31 | obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o |
33 | 32 | ||
34 | obj-$(CONFIG_KEXEC) += machine_kexec.o | 33 | obj-$(CONFIG_KEXEC) += machine_kexec.o |
35 | obj-$(CONFIG_EEH) += eeh.o | 34 | obj-$(CONFIG_EEH) += eeh.o |
36 | obj-$(CONFIG_PROC_FS) += proc_ppc64.o | 35 | obj-$(CONFIG_PROC_FS) += proc_ppc64.o |
37 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | ||
38 | obj-$(CONFIG_SMP) += smp.o | 36 | obj-$(CONFIG_SMP) += smp.o |
39 | obj-$(CONFIG_MODULES) += module.o | 37 | obj-$(CONFIG_MODULES) += module.o |
40 | ifneq ($(CONFIG_PPC_MERGE),y) | 38 | ifneq ($(CONFIG_PPC_MERGE),y) |
41 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 39 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
42 | endif | 40 | endif |
43 | obj-$(CONFIG_PPC_RTAS) += rtas_pci.o | 41 | obj-$(CONFIG_PPC_RTAS) += rtas_pci.o |
44 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | ||
45 | obj-$(CONFIG_SCANLOG) += scanlog.o | 42 | obj-$(CONFIG_SCANLOG) += scanlog.o |
46 | obj-$(CONFIG_LPARCFG) += lparcfg.o | 43 | obj-$(CONFIG_LPARCFG) += lparcfg.o |
47 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 44 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c index 493bbe43f5b4..1a443a7ada4c 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/ppc64/kernel/pci_dn.c | |||
@@ -181,13 +181,14 @@ EXPORT_SYMBOL(fetch_dev_dn); | |||
181 | static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | 181 | static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) |
182 | { | 182 | { |
183 | struct device_node *np = node; | 183 | struct device_node *np = node; |
184 | struct pci_dn *pci; | 184 | struct pci_dn *pci = NULL; |
185 | int err = NOTIFY_OK; | 185 | int err = NOTIFY_OK; |
186 | 186 | ||
187 | switch (action) { | 187 | switch (action) { |
188 | case PSERIES_RECONFIG_ADD: | 188 | case PSERIES_RECONFIG_ADD: |
189 | pci = np->parent->data; | 189 | pci = np->parent->data; |
190 | update_dn_pci_info(np, pci->phb); | 190 | if (pci) |
191 | update_dn_pci_info(np, pci->phb); | ||
191 | break; | 192 | break; |
192 | default: | 193 | default: |
193 | err = NOTIFY_DONE; | 194 | err = NOTIFY_DONE; |