diff options
Diffstat (limited to 'arch')
472 files changed, 14726 insertions, 8052 deletions
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c index bd03dc94c72b..026ba9af6d6a 100644 --- a/arch/alpha/kernel/module.c +++ b/arch/alpha/kernel/module.c | |||
@@ -119,8 +119,7 @@ module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs, | |||
119 | } | 119 | } |
120 | 120 | ||
121 | nsyms = symtab->sh_size / sizeof(Elf64_Sym); | 121 | nsyms = symtab->sh_size / sizeof(Elf64_Sym); |
122 | chains = kmalloc(nsyms * sizeof(struct got_entry), GFP_KERNEL); | 122 | chains = kcalloc(nsyms, sizeof(struct got_entry), GFP_KERNEL); |
123 | memset(chains, 0, nsyms * sizeof(struct got_entry)); | ||
124 | 123 | ||
125 | got->sh_size = 0; | 124 | got->sh_size = 0; |
126 | got->sh_addralign = 8; | 125 | got->sh_addralign = 8; |
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 0cd060598f9a..83a781842266 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c | |||
@@ -315,9 +315,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, | |||
315 | /* When I and D space are separate, this will have to be fixed. */ | 315 | /* When I and D space are separate, this will have to be fixed. */ |
316 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 316 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
317 | case PTRACE_POKEDATA: | 317 | case PTRACE_POKEDATA: |
318 | tmp = data; | 318 | ret = generic_ptrace_pokedata(child, addr, data); |
319 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1); | ||
320 | ret = (copied == sizeof(tmp)) ? 0 : -EIO; | ||
321 | break; | 319 | break; |
322 | 320 | ||
323 | case PTRACE_POKEUSR: /* write the specified register */ | 321 | case PTRACE_POKEUSR: /* write the specified register */ |
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 80cfb758ee2b..b28731437c31 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c | |||
@@ -65,7 +65,7 @@ enum ipi_message_type { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* Set to a secondary's cpuid when it comes online. */ | 67 | /* Set to a secondary's cpuid when it comes online. */ |
68 | static int smp_secondary_alive __initdata = 0; | 68 | static int smp_secondary_alive __devinitdata = 0; |
69 | 69 | ||
70 | /* Which cpus ids came online. */ | 70 | /* Which cpus ids came online. */ |
71 | cpumask_t cpu_online_map; | 71 | cpumask_t cpu_online_map; |
@@ -173,7 +173,7 @@ smp_callin(void) | |||
173 | } | 173 | } |
174 | 174 | ||
175 | /* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */ | 175 | /* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */ |
176 | static int __init | 176 | static int __devinit |
177 | wait_for_txrdy (unsigned long cpumask) | 177 | wait_for_txrdy (unsigned long cpumask) |
178 | { | 178 | { |
179 | unsigned long timeout; | 179 | unsigned long timeout; |
@@ -358,7 +358,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) | |||
358 | /* | 358 | /* |
359 | * Bring one cpu online. | 359 | * Bring one cpu online. |
360 | */ | 360 | */ |
361 | static int __init | 361 | static int __devinit |
362 | smp_boot_one_cpu(int cpuid) | 362 | smp_boot_one_cpu(int cpuid) |
363 | { | 363 | { |
364 | struct task_struct *idle; | 364 | struct task_struct *idle; |
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index d6e665d567bd..ec0f05e0d8ff 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c | |||
@@ -184,6 +184,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) | |||
184 | #endif | 184 | #endif |
185 | printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); | 185 | printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); |
186 | dik_show_regs(regs, r9_15); | 186 | dik_show_regs(regs, r9_15); |
187 | add_taint(TAINT_DIE); | ||
187 | dik_show_trace((unsigned long *)(regs+1)); | 188 | dik_show_trace((unsigned long *)(regs+1)); |
188 | dik_show_code((unsigned int *)regs->pc); | 189 | dik_show_code((unsigned int *)regs->pc); |
189 | 190 | ||
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index 449e76f118d3..fe13daa5cb2c 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S | |||
@@ -3,7 +3,7 @@ | |||
3 | OUTPUT_FORMAT("elf64-alpha") | 3 | OUTPUT_FORMAT("elf64-alpha") |
4 | OUTPUT_ARCH(alpha) | 4 | OUTPUT_ARCH(alpha) |
5 | ENTRY(__start) | 5 | ENTRY(__start) |
6 | PHDRS { kernel PT_LOAD ; } | 6 | PHDRS { kernel PT_LOAD; note PT_NOTE; } |
7 | jiffies = jiffies_64; | 7 | jiffies = jiffies_64; |
8 | SECTIONS | 8 | SECTIONS |
9 | { | 9 | { |
@@ -28,6 +28,9 @@ SECTIONS | |||
28 | __ex_table : { *(__ex_table) } | 28 | __ex_table : { *(__ex_table) } |
29 | __stop___ex_table = .; | 29 | __stop___ex_table = .; |
30 | 30 | ||
31 | NOTES :kernel :note | ||
32 | .dummy : { *(.dummy) } :kernel | ||
33 | |||
31 | RODATA | 34 | RODATA |
32 | 35 | ||
33 | /* Will be freed after init */ | 36 | /* Will be freed after init */ |
@@ -69,10 +72,7 @@ SECTIONS | |||
69 | . = ALIGN(8); | 72 | . = ALIGN(8); |
70 | SECURITY_INIT | 73 | SECURITY_INIT |
71 | 74 | ||
72 | . = ALIGN(8192); | 75 | PERCPU(8192) |
73 | __per_cpu_start = .; | ||
74 | .data.percpu : { *(.data.percpu) } | ||
75 | __per_cpu_end = .; | ||
76 | 76 | ||
77 | . = ALIGN(2*8192); | 77 | . = ALIGN(2*8192); |
78 | __init_end = .; | 78 | __init_end = .; |
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c index ab3761c437a8..8698e0746f9f 100644 --- a/arch/alpha/lib/checksum.c +++ b/arch/alpha/lib/checksum.c | |||
@@ -69,6 +69,7 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |||
69 | result = (result & 0xffffffff) + (result >> 32); | 69 | result = (result & 0xffffffff) + (result >> 32); |
70 | return (__force __wsum)result; | 70 | return (__force __wsum)result; |
71 | } | 71 | } |
72 | EXPORT_SYMBOL(csum_tcpudp_nofold); | ||
72 | 73 | ||
73 | /* | 74 | /* |
74 | * Do a 64-bit checksum on an arbitrary memory area.. | 75 | * Do a 64-bit checksum on an arbitrary memory area.. |
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index f5862792a167..a0e18da594d9 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c | |||
@@ -148,21 +148,17 @@ do_page_fault(unsigned long address, unsigned long mmcsr, | |||
148 | the fault. */ | 148 | the fault. */ |
149 | fault = handle_mm_fault(mm, vma, address, cause > 0); | 149 | fault = handle_mm_fault(mm, vma, address, cause > 0); |
150 | up_read(&mm->mmap_sem); | 150 | up_read(&mm->mmap_sem); |
151 | 151 | if (unlikely(fault & VM_FAULT_ERROR)) { | |
152 | switch (fault) { | 152 | if (fault & VM_FAULT_OOM) |
153 | case VM_FAULT_MINOR: | 153 | goto out_of_memory; |
154 | current->min_flt++; | 154 | else if (fault & VM_FAULT_SIGBUS) |
155 | break; | 155 | goto do_sigbus; |
156 | case VM_FAULT_MAJOR: | ||
157 | current->maj_flt++; | ||
158 | break; | ||
159 | case VM_FAULT_SIGBUS: | ||
160 | goto do_sigbus; | ||
161 | case VM_FAULT_OOM: | ||
162 | goto out_of_memory; | ||
163 | default: | ||
164 | BUG(); | 156 | BUG(); |
165 | } | 157 | } |
158 | if (fault & VM_FAULT_MAJOR) | ||
159 | current->maj_flt++; | ||
160 | else | ||
161 | current->min_flt++; | ||
166 | return; | 162 | return; |
167 | 163 | ||
168 | /* Something tried to access memory that isn't in our memory map. | 164 | /* Something tried to access memory that isn't in our memory map. |
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig index 821865f75605..b2bbf217c707 100644 --- a/arch/arm/configs/badge4_defconfig +++ b/arch/arm/configs/badge4_defconfig | |||
@@ -708,7 +708,6 @@ CONFIG_I2C_ALGOPCF=m | |||
708 | # I2C Hardware Bus support | 708 | # I2C Hardware Bus support |
709 | # | 709 | # |
710 | CONFIG_I2C_ELEKTOR=m | 710 | CONFIG_I2C_ELEKTOR=m |
711 | # CONFIG_I2C_ISA is not set | ||
712 | # CONFIG_I2C_PARPORT is not set | 711 | # CONFIG_I2C_PARPORT is not set |
713 | # CONFIG_I2C_PARPORT_LIGHT is not set | 712 | # CONFIG_I2C_PARPORT_LIGHT is not set |
714 | # CONFIG_I2C_STUB is not set | 713 | # CONFIG_I2C_STUB is not set |
diff --git a/arch/arm/configs/clps7500_defconfig b/arch/arm/configs/clps7500_defconfig index af9ae5389131..49e9f9d8b3d1 100644 --- a/arch/arm/configs/clps7500_defconfig +++ b/arch/arm/configs/clps7500_defconfig | |||
@@ -536,7 +536,6 @@ CONFIG_I2C_ALGOBIT=y | |||
536 | # I2C Hardware Bus support | 536 | # I2C Hardware Bus support |
537 | # | 537 | # |
538 | # CONFIG_I2C_ELEKTOR is not set | 538 | # CONFIG_I2C_ELEKTOR is not set |
539 | # CONFIG_I2C_ISA is not set | ||
540 | # CONFIG_I2C_PARPORT is not set | 539 | # CONFIG_I2C_PARPORT is not set |
541 | # CONFIG_I2C_PARPORT_LIGHT is not set | 540 | # CONFIG_I2C_PARPORT_LIGHT is not set |
542 | # CONFIG_I2C_PCA_ISA is not set | 541 | # CONFIG_I2C_PCA_ISA is not set |
diff --git a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig index 2a612d23120b..299dc22294a0 100644 --- a/arch/arm/configs/footbridge_defconfig +++ b/arch/arm/configs/footbridge_defconfig | |||
@@ -748,7 +748,6 @@ CONFIG_I2C=m | |||
748 | # CONFIG_I2C_ELEKTOR is not set | 748 | # CONFIG_I2C_ELEKTOR is not set |
749 | # CONFIG_I2C_I801 is not set | 749 | # CONFIG_I2C_I801 is not set |
750 | # CONFIG_I2C_I810 is not set | 750 | # CONFIG_I2C_I810 is not set |
751 | # CONFIG_I2C_ISA is not set | ||
752 | # CONFIG_I2C_NFORCE2 is not set | 751 | # CONFIG_I2C_NFORCE2 is not set |
753 | # CONFIG_I2C_PARPORT is not set | 752 | # CONFIG_I2C_PARPORT is not set |
754 | # CONFIG_I2C_PARPORT_LIGHT is not set | 753 | # CONFIG_I2C_PARPORT_LIGHT is not set |
diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig index e86794a10fc0..92ccdc6492f7 100644 --- a/arch/arm/configs/neponset_defconfig +++ b/arch/arm/configs/neponset_defconfig | |||
@@ -698,7 +698,6 @@ CONFIG_I2C_ALGOBIT=y | |||
698 | # I2C Hardware Bus support | 698 | # I2C Hardware Bus support |
699 | # | 699 | # |
700 | # CONFIG_I2C_ELEKTOR is not set | 700 | # CONFIG_I2C_ELEKTOR is not set |
701 | # CONFIG_I2C_ISA is not set | ||
702 | # CONFIG_I2C_PARPORT_LIGHT is not set | 701 | # CONFIG_I2C_PARPORT_LIGHT is not set |
703 | # CONFIG_I2C_STUB is not set | 702 | # CONFIG_I2C_STUB is not set |
704 | # CONFIG_I2C_PCA_ISA is not set | 703 | # CONFIG_I2C_PCA_ISA is not set |
diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig index 339c48953a62..3c0c4f192dc1 100644 --- a/arch/arm/configs/picotux200_defconfig +++ b/arch/arm/configs/picotux200_defconfig | |||
@@ -735,7 +735,6 @@ CONFIG_I2C_CHARDEV=m | |||
735 | # I2C Hardware Bus support | 735 | # I2C Hardware Bus support |
736 | # | 736 | # |
737 | CONFIG_I2C_AT91=m | 737 | CONFIG_I2C_AT91=m |
738 | CONFIG_I2C_ISA=m | ||
739 | # CONFIG_I2C_OCORES is not set | 738 | # CONFIG_I2C_OCORES is not set |
740 | # CONFIG_I2C_PARPORT_LIGHT is not set | 739 | # CONFIG_I2C_PARPORT_LIGHT is not set |
741 | # CONFIG_I2C_STUB is not set | 740 | # CONFIG_I2C_STUB is not set |
diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig index bc091264d354..8452dc8c7cc3 100644 --- a/arch/arm/configs/rpc_defconfig +++ b/arch/arm/configs/rpc_defconfig | |||
@@ -558,7 +558,6 @@ CONFIG_I2C_ALGOBIT=y | |||
558 | # | 558 | # |
559 | # I2C Hardware Bus support | 559 | # I2C Hardware Bus support |
560 | # | 560 | # |
561 | # CONFIG_I2C_ISA is not set | ||
562 | # CONFIG_I2C_PARPORT is not set | 561 | # CONFIG_I2C_PARPORT is not set |
563 | # CONFIG_I2C_PARPORT_LIGHT is not set | 562 | # CONFIG_I2C_PARPORT_LIGHT is not set |
564 | # CONFIG_I2C_STUB is not set | 563 | # CONFIG_I2C_STUB is not set |
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index a850da377a29..1d5150e4d6b3 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig | |||
@@ -826,7 +826,6 @@ CONFIG_I2C_ALGOBIT=m | |||
826 | # I2C Hardware Bus support | 826 | # I2C Hardware Bus support |
827 | # | 827 | # |
828 | # CONFIG_I2C_ELEKTOR is not set | 828 | # CONFIG_I2C_ELEKTOR is not set |
829 | CONFIG_I2C_ISA=m | ||
830 | # CONFIG_I2C_OCORES is not set | 829 | # CONFIG_I2C_OCORES is not set |
831 | # CONFIG_I2C_PARPORT is not set | 830 | # CONFIG_I2C_PARPORT is not set |
832 | # CONFIG_I2C_PARPORT_LIGHT is not set | 831 | # CONFIG_I2C_PARPORT_LIGHT is not set |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 6f2f46c2e406..78c9f1a3d41f 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -657,7 +657,6 @@ static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp) | |||
657 | 657 | ||
658 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 658 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
659 | { | 659 | { |
660 | unsigned long tmp; | ||
661 | int ret; | 660 | int ret; |
662 | 661 | ||
663 | switch (request) { | 662 | switch (request) { |
@@ -666,12 +665,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
666 | */ | 665 | */ |
667 | case PTRACE_PEEKTEXT: | 666 | case PTRACE_PEEKTEXT: |
668 | case PTRACE_PEEKDATA: | 667 | case PTRACE_PEEKDATA: |
669 | ret = access_process_vm(child, addr, &tmp, | 668 | ret = generic_ptrace_peekdata(child, addr, data); |
670 | sizeof(unsigned long), 0); | ||
671 | if (ret == sizeof(unsigned long)) | ||
672 | ret = put_user(tmp, (unsigned long __user *) data); | ||
673 | else | ||
674 | ret = -EIO; | ||
675 | break; | 669 | break; |
676 | 670 | ||
677 | case PTRACE_PEEKUSR: | 671 | case PTRACE_PEEKUSR: |
@@ -683,12 +677,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
683 | */ | 677 | */ |
684 | case PTRACE_POKETEXT: | 678 | case PTRACE_POKETEXT: |
685 | case PTRACE_POKEDATA: | 679 | case PTRACE_POKEDATA: |
686 | ret = access_process_vm(child, addr, &data, | 680 | ret = generic_ptrace_pokedata(child, addr, data); |
687 | sizeof(unsigned long), 1); | ||
688 | if (ret == sizeof(unsigned long)) | ||
689 | ret = 0; | ||
690 | else | ||
691 | ret = -EIO; | ||
692 | break; | 681 | break; |
693 | 682 | ||
694 | case PTRACE_POKEUSR: | 683 | case PTRACE_POKEUSR: |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 237f4999b9a1..f2114bcf09d5 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -249,6 +249,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) | |||
249 | bust_spinlocks(1); | 249 | bust_spinlocks(1); |
250 | __die(str, err, thread, regs); | 250 | __die(str, err, thread, regs); |
251 | bust_spinlocks(0); | 251 | bust_spinlocks(0); |
252 | add_taint(TAINT_DIE); | ||
252 | spin_unlock_irq(&die_lock); | 253 | spin_unlock_irq(&die_lock); |
253 | 254 | ||
254 | if (in_interrupt()) | 255 | if (in_interrupt()) |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 2b7a8f5d8cf2..5ff5406666b4 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -66,6 +66,7 @@ SECTIONS | |||
66 | . = ALIGN(4096); | 66 | . = ALIGN(4096); |
67 | __per_cpu_start = .; | 67 | __per_cpu_start = .; |
68 | *(.data.percpu) | 68 | *(.data.percpu) |
69 | *(.data.percpu.shared_aligned) | ||
69 | __per_cpu_end = .; | 70 | __per_cpu_end = .; |
70 | #ifndef CONFIG_XIP_KERNEL | 71 | #ifndef CONFIG_XIP_KERNEL |
71 | __init_begin = _stext; | 72 | __init_begin = _stext; |
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index e18a41e61f0c..dde089922e3b 100644 --- a/arch/arm/mach-at91/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/i2c.h> | ||
26 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
27 | #include <linux/mtd/physmap.h> | 28 | #include <linux/mtd/physmap.h> |
28 | 29 | ||
@@ -83,6 +84,13 @@ static struct at91_udc_data __initdata csb337_udc_data = { | |||
83 | .pullup_pin = AT91_PIN_PA24, | 84 | .pullup_pin = AT91_PIN_PA24, |
84 | }; | 85 | }; |
85 | 86 | ||
87 | static struct i2c_board_info __initdata csb337_i2c_devices[] = { | ||
88 | { I2C_BOARD_INFO("rtc-ds1307", 0x68), | ||
89 | .type = "ds1307", | ||
90 | }, | ||
91 | }; | ||
92 | |||
93 | |||
86 | static struct at91_cf_data __initdata csb337_cf_data = { | 94 | static struct at91_cf_data __initdata csb337_cf_data = { |
87 | /* | 95 | /* |
88 | * connector P4 on the CSB 337 mates to | 96 | * connector P4 on the CSB 337 mates to |
@@ -161,6 +169,8 @@ static void __init csb337_board_init(void) | |||
161 | at91_add_device_udc(&csb337_udc_data); | 169 | at91_add_device_udc(&csb337_udc_data); |
162 | /* I2C */ | 170 | /* I2C */ |
163 | at91_add_device_i2c(); | 171 | at91_add_device_i2c(); |
172 | i2c_register_board_info(0, csb337_i2c_devices, | ||
173 | ARRAY_SIZE(csb337_i2c_devices)); | ||
164 | /* Compact Flash */ | 174 | /* Compact Flash */ |
165 | at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */ | 175 | at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */ |
166 | at91_add_device_cf(&csb337_cf_data); | 176 | at91_add_device_cf(&csb337_cf_data); |
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c index 9d63d7f260ca..99d94cb1bafd 100644 --- a/arch/arm/mach-iop13xx/pci.c +++ b/arch/arm/mach-iop13xx/pci.c | |||
@@ -1002,11 +1002,10 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) | |||
1002 | if (nr > 1) | 1002 | if (nr > 1) |
1003 | return 0; | 1003 | return 0; |
1004 | 1004 | ||
1005 | res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL); | 1005 | res = kcalloc(2, sizeof(struct resource), GFP_KERNEL); |
1006 | if (!res) | 1006 | if (!res) |
1007 | panic("PCI: unable to alloc resources"); | 1007 | panic("PCI: unable to alloc resources"); |
1008 | 1008 | ||
1009 | memset(res, 0, sizeof(struct resource) * 2); | ||
1010 | 1009 | ||
1011 | /* 'nr' assumptions: | 1010 | /* 'nr' assumptions: |
1012 | * ATUX is always 0 | 1011 | * ATUX is always 0 |
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c index 390a97d39e5a..1873bd8cd1b2 100644 --- a/arch/arm/mach-iop32x/n2100.c +++ b/arch/arm/mach-iop32x/n2100.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
26 | #include <linux/serial_8250.h> | 26 | #include <linux/serial_8250.h> |
27 | #include <linux/mtd/physmap.h> | 27 | #include <linux/mtd/physmap.h> |
28 | #include <linux/i2c.h> | ||
28 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
29 | #include <linux/reboot.h> | 30 | #include <linux/reboot.h> |
30 | #include <asm/hardware.h> | 31 | #include <asm/hardware.h> |
@@ -199,6 +200,12 @@ static struct platform_device n2100_serial_device = { | |||
199 | .resource = &n2100_uart_resource, | 200 | .resource = &n2100_uart_resource, |
200 | }; | 201 | }; |
201 | 202 | ||
203 | static struct i2c_board_info __initdata n2100_i2c_devices[] = { | ||
204 | { | ||
205 | I2C_BOARD_INFO("rtc-rs5c372", 0x32), | ||
206 | .type = "rs5c372b", | ||
207 | }, | ||
208 | }; | ||
202 | 209 | ||
203 | /* | 210 | /* |
204 | * Pull PCA9532 GPIO #8 low to power off the machine. | 211 | * Pull PCA9532 GPIO #8 low to power off the machine. |
@@ -248,6 +255,9 @@ static void __init n2100_init_machine(void) | |||
248 | platform_device_register(&iop3xx_dma_0_channel); | 255 | platform_device_register(&iop3xx_dma_0_channel); |
249 | platform_device_register(&iop3xx_dma_1_channel); | 256 | platform_device_register(&iop3xx_dma_1_channel); |
250 | 257 | ||
258 | i2c_register_board_info(0, n2100_i2c_devices, | ||
259 | ARRAY_SIZE(n2100_i2c_devices)); | ||
260 | |||
251 | pm_power_off = n2100_power_off; | 261 | pm_power_off = n2100_power_off; |
252 | 262 | ||
253 | init_timer(&power_button_poll_timer); | 263 | init_timer(&power_button_poll_timer); |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 75d491448e45..c04124a095cf 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -183,20 +183,20 @@ good_area: | |||
183 | */ | 183 | */ |
184 | survive: | 184 | survive: |
185 | fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, fsr & (1 << 11)); | 185 | fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, fsr & (1 << 11)); |
186 | 186 | if (unlikely(fault & VM_FAULT_ERROR)) { | |
187 | /* | 187 | if (fault & VM_FAULT_OOM) |
188 | * Handle the "normal" cases first - successful and sigbus | 188 | goto out_of_memory; |
189 | */ | 189 | else if (fault & VM_FAULT_SIGBUS) |
190 | switch (fault) { | 190 | return fault; |
191 | case VM_FAULT_MAJOR: | 191 | BUG(); |
192 | } | ||
193 | if (fault & VM_FAULT_MAJOR) | ||
192 | tsk->maj_flt++; | 194 | tsk->maj_flt++; |
193 | return fault; | 195 | else |
194 | case VM_FAULT_MINOR: | ||
195 | tsk->min_flt++; | 196 | tsk->min_flt++; |
196 | case VM_FAULT_SIGBUS: | 197 | return fault; |
197 | return fault; | ||
198 | } | ||
199 | 198 | ||
199 | out_of_memory: | ||
200 | if (!is_init(tsk)) | 200 | if (!is_init(tsk)) |
201 | goto out; | 201 | goto out; |
202 | 202 | ||
@@ -249,7 +249,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
249 | /* | 249 | /* |
250 | * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR | 250 | * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR |
251 | */ | 251 | */ |
252 | if (fault >= VM_FAULT_MINOR) | 252 | if (likely(!(fault & VM_FAULT_ERROR))) |
253 | return 0; | 253 | return 0; |
254 | 254 | ||
255 | /* | 255 | /* |
@@ -259,8 +259,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
259 | if (!user_mode(regs)) | 259 | if (!user_mode(regs)) |
260 | goto no_context; | 260 | goto no_context; |
261 | 261 | ||
262 | switch (fault) { | 262 | if (fault & VM_FAULT_OOM) { |
263 | case VM_FAULT_OOM: | ||
264 | /* | 263 | /* |
265 | * We ran out of memory, or some other thing | 264 | * We ran out of memory, or some other thing |
266 | * happened to us that made us unable to handle | 265 | * happened to us that made us unable to handle |
@@ -269,17 +268,15 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
269 | printk("VM: killing process %s\n", tsk->comm); | 268 | printk("VM: killing process %s\n", tsk->comm); |
270 | do_exit(SIGKILL); | 269 | do_exit(SIGKILL); |
271 | return 0; | 270 | return 0; |
272 | 271 | } | |
273 | case VM_FAULT_SIGBUS: | 272 | if (fault & VM_FAULT_SIGBUS) { |
274 | /* | 273 | /* |
275 | * We had some memory, but were unable to | 274 | * We had some memory, but were unable to |
276 | * successfully fix up this page fault. | 275 | * successfully fix up this page fault. |
277 | */ | 276 | */ |
278 | sig = SIGBUS; | 277 | sig = SIGBUS; |
279 | code = BUS_ADRERR; | 278 | code = BUS_ADRERR; |
280 | break; | 279 | } else { |
281 | |||
282 | default: | ||
283 | /* | 280 | /* |
284 | * Something tried to access memory that | 281 | * Something tried to access memory that |
285 | * isn't in our memory map.. | 282 | * isn't in our memory map.. |
@@ -287,7 +284,6 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
287 | sig = SIGSEGV; | 284 | sig = SIGSEGV; |
288 | code = fault == VM_FAULT_BADACCESS ? | 285 | code = fault == VM_FAULT_BADACCESS ? |
289 | SEGV_ACCERR : SEGV_MAPERR; | 286 | SEGV_ACCERR : SEGV_MAPERR; |
290 | break; | ||
291 | } | 287 | } |
292 | 288 | ||
293 | __do_user_fault(tsk, addr, fsr, sig, code, regs); | 289 | __do_user_fault(tsk, addr, fsr, sig, code, regs); |
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 416927956721..0fefb86970c6 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c | |||
@@ -531,7 +531,6 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) | |||
531 | 531 | ||
532 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 532 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
533 | { | 533 | { |
534 | unsigned long tmp; | ||
535 | int ret; | 534 | int ret; |
536 | 535 | ||
537 | switch (request) { | 536 | switch (request) { |
@@ -540,12 +539,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
540 | */ | 539 | */ |
541 | case PTRACE_PEEKTEXT: | 540 | case PTRACE_PEEKTEXT: |
542 | case PTRACE_PEEKDATA: | 541 | case PTRACE_PEEKDATA: |
543 | ret = access_process_vm(child, addr, &tmp, | 542 | ret = generic_ptrace_peekdata(child, addr, data); |
544 | sizeof(unsigned long), 0); | ||
545 | if (ret == sizeof(unsigned long)) | ||
546 | ret = put_user(tmp, (unsigned long *) data); | ||
547 | else | ||
548 | ret = -EIO; | ||
549 | break; | 543 | break; |
550 | 544 | ||
551 | case PTRACE_PEEKUSR: | 545 | case PTRACE_PEEKUSR: |
@@ -557,12 +551,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
557 | */ | 551 | */ |
558 | case PTRACE_POKETEXT: | 552 | case PTRACE_POKETEXT: |
559 | case PTRACE_POKEDATA: | 553 | case PTRACE_POKEDATA: |
560 | ret = access_process_vm(child, addr, &data, | 554 | ret = generic_ptrace_pokedata(child, addr, data); |
561 | sizeof(unsigned long), 1); | ||
562 | if (ret == sizeof(unsigned long)) | ||
563 | ret = 0; | ||
564 | else | ||
565 | ret = -EIO; | ||
566 | break; | 555 | break; |
567 | 556 | ||
568 | case PTRACE_POKEUSR: | 557 | case PTRACE_POKEUSR: |
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c index d594fb59e945..2911e2eae80e 100644 --- a/arch/arm26/kernel/traps.c +++ b/arch/arm26/kernel/traps.c | |||
@@ -185,6 +185,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) | |||
185 | printk("Internal error: %s: %x\n", str, err); | 185 | printk("Internal error: %s: %x\n", str, err); |
186 | printk("CPU: %d\n", smp_processor_id()); | 186 | printk("CPU: %d\n", smp_processor_id()); |
187 | show_regs(regs); | 187 | show_regs(regs); |
188 | add_taint(TAINT_DIE); | ||
188 | printk("Process %s (pid: %d, stack limit = 0x%p)\n", | 189 | printk("Process %s (pid: %d, stack limit = 0x%p)\n", |
189 | current->comm, current->pid, end_of_stack(tsk)); | 190 | current->comm, current->pid, end_of_stack(tsk)); |
190 | 191 | ||
diff --git a/arch/arm26/mm/fault.c b/arch/arm26/mm/fault.c index 93c0cee0fb5e..dec638a0c8d9 100644 --- a/arch/arm26/mm/fault.c +++ b/arch/arm26/mm/fault.c | |||
@@ -170,20 +170,20 @@ good_area: | |||
170 | */ | 170 | */ |
171 | survive: | 171 | survive: |
172 | fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr)); | 172 | fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr)); |
173 | 173 | if (unlikely(fault & VM_FAULT_ERROR)) { | |
174 | /* | 174 | if (fault & VM_FAULT_OOM) |
175 | * Handle the "normal" cases first - successful and sigbus | 175 | goto out_of_memory; |
176 | */ | 176 | else if (fault & VM_FAULT_SIGBUS) |
177 | switch (fault) { | 177 | return fault; |
178 | case VM_FAULT_MAJOR: | 178 | BUG(); |
179 | } | ||
180 | if (fault & VM_FAULT_MAJOR) | ||
179 | tsk->maj_flt++; | 181 | tsk->maj_flt++; |
180 | return fault; | 182 | else |
181 | case VM_FAULT_MINOR: | ||
182 | tsk->min_flt++; | 183 | tsk->min_flt++; |
183 | case VM_FAULT_SIGBUS: | 184 | return fault; |
184 | return fault; | ||
185 | } | ||
186 | 185 | ||
186 | out_of_memory: | ||
187 | fault = -3; /* out of memory */ | 187 | fault = -3; /* out of memory */ |
188 | if (!is_init(tsk)) | 188 | if (!is_init(tsk)) |
189 | goto out; | 189 | goto out; |
@@ -225,13 +225,11 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
225 | /* | 225 | /* |
226 | * Handle the "normal" case first | 226 | * Handle the "normal" case first |
227 | */ | 227 | */ |
228 | switch (fault) { | 228 | if (likely(!(fault & VM_FAULT_ERROR))) |
229 | case VM_FAULT_MINOR: | ||
230 | case VM_FAULT_MAJOR: | ||
231 | return 0; | 229 | return 0; |
232 | case VM_FAULT_SIGBUS: | 230 | if (fault & VM_FAULT_SIGBUS) |
233 | goto do_sigbus; | 231 | goto do_sigbus; |
234 | } | 232 | /* else VM_FAULT_OOM */ |
235 | 233 | ||
236 | /* | 234 | /* |
237 | * If we are in kernel mode at this point, we | 235 | * If we are in kernel mode at this point, we |
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 3ec76586877e..d12346aaa88b 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
@@ -113,6 +113,10 @@ config BOARD_ATNGW100 | |||
113 | bool "ATNGW100 Network Gateway" | 113 | bool "ATNGW100 Network Gateway" |
114 | endchoice | 114 | endchoice |
115 | 115 | ||
116 | if BOARD_ATSTK1000 | ||
117 | source "arch/avr32/boards/atstk1000/Kconfig" | ||
118 | endif | ||
119 | |||
116 | choice | 120 | choice |
117 | prompt "Boot loader type" | 121 | prompt "Boot loader type" |
118 | default LOADER_U_BOOT | 122 | default LOADER_U_BOOT |
@@ -185,6 +189,27 @@ config CMDLINE | |||
185 | 189 | ||
186 | endmenu | 190 | endmenu |
187 | 191 | ||
192 | menu "Power managment options" | ||
193 | |||
194 | menu "CPU Frequency scaling" | ||
195 | |||
196 | source "drivers/cpufreq/Kconfig" | ||
197 | |||
198 | config CPU_FREQ_AT32AP | ||
199 | bool "CPU frequency driver for AT32AP" | ||
200 | depends on CPU_FREQ && PLATFORM_AT32AP | ||
201 | default n | ||
202 | help | ||
203 | This enables the CPU frequency driver for AT32AP processors. | ||
204 | |||
205 | For details, take a look in <file:Documentation/cpu-freq>. | ||
206 | |||
207 | If in doubt, say N. | ||
208 | |||
209 | endmenu | ||
210 | |||
211 | endmenu | ||
212 | |||
188 | menu "Bus options" | 213 | menu "Bus options" |
189 | 214 | ||
190 | config PCI | 215 | config PCI |
diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig new file mode 100644 index 000000000000..71bc7d364fb7 --- /dev/null +++ b/arch/avr32/boards/atstk1000/Kconfig | |||
@@ -0,0 +1,53 @@ | |||
1 | # STK1000 customization | ||
2 | |||
3 | if BOARD_ATSTK1002 | ||
4 | |||
5 | config BOARD_ATSTK1002_CUSTOM | ||
6 | bool "Non-default STK-1002 jumper settings" | ||
7 | help | ||
8 | You will normally leave the jumpers on the CPU card at their | ||
9 | default settings. If you need to use certain peripherals, | ||
10 | you will need to change some of those jumpers. | ||
11 | |||
12 | if BOARD_ATSTK1002_CUSTOM | ||
13 | |||
14 | config BOARD_ATSTK1002_SW1_CUSTOM | ||
15 | bool "SW1: use SSC1 (not SPI0)" | ||
16 | help | ||
17 | This also prevents using the external DAC as an audio interface, | ||
18 | and means you can't initialize the on-board QVGA display. | ||
19 | |||
20 | config BOARD_ATSTK1002_SW2_CUSTOM | ||
21 | bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)" | ||
22 | help | ||
23 | If you change this you'll want an updated boot loader putting | ||
24 | the console on UART-C not UART-A. | ||
25 | |||
26 | config BOARD_ATSTK1002_SW3_CUSTOM | ||
27 | bool "SW3: use TIMER1 (not SSC0 and GCLK)" | ||
28 | help | ||
29 | This also prevents using the external DAC as an audio interface. | ||
30 | |||
31 | config BOARD_ATSTK1002_SW4_CUSTOM | ||
32 | bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)" | ||
33 | help | ||
34 | To use the camera interface you'll need a custom card (on the | ||
35 | PCI-format connector) connect a video sensor. | ||
36 | |||
37 | config BOARD_ATSTK1002_SW5_CUSTOM | ||
38 | bool "SW5: use MACB1 (not LCDC)" | ||
39 | |||
40 | config BOARD_ATSTK1002_SW6_CUSTOM | ||
41 | bool "SW6: more GPIOs (not MACB0)" | ||
42 | |||
43 | endif # custom | ||
44 | |||
45 | config BOARD_ATSTK1002_SPI1 | ||
46 | bool "Configure SPI1 controller" | ||
47 | depends on !BOARD_ATSTK1002_SW4_CUSTOM | ||
48 | help | ||
49 | All the signals for the second SPI controller are available on | ||
50 | GPIO lines and accessed through the J1 jumper block. Say "y" | ||
51 | here to configure that SPI controller. | ||
52 | |||
53 | endif # stk 1002 | ||
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index e253e86a1a39..cb93eabb9c6c 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c | |||
@@ -27,15 +27,27 @@ | |||
27 | 27 | ||
28 | #include "atstk1000.h" | 28 | #include "atstk1000.h" |
29 | 29 | ||
30 | #define SW2_DEFAULT /* MMCI and UART_A available */ | ||
31 | 30 | ||
32 | struct eth_addr { | 31 | struct eth_addr { |
33 | u8 addr[6]; | 32 | u8 addr[6]; |
34 | }; | 33 | }; |
35 | 34 | ||
36 | static struct eth_addr __initdata hw_addr[2]; | 35 | static struct eth_addr __initdata hw_addr[2]; |
37 | static struct eth_platform_data __initdata eth_data[2]; | 36 | static struct eth_platform_data __initdata eth_data[2] = { |
37 | { | ||
38 | /* | ||
39 | * The MDIO pullups on STK1000 are a bit too weak for | ||
40 | * the autodetection to work properly, so we have to | ||
41 | * mask out everything but the correct address. | ||
42 | */ | ||
43 | .phy_mask = ~(1U << 16), | ||
44 | }, | ||
45 | { | ||
46 | .phy_mask = ~(1U << 17), | ||
47 | }, | ||
48 | }; | ||
38 | 49 | ||
50 | #ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM | ||
39 | static struct spi_board_info spi0_board_info[] __initdata = { | 51 | static struct spi_board_info spi0_board_info[] __initdata = { |
40 | { | 52 | { |
41 | /* QVGA display */ | 53 | /* QVGA display */ |
@@ -45,6 +57,13 @@ static struct spi_board_info spi0_board_info[] __initdata = { | |||
45 | .mode = SPI_MODE_3, | 57 | .mode = SPI_MODE_3, |
46 | }, | 58 | }, |
47 | }; | 59 | }; |
60 | #endif | ||
61 | |||
62 | #ifdef CONFIG_BOARD_ATSTK1002_SPI1 | ||
63 | static struct spi_board_info spi1_board_info[] __initdata = { { | ||
64 | /* patch in custom entries here */ | ||
65 | } }; | ||
66 | #endif | ||
48 | 67 | ||
49 | /* | 68 | /* |
50 | * The next two functions should go away as the boot loader is | 69 | * The next two functions should go away as the boot loader is |
@@ -103,10 +122,10 @@ static void __init set_hw_addr(struct platform_device *pdev) | |||
103 | 122 | ||
104 | void __init setup_board(void) | 123 | void __init setup_board(void) |
105 | { | 124 | { |
106 | #ifdef SW2_DEFAULT | 125 | #ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM |
107 | at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */ | ||
108 | #else | ||
109 | at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */ | 126 | at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */ |
127 | #else | ||
128 | at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */ | ||
110 | #endif | 129 | #endif |
111 | /* USART 2/unused: expansion connector */ | 130 | /* USART 2/unused: expansion connector */ |
112 | at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */ | 131 | at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */ |
@@ -140,18 +159,31 @@ static int __init atstk1002_init(void) | |||
140 | 159 | ||
141 | at32_add_system_devices(); | 160 | at32_add_system_devices(); |
142 | 161 | ||
143 | #ifdef SW2_DEFAULT | 162 | #ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM |
144 | at32_add_device_usart(0); | ||
145 | #else | ||
146 | at32_add_device_usart(1); | 163 | at32_add_device_usart(1); |
164 | #else | ||
165 | at32_add_device_usart(0); | ||
147 | #endif | 166 | #endif |
148 | at32_add_device_usart(2); | 167 | at32_add_device_usart(2); |
149 | 168 | ||
169 | #ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM | ||
150 | set_hw_addr(at32_add_device_eth(0, ð_data[0])); | 170 | set_hw_addr(at32_add_device_eth(0, ð_data[0])); |
151 | 171 | #endif | |
172 | #ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM | ||
152 | at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); | 173 | at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); |
174 | #endif | ||
175 | #ifdef CONFIG_BOARD_ATSTK1002_SPI1 | ||
176 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); | ||
177 | #endif | ||
178 | #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM | ||
179 | set_hw_addr(at32_add_device_eth(1, ð_data[1])); | ||
180 | #else | ||
153 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, | 181 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, |
154 | fbmem_start, fbmem_size); | 182 | fbmem_start, fbmem_size); |
183 | #endif | ||
184 | #ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM | ||
185 | at32_add_device_ssc(0, ATMEL_SSC_TX); | ||
186 | #endif | ||
155 | 187 | ||
156 | return 0; | 188 | return 0; |
157 | } | 189 | } |
diff --git a/arch/avr32/kernel/ptrace.c b/arch/avr32/kernel/ptrace.c index 3c36c2d16148..39060cbeb2a3 100644 --- a/arch/avr32/kernel/ptrace.c +++ b/arch/avr32/kernel/ptrace.c | |||
@@ -153,7 +153,6 @@ static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs) | |||
153 | 153 | ||
154 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 154 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
155 | { | 155 | { |
156 | unsigned long tmp; | ||
157 | int ret; | 156 | int ret; |
158 | 157 | ||
159 | pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n", | 158 | pr_debug("arch_ptrace(%ld, %d, %#lx, %#lx)\n", |
@@ -166,11 +165,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
166 | /* Read the word at location addr in the child process */ | 165 | /* Read the word at location addr in the child process */ |
167 | case PTRACE_PEEKTEXT: | 166 | case PTRACE_PEEKTEXT: |
168 | case PTRACE_PEEKDATA: | 167 | case PTRACE_PEEKDATA: |
169 | ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | 168 | ret = generic_ptrace_peekdata(child, addr, data); |
170 | if (ret == sizeof(tmp)) | ||
171 | ret = put_user(tmp, (unsigned long __user *)data); | ||
172 | else | ||
173 | ret = -EIO; | ||
174 | break; | 169 | break; |
175 | 170 | ||
176 | case PTRACE_PEEKUSR: | 171 | case PTRACE_PEEKUSR: |
@@ -181,11 +176,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
181 | /* Write the word in data at location addr */ | 176 | /* Write the word in data at location addr */ |
182 | case PTRACE_POKETEXT: | 177 | case PTRACE_POKETEXT: |
183 | case PTRACE_POKEDATA: | 178 | case PTRACE_POKEDATA: |
184 | ret = access_process_vm(child, addr, &data, sizeof(data), 1); | 179 | ret = generic_ptrace_pokedata(child, addr, data); |
185 | if (ret == sizeof(data)) | ||
186 | ret = 0; | ||
187 | else | ||
188 | ret = -EIO; | ||
189 | break; | 180 | break; |
190 | 181 | ||
191 | case PTRACE_POKEUSR: | 182 | case PTRACE_POKEUSR: |
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index b279d66acf5f..d08b0bc6b2bb 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c | |||
@@ -313,7 +313,7 @@ __tagtable(ATAG_MEM, parse_tag_mem); | |||
313 | 313 | ||
314 | static int __init parse_tag_rdimg(struct tag *tag) | 314 | static int __init parse_tag_rdimg(struct tag *tag) |
315 | { | 315 | { |
316 | #ifdef CONFIG_INITRD | 316 | #ifdef CONFIG_BLK_DEV_INITRD |
317 | struct tag_mem_range *mem = &tag->u.mem_range; | 317 | struct tag_mem_range *mem = &tag->u.mem_range; |
318 | int ret; | 318 | int ret; |
319 | 319 | ||
@@ -323,7 +323,7 @@ static int __init parse_tag_rdimg(struct tag *tag) | |||
323 | return 0; | 323 | return 0; |
324 | } | 324 | } |
325 | 325 | ||
326 | ret = add_reserved_region(mem->start, mem->start + mem->size - 1, | 326 | ret = add_reserved_region(mem->addr, mem->addr + mem->size - 1, |
327 | "initrd"); | 327 | "initrd"); |
328 | if (ret) { | 328 | if (ret) { |
329 | printk(KERN_WARNING | 329 | printk(KERN_WARNING |
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c index aaa792815cd7..9a73ce7eb50f 100644 --- a/arch/avr32/kernel/traps.c +++ b/arch/avr32/kernel/traps.c | |||
@@ -56,6 +56,7 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err) | |||
56 | show_regs_log_lvl(regs, KERN_EMERG); | 56 | show_regs_log_lvl(regs, KERN_EMERG); |
57 | show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG); | 57 | show_stack_log_lvl(current, regs->sp, regs, KERN_EMERG); |
58 | bust_spinlocks(0); | 58 | bust_spinlocks(0); |
59 | add_taint(TAINT_DIE); | ||
59 | spin_unlock_irq(&die_lock); | 60 | spin_unlock_irq(&die_lock); |
60 | 61 | ||
61 | if (in_interrupt()) | 62 | if (in_interrupt()) |
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile index f1d395724ac6..a8b445046e3e 100644 --- a/arch/avr32/mach-at32ap/Makefile +++ b/arch/avr32/mach-at32ap/Makefile | |||
@@ -1,3 +1,4 @@ | |||
1 | obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o | 1 | obj-y += at32ap.o clock.o intc.o extint.o pio.o hsmc.o |
2 | obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o | 2 | obj-$(CONFIG_CPU_AT32AP7000) += at32ap7000.o |
3 | obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o | 3 | obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o |
4 | obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o | ||
diff --git a/arch/avr32/mach-at32ap/at32ap.c b/arch/avr32/mach-at32ap/at32ap.c index 90f207e8e96d..7c4987f3287a 100644 --- a/arch/avr32/mach-at32ap/at32ap.c +++ b/arch/avr32/mach-at32ap/at32ap.c | |||
@@ -11,41 +11,10 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | 13 | ||
14 | #include <asm/io.h> | ||
15 | |||
16 | #include <asm/arch/init.h> | 14 | #include <asm/arch/init.h> |
17 | #include <asm/arch/sm.h> | ||
18 | |||
19 | struct at32_sm system_manager; | ||
20 | |||
21 | static int __init at32_sm_init(void) | ||
22 | { | ||
23 | struct resource *regs; | ||
24 | struct at32_sm *sm = &system_manager; | ||
25 | int ret = -ENXIO; | ||
26 | |||
27 | regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0); | ||
28 | if (!regs) | ||
29 | goto fail; | ||
30 | |||
31 | spin_lock_init(&sm->lock); | ||
32 | sm->pdev = &at32_sm_device; | ||
33 | |||
34 | ret = -ENOMEM; | ||
35 | sm->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
36 | if (!sm->regs) | ||
37 | goto fail; | ||
38 | |||
39 | return 0; | ||
40 | |||
41 | fail: | ||
42 | printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret); | ||
43 | return ret; | ||
44 | } | ||
45 | 15 | ||
46 | void __init setup_platform(void) | 16 | void __init setup_platform(void) |
47 | { | 17 | { |
48 | at32_sm_init(); | ||
49 | at32_clock_init(); | 18 | at32_clock_init(); |
50 | at32_portmux_init(); | 19 | at32_portmux_init(); |
51 | } | 20 | } |
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c index 4dda42d3f6d5..64cc5583ddfb 100644 --- a/arch/avr32/mach-at32ap/at32ap7000.c +++ b/arch/avr32/mach-at32ap/at32ap7000.c | |||
@@ -17,14 +17,20 @@ | |||
17 | #include <asm/arch/at32ap7000.h> | 17 | #include <asm/arch/at32ap7000.h> |
18 | #include <asm/arch/board.h> | 18 | #include <asm/arch/board.h> |
19 | #include <asm/arch/portmux.h> | 19 | #include <asm/arch/portmux.h> |
20 | #include <asm/arch/sm.h> | ||
21 | 20 | ||
22 | #include <video/atmel_lcdc.h> | 21 | #include <video/atmel_lcdc.h> |
23 | 22 | ||
24 | #include "clock.h" | 23 | #include "clock.h" |
25 | #include "hmatrix.h" | 24 | #include "hmatrix.h" |
26 | #include "pio.h" | 25 | #include "pio.h" |
27 | #include "sm.h" | 26 | #include "pm.h" |
27 | |||
28 | /* | ||
29 | * We can reduce the code size a bit by using a constant here. Since | ||
30 | * this file is completely chip-specific, it's safe to not use | ||
31 | * ioremap. Generic drivers should of course never do this. | ||
32 | */ | ||
33 | #define AT32_PM_BASE 0xfff00000 | ||
28 | 34 | ||
29 | #define PBMEM(base) \ | 35 | #define PBMEM(base) \ |
30 | { \ | 36 | { \ |
@@ -88,6 +94,8 @@ static struct clk devname##_##_name = { \ | |||
88 | .index = _index, \ | 94 | .index = _index, \ |
89 | } | 95 | } |
90 | 96 | ||
97 | static DEFINE_SPINLOCK(pm_lock); | ||
98 | |||
91 | unsigned long at32ap7000_osc_rates[3] = { | 99 | unsigned long at32ap7000_osc_rates[3] = { |
92 | [0] = 32768, | 100 | [0] = 32768, |
93 | /* FIXME: these are ATSTK1002-specific */ | 101 | /* FIXME: these are ATSTK1002-specific */ |
@@ -104,11 +112,11 @@ static unsigned long pll_get_rate(struct clk *clk, unsigned long control) | |||
104 | { | 112 | { |
105 | unsigned long div, mul, rate; | 113 | unsigned long div, mul, rate; |
106 | 114 | ||
107 | if (!(control & SM_BIT(PLLEN))) | 115 | if (!(control & PM_BIT(PLLEN))) |
108 | return 0; | 116 | return 0; |
109 | 117 | ||
110 | div = SM_BFEXT(PLLDIV, control) + 1; | 118 | div = PM_BFEXT(PLLDIV, control) + 1; |
111 | mul = SM_BFEXT(PLLMUL, control) + 1; | 119 | mul = PM_BFEXT(PLLMUL, control) + 1; |
112 | 120 | ||
113 | rate = clk->parent->get_rate(clk->parent); | 121 | rate = clk->parent->get_rate(clk->parent); |
114 | rate = (rate + div / 2) / div; | 122 | rate = (rate + div / 2) / div; |
@@ -121,7 +129,7 @@ static unsigned long pll0_get_rate(struct clk *clk) | |||
121 | { | 129 | { |
122 | u32 control; | 130 | u32 control; |
123 | 131 | ||
124 | control = sm_readl(&system_manager, PM_PLL0); | 132 | control = pm_readl(PLL0); |
125 | 133 | ||
126 | return pll_get_rate(clk, control); | 134 | return pll_get_rate(clk, control); |
127 | } | 135 | } |
@@ -130,7 +138,7 @@ static unsigned long pll1_get_rate(struct clk *clk) | |||
130 | { | 138 | { |
131 | u32 control; | 139 | u32 control; |
132 | 140 | ||
133 | control = sm_readl(&system_manager, PM_PLL1); | 141 | control = pm_readl(PLL1); |
134 | 142 | ||
135 | return pll_get_rate(clk, control); | 143 | return pll_get_rate(clk, control); |
136 | } | 144 | } |
@@ -187,108 +195,139 @@ static unsigned long bus_clk_get_rate(struct clk *clk, unsigned int shift) | |||
187 | 195 | ||
188 | static void cpu_clk_mode(struct clk *clk, int enabled) | 196 | static void cpu_clk_mode(struct clk *clk, int enabled) |
189 | { | 197 | { |
190 | struct at32_sm *sm = &system_manager; | ||
191 | unsigned long flags; | 198 | unsigned long flags; |
192 | u32 mask; | 199 | u32 mask; |
193 | 200 | ||
194 | spin_lock_irqsave(&sm->lock, flags); | 201 | spin_lock_irqsave(&pm_lock, flags); |
195 | mask = sm_readl(sm, PM_CPU_MASK); | 202 | mask = pm_readl(CPU_MASK); |
196 | if (enabled) | 203 | if (enabled) |
197 | mask |= 1 << clk->index; | 204 | mask |= 1 << clk->index; |
198 | else | 205 | else |
199 | mask &= ~(1 << clk->index); | 206 | mask &= ~(1 << clk->index); |
200 | sm_writel(sm, PM_CPU_MASK, mask); | 207 | pm_writel(CPU_MASK, mask); |
201 | spin_unlock_irqrestore(&sm->lock, flags); | 208 | spin_unlock_irqrestore(&pm_lock, flags); |
202 | } | 209 | } |
203 | 210 | ||
204 | static unsigned long cpu_clk_get_rate(struct clk *clk) | 211 | static unsigned long cpu_clk_get_rate(struct clk *clk) |
205 | { | 212 | { |
206 | unsigned long cksel, shift = 0; | 213 | unsigned long cksel, shift = 0; |
207 | 214 | ||
208 | cksel = sm_readl(&system_manager, PM_CKSEL); | 215 | cksel = pm_readl(CKSEL); |
209 | if (cksel & SM_BIT(CPUDIV)) | 216 | if (cksel & PM_BIT(CPUDIV)) |
210 | shift = SM_BFEXT(CPUSEL, cksel) + 1; | 217 | shift = PM_BFEXT(CPUSEL, cksel) + 1; |
211 | 218 | ||
212 | return bus_clk_get_rate(clk, shift); | 219 | return bus_clk_get_rate(clk, shift); |
213 | } | 220 | } |
214 | 221 | ||
222 | static long cpu_clk_set_rate(struct clk *clk, unsigned long rate, int apply) | ||
223 | { | ||
224 | u32 control; | ||
225 | unsigned long parent_rate, child_div, actual_rate, div; | ||
226 | |||
227 | parent_rate = clk->parent->get_rate(clk->parent); | ||
228 | control = pm_readl(CKSEL); | ||
229 | |||
230 | if (control & PM_BIT(HSBDIV)) | ||
231 | child_div = 1 << (PM_BFEXT(HSBSEL, control) + 1); | ||
232 | else | ||
233 | child_div = 1; | ||
234 | |||
235 | if (rate > 3 * (parent_rate / 4) || child_div == 1) { | ||
236 | actual_rate = parent_rate; | ||
237 | control &= ~PM_BIT(CPUDIV); | ||
238 | } else { | ||
239 | unsigned int cpusel; | ||
240 | div = (parent_rate + rate / 2) / rate; | ||
241 | if (div > child_div) | ||
242 | div = child_div; | ||
243 | cpusel = (div > 1) ? (fls(div) - 2) : 0; | ||
244 | control = PM_BIT(CPUDIV) | PM_BFINS(CPUSEL, cpusel, control); | ||
245 | actual_rate = parent_rate / (1 << (cpusel + 1)); | ||
246 | } | ||
247 | |||
248 | pr_debug("clk %s: new rate %lu (actual rate %lu)\n", | ||
249 | clk->name, rate, actual_rate); | ||
250 | |||
251 | if (apply) | ||
252 | pm_writel(CKSEL, control); | ||
253 | |||
254 | return actual_rate; | ||
255 | } | ||
256 | |||
215 | static void hsb_clk_mode(struct clk *clk, int enabled) | 257 | static void hsb_clk_mode(struct clk *clk, int enabled) |
216 | { | 258 | { |
217 | struct at32_sm *sm = &system_manager; | ||
218 | unsigned long flags; | 259 | unsigned long flags; |
219 | u32 mask; | 260 | u32 mask; |
220 | 261 | ||
221 | spin_lock_irqsave(&sm->lock, flags); | 262 | spin_lock_irqsave(&pm_lock, flags); |
222 | mask = sm_readl(sm, PM_HSB_MASK); | 263 | mask = pm_readl(HSB_MASK); |
223 | if (enabled) | 264 | if (enabled) |
224 | mask |= 1 << clk->index; | 265 | mask |= 1 << clk->index; |
225 | else | 266 | else |
226 | mask &= ~(1 << clk->index); | 267 | mask &= ~(1 << clk->index); |
227 | sm_writel(sm, PM_HSB_MASK, mask); | 268 | pm_writel(HSB_MASK, mask); |
228 | spin_unlock_irqrestore(&sm->lock, flags); | 269 | spin_unlock_irqrestore(&pm_lock, flags); |
229 | } | 270 | } |
230 | 271 | ||
231 | static unsigned long hsb_clk_get_rate(struct clk *clk) | 272 | static unsigned long hsb_clk_get_rate(struct clk *clk) |
232 | { | 273 | { |
233 | unsigned long cksel, shift = 0; | 274 | unsigned long cksel, shift = 0; |
234 | 275 | ||
235 | cksel = sm_readl(&system_manager, PM_CKSEL); | 276 | cksel = pm_readl(CKSEL); |
236 | if (cksel & SM_BIT(HSBDIV)) | 277 | if (cksel & PM_BIT(HSBDIV)) |
237 | shift = SM_BFEXT(HSBSEL, cksel) + 1; | 278 | shift = PM_BFEXT(HSBSEL, cksel) + 1; |
238 | 279 | ||
239 | return bus_clk_get_rate(clk, shift); | 280 | return bus_clk_get_rate(clk, shift); |
240 | } | 281 | } |
241 | 282 | ||
242 | static void pba_clk_mode(struct clk *clk, int enabled) | 283 | static void pba_clk_mode(struct clk *clk, int enabled) |
243 | { | 284 | { |
244 | struct at32_sm *sm = &system_manager; | ||
245 | unsigned long flags; | 285 | unsigned long flags; |
246 | u32 mask; | 286 | u32 mask; |
247 | 287 | ||
248 | spin_lock_irqsave(&sm->lock, flags); | 288 | spin_lock_irqsave(&pm_lock, flags); |
249 | mask = sm_readl(sm, PM_PBA_MASK); | 289 | mask = pm_readl(PBA_MASK); |
250 | if (enabled) | 290 | if (enabled) |
251 | mask |= 1 << clk->index; | 291 | mask |= 1 << clk->index; |
252 | else | 292 | else |
253 | mask &= ~(1 << clk->index); | 293 | mask &= ~(1 << clk->index); |
254 | sm_writel(sm, PM_PBA_MASK, mask); | 294 | pm_writel(PBA_MASK, mask); |
255 | spin_unlock_irqrestore(&sm->lock, flags); | 295 | spin_unlock_irqrestore(&pm_lock, flags); |
256 | } | 296 | } |
257 | 297 | ||
258 | static unsigned long pba_clk_get_rate(struct clk *clk) | 298 | static unsigned long pba_clk_get_rate(struct clk *clk) |
259 | { | 299 | { |
260 | unsigned long cksel, shift = 0; | 300 | unsigned long cksel, shift = 0; |
261 | 301 | ||
262 | cksel = sm_readl(&system_manager, PM_CKSEL); | 302 | cksel = pm_readl(CKSEL); |
263 | if (cksel & SM_BIT(PBADIV)) | 303 | if (cksel & PM_BIT(PBADIV)) |
264 | shift = SM_BFEXT(PBASEL, cksel) + 1; | 304 | shift = PM_BFEXT(PBASEL, cksel) + 1; |
265 | 305 | ||
266 | return bus_clk_get_rate(clk, shift); | 306 | return bus_clk_get_rate(clk, shift); |
267 | } | 307 | } |
268 | 308 | ||
269 | static void pbb_clk_mode(struct clk *clk, int enabled) | 309 | static void pbb_clk_mode(struct clk *clk, int enabled) |
270 | { | 310 | { |
271 | struct at32_sm *sm = &system_manager; | ||
272 | unsigned long flags; | 311 | unsigned long flags; |
273 | u32 mask; | 312 | u32 mask; |
274 | 313 | ||
275 | spin_lock_irqsave(&sm->lock, flags); | 314 | spin_lock_irqsave(&pm_lock, flags); |
276 | mask = sm_readl(sm, PM_PBB_MASK); | 315 | mask = pm_readl(PBB_MASK); |
277 | if (enabled) | 316 | if (enabled) |
278 | mask |= 1 << clk->index; | 317 | mask |= 1 << clk->index; |
279 | else | 318 | else |
280 | mask &= ~(1 << clk->index); | 319 | mask &= ~(1 << clk->index); |
281 | sm_writel(sm, PM_PBB_MASK, mask); | 320 | pm_writel(PBB_MASK, mask); |
282 | spin_unlock_irqrestore(&sm->lock, flags); | 321 | spin_unlock_irqrestore(&pm_lock, flags); |
283 | } | 322 | } |
284 | 323 | ||
285 | static unsigned long pbb_clk_get_rate(struct clk *clk) | 324 | static unsigned long pbb_clk_get_rate(struct clk *clk) |
286 | { | 325 | { |
287 | unsigned long cksel, shift = 0; | 326 | unsigned long cksel, shift = 0; |
288 | 327 | ||
289 | cksel = sm_readl(&system_manager, PM_CKSEL); | 328 | cksel = pm_readl(CKSEL); |
290 | if (cksel & SM_BIT(PBBDIV)) | 329 | if (cksel & PM_BIT(PBBDIV)) |
291 | shift = SM_BFEXT(PBBSEL, cksel) + 1; | 330 | shift = PM_BFEXT(PBBSEL, cksel) + 1; |
292 | 331 | ||
293 | return bus_clk_get_rate(clk, shift); | 332 | return bus_clk_get_rate(clk, shift); |
294 | } | 333 | } |
@@ -296,6 +335,7 @@ static unsigned long pbb_clk_get_rate(struct clk *clk) | |||
296 | static struct clk cpu_clk = { | 335 | static struct clk cpu_clk = { |
297 | .name = "cpu", | 336 | .name = "cpu", |
298 | .get_rate = cpu_clk_get_rate, | 337 | .get_rate = cpu_clk_get_rate, |
338 | .set_rate = cpu_clk_set_rate, | ||
299 | .users = 1, | 339 | .users = 1, |
300 | }; | 340 | }; |
301 | static struct clk hsb_clk = { | 341 | static struct clk hsb_clk = { |
@@ -327,12 +367,12 @@ static void genclk_mode(struct clk *clk, int enabled) | |||
327 | { | 367 | { |
328 | u32 control; | 368 | u32 control; |
329 | 369 | ||
330 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 370 | control = pm_readl(GCCTRL(clk->index)); |
331 | if (enabled) | 371 | if (enabled) |
332 | control |= SM_BIT(CEN); | 372 | control |= PM_BIT(CEN); |
333 | else | 373 | else |
334 | control &= ~SM_BIT(CEN); | 374 | control &= ~PM_BIT(CEN); |
335 | sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control); | 375 | pm_writel(GCCTRL(clk->index), control); |
336 | } | 376 | } |
337 | 377 | ||
338 | static unsigned long genclk_get_rate(struct clk *clk) | 378 | static unsigned long genclk_get_rate(struct clk *clk) |
@@ -340,9 +380,9 @@ static unsigned long genclk_get_rate(struct clk *clk) | |||
340 | u32 control; | 380 | u32 control; |
341 | unsigned long div = 1; | 381 | unsigned long div = 1; |
342 | 382 | ||
343 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 383 | control = pm_readl(GCCTRL(clk->index)); |
344 | if (control & SM_BIT(DIVEN)) | 384 | if (control & PM_BIT(DIVEN)) |
345 | div = 2 * (SM_BFEXT(DIV, control) + 1); | 385 | div = 2 * (PM_BFEXT(DIV, control) + 1); |
346 | 386 | ||
347 | return clk->parent->get_rate(clk->parent) / div; | 387 | return clk->parent->get_rate(clk->parent) / div; |
348 | } | 388 | } |
@@ -353,23 +393,22 @@ static long genclk_set_rate(struct clk *clk, unsigned long rate, int apply) | |||
353 | unsigned long parent_rate, actual_rate, div; | 393 | unsigned long parent_rate, actual_rate, div; |
354 | 394 | ||
355 | parent_rate = clk->parent->get_rate(clk->parent); | 395 | parent_rate = clk->parent->get_rate(clk->parent); |
356 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 396 | control = pm_readl(GCCTRL(clk->index)); |
357 | 397 | ||
358 | if (rate > 3 * parent_rate / 4) { | 398 | if (rate > 3 * parent_rate / 4) { |
359 | actual_rate = parent_rate; | 399 | actual_rate = parent_rate; |
360 | control &= ~SM_BIT(DIVEN); | 400 | control &= ~PM_BIT(DIVEN); |
361 | } else { | 401 | } else { |
362 | div = (parent_rate + rate) / (2 * rate) - 1; | 402 | div = (parent_rate + rate) / (2 * rate) - 1; |
363 | control = SM_BFINS(DIV, div, control) | SM_BIT(DIVEN); | 403 | control = PM_BFINS(DIV, div, control) | PM_BIT(DIVEN); |
364 | actual_rate = parent_rate / (2 * (div + 1)); | 404 | actual_rate = parent_rate / (2 * (div + 1)); |
365 | } | 405 | } |
366 | 406 | ||
367 | printk("clk %s: new rate %lu (actual rate %lu)\n", | 407 | dev_dbg(clk->dev, "clk %s: new rate %lu (actual rate %lu)\n", |
368 | clk->name, rate, actual_rate); | 408 | clk->name, rate, actual_rate); |
369 | 409 | ||
370 | if (apply) | 410 | if (apply) |
371 | sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, | 411 | pm_writel(GCCTRL(clk->index), control); |
372 | control); | ||
373 | 412 | ||
374 | return actual_rate; | 413 | return actual_rate; |
375 | } | 414 | } |
@@ -378,24 +417,24 @@ int genclk_set_parent(struct clk *clk, struct clk *parent) | |||
378 | { | 417 | { |
379 | u32 control; | 418 | u32 control; |
380 | 419 | ||
381 | printk("clk %s: new parent %s (was %s)\n", | 420 | dev_dbg(clk->dev, "clk %s: new parent %s (was %s)\n", |
382 | clk->name, parent->name, clk->parent->name); | 421 | clk->name, parent->name, clk->parent->name); |
383 | 422 | ||
384 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 423 | control = pm_readl(GCCTRL(clk->index)); |
385 | 424 | ||
386 | if (parent == &osc1 || parent == &pll1) | 425 | if (parent == &osc1 || parent == &pll1) |
387 | control |= SM_BIT(OSCSEL); | 426 | control |= PM_BIT(OSCSEL); |
388 | else if (parent == &osc0 || parent == &pll0) | 427 | else if (parent == &osc0 || parent == &pll0) |
389 | control &= ~SM_BIT(OSCSEL); | 428 | control &= ~PM_BIT(OSCSEL); |
390 | else | 429 | else |
391 | return -EINVAL; | 430 | return -EINVAL; |
392 | 431 | ||
393 | if (parent == &pll0 || parent == &pll1) | 432 | if (parent == &pll0 || parent == &pll1) |
394 | control |= SM_BIT(PLLSEL); | 433 | control |= PM_BIT(PLLSEL); |
395 | else | 434 | else |
396 | control &= ~SM_BIT(PLLSEL); | 435 | control &= ~PM_BIT(PLLSEL); |
397 | 436 | ||
398 | sm_writel(&system_manager, PM_GCCTRL + 4 * clk->index, control); | 437 | pm_writel(GCCTRL(clk->index), control); |
399 | clk->parent = parent; | 438 | clk->parent = parent; |
400 | 439 | ||
401 | return 0; | 440 | return 0; |
@@ -408,11 +447,11 @@ static void __init genclk_init_parent(struct clk *clk) | |||
408 | 447 | ||
409 | BUG_ON(clk->index > 7); | 448 | BUG_ON(clk->index > 7); |
410 | 449 | ||
411 | control = sm_readl(&system_manager, PM_GCCTRL + 4 * clk->index); | 450 | control = pm_readl(GCCTRL(clk->index)); |
412 | if (control & SM_BIT(OSCSEL)) | 451 | if (control & PM_BIT(OSCSEL)) |
413 | parent = (control & SM_BIT(PLLSEL)) ? &pll1 : &osc1; | 452 | parent = (control & PM_BIT(PLLSEL)) ? &pll1 : &osc1; |
414 | else | 453 | else |
415 | parent = (control & SM_BIT(PLLSEL)) ? &pll0 : &osc0; | 454 | parent = (control & PM_BIT(PLLSEL)) ? &pll0 : &osc0; |
416 | 455 | ||
417 | clk->parent = parent; | 456 | clk->parent = parent; |
418 | } | 457 | } |
@@ -420,21 +459,53 @@ static void __init genclk_init_parent(struct clk *clk) | |||
420 | /* -------------------------------------------------------------------- | 459 | /* -------------------------------------------------------------------- |
421 | * System peripherals | 460 | * System peripherals |
422 | * -------------------------------------------------------------------- */ | 461 | * -------------------------------------------------------------------- */ |
423 | static struct resource sm_resource[] = { | 462 | static struct resource at32_pm0_resource[] = { |
424 | PBMEM(0xfff00000), | 463 | { |
425 | NAMED_IRQ(19, "eim"), | 464 | .start = 0xfff00000, |
426 | NAMED_IRQ(20, "pm"), | 465 | .end = 0xfff0007f, |
427 | NAMED_IRQ(21, "rtc"), | 466 | .flags = IORESOURCE_MEM, |
467 | }, | ||
468 | IRQ(20), | ||
428 | }; | 469 | }; |
429 | struct platform_device at32_sm_device = { | 470 | |
430 | .name = "sm", | 471 | static struct resource at32ap700x_rtc0_resource[] = { |
431 | .id = 0, | 472 | { |
432 | .resource = sm_resource, | 473 | .start = 0xfff00080, |
433 | .num_resources = ARRAY_SIZE(sm_resource), | 474 | .end = 0xfff000af, |
475 | .flags = IORESOURCE_MEM, | ||
476 | }, | ||
477 | IRQ(21), | ||
478 | }; | ||
479 | |||
480 | static struct resource at32_wdt0_resource[] = { | ||
481 | { | ||
482 | .start = 0xfff000b0, | ||
483 | .end = 0xfff000bf, | ||
484 | .flags = IORESOURCE_MEM, | ||
485 | }, | ||
486 | }; | ||
487 | |||
488 | static struct resource at32_eic0_resource[] = { | ||
489 | { | ||
490 | .start = 0xfff00100, | ||
491 | .end = 0xfff0013f, | ||
492 | .flags = IORESOURCE_MEM, | ||
493 | }, | ||
494 | IRQ(19), | ||
434 | }; | 495 | }; |
435 | static struct clk at32_sm_pclk = { | 496 | |
497 | DEFINE_DEV(at32_pm, 0); | ||
498 | DEFINE_DEV(at32ap700x_rtc, 0); | ||
499 | DEFINE_DEV(at32_wdt, 0); | ||
500 | DEFINE_DEV(at32_eic, 0); | ||
501 | |||
502 | /* | ||
503 | * Peripheral clock for PM, RTC, WDT and EIC. PM will ensure that this | ||
504 | * is always running. | ||
505 | */ | ||
506 | static struct clk at32_pm_pclk = { | ||
436 | .name = "pclk", | 507 | .name = "pclk", |
437 | .dev = &at32_sm_device.dev, | 508 | .dev = &at32_pm0_device.dev, |
438 | .parent = &pbb_clk, | 509 | .parent = &pbb_clk, |
439 | .mode = pbb_clk_mode, | 510 | .mode = pbb_clk_mode, |
440 | .get_rate = pbb_clk_get_rate, | 511 | .get_rate = pbb_clk_get_rate, |
@@ -583,10 +654,11 @@ DEV_CLK(mck, pio4, pba, 14); | |||
583 | 654 | ||
584 | void __init at32_add_system_devices(void) | 655 | void __init at32_add_system_devices(void) |
585 | { | 656 | { |
586 | system_manager.eim_first_irq = EIM_IRQ_BASE; | 657 | platform_device_register(&at32_pm0_device); |
587 | |||
588 | platform_device_register(&at32_sm_device); | ||
589 | platform_device_register(&at32_intc0_device); | 658 | platform_device_register(&at32_intc0_device); |
659 | platform_device_register(&at32ap700x_rtc0_device); | ||
660 | platform_device_register(&at32_wdt0_device); | ||
661 | platform_device_register(&at32_eic0_device); | ||
590 | platform_device_register(&smc0_device); | 662 | platform_device_register(&smc0_device); |
591 | platform_device_register(&pdc_device); | 663 | platform_device_register(&pdc_device); |
592 | 664 | ||
@@ -1013,6 +1085,89 @@ err_dup_modedb: | |||
1013 | } | 1085 | } |
1014 | 1086 | ||
1015 | /* -------------------------------------------------------------------- | 1087 | /* -------------------------------------------------------------------- |
1088 | * SSC | ||
1089 | * -------------------------------------------------------------------- */ | ||
1090 | static struct resource ssc0_resource[] = { | ||
1091 | PBMEM(0xffe01c00), | ||
1092 | IRQ(10), | ||
1093 | }; | ||
1094 | DEFINE_DEV(ssc, 0); | ||
1095 | DEV_CLK(pclk, ssc0, pba, 7); | ||
1096 | |||
1097 | static struct resource ssc1_resource[] = { | ||
1098 | PBMEM(0xffe02000), | ||
1099 | IRQ(11), | ||
1100 | }; | ||
1101 | DEFINE_DEV(ssc, 1); | ||
1102 | DEV_CLK(pclk, ssc1, pba, 8); | ||
1103 | |||
1104 | static struct resource ssc2_resource[] = { | ||
1105 | PBMEM(0xffe02400), | ||
1106 | IRQ(12), | ||
1107 | }; | ||
1108 | DEFINE_DEV(ssc, 2); | ||
1109 | DEV_CLK(pclk, ssc2, pba, 9); | ||
1110 | |||
1111 | struct platform_device *__init | ||
1112 | at32_add_device_ssc(unsigned int id, unsigned int flags) | ||
1113 | { | ||
1114 | struct platform_device *pdev; | ||
1115 | |||
1116 | switch (id) { | ||
1117 | case 0: | ||
1118 | pdev = &ssc0_device; | ||
1119 | if (flags & ATMEL_SSC_RF) | ||
1120 | select_peripheral(PA(21), PERIPH_A, 0); /* RF */ | ||
1121 | if (flags & ATMEL_SSC_RK) | ||
1122 | select_peripheral(PA(22), PERIPH_A, 0); /* RK */ | ||
1123 | if (flags & ATMEL_SSC_TK) | ||
1124 | select_peripheral(PA(23), PERIPH_A, 0); /* TK */ | ||
1125 | if (flags & ATMEL_SSC_TF) | ||
1126 | select_peripheral(PA(24), PERIPH_A, 0); /* TF */ | ||
1127 | if (flags & ATMEL_SSC_TD) | ||
1128 | select_peripheral(PA(25), PERIPH_A, 0); /* TD */ | ||
1129 | if (flags & ATMEL_SSC_RD) | ||
1130 | select_peripheral(PA(26), PERIPH_A, 0); /* RD */ | ||
1131 | break; | ||
1132 | case 1: | ||
1133 | pdev = &ssc1_device; | ||
1134 | if (flags & ATMEL_SSC_RF) | ||
1135 | select_peripheral(PA(0), PERIPH_B, 0); /* RF */ | ||
1136 | if (flags & ATMEL_SSC_RK) | ||
1137 | select_peripheral(PA(1), PERIPH_B, 0); /* RK */ | ||
1138 | if (flags & ATMEL_SSC_TK) | ||
1139 | select_peripheral(PA(2), PERIPH_B, 0); /* TK */ | ||
1140 | if (flags & ATMEL_SSC_TF) | ||
1141 | select_peripheral(PA(3), PERIPH_B, 0); /* TF */ | ||
1142 | if (flags & ATMEL_SSC_TD) | ||
1143 | select_peripheral(PA(4), PERIPH_B, 0); /* TD */ | ||
1144 | if (flags & ATMEL_SSC_RD) | ||
1145 | select_peripheral(PA(5), PERIPH_B, 0); /* RD */ | ||
1146 | break; | ||
1147 | case 2: | ||
1148 | pdev = &ssc2_device; | ||
1149 | if (flags & ATMEL_SSC_TD) | ||
1150 | select_peripheral(PB(13), PERIPH_A, 0); /* TD */ | ||
1151 | if (flags & ATMEL_SSC_RD) | ||
1152 | select_peripheral(PB(14), PERIPH_A, 0); /* RD */ | ||
1153 | if (flags & ATMEL_SSC_TK) | ||
1154 | select_peripheral(PB(15), PERIPH_A, 0); /* TK */ | ||
1155 | if (flags & ATMEL_SSC_TF) | ||
1156 | select_peripheral(PB(16), PERIPH_A, 0); /* TF */ | ||
1157 | if (flags & ATMEL_SSC_RF) | ||
1158 | select_peripheral(PB(17), PERIPH_A, 0); /* RF */ | ||
1159 | if (flags & ATMEL_SSC_RK) | ||
1160 | select_peripheral(PB(18), PERIPH_A, 0); /* RK */ | ||
1161 | break; | ||
1162 | default: | ||
1163 | return NULL; | ||
1164 | } | ||
1165 | |||
1166 | platform_device_register(pdev); | ||
1167 | return pdev; | ||
1168 | } | ||
1169 | |||
1170 | /* -------------------------------------------------------------------- | ||
1016 | * GCLK | 1171 | * GCLK |
1017 | * -------------------------------------------------------------------- */ | 1172 | * -------------------------------------------------------------------- */ |
1018 | static struct clk gclk0 = { | 1173 | static struct clk gclk0 = { |
@@ -1066,7 +1221,7 @@ struct clk *at32_clock_list[] = { | |||
1066 | &hsb_clk, | 1221 | &hsb_clk, |
1067 | &pba_clk, | 1222 | &pba_clk, |
1068 | &pbb_clk, | 1223 | &pbb_clk, |
1069 | &at32_sm_pclk, | 1224 | &at32_pm_pclk, |
1070 | &at32_intc0_pclk, | 1225 | &at32_intc0_pclk, |
1071 | &hmatrix_clk, | 1226 | &hmatrix_clk, |
1072 | &ebi_clk, | 1227 | &ebi_clk, |
@@ -1094,6 +1249,9 @@ struct clk *at32_clock_list[] = { | |||
1094 | &atmel_spi1_spi_clk, | 1249 | &atmel_spi1_spi_clk, |
1095 | &atmel_lcdfb0_hck1, | 1250 | &atmel_lcdfb0_hck1, |
1096 | &atmel_lcdfb0_pixclk, | 1251 | &atmel_lcdfb0_pixclk, |
1252 | &ssc0_pclk, | ||
1253 | &ssc1_pclk, | ||
1254 | &ssc2_pclk, | ||
1097 | &gclk0, | 1255 | &gclk0, |
1098 | &gclk1, | 1256 | &gclk1, |
1099 | &gclk2, | 1257 | &gclk2, |
@@ -1113,18 +1271,20 @@ void __init at32_portmux_init(void) | |||
1113 | 1271 | ||
1114 | void __init at32_clock_init(void) | 1272 | void __init at32_clock_init(void) |
1115 | { | 1273 | { |
1116 | struct at32_sm *sm = &system_manager; | ||
1117 | u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; | 1274 | u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0; |
1118 | int i; | 1275 | int i; |
1119 | 1276 | ||
1120 | if (sm_readl(sm, PM_MCCTRL) & SM_BIT(PLLSEL)) | 1277 | if (pm_readl(MCCTRL) & PM_BIT(PLLSEL)) { |
1121 | main_clock = &pll0; | 1278 | main_clock = &pll0; |
1122 | else | 1279 | cpu_clk.parent = &pll0; |
1280 | } else { | ||
1123 | main_clock = &osc0; | 1281 | main_clock = &osc0; |
1282 | cpu_clk.parent = &osc0; | ||
1283 | } | ||
1124 | 1284 | ||
1125 | if (sm_readl(sm, PM_PLL0) & SM_BIT(PLLOSC)) | 1285 | if (pm_readl(PLL0) & PM_BIT(PLLOSC)) |
1126 | pll0.parent = &osc1; | 1286 | pll0.parent = &osc1; |
1127 | if (sm_readl(sm, PM_PLL1) & SM_BIT(PLLOSC)) | 1287 | if (pm_readl(PLL1) & PM_BIT(PLLOSC)) |
1128 | pll1.parent = &osc1; | 1288 | pll1.parent = &osc1; |
1129 | 1289 | ||
1130 | genclk_init_parent(&gclk0); | 1290 | genclk_init_parent(&gclk0); |
@@ -1157,8 +1317,8 @@ void __init at32_clock_init(void) | |||
1157 | pbb_mask |= 1 << clk->index; | 1317 | pbb_mask |= 1 << clk->index; |
1158 | } | 1318 | } |
1159 | 1319 | ||
1160 | sm_writel(sm, PM_CPU_MASK, cpu_mask); | 1320 | pm_writel(CPU_MASK, cpu_mask); |
1161 | sm_writel(sm, PM_HSB_MASK, hsb_mask); | 1321 | pm_writel(HSB_MASK, hsb_mask); |
1162 | sm_writel(sm, PM_PBA_MASK, pba_mask); | 1322 | pm_writel(PBA_MASK, pba_mask); |
1163 | sm_writel(sm, PM_PBB_MASK, pbb_mask); | 1323 | pm_writel(PBB_MASK, pbb_mask); |
1164 | } | 1324 | } |
diff --git a/arch/avr32/mach-at32ap/cpufreq.c b/arch/avr32/mach-at32ap/cpufreq.c new file mode 100644 index 000000000000..235524b79193 --- /dev/null +++ b/arch/avr32/mach-at32ap/cpufreq.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004-2007 Atmel Corporation | ||
3 | * | ||
4 | * Based on MIPS implementation arch/mips/kernel/time.c | ||
5 | * Copyright 2001 MontaVista Software Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | /*#define DEBUG*/ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/cpufreq.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <asm/system.h> | ||
22 | |||
23 | static struct clk *cpuclk; | ||
24 | |||
25 | static int at32_verify_speed(struct cpufreq_policy *policy) | ||
26 | { | ||
27 | if (policy->cpu != 0) | ||
28 | return -EINVAL; | ||
29 | |||
30 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
31 | policy->cpuinfo.max_freq); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static unsigned int at32_get_speed(unsigned int cpu) | ||
36 | { | ||
37 | /* No SMP support */ | ||
38 | if (cpu) | ||
39 | return 0; | ||
40 | return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000); | ||
41 | } | ||
42 | |||
43 | static int at32_set_target(struct cpufreq_policy *policy, | ||
44 | unsigned int target_freq, | ||
45 | unsigned int relation) | ||
46 | { | ||
47 | struct cpufreq_freqs freqs; | ||
48 | long freq; | ||
49 | |||
50 | /* Convert target_freq from kHz to Hz */ | ||
51 | freq = clk_round_rate(cpuclk, target_freq * 1000); | ||
52 | |||
53 | /* Check if policy->min <= new_freq <= policy->max */ | ||
54 | if(freq < (policy->min * 1000) || freq > (policy->max * 1000)) | ||
55 | return -EINVAL; | ||
56 | |||
57 | pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000); | ||
58 | |||
59 | freqs.old = at32_get_speed(0); | ||
60 | freqs.new = (freq + 500) / 1000; | ||
61 | freqs.cpu = 0; | ||
62 | freqs.flags = 0; | ||
63 | |||
64 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
65 | clk_set_rate(cpuclk, freq); | ||
66 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
67 | |||
68 | pr_debug("cpufreq: set frequency %lu Hz\n", freq); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) | ||
74 | { | ||
75 | if (policy->cpu != 0) | ||
76 | return -EINVAL; | ||
77 | |||
78 | cpuclk = clk_get(NULL, "cpu"); | ||
79 | if (IS_ERR(cpuclk)) { | ||
80 | pr_debug("cpufreq: could not get CPU clk\n"); | ||
81 | return PTR_ERR(cpuclk); | ||
82 | } | ||
83 | |||
84 | policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; | ||
85 | policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; | ||
86 | policy->cpuinfo.transition_latency = 0; | ||
87 | policy->cur = at32_get_speed(0); | ||
88 | policy->min = policy->cpuinfo.min_freq; | ||
89 | policy->max = policy->cpuinfo.max_freq; | ||
90 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
91 | |||
92 | printk("cpufreq: AT32AP CPU frequency driver\n"); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static struct cpufreq_driver at32_driver = { | ||
98 | .name = "at32ap", | ||
99 | .owner = THIS_MODULE, | ||
100 | .init = at32_cpufreq_driver_init, | ||
101 | .verify = at32_verify_speed, | ||
102 | .target = at32_set_target, | ||
103 | .get = at32_get_speed, | ||
104 | .flags = CPUFREQ_STICKY, | ||
105 | }; | ||
106 | |||
107 | static int __init at32_cpufreq_init(void) | ||
108 | { | ||
109 | return cpufreq_register_driver(&at32_driver); | ||
110 | } | ||
111 | |||
112 | arch_initcall(at32_cpufreq_init); | ||
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c index 4a60eccfebd2..8acd01090031 100644 --- a/arch/avr32/mach-at32ap/extint.c +++ b/arch/avr32/mach-at32ap/extint.c | |||
@@ -17,42 +17,83 @@ | |||
17 | 17 | ||
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | 19 | ||
20 | #include <asm/arch/sm.h> | 20 | /* EIC register offsets */ |
21 | 21 | #define EIC_IER 0x0000 | |
22 | #include "sm.h" | 22 | #define EIC_IDR 0x0004 |
23 | #define EIC_IMR 0x0008 | ||
24 | #define EIC_ISR 0x000c | ||
25 | #define EIC_ICR 0x0010 | ||
26 | #define EIC_MODE 0x0014 | ||
27 | #define EIC_EDGE 0x0018 | ||
28 | #define EIC_LEVEL 0x001c | ||
29 | #define EIC_TEST 0x0020 | ||
30 | #define EIC_NMIC 0x0024 | ||
31 | |||
32 | /* Bitfields in TEST */ | ||
33 | #define EIC_TESTEN_OFFSET 31 | ||
34 | #define EIC_TESTEN_SIZE 1 | ||
35 | |||
36 | /* Bitfields in NMIC */ | ||
37 | #define EIC_EN_OFFSET 0 | ||
38 | #define EIC_EN_SIZE 1 | ||
39 | |||
40 | /* Bit manipulation macros */ | ||
41 | #define EIC_BIT(name) \ | ||
42 | (1 << EIC_##name##_OFFSET) | ||
43 | #define EIC_BF(name,value) \ | ||
44 | (((value) & ((1 << EIC_##name##_SIZE) - 1)) \ | ||
45 | << EIC_##name##_OFFSET) | ||
46 | #define EIC_BFEXT(name,value) \ | ||
47 | (((value) >> EIC_##name##_OFFSET) \ | ||
48 | & ((1 << EIC_##name##_SIZE) - 1)) | ||
49 | #define EIC_BFINS(name,value,old) \ | ||
50 | (((old) & ~(((1 << EIC_##name##_SIZE) - 1) \ | ||
51 | << EIC_##name##_OFFSET)) \ | ||
52 | | EIC_BF(name,value)) | ||
53 | |||
54 | /* Register access macros */ | ||
55 | #define eic_readl(port,reg) \ | ||
56 | __raw_readl((port)->regs + EIC_##reg) | ||
57 | #define eic_writel(port,reg,value) \ | ||
58 | __raw_writel((value), (port)->regs + EIC_##reg) | ||
59 | |||
60 | struct eic { | ||
61 | void __iomem *regs; | ||
62 | struct irq_chip *chip; | ||
63 | unsigned int first_irq; | ||
64 | }; | ||
23 | 65 | ||
24 | static void eim_ack_irq(unsigned int irq) | 66 | static void eic_ack_irq(unsigned int irq) |
25 | { | 67 | { |
26 | struct at32_sm *sm = get_irq_chip_data(irq); | 68 | struct eic *eic = get_irq_chip_data(irq); |
27 | sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq)); | 69 | eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); |
28 | } | 70 | } |
29 | 71 | ||
30 | static void eim_mask_irq(unsigned int irq) | 72 | static void eic_mask_irq(unsigned int irq) |
31 | { | 73 | { |
32 | struct at32_sm *sm = get_irq_chip_data(irq); | 74 | struct eic *eic = get_irq_chip_data(irq); |
33 | sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq)); | 75 | eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); |
34 | } | 76 | } |
35 | 77 | ||
36 | static void eim_mask_ack_irq(unsigned int irq) | 78 | static void eic_mask_ack_irq(unsigned int irq) |
37 | { | 79 | { |
38 | struct at32_sm *sm = get_irq_chip_data(irq); | 80 | struct eic *eic = get_irq_chip_data(irq); |
39 | sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq)); | 81 | eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); |
40 | sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq)); | 82 | eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); |
41 | } | 83 | } |
42 | 84 | ||
43 | static void eim_unmask_irq(unsigned int irq) | 85 | static void eic_unmask_irq(unsigned int irq) |
44 | { | 86 | { |
45 | struct at32_sm *sm = get_irq_chip_data(irq); | 87 | struct eic *eic = get_irq_chip_data(irq); |
46 | sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq)); | 88 | eic_writel(eic, IER, 1 << (irq - eic->first_irq)); |
47 | } | 89 | } |
48 | 90 | ||
49 | static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | 91 | static int eic_set_irq_type(unsigned int irq, unsigned int flow_type) |
50 | { | 92 | { |
51 | struct at32_sm *sm = get_irq_chip_data(irq); | 93 | struct eic *eic = get_irq_chip_data(irq); |
52 | struct irq_desc *desc; | 94 | struct irq_desc *desc; |
53 | unsigned int i = irq - sm->eim_first_irq; | 95 | unsigned int i = irq - eic->first_irq; |
54 | u32 mode, edge, level; | 96 | u32 mode, edge, level; |
55 | unsigned long flags; | ||
56 | int ret = 0; | 97 | int ret = 0; |
57 | 98 | ||
58 | flow_type &= IRQ_TYPE_SENSE_MASK; | 99 | flow_type &= IRQ_TYPE_SENSE_MASK; |
@@ -60,11 +101,10 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | |||
60 | flow_type = IRQ_TYPE_LEVEL_LOW; | 101 | flow_type = IRQ_TYPE_LEVEL_LOW; |
61 | 102 | ||
62 | desc = &irq_desc[irq]; | 103 | desc = &irq_desc[irq]; |
63 | spin_lock_irqsave(&sm->lock, flags); | ||
64 | 104 | ||
65 | mode = sm_readl(sm, EIM_MODE); | 105 | mode = eic_readl(eic, MODE); |
66 | edge = sm_readl(sm, EIM_EDGE); | 106 | edge = eic_readl(eic, EDGE); |
67 | level = sm_readl(sm, EIM_LEVEL); | 107 | level = eic_readl(eic, LEVEL); |
68 | 108 | ||
69 | switch (flow_type) { | 109 | switch (flow_type) { |
70 | case IRQ_TYPE_LEVEL_LOW: | 110 | case IRQ_TYPE_LEVEL_LOW: |
@@ -89,9 +129,9 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | |||
89 | } | 129 | } |
90 | 130 | ||
91 | if (ret == 0) { | 131 | if (ret == 0) { |
92 | sm_writel(sm, EIM_MODE, mode); | 132 | eic_writel(eic, MODE, mode); |
93 | sm_writel(sm, EIM_EDGE, edge); | 133 | eic_writel(eic, EDGE, edge); |
94 | sm_writel(sm, EIM_LEVEL, level); | 134 | eic_writel(eic, LEVEL, level); |
95 | 135 | ||
96 | if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | 136 | if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) |
97 | flow_type |= IRQ_LEVEL; | 137 | flow_type |= IRQ_LEVEL; |
@@ -99,35 +139,33 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | |||
99 | desc->status |= flow_type; | 139 | desc->status |= flow_type; |
100 | } | 140 | } |
101 | 141 | ||
102 | spin_unlock_irqrestore(&sm->lock, flags); | ||
103 | |||
104 | return ret; | 142 | return ret; |
105 | } | 143 | } |
106 | 144 | ||
107 | struct irq_chip eim_chip = { | 145 | struct irq_chip eic_chip = { |
108 | .name = "eim", | 146 | .name = "eic", |
109 | .ack = eim_ack_irq, | 147 | .ack = eic_ack_irq, |
110 | .mask = eim_mask_irq, | 148 | .mask = eic_mask_irq, |
111 | .mask_ack = eim_mask_ack_irq, | 149 | .mask_ack = eic_mask_ack_irq, |
112 | .unmask = eim_unmask_irq, | 150 | .unmask = eic_unmask_irq, |
113 | .set_type = eim_set_irq_type, | 151 | .set_type = eic_set_irq_type, |
114 | }; | 152 | }; |
115 | 153 | ||
116 | static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) | 154 | static void demux_eic_irq(unsigned int irq, struct irq_desc *desc) |
117 | { | 155 | { |
118 | struct at32_sm *sm = desc->handler_data; | 156 | struct eic *eic = desc->handler_data; |
119 | struct irq_desc *ext_desc; | 157 | struct irq_desc *ext_desc; |
120 | unsigned long status, pending; | 158 | unsigned long status, pending; |
121 | unsigned int i, ext_irq; | 159 | unsigned int i, ext_irq; |
122 | 160 | ||
123 | status = sm_readl(sm, EIM_ISR); | 161 | status = eic_readl(eic, ISR); |
124 | pending = status & sm_readl(sm, EIM_IMR); | 162 | pending = status & eic_readl(eic, IMR); |
125 | 163 | ||
126 | while (pending) { | 164 | while (pending) { |
127 | i = fls(pending) - 1; | 165 | i = fls(pending) - 1; |
128 | pending &= ~(1 << i); | 166 | pending &= ~(1 << i); |
129 | 167 | ||
130 | ext_irq = i + sm->eim_first_irq; | 168 | ext_irq = i + eic->first_irq; |
131 | ext_desc = irq_desc + ext_irq; | 169 | ext_desc = irq_desc + ext_irq; |
132 | if (ext_desc->status & IRQ_LEVEL) | 170 | if (ext_desc->status & IRQ_LEVEL) |
133 | handle_level_irq(ext_irq, ext_desc); | 171 | handle_level_irq(ext_irq, ext_desc); |
@@ -136,51 +174,85 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) | |||
136 | } | 174 | } |
137 | } | 175 | } |
138 | 176 | ||
139 | static int __init eim_init(void) | 177 | static int __init eic_probe(struct platform_device *pdev) |
140 | { | 178 | { |
141 | struct at32_sm *sm = &system_manager; | 179 | struct eic *eic; |
180 | struct resource *regs; | ||
142 | unsigned int i; | 181 | unsigned int i; |
143 | unsigned int nr_irqs; | 182 | unsigned int nr_irqs; |
144 | unsigned int int_irq; | 183 | unsigned int int_irq; |
184 | int ret; | ||
145 | u32 pattern; | 185 | u32 pattern; |
146 | 186 | ||
147 | /* | 187 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
148 | * The EIM is really the same module as SM, so register | 188 | int_irq = platform_get_irq(pdev, 0); |
149 | * mapping, etc. has been taken care of already. | 189 | if (!regs || !int_irq) { |
150 | */ | 190 | dev_dbg(&pdev->dev, "missing regs and/or irq resource\n"); |
191 | return -ENXIO; | ||
192 | } | ||
193 | |||
194 | ret = -ENOMEM; | ||
195 | eic = kzalloc(sizeof(struct eic), GFP_KERNEL); | ||
196 | if (!eic) { | ||
197 | dev_dbg(&pdev->dev, "no memory for eic structure\n"); | ||
198 | goto err_kzalloc; | ||
199 | } | ||
200 | |||
201 | eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id; | ||
202 | eic->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
203 | if (!eic->regs) { | ||
204 | dev_dbg(&pdev->dev, "failed to map regs\n"); | ||
205 | goto err_ioremap; | ||
206 | } | ||
151 | 207 | ||
152 | /* | 208 | /* |
153 | * Find out how many interrupt lines that are actually | 209 | * Find out how many interrupt lines that are actually |
154 | * implemented in hardware. | 210 | * implemented in hardware. |
155 | */ | 211 | */ |
156 | sm_writel(sm, EIM_IDR, ~0UL); | 212 | eic_writel(eic, IDR, ~0UL); |
157 | sm_writel(sm, EIM_MODE, ~0UL); | 213 | eic_writel(eic, MODE, ~0UL); |
158 | pattern = sm_readl(sm, EIM_MODE); | 214 | pattern = eic_readl(eic, MODE); |
159 | nr_irqs = fls(pattern); | 215 | nr_irqs = fls(pattern); |
160 | 216 | ||
161 | /* Trigger on falling edge unless overridden by driver */ | 217 | /* Trigger on falling edge unless overridden by driver */ |
162 | sm_writel(sm, EIM_MODE, 0UL); | 218 | eic_writel(eic, MODE, 0UL); |
163 | sm_writel(sm, EIM_EDGE, 0UL); | 219 | eic_writel(eic, EDGE, 0UL); |
164 | 220 | ||
165 | sm->eim_chip = &eim_chip; | 221 | eic->chip = &eic_chip; |
166 | 222 | ||
167 | for (i = 0; i < nr_irqs; i++) { | 223 | for (i = 0; i < nr_irqs; i++) { |
168 | /* NOTE the handler we set here is ignored by the demux */ | 224 | /* NOTE the handler we set here is ignored by the demux */ |
169 | set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip, | 225 | set_irq_chip_and_handler(eic->first_irq + i, &eic_chip, |
170 | handle_level_irq); | 226 | handle_level_irq); |
171 | set_irq_chip_data(sm->eim_first_irq + i, sm); | 227 | set_irq_chip_data(eic->first_irq + i, eic); |
172 | } | 228 | } |
173 | 229 | ||
174 | int_irq = platform_get_irq_byname(sm->pdev, "eim"); | 230 | set_irq_chained_handler(int_irq, demux_eic_irq); |
175 | 231 | set_irq_data(int_irq, eic); | |
176 | set_irq_chained_handler(int_irq, demux_eim_irq); | ||
177 | set_irq_data(int_irq, sm); | ||
178 | 232 | ||
179 | printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n", | 233 | dev_info(&pdev->dev, |
180 | sm->regs, int_irq); | 234 | "External Interrupt Controller at 0x%p, IRQ %u\n", |
181 | printk("EIM: Handling %u external IRQs, starting with IRQ %u\n", | 235 | eic->regs, int_irq); |
182 | nr_irqs, sm->eim_first_irq); | 236 | dev_info(&pdev->dev, |
237 | "Handling %u external IRQs, starting with IRQ %u\n", | ||
238 | nr_irqs, eic->first_irq); | ||
183 | 239 | ||
184 | return 0; | 240 | return 0; |
241 | |||
242 | err_ioremap: | ||
243 | kfree(eic); | ||
244 | err_kzalloc: | ||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static struct platform_driver eic_driver = { | ||
249 | .driver = { | ||
250 | .name = "at32_eic", | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static int __init eic_init(void) | ||
255 | { | ||
256 | return platform_driver_probe(&eic_driver, eic_probe); | ||
185 | } | 257 | } |
186 | arch_initcall(eim_init); | 258 | arch_initcall(eic_init); |
diff --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h new file mode 100644 index 000000000000..a1f8aced0a8c --- /dev/null +++ b/arch/avr32/mach-at32ap/pm.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Register definitions for the Power Manager (PM) | ||
3 | */ | ||
4 | #ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__ | ||
5 | #define __ARCH_AVR32_MACH_AT32AP_PM_H__ | ||
6 | |||
7 | /* PM register offsets */ | ||
8 | #define PM_MCCTRL 0x0000 | ||
9 | #define PM_CKSEL 0x0004 | ||
10 | #define PM_CPU_MASK 0x0008 | ||
11 | #define PM_HSB_MASK 0x000c | ||
12 | #define PM_PBA_MASK 0x0010 | ||
13 | #define PM_PBB_MASK 0x0014 | ||
14 | #define PM_PLL0 0x0020 | ||
15 | #define PM_PLL1 0x0024 | ||
16 | #define PM_IER 0x0040 | ||
17 | #define PM_IDR 0x0044 | ||
18 | #define PM_IMR 0x0048 | ||
19 | #define PM_ISR 0x004c | ||
20 | #define PM_ICR 0x0050 | ||
21 | #define PM_GCCTRL(x) (0x0060 + 4 * (x)) | ||
22 | #define PM_RCAUSE 0x00c0 | ||
23 | |||
24 | /* Bitfields in CKSEL */ | ||
25 | #define PM_CPUSEL_OFFSET 0 | ||
26 | #define PM_CPUSEL_SIZE 3 | ||
27 | #define PM_CPUDIV_OFFSET 7 | ||
28 | #define PM_CPUDIV_SIZE 1 | ||
29 | #define PM_HSBSEL_OFFSET 8 | ||
30 | #define PM_HSBSEL_SIZE 3 | ||
31 | #define PM_HSBDIV_OFFSET 15 | ||
32 | #define PM_HSBDIV_SIZE 1 | ||
33 | #define PM_PBASEL_OFFSET 16 | ||
34 | #define PM_PBASEL_SIZE 3 | ||
35 | #define PM_PBADIV_OFFSET 23 | ||
36 | #define PM_PBADIV_SIZE 1 | ||
37 | #define PM_PBBSEL_OFFSET 24 | ||
38 | #define PM_PBBSEL_SIZE 3 | ||
39 | #define PM_PBBDIV_OFFSET 31 | ||
40 | #define PM_PBBDIV_SIZE 1 | ||
41 | |||
42 | /* Bitfields in PLL0 */ | ||
43 | #define PM_PLLEN_OFFSET 0 | ||
44 | #define PM_PLLEN_SIZE 1 | ||
45 | #define PM_PLLOSC_OFFSET 1 | ||
46 | #define PM_PLLOSC_SIZE 1 | ||
47 | #define PM_PLLOPT_OFFSET 2 | ||
48 | #define PM_PLLOPT_SIZE 3 | ||
49 | #define PM_PLLDIV_OFFSET 8 | ||
50 | #define PM_PLLDIV_SIZE 8 | ||
51 | #define PM_PLLMUL_OFFSET 16 | ||
52 | #define PM_PLLMUL_SIZE 8 | ||
53 | #define PM_PLLCOUNT_OFFSET 24 | ||
54 | #define PM_PLLCOUNT_SIZE 6 | ||
55 | #define PM_PLLTEST_OFFSET 31 | ||
56 | #define PM_PLLTEST_SIZE 1 | ||
57 | |||
58 | /* Bitfields in ICR */ | ||
59 | #define PM_LOCK0_OFFSET 0 | ||
60 | #define PM_LOCK0_SIZE 1 | ||
61 | #define PM_LOCK1_OFFSET 1 | ||
62 | #define PM_LOCK1_SIZE 1 | ||
63 | #define PM_WAKE_OFFSET 2 | ||
64 | #define PM_WAKE_SIZE 1 | ||
65 | #define PM_CKRDY_OFFSET 5 | ||
66 | #define PM_CKRDY_SIZE 1 | ||
67 | #define PM_MSKRDY_OFFSET 6 | ||
68 | #define PM_MSKRDY_SIZE 1 | ||
69 | |||
70 | /* Bitfields in GCCTRL0 */ | ||
71 | #define PM_OSCSEL_OFFSET 0 | ||
72 | #define PM_OSCSEL_SIZE 1 | ||
73 | #define PM_PLLSEL_OFFSET 1 | ||
74 | #define PM_PLLSEL_SIZE 1 | ||
75 | #define PM_CEN_OFFSET 2 | ||
76 | #define PM_CEN_SIZE 1 | ||
77 | #define PM_DIVEN_OFFSET 4 | ||
78 | #define PM_DIVEN_SIZE 1 | ||
79 | #define PM_DIV_OFFSET 8 | ||
80 | #define PM_DIV_SIZE 8 | ||
81 | |||
82 | /* Bitfields in RCAUSE */ | ||
83 | #define PM_POR_OFFSET 0 | ||
84 | #define PM_POR_SIZE 1 | ||
85 | #define PM_EXT_OFFSET 2 | ||
86 | #define PM_EXT_SIZE 1 | ||
87 | #define PM_WDT_OFFSET 3 | ||
88 | #define PM_WDT_SIZE 1 | ||
89 | #define PM_NTAE_OFFSET 4 | ||
90 | #define PM_NTAE_SIZE 1 | ||
91 | |||
92 | /* Bit manipulation macros */ | ||
93 | #define PM_BIT(name) \ | ||
94 | (1 << PM_##name##_OFFSET) | ||
95 | #define PM_BF(name,value) \ | ||
96 | (((value) & ((1 << PM_##name##_SIZE) - 1)) \ | ||
97 | << PM_##name##_OFFSET) | ||
98 | #define PM_BFEXT(name,value) \ | ||
99 | (((value) >> PM_##name##_OFFSET) \ | ||
100 | & ((1 << PM_##name##_SIZE) - 1)) | ||
101 | #define PM_BFINS(name,value,old)\ | ||
102 | (((old) & ~(((1 << PM_##name##_SIZE) - 1) \ | ||
103 | << PM_##name##_OFFSET)) \ | ||
104 | | PM_BF(name,value)) | ||
105 | |||
106 | /* Register access macros */ | ||
107 | #define pm_readl(reg) \ | ||
108 | __raw_readl((void __iomem *)AT32_PM_BASE + PM_##reg) | ||
109 | #define pm_writel(reg,value) \ | ||
110 | __raw_writel((value), (void __iomem *)AT32_PM_BASE + PM_##reg) | ||
111 | |||
112 | #endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */ | ||
diff --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h deleted file mode 100644 index cad02b512bcb..000000000000 --- a/arch/avr32/mach-at32ap/sm.h +++ /dev/null | |||
@@ -1,242 +0,0 @@ | |||
1 | /* | ||
2 | * Register definitions for SM | ||
3 | * | ||
4 | * System Manager | ||
5 | */ | ||
6 | #ifndef __ASM_AVR32_SM_H__ | ||
7 | #define __ASM_AVR32_SM_H__ | ||
8 | |||
9 | /* SM register offsets */ | ||
10 | #define SM_PM_MCCTRL 0x0000 | ||
11 | #define SM_PM_CKSEL 0x0004 | ||
12 | #define SM_PM_CPU_MASK 0x0008 | ||
13 | #define SM_PM_HSB_MASK 0x000c | ||
14 | #define SM_PM_PBA_MASK 0x0010 | ||
15 | #define SM_PM_PBB_MASK 0x0014 | ||
16 | #define SM_PM_PLL0 0x0020 | ||
17 | #define SM_PM_PLL1 0x0024 | ||
18 | #define SM_PM_VCTRL 0x0030 | ||
19 | #define SM_PM_VMREF 0x0034 | ||
20 | #define SM_PM_VMV 0x0038 | ||
21 | #define SM_PM_IER 0x0040 | ||
22 | #define SM_PM_IDR 0x0044 | ||
23 | #define SM_PM_IMR 0x0048 | ||
24 | #define SM_PM_ISR 0x004c | ||
25 | #define SM_PM_ICR 0x0050 | ||
26 | #define SM_PM_GCCTRL 0x0060 | ||
27 | #define SM_RTC_CTRL 0x0080 | ||
28 | #define SM_RTC_VAL 0x0084 | ||
29 | #define SM_RTC_TOP 0x0088 | ||
30 | #define SM_RTC_IER 0x0090 | ||
31 | #define SM_RTC_IDR 0x0094 | ||
32 | #define SM_RTC_IMR 0x0098 | ||
33 | #define SM_RTC_ISR 0x009c | ||
34 | #define SM_RTC_ICR 0x00a0 | ||
35 | #define SM_WDT_CTRL 0x00b0 | ||
36 | #define SM_WDT_CLR 0x00b4 | ||
37 | #define SM_WDT_EXT 0x00b8 | ||
38 | #define SM_RC_RCAUSE 0x00c0 | ||
39 | #define SM_EIM_IER 0x0100 | ||
40 | #define SM_EIM_IDR 0x0104 | ||
41 | #define SM_EIM_IMR 0x0108 | ||
42 | #define SM_EIM_ISR 0x010c | ||
43 | #define SM_EIM_ICR 0x0110 | ||
44 | #define SM_EIM_MODE 0x0114 | ||
45 | #define SM_EIM_EDGE 0x0118 | ||
46 | #define SM_EIM_LEVEL 0x011c | ||
47 | #define SM_EIM_TEST 0x0120 | ||
48 | #define SM_EIM_NMIC 0x0124 | ||
49 | |||
50 | /* Bitfields in PM_MCCTRL */ | ||
51 | |||
52 | /* Bitfields in PM_CKSEL */ | ||
53 | #define SM_CPUSEL_OFFSET 0 | ||
54 | #define SM_CPUSEL_SIZE 3 | ||
55 | #define SM_CPUDIV_OFFSET 7 | ||
56 | #define SM_CPUDIV_SIZE 1 | ||
57 | #define SM_HSBSEL_OFFSET 8 | ||
58 | #define SM_HSBSEL_SIZE 3 | ||
59 | #define SM_HSBDIV_OFFSET 15 | ||
60 | #define SM_HSBDIV_SIZE 1 | ||
61 | #define SM_PBASEL_OFFSET 16 | ||
62 | #define SM_PBASEL_SIZE 3 | ||
63 | #define SM_PBADIV_OFFSET 23 | ||
64 | #define SM_PBADIV_SIZE 1 | ||
65 | #define SM_PBBSEL_OFFSET 24 | ||
66 | #define SM_PBBSEL_SIZE 3 | ||
67 | #define SM_PBBDIV_OFFSET 31 | ||
68 | #define SM_PBBDIV_SIZE 1 | ||
69 | |||
70 | /* Bitfields in PM_CPU_MASK */ | ||
71 | |||
72 | /* Bitfields in PM_HSB_MASK */ | ||
73 | |||
74 | /* Bitfields in PM_PBA_MASK */ | ||
75 | |||
76 | /* Bitfields in PM_PBB_MASK */ | ||
77 | |||
78 | /* Bitfields in PM_PLL0 */ | ||
79 | #define SM_PLLEN_OFFSET 0 | ||
80 | #define SM_PLLEN_SIZE 1 | ||
81 | #define SM_PLLOSC_OFFSET 1 | ||
82 | #define SM_PLLOSC_SIZE 1 | ||
83 | #define SM_PLLOPT_OFFSET 2 | ||
84 | #define SM_PLLOPT_SIZE 3 | ||
85 | #define SM_PLLDIV_OFFSET 8 | ||
86 | #define SM_PLLDIV_SIZE 8 | ||
87 | #define SM_PLLMUL_OFFSET 16 | ||
88 | #define SM_PLLMUL_SIZE 8 | ||
89 | #define SM_PLLCOUNT_OFFSET 24 | ||
90 | #define SM_PLLCOUNT_SIZE 6 | ||
91 | #define SM_PLLTEST_OFFSET 31 | ||
92 | #define SM_PLLTEST_SIZE 1 | ||
93 | |||
94 | /* Bitfields in PM_PLL1 */ | ||
95 | |||
96 | /* Bitfields in PM_VCTRL */ | ||
97 | #define SM_VAUTO_OFFSET 0 | ||
98 | #define SM_VAUTO_SIZE 1 | ||
99 | #define SM_PM_VCTRL_VAL_OFFSET 8 | ||
100 | #define SM_PM_VCTRL_VAL_SIZE 7 | ||
101 | |||
102 | /* Bitfields in PM_VMREF */ | ||
103 | #define SM_REFSEL_OFFSET 0 | ||
104 | #define SM_REFSEL_SIZE 4 | ||
105 | |||
106 | /* Bitfields in PM_VMV */ | ||
107 | #define SM_PM_VMV_VAL_OFFSET 0 | ||
108 | #define SM_PM_VMV_VAL_SIZE 8 | ||
109 | |||
110 | /* Bitfields in PM_IER */ | ||
111 | |||
112 | /* Bitfields in PM_IDR */ | ||
113 | |||
114 | /* Bitfields in PM_IMR */ | ||
115 | |||
116 | /* Bitfields in PM_ISR */ | ||
117 | |||
118 | /* Bitfields in PM_ICR */ | ||
119 | #define SM_LOCK0_OFFSET 0 | ||
120 | #define SM_LOCK0_SIZE 1 | ||
121 | #define SM_LOCK1_OFFSET 1 | ||
122 | #define SM_LOCK1_SIZE 1 | ||
123 | #define SM_WAKE_OFFSET 2 | ||
124 | #define SM_WAKE_SIZE 1 | ||
125 | #define SM_VOK_OFFSET 3 | ||
126 | #define SM_VOK_SIZE 1 | ||
127 | #define SM_VMRDY_OFFSET 4 | ||
128 | #define SM_VMRDY_SIZE 1 | ||
129 | #define SM_CKRDY_OFFSET 5 | ||
130 | #define SM_CKRDY_SIZE 1 | ||
131 | |||
132 | /* Bitfields in PM_GCCTRL */ | ||
133 | #define SM_OSCSEL_OFFSET 0 | ||
134 | #define SM_OSCSEL_SIZE 1 | ||
135 | #define SM_PLLSEL_OFFSET 1 | ||
136 | #define SM_PLLSEL_SIZE 1 | ||
137 | #define SM_CEN_OFFSET 2 | ||
138 | #define SM_CEN_SIZE 1 | ||
139 | #define SM_CPC_OFFSET 3 | ||
140 | #define SM_CPC_SIZE 1 | ||
141 | #define SM_DIVEN_OFFSET 4 | ||
142 | #define SM_DIVEN_SIZE 1 | ||
143 | #define SM_DIV_OFFSET 8 | ||
144 | #define SM_DIV_SIZE 8 | ||
145 | |||
146 | /* Bitfields in RTC_CTRL */ | ||
147 | #define SM_PCLR_OFFSET 1 | ||
148 | #define SM_PCLR_SIZE 1 | ||
149 | #define SM_TOPEN_OFFSET 2 | ||
150 | #define SM_TOPEN_SIZE 1 | ||
151 | #define SM_CLKEN_OFFSET 3 | ||
152 | #define SM_CLKEN_SIZE 1 | ||
153 | #define SM_PSEL_OFFSET 8 | ||
154 | #define SM_PSEL_SIZE 16 | ||
155 | |||
156 | /* Bitfields in RTC_VAL */ | ||
157 | #define SM_RTC_VAL_VAL_OFFSET 0 | ||
158 | #define SM_RTC_VAL_VAL_SIZE 31 | ||
159 | |||
160 | /* Bitfields in RTC_TOP */ | ||
161 | #define SM_RTC_TOP_VAL_OFFSET 0 | ||
162 | #define SM_RTC_TOP_VAL_SIZE 32 | ||
163 | |||
164 | /* Bitfields in RTC_IER */ | ||
165 | |||
166 | /* Bitfields in RTC_IDR */ | ||
167 | |||
168 | /* Bitfields in RTC_IMR */ | ||
169 | |||
170 | /* Bitfields in RTC_ISR */ | ||
171 | |||
172 | /* Bitfields in RTC_ICR */ | ||
173 | #define SM_TOPI_OFFSET 0 | ||
174 | #define SM_TOPI_SIZE 1 | ||
175 | |||
176 | /* Bitfields in WDT_CTRL */ | ||
177 | #define SM_KEY_OFFSET 24 | ||
178 | #define SM_KEY_SIZE 8 | ||
179 | |||
180 | /* Bitfields in WDT_CLR */ | ||
181 | |||
182 | /* Bitfields in WDT_EXT */ | ||
183 | |||
184 | /* Bitfields in RC_RCAUSE */ | ||
185 | #define SM_POR_OFFSET 0 | ||
186 | #define SM_POR_SIZE 1 | ||
187 | #define SM_BOD_OFFSET 1 | ||
188 | #define SM_BOD_SIZE 1 | ||
189 | #define SM_EXT_OFFSET 2 | ||
190 | #define SM_EXT_SIZE 1 | ||
191 | #define SM_WDT_OFFSET 3 | ||
192 | #define SM_WDT_SIZE 1 | ||
193 | #define SM_NTAE_OFFSET 4 | ||
194 | #define SM_NTAE_SIZE 1 | ||
195 | #define SM_SERP_OFFSET 5 | ||
196 | #define SM_SERP_SIZE 1 | ||
197 | |||
198 | /* Bitfields in EIM_IER */ | ||
199 | |||
200 | /* Bitfields in EIM_IDR */ | ||
201 | |||
202 | /* Bitfields in EIM_IMR */ | ||
203 | |||
204 | /* Bitfields in EIM_ISR */ | ||
205 | |||
206 | /* Bitfields in EIM_ICR */ | ||
207 | |||
208 | /* Bitfields in EIM_MODE */ | ||
209 | |||
210 | /* Bitfields in EIM_EDGE */ | ||
211 | #define SM_INT0_OFFSET 0 | ||
212 | #define SM_INT0_SIZE 1 | ||
213 | #define SM_INT1_OFFSET 1 | ||
214 | #define SM_INT1_SIZE 1 | ||
215 | #define SM_INT2_OFFSET 2 | ||
216 | #define SM_INT2_SIZE 1 | ||
217 | #define SM_INT3_OFFSET 3 | ||
218 | #define SM_INT3_SIZE 1 | ||
219 | |||
220 | /* Bitfields in EIM_LEVEL */ | ||
221 | |||
222 | /* Bitfields in EIM_TEST */ | ||
223 | #define SM_TESTEN_OFFSET 31 | ||
224 | #define SM_TESTEN_SIZE 1 | ||
225 | |||
226 | /* Bitfields in EIM_NMIC */ | ||
227 | #define SM_EN_OFFSET 0 | ||
228 | #define SM_EN_SIZE 1 | ||
229 | |||
230 | /* Bit manipulation macros */ | ||
231 | #define SM_BIT(name) (1 << SM_##name##_OFFSET) | ||
232 | #define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET) | ||
233 | #define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1)) | ||
234 | #define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value)) | ||
235 | |||
236 | /* Register access macros */ | ||
237 | #define sm_readl(port,reg) \ | ||
238 | __raw_readl((port)->regs + SM_##reg) | ||
239 | #define sm_writel(port,reg,value) \ | ||
240 | __raw_writel((value), (port)->regs + SM_##reg) | ||
241 | |||
242 | #endif /* __ASM_AVR32_SM_H__ */ | ||
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index 4b2495285d94..ae2d2c593b2b 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c | |||
@@ -64,6 +64,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs) | |||
64 | int writeaccess; | 64 | int writeaccess; |
65 | long signr; | 65 | long signr; |
66 | int code; | 66 | int code; |
67 | int fault; | ||
67 | 68 | ||
68 | if (notify_page_fault(regs, ecr)) | 69 | if (notify_page_fault(regs, ecr)) |
69 | return; | 70 | return; |
@@ -132,20 +133,18 @@ good_area: | |||
132 | * fault. | 133 | * fault. |
133 | */ | 134 | */ |
134 | survive: | 135 | survive: |
135 | switch (handle_mm_fault(mm, vma, address, writeaccess)) { | 136 | fault = handle_mm_fault(mm, vma, address, writeaccess); |
136 | case VM_FAULT_MINOR: | 137 | if (unlikely(fault & VM_FAULT_ERROR)) { |
137 | tsk->min_flt++; | 138 | if (fault & VM_FAULT_OOM) |
138 | break; | 139 | goto out_of_memory; |
139 | case VM_FAULT_MAJOR: | 140 | else if (fault & VM_FAULT_SIGBUS) |
140 | tsk->maj_flt++; | 141 | goto do_sigbus; |
141 | break; | ||
142 | case VM_FAULT_SIGBUS: | ||
143 | goto do_sigbus; | ||
144 | case VM_FAULT_OOM: | ||
145 | goto out_of_memory; | ||
146 | default: | ||
147 | BUG(); | 142 | BUG(); |
148 | } | 143 | } |
144 | if (fault & VM_FAULT_MAJOR) | ||
145 | tsk->maj_flt++; | ||
146 | else | ||
147 | tsk->min_flt++; | ||
149 | 148 | ||
150 | up_read(&mm->mmap_sem); | 149 | up_read(&mm->mmap_sem); |
151 | return; | 150 | return; |
diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c index 16c6169ed01b..b99ea883cd22 100644 --- a/arch/blackfin/mm/blackfin_sram.c +++ b/arch/blackfin/mm/blackfin_sram.c | |||
@@ -521,10 +521,9 @@ void *sram_alloc_with_lsl(size_t size, unsigned long flags) | |||
521 | struct sram_list_struct *lsl = NULL; | 521 | struct sram_list_struct *lsl = NULL; |
522 | struct mm_struct *mm = current->mm; | 522 | struct mm_struct *mm = current->mm; |
523 | 523 | ||
524 | lsl = kmalloc(sizeof(struct sram_list_struct), GFP_KERNEL); | 524 | lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL); |
525 | if (!lsl) | 525 | if (!lsl) |
526 | return NULL; | 526 | return NULL; |
527 | memset(lsl, 0, sizeof(*lsl)); | ||
528 | 527 | ||
529 | if (flags & L1_INST_SRAM) | 528 | if (flags & L1_INST_SRAM) |
530 | addr = l1_inst_sram_alloc(size); | 529 | addr = l1_inst_sram_alloc(size); |
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index d47cfbf98d6e..1de0026bb94e 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c | |||
@@ -180,9 +180,7 @@ err: | |||
180 | void __exit | 180 | void __exit |
181 | pcf8563_exit(void) | 181 | pcf8563_exit(void) |
182 | { | 182 | { |
183 | if (unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME) < 0) { | 183 | unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME); |
184 | printk(KERN_INFO "%s: Unable to unregister device.\n", PCF8563_NAME); | ||
185 | } | ||
186 | } | 184 | } |
187 | 185 | ||
188 | /* | 186 | /* |
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index fd2129a04586..f4f9db698b44 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c | |||
@@ -83,19 +83,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
83 | switch (request) { | 83 | switch (request) { |
84 | /* Read word at location address. */ | 84 | /* Read word at location address. */ |
85 | case PTRACE_PEEKTEXT: | 85 | case PTRACE_PEEKTEXT: |
86 | case PTRACE_PEEKDATA: { | 86 | case PTRACE_PEEKDATA: |
87 | unsigned long tmp; | 87 | ret = generic_ptrace_peekdata(child, addr, data); |
88 | int copied; | ||
89 | |||
90 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
91 | ret = -EIO; | ||
92 | |||
93 | if (copied != sizeof(tmp)) | ||
94 | break; | ||
95 | |||
96 | ret = put_user(tmp,datap); | ||
97 | break; | 88 | break; |
98 | } | ||
99 | 89 | ||
100 | /* Read the word at location address in the USER area. */ | 90 | /* Read the word at location address in the USER area. */ |
101 | case PTRACE_PEEKUSR: { | 91 | case PTRACE_PEEKUSR: { |
@@ -113,12 +103,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
113 | /* Write the word at location address. */ | 103 | /* Write the word at location address. */ |
114 | case PTRACE_POKETEXT: | 104 | case PTRACE_POKETEXT: |
115 | case PTRACE_POKEDATA: | 105 | case PTRACE_POKEDATA: |
116 | ret = 0; | 106 | ret = generic_ptrace_pokedata(child, addr, data); |
117 | |||
118 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
119 | break; | ||
120 | |||
121 | ret = -EIO; | ||
122 | break; | 107 | break; |
123 | 108 | ||
124 | /* Write the word at location address in the USER area. */ | 109 | /* Write the word at location address in the USER area. */ |
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c index fa8d50007e4c..da479a14f836 100644 --- a/arch/cris/arch-v32/drivers/pcf8563.c +++ b/arch/cris/arch-v32/drivers/pcf8563.c | |||
@@ -193,9 +193,7 @@ err: | |||
193 | void __exit | 193 | void __exit |
194 | pcf8563_exit(void) | 194 | pcf8563_exit(void) |
195 | { | 195 | { |
196 | if (unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME) < 0) { | 196 | unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME); |
197 | printk(KERN_INFO "%s: Unable to unregister device.\n", PCF8563_NAME); | ||
198 | } | ||
199 | } | 197 | } |
200 | 198 | ||
201 | /* | 199 | /* |
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c index 832fc63504d4..66f9500fbc02 100644 --- a/arch/cris/arch-v32/drivers/pci/dma.c +++ b/arch/cris/arch-v32/drivers/pci/dma.c | |||
@@ -91,14 +91,12 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, | |||
91 | if (!mem_base) | 91 | if (!mem_base) |
92 | goto out; | 92 | goto out; |
93 | 93 | ||
94 | dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); | 94 | dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); |
95 | if (!dev->dma_mem) | 95 | if (!dev->dma_mem) |
96 | goto out; | 96 | goto out; |
97 | memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem)); | 97 | dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); |
98 | dev->dma_mem->bitmap = kmalloc(bitmap_size, GFP_KERNEL); | ||
99 | if (!dev->dma_mem->bitmap) | 98 | if (!dev->dma_mem->bitmap) |
100 | goto free1_out; | 99 | goto free1_out; |
101 | memset(dev->dma_mem->bitmap, 0, bitmap_size); | ||
102 | 100 | ||
103 | dev->dma_mem->virt_base = mem_base; | 101 | dev->dma_mem->virt_base = mem_base; |
104 | dev->dma_mem->device_base = device_addr; | 102 | dev->dma_mem->device_base = device_addr; |
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index d4d57b741334..38ece0cd47cb 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c | |||
@@ -146,12 +146,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
146 | /* Write the word at location address. */ | 146 | /* Write the word at location address. */ |
147 | case PTRACE_POKETEXT: | 147 | case PTRACE_POKETEXT: |
148 | case PTRACE_POKEDATA: | 148 | case PTRACE_POKEDATA: |
149 | ret = 0; | 149 | ret = generic_ptrace_pokedata(child, addr, data); |
150 | |||
151 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
152 | break; | ||
153 | |||
154 | ret = -EIO; | ||
155 | break; | 150 | break; |
156 | 151 | ||
157 | /* Write the word at location address in the USER area. */ | 152 | /* Write the word at location address in the USER area. */ |
diff --git a/arch/cris/arch-v32/vmlinux.lds.S b/arch/cris/arch-v32/vmlinux.lds.S index e3a32ac17ab2..b076c134c0bb 100644 --- a/arch/cris/arch-v32/vmlinux.lds.S +++ b/arch/cris/arch-v32/vmlinux.lds.S | |||
@@ -91,10 +91,7 @@ SECTIONS | |||
91 | } | 91 | } |
92 | SECURITY_INIT | 92 | SECURITY_INIT |
93 | 93 | ||
94 | . = ALIGN (8192); | 94 | PERCPU(8192) |
95 | __per_cpu_start = .; | ||
96 | .data.percpu : { *(.data.percpu) } | ||
97 | __per_cpu_end = .; | ||
98 | 95 | ||
99 | #ifdef CONFIG_BLK_DEV_INITRD | 96 | #ifdef CONFIG_BLK_DEV_INITRD |
100 | .init.ramfs : { | 97 | .init.ramfs : { |
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index c73e91f1299a..8672ab7d7978 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c | |||
@@ -179,6 +179,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
179 | struct mm_struct *mm; | 179 | struct mm_struct *mm; |
180 | struct vm_area_struct * vma; | 180 | struct vm_area_struct * vma; |
181 | siginfo_t info; | 181 | siginfo_t info; |
182 | int fault; | ||
182 | 183 | ||
183 | D(printk("Page fault for %lX on %X at %lX, prot %d write %d\n", | 184 | D(printk("Page fault for %lX on %X at %lX, prot %d write %d\n", |
184 | address, smp_processor_id(), instruction_pointer(regs), | 185 | address, smp_processor_id(), instruction_pointer(regs), |
@@ -283,18 +284,18 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
283 | * the fault. | 284 | * the fault. |
284 | */ | 285 | */ |
285 | 286 | ||
286 | switch (handle_mm_fault(mm, vma, address, writeaccess & 1)) { | 287 | fault = handle_mm_fault(mm, vma, address, writeaccess & 1); |
287 | case VM_FAULT_MINOR: | 288 | if (unlikely(fault & VM_FAULT_ERROR)) { |
288 | tsk->min_flt++; | 289 | if (fault & VM_FAULT_OOM) |
289 | break; | 290 | goto out_of_memory; |
290 | case VM_FAULT_MAJOR: | 291 | else if (fault & VM_FAULT_SIGBUS) |
291 | tsk->maj_flt++; | 292 | goto do_sigbus; |
292 | break; | 293 | BUG(); |
293 | case VM_FAULT_SIGBUS: | ||
294 | goto do_sigbus; | ||
295 | default: | ||
296 | goto out_of_memory; | ||
297 | } | 294 | } |
295 | if (fault & VM_FAULT_MAJOR) | ||
296 | tsk->maj_flt++; | ||
297 | else | ||
298 | tsk->min_flt++; | ||
298 | 299 | ||
299 | up_read(&mm->mmap_sem); | 300 | up_read(&mm->mmap_sem); |
300 | return; | 301 | return; |
diff --git a/arch/frv/Makefile b/arch/frv/Makefile index 038e3a8457e0..9bf7345c5cc9 100644 --- a/arch/frv/Makefile +++ b/arch/frv/Makefile | |||
@@ -88,7 +88,7 @@ ASFLAGS += -mno-fdpic | |||
88 | # make sure the .S files get compiled with debug info | 88 | # make sure the .S files get compiled with debug info |
89 | # and disable optimisations that are unhelpful whilst debugging | 89 | # and disable optimisations that are unhelpful whilst debugging |
90 | ifdef CONFIG_DEBUG_INFO | 90 | ifdef CONFIG_DEBUG_INFO |
91 | CFLAGS += -O1 | 91 | #CFLAGS += -O1 |
92 | AFLAGS += -Wa,--gdwarf2 | 92 | AFLAGS += -Wa,--gdwarf2 |
93 | ASFLAGS += -Wa,--gdwarf2 | 93 | ASFLAGS += -Wa,--gdwarf2 |
94 | endif | 94 | endif |
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index ce88fb95ee59..709e9bdc6126 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c | |||
@@ -112,20 +112,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
112 | switch (request) { | 112 | switch (request) { |
113 | /* when I and D space are separate, these will need to be fixed. */ | 113 | /* when I and D space are separate, these will need to be fixed. */ |
114 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 114 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
115 | case PTRACE_PEEKDATA: { | 115 | case PTRACE_PEEKDATA: |
116 | int copied; | ||
117 | |||
118 | ret = -EIO; | 116 | ret = -EIO; |
119 | if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) | 117 | if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) |
120 | break; | 118 | break; |
121 | 119 | ret = generic_ptrace_peekdata(child, addr, data); | |
122 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
123 | if (copied != sizeof(tmp)) | ||
124 | break; | ||
125 | |||
126 | ret = put_user(tmp,(unsigned long *) data); | ||
127 | break; | 120 | break; |
128 | } | ||
129 | 121 | ||
130 | /* read the word at location addr in the USER area. */ | 122 | /* read the word at location addr in the USER area. */ |
131 | case PTRACE_PEEKUSR: { | 123 | case PTRACE_PEEKUSR: { |
@@ -176,9 +168,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
176 | ret = -EIO; | 168 | ret = -EIO; |
177 | if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) | 169 | if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) |
178 | break; | 170 | break; |
179 | if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data)) | 171 | ret = generic_ptrace_pokedata(child, addr, data); |
180 | break; | ||
181 | ret = 0; | ||
182 | break; | 172 | break; |
183 | 173 | ||
184 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 174 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index c1c32e4c863d..a74c08786b21 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/serial.h> | 29 | #include <linux/serial.h> |
30 | #include <linux/serial_core.h> | 30 | #include <linux/serial_core.h> |
31 | #include <linux/serial_reg.h> | 31 | #include <linux/serial_reg.h> |
32 | #include <linux/serial_8250.h> | ||
32 | 33 | ||
33 | #include <asm/setup.h> | 34 | #include <asm/setup.h> |
34 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index 481dc1374640..3b71e0c86399 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S | |||
@@ -57,10 +57,7 @@ SECTIONS | |||
57 | __alt_instructions_end = .; | 57 | __alt_instructions_end = .; |
58 | .altinstr_replacement : { *(.altinstr_replacement) } | 58 | .altinstr_replacement : { *(.altinstr_replacement) } |
59 | 59 | ||
60 | . = ALIGN(4096); | 60 | PERCPU(4096) |
61 | __per_cpu_start = .; | ||
62 | .data.percpu : { *(.data.percpu) } | ||
63 | __per_cpu_end = .; | ||
64 | 61 | ||
65 | #ifdef CONFIG_BLK_DEV_INITRD | 62 | #ifdef CONFIG_BLK_DEV_INITRD |
66 | . = ALIGN(4096); | 63 | . = ALIGN(4096); |
diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c index 3f12296c3688..6798fa0257b1 100644 --- a/arch/frv/mm/fault.c +++ b/arch/frv/mm/fault.c | |||
@@ -40,6 +40,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear | |||
40 | pud_t *pue; | 40 | pud_t *pue; |
41 | pte_t *pte; | 41 | pte_t *pte; |
42 | int write; | 42 | int write; |
43 | int fault; | ||
43 | 44 | ||
44 | #if 0 | 45 | #if 0 |
45 | const char *atxc[16] = { | 46 | const char *atxc[16] = { |
@@ -162,18 +163,18 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear | |||
162 | * make sure we exit gracefully rather than endlessly redo | 163 | * make sure we exit gracefully rather than endlessly redo |
163 | * the fault. | 164 | * the fault. |
164 | */ | 165 | */ |
165 | switch (handle_mm_fault(mm, vma, ear0, write)) { | 166 | fault = handle_mm_fault(mm, vma, ear0, write); |
166 | case VM_FAULT_MINOR: | 167 | if (unlikely(fault & VM_FAULT_ERROR)) { |
167 | current->min_flt++; | 168 | if (fault & VM_FAULT_OOM) |
168 | break; | 169 | goto out_of_memory; |
169 | case VM_FAULT_MAJOR: | 170 | else if (fault & VM_FAULT_SIGBUS) |
170 | current->maj_flt++; | 171 | goto do_sigbus; |
171 | break; | 172 | BUG(); |
172 | case VM_FAULT_SIGBUS: | ||
173 | goto do_sigbus; | ||
174 | default: | ||
175 | goto out_of_memory; | ||
176 | } | 173 | } |
174 | if (fault & VM_FAULT_MAJOR) | ||
175 | current->maj_flt++; | ||
176 | else | ||
177 | current->min_flt++; | ||
177 | 178 | ||
178 | up_read(&mm->mmap_sem); | 179 | up_read(&mm->mmap_sem); |
179 | return; | 180 | return; |
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index 8a7a991b8f76..d32bbf02fc48 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c | |||
@@ -111,10 +111,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
111 | /* when I and D space are separate, this will have to be fixed. */ | 111 | /* when I and D space are separate, this will have to be fixed. */ |
112 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 112 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
113 | case PTRACE_POKEDATA: | 113 | case PTRACE_POKEDATA: |
114 | ret = 0; | 114 | ret = generic_ptrace_pokedata(child, addr, data); |
115 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
116 | break; | ||
117 | ret = -EIO; | ||
118 | break; | 115 | break; |
119 | 116 | ||
120 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 117 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 8531a540ca8c..7a11b905ef49 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -222,6 +222,8 @@ config PARAVIRT | |||
222 | However, when run without a hypervisor the kernel is | 222 | However, when run without a hypervisor the kernel is |
223 | theoretically slower. If in doubt, say N. | 223 | theoretically slower. If in doubt, say N. |
224 | 224 | ||
225 | source "arch/i386/xen/Kconfig" | ||
226 | |||
225 | config VMI | 227 | config VMI |
226 | bool "VMI Paravirt-ops support" | 228 | bool "VMI Paravirt-ops support" |
227 | depends on PARAVIRT | 229 | depends on PARAVIRT |
@@ -1222,8 +1224,8 @@ if INSTRUMENTATION | |||
1222 | source "arch/i386/oprofile/Kconfig" | 1224 | source "arch/i386/oprofile/Kconfig" |
1223 | 1225 | ||
1224 | config KPROBES | 1226 | config KPROBES |
1225 | bool "Kprobes (EXPERIMENTAL)" | 1227 | bool "Kprobes" |
1226 | depends on KALLSYMS && EXPERIMENTAL && MODULES | 1228 | depends on KALLSYMS && MODULES |
1227 | help | 1229 | help |
1228 | Kprobes allows you to trap at almost any kernel address and | 1230 | Kprobes allows you to trap at almost any kernel address and |
1229 | execute a callback function. register_kprobe() establishes | 1231 | execute a callback function. register_kprobe() establishes |
diff --git a/arch/i386/Makefile b/arch/i386/Makefile index bd28f9f9b4b7..01f0ff0daaf4 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile | |||
@@ -93,6 +93,9 @@ mflags-$(CONFIG_X86_ES7000) := -Iinclude/asm-i386/mach-es7000 | |||
93 | mcore-$(CONFIG_X86_ES7000) := mach-default | 93 | mcore-$(CONFIG_X86_ES7000) := mach-default |
94 | core-$(CONFIG_X86_ES7000) := arch/i386/mach-es7000/ | 94 | core-$(CONFIG_X86_ES7000) := arch/i386/mach-es7000/ |
95 | 95 | ||
96 | # Xen paravirtualization support | ||
97 | core-$(CONFIG_XEN) += arch/i386/xen/ | ||
98 | |||
96 | # default subarch .h files | 99 | # default subarch .h files |
97 | mflags-y += -Iinclude/asm-i386/mach-default | 100 | mflags-y += -Iinclude/asm-i386/mach-default |
98 | 101 | ||
@@ -108,6 +111,7 @@ drivers-$(CONFIG_PCI) += arch/i386/pci/ | |||
108 | # must be linked after kernel/ | 111 | # must be linked after kernel/ |
109 | drivers-$(CONFIG_OPROFILE) += arch/i386/oprofile/ | 112 | drivers-$(CONFIG_OPROFILE) += arch/i386/oprofile/ |
110 | drivers-$(CONFIG_PM) += arch/i386/power/ | 113 | drivers-$(CONFIG_PM) += arch/i386/power/ |
114 | drivers-$(CONFIG_FB) += arch/i386/video/ | ||
111 | 115 | ||
112 | CFLAGS += $(mflags-y) | 116 | CFLAGS += $(mflags-y) |
113 | AFLAGS += $(mflags-y) | 117 | AFLAGS += $(mflags-y) |
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index 08678a0a3d19..93386a4e40b4 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile | |||
@@ -39,7 +39,7 @@ setup-y += printf.o string.o tty.o video.o version.o voyager.o | |||
39 | setup-y += video-vga.o | 39 | setup-y += video-vga.o |
40 | setup-y += video-vesa.o | 40 | setup-y += video-vesa.o |
41 | setup-y += video-bios.o | 41 | setup-y += video-bios.o |
42 | 42 | targets += $(setup-y) | |
43 | hostprogs-y := tools/build | 43 | hostprogs-y := tools/build |
44 | 44 | ||
45 | HOSTCFLAGS_build.o := $(LINUXINCLUDE) | 45 | HOSTCFLAGS_build.o := $(LINUXINCLUDE) |
diff --git a/arch/i386/boot/boot.h b/arch/i386/boot/boot.h index 0329c4fe4f88..dec70c9b6050 100644 --- a/arch/i386/boot/boot.h +++ b/arch/i386/boot/boot.h | |||
@@ -56,7 +56,7 @@ static inline u16 inw(u16 port) | |||
56 | 56 | ||
57 | static inline void outl(u32 v, u16 port) | 57 | static inline void outl(u32 v, u16 port) |
58 | { | 58 | { |
59 | asm volatile("outl %0,%1" : : "a" (v), "dn" (port)); | 59 | asm volatile("outl %0,%1" : : "a" (v), "dN" (port)); |
60 | } | 60 | } |
61 | static inline u32 inl(u32 port) | 61 | static inline u32 inl(u32 port) |
62 | { | 62 | { |
diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c index ce4fda261aaf..b0e21c3cee5c 100644 --- a/arch/i386/boot/compressed/relocs.c +++ b/arch/i386/boot/compressed/relocs.c | |||
@@ -31,6 +31,8 @@ static const char* safe_abs_relocs[] = { | |||
31 | "__kernel_rt_sigreturn", | 31 | "__kernel_rt_sigreturn", |
32 | "__kernel_sigreturn", | 32 | "__kernel_sigreturn", |
33 | "SYSENTER_RETURN", | 33 | "SYSENTER_RETURN", |
34 | "xen_irq_disable_direct_reloc", | ||
35 | "xen_save_fl_direct_reloc", | ||
34 | }; | 36 | }; |
35 | 37 | ||
36 | static int is_safe_abs_reloc(const char* sym_name) | 38 | static int is_safe_abs_reloc(const char* sym_name) |
diff --git a/arch/i386/boot/cpucheck.c b/arch/i386/boot/cpucheck.c index 8b0f4473b083..991e8ceae1de 100644 --- a/arch/i386/boot/cpucheck.c +++ b/arch/i386/boot/cpucheck.c | |||
@@ -115,8 +115,8 @@ static int has_eflag(u32 mask) | |||
115 | "pushfl ; " | 115 | "pushfl ; " |
116 | "popl %1 ; " | 116 | "popl %1 ; " |
117 | "popfl" | 117 | "popfl" |
118 | : "=r" (f0), "=r" (f1) | 118 | : "=&r" (f0), "=&r" (f1) |
119 | : "g" (mask)); | 119 | : "ri" (mask)); |
120 | 120 | ||
121 | return !!((f0^f1) & mask); | 121 | return !!((f0^f1) & mask); |
122 | } | 122 | } |
diff --git a/arch/i386/boot/mca.c b/arch/i386/boot/mca.c index 9b68bd1aef19..68222f2d4b67 100644 --- a/arch/i386/boot/mca.c +++ b/arch/i386/boot/mca.c | |||
@@ -26,7 +26,7 @@ int query_mca(void) | |||
26 | "setc %0 ; " | 26 | "setc %0 ; " |
27 | "movw %%es, %1 ; " | 27 | "movw %%es, %1 ; " |
28 | "popw %%es" | 28 | "popw %%es" |
29 | : "=acdSDm" (err), "=acdSDm" (es), "=b" (bx) | 29 | : "=acd" (err), "=acdSD" (es), "=b" (bx) |
30 | : "a" (0xc000)); | 30 | : "a" (0xc000)); |
31 | 31 | ||
32 | if (err) | 32 | if (err) |
diff --git a/arch/i386/boot/pm.c b/arch/i386/boot/pm.c index 3fa53e15ed77..1df025c73261 100644 --- a/arch/i386/boot/pm.c +++ b/arch/i386/boot/pm.c | |||
@@ -65,7 +65,7 @@ static void move_kernel_around(void) | |||
65 | "popw %%ds ; " | 65 | "popw %%ds ; " |
66 | "popw %%es" | 66 | "popw %%es" |
67 | : "+c" (dwords) | 67 | : "+c" (dwords) |
68 | : "rm" (dst_seg), "rm" (src_seg) | 68 | : "r" (dst_seg), "r" (src_seg) |
69 | : "esi", "edi"); | 69 | : "esi", "edi"); |
70 | 70 | ||
71 | syssize -= paras; | 71 | syssize -= paras; |
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c index 886f47d8a488..b4248740ff0d 100644 --- a/arch/i386/boot/tools/build.c +++ b/arch/i386/boot/tools/build.c | |||
@@ -5,7 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * This file builds a disk-image from three different files: | 8 | * This file builds a disk-image from two different files: |
9 | * | 9 | * |
10 | * - setup: 8086 machine code, sets up system parm | 10 | * - setup: 8086 machine code, sets up system parm |
11 | * - system: 80386 code for actual system | 11 | * - system: 80386 code for actual system |
diff --git a/arch/i386/boot/tty.c b/arch/i386/boot/tty.c index a8db78736b02..9c668aad3515 100644 --- a/arch/i386/boot/tty.c +++ b/arch/i386/boot/tty.c | |||
@@ -31,7 +31,7 @@ void __attribute__((section(".inittext"))) putchar(int ch) | |||
31 | 31 | ||
32 | /* int $0x10 is known to have bugs involving touching registers | 32 | /* int $0x10 is known to have bugs involving touching registers |
33 | it shouldn't. Be extra conservative... */ | 33 | it shouldn't. Be extra conservative... */ |
34 | asm volatile("pushal; int $0x10; popal" | 34 | asm volatile("pushal; pushw %%ds; int $0x10; popw %%ds; popal" |
35 | : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); | 35 | : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/arch/i386/boot/video.c b/arch/i386/boot/video.c index 3bb3573cd6a1..958130ef0042 100644 --- a/arch/i386/boot/video.c +++ b/arch/i386/boot/video.c | |||
@@ -195,7 +195,7 @@ static void vga_recalc_vertical(void) | |||
195 | { | 195 | { |
196 | unsigned int font_size, rows; | 196 | unsigned int font_size, rows; |
197 | u16 crtc; | 197 | u16 crtc; |
198 | u8 ov; | 198 | u8 pt, ov; |
199 | 199 | ||
200 | set_fs(0); | 200 | set_fs(0); |
201 | font_size = rdfs8(0x485); /* BIOS: font size (pixels) */ | 201 | font_size = rdfs8(0x485); /* BIOS: font size (pixels) */ |
@@ -206,7 +206,12 @@ static void vga_recalc_vertical(void) | |||
206 | 206 | ||
207 | crtc = vga_crtc(); | 207 | crtc = vga_crtc(); |
208 | 208 | ||
209 | pt = in_idx(crtc, 0x11); | ||
210 | pt &= ~0x80; /* Unlock CR0-7 */ | ||
211 | out_idx(pt, crtc, 0x11); | ||
212 | |||
209 | out_idx((u8)rows, crtc, 0x12); /* Lower height register */ | 213 | out_idx((u8)rows, crtc, 0x12); /* Lower height register */ |
214 | |||
210 | ov = in_idx(crtc, 0x07); /* Overflow register */ | 215 | ov = in_idx(crtc, 0x07); /* Overflow register */ |
211 | ov &= 0xbd; | 216 | ov &= 0xbd; |
212 | ov |= (rows >> (8-1)) & 0x02; | 217 | ov |= (rows >> (8-1)) & 0x02; |
@@ -411,7 +416,7 @@ static void restore_screen(void) | |||
411 | "1: rep;stosl ; " | 416 | "1: rep;stosl ; " |
412 | "popw %%es" | 417 | "popw %%es" |
413 | : "+D" (dst), "+c" (npad) | 418 | : "+D" (dst), "+c" (npad) |
414 | : "bdSm" (video_segment), | 419 | : "bdS" (video_segment), |
415 | "a" (0x07200720)); | 420 | "a" (0x07200720)); |
416 | } | 421 | } |
417 | 422 | ||
diff --git a/arch/i386/boot/video.h b/arch/i386/boot/video.h index 29eca1710b2c..b92447d51213 100644 --- a/arch/i386/boot/video.h +++ b/arch/i386/boot/video.h | |||
@@ -117,8 +117,15 @@ extern int graphic_mode; /* Graphics mode with linear frame buffer */ | |||
117 | * int $0x10 is notorious for touching registers it shouldn't. | 117 | * int $0x10 is notorious for touching registers it shouldn't. |
118 | * gcc doesn't like %ebp being clobbered, so define it as a push/pop | 118 | * gcc doesn't like %ebp being clobbered, so define it as a push/pop |
119 | * sequence here. | 119 | * sequence here. |
120 | * | ||
121 | * A number of systems, including the original PC can clobber %bp in | ||
122 | * certain circumstances, like when scrolling. There exists at least | ||
123 | * one Trident video card which could clobber DS under a set of | ||
124 | * circumstances that we are unlikely to encounter (scrolling when | ||
125 | * using an extended graphics mode of more than 800x600 pixels), but | ||
126 | * it's cheap insurance to deal with that here. | ||
120 | */ | 127 | */ |
121 | #define INT10 "pushl %%ebp; int $0x10; popl %%ebp" | 128 | #define INT10 "pushl %%ebp; pushw %%ds; int $0x10; popw %%ds; popl %%ebp" |
122 | 129 | ||
123 | /* Accessing VGA indexed registers */ | 130 | /* Accessing VGA indexed registers */ |
124 | static inline u8 in_idx(u16 port, u8 index) | 131 | static inline u8 in_idx(u16 port, u8 index) |
diff --git a/arch/i386/boot/voyager.c b/arch/i386/boot/voyager.c index 9221614d0db8..61c8fe0453be 100644 --- a/arch/i386/boot/voyager.c +++ b/arch/i386/boot/voyager.c | |||
@@ -32,7 +32,7 @@ int query_voyager(void) | |||
32 | "setc %0 ; " | 32 | "setc %0 ; " |
33 | "movw %%es, %1 ; " | 33 | "movw %%es, %1 ; " |
34 | "popw %%es" | 34 | "popw %%es" |
35 | : "=qm" (err), "=rm" (es), "=D" (di) | 35 | : "=q" (err), "=r" (es), "=D" (di) |
36 | : "a" (0xffc0)); | 36 | : "a" (0xffc0)); |
37 | 37 | ||
38 | if (err) | 38 | if (err) |
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c index 4ee83577bf61..c42b5ab49deb 100644 --- a/arch/i386/kernel/acpi/sleep.c +++ b/arch/i386/kernel/acpi/sleep.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | /* address in low memory of the wakeup routine. */ | 15 | /* address in low memory of the wakeup routine. */ |
16 | unsigned long acpi_wakeup_address = 0; | 16 | unsigned long acpi_wakeup_address = 0; |
17 | unsigned long acpi_video_flags; | 17 | unsigned long acpi_realmode_flags; |
18 | extern char wakeup_start, wakeup_end; | 18 | extern char wakeup_start, wakeup_end; |
19 | 19 | ||
20 | extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); | 20 | extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); |
@@ -68,9 +68,11 @@ static int __init acpi_sleep_setup(char *str) | |||
68 | { | 68 | { |
69 | while ((str != NULL) && (*str != '\0')) { | 69 | while ((str != NULL) && (*str != '\0')) { |
70 | if (strncmp(str, "s3_bios", 7) == 0) | 70 | if (strncmp(str, "s3_bios", 7) == 0) |
71 | acpi_video_flags = 1; | 71 | acpi_realmode_flags |= 1; |
72 | if (strncmp(str, "s3_mode", 7) == 0) | 72 | if (strncmp(str, "s3_mode", 7) == 0) |
73 | acpi_video_flags |= 2; | 73 | acpi_realmode_flags |= 2; |
74 | if (strncmp(str, "s3_beep", 7) == 0) | ||
75 | acpi_realmode_flags |= 4; | ||
74 | str = strchr(str, ','); | 76 | str = strchr(str, ','); |
75 | if (str != NULL) | 77 | if (str != NULL) |
76 | str += strspn(str, ", \t"); | 78 | str += strspn(str, ", \t"); |
@@ -80,9 +82,11 @@ static int __init acpi_sleep_setup(char *str) | |||
80 | 82 | ||
81 | __setup("acpi_sleep=", acpi_sleep_setup); | 83 | __setup("acpi_sleep=", acpi_sleep_setup); |
82 | 84 | ||
85 | /* Ouch, we want to delete this. We already have better version in userspace, in | ||
86 | s2ram from suspend.sf.net project */ | ||
83 | static __init int reset_videomode_after_s3(struct dmi_system_id *d) | 87 | static __init int reset_videomode_after_s3(struct dmi_system_id *d) |
84 | { | 88 | { |
85 | acpi_video_flags |= 2; | 89 | acpi_realmode_flags |= 2; |
86 | return 0; | 90 | return 0; |
87 | } | 91 | } |
88 | 92 | ||
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index a2295a34b2c7..ed0a0f2c1597 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S | |||
@@ -13,6 +13,21 @@ | |||
13 | # cs = 0x1234, eip = 0x05 | 13 | # cs = 0x1234, eip = 0x05 |
14 | # | 14 | # |
15 | 15 | ||
16 | #define BEEP \ | ||
17 | inb $97, %al; \ | ||
18 | outb %al, $0x80; \ | ||
19 | movb $3, %al; \ | ||
20 | outb %al, $97; \ | ||
21 | outb %al, $0x80; \ | ||
22 | movb $-74, %al; \ | ||
23 | outb %al, $67; \ | ||
24 | outb %al, $0x80; \ | ||
25 | movb $-119, %al; \ | ||
26 | outb %al, $66; \ | ||
27 | outb %al, $0x80; \ | ||
28 | movb $15, %al; \ | ||
29 | outb %al, $66; | ||
30 | |||
16 | ALIGN | 31 | ALIGN |
17 | .align 4096 | 32 | .align 4096 |
18 | ENTRY(wakeup_start) | 33 | ENTRY(wakeup_start) |
@@ -31,6 +46,11 @@ wakeup_code: | |||
31 | movw %cs, %ax | 46 | movw %cs, %ax |
32 | movw %ax, %ds # Make ds:0 point to wakeup_start | 47 | movw %ax, %ds # Make ds:0 point to wakeup_start |
33 | movw %ax, %ss | 48 | movw %ax, %ss |
49 | |||
50 | testl $4, realmode_flags - wakeup_code | ||
51 | jz 1f | ||
52 | BEEP | ||
53 | 1: | ||
34 | mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board | 54 | mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board |
35 | movw $0x0e00 + 'S', %fs:(0x12) | 55 | movw $0x0e00 + 'S', %fs:(0x12) |
36 | 56 | ||
@@ -41,7 +61,7 @@ wakeup_code: | |||
41 | cmpl $0x12345678, %eax | 61 | cmpl $0x12345678, %eax |
42 | jne bogus_real_magic | 62 | jne bogus_real_magic |
43 | 63 | ||
44 | testl $1, video_flags - wakeup_code | 64 | testl $1, realmode_flags - wakeup_code |
45 | jz 1f | 65 | jz 1f |
46 | lcall $0xc000,$3 | 66 | lcall $0xc000,$3 |
47 | movw %cs, %ax | 67 | movw %cs, %ax |
@@ -49,7 +69,7 @@ wakeup_code: | |||
49 | movw %ax, %ss | 69 | movw %ax, %ss |
50 | 1: | 70 | 1: |
51 | 71 | ||
52 | testl $2, video_flags - wakeup_code | 72 | testl $2, realmode_flags - wakeup_code |
53 | jz 1f | 73 | jz 1f |
54 | mov video_mode - wakeup_code, %ax | 74 | mov video_mode - wakeup_code, %ax |
55 | call mode_set | 75 | call mode_set |
@@ -88,7 +108,11 @@ wakeup_code: | |||
88 | cmpl $0x12345678, %eax | 108 | cmpl $0x12345678, %eax |
89 | jne bogus_real_magic | 109 | jne bogus_real_magic |
90 | 110 | ||
91 | ljmpl $__KERNEL_CS,$wakeup_pmode_return | 111 | testl $8, realmode_flags - wakeup_code |
112 | jz 1f | ||
113 | BEEP | ||
114 | 1: | ||
115 | ljmpl $__KERNEL_CS, $wakeup_pmode_return | ||
92 | 116 | ||
93 | real_save_gdt: .word 0 | 117 | real_save_gdt: .word 0 |
94 | .long 0 | 118 | .long 0 |
@@ -97,7 +121,8 @@ real_save_cr3: .long 0 | |||
97 | real_save_cr4: .long 0 | 121 | real_save_cr4: .long 0 |
98 | real_magic: .long 0 | 122 | real_magic: .long 0 |
99 | video_mode: .long 0 | 123 | video_mode: .long 0 |
100 | video_flags: .long 0 | 124 | realmode_flags: .long 0 |
125 | beep_flags: .long 0 | ||
101 | real_efer_save_restore: .long 0 | 126 | real_efer_save_restore: .long 0 |
102 | real_save_efer_edx: .long 0 | 127 | real_save_efer_edx: .long 0 |
103 | real_save_efer_eax: .long 0 | 128 | real_save_efer_eax: .long 0 |
@@ -260,8 +285,8 @@ ENTRY(acpi_copy_wakeup_routine) | |||
260 | 285 | ||
261 | movl saved_videomode, %edx | 286 | movl saved_videomode, %edx |
262 | movl %edx, video_mode - wakeup_start (%eax) | 287 | movl %edx, video_mode - wakeup_start (%eax) |
263 | movl acpi_video_flags, %edx | 288 | movl acpi_realmode_flags, %edx |
264 | movl %edx, video_flags - wakeup_start (%eax) | 289 | movl %edx, realmode_flags - wakeup_start (%eax) |
265 | movl $0x12345678, real_magic - wakeup_start (%eax) | 290 | movl $0x12345678, real_magic - wakeup_start (%eax) |
266 | movl $0x12345678, saved_magic | 291 | movl $0x12345678, saved_magic |
267 | popl %ebx | 292 | popl %ebx |
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 4112afe712b9..47001d50a083 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -222,6 +222,7 @@ | |||
222 | #include <linux/capability.h> | 222 | #include <linux/capability.h> |
223 | #include <linux/device.h> | 223 | #include <linux/device.h> |
224 | #include <linux/kernel.h> | 224 | #include <linux/kernel.h> |
225 | #include <linux/freezer.h> | ||
225 | #include <linux/smp.h> | 226 | #include <linux/smp.h> |
226 | #include <linux/dmi.h> | 227 | #include <linux/dmi.h> |
227 | #include <linux/suspend.h> | 228 | #include <linux/suspend.h> |
@@ -2311,7 +2312,6 @@ static int __init apm_init(void) | |||
2311 | remove_proc_entry("apm", NULL); | 2312 | remove_proc_entry("apm", NULL); |
2312 | return err; | 2313 | return err; |
2313 | } | 2314 | } |
2314 | kapmd_task->flags |= PF_NOFREEZE; | ||
2315 | wake_up_process(kapmd_task); | 2315 | wake_up_process(kapmd_task); |
2316 | 2316 | ||
2317 | if (num_online_cpus() > 1 && !smp ) { | 2317 | if (num_online_cpus() > 1 && !smp ) { |
diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c index 27a776c9044d..7288ac88d746 100644 --- a/arch/i386/kernel/asm-offsets.c +++ b/arch/i386/kernel/asm-offsets.c | |||
@@ -17,6 +17,13 @@ | |||
17 | #include <asm/thread_info.h> | 17 | #include <asm/thread_info.h> |
18 | #include <asm/elf.h> | 18 | #include <asm/elf.h> |
19 | 19 | ||
20 | #include <xen/interface/xen.h> | ||
21 | |||
22 | #ifdef CONFIG_LGUEST_GUEST | ||
23 | #include <linux/lguest.h> | ||
24 | #include "../../../drivers/lguest/lg.h" | ||
25 | #endif | ||
26 | |||
20 | #define DEFINE(sym, val) \ | 27 | #define DEFINE(sym, val) \ |
21 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | 28 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) |
22 | 29 | ||
@@ -59,6 +66,7 @@ void foo(void) | |||
59 | OFFSET(TI_addr_limit, thread_info, addr_limit); | 66 | OFFSET(TI_addr_limit, thread_info, addr_limit); |
60 | OFFSET(TI_restart_block, thread_info, restart_block); | 67 | OFFSET(TI_restart_block, thread_info, restart_block); |
61 | OFFSET(TI_sysenter_return, thread_info, sysenter_return); | 68 | OFFSET(TI_sysenter_return, thread_info, sysenter_return); |
69 | OFFSET(TI_cpu, thread_info, cpu); | ||
62 | BLANK(); | 70 | BLANK(); |
63 | 71 | ||
64 | OFFSET(GDS_size, Xgt_desc_struct, size); | 72 | OFFSET(GDS_size, Xgt_desc_struct, size); |
@@ -115,4 +123,25 @@ void foo(void) | |||
115 | OFFSET(PARAVIRT_iret, paravirt_ops, iret); | 123 | OFFSET(PARAVIRT_iret, paravirt_ops, iret); |
116 | OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); | 124 | OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); |
117 | #endif | 125 | #endif |
126 | |||
127 | #ifdef CONFIG_XEN | ||
128 | BLANK(); | ||
129 | OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask); | ||
130 | OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending); | ||
131 | #endif | ||
132 | |||
133 | #ifdef CONFIG_LGUEST_GUEST | ||
134 | BLANK(); | ||
135 | OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled); | ||
136 | OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc); | ||
137 | OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc); | ||
138 | OFFSET(LGUEST_PAGES_host_cr3, lguest_pages, state.host_cr3); | ||
139 | OFFSET(LGUEST_PAGES_host_sp, lguest_pages, state.host_sp); | ||
140 | OFFSET(LGUEST_PAGES_guest_gdt_desc, lguest_pages,state.guest_gdt_desc); | ||
141 | OFFSET(LGUEST_PAGES_guest_idt_desc, lguest_pages,state.guest_idt_desc); | ||
142 | OFFSET(LGUEST_PAGES_guest_gdt, lguest_pages, state.guest_gdt); | ||
143 | OFFSET(LGUEST_PAGES_regs_trapnum, lguest_pages, regs.trapnum); | ||
144 | OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode); | ||
145 | OFFSET(LGUEST_PAGES_regs, lguest_pages, regs); | ||
146 | #endif | ||
118 | } | 147 | } |
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c index 7ba7c3abd3a4..1203dc5ab87a 100644 --- a/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c | |||
@@ -134,19 +134,21 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb, | |||
134 | int err; | 134 | int err; |
135 | 135 | ||
136 | sys_dev = get_cpu_sysdev(cpu); | 136 | sys_dev = get_cpu_sysdev(cpu); |
137 | mutex_lock(&therm_cpu_lock); | ||
138 | switch (action) { | 137 | switch (action) { |
139 | case CPU_ONLINE: | 138 | case CPU_ONLINE: |
140 | case CPU_ONLINE_FROZEN: | 139 | case CPU_ONLINE_FROZEN: |
140 | mutex_lock(&therm_cpu_lock); | ||
141 | err = thermal_throttle_add_dev(sys_dev); | 141 | err = thermal_throttle_add_dev(sys_dev); |
142 | mutex_unlock(&therm_cpu_lock); | ||
142 | WARN_ON(err); | 143 | WARN_ON(err); |
143 | break; | 144 | break; |
144 | case CPU_DEAD: | 145 | case CPU_DEAD: |
145 | case CPU_DEAD_FROZEN: | 146 | case CPU_DEAD_FROZEN: |
147 | mutex_lock(&therm_cpu_lock); | ||
146 | thermal_throttle_remove_dev(sys_dev); | 148 | thermal_throttle_remove_dev(sys_dev); |
149 | mutex_unlock(&therm_cpu_lock); | ||
147 | break; | 150 | break; |
148 | } | 151 | } |
149 | mutex_unlock(&therm_cpu_lock); | ||
150 | return NOTIFY_OK; | 152 | return NOTIFY_OK; |
151 | } | 153 | } |
152 | 154 | ||
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index a1808022ea19..2452c6fbe992 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c | |||
@@ -278,7 +278,7 @@ void efi_memmap_walk(efi_freemem_callback_t callback, void *arg) | |||
278 | struct range { | 278 | struct range { |
279 | unsigned long start; | 279 | unsigned long start; |
280 | unsigned long end; | 280 | unsigned long end; |
281 | } prev, curr; | 281 | } uninitialized_var(prev), curr; |
282 | efi_memory_desc_t *md; | 282 | efi_memory_desc_t *md; |
283 | unsigned long start, end; | 283 | unsigned long start, end; |
284 | void *p; | 284 | void *p; |
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 3c3c220488c9..a714d6b43506 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -409,8 +409,6 @@ restore_nocheck_notrace: | |||
409 | 1: INTERRUPT_RETURN | 409 | 1: INTERRUPT_RETURN |
410 | .section .fixup,"ax" | 410 | .section .fixup,"ax" |
411 | iret_exc: | 411 | iret_exc: |
412 | TRACE_IRQS_ON | ||
413 | ENABLE_INTERRUPTS(CLBR_NONE) | ||
414 | pushl $0 # no error code | 412 | pushl $0 # no error code |
415 | pushl $do_iret_error | 413 | pushl $do_iret_error |
416 | jmp error_code | 414 | jmp error_code |
@@ -1023,6 +1021,91 @@ ENTRY(kernel_thread_helper) | |||
1023 | CFI_ENDPROC | 1021 | CFI_ENDPROC |
1024 | ENDPROC(kernel_thread_helper) | 1022 | ENDPROC(kernel_thread_helper) |
1025 | 1023 | ||
1024 | #ifdef CONFIG_XEN | ||
1025 | ENTRY(xen_hypervisor_callback) | ||
1026 | CFI_STARTPROC | ||
1027 | pushl $0 | ||
1028 | CFI_ADJUST_CFA_OFFSET 4 | ||
1029 | SAVE_ALL | ||
1030 | TRACE_IRQS_OFF | ||
1031 | |||
1032 | /* Check to see if we got the event in the critical | ||
1033 | region in xen_iret_direct, after we've reenabled | ||
1034 | events and checked for pending events. This simulates | ||
1035 | iret instruction's behaviour where it delivers a | ||
1036 | pending interrupt when enabling interrupts. */ | ||
1037 | movl PT_EIP(%esp),%eax | ||
1038 | cmpl $xen_iret_start_crit,%eax | ||
1039 | jb 1f | ||
1040 | cmpl $xen_iret_end_crit,%eax | ||
1041 | jae 1f | ||
1042 | |||
1043 | call xen_iret_crit_fixup | ||
1044 | |||
1045 | 1: mov %esp, %eax | ||
1046 | call xen_evtchn_do_upcall | ||
1047 | jmp ret_from_intr | ||
1048 | CFI_ENDPROC | ||
1049 | ENDPROC(xen_hypervisor_callback) | ||
1050 | |||
1051 | # Hypervisor uses this for application faults while it executes. | ||
1052 | # We get here for two reasons: | ||
1053 | # 1. Fault while reloading DS, ES, FS or GS | ||
1054 | # 2. Fault while executing IRET | ||
1055 | # Category 1 we fix up by reattempting the load, and zeroing the segment | ||
1056 | # register if the load fails. | ||
1057 | # Category 2 we fix up by jumping to do_iret_error. We cannot use the | ||
1058 | # normal Linux return path in this case because if we use the IRET hypercall | ||
1059 | # to pop the stack frame we end up in an infinite loop of failsafe callbacks. | ||
1060 | # We distinguish between categories by maintaining a status value in EAX. | ||
1061 | ENTRY(xen_failsafe_callback) | ||
1062 | CFI_STARTPROC | ||
1063 | pushl %eax | ||
1064 | CFI_ADJUST_CFA_OFFSET 4 | ||
1065 | movl $1,%eax | ||
1066 | 1: mov 4(%esp),%ds | ||
1067 | 2: mov 8(%esp),%es | ||
1068 | 3: mov 12(%esp),%fs | ||
1069 | 4: mov 16(%esp),%gs | ||
1070 | testl %eax,%eax | ||
1071 | popl %eax | ||
1072 | CFI_ADJUST_CFA_OFFSET -4 | ||
1073 | lea 16(%esp),%esp | ||
1074 | CFI_ADJUST_CFA_OFFSET -16 | ||
1075 | jz 5f | ||
1076 | addl $16,%esp | ||
1077 | jmp iret_exc # EAX != 0 => Category 2 (Bad IRET) | ||
1078 | 5: pushl $0 # EAX == 0 => Category 1 (Bad segment) | ||
1079 | CFI_ADJUST_CFA_OFFSET 4 | ||
1080 | SAVE_ALL | ||
1081 | jmp ret_from_exception | ||
1082 | CFI_ENDPROC | ||
1083 | |||
1084 | .section .fixup,"ax" | ||
1085 | 6: xorl %eax,%eax | ||
1086 | movl %eax,4(%esp) | ||
1087 | jmp 1b | ||
1088 | 7: xorl %eax,%eax | ||
1089 | movl %eax,8(%esp) | ||
1090 | jmp 2b | ||
1091 | 8: xorl %eax,%eax | ||
1092 | movl %eax,12(%esp) | ||
1093 | jmp 3b | ||
1094 | 9: xorl %eax,%eax | ||
1095 | movl %eax,16(%esp) | ||
1096 | jmp 4b | ||
1097 | .previous | ||
1098 | .section __ex_table,"a" | ||
1099 | .align 4 | ||
1100 | .long 1b,6b | ||
1101 | .long 2b,7b | ||
1102 | .long 3b,8b | ||
1103 | .long 4b,9b | ||
1104 | .previous | ||
1105 | ENDPROC(xen_failsafe_callback) | ||
1106 | |||
1107 | #endif /* CONFIG_XEN */ | ||
1108 | |||
1026 | .section .rodata,"a" | 1109 | .section .rodata,"a" |
1027 | #include "syscall_table.S" | 1110 | #include "syscall_table.S" |
1028 | 1111 | ||
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 82714668d43b..7c52b222207e 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S | |||
@@ -510,7 +510,8 @@ ENTRY(_stext) | |||
510 | /* | 510 | /* |
511 | * BSS section | 511 | * BSS section |
512 | */ | 512 | */ |
513 | .section ".bss.page_aligned","w" | 513 | .section ".bss.page_aligned","wa" |
514 | .align PAGE_SIZE_asm | ||
514 | ENTRY(swapper_pg_dir) | 515 | ENTRY(swapper_pg_dir) |
515 | .fill 1024,4,0 | 516 | .fill 1024,4,0 |
516 | ENTRY(swapper_pg_pmd) | 517 | ENTRY(swapper_pg_pmd) |
@@ -538,6 +539,8 @@ fault_msg: | |||
538 | .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n" | 539 | .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n" |
539 | .asciz "Stack: %p %p %p %p %p %p %p %p\n" | 540 | .asciz "Stack: %p %p %p %p %p %p %p %p\n" |
540 | 541 | ||
542 | #include "../xen/xen-head.S" | ||
543 | |||
541 | /* | 544 | /* |
542 | * The IDT and GDT 'descriptors' are a strange 48-bit object | 545 | * The IDT and GDT 'descriptors' are a strange 48-bit object |
543 | * only used by the lidt and lgdt instructions. They are not | 546 | * only used by the lidt and lgdt instructions. They are not |
diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c index cff95d10a4d8..d26fc063a760 100644 --- a/arch/i386/kernel/init_task.c +++ b/arch/i386/kernel/init_task.c | |||
@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task); | |||
42 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, | 42 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, |
43 | * no more per-task TSS's. | 43 | * no more per-task TSS's. |
44 | */ | 44 | */ |
45 | DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; | 45 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; |
46 | 46 | ||
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 7f8b7af2b95f..21db8f56c9a1 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -667,6 +667,7 @@ static int balanced_irq(void *unused) | |||
667 | set_pending_irq(i, cpumask_of_cpu(0)); | 667 | set_pending_irq(i, cpumask_of_cpu(0)); |
668 | } | 668 | } |
669 | 669 | ||
670 | set_freezable(); | ||
670 | for ( ; ; ) { | 671 | for ( ; ; ) { |
671 | time_remaining = schedule_timeout_interruptible(time_remaining); | 672 | time_remaining = schedule_timeout_interruptible(time_remaining); |
672 | try_to_freeze(); | 673 | try_to_freeze(); |
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index d2daf672f4a2..ba44d40b066d 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <asm/apic.h> | 21 | #include <asm/apic.h> |
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | 23 | ||
24 | DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp; | 24 | DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); |
25 | EXPORT_PER_CPU_SYMBOL(irq_stat); | 25 | EXPORT_PER_CPU_SYMBOL(irq_stat); |
26 | 26 | ||
27 | DEFINE_PER_CPU(struct pt_regs *, irq_regs); | 27 | DEFINE_PER_CPU(struct pt_regs *, irq_regs); |
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index fba121f7973f..03b7f5584d71 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c | |||
@@ -295,7 +295,7 @@ static unsigned int | |||
295 | last_irq_sums [NR_CPUS], | 295 | last_irq_sums [NR_CPUS], |
296 | alert_counter [NR_CPUS]; | 296 | alert_counter [NR_CPUS]; |
297 | 297 | ||
298 | void touch_nmi_watchdog (void) | 298 | void touch_nmi_watchdog(void) |
299 | { | 299 | { |
300 | if (nmi_watchdog > 0) { | 300 | if (nmi_watchdog > 0) { |
301 | unsigned cpu; | 301 | unsigned cpu; |
@@ -304,8 +304,10 @@ void touch_nmi_watchdog (void) | |||
304 | * Just reset the alert counters, (other CPUs might be | 304 | * Just reset the alert counters, (other CPUs might be |
305 | * spinning on locks we hold): | 305 | * spinning on locks we hold): |
306 | */ | 306 | */ |
307 | for_each_present_cpu (cpu) | 307 | for_each_present_cpu(cpu) { |
308 | alert_counter[cpu] = 0; | 308 | if (alert_counter[cpu]) |
309 | alert_counter[cpu] = 0; | ||
310 | } | ||
309 | } | 311 | } |
310 | 312 | ||
311 | /* | 313 | /* |
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c index faab09abca5e..53f07a8275e3 100644 --- a/arch/i386/kernel/paravirt.c +++ b/arch/i386/kernel/paravirt.c | |||
@@ -228,6 +228,41 @@ static int __init print_banner(void) | |||
228 | } | 228 | } |
229 | core_initcall(print_banner); | 229 | core_initcall(print_banner); |
230 | 230 | ||
231 | static struct resource reserve_ioports = { | ||
232 | .start = 0, | ||
233 | .end = IO_SPACE_LIMIT, | ||
234 | .name = "paravirt-ioport", | ||
235 | .flags = IORESOURCE_IO | IORESOURCE_BUSY, | ||
236 | }; | ||
237 | |||
238 | static struct resource reserve_iomem = { | ||
239 | .start = 0, | ||
240 | .end = -1, | ||
241 | .name = "paravirt-iomem", | ||
242 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, | ||
243 | }; | ||
244 | |||
245 | /* | ||
246 | * Reserve the whole legacy IO space to prevent any legacy drivers | ||
247 | * from wasting time probing for their hardware. This is a fairly | ||
248 | * brute-force approach to disabling all non-virtual drivers. | ||
249 | * | ||
250 | * Note that this must be called very early to have any effect. | ||
251 | */ | ||
252 | int paravirt_disable_iospace(void) | ||
253 | { | ||
254 | int ret; | ||
255 | |||
256 | ret = request_resource(&ioport_resource, &reserve_ioports); | ||
257 | if (ret == 0) { | ||
258 | ret = request_resource(&iomem_resource, &reserve_iomem); | ||
259 | if (ret) | ||
260 | release_resource(&reserve_ioports); | ||
261 | } | ||
262 | |||
263 | return ret; | ||
264 | } | ||
265 | |||
231 | struct paravirt_ops paravirt_ops = { | 266 | struct paravirt_ops paravirt_ops = { |
232 | .name = "bare hardware", | 267 | .name = "bare hardware", |
233 | .paravirt_enabled = 0, | 268 | .paravirt_enabled = 0, |
@@ -267,7 +302,7 @@ struct paravirt_ops paravirt_ops = { | |||
267 | .write_msr = native_write_msr_safe, | 302 | .write_msr = native_write_msr_safe, |
268 | .read_tsc = native_read_tsc, | 303 | .read_tsc = native_read_tsc, |
269 | .read_pmc = native_read_pmc, | 304 | .read_pmc = native_read_pmc, |
270 | .get_scheduled_cycles = native_read_tsc, | 305 | .sched_clock = native_sched_clock, |
271 | .get_cpu_khz = native_calculate_cpu_khz, | 306 | .get_cpu_khz = native_calculate_cpu_khz, |
272 | .load_tr_desc = native_load_tr_desc, | 307 | .load_tr_desc = native_load_tr_desc, |
273 | .set_ldt = native_set_ldt, | 308 | .set_ldt = native_set_ldt, |
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 0c0ceec5de00..0c8f00e69c4d 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c | |||
@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_ | |||
164 | u32 *desc; | 164 | u32 *desc; |
165 | unsigned long base; | 165 | unsigned long base; |
166 | 166 | ||
167 | down(&child->mm->context.sem); | 167 | seg &= ~7UL; |
168 | desc = child->mm->context.ldt + (seg & ~7); | ||
169 | base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000); | ||
170 | 168 | ||
171 | /* 16-bit code segment? */ | 169 | down(&child->mm->context.sem); |
172 | if (!((desc[1] >> 22) & 1)) | 170 | if (unlikely((seg >> 3) >= child->mm->context.size)) |
173 | addr &= 0xffff; | 171 | addr = -1L; /* bogus selector, access would fault */ |
174 | addr += base; | 172 | else { |
173 | desc = child->mm->context.ldt + seg; | ||
174 | base = ((desc[0] >> 16) | | ||
175 | ((desc[1] & 0xff) << 16) | | ||
176 | (desc[1] & 0xff000000)); | ||
177 | |||
178 | /* 16-bit code segment? */ | ||
179 | if (!((desc[1] >> 22) & 1)) | ||
180 | addr &= 0xffff; | ||
181 | addr += base; | ||
182 | } | ||
175 | up(&child->mm->context.sem); | 183 | up(&child->mm->context.sem); |
176 | } | 184 | } |
177 | return addr; | 185 | return addr; |
@@ -358,17 +366,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
358 | switch (request) { | 366 | switch (request) { |
359 | /* when I and D space are separate, these will need to be fixed. */ | 367 | /* when I and D space are separate, these will need to be fixed. */ |
360 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 368 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
361 | case PTRACE_PEEKDATA: { | 369 | case PTRACE_PEEKDATA: |
362 | unsigned long tmp; | 370 | ret = generic_ptrace_peekdata(child, addr, data); |
363 | int copied; | ||
364 | |||
365 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
366 | ret = -EIO; | ||
367 | if (copied != sizeof(tmp)) | ||
368 | break; | ||
369 | ret = put_user(tmp, datap); | ||
370 | break; | 371 | break; |
371 | } | ||
372 | 372 | ||
373 | /* read the word at location addr in the USER area. */ | 373 | /* read the word at location addr in the USER area. */ |
374 | case PTRACE_PEEKUSR: { | 374 | case PTRACE_PEEKUSR: { |
@@ -395,10 +395,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
395 | /* when I and D space are separate, this will have to be fixed. */ | 395 | /* when I and D space are separate, this will have to be fixed. */ |
396 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 396 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
397 | case PTRACE_POKEDATA: | 397 | case PTRACE_POKEDATA: |
398 | ret = 0; | 398 | ret = generic_ptrace_pokedata(child, addr, data); |
399 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
400 | break; | ||
401 | ret = -EIO; | ||
402 | break; | 399 | break; |
403 | 400 | ||
404 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 401 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 2d61e65eeb50..74871d066c2b 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -601,6 +601,8 @@ void __init setup_arch(char **cmdline_p) | |||
601 | * NOTE: at this point the bootmem allocator is fully available. | 601 | * NOTE: at this point the bootmem allocator is fully available. |
602 | */ | 602 | */ |
603 | 603 | ||
604 | paravirt_post_allocator_init(); | ||
605 | |||
604 | dmi_scan_machine(); | 606 | dmi_scan_machine(); |
605 | 607 | ||
606 | #ifdef CONFIG_X86_GENERICARCH | 608 | #ifdef CONFIG_X86_GENERICARCH |
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 6299c080f6e2..2d35d8502029 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <asm/mtrr.h> | 23 | #include <asm/mtrr.h> |
24 | #include <asm/tlbflush.h> | 24 | #include <asm/tlbflush.h> |
25 | #include <asm/mmu_context.h> | ||
25 | #include <mach_apic.h> | 26 | #include <mach_apic.h> |
26 | 27 | ||
27 | /* | 28 | /* |
@@ -249,13 +250,13 @@ static unsigned long flush_va; | |||
249 | static DEFINE_SPINLOCK(tlbstate_lock); | 250 | static DEFINE_SPINLOCK(tlbstate_lock); |
250 | 251 | ||
251 | /* | 252 | /* |
252 | * We cannot call mmdrop() because we are in interrupt context, | 253 | * We cannot call mmdrop() because we are in interrupt context, |
253 | * instead update mm->cpu_vm_mask. | 254 | * instead update mm->cpu_vm_mask. |
254 | * | 255 | * |
255 | * We need to reload %cr3 since the page tables may be going | 256 | * We need to reload %cr3 since the page tables may be going |
256 | * away from under us.. | 257 | * away from under us.. |
257 | */ | 258 | */ |
258 | static inline void leave_mm (unsigned long cpu) | 259 | void leave_mm(unsigned long cpu) |
259 | { | 260 | { |
260 | if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) | 261 | if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) |
261 | BUG(); | 262 | BUG(); |
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 0b2954534b8e..5910d3fac561 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -148,7 +148,7 @@ void __init smp_alloc_memory(void) | |||
148 | * a given CPU | 148 | * a given CPU |
149 | */ | 149 | */ |
150 | 150 | ||
151 | static void __cpuinit smp_store_cpu_info(int id) | 151 | void __cpuinit smp_store_cpu_info(int id) |
152 | { | 152 | { |
153 | struct cpuinfo_x86 *c = cpu_data + id; | 153 | struct cpuinfo_x86 *c = cpu_data + id; |
154 | 154 | ||
@@ -308,8 +308,7 @@ cpumask_t cpu_coregroup_map(int cpu) | |||
308 | /* representing cpus for which sibling maps can be computed */ | 308 | /* representing cpus for which sibling maps can be computed */ |
309 | static cpumask_t cpu_sibling_setup_map; | 309 | static cpumask_t cpu_sibling_setup_map; |
310 | 310 | ||
311 | static inline void | 311 | void set_cpu_sibling_map(int cpu) |
312 | set_cpu_sibling_map(int cpu) | ||
313 | { | 312 | { |
314 | int i; | 313 | int i; |
315 | struct cpuinfo_x86 *c = cpu_data; | 314 | struct cpuinfo_x86 *c = cpu_data; |
@@ -1144,8 +1143,7 @@ void __init native_smp_prepare_boot_cpu(void) | |||
1144 | } | 1143 | } |
1145 | 1144 | ||
1146 | #ifdef CONFIG_HOTPLUG_CPU | 1145 | #ifdef CONFIG_HOTPLUG_CPU |
1147 | static void | 1146 | void remove_siblinginfo(int cpu) |
1148 | remove_siblinginfo(int cpu) | ||
1149 | { | 1147 | { |
1150 | int sibling; | 1148 | int sibling; |
1151 | struct cpuinfo_x86 *c = cpu_data; | 1149 | struct cpuinfo_x86 *c = cpu_data; |
diff --git a/arch/i386/kernel/smpcommon.c b/arch/i386/kernel/smpcommon.c index 1868ae18eb4d..bbfe85a0f699 100644 --- a/arch/i386/kernel/smpcommon.c +++ b/arch/i386/kernel/smpcommon.c | |||
@@ -47,7 +47,7 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic, | |||
47 | EXPORT_SYMBOL(smp_call_function); | 47 | EXPORT_SYMBOL(smp_call_function); |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * smp_call_function_single - Run a function on another CPU | 50 | * smp_call_function_single - Run a function on a specific CPU |
51 | * @cpu: The target CPU. Cannot be the calling CPU. | 51 | * @cpu: The target CPU. Cannot be the calling CPU. |
52 | * @func: The function to run. This must be fast and non-blocking. | 52 | * @func: The function to run. This must be fast and non-blocking. |
53 | * @info: An arbitrary pointer to pass to the function. | 53 | * @info: An arbitrary pointer to pass to the function. |
@@ -66,9 +66,11 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
66 | int ret; | 66 | int ret; |
67 | int me = get_cpu(); | 67 | int me = get_cpu(); |
68 | if (cpu == me) { | 68 | if (cpu == me) { |
69 | WARN_ON(1); | 69 | local_irq_disable(); |
70 | func(info); | ||
71 | local_irq_enable(); | ||
70 | put_cpu(); | 72 | put_cpu(); |
71 | return -EBUSY; | 73 | return 0; |
72 | } | 74 | } |
73 | 75 | ||
74 | ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); | 76 | ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); |
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index bf6adce52267..8344c70adf61 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
@@ -323,3 +323,4 @@ ENTRY(sys_call_table) | |||
323 | .long sys_signalfd | 323 | .long sys_signalfd |
324 | .long sys_timerfd | 324 | .long sys_timerfd |
325 | .long sys_eventfd | 325 | .long sys_eventfd |
326 | .long sys_fallocate | ||
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 28bd1c5163ec..3e7753c78b9b 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -41,6 +41,10 @@ | |||
41 | #include <linux/mca.h> | 41 | #include <linux/mca.h> |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #if defined(CONFIG_EDAC) | ||
45 | #include <linux/edac.h> | ||
46 | #endif | ||
47 | |||
44 | #include <asm/processor.h> | 48 | #include <asm/processor.h> |
45 | #include <asm/system.h> | 49 | #include <asm/system.h> |
46 | #include <asm/io.h> | 50 | #include <asm/io.h> |
@@ -433,6 +437,7 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
433 | 437 | ||
434 | bust_spinlocks(0); | 438 | bust_spinlocks(0); |
435 | die.lock_owner = -1; | 439 | die.lock_owner = -1; |
440 | add_taint(TAINT_DIE); | ||
436 | spin_unlock_irqrestore(&die.lock, flags); | 441 | spin_unlock_irqrestore(&die.lock, flags); |
437 | 442 | ||
438 | if (!regs) | 443 | if (!regs) |
@@ -517,10 +522,12 @@ fastcall void do_##name(struct pt_regs * regs, long error_code) \ | |||
517 | do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ | 522 | do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ |
518 | } | 523 | } |
519 | 524 | ||
520 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | 525 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \ |
521 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ | 526 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ |
522 | { \ | 527 | { \ |
523 | siginfo_t info; \ | 528 | siginfo_t info; \ |
529 | if (irq) \ | ||
530 | local_irq_enable(); \ | ||
524 | info.si_signo = signr; \ | 531 | info.si_signo = signr; \ |
525 | info.si_errno = 0; \ | 532 | info.si_errno = 0; \ |
526 | info.si_code = sicode; \ | 533 | info.si_code = sicode; \ |
@@ -560,13 +567,13 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) | |||
560 | #endif | 567 | #endif |
561 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) | 568 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) |
562 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) | 569 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) |
563 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip) | 570 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip, 0) |
564 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | 571 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) |
565 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | 572 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) |
566 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | 573 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) |
567 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) | 574 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) |
568 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) | 575 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0) |
569 | DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0) | 576 | DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1) |
570 | 577 | ||
571 | fastcall void __kprobes do_general_protection(struct pt_regs * regs, | 578 | fastcall void __kprobes do_general_protection(struct pt_regs * regs, |
572 | long error_code) | 579 | long error_code) |
@@ -635,6 +642,14 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs) | |||
635 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " | 642 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " |
636 | "CPU %d.\n", reason, smp_processor_id()); | 643 | "CPU %d.\n", reason, smp_processor_id()); |
637 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); | 644 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); |
645 | |||
646 | #if defined(CONFIG_EDAC) | ||
647 | if(edac_handler_set()) { | ||
648 | edac_atomic_assert_error(); | ||
649 | return; | ||
650 | } | ||
651 | #endif | ||
652 | |||
638 | if (panic_on_unrecovered_nmi) | 653 | if (panic_on_unrecovered_nmi) |
639 | panic("NMI: Not continuing"); | 654 | panic("NMI: Not continuing"); |
640 | 655 | ||
@@ -1053,6 +1068,7 @@ asmlinkage void math_state_restore(void) | |||
1053 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ | 1068 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ |
1054 | tsk->fpu_counter++; | 1069 | tsk->fpu_counter++; |
1055 | } | 1070 | } |
1071 | EXPORT_SYMBOL_GPL(math_state_restore); | ||
1056 | 1072 | ||
1057 | #ifndef CONFIG_MATH_EMULATION | 1073 | #ifndef CONFIG_MATH_EMULATION |
1058 | 1074 | ||
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c index ea63a30ca3e8..debd7dbb4158 100644 --- a/arch/i386/kernel/tsc.c +++ b/arch/i386/kernel/tsc.c | |||
@@ -27,6 +27,7 @@ static int tsc_enabled; | |||
27 | * an extra value to store the TSC freq | 27 | * an extra value to store the TSC freq |
28 | */ | 28 | */ |
29 | unsigned int tsc_khz; | 29 | unsigned int tsc_khz; |
30 | EXPORT_SYMBOL_GPL(tsc_khz); | ||
30 | 31 | ||
31 | int tsc_disable; | 32 | int tsc_disable; |
32 | 33 | ||
@@ -58,10 +59,11 @@ __setup("notsc", tsc_setup); | |||
58 | */ | 59 | */ |
59 | static int tsc_unstable; | 60 | static int tsc_unstable; |
60 | 61 | ||
61 | static inline int check_tsc_unstable(void) | 62 | int check_tsc_unstable(void) |
62 | { | 63 | { |
63 | return tsc_unstable; | 64 | return tsc_unstable; |
64 | } | 65 | } |
66 | EXPORT_SYMBOL_GPL(check_tsc_unstable); | ||
65 | 67 | ||
66 | /* Accellerators for sched_clock() | 68 | /* Accellerators for sched_clock() |
67 | * convert from cycles(64bits) => nanoseconds (64bits) | 69 | * convert from cycles(64bits) => nanoseconds (64bits) |
@@ -84,7 +86,7 @@ static inline int check_tsc_unstable(void) | |||
84 | * | 86 | * |
85 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | 87 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" |
86 | */ | 88 | */ |
87 | static unsigned long cyc2ns_scale __read_mostly; | 89 | unsigned long cyc2ns_scale __read_mostly; |
88 | 90 | ||
89 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ | 91 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ |
90 | 92 | ||
@@ -93,15 +95,10 @@ static inline void set_cyc2ns_scale(unsigned long cpu_khz) | |||
93 | cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; | 95 | cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; |
94 | } | 96 | } |
95 | 97 | ||
96 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | ||
97 | { | ||
98 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; | ||
99 | } | ||
100 | |||
101 | /* | 98 | /* |
102 | * Scheduler clock - returns current time in nanosec units. | 99 | * Scheduler clock - returns current time in nanosec units. |
103 | */ | 100 | */ |
104 | unsigned long long sched_clock(void) | 101 | unsigned long long native_sched_clock(void) |
105 | { | 102 | { |
106 | unsigned long long this_offset; | 103 | unsigned long long this_offset; |
107 | 104 | ||
@@ -118,12 +115,24 @@ unsigned long long sched_clock(void) | |||
118 | return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); | 115 | return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); |
119 | 116 | ||
120 | /* read the Time Stamp Counter: */ | 117 | /* read the Time Stamp Counter: */ |
121 | get_scheduled_cycles(this_offset); | 118 | rdtscll(this_offset); |
122 | 119 | ||
123 | /* return the value in ns */ | 120 | /* return the value in ns */ |
124 | return cycles_2_ns(this_offset); | 121 | return cycles_2_ns(this_offset); |
125 | } | 122 | } |
126 | 123 | ||
124 | /* We need to define a real function for sched_clock, to override the | ||
125 | weak default version */ | ||
126 | #ifdef CONFIG_PARAVIRT | ||
127 | unsigned long long sched_clock(void) | ||
128 | { | ||
129 | return paravirt_sched_clock(); | ||
130 | } | ||
131 | #else | ||
132 | unsigned long long sched_clock(void) | ||
133 | __attribute__((alias("native_sched_clock"))); | ||
134 | #endif | ||
135 | |||
127 | unsigned long native_calculate_cpu_khz(void) | 136 | unsigned long native_calculate_cpu_khz(void) |
128 | { | 137 | { |
129 | unsigned long long start, end; | 138 | unsigned long long start, end; |
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c index c12720d7cbc5..72042bb7ec94 100644 --- a/arch/i386/kernel/vmi.c +++ b/arch/i386/kernel/vmi.c | |||
@@ -362,7 +362,7 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type) | |||
362 | } | 362 | } |
363 | #endif | 363 | #endif |
364 | 364 | ||
365 | static void vmi_allocate_pt(u32 pfn) | 365 | static void vmi_allocate_pt(struct mm_struct *mm, u32 pfn) |
366 | { | 366 | { |
367 | vmi_set_page_type(pfn, VMI_PAGE_L1); | 367 | vmi_set_page_type(pfn, VMI_PAGE_L1); |
368 | vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0); | 368 | vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0); |
@@ -891,7 +891,7 @@ static inline int __init activate_vmi(void) | |||
891 | paravirt_ops.setup_boot_clock = vmi_time_bsp_init; | 891 | paravirt_ops.setup_boot_clock = vmi_time_bsp_init; |
892 | paravirt_ops.setup_secondary_clock = vmi_time_ap_init; | 892 | paravirt_ops.setup_secondary_clock = vmi_time_ap_init; |
893 | #endif | 893 | #endif |
894 | paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles; | 894 | paravirt_ops.sched_clock = vmi_sched_clock; |
895 | paravirt_ops.get_cpu_khz = vmi_cpu_khz; | 895 | paravirt_ops.get_cpu_khz = vmi_cpu_khz; |
896 | 896 | ||
897 | /* We have true wallclock functions; disable CMOS clock sync */ | 897 | /* We have true wallclock functions; disable CMOS clock sync */ |
diff --git a/arch/i386/kernel/vmiclock.c b/arch/i386/kernel/vmiclock.c index 26a37f8a8762..f9b845f4e692 100644 --- a/arch/i386/kernel/vmiclock.c +++ b/arch/i386/kernel/vmiclock.c | |||
@@ -64,10 +64,10 @@ int vmi_set_wallclock(unsigned long now) | |||
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | /* paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles */ | 67 | /* paravirt_ops.sched_clock = vmi_sched_clock */ |
68 | unsigned long long vmi_get_sched_cycles(void) | 68 | unsigned long long vmi_sched_clock(void) |
69 | { | 69 | { |
70 | return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE); | 70 | return cycles_2_ns(vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE)); |
71 | } | 71 | } |
72 | 72 | ||
73 | /* paravirt_ops.get_cpu_khz = vmi_cpu_khz */ | 73 | /* paravirt_ops.get_cpu_khz = vmi_cpu_khz */ |
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index aa87b06c7c82..7d72cce00529 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S | |||
@@ -60,7 +60,9 @@ SECTIONS | |||
60 | __stop___ex_table = .; | 60 | __stop___ex_table = .; |
61 | } | 61 | } |
62 | 62 | ||
63 | BUG_TABLE | 63 | NOTES :text :note |
64 | |||
65 | BUG_TABLE :text | ||
64 | 66 | ||
65 | . = ALIGN(4); | 67 | . = ALIGN(4); |
66 | .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { | 68 | .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { |
@@ -88,6 +90,7 @@ SECTIONS | |||
88 | 90 | ||
89 | . = ALIGN(4096); | 91 | . = ALIGN(4096); |
90 | .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { | 92 | .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { |
93 | *(.data.page_aligned) | ||
91 | *(.data.idt) | 94 | *(.data.idt) |
92 | } | 95 | } |
93 | 96 | ||
@@ -180,6 +183,7 @@ SECTIONS | |||
180 | .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { | 183 | .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { |
181 | __per_cpu_start = .; | 184 | __per_cpu_start = .; |
182 | *(.data.percpu) | 185 | *(.data.percpu) |
186 | *(.data.percpu.shared_aligned) | ||
183 | __per_cpu_end = .; | 187 | __per_cpu_end = .; |
184 | } | 188 | } |
185 | . = ALIGN(4096); | 189 | . = ALIGN(4096); |
@@ -206,6 +210,4 @@ SECTIONS | |||
206 | STABS_DEBUG | 210 | STABS_DEBUG |
207 | 211 | ||
208 | DWARF_DEBUG | 212 | DWARF_DEBUG |
209 | |||
210 | NOTES | ||
211 | } | 213 | } |
diff --git a/arch/i386/kernel/vsyscall-note.S b/arch/i386/kernel/vsyscall-note.S index d4b5be4f3d5f..271f16a8ca01 100644 --- a/arch/i386/kernel/vsyscall-note.S +++ b/arch/i386/kernel/vsyscall-note.S | |||
@@ -3,23 +3,40 @@ | |||
3 | * Here we can supply some information useful to userland. | 3 | * Here we can supply some information useful to userland. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/uts.h> | ||
7 | #include <linux/version.h> | 6 | #include <linux/version.h> |
7 | #include <linux/elfnote.h> | ||
8 | 8 | ||
9 | #define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \ | 9 | /* Ideally this would use UTS_NAME, but using a quoted string here |
10 | .section name, flags; \ | 10 | doesn't work. Remember to change this when changing the |
11 | .balign 4; \ | 11 | kernel's name. */ |
12 | .long 1f - 0f; /* name length */ \ | 12 | ELFNOTE_START(Linux, 0, "a") |
13 | .long 3f - 2f; /* data length */ \ | 13 | .long LINUX_VERSION_CODE |
14 | .long type; /* note type */ \ | 14 | ELFNOTE_END |
15 | 0: .asciz vendor; /* vendor name */ \ | ||
16 | 1: .balign 4; \ | ||
17 | 2: | ||
18 | 15 | ||
19 | #define ASM_ELF_NOTE_END \ | 16 | #ifdef CONFIG_XEN |
20 | 3: .balign 4; /* pad out section */ \ | ||
21 | .previous | ||
22 | 17 | ||
23 | ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0) | 18 | /* |
24 | .long LINUX_VERSION_CODE | 19 | * Add a special note telling glibc's dynamic linker a fake hardware |
25 | ASM_ELF_NOTE_END | 20 | * flavor that it will use to choose the search path for libraries in the |
21 | * same way it uses real hardware capabilities like "mmx". | ||
22 | * We supply "nosegneg" as the fake capability, to indicate that we | ||
23 | * do not like negative offsets in instructions using segment overrides, | ||
24 | * since we implement those inefficiently. This makes it possible to | ||
25 | * install libraries optimized to avoid those access patterns in someplace | ||
26 | * like /lib/i686/tls/nosegneg. Note that an /etc/ld.so.conf.d/file | ||
27 | * corresponding to the bits here is needed to make ldconfig work right. | ||
28 | * It should contain: | ||
29 | * hwcap 1 nosegneg | ||
30 | * to match the mapping of bit to name that we give here. | ||
31 | */ | ||
32 | |||
33 | /* Bit used for the pseudo-hwcap for non-negative segments. We use | ||
34 | bit 1 to avoid bugs in some versions of glibc when bit 0 is | ||
35 | used; the choice is otherwise arbitrary. */ | ||
36 | #define VDSO_NOTE_NONEGSEG_BIT 1 | ||
37 | |||
38 | ELFNOTE_START(GNU, 2, "a") | ||
39 | .long 1, 1<<VDSO_NOTE_NONEGSEG_BIT /* ncaps, mask */ | ||
40 | .byte VDSO_NOTE_NONEGSEG_BIT; .asciz "nosegneg" /* bit, name */ | ||
41 | ELFNOTE_END | ||
42 | #endif | ||
diff --git a/arch/i386/mach-voyager/voyager_thread.c b/arch/i386/mach-voyager/voyager_thread.c index b4b24e0e45e1..f9d595338159 100644 --- a/arch/i386/mach-voyager/voyager_thread.c +++ b/arch/i386/mach-voyager/voyager_thread.c | |||
@@ -52,7 +52,7 @@ execute(const char *string) | |||
52 | NULL, | 52 | NULL, |
53 | }; | 53 | }; |
54 | 54 | ||
55 | if ((ret = call_usermodehelper(argv[0], argv, envp, 1)) != 0) { | 55 | if ((ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) { |
56 | printk(KERN_ERR "Voyager failed to run \"%s\": %i\n", | 56 | printk(KERN_ERR "Voyager failed to run \"%s\": %i\n", |
57 | string, ret); | 57 | string, ret); |
58 | } | 58 | } |
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 1ecb3e43b523..e92a10124935 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c | |||
@@ -303,6 +303,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs, | |||
303 | struct vm_area_struct * vma; | 303 | struct vm_area_struct * vma; |
304 | unsigned long address; | 304 | unsigned long address; |
305 | int write, si_code; | 305 | int write, si_code; |
306 | int fault; | ||
306 | 307 | ||
307 | /* get the address */ | 308 | /* get the address */ |
308 | address = read_cr2(); | 309 | address = read_cr2(); |
@@ -422,20 +423,18 @@ good_area: | |||
422 | * make sure we exit gracefully rather than endlessly redo | 423 | * make sure we exit gracefully rather than endlessly redo |
423 | * the fault. | 424 | * the fault. |
424 | */ | 425 | */ |
425 | switch (handle_mm_fault(mm, vma, address, write)) { | 426 | fault = handle_mm_fault(mm, vma, address, write); |
426 | case VM_FAULT_MINOR: | 427 | if (unlikely(fault & VM_FAULT_ERROR)) { |
427 | tsk->min_flt++; | 428 | if (fault & VM_FAULT_OOM) |
428 | break; | ||
429 | case VM_FAULT_MAJOR: | ||
430 | tsk->maj_flt++; | ||
431 | break; | ||
432 | case VM_FAULT_SIGBUS: | ||
433 | goto do_sigbus; | ||
434 | case VM_FAULT_OOM: | ||
435 | goto out_of_memory; | 429 | goto out_of_memory; |
436 | default: | 430 | else if (fault & VM_FAULT_SIGBUS) |
437 | BUG(); | 431 | goto do_sigbus; |
432 | BUG(); | ||
438 | } | 433 | } |
434 | if (fault & VM_FAULT_MAJOR) | ||
435 | tsk->maj_flt++; | ||
436 | else | ||
437 | tsk->min_flt++; | ||
439 | 438 | ||
440 | /* | 439 | /* |
441 | * Did it hit the DOS screen memory VA from vm86 mode? | 440 | * Did it hit the DOS screen memory VA from vm86 mode? |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 7135946d3663..6a68b1ae061c 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -87,7 +87,7 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) | |||
87 | if (!(pmd_val(*pmd) & _PAGE_PRESENT)) { | 87 | if (!(pmd_val(*pmd) & _PAGE_PRESENT)) { |
88 | pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); | 88 | pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); |
89 | 89 | ||
90 | paravirt_alloc_pt(__pa(page_table) >> PAGE_SHIFT); | 90 | paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT); |
91 | set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); | 91 | set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); |
92 | BUG_ON(page_table != pte_offset_kernel(pmd, 0)); | 92 | BUG_ON(page_table != pte_offset_kernel(pmd, 0)); |
93 | } | 93 | } |
@@ -473,6 +473,7 @@ void zap_low_mappings (void) | |||
473 | 473 | ||
474 | static int disable_nx __initdata = 0; | 474 | static int disable_nx __initdata = 0; |
475 | u64 __supported_pte_mask __read_mostly = ~_PAGE_NX; | 475 | u64 __supported_pte_mask __read_mostly = ~_PAGE_NX; |
476 | EXPORT_SYMBOL_GPL(__supported_pte_mask); | ||
476 | 477 | ||
477 | /* | 478 | /* |
478 | * noexec = on|off | 479 | * noexec = on|off |
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index 2eb14a73be9c..37992ffb1633 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c | |||
@@ -60,7 +60,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, | |||
60 | address = __pa(address); | 60 | address = __pa(address); |
61 | addr = address & LARGE_PAGE_MASK; | 61 | addr = address & LARGE_PAGE_MASK; |
62 | pbase = (pte_t *)page_address(base); | 62 | pbase = (pte_t *)page_address(base); |
63 | paravirt_alloc_pt(page_to_pfn(base)); | 63 | paravirt_alloc_pt(&init_mm, page_to_pfn(base)); |
64 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { | 64 | for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { |
65 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, | 65 | set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, |
66 | addr == address ? prot : ref_prot)); | 66 | addr == address ? prot : ref_prot)); |
diff --git a/arch/i386/video/Makefile b/arch/i386/video/Makefile new file mode 100644 index 000000000000..2c447c94adcc --- /dev/null +++ b/arch/i386/video/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_FB) += fbdev.o | |||
diff --git a/arch/i386/video/fbdev.c b/arch/i386/video/fbdev.c new file mode 100644 index 000000000000..48fb38d7d2c0 --- /dev/null +++ b/arch/i386/video/fbdev.c | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * arch/i386/video/fbdev.c - i386 Framebuffer | ||
3 | * | ||
4 | * Copyright (C) 2007 Antonino Daplas <adaplas@gmail.com> | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive | ||
8 | * for more details. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/fb.h> | ||
12 | #include <linux/pci.h> | ||
13 | |||
14 | int fb_is_primary_device(struct fb_info *info) | ||
15 | { | ||
16 | struct device *device = info->device; | ||
17 | struct pci_dev *pci_dev = NULL; | ||
18 | struct resource *res = NULL; | ||
19 | int retval = 0; | ||
20 | |||
21 | if (device) | ||
22 | pci_dev = to_pci_dev(device); | ||
23 | |||
24 | if (pci_dev) | ||
25 | res = &pci_dev->resource[PCI_ROM_RESOURCE]; | ||
26 | |||
27 | if (res && res->flags & IORESOURCE_ROM_SHADOW) | ||
28 | retval = 1; | ||
29 | |||
30 | return retval; | ||
31 | } | ||
32 | EXPORT_SYMBOL(fb_is_primary_device); | ||
diff --git a/arch/i386/xen/Kconfig b/arch/i386/xen/Kconfig new file mode 100644 index 000000000000..9df99e1885a4 --- /dev/null +++ b/arch/i386/xen/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # This Kconfig describes xen options | ||
3 | # | ||
4 | |||
5 | config XEN | ||
6 | bool "Enable support for Xen hypervisor" | ||
7 | depends on PARAVIRT && X86_CMPXCHG && X86_TSC && !NEED_MULTIPLE_NODES | ||
8 | help | ||
9 | This is the Linux Xen port. Enabling this will allow the | ||
10 | kernel to boot in a paravirtualized environment under the | ||
11 | Xen hypervisor. | ||
diff --git a/arch/i386/xen/Makefile b/arch/i386/xen/Makefile new file mode 100644 index 000000000000..343df246bd3e --- /dev/null +++ b/arch/i386/xen/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | obj-y := enlighten.o setup.o features.o multicalls.o mmu.o \ | ||
2 | events.o time.o manage.o xen-asm.o | ||
3 | |||
4 | obj-$(CONFIG_SMP) += smp.o | ||
diff --git a/arch/i386/xen/enlighten.c b/arch/i386/xen/enlighten.c new file mode 100644 index 000000000000..9a8c1181c001 --- /dev/null +++ b/arch/i386/xen/enlighten.c | |||
@@ -0,0 +1,1144 @@ | |||
1 | /* | ||
2 | * Core of Xen paravirt_ops implementation. | ||
3 | * | ||
4 | * This file contains the xen_paravirt_ops structure itself, and the | ||
5 | * implementations for: | ||
6 | * - privileged instructions | ||
7 | * - interrupt flags | ||
8 | * - segment operations | ||
9 | * - booting and setup | ||
10 | * | ||
11 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/smp.h> | ||
17 | #include <linux/preempt.h> | ||
18 | #include <linux/hardirq.h> | ||
19 | #include <linux/percpu.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/start_kernel.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/bootmem.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <linux/page-flags.h> | ||
27 | #include <linux/highmem.h> | ||
28 | #include <linux/smp.h> | ||
29 | |||
30 | #include <xen/interface/xen.h> | ||
31 | #include <xen/interface/physdev.h> | ||
32 | #include <xen/interface/vcpu.h> | ||
33 | #include <xen/interface/sched.h> | ||
34 | #include <xen/features.h> | ||
35 | #include <xen/page.h> | ||
36 | |||
37 | #include <asm/paravirt.h> | ||
38 | #include <asm/page.h> | ||
39 | #include <asm/xen/hypercall.h> | ||
40 | #include <asm/xen/hypervisor.h> | ||
41 | #include <asm/fixmap.h> | ||
42 | #include <asm/processor.h> | ||
43 | #include <asm/setup.h> | ||
44 | #include <asm/desc.h> | ||
45 | #include <asm/pgtable.h> | ||
46 | #include <asm/tlbflush.h> | ||
47 | #include <asm/reboot.h> | ||
48 | |||
49 | #include "xen-ops.h" | ||
50 | #include "mmu.h" | ||
51 | #include "multicalls.h" | ||
52 | |||
53 | EXPORT_SYMBOL_GPL(hypercall_page); | ||
54 | |||
55 | DEFINE_PER_CPU(enum paravirt_lazy_mode, xen_lazy_mode); | ||
56 | |||
57 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | ||
58 | DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); | ||
59 | DEFINE_PER_CPU(unsigned long, xen_cr3); | ||
60 | |||
61 | struct start_info *xen_start_info; | ||
62 | EXPORT_SYMBOL_GPL(xen_start_info); | ||
63 | |||
64 | static /* __initdata */ struct shared_info dummy_shared_info; | ||
65 | |||
66 | /* | ||
67 | * Point at some empty memory to start with. We map the real shared_info | ||
68 | * page as soon as fixmap is up and running. | ||
69 | */ | ||
70 | struct shared_info *HYPERVISOR_shared_info = (void *)&dummy_shared_info; | ||
71 | |||
72 | /* | ||
73 | * Flag to determine whether vcpu info placement is available on all | ||
74 | * VCPUs. We assume it is to start with, and then set it to zero on | ||
75 | * the first failure. This is because it can succeed on some VCPUs | ||
76 | * and not others, since it can involve hypervisor memory allocation, | ||
77 | * or because the guest failed to guarantee all the appropriate | ||
78 | * constraints on all VCPUs (ie buffer can't cross a page boundary). | ||
79 | * | ||
80 | * Note that any particular CPU may be using a placed vcpu structure, | ||
81 | * but we can only optimise if the all are. | ||
82 | * | ||
83 | * 0: not available, 1: available | ||
84 | */ | ||
85 | static int have_vcpu_info_placement = 1; | ||
86 | |||
87 | static void __init xen_vcpu_setup(int cpu) | ||
88 | { | ||
89 | struct vcpu_register_vcpu_info info; | ||
90 | int err; | ||
91 | struct vcpu_info *vcpup; | ||
92 | |||
93 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | ||
94 | |||
95 | if (!have_vcpu_info_placement) | ||
96 | return; /* already tested, not available */ | ||
97 | |||
98 | vcpup = &per_cpu(xen_vcpu_info, cpu); | ||
99 | |||
100 | info.mfn = virt_to_mfn(vcpup); | ||
101 | info.offset = offset_in_page(vcpup); | ||
102 | |||
103 | printk(KERN_DEBUG "trying to map vcpu_info %d at %p, mfn %x, offset %d\n", | ||
104 | cpu, vcpup, info.mfn, info.offset); | ||
105 | |||
106 | /* Check to see if the hypervisor will put the vcpu_info | ||
107 | structure where we want it, which allows direct access via | ||
108 | a percpu-variable. */ | ||
109 | err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); | ||
110 | |||
111 | if (err) { | ||
112 | printk(KERN_DEBUG "register_vcpu_info failed: err=%d\n", err); | ||
113 | have_vcpu_info_placement = 0; | ||
114 | } else { | ||
115 | /* This cpu is using the registered vcpu info, even if | ||
116 | later ones fail to. */ | ||
117 | per_cpu(xen_vcpu, cpu) = vcpup; | ||
118 | |||
119 | printk(KERN_DEBUG "cpu %d using vcpu_info at %p\n", | ||
120 | cpu, vcpup); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static void __init xen_banner(void) | ||
125 | { | ||
126 | printk(KERN_INFO "Booting paravirtualized kernel on %s\n", | ||
127 | paravirt_ops.name); | ||
128 | printk(KERN_INFO "Hypervisor signature: %s\n", xen_start_info->magic); | ||
129 | } | ||
130 | |||
131 | static void xen_cpuid(unsigned int *eax, unsigned int *ebx, | ||
132 | unsigned int *ecx, unsigned int *edx) | ||
133 | { | ||
134 | unsigned maskedx = ~0; | ||
135 | |||
136 | /* | ||
137 | * Mask out inconvenient features, to try and disable as many | ||
138 | * unsupported kernel subsystems as possible. | ||
139 | */ | ||
140 | if (*eax == 1) | ||
141 | maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */ | ||
142 | (1 << X86_FEATURE_ACPI) | /* disable ACPI */ | ||
143 | (1 << X86_FEATURE_ACC)); /* thermal monitoring */ | ||
144 | |||
145 | asm(XEN_EMULATE_PREFIX "cpuid" | ||
146 | : "=a" (*eax), | ||
147 | "=b" (*ebx), | ||
148 | "=c" (*ecx), | ||
149 | "=d" (*edx) | ||
150 | : "0" (*eax), "2" (*ecx)); | ||
151 | *edx &= maskedx; | ||
152 | } | ||
153 | |||
154 | static void xen_set_debugreg(int reg, unsigned long val) | ||
155 | { | ||
156 | HYPERVISOR_set_debugreg(reg, val); | ||
157 | } | ||
158 | |||
159 | static unsigned long xen_get_debugreg(int reg) | ||
160 | { | ||
161 | return HYPERVISOR_get_debugreg(reg); | ||
162 | } | ||
163 | |||
164 | static unsigned long xen_save_fl(void) | ||
165 | { | ||
166 | struct vcpu_info *vcpu; | ||
167 | unsigned long flags; | ||
168 | |||
169 | vcpu = x86_read_percpu(xen_vcpu); | ||
170 | |||
171 | /* flag has opposite sense of mask */ | ||
172 | flags = !vcpu->evtchn_upcall_mask; | ||
173 | |||
174 | /* convert to IF type flag | ||
175 | -0 -> 0x00000000 | ||
176 | -1 -> 0xffffffff | ||
177 | */ | ||
178 | return (-flags) & X86_EFLAGS_IF; | ||
179 | } | ||
180 | |||
181 | static void xen_restore_fl(unsigned long flags) | ||
182 | { | ||
183 | struct vcpu_info *vcpu; | ||
184 | |||
185 | /* convert from IF type flag */ | ||
186 | flags = !(flags & X86_EFLAGS_IF); | ||
187 | |||
188 | /* There's a one instruction preempt window here. We need to | ||
189 | make sure we're don't switch CPUs between getting the vcpu | ||
190 | pointer and updating the mask. */ | ||
191 | preempt_disable(); | ||
192 | vcpu = x86_read_percpu(xen_vcpu); | ||
193 | vcpu->evtchn_upcall_mask = flags; | ||
194 | preempt_enable_no_resched(); | ||
195 | |||
196 | /* Doesn't matter if we get preempted here, because any | ||
197 | pending event will get dealt with anyway. */ | ||
198 | |||
199 | if (flags == 0) { | ||
200 | preempt_check_resched(); | ||
201 | barrier(); /* unmask then check (avoid races) */ | ||
202 | if (unlikely(vcpu->evtchn_upcall_pending)) | ||
203 | force_evtchn_callback(); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void xen_irq_disable(void) | ||
208 | { | ||
209 | /* There's a one instruction preempt window here. We need to | ||
210 | make sure we're don't switch CPUs between getting the vcpu | ||
211 | pointer and updating the mask. */ | ||
212 | preempt_disable(); | ||
213 | x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; | ||
214 | preempt_enable_no_resched(); | ||
215 | } | ||
216 | |||
217 | static void xen_irq_enable(void) | ||
218 | { | ||
219 | struct vcpu_info *vcpu; | ||
220 | |||
221 | /* There's a one instruction preempt window here. We need to | ||
222 | make sure we're don't switch CPUs between getting the vcpu | ||
223 | pointer and updating the mask. */ | ||
224 | preempt_disable(); | ||
225 | vcpu = x86_read_percpu(xen_vcpu); | ||
226 | vcpu->evtchn_upcall_mask = 0; | ||
227 | preempt_enable_no_resched(); | ||
228 | |||
229 | /* Doesn't matter if we get preempted here, because any | ||
230 | pending event will get dealt with anyway. */ | ||
231 | |||
232 | barrier(); /* unmask then check (avoid races) */ | ||
233 | if (unlikely(vcpu->evtchn_upcall_pending)) | ||
234 | force_evtchn_callback(); | ||
235 | } | ||
236 | |||
237 | static void xen_safe_halt(void) | ||
238 | { | ||
239 | /* Blocking includes an implicit local_irq_enable(). */ | ||
240 | if (HYPERVISOR_sched_op(SCHEDOP_block, 0) != 0) | ||
241 | BUG(); | ||
242 | } | ||
243 | |||
244 | static void xen_halt(void) | ||
245 | { | ||
246 | if (irqs_disabled()) | ||
247 | HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); | ||
248 | else | ||
249 | xen_safe_halt(); | ||
250 | } | ||
251 | |||
252 | static void xen_set_lazy_mode(enum paravirt_lazy_mode mode) | ||
253 | { | ||
254 | BUG_ON(preemptible()); | ||
255 | |||
256 | switch (mode) { | ||
257 | case PARAVIRT_LAZY_NONE: | ||
258 | BUG_ON(x86_read_percpu(xen_lazy_mode) == PARAVIRT_LAZY_NONE); | ||
259 | break; | ||
260 | |||
261 | case PARAVIRT_LAZY_MMU: | ||
262 | case PARAVIRT_LAZY_CPU: | ||
263 | BUG_ON(x86_read_percpu(xen_lazy_mode) != PARAVIRT_LAZY_NONE); | ||
264 | break; | ||
265 | |||
266 | case PARAVIRT_LAZY_FLUSH: | ||
267 | /* flush if necessary, but don't change state */ | ||
268 | if (x86_read_percpu(xen_lazy_mode) != PARAVIRT_LAZY_NONE) | ||
269 | xen_mc_flush(); | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | xen_mc_flush(); | ||
274 | x86_write_percpu(xen_lazy_mode, mode); | ||
275 | } | ||
276 | |||
277 | static unsigned long xen_store_tr(void) | ||
278 | { | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static void xen_set_ldt(const void *addr, unsigned entries) | ||
283 | { | ||
284 | unsigned long linear_addr = (unsigned long)addr; | ||
285 | struct mmuext_op *op; | ||
286 | struct multicall_space mcs = xen_mc_entry(sizeof(*op)); | ||
287 | |||
288 | op = mcs.args; | ||
289 | op->cmd = MMUEXT_SET_LDT; | ||
290 | if (linear_addr) { | ||
291 | /* ldt my be vmalloced, use arbitrary_virt_to_machine */ | ||
292 | xmaddr_t maddr; | ||
293 | maddr = arbitrary_virt_to_machine((unsigned long)addr); | ||
294 | linear_addr = (unsigned long)maddr.maddr; | ||
295 | } | ||
296 | op->arg1.linear_addr = linear_addr; | ||
297 | op->arg2.nr_ents = entries; | ||
298 | |||
299 | MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | ||
300 | |||
301 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
302 | } | ||
303 | |||
304 | static void xen_load_gdt(const struct Xgt_desc_struct *dtr) | ||
305 | { | ||
306 | unsigned long *frames; | ||
307 | unsigned long va = dtr->address; | ||
308 | unsigned int size = dtr->size + 1; | ||
309 | unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; | ||
310 | int f; | ||
311 | struct multicall_space mcs; | ||
312 | |||
313 | /* A GDT can be up to 64k in size, which corresponds to 8192 | ||
314 | 8-byte entries, or 16 4k pages.. */ | ||
315 | |||
316 | BUG_ON(size > 65536); | ||
317 | BUG_ON(va & ~PAGE_MASK); | ||
318 | |||
319 | mcs = xen_mc_entry(sizeof(*frames) * pages); | ||
320 | frames = mcs.args; | ||
321 | |||
322 | for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { | ||
323 | frames[f] = virt_to_mfn(va); | ||
324 | make_lowmem_page_readonly((void *)va); | ||
325 | } | ||
326 | |||
327 | MULTI_set_gdt(mcs.mc, frames, size / sizeof(struct desc_struct)); | ||
328 | |||
329 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
330 | } | ||
331 | |||
332 | static void load_TLS_descriptor(struct thread_struct *t, | ||
333 | unsigned int cpu, unsigned int i) | ||
334 | { | ||
335 | struct desc_struct *gdt = get_cpu_gdt_table(cpu); | ||
336 | xmaddr_t maddr = virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]); | ||
337 | struct multicall_space mc = __xen_mc_entry(0); | ||
338 | |||
339 | MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]); | ||
340 | } | ||
341 | |||
342 | static void xen_load_tls(struct thread_struct *t, unsigned int cpu) | ||
343 | { | ||
344 | xen_mc_batch(); | ||
345 | |||
346 | load_TLS_descriptor(t, cpu, 0); | ||
347 | load_TLS_descriptor(t, cpu, 1); | ||
348 | load_TLS_descriptor(t, cpu, 2); | ||
349 | |||
350 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
351 | |||
352 | /* | ||
353 | * XXX sleazy hack: If we're being called in a lazy-cpu zone, | ||
354 | * it means we're in a context switch, and %gs has just been | ||
355 | * saved. This means we can zero it out to prevent faults on | ||
356 | * exit from the hypervisor if the next process has no %gs. | ||
357 | * Either way, it has been saved, and the new value will get | ||
358 | * loaded properly. This will go away as soon as Xen has been | ||
359 | * modified to not save/restore %gs for normal hypercalls. | ||
360 | */ | ||
361 | if (xen_get_lazy_mode() == PARAVIRT_LAZY_CPU) | ||
362 | loadsegment(gs, 0); | ||
363 | } | ||
364 | |||
365 | static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, | ||
366 | u32 low, u32 high) | ||
367 | { | ||
368 | unsigned long lp = (unsigned long)&dt[entrynum]; | ||
369 | xmaddr_t mach_lp = virt_to_machine(lp); | ||
370 | u64 entry = (u64)high << 32 | low; | ||
371 | |||
372 | preempt_disable(); | ||
373 | |||
374 | xen_mc_flush(); | ||
375 | if (HYPERVISOR_update_descriptor(mach_lp.maddr, entry)) | ||
376 | BUG(); | ||
377 | |||
378 | preempt_enable(); | ||
379 | } | ||
380 | |||
381 | static int cvt_gate_to_trap(int vector, u32 low, u32 high, | ||
382 | struct trap_info *info) | ||
383 | { | ||
384 | u8 type, dpl; | ||
385 | |||
386 | type = (high >> 8) & 0x1f; | ||
387 | dpl = (high >> 13) & 3; | ||
388 | |||
389 | if (type != 0xf && type != 0xe) | ||
390 | return 0; | ||
391 | |||
392 | info->vector = vector; | ||
393 | info->address = (high & 0xffff0000) | (low & 0x0000ffff); | ||
394 | info->cs = low >> 16; | ||
395 | info->flags = dpl; | ||
396 | /* interrupt gates clear IF */ | ||
397 | if (type == 0xe) | ||
398 | info->flags |= 4; | ||
399 | |||
400 | return 1; | ||
401 | } | ||
402 | |||
403 | /* Locations of each CPU's IDT */ | ||
404 | static DEFINE_PER_CPU(struct Xgt_desc_struct, idt_desc); | ||
405 | |||
406 | /* Set an IDT entry. If the entry is part of the current IDT, then | ||
407 | also update Xen. */ | ||
408 | static void xen_write_idt_entry(struct desc_struct *dt, int entrynum, | ||
409 | u32 low, u32 high) | ||
410 | { | ||
411 | unsigned long p = (unsigned long)&dt[entrynum]; | ||
412 | unsigned long start, end; | ||
413 | |||
414 | preempt_disable(); | ||
415 | |||
416 | start = __get_cpu_var(idt_desc).address; | ||
417 | end = start + __get_cpu_var(idt_desc).size + 1; | ||
418 | |||
419 | xen_mc_flush(); | ||
420 | |||
421 | write_dt_entry(dt, entrynum, low, high); | ||
422 | |||
423 | if (p >= start && (p + 8) <= end) { | ||
424 | struct trap_info info[2]; | ||
425 | |||
426 | info[1].address = 0; | ||
427 | |||
428 | if (cvt_gate_to_trap(entrynum, low, high, &info[0])) | ||
429 | if (HYPERVISOR_set_trap_table(info)) | ||
430 | BUG(); | ||
431 | } | ||
432 | |||
433 | preempt_enable(); | ||
434 | } | ||
435 | |||
436 | static void xen_convert_trap_info(const struct Xgt_desc_struct *desc, | ||
437 | struct trap_info *traps) | ||
438 | { | ||
439 | unsigned in, out, count; | ||
440 | |||
441 | count = (desc->size+1) / 8; | ||
442 | BUG_ON(count > 256); | ||
443 | |||
444 | for (in = out = 0; in < count; in++) { | ||
445 | const u32 *entry = (u32 *)(desc->address + in * 8); | ||
446 | |||
447 | if (cvt_gate_to_trap(in, entry[0], entry[1], &traps[out])) | ||
448 | out++; | ||
449 | } | ||
450 | traps[out].address = 0; | ||
451 | } | ||
452 | |||
453 | void xen_copy_trap_info(struct trap_info *traps) | ||
454 | { | ||
455 | const struct Xgt_desc_struct *desc = &__get_cpu_var(idt_desc); | ||
456 | |||
457 | xen_convert_trap_info(desc, traps); | ||
458 | } | ||
459 | |||
460 | /* Load a new IDT into Xen. In principle this can be per-CPU, so we | ||
461 | hold a spinlock to protect the static traps[] array (static because | ||
462 | it avoids allocation, and saves stack space). */ | ||
463 | static void xen_load_idt(const struct Xgt_desc_struct *desc) | ||
464 | { | ||
465 | static DEFINE_SPINLOCK(lock); | ||
466 | static struct trap_info traps[257]; | ||
467 | |||
468 | spin_lock(&lock); | ||
469 | |||
470 | __get_cpu_var(idt_desc) = *desc; | ||
471 | |||
472 | xen_convert_trap_info(desc, traps); | ||
473 | |||
474 | xen_mc_flush(); | ||
475 | if (HYPERVISOR_set_trap_table(traps)) | ||
476 | BUG(); | ||
477 | |||
478 | spin_unlock(&lock); | ||
479 | } | ||
480 | |||
481 | /* Write a GDT descriptor entry. Ignore LDT descriptors, since | ||
482 | they're handled differently. */ | ||
483 | static void xen_write_gdt_entry(struct desc_struct *dt, int entry, | ||
484 | u32 low, u32 high) | ||
485 | { | ||
486 | preempt_disable(); | ||
487 | |||
488 | switch ((high >> 8) & 0xff) { | ||
489 | case DESCTYPE_LDT: | ||
490 | case DESCTYPE_TSS: | ||
491 | /* ignore */ | ||
492 | break; | ||
493 | |||
494 | default: { | ||
495 | xmaddr_t maddr = virt_to_machine(&dt[entry]); | ||
496 | u64 desc = (u64)high << 32 | low; | ||
497 | |||
498 | xen_mc_flush(); | ||
499 | if (HYPERVISOR_update_descriptor(maddr.maddr, desc)) | ||
500 | BUG(); | ||
501 | } | ||
502 | |||
503 | } | ||
504 | |||
505 | preempt_enable(); | ||
506 | } | ||
507 | |||
508 | static void xen_load_esp0(struct tss_struct *tss, | ||
509 | struct thread_struct *thread) | ||
510 | { | ||
511 | struct multicall_space mcs = xen_mc_entry(0); | ||
512 | MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->esp0); | ||
513 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
514 | } | ||
515 | |||
516 | static void xen_set_iopl_mask(unsigned mask) | ||
517 | { | ||
518 | struct physdev_set_iopl set_iopl; | ||
519 | |||
520 | /* Force the change at ring 0. */ | ||
521 | set_iopl.iopl = (mask == 0) ? 1 : (mask >> 12) & 3; | ||
522 | HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); | ||
523 | } | ||
524 | |||
525 | static void xen_io_delay(void) | ||
526 | { | ||
527 | } | ||
528 | |||
529 | #ifdef CONFIG_X86_LOCAL_APIC | ||
530 | static unsigned long xen_apic_read(unsigned long reg) | ||
531 | { | ||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static void xen_apic_write(unsigned long reg, unsigned long val) | ||
536 | { | ||
537 | /* Warn to see if there's any stray references */ | ||
538 | WARN_ON(1); | ||
539 | } | ||
540 | #endif | ||
541 | |||
542 | static void xen_flush_tlb(void) | ||
543 | { | ||
544 | struct mmuext_op *op; | ||
545 | struct multicall_space mcs = xen_mc_entry(sizeof(*op)); | ||
546 | |||
547 | op = mcs.args; | ||
548 | op->cmd = MMUEXT_TLB_FLUSH_LOCAL; | ||
549 | MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | ||
550 | |||
551 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
552 | } | ||
553 | |||
554 | static void xen_flush_tlb_single(unsigned long addr) | ||
555 | { | ||
556 | struct mmuext_op *op; | ||
557 | struct multicall_space mcs = xen_mc_entry(sizeof(*op)); | ||
558 | |||
559 | op = mcs.args; | ||
560 | op->cmd = MMUEXT_INVLPG_LOCAL; | ||
561 | op->arg1.linear_addr = addr & PAGE_MASK; | ||
562 | MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | ||
563 | |||
564 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
565 | } | ||
566 | |||
567 | static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm, | ||
568 | unsigned long va) | ||
569 | { | ||
570 | struct { | ||
571 | struct mmuext_op op; | ||
572 | cpumask_t mask; | ||
573 | } *args; | ||
574 | cpumask_t cpumask = *cpus; | ||
575 | struct multicall_space mcs; | ||
576 | |||
577 | /* | ||
578 | * A couple of (to be removed) sanity checks: | ||
579 | * | ||
580 | * - current CPU must not be in mask | ||
581 | * - mask must exist :) | ||
582 | */ | ||
583 | BUG_ON(cpus_empty(cpumask)); | ||
584 | BUG_ON(cpu_isset(smp_processor_id(), cpumask)); | ||
585 | BUG_ON(!mm); | ||
586 | |||
587 | /* If a CPU which we ran on has gone down, OK. */ | ||
588 | cpus_and(cpumask, cpumask, cpu_online_map); | ||
589 | if (cpus_empty(cpumask)) | ||
590 | return; | ||
591 | |||
592 | mcs = xen_mc_entry(sizeof(*args)); | ||
593 | args = mcs.args; | ||
594 | args->mask = cpumask; | ||
595 | args->op.arg2.vcpumask = &args->mask; | ||
596 | |||
597 | if (va == TLB_FLUSH_ALL) { | ||
598 | args->op.cmd = MMUEXT_TLB_FLUSH_MULTI; | ||
599 | } else { | ||
600 | args->op.cmd = MMUEXT_INVLPG_MULTI; | ||
601 | args->op.arg1.linear_addr = va; | ||
602 | } | ||
603 | |||
604 | MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF); | ||
605 | |||
606 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
607 | } | ||
608 | |||
609 | static void xen_write_cr2(unsigned long cr2) | ||
610 | { | ||
611 | x86_read_percpu(xen_vcpu)->arch.cr2 = cr2; | ||
612 | } | ||
613 | |||
614 | static unsigned long xen_read_cr2(void) | ||
615 | { | ||
616 | return x86_read_percpu(xen_vcpu)->arch.cr2; | ||
617 | } | ||
618 | |||
619 | static unsigned long xen_read_cr2_direct(void) | ||
620 | { | ||
621 | return x86_read_percpu(xen_vcpu_info.arch.cr2); | ||
622 | } | ||
623 | |||
624 | static void xen_write_cr4(unsigned long cr4) | ||
625 | { | ||
626 | /* never allow TSC to be disabled */ | ||
627 | native_write_cr4(cr4 & ~X86_CR4_TSD); | ||
628 | } | ||
629 | |||
630 | static unsigned long xen_read_cr3(void) | ||
631 | { | ||
632 | return x86_read_percpu(xen_cr3); | ||
633 | } | ||
634 | |||
635 | static void xen_write_cr3(unsigned long cr3) | ||
636 | { | ||
637 | BUG_ON(preemptible()); | ||
638 | |||
639 | if (cr3 == x86_read_percpu(xen_cr3)) { | ||
640 | /* just a simple tlb flush */ | ||
641 | xen_flush_tlb(); | ||
642 | return; | ||
643 | } | ||
644 | |||
645 | x86_write_percpu(xen_cr3, cr3); | ||
646 | |||
647 | |||
648 | { | ||
649 | struct mmuext_op *op; | ||
650 | struct multicall_space mcs = xen_mc_entry(sizeof(*op)); | ||
651 | unsigned long mfn = pfn_to_mfn(PFN_DOWN(cr3)); | ||
652 | |||
653 | op = mcs.args; | ||
654 | op->cmd = MMUEXT_NEW_BASEPTR; | ||
655 | op->arg1.mfn = mfn; | ||
656 | |||
657 | MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | ||
658 | |||
659 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | /* Early in boot, while setting up the initial pagetable, assume | ||
664 | everything is pinned. */ | ||
665 | static __init void xen_alloc_pt_init(struct mm_struct *mm, u32 pfn) | ||
666 | { | ||
667 | BUG_ON(mem_map); /* should only be used early */ | ||
668 | make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); | ||
669 | } | ||
670 | |||
671 | /* This needs to make sure the new pte page is pinned iff its being | ||
672 | attached to a pinned pagetable. */ | ||
673 | static void xen_alloc_pt(struct mm_struct *mm, u32 pfn) | ||
674 | { | ||
675 | struct page *page = pfn_to_page(pfn); | ||
676 | |||
677 | if (PagePinned(virt_to_page(mm->pgd))) { | ||
678 | SetPagePinned(page); | ||
679 | |||
680 | if (!PageHighMem(page)) | ||
681 | make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); | ||
682 | else | ||
683 | /* make sure there are no stray mappings of | ||
684 | this page */ | ||
685 | kmap_flush_unused(); | ||
686 | } | ||
687 | } | ||
688 | |||
689 | /* This should never happen until we're OK to use struct page */ | ||
690 | static void xen_release_pt(u32 pfn) | ||
691 | { | ||
692 | struct page *page = pfn_to_page(pfn); | ||
693 | |||
694 | if (PagePinned(page)) { | ||
695 | if (!PageHighMem(page)) | ||
696 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | #ifdef CONFIG_HIGHPTE | ||
701 | static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) | ||
702 | { | ||
703 | pgprot_t prot = PAGE_KERNEL; | ||
704 | |||
705 | if (PagePinned(page)) | ||
706 | prot = PAGE_KERNEL_RO; | ||
707 | |||
708 | if (0 && PageHighMem(page)) | ||
709 | printk("mapping highpte %lx type %d prot %s\n", | ||
710 | page_to_pfn(page), type, | ||
711 | (unsigned long)pgprot_val(prot) & _PAGE_RW ? "WRITE" : "READ"); | ||
712 | |||
713 | return kmap_atomic_prot(page, type, prot); | ||
714 | } | ||
715 | #endif | ||
716 | |||
717 | static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) | ||
718 | { | ||
719 | /* If there's an existing pte, then don't allow _PAGE_RW to be set */ | ||
720 | if (pte_val_ma(*ptep) & _PAGE_PRESENT) | ||
721 | pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & | ||
722 | pte_val_ma(pte)); | ||
723 | |||
724 | return pte; | ||
725 | } | ||
726 | |||
727 | /* Init-time set_pte while constructing initial pagetables, which | ||
728 | doesn't allow RO pagetable pages to be remapped RW */ | ||
729 | static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) | ||
730 | { | ||
731 | pte = mask_rw_pte(ptep, pte); | ||
732 | |||
733 | xen_set_pte(ptep, pte); | ||
734 | } | ||
735 | |||
736 | static __init void xen_pagetable_setup_start(pgd_t *base) | ||
737 | { | ||
738 | pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base; | ||
739 | |||
740 | /* special set_pte for pagetable initialization */ | ||
741 | paravirt_ops.set_pte = xen_set_pte_init; | ||
742 | |||
743 | init_mm.pgd = base; | ||
744 | /* | ||
745 | * copy top-level of Xen-supplied pagetable into place. For | ||
746 | * !PAE we can use this as-is, but for PAE it is a stand-in | ||
747 | * while we copy the pmd pages. | ||
748 | */ | ||
749 | memcpy(base, xen_pgd, PTRS_PER_PGD * sizeof(pgd_t)); | ||
750 | |||
751 | if (PTRS_PER_PMD > 1) { | ||
752 | int i; | ||
753 | /* | ||
754 | * For PAE, need to allocate new pmds, rather than | ||
755 | * share Xen's, since Xen doesn't like pmd's being | ||
756 | * shared between address spaces. | ||
757 | */ | ||
758 | for (i = 0; i < PTRS_PER_PGD; i++) { | ||
759 | if (pgd_val_ma(xen_pgd[i]) & _PAGE_PRESENT) { | ||
760 | pmd_t *pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); | ||
761 | |||
762 | memcpy(pmd, (void *)pgd_page_vaddr(xen_pgd[i]), | ||
763 | PAGE_SIZE); | ||
764 | |||
765 | make_lowmem_page_readonly(pmd); | ||
766 | |||
767 | set_pgd(&base[i], __pgd(1 + __pa(pmd))); | ||
768 | } else | ||
769 | pgd_clear(&base[i]); | ||
770 | } | ||
771 | } | ||
772 | |||
773 | /* make sure zero_page is mapped RO so we can use it in pagetables */ | ||
774 | make_lowmem_page_readonly(empty_zero_page); | ||
775 | make_lowmem_page_readonly(base); | ||
776 | /* | ||
777 | * Switch to new pagetable. This is done before | ||
778 | * pagetable_init has done anything so that the new pages | ||
779 | * added to the table can be prepared properly for Xen. | ||
780 | */ | ||
781 | xen_write_cr3(__pa(base)); | ||
782 | } | ||
783 | |||
784 | static __init void xen_pagetable_setup_done(pgd_t *base) | ||
785 | { | ||
786 | /* This will work as long as patching hasn't happened yet | ||
787 | (which it hasn't) */ | ||
788 | paravirt_ops.alloc_pt = xen_alloc_pt; | ||
789 | paravirt_ops.set_pte = xen_set_pte; | ||
790 | |||
791 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | ||
792 | /* | ||
793 | * Create a mapping for the shared info page. | ||
794 | * Should be set_fixmap(), but shared_info is a machine | ||
795 | * address with no corresponding pseudo-phys address. | ||
796 | */ | ||
797 | set_pte_mfn(fix_to_virt(FIX_PARAVIRT_BOOTMAP), | ||
798 | PFN_DOWN(xen_start_info->shared_info), | ||
799 | PAGE_KERNEL); | ||
800 | |||
801 | HYPERVISOR_shared_info = | ||
802 | (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); | ||
803 | |||
804 | } else | ||
805 | HYPERVISOR_shared_info = | ||
806 | (struct shared_info *)__va(xen_start_info->shared_info); | ||
807 | |||
808 | /* Actually pin the pagetable down, but we can't set PG_pinned | ||
809 | yet because the page structures don't exist yet. */ | ||
810 | { | ||
811 | struct mmuext_op op; | ||
812 | #ifdef CONFIG_X86_PAE | ||
813 | op.cmd = MMUEXT_PIN_L3_TABLE; | ||
814 | #else | ||
815 | op.cmd = MMUEXT_PIN_L3_TABLE; | ||
816 | #endif | ||
817 | op.arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(base))); | ||
818 | if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) | ||
819 | BUG(); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | /* This is called once we have the cpu_possible_map */ | ||
824 | void __init xen_setup_vcpu_info_placement(void) | ||
825 | { | ||
826 | int cpu; | ||
827 | |||
828 | for_each_possible_cpu(cpu) | ||
829 | xen_vcpu_setup(cpu); | ||
830 | |||
831 | /* xen_vcpu_setup managed to place the vcpu_info within the | ||
832 | percpu area for all cpus, so make use of it */ | ||
833 | if (have_vcpu_info_placement) { | ||
834 | printk(KERN_INFO "Xen: using vcpu_info placement\n"); | ||
835 | |||
836 | paravirt_ops.save_fl = xen_save_fl_direct; | ||
837 | paravirt_ops.restore_fl = xen_restore_fl_direct; | ||
838 | paravirt_ops.irq_disable = xen_irq_disable_direct; | ||
839 | paravirt_ops.irq_enable = xen_irq_enable_direct; | ||
840 | paravirt_ops.read_cr2 = xen_read_cr2_direct; | ||
841 | paravirt_ops.iret = xen_iret_direct; | ||
842 | } | ||
843 | } | ||
844 | |||
845 | static unsigned xen_patch(u8 type, u16 clobbers, void *insns, unsigned len) | ||
846 | { | ||
847 | char *start, *end, *reloc; | ||
848 | unsigned ret; | ||
849 | |||
850 | start = end = reloc = NULL; | ||
851 | |||
852 | #define SITE(x) \ | ||
853 | case PARAVIRT_PATCH(x): \ | ||
854 | if (have_vcpu_info_placement) { \ | ||
855 | start = (char *)xen_##x##_direct; \ | ||
856 | end = xen_##x##_direct_end; \ | ||
857 | reloc = xen_##x##_direct_reloc; \ | ||
858 | } \ | ||
859 | goto patch_site | ||
860 | |||
861 | switch (type) { | ||
862 | SITE(irq_enable); | ||
863 | SITE(irq_disable); | ||
864 | SITE(save_fl); | ||
865 | SITE(restore_fl); | ||
866 | #undef SITE | ||
867 | |||
868 | patch_site: | ||
869 | if (start == NULL || (end-start) > len) | ||
870 | goto default_patch; | ||
871 | |||
872 | ret = paravirt_patch_insns(insns, len, start, end); | ||
873 | |||
874 | /* Note: because reloc is assigned from something that | ||
875 | appears to be an array, gcc assumes it's non-null, | ||
876 | but doesn't know its relationship with start and | ||
877 | end. */ | ||
878 | if (reloc > start && reloc < end) { | ||
879 | int reloc_off = reloc - start; | ||
880 | long *relocp = (long *)(insns + reloc_off); | ||
881 | long delta = start - (char *)insns; | ||
882 | |||
883 | *relocp += delta; | ||
884 | } | ||
885 | break; | ||
886 | |||
887 | default_patch: | ||
888 | default: | ||
889 | ret = paravirt_patch_default(type, clobbers, insns, len); | ||
890 | break; | ||
891 | } | ||
892 | |||
893 | return ret; | ||
894 | } | ||
895 | |||
896 | static const struct paravirt_ops xen_paravirt_ops __initdata = { | ||
897 | .paravirt_enabled = 1, | ||
898 | .shared_kernel_pmd = 0, | ||
899 | |||
900 | .name = "Xen", | ||
901 | .banner = xen_banner, | ||
902 | |||
903 | .patch = xen_patch, | ||
904 | |||
905 | .memory_setup = xen_memory_setup, | ||
906 | .arch_setup = xen_arch_setup, | ||
907 | .init_IRQ = xen_init_IRQ, | ||
908 | .post_allocator_init = xen_mark_init_mm_pinned, | ||
909 | |||
910 | .time_init = xen_time_init, | ||
911 | .set_wallclock = xen_set_wallclock, | ||
912 | .get_wallclock = xen_get_wallclock, | ||
913 | .get_cpu_khz = xen_cpu_khz, | ||
914 | .sched_clock = xen_sched_clock, | ||
915 | |||
916 | .cpuid = xen_cpuid, | ||
917 | |||
918 | .set_debugreg = xen_set_debugreg, | ||
919 | .get_debugreg = xen_get_debugreg, | ||
920 | |||
921 | .clts = native_clts, | ||
922 | |||
923 | .read_cr0 = native_read_cr0, | ||
924 | .write_cr0 = native_write_cr0, | ||
925 | |||
926 | .read_cr2 = xen_read_cr2, | ||
927 | .write_cr2 = xen_write_cr2, | ||
928 | |||
929 | .read_cr3 = xen_read_cr3, | ||
930 | .write_cr3 = xen_write_cr3, | ||
931 | |||
932 | .read_cr4 = native_read_cr4, | ||
933 | .read_cr4_safe = native_read_cr4_safe, | ||
934 | .write_cr4 = xen_write_cr4, | ||
935 | |||
936 | .save_fl = xen_save_fl, | ||
937 | .restore_fl = xen_restore_fl, | ||
938 | .irq_disable = xen_irq_disable, | ||
939 | .irq_enable = xen_irq_enable, | ||
940 | .safe_halt = xen_safe_halt, | ||
941 | .halt = xen_halt, | ||
942 | .wbinvd = native_wbinvd, | ||
943 | |||
944 | .read_msr = native_read_msr_safe, | ||
945 | .write_msr = native_write_msr_safe, | ||
946 | .read_tsc = native_read_tsc, | ||
947 | .read_pmc = native_read_pmc, | ||
948 | |||
949 | .iret = (void *)&hypercall_page[__HYPERVISOR_iret], | ||
950 | .irq_enable_sysexit = NULL, /* never called */ | ||
951 | |||
952 | .load_tr_desc = paravirt_nop, | ||
953 | .set_ldt = xen_set_ldt, | ||
954 | .load_gdt = xen_load_gdt, | ||
955 | .load_idt = xen_load_idt, | ||
956 | .load_tls = xen_load_tls, | ||
957 | |||
958 | .store_gdt = native_store_gdt, | ||
959 | .store_idt = native_store_idt, | ||
960 | .store_tr = xen_store_tr, | ||
961 | |||
962 | .write_ldt_entry = xen_write_ldt_entry, | ||
963 | .write_gdt_entry = xen_write_gdt_entry, | ||
964 | .write_idt_entry = xen_write_idt_entry, | ||
965 | .load_esp0 = xen_load_esp0, | ||
966 | |||
967 | .set_iopl_mask = xen_set_iopl_mask, | ||
968 | .io_delay = xen_io_delay, | ||
969 | |||
970 | #ifdef CONFIG_X86_LOCAL_APIC | ||
971 | .apic_write = xen_apic_write, | ||
972 | .apic_write_atomic = xen_apic_write, | ||
973 | .apic_read = xen_apic_read, | ||
974 | .setup_boot_clock = paravirt_nop, | ||
975 | .setup_secondary_clock = paravirt_nop, | ||
976 | .startup_ipi_hook = paravirt_nop, | ||
977 | #endif | ||
978 | |||
979 | .flush_tlb_user = xen_flush_tlb, | ||
980 | .flush_tlb_kernel = xen_flush_tlb, | ||
981 | .flush_tlb_single = xen_flush_tlb_single, | ||
982 | .flush_tlb_others = xen_flush_tlb_others, | ||
983 | |||
984 | .pte_update = paravirt_nop, | ||
985 | .pte_update_defer = paravirt_nop, | ||
986 | |||
987 | .pagetable_setup_start = xen_pagetable_setup_start, | ||
988 | .pagetable_setup_done = xen_pagetable_setup_done, | ||
989 | |||
990 | .alloc_pt = xen_alloc_pt_init, | ||
991 | .release_pt = xen_release_pt, | ||
992 | .alloc_pd = paravirt_nop, | ||
993 | .alloc_pd_clone = paravirt_nop, | ||
994 | .release_pd = paravirt_nop, | ||
995 | |||
996 | #ifdef CONFIG_HIGHPTE | ||
997 | .kmap_atomic_pte = xen_kmap_atomic_pte, | ||
998 | #endif | ||
999 | |||
1000 | .set_pte = NULL, /* see xen_pagetable_setup_* */ | ||
1001 | .set_pte_at = xen_set_pte_at, | ||
1002 | .set_pmd = xen_set_pmd, | ||
1003 | |||
1004 | .pte_val = xen_pte_val, | ||
1005 | .pgd_val = xen_pgd_val, | ||
1006 | |||
1007 | .make_pte = xen_make_pte, | ||
1008 | .make_pgd = xen_make_pgd, | ||
1009 | |||
1010 | #ifdef CONFIG_X86_PAE | ||
1011 | .set_pte_atomic = xen_set_pte_atomic, | ||
1012 | .set_pte_present = xen_set_pte_at, | ||
1013 | .set_pud = xen_set_pud, | ||
1014 | .pte_clear = xen_pte_clear, | ||
1015 | .pmd_clear = xen_pmd_clear, | ||
1016 | |||
1017 | .make_pmd = xen_make_pmd, | ||
1018 | .pmd_val = xen_pmd_val, | ||
1019 | #endif /* PAE */ | ||
1020 | |||
1021 | .activate_mm = xen_activate_mm, | ||
1022 | .dup_mmap = xen_dup_mmap, | ||
1023 | .exit_mmap = xen_exit_mmap, | ||
1024 | |||
1025 | .set_lazy_mode = xen_set_lazy_mode, | ||
1026 | }; | ||
1027 | |||
1028 | #ifdef CONFIG_SMP | ||
1029 | static const struct smp_ops xen_smp_ops __initdata = { | ||
1030 | .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, | ||
1031 | .smp_prepare_cpus = xen_smp_prepare_cpus, | ||
1032 | .cpu_up = xen_cpu_up, | ||
1033 | .smp_cpus_done = xen_smp_cpus_done, | ||
1034 | |||
1035 | .smp_send_stop = xen_smp_send_stop, | ||
1036 | .smp_send_reschedule = xen_smp_send_reschedule, | ||
1037 | .smp_call_function_mask = xen_smp_call_function_mask, | ||
1038 | }; | ||
1039 | #endif /* CONFIG_SMP */ | ||
1040 | |||
1041 | static void xen_reboot(int reason) | ||
1042 | { | ||
1043 | #ifdef CONFIG_SMP | ||
1044 | smp_send_stop(); | ||
1045 | #endif | ||
1046 | |||
1047 | if (HYPERVISOR_sched_op(SCHEDOP_shutdown, reason)) | ||
1048 | BUG(); | ||
1049 | } | ||
1050 | |||
1051 | static void xen_restart(char *msg) | ||
1052 | { | ||
1053 | xen_reboot(SHUTDOWN_reboot); | ||
1054 | } | ||
1055 | |||
1056 | static void xen_emergency_restart(void) | ||
1057 | { | ||
1058 | xen_reboot(SHUTDOWN_reboot); | ||
1059 | } | ||
1060 | |||
1061 | static void xen_machine_halt(void) | ||
1062 | { | ||
1063 | xen_reboot(SHUTDOWN_poweroff); | ||
1064 | } | ||
1065 | |||
1066 | static void xen_crash_shutdown(struct pt_regs *regs) | ||
1067 | { | ||
1068 | xen_reboot(SHUTDOWN_crash); | ||
1069 | } | ||
1070 | |||
1071 | static const struct machine_ops __initdata xen_machine_ops = { | ||
1072 | .restart = xen_restart, | ||
1073 | .halt = xen_machine_halt, | ||
1074 | .power_off = xen_machine_halt, | ||
1075 | .shutdown = xen_machine_halt, | ||
1076 | .crash_shutdown = xen_crash_shutdown, | ||
1077 | .emergency_restart = xen_emergency_restart, | ||
1078 | }; | ||
1079 | |||
1080 | |||
1081 | /* First C function to be called on Xen boot */ | ||
1082 | asmlinkage void __init xen_start_kernel(void) | ||
1083 | { | ||
1084 | pgd_t *pgd; | ||
1085 | |||
1086 | if (!xen_start_info) | ||
1087 | return; | ||
1088 | |||
1089 | BUG_ON(memcmp(xen_start_info->magic, "xen-3.0", 7) != 0); | ||
1090 | |||
1091 | /* Install Xen paravirt ops */ | ||
1092 | paravirt_ops = xen_paravirt_ops; | ||
1093 | machine_ops = xen_machine_ops; | ||
1094 | |||
1095 | #ifdef CONFIG_SMP | ||
1096 | smp_ops = xen_smp_ops; | ||
1097 | #endif | ||
1098 | |||
1099 | xen_setup_features(); | ||
1100 | |||
1101 | /* Get mfn list */ | ||
1102 | if (!xen_feature(XENFEAT_auto_translated_physmap)) | ||
1103 | phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list; | ||
1104 | |||
1105 | pgd = (pgd_t *)xen_start_info->pt_base; | ||
1106 | |||
1107 | init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE; | ||
1108 | |||
1109 | init_mm.pgd = pgd; /* use the Xen pagetables to start */ | ||
1110 | |||
1111 | /* keep using Xen gdt for now; no urgent need to change it */ | ||
1112 | |||
1113 | x86_write_percpu(xen_cr3, __pa(pgd)); | ||
1114 | |||
1115 | #ifdef CONFIG_SMP | ||
1116 | /* Don't do the full vcpu_info placement stuff until we have a | ||
1117 | possible map. */ | ||
1118 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; | ||
1119 | #else | ||
1120 | /* May as well do it now, since there's no good time to call | ||
1121 | it later on UP. */ | ||
1122 | xen_setup_vcpu_info_placement(); | ||
1123 | #endif | ||
1124 | |||
1125 | paravirt_ops.kernel_rpl = 1; | ||
1126 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) | ||
1127 | paravirt_ops.kernel_rpl = 0; | ||
1128 | |||
1129 | /* set the limit of our address space */ | ||
1130 | reserve_top_address(-HYPERVISOR_VIRT_START + 2 * PAGE_SIZE); | ||
1131 | |||
1132 | /* set up basic CPUID stuff */ | ||
1133 | cpu_detect(&new_cpu_data); | ||
1134 | new_cpu_data.hard_math = 1; | ||
1135 | new_cpu_data.x86_capability[0] = cpuid_edx(1); | ||
1136 | |||
1137 | /* Poke various useful things into boot_params */ | ||
1138 | LOADER_TYPE = (9 << 4) | 0; | ||
1139 | INITRD_START = xen_start_info->mod_start ? __pa(xen_start_info->mod_start) : 0; | ||
1140 | INITRD_SIZE = xen_start_info->mod_len; | ||
1141 | |||
1142 | /* Start the world */ | ||
1143 | start_kernel(); | ||
1144 | } | ||
diff --git a/arch/i386/xen/events.c b/arch/i386/xen/events.c new file mode 100644 index 000000000000..8904acc20f8c --- /dev/null +++ b/arch/i386/xen/events.c | |||
@@ -0,0 +1,590 @@ | |||
1 | /* | ||
2 | * Xen event channels | ||
3 | * | ||
4 | * Xen models interrupts with abstract event channels. Because each | ||
5 | * domain gets 1024 event channels, but NR_IRQ is not that large, we | ||
6 | * must dynamically map irqs<->event channels. The event channels | ||
7 | * interface with the rest of the kernel by defining a xen interrupt | ||
8 | * chip. When an event is recieved, it is mapped to an irq and sent | ||
9 | * through the normal interrupt processing path. | ||
10 | * | ||
11 | * There are four kinds of events which can be mapped to an event | ||
12 | * channel: | ||
13 | * | ||
14 | * 1. Inter-domain notifications. This includes all the virtual | ||
15 | * device events, since they're driven by front-ends in another domain | ||
16 | * (typically dom0). | ||
17 | * 2. VIRQs, typically used for timers. These are per-cpu events. | ||
18 | * 3. IPIs. | ||
19 | * 4. Hardware interrupts. Not supported at present. | ||
20 | * | ||
21 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 | ||
22 | */ | ||
23 | |||
24 | #include <linux/linkage.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/string.h> | ||
29 | |||
30 | #include <asm/ptrace.h> | ||
31 | #include <asm/irq.h> | ||
32 | #include <asm/sync_bitops.h> | ||
33 | #include <asm/xen/hypercall.h> | ||
34 | |||
35 | #include <xen/events.h> | ||
36 | #include <xen/interface/xen.h> | ||
37 | #include <xen/interface/event_channel.h> | ||
38 | |||
39 | #include "xen-ops.h" | ||
40 | |||
41 | /* | ||
42 | * This lock protects updates to the following mapping and reference-count | ||
43 | * arrays. The lock does not need to be acquired to read the mapping tables. | ||
44 | */ | ||
45 | static DEFINE_SPINLOCK(irq_mapping_update_lock); | ||
46 | |||
47 | /* IRQ <-> VIRQ mapping. */ | ||
48 | static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1}; | ||
49 | |||
50 | /* IRQ <-> IPI mapping */ | ||
51 | static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1}; | ||
52 | |||
53 | /* Packed IRQ information: binding type, sub-type index, and event channel. */ | ||
54 | struct packed_irq | ||
55 | { | ||
56 | unsigned short evtchn; | ||
57 | unsigned char index; | ||
58 | unsigned char type; | ||
59 | }; | ||
60 | |||
61 | static struct packed_irq irq_info[NR_IRQS]; | ||
62 | |||
63 | /* Binding types. */ | ||
64 | enum { | ||
65 | IRQT_UNBOUND, | ||
66 | IRQT_PIRQ, | ||
67 | IRQT_VIRQ, | ||
68 | IRQT_IPI, | ||
69 | IRQT_EVTCHN | ||
70 | }; | ||
71 | |||
72 | /* Convenient shorthand for packed representation of an unbound IRQ. */ | ||
73 | #define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0) | ||
74 | |||
75 | static int evtchn_to_irq[NR_EVENT_CHANNELS] = { | ||
76 | [0 ... NR_EVENT_CHANNELS-1] = -1 | ||
77 | }; | ||
78 | static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG]; | ||
79 | static u8 cpu_evtchn[NR_EVENT_CHANNELS]; | ||
80 | |||
81 | /* Reference counts for bindings to IRQs. */ | ||
82 | static int irq_bindcount[NR_IRQS]; | ||
83 | |||
84 | /* Xen will never allocate port zero for any purpose. */ | ||
85 | #define VALID_EVTCHN(chn) ((chn) != 0) | ||
86 | |||
87 | /* | ||
88 | * Force a proper event-channel callback from Xen after clearing the | ||
89 | * callback mask. We do this in a very simple manner, by making a call | ||
90 | * down into Xen. The pending flag will be checked by Xen on return. | ||
91 | */ | ||
92 | void force_evtchn_callback(void) | ||
93 | { | ||
94 | (void)HYPERVISOR_xen_version(0, NULL); | ||
95 | } | ||
96 | EXPORT_SYMBOL_GPL(force_evtchn_callback); | ||
97 | |||
98 | static struct irq_chip xen_dynamic_chip; | ||
99 | |||
100 | /* Constructor for packed IRQ information. */ | ||
101 | static inline struct packed_irq mk_irq_info(u32 type, u32 index, u32 evtchn) | ||
102 | { | ||
103 | return (struct packed_irq) { evtchn, index, type }; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * Accessors for packed IRQ information. | ||
108 | */ | ||
109 | static inline unsigned int evtchn_from_irq(int irq) | ||
110 | { | ||
111 | return irq_info[irq].evtchn; | ||
112 | } | ||
113 | |||
114 | static inline unsigned int index_from_irq(int irq) | ||
115 | { | ||
116 | return irq_info[irq].index; | ||
117 | } | ||
118 | |||
119 | static inline unsigned int type_from_irq(int irq) | ||
120 | { | ||
121 | return irq_info[irq].type; | ||
122 | } | ||
123 | |||
124 | static inline unsigned long active_evtchns(unsigned int cpu, | ||
125 | struct shared_info *sh, | ||
126 | unsigned int idx) | ||
127 | { | ||
128 | return (sh->evtchn_pending[idx] & | ||
129 | cpu_evtchn_mask[cpu][idx] & | ||
130 | ~sh->evtchn_mask[idx]); | ||
131 | } | ||
132 | |||
133 | static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) | ||
134 | { | ||
135 | int irq = evtchn_to_irq[chn]; | ||
136 | |||
137 | BUG_ON(irq == -1); | ||
138 | #ifdef CONFIG_SMP | ||
139 | irq_desc[irq].affinity = cpumask_of_cpu(cpu); | ||
140 | #endif | ||
141 | |||
142 | __clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]); | ||
143 | __set_bit(chn, cpu_evtchn_mask[cpu]); | ||
144 | |||
145 | cpu_evtchn[chn] = cpu; | ||
146 | } | ||
147 | |||
148 | static void init_evtchn_cpu_bindings(void) | ||
149 | { | ||
150 | #ifdef CONFIG_SMP | ||
151 | int i; | ||
152 | /* By default all event channels notify CPU#0. */ | ||
153 | for (i = 0; i < NR_IRQS; i++) | ||
154 | irq_desc[i].affinity = cpumask_of_cpu(0); | ||
155 | #endif | ||
156 | |||
157 | memset(cpu_evtchn, 0, sizeof(cpu_evtchn)); | ||
158 | memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0])); | ||
159 | } | ||
160 | |||
161 | static inline unsigned int cpu_from_evtchn(unsigned int evtchn) | ||
162 | { | ||
163 | return cpu_evtchn[evtchn]; | ||
164 | } | ||
165 | |||
166 | static inline void clear_evtchn(int port) | ||
167 | { | ||
168 | struct shared_info *s = HYPERVISOR_shared_info; | ||
169 | sync_clear_bit(port, &s->evtchn_pending[0]); | ||
170 | } | ||
171 | |||
172 | static inline void set_evtchn(int port) | ||
173 | { | ||
174 | struct shared_info *s = HYPERVISOR_shared_info; | ||
175 | sync_set_bit(port, &s->evtchn_pending[0]); | ||
176 | } | ||
177 | |||
178 | |||
179 | /** | ||
180 | * notify_remote_via_irq - send event to remote end of event channel via irq | ||
181 | * @irq: irq of event channel to send event to | ||
182 | * | ||
183 | * Unlike notify_remote_via_evtchn(), this is safe to use across | ||
184 | * save/restore. Notifications on a broken connection are silently | ||
185 | * dropped. | ||
186 | */ | ||
187 | void notify_remote_via_irq(int irq) | ||
188 | { | ||
189 | int evtchn = evtchn_from_irq(irq); | ||
190 | |||
191 | if (VALID_EVTCHN(evtchn)) | ||
192 | notify_remote_via_evtchn(evtchn); | ||
193 | } | ||
194 | EXPORT_SYMBOL_GPL(notify_remote_via_irq); | ||
195 | |||
196 | static void mask_evtchn(int port) | ||
197 | { | ||
198 | struct shared_info *s = HYPERVISOR_shared_info; | ||
199 | sync_set_bit(port, &s->evtchn_mask[0]); | ||
200 | } | ||
201 | |||
202 | static void unmask_evtchn(int port) | ||
203 | { | ||
204 | struct shared_info *s = HYPERVISOR_shared_info; | ||
205 | unsigned int cpu = get_cpu(); | ||
206 | |||
207 | BUG_ON(!irqs_disabled()); | ||
208 | |||
209 | /* Slow path (hypercall) if this is a non-local port. */ | ||
210 | if (unlikely(cpu != cpu_from_evtchn(port))) { | ||
211 | struct evtchn_unmask unmask = { .port = port }; | ||
212 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); | ||
213 | } else { | ||
214 | struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); | ||
215 | |||
216 | sync_clear_bit(port, &s->evtchn_mask[0]); | ||
217 | |||
218 | /* | ||
219 | * The following is basically the equivalent of | ||
220 | * 'hw_resend_irq'. Just like a real IO-APIC we 'lose | ||
221 | * the interrupt edge' if the channel is masked. | ||
222 | */ | ||
223 | if (sync_test_bit(port, &s->evtchn_pending[0]) && | ||
224 | !sync_test_and_set_bit(port / BITS_PER_LONG, | ||
225 | &vcpu_info->evtchn_pending_sel)) | ||
226 | vcpu_info->evtchn_upcall_pending = 1; | ||
227 | } | ||
228 | |||
229 | put_cpu(); | ||
230 | } | ||
231 | |||
232 | static int find_unbound_irq(void) | ||
233 | { | ||
234 | int irq; | ||
235 | |||
236 | /* Only allocate from dynirq range */ | ||
237 | for (irq = 0; irq < NR_IRQS; irq++) | ||
238 | if (irq_bindcount[irq] == 0) | ||
239 | break; | ||
240 | |||
241 | if (irq == NR_IRQS) | ||
242 | panic("No available IRQ to bind to: increase NR_IRQS!\n"); | ||
243 | |||
244 | return irq; | ||
245 | } | ||
246 | |||
247 | int bind_evtchn_to_irq(unsigned int evtchn) | ||
248 | { | ||
249 | int irq; | ||
250 | |||
251 | spin_lock(&irq_mapping_update_lock); | ||
252 | |||
253 | irq = evtchn_to_irq[evtchn]; | ||
254 | |||
255 | if (irq == -1) { | ||
256 | irq = find_unbound_irq(); | ||
257 | |||
258 | dynamic_irq_init(irq); | ||
259 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, | ||
260 | handle_level_irq, "event"); | ||
261 | |||
262 | evtchn_to_irq[evtchn] = irq; | ||
263 | irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn); | ||
264 | } | ||
265 | |||
266 | irq_bindcount[irq]++; | ||
267 | |||
268 | spin_unlock(&irq_mapping_update_lock); | ||
269 | |||
270 | return irq; | ||
271 | } | ||
272 | EXPORT_SYMBOL_GPL(bind_evtchn_to_irq); | ||
273 | |||
274 | static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) | ||
275 | { | ||
276 | struct evtchn_bind_ipi bind_ipi; | ||
277 | int evtchn, irq; | ||
278 | |||
279 | spin_lock(&irq_mapping_update_lock); | ||
280 | |||
281 | irq = per_cpu(ipi_to_irq, cpu)[ipi]; | ||
282 | if (irq == -1) { | ||
283 | irq = find_unbound_irq(); | ||
284 | if (irq < 0) | ||
285 | goto out; | ||
286 | |||
287 | dynamic_irq_init(irq); | ||
288 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, | ||
289 | handle_level_irq, "ipi"); | ||
290 | |||
291 | bind_ipi.vcpu = cpu; | ||
292 | if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, | ||
293 | &bind_ipi) != 0) | ||
294 | BUG(); | ||
295 | evtchn = bind_ipi.port; | ||
296 | |||
297 | evtchn_to_irq[evtchn] = irq; | ||
298 | irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); | ||
299 | |||
300 | per_cpu(ipi_to_irq, cpu)[ipi] = irq; | ||
301 | |||
302 | bind_evtchn_to_cpu(evtchn, cpu); | ||
303 | } | ||
304 | |||
305 | irq_bindcount[irq]++; | ||
306 | |||
307 | out: | ||
308 | spin_unlock(&irq_mapping_update_lock); | ||
309 | return irq; | ||
310 | } | ||
311 | |||
312 | |||
313 | static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | ||
314 | { | ||
315 | struct evtchn_bind_virq bind_virq; | ||
316 | int evtchn, irq; | ||
317 | |||
318 | spin_lock(&irq_mapping_update_lock); | ||
319 | |||
320 | irq = per_cpu(virq_to_irq, cpu)[virq]; | ||
321 | |||
322 | if (irq == -1) { | ||
323 | bind_virq.virq = virq; | ||
324 | bind_virq.vcpu = cpu; | ||
325 | if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, | ||
326 | &bind_virq) != 0) | ||
327 | BUG(); | ||
328 | evtchn = bind_virq.port; | ||
329 | |||
330 | irq = find_unbound_irq(); | ||
331 | |||
332 | dynamic_irq_init(irq); | ||
333 | set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, | ||
334 | handle_level_irq, "virq"); | ||
335 | |||
336 | evtchn_to_irq[evtchn] = irq; | ||
337 | irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); | ||
338 | |||
339 | per_cpu(virq_to_irq, cpu)[virq] = irq; | ||
340 | |||
341 | bind_evtchn_to_cpu(evtchn, cpu); | ||
342 | } | ||
343 | |||
344 | irq_bindcount[irq]++; | ||
345 | |||
346 | spin_unlock(&irq_mapping_update_lock); | ||
347 | |||
348 | return irq; | ||
349 | } | ||
350 | |||
351 | static void unbind_from_irq(unsigned int irq) | ||
352 | { | ||
353 | struct evtchn_close close; | ||
354 | int evtchn = evtchn_from_irq(irq); | ||
355 | |||
356 | spin_lock(&irq_mapping_update_lock); | ||
357 | |||
358 | if (VALID_EVTCHN(evtchn) && (--irq_bindcount[irq] == 0)) { | ||
359 | close.port = evtchn; | ||
360 | if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) | ||
361 | BUG(); | ||
362 | |||
363 | switch (type_from_irq(irq)) { | ||
364 | case IRQT_VIRQ: | ||
365 | per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) | ||
366 | [index_from_irq(irq)] = -1; | ||
367 | break; | ||
368 | default: | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | /* Closed ports are implicitly re-bound to VCPU0. */ | ||
373 | bind_evtchn_to_cpu(evtchn, 0); | ||
374 | |||
375 | evtchn_to_irq[evtchn] = -1; | ||
376 | irq_info[irq] = IRQ_UNBOUND; | ||
377 | |||
378 | dynamic_irq_init(irq); | ||
379 | } | ||
380 | |||
381 | spin_unlock(&irq_mapping_update_lock); | ||
382 | } | ||
383 | |||
384 | int bind_evtchn_to_irqhandler(unsigned int evtchn, | ||
385 | irqreturn_t (*handler)(int, void *), | ||
386 | unsigned long irqflags, | ||
387 | const char *devname, void *dev_id) | ||
388 | { | ||
389 | unsigned int irq; | ||
390 | int retval; | ||
391 | |||
392 | irq = bind_evtchn_to_irq(evtchn); | ||
393 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | ||
394 | if (retval != 0) { | ||
395 | unbind_from_irq(irq); | ||
396 | return retval; | ||
397 | } | ||
398 | |||
399 | return irq; | ||
400 | } | ||
401 | EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler); | ||
402 | |||
403 | int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu, | ||
404 | irqreturn_t (*handler)(int, void *), | ||
405 | unsigned long irqflags, const char *devname, void *dev_id) | ||
406 | { | ||
407 | unsigned int irq; | ||
408 | int retval; | ||
409 | |||
410 | irq = bind_virq_to_irq(virq, cpu); | ||
411 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | ||
412 | if (retval != 0) { | ||
413 | unbind_from_irq(irq); | ||
414 | return retval; | ||
415 | } | ||
416 | |||
417 | return irq; | ||
418 | } | ||
419 | EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler); | ||
420 | |||
421 | int bind_ipi_to_irqhandler(enum ipi_vector ipi, | ||
422 | unsigned int cpu, | ||
423 | irq_handler_t handler, | ||
424 | unsigned long irqflags, | ||
425 | const char *devname, | ||
426 | void *dev_id) | ||
427 | { | ||
428 | int irq, retval; | ||
429 | |||
430 | irq = bind_ipi_to_irq(ipi, cpu); | ||
431 | if (irq < 0) | ||
432 | return irq; | ||
433 | |||
434 | retval = request_irq(irq, handler, irqflags, devname, dev_id); | ||
435 | if (retval != 0) { | ||
436 | unbind_from_irq(irq); | ||
437 | return retval; | ||
438 | } | ||
439 | |||
440 | return irq; | ||
441 | } | ||
442 | |||
443 | void unbind_from_irqhandler(unsigned int irq, void *dev_id) | ||
444 | { | ||
445 | free_irq(irq, dev_id); | ||
446 | unbind_from_irq(irq); | ||
447 | } | ||
448 | EXPORT_SYMBOL_GPL(unbind_from_irqhandler); | ||
449 | |||
450 | void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector) | ||
451 | { | ||
452 | int irq = per_cpu(ipi_to_irq, cpu)[vector]; | ||
453 | BUG_ON(irq < 0); | ||
454 | notify_remote_via_irq(irq); | ||
455 | } | ||
456 | |||
457 | |||
458 | /* | ||
459 | * Search the CPUs pending events bitmasks. For each one found, map | ||
460 | * the event number to an irq, and feed it into do_IRQ() for | ||
461 | * handling. | ||
462 | * | ||
463 | * Xen uses a two-level bitmap to speed searching. The first level is | ||
464 | * a bitset of words which contain pending event bits. The second | ||
465 | * level is a bitset of pending events themselves. | ||
466 | */ | ||
467 | fastcall void xen_evtchn_do_upcall(struct pt_regs *regs) | ||
468 | { | ||
469 | int cpu = get_cpu(); | ||
470 | struct shared_info *s = HYPERVISOR_shared_info; | ||
471 | struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu); | ||
472 | unsigned long pending_words; | ||
473 | |||
474 | vcpu_info->evtchn_upcall_pending = 0; | ||
475 | |||
476 | /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ | ||
477 | pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); | ||
478 | while (pending_words != 0) { | ||
479 | unsigned long pending_bits; | ||
480 | int word_idx = __ffs(pending_words); | ||
481 | pending_words &= ~(1UL << word_idx); | ||
482 | |||
483 | while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) { | ||
484 | int bit_idx = __ffs(pending_bits); | ||
485 | int port = (word_idx * BITS_PER_LONG) + bit_idx; | ||
486 | int irq = evtchn_to_irq[port]; | ||
487 | |||
488 | if (irq != -1) { | ||
489 | regs->orig_eax = ~irq; | ||
490 | do_IRQ(regs); | ||
491 | } | ||
492 | } | ||
493 | } | ||
494 | |||
495 | put_cpu(); | ||
496 | } | ||
497 | |||
498 | /* Rebind an evtchn so that it gets delivered to a specific cpu */ | ||
499 | static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | ||
500 | { | ||
501 | struct evtchn_bind_vcpu bind_vcpu; | ||
502 | int evtchn = evtchn_from_irq(irq); | ||
503 | |||
504 | if (!VALID_EVTCHN(evtchn)) | ||
505 | return; | ||
506 | |||
507 | /* Send future instances of this interrupt to other vcpu. */ | ||
508 | bind_vcpu.port = evtchn; | ||
509 | bind_vcpu.vcpu = tcpu; | ||
510 | |||
511 | /* | ||
512 | * If this fails, it usually just indicates that we're dealing with a | ||
513 | * virq or IPI channel, which don't actually need to be rebound. Ignore | ||
514 | * it, but don't do the xenlinux-level rebind in that case. | ||
515 | */ | ||
516 | if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0) | ||
517 | bind_evtchn_to_cpu(evtchn, tcpu); | ||
518 | } | ||
519 | |||
520 | |||
521 | static void set_affinity_irq(unsigned irq, cpumask_t dest) | ||
522 | { | ||
523 | unsigned tcpu = first_cpu(dest); | ||
524 | rebind_irq_to_cpu(irq, tcpu); | ||
525 | } | ||
526 | |||
527 | static void enable_dynirq(unsigned int irq) | ||
528 | { | ||
529 | int evtchn = evtchn_from_irq(irq); | ||
530 | |||
531 | if (VALID_EVTCHN(evtchn)) | ||
532 | unmask_evtchn(evtchn); | ||
533 | } | ||
534 | |||
535 | static void disable_dynirq(unsigned int irq) | ||
536 | { | ||
537 | int evtchn = evtchn_from_irq(irq); | ||
538 | |||
539 | if (VALID_EVTCHN(evtchn)) | ||
540 | mask_evtchn(evtchn); | ||
541 | } | ||
542 | |||
543 | static void ack_dynirq(unsigned int irq) | ||
544 | { | ||
545 | int evtchn = evtchn_from_irq(irq); | ||
546 | |||
547 | move_native_irq(irq); | ||
548 | |||
549 | if (VALID_EVTCHN(evtchn)) | ||
550 | clear_evtchn(evtchn); | ||
551 | } | ||
552 | |||
553 | static int retrigger_dynirq(unsigned int irq) | ||
554 | { | ||
555 | int evtchn = evtchn_from_irq(irq); | ||
556 | int ret = 0; | ||
557 | |||
558 | if (VALID_EVTCHN(evtchn)) { | ||
559 | set_evtchn(evtchn); | ||
560 | ret = 1; | ||
561 | } | ||
562 | |||
563 | return ret; | ||
564 | } | ||
565 | |||
566 | static struct irq_chip xen_dynamic_chip __read_mostly = { | ||
567 | .name = "xen-dyn", | ||
568 | .mask = disable_dynirq, | ||
569 | .unmask = enable_dynirq, | ||
570 | .ack = ack_dynirq, | ||
571 | .set_affinity = set_affinity_irq, | ||
572 | .retrigger = retrigger_dynirq, | ||
573 | }; | ||
574 | |||
575 | void __init xen_init_IRQ(void) | ||
576 | { | ||
577 | int i; | ||
578 | |||
579 | init_evtchn_cpu_bindings(); | ||
580 | |||
581 | /* No event channels are 'live' right now. */ | ||
582 | for (i = 0; i < NR_EVENT_CHANNELS; i++) | ||
583 | mask_evtchn(i); | ||
584 | |||
585 | /* Dynamic IRQ space is currently unbound. Zero the refcnts. */ | ||
586 | for (i = 0; i < NR_IRQS; i++) | ||
587 | irq_bindcount[i] = 0; | ||
588 | |||
589 | irq_ctx_init(smp_processor_id()); | ||
590 | } | ||
diff --git a/arch/i386/xen/features.c b/arch/i386/xen/features.c new file mode 100644 index 000000000000..0707714e40d6 --- /dev/null +++ b/arch/i386/xen/features.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /****************************************************************************** | ||
2 | * features.c | ||
3 | * | ||
4 | * Xen feature flags. | ||
5 | * | ||
6 | * Copyright (c) 2006, Ian Campbell, XenSource Inc. | ||
7 | */ | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/cache.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <asm/xen/hypervisor.h> | ||
12 | #include <xen/features.h> | ||
13 | |||
14 | u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly; | ||
15 | EXPORT_SYMBOL_GPL(xen_features); | ||
16 | |||
17 | void xen_setup_features(void) | ||
18 | { | ||
19 | struct xen_feature_info fi; | ||
20 | int i, j; | ||
21 | |||
22 | for (i = 0; i < XENFEAT_NR_SUBMAPS; i++) { | ||
23 | fi.submap_idx = i; | ||
24 | if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0) | ||
25 | break; | ||
26 | for (j = 0; j < 32; j++) | ||
27 | xen_features[i * 32 + j] = !!(fi.submap & 1<<j); | ||
28 | } | ||
29 | } | ||
diff --git a/arch/i386/xen/manage.c b/arch/i386/xen/manage.c new file mode 100644 index 000000000000..aa7af9e6abc0 --- /dev/null +++ b/arch/i386/xen/manage.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Handle extern requests for shutdown, reboot and sysrq | ||
3 | */ | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/err.h> | ||
6 | #include <linux/reboot.h> | ||
7 | #include <linux/sysrq.h> | ||
8 | |||
9 | #include <xen/xenbus.h> | ||
10 | |||
11 | #define SHUTDOWN_INVALID -1 | ||
12 | #define SHUTDOWN_POWEROFF 0 | ||
13 | #define SHUTDOWN_SUSPEND 2 | ||
14 | /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only | ||
15 | * report a crash, not be instructed to crash! | ||
16 | * HALT is the same as POWEROFF, as far as we're concerned. The tools use | ||
17 | * the distinction when we return the reason code to them. | ||
18 | */ | ||
19 | #define SHUTDOWN_HALT 4 | ||
20 | |||
21 | /* Ignore multiple shutdown requests. */ | ||
22 | static int shutting_down = SHUTDOWN_INVALID; | ||
23 | |||
24 | static void shutdown_handler(struct xenbus_watch *watch, | ||
25 | const char **vec, unsigned int len) | ||
26 | { | ||
27 | char *str; | ||
28 | struct xenbus_transaction xbt; | ||
29 | int err; | ||
30 | |||
31 | if (shutting_down != SHUTDOWN_INVALID) | ||
32 | return; | ||
33 | |||
34 | again: | ||
35 | err = xenbus_transaction_start(&xbt); | ||
36 | if (err) | ||
37 | return; | ||
38 | |||
39 | str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); | ||
40 | /* Ignore read errors and empty reads. */ | ||
41 | if (XENBUS_IS_ERR_READ(str)) { | ||
42 | xenbus_transaction_end(xbt, 1); | ||
43 | return; | ||
44 | } | ||
45 | |||
46 | xenbus_write(xbt, "control", "shutdown", ""); | ||
47 | |||
48 | err = xenbus_transaction_end(xbt, 0); | ||
49 | if (err == -EAGAIN) { | ||
50 | kfree(str); | ||
51 | goto again; | ||
52 | } | ||
53 | |||
54 | if (strcmp(str, "poweroff") == 0 || | ||
55 | strcmp(str, "halt") == 0) | ||
56 | orderly_poweroff(false); | ||
57 | else if (strcmp(str, "reboot") == 0) | ||
58 | ctrl_alt_del(); | ||
59 | else { | ||
60 | printk(KERN_INFO "Ignoring shutdown request: %s\n", str); | ||
61 | shutting_down = SHUTDOWN_INVALID; | ||
62 | } | ||
63 | |||
64 | kfree(str); | ||
65 | } | ||
66 | |||
67 | static void sysrq_handler(struct xenbus_watch *watch, const char **vec, | ||
68 | unsigned int len) | ||
69 | { | ||
70 | char sysrq_key = '\0'; | ||
71 | struct xenbus_transaction xbt; | ||
72 | int err; | ||
73 | |||
74 | again: | ||
75 | err = xenbus_transaction_start(&xbt); | ||
76 | if (err) | ||
77 | return; | ||
78 | if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) { | ||
79 | printk(KERN_ERR "Unable to read sysrq code in " | ||
80 | "control/sysrq\n"); | ||
81 | xenbus_transaction_end(xbt, 1); | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | if (sysrq_key != '\0') | ||
86 | xenbus_printf(xbt, "control", "sysrq", "%c", '\0'); | ||
87 | |||
88 | err = xenbus_transaction_end(xbt, 0); | ||
89 | if (err == -EAGAIN) | ||
90 | goto again; | ||
91 | |||
92 | if (sysrq_key != '\0') | ||
93 | handle_sysrq(sysrq_key, NULL); | ||
94 | } | ||
95 | |||
96 | static struct xenbus_watch shutdown_watch = { | ||
97 | .node = "control/shutdown", | ||
98 | .callback = shutdown_handler | ||
99 | }; | ||
100 | |||
101 | static struct xenbus_watch sysrq_watch = { | ||
102 | .node = "control/sysrq", | ||
103 | .callback = sysrq_handler | ||
104 | }; | ||
105 | |||
106 | static int setup_shutdown_watcher(void) | ||
107 | { | ||
108 | int err; | ||
109 | |||
110 | err = register_xenbus_watch(&shutdown_watch); | ||
111 | if (err) { | ||
112 | printk(KERN_ERR "Failed to set shutdown watcher\n"); | ||
113 | return err; | ||
114 | } | ||
115 | |||
116 | err = register_xenbus_watch(&sysrq_watch); | ||
117 | if (err) { | ||
118 | printk(KERN_ERR "Failed to set sysrq watcher\n"); | ||
119 | return err; | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static int shutdown_event(struct notifier_block *notifier, | ||
126 | unsigned long event, | ||
127 | void *data) | ||
128 | { | ||
129 | setup_shutdown_watcher(); | ||
130 | return NOTIFY_DONE; | ||
131 | } | ||
132 | |||
133 | static int __init setup_shutdown_event(void) | ||
134 | { | ||
135 | static struct notifier_block xenstore_notifier = { | ||
136 | .notifier_call = shutdown_event | ||
137 | }; | ||
138 | register_xenstore_notifier(&xenstore_notifier); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | subsys_initcall(setup_shutdown_event); | ||
diff --git a/arch/i386/xen/mmu.c b/arch/i386/xen/mmu.c new file mode 100644 index 000000000000..4ae038aa6c24 --- /dev/null +++ b/arch/i386/xen/mmu.c | |||
@@ -0,0 +1,564 @@ | |||
1 | /* | ||
2 | * Xen mmu operations | ||
3 | * | ||
4 | * This file contains the various mmu fetch and update operations. | ||
5 | * The most important job they must perform is the mapping between the | ||
6 | * domain's pfn and the overall machine mfns. | ||
7 | * | ||
8 | * Xen allows guests to directly update the pagetable, in a controlled | ||
9 | * fashion. In other words, the guest modifies the same pagetable | ||
10 | * that the CPU actually uses, which eliminates the overhead of having | ||
11 | * a separate shadow pagetable. | ||
12 | * | ||
13 | * In order to allow this, it falls on the guest domain to map its | ||
14 | * notion of a "physical" pfn - which is just a domain-local linear | ||
15 | * address - into a real "machine address" which the CPU's MMU can | ||
16 | * use. | ||
17 | * | ||
18 | * A pgd_t/pmd_t/pte_t will typically contain an mfn, and so can be | ||
19 | * inserted directly into the pagetable. When creating a new | ||
20 | * pte/pmd/pgd, it converts the passed pfn into an mfn. Conversely, | ||
21 | * when reading the content back with __(pgd|pmd|pte)_val, it converts | ||
22 | * the mfn back into a pfn. | ||
23 | * | ||
24 | * The other constraint is that all pages which make up a pagetable | ||
25 | * must be mapped read-only in the guest. This prevents uncontrolled | ||
26 | * guest updates to the pagetable. Xen strictly enforces this, and | ||
27 | * will disallow any pagetable update which will end up mapping a | ||
28 | * pagetable page RW, and will disallow using any writable page as a | ||
29 | * pagetable. | ||
30 | * | ||
31 | * Naively, when loading %cr3 with the base of a new pagetable, Xen | ||
32 | * would need to validate the whole pagetable before going on. | ||
33 | * Naturally, this is quite slow. The solution is to "pin" a | ||
34 | * pagetable, which enforces all the constraints on the pagetable even | ||
35 | * when it is not actively in use. This menas that Xen can be assured | ||
36 | * that it is still valid when you do load it into %cr3, and doesn't | ||
37 | * need to revalidate it. | ||
38 | * | ||
39 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 | ||
40 | */ | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/highmem.h> | ||
43 | #include <linux/bug.h> | ||
44 | #include <linux/sched.h> | ||
45 | |||
46 | #include <asm/pgtable.h> | ||
47 | #include <asm/tlbflush.h> | ||
48 | #include <asm/mmu_context.h> | ||
49 | #include <asm/paravirt.h> | ||
50 | |||
51 | #include <asm/xen/hypercall.h> | ||
52 | #include <asm/xen/hypervisor.h> | ||
53 | |||
54 | #include <xen/page.h> | ||
55 | #include <xen/interface/xen.h> | ||
56 | |||
57 | #include "multicalls.h" | ||
58 | #include "mmu.h" | ||
59 | |||
60 | xmaddr_t arbitrary_virt_to_machine(unsigned long address) | ||
61 | { | ||
62 | pte_t *pte = lookup_address(address); | ||
63 | unsigned offset = address & PAGE_MASK; | ||
64 | |||
65 | BUG_ON(pte == NULL); | ||
66 | |||
67 | return XMADDR((pte_mfn(*pte) << PAGE_SHIFT) + offset); | ||
68 | } | ||
69 | |||
70 | void make_lowmem_page_readonly(void *vaddr) | ||
71 | { | ||
72 | pte_t *pte, ptev; | ||
73 | unsigned long address = (unsigned long)vaddr; | ||
74 | |||
75 | pte = lookup_address(address); | ||
76 | BUG_ON(pte == NULL); | ||
77 | |||
78 | ptev = pte_wrprotect(*pte); | ||
79 | |||
80 | if (HYPERVISOR_update_va_mapping(address, ptev, 0)) | ||
81 | BUG(); | ||
82 | } | ||
83 | |||
84 | void make_lowmem_page_readwrite(void *vaddr) | ||
85 | { | ||
86 | pte_t *pte, ptev; | ||
87 | unsigned long address = (unsigned long)vaddr; | ||
88 | |||
89 | pte = lookup_address(address); | ||
90 | BUG_ON(pte == NULL); | ||
91 | |||
92 | ptev = pte_mkwrite(*pte); | ||
93 | |||
94 | if (HYPERVISOR_update_va_mapping(address, ptev, 0)) | ||
95 | BUG(); | ||
96 | } | ||
97 | |||
98 | |||
99 | void xen_set_pmd(pmd_t *ptr, pmd_t val) | ||
100 | { | ||
101 | struct multicall_space mcs; | ||
102 | struct mmu_update *u; | ||
103 | |||
104 | preempt_disable(); | ||
105 | |||
106 | mcs = xen_mc_entry(sizeof(*u)); | ||
107 | u = mcs.args; | ||
108 | u->ptr = virt_to_machine(ptr).maddr; | ||
109 | u->val = pmd_val_ma(val); | ||
110 | MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF); | ||
111 | |||
112 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
113 | |||
114 | preempt_enable(); | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * Associate a virtual page frame with a given physical page frame | ||
119 | * and protection flags for that frame. | ||
120 | */ | ||
121 | void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags) | ||
122 | { | ||
123 | pgd_t *pgd; | ||
124 | pud_t *pud; | ||
125 | pmd_t *pmd; | ||
126 | pte_t *pte; | ||
127 | |||
128 | pgd = swapper_pg_dir + pgd_index(vaddr); | ||
129 | if (pgd_none(*pgd)) { | ||
130 | BUG(); | ||
131 | return; | ||
132 | } | ||
133 | pud = pud_offset(pgd, vaddr); | ||
134 | if (pud_none(*pud)) { | ||
135 | BUG(); | ||
136 | return; | ||
137 | } | ||
138 | pmd = pmd_offset(pud, vaddr); | ||
139 | if (pmd_none(*pmd)) { | ||
140 | BUG(); | ||
141 | return; | ||
142 | } | ||
143 | pte = pte_offset_kernel(pmd, vaddr); | ||
144 | /* <mfn,flags> stored as-is, to permit clearing entries */ | ||
145 | xen_set_pte(pte, mfn_pte(mfn, flags)); | ||
146 | |||
147 | /* | ||
148 | * It's enough to flush this one mapping. | ||
149 | * (PGE mappings get flushed as well) | ||
150 | */ | ||
151 | __flush_tlb_one(vaddr); | ||
152 | } | ||
153 | |||
154 | void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
155 | pte_t *ptep, pte_t pteval) | ||
156 | { | ||
157 | if (mm == current->mm || mm == &init_mm) { | ||
158 | if (xen_get_lazy_mode() == PARAVIRT_LAZY_MMU) { | ||
159 | struct multicall_space mcs; | ||
160 | mcs = xen_mc_entry(0); | ||
161 | |||
162 | MULTI_update_va_mapping(mcs.mc, addr, pteval, 0); | ||
163 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
164 | return; | ||
165 | } else | ||
166 | if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0) | ||
167 | return; | ||
168 | } | ||
169 | xen_set_pte(ptep, pteval); | ||
170 | } | ||
171 | |||
172 | #ifdef CONFIG_X86_PAE | ||
173 | void xen_set_pud(pud_t *ptr, pud_t val) | ||
174 | { | ||
175 | struct multicall_space mcs; | ||
176 | struct mmu_update *u; | ||
177 | |||
178 | preempt_disable(); | ||
179 | |||
180 | mcs = xen_mc_entry(sizeof(*u)); | ||
181 | u = mcs.args; | ||
182 | u->ptr = virt_to_machine(ptr).maddr; | ||
183 | u->val = pud_val_ma(val); | ||
184 | MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF); | ||
185 | |||
186 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
187 | |||
188 | preempt_enable(); | ||
189 | } | ||
190 | |||
191 | void xen_set_pte(pte_t *ptep, pte_t pte) | ||
192 | { | ||
193 | ptep->pte_high = pte.pte_high; | ||
194 | smp_wmb(); | ||
195 | ptep->pte_low = pte.pte_low; | ||
196 | } | ||
197 | |||
198 | void xen_set_pte_atomic(pte_t *ptep, pte_t pte) | ||
199 | { | ||
200 | set_64bit((u64 *)ptep, pte_val_ma(pte)); | ||
201 | } | ||
202 | |||
203 | void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | ||
204 | { | ||
205 | ptep->pte_low = 0; | ||
206 | smp_wmb(); /* make sure low gets written first */ | ||
207 | ptep->pte_high = 0; | ||
208 | } | ||
209 | |||
210 | void xen_pmd_clear(pmd_t *pmdp) | ||
211 | { | ||
212 | xen_set_pmd(pmdp, __pmd(0)); | ||
213 | } | ||
214 | |||
215 | unsigned long long xen_pte_val(pte_t pte) | ||
216 | { | ||
217 | unsigned long long ret = 0; | ||
218 | |||
219 | if (pte.pte_low) { | ||
220 | ret = ((unsigned long long)pte.pte_high << 32) | pte.pte_low; | ||
221 | ret = machine_to_phys(XMADDR(ret)).paddr | 1; | ||
222 | } | ||
223 | |||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | unsigned long long xen_pmd_val(pmd_t pmd) | ||
228 | { | ||
229 | unsigned long long ret = pmd.pmd; | ||
230 | if (ret) | ||
231 | ret = machine_to_phys(XMADDR(ret)).paddr | 1; | ||
232 | return ret; | ||
233 | } | ||
234 | |||
235 | unsigned long long xen_pgd_val(pgd_t pgd) | ||
236 | { | ||
237 | unsigned long long ret = pgd.pgd; | ||
238 | if (ret) | ||
239 | ret = machine_to_phys(XMADDR(ret)).paddr | 1; | ||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | pte_t xen_make_pte(unsigned long long pte) | ||
244 | { | ||
245 | if (pte & 1) | ||
246 | pte = phys_to_machine(XPADDR(pte)).maddr; | ||
247 | |||
248 | return (pte_t){ pte, pte >> 32 }; | ||
249 | } | ||
250 | |||
251 | pmd_t xen_make_pmd(unsigned long long pmd) | ||
252 | { | ||
253 | if (pmd & 1) | ||
254 | pmd = phys_to_machine(XPADDR(pmd)).maddr; | ||
255 | |||
256 | return (pmd_t){ pmd }; | ||
257 | } | ||
258 | |||
259 | pgd_t xen_make_pgd(unsigned long long pgd) | ||
260 | { | ||
261 | if (pgd & _PAGE_PRESENT) | ||
262 | pgd = phys_to_machine(XPADDR(pgd)).maddr; | ||
263 | |||
264 | return (pgd_t){ pgd }; | ||
265 | } | ||
266 | #else /* !PAE */ | ||
267 | void xen_set_pte(pte_t *ptep, pte_t pte) | ||
268 | { | ||
269 | *ptep = pte; | ||
270 | } | ||
271 | |||
272 | unsigned long xen_pte_val(pte_t pte) | ||
273 | { | ||
274 | unsigned long ret = pte.pte_low; | ||
275 | |||
276 | if (ret & _PAGE_PRESENT) | ||
277 | ret = machine_to_phys(XMADDR(ret)).paddr; | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | unsigned long xen_pgd_val(pgd_t pgd) | ||
283 | { | ||
284 | unsigned long ret = pgd.pgd; | ||
285 | if (ret) | ||
286 | ret = machine_to_phys(XMADDR(ret)).paddr | 1; | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | pte_t xen_make_pte(unsigned long pte) | ||
291 | { | ||
292 | if (pte & _PAGE_PRESENT) | ||
293 | pte = phys_to_machine(XPADDR(pte)).maddr; | ||
294 | |||
295 | return (pte_t){ pte }; | ||
296 | } | ||
297 | |||
298 | pgd_t xen_make_pgd(unsigned long pgd) | ||
299 | { | ||
300 | if (pgd & _PAGE_PRESENT) | ||
301 | pgd = phys_to_machine(XPADDR(pgd)).maddr; | ||
302 | |||
303 | return (pgd_t){ pgd }; | ||
304 | } | ||
305 | #endif /* CONFIG_X86_PAE */ | ||
306 | |||
307 | |||
308 | |||
309 | /* | ||
310 | (Yet another) pagetable walker. This one is intended for pinning a | ||
311 | pagetable. This means that it walks a pagetable and calls the | ||
312 | callback function on each page it finds making up the page table, | ||
313 | at every level. It walks the entire pagetable, but it only bothers | ||
314 | pinning pte pages which are below pte_limit. In the normal case | ||
315 | this will be TASK_SIZE, but at boot we need to pin up to | ||
316 | FIXADDR_TOP. But the important bit is that we don't pin beyond | ||
317 | there, because then we start getting into Xen's ptes. | ||
318 | */ | ||
319 | static int pgd_walk(pgd_t *pgd_base, int (*func)(struct page *, unsigned), | ||
320 | unsigned long limit) | ||
321 | { | ||
322 | pgd_t *pgd = pgd_base; | ||
323 | int flush = 0; | ||
324 | unsigned long addr = 0; | ||
325 | unsigned long pgd_next; | ||
326 | |||
327 | BUG_ON(limit > FIXADDR_TOP); | ||
328 | |||
329 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
330 | return 0; | ||
331 | |||
332 | for (; addr != FIXADDR_TOP; pgd++, addr = pgd_next) { | ||
333 | pud_t *pud; | ||
334 | unsigned long pud_limit, pud_next; | ||
335 | |||
336 | pgd_next = pud_limit = pgd_addr_end(addr, FIXADDR_TOP); | ||
337 | |||
338 | if (!pgd_val(*pgd)) | ||
339 | continue; | ||
340 | |||
341 | pud = pud_offset(pgd, 0); | ||
342 | |||
343 | if (PTRS_PER_PUD > 1) /* not folded */ | ||
344 | flush |= (*func)(virt_to_page(pud), 0); | ||
345 | |||
346 | for (; addr != pud_limit; pud++, addr = pud_next) { | ||
347 | pmd_t *pmd; | ||
348 | unsigned long pmd_limit; | ||
349 | |||
350 | pud_next = pud_addr_end(addr, pud_limit); | ||
351 | |||
352 | if (pud_next < limit) | ||
353 | pmd_limit = pud_next; | ||
354 | else | ||
355 | pmd_limit = limit; | ||
356 | |||
357 | if (pud_none(*pud)) | ||
358 | continue; | ||
359 | |||
360 | pmd = pmd_offset(pud, 0); | ||
361 | |||
362 | if (PTRS_PER_PMD > 1) /* not folded */ | ||
363 | flush |= (*func)(virt_to_page(pmd), 0); | ||
364 | |||
365 | for (; addr != pmd_limit; pmd++) { | ||
366 | addr += (PAGE_SIZE * PTRS_PER_PTE); | ||
367 | if ((pmd_limit-1) < (addr-1)) { | ||
368 | addr = pmd_limit; | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | if (pmd_none(*pmd)) | ||
373 | continue; | ||
374 | |||
375 | flush |= (*func)(pmd_page(*pmd), 0); | ||
376 | } | ||
377 | } | ||
378 | } | ||
379 | |||
380 | flush |= (*func)(virt_to_page(pgd_base), UVMF_TLB_FLUSH); | ||
381 | |||
382 | return flush; | ||
383 | } | ||
384 | |||
385 | static int pin_page(struct page *page, unsigned flags) | ||
386 | { | ||
387 | unsigned pgfl = test_and_set_bit(PG_pinned, &page->flags); | ||
388 | int flush; | ||
389 | |||
390 | if (pgfl) | ||
391 | flush = 0; /* already pinned */ | ||
392 | else if (PageHighMem(page)) | ||
393 | /* kmaps need flushing if we found an unpinned | ||
394 | highpage */ | ||
395 | flush = 1; | ||
396 | else { | ||
397 | void *pt = lowmem_page_address(page); | ||
398 | unsigned long pfn = page_to_pfn(page); | ||
399 | struct multicall_space mcs = __xen_mc_entry(0); | ||
400 | |||
401 | flush = 0; | ||
402 | |||
403 | MULTI_update_va_mapping(mcs.mc, (unsigned long)pt, | ||
404 | pfn_pte(pfn, PAGE_KERNEL_RO), | ||
405 | flags); | ||
406 | } | ||
407 | |||
408 | return flush; | ||
409 | } | ||
410 | |||
411 | /* This is called just after a mm has been created, but it has not | ||
412 | been used yet. We need to make sure that its pagetable is all | ||
413 | read-only, and can be pinned. */ | ||
414 | void xen_pgd_pin(pgd_t *pgd) | ||
415 | { | ||
416 | struct multicall_space mcs; | ||
417 | struct mmuext_op *op; | ||
418 | |||
419 | xen_mc_batch(); | ||
420 | |||
421 | if (pgd_walk(pgd, pin_page, TASK_SIZE)) { | ||
422 | /* re-enable interrupts for kmap_flush_unused */ | ||
423 | xen_mc_issue(0); | ||
424 | kmap_flush_unused(); | ||
425 | xen_mc_batch(); | ||
426 | } | ||
427 | |||
428 | mcs = __xen_mc_entry(sizeof(*op)); | ||
429 | op = mcs.args; | ||
430 | |||
431 | #ifdef CONFIG_X86_PAE | ||
432 | op->cmd = MMUEXT_PIN_L3_TABLE; | ||
433 | #else | ||
434 | op->cmd = MMUEXT_PIN_L2_TABLE; | ||
435 | #endif | ||
436 | op->arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(pgd))); | ||
437 | MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | ||
438 | |||
439 | xen_mc_issue(0); | ||
440 | } | ||
441 | |||
442 | /* The init_mm pagetable is really pinned as soon as its created, but | ||
443 | that's before we have page structures to store the bits. So do all | ||
444 | the book-keeping now. */ | ||
445 | static __init int mark_pinned(struct page *page, unsigned flags) | ||
446 | { | ||
447 | SetPagePinned(page); | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | void __init xen_mark_init_mm_pinned(void) | ||
452 | { | ||
453 | pgd_walk(init_mm.pgd, mark_pinned, FIXADDR_TOP); | ||
454 | } | ||
455 | |||
456 | static int unpin_page(struct page *page, unsigned flags) | ||
457 | { | ||
458 | unsigned pgfl = test_and_clear_bit(PG_pinned, &page->flags); | ||
459 | |||
460 | if (pgfl && !PageHighMem(page)) { | ||
461 | void *pt = lowmem_page_address(page); | ||
462 | unsigned long pfn = page_to_pfn(page); | ||
463 | struct multicall_space mcs = __xen_mc_entry(0); | ||
464 | |||
465 | MULTI_update_va_mapping(mcs.mc, (unsigned long)pt, | ||
466 | pfn_pte(pfn, PAGE_KERNEL), | ||
467 | flags); | ||
468 | } | ||
469 | |||
470 | return 0; /* never need to flush on unpin */ | ||
471 | } | ||
472 | |||
473 | /* Release a pagetables pages back as normal RW */ | ||
474 | static void xen_pgd_unpin(pgd_t *pgd) | ||
475 | { | ||
476 | struct mmuext_op *op; | ||
477 | struct multicall_space mcs; | ||
478 | |||
479 | xen_mc_batch(); | ||
480 | |||
481 | mcs = __xen_mc_entry(sizeof(*op)); | ||
482 | |||
483 | op = mcs.args; | ||
484 | op->cmd = MMUEXT_UNPIN_TABLE; | ||
485 | op->arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(pgd))); | ||
486 | |||
487 | MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); | ||
488 | |||
489 | pgd_walk(pgd, unpin_page, TASK_SIZE); | ||
490 | |||
491 | xen_mc_issue(0); | ||
492 | } | ||
493 | |||
494 | void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) | ||
495 | { | ||
496 | spin_lock(&next->page_table_lock); | ||
497 | xen_pgd_pin(next->pgd); | ||
498 | spin_unlock(&next->page_table_lock); | ||
499 | } | ||
500 | |||
501 | void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) | ||
502 | { | ||
503 | spin_lock(&mm->page_table_lock); | ||
504 | xen_pgd_pin(mm->pgd); | ||
505 | spin_unlock(&mm->page_table_lock); | ||
506 | } | ||
507 | |||
508 | |||
509 | #ifdef CONFIG_SMP | ||
510 | /* Another cpu may still have their %cr3 pointing at the pagetable, so | ||
511 | we need to repoint it somewhere else before we can unpin it. */ | ||
512 | static void drop_other_mm_ref(void *info) | ||
513 | { | ||
514 | struct mm_struct *mm = info; | ||
515 | |||
516 | if (__get_cpu_var(cpu_tlbstate).active_mm == mm) | ||
517 | leave_mm(smp_processor_id()); | ||
518 | } | ||
519 | |||
520 | static void drop_mm_ref(struct mm_struct *mm) | ||
521 | { | ||
522 | if (current->active_mm == mm) { | ||
523 | if (current->mm == mm) | ||
524 | load_cr3(swapper_pg_dir); | ||
525 | else | ||
526 | leave_mm(smp_processor_id()); | ||
527 | } | ||
528 | |||
529 | if (!cpus_empty(mm->cpu_vm_mask)) | ||
530 | xen_smp_call_function_mask(mm->cpu_vm_mask, drop_other_mm_ref, | ||
531 | mm, 1); | ||
532 | } | ||
533 | #else | ||
534 | static void drop_mm_ref(struct mm_struct *mm) | ||
535 | { | ||
536 | if (current->active_mm == mm) | ||
537 | load_cr3(swapper_pg_dir); | ||
538 | } | ||
539 | #endif | ||
540 | |||
541 | /* | ||
542 | * While a process runs, Xen pins its pagetables, which means that the | ||
543 | * hypervisor forces it to be read-only, and it controls all updates | ||
544 | * to it. This means that all pagetable updates have to go via the | ||
545 | * hypervisor, which is moderately expensive. | ||
546 | * | ||
547 | * Since we're pulling the pagetable down, we switch to use init_mm, | ||
548 | * unpin old process pagetable and mark it all read-write, which | ||
549 | * allows further operations on it to be simple memory accesses. | ||
550 | * | ||
551 | * The only subtle point is that another CPU may be still using the | ||
552 | * pagetable because of lazy tlb flushing. This means we need need to | ||
553 | * switch all CPUs off this pagetable before we can unpin it. | ||
554 | */ | ||
555 | void xen_exit_mmap(struct mm_struct *mm) | ||
556 | { | ||
557 | get_cpu(); /* make sure we don't move around */ | ||
558 | drop_mm_ref(mm); | ||
559 | put_cpu(); | ||
560 | |||
561 | spin_lock(&mm->page_table_lock); | ||
562 | xen_pgd_unpin(mm->pgd); | ||
563 | spin_unlock(&mm->page_table_lock); | ||
564 | } | ||
diff --git a/arch/i386/xen/mmu.h b/arch/i386/xen/mmu.h new file mode 100644 index 000000000000..c9ff27f3ac3a --- /dev/null +++ b/arch/i386/xen/mmu.h | |||
@@ -0,0 +1,60 @@ | |||
1 | #ifndef _XEN_MMU_H | ||
2 | |||
3 | #include <linux/linkage.h> | ||
4 | #include <asm/page.h> | ||
5 | |||
6 | /* | ||
7 | * Page-directory addresses above 4GB do not fit into architectural %cr3. | ||
8 | * When accessing %cr3, or equivalent field in vcpu_guest_context, guests | ||
9 | * must use the following accessor macros to pack/unpack valid MFNs. | ||
10 | * | ||
11 | * Note that Xen is using the fact that the pagetable base is always | ||
12 | * page-aligned, and putting the 12 MSB of the address into the 12 LSB | ||
13 | * of cr3. | ||
14 | */ | ||
15 | #define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20)) | ||
16 | #define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20)) | ||
17 | |||
18 | |||
19 | void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); | ||
20 | |||
21 | void xen_set_pte(pte_t *ptep, pte_t pteval); | ||
22 | void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
23 | pte_t *ptep, pte_t pteval); | ||
24 | void xen_set_pmd(pmd_t *pmdp, pmd_t pmdval); | ||
25 | |||
26 | void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next); | ||
27 | void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm); | ||
28 | void xen_exit_mmap(struct mm_struct *mm); | ||
29 | |||
30 | void xen_pgd_pin(pgd_t *pgd); | ||
31 | //void xen_pgd_unpin(pgd_t *pgd); | ||
32 | |||
33 | #ifdef CONFIG_X86_PAE | ||
34 | unsigned long long xen_pte_val(pte_t); | ||
35 | unsigned long long xen_pmd_val(pmd_t); | ||
36 | unsigned long long xen_pgd_val(pgd_t); | ||
37 | |||
38 | pte_t xen_make_pte(unsigned long long); | ||
39 | pmd_t xen_make_pmd(unsigned long long); | ||
40 | pgd_t xen_make_pgd(unsigned long long); | ||
41 | |||
42 | void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
43 | pte_t *ptep, pte_t pteval); | ||
44 | void xen_set_pte_atomic(pte_t *ptep, pte_t pte); | ||
45 | void xen_set_pud(pud_t *ptr, pud_t val); | ||
46 | void xen_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); | ||
47 | void xen_pmd_clear(pmd_t *pmdp); | ||
48 | |||
49 | |||
50 | #else | ||
51 | unsigned long xen_pte_val(pte_t); | ||
52 | unsigned long xen_pmd_val(pmd_t); | ||
53 | unsigned long xen_pgd_val(pgd_t); | ||
54 | |||
55 | pte_t xen_make_pte(unsigned long); | ||
56 | pmd_t xen_make_pmd(unsigned long); | ||
57 | pgd_t xen_make_pgd(unsigned long); | ||
58 | #endif | ||
59 | |||
60 | #endif /* _XEN_MMU_H */ | ||
diff --git a/arch/i386/xen/multicalls.c b/arch/i386/xen/multicalls.c new file mode 100644 index 000000000000..c837e8e463db --- /dev/null +++ b/arch/i386/xen/multicalls.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * Xen hypercall batching. | ||
3 | * | ||
4 | * Xen allows multiple hypercalls to be issued at once, using the | ||
5 | * multicall interface. This allows the cost of trapping into the | ||
6 | * hypervisor to be amortized over several calls. | ||
7 | * | ||
8 | * This file implements a simple interface for multicalls. There's a | ||
9 | * per-cpu buffer of outstanding multicalls. When you want to queue a | ||
10 | * multicall for issuing, you can allocate a multicall slot for the | ||
11 | * call and its arguments, along with storage for space which is | ||
12 | * pointed to by the arguments (for passing pointers to structures, | ||
13 | * etc). When the multicall is actually issued, all the space for the | ||
14 | * commands and allocated memory is freed for reuse. | ||
15 | * | ||
16 | * Multicalls are flushed whenever any of the buffers get full, or | ||
17 | * when explicitly requested. There's no way to get per-multicall | ||
18 | * return results back. It will BUG if any of the multicalls fail. | ||
19 | * | ||
20 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 | ||
21 | */ | ||
22 | #include <linux/percpu.h> | ||
23 | #include <linux/hardirq.h> | ||
24 | |||
25 | #include <asm/xen/hypercall.h> | ||
26 | |||
27 | #include "multicalls.h" | ||
28 | |||
29 | #define MC_BATCH 32 | ||
30 | #define MC_ARGS (MC_BATCH * 16 / sizeof(u64)) | ||
31 | |||
32 | struct mc_buffer { | ||
33 | struct multicall_entry entries[MC_BATCH]; | ||
34 | u64 args[MC_ARGS]; | ||
35 | unsigned mcidx, argidx; | ||
36 | }; | ||
37 | |||
38 | static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); | ||
39 | DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags); | ||
40 | |||
41 | void xen_mc_flush(void) | ||
42 | { | ||
43 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); | ||
44 | int ret = 0; | ||
45 | unsigned long flags; | ||
46 | |||
47 | BUG_ON(preemptible()); | ||
48 | |||
49 | /* Disable interrupts in case someone comes in and queues | ||
50 | something in the middle */ | ||
51 | local_irq_save(flags); | ||
52 | |||
53 | if (b->mcidx) { | ||
54 | int i; | ||
55 | |||
56 | if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0) | ||
57 | BUG(); | ||
58 | for (i = 0; i < b->mcidx; i++) | ||
59 | if (b->entries[i].result < 0) | ||
60 | ret++; | ||
61 | b->mcidx = 0; | ||
62 | b->argidx = 0; | ||
63 | } else | ||
64 | BUG_ON(b->argidx != 0); | ||
65 | |||
66 | local_irq_restore(flags); | ||
67 | |||
68 | BUG_ON(ret); | ||
69 | } | ||
70 | |||
71 | struct multicall_space __xen_mc_entry(size_t args) | ||
72 | { | ||
73 | struct mc_buffer *b = &__get_cpu_var(mc_buffer); | ||
74 | struct multicall_space ret; | ||
75 | unsigned argspace = (args + sizeof(u64) - 1) / sizeof(u64); | ||
76 | |||
77 | BUG_ON(preemptible()); | ||
78 | BUG_ON(argspace > MC_ARGS); | ||
79 | |||
80 | if (b->mcidx == MC_BATCH || | ||
81 | (b->argidx + argspace) > MC_ARGS) | ||
82 | xen_mc_flush(); | ||
83 | |||
84 | ret.mc = &b->entries[b->mcidx]; | ||
85 | b->mcidx++; | ||
86 | ret.args = &b->args[b->argidx]; | ||
87 | b->argidx += argspace; | ||
88 | |||
89 | return ret; | ||
90 | } | ||
diff --git a/arch/i386/xen/multicalls.h b/arch/i386/xen/multicalls.h new file mode 100644 index 000000000000..e6f7530b156c --- /dev/null +++ b/arch/i386/xen/multicalls.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef _XEN_MULTICALLS_H | ||
2 | #define _XEN_MULTICALLS_H | ||
3 | |||
4 | #include "xen-ops.h" | ||
5 | |||
6 | /* Multicalls */ | ||
7 | struct multicall_space | ||
8 | { | ||
9 | struct multicall_entry *mc; | ||
10 | void *args; | ||
11 | }; | ||
12 | |||
13 | /* Allocate room for a multicall and its args */ | ||
14 | struct multicall_space __xen_mc_entry(size_t args); | ||
15 | |||
16 | DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags); | ||
17 | |||
18 | /* Call to start a batch of multiple __xen_mc_entry()s. Must be | ||
19 | paired with xen_mc_issue() */ | ||
20 | static inline void xen_mc_batch(void) | ||
21 | { | ||
22 | /* need to disable interrupts until this entry is complete */ | ||
23 | local_irq_save(__get_cpu_var(xen_mc_irq_flags)); | ||
24 | } | ||
25 | |||
26 | static inline struct multicall_space xen_mc_entry(size_t args) | ||
27 | { | ||
28 | xen_mc_batch(); | ||
29 | return __xen_mc_entry(args); | ||
30 | } | ||
31 | |||
32 | /* Flush all pending multicalls */ | ||
33 | void xen_mc_flush(void); | ||
34 | |||
35 | /* Issue a multicall if we're not in a lazy mode */ | ||
36 | static inline void xen_mc_issue(unsigned mode) | ||
37 | { | ||
38 | if ((xen_get_lazy_mode() & mode) == 0) | ||
39 | xen_mc_flush(); | ||
40 | |||
41 | /* restore flags saved in xen_mc_batch */ | ||
42 | local_irq_restore(x86_read_percpu(xen_mc_irq_flags)); | ||
43 | } | ||
44 | |||
45 | #endif /* _XEN_MULTICALLS_H */ | ||
diff --git a/arch/i386/xen/setup.c b/arch/i386/xen/setup.c new file mode 100644 index 000000000000..2fe6eac510f0 --- /dev/null +++ b/arch/i386/xen/setup.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Machine specific setup for xen | ||
3 | * | ||
4 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/sched.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/pm.h> | ||
11 | |||
12 | #include <asm/elf.h> | ||
13 | #include <asm/e820.h> | ||
14 | #include <asm/setup.h> | ||
15 | #include <asm/xen/hypervisor.h> | ||
16 | #include <asm/xen/hypercall.h> | ||
17 | |||
18 | #include <xen/interface/physdev.h> | ||
19 | #include <xen/features.h> | ||
20 | |||
21 | #include "xen-ops.h" | ||
22 | |||
23 | /* These are code, but not functions. Defined in entry.S */ | ||
24 | extern const char xen_hypervisor_callback[]; | ||
25 | extern const char xen_failsafe_callback[]; | ||
26 | |||
27 | unsigned long *phys_to_machine_mapping; | ||
28 | EXPORT_SYMBOL(phys_to_machine_mapping); | ||
29 | |||
30 | /** | ||
31 | * machine_specific_memory_setup - Hook for machine specific memory setup. | ||
32 | **/ | ||
33 | |||
34 | char * __init xen_memory_setup(void) | ||
35 | { | ||
36 | unsigned long max_pfn = xen_start_info->nr_pages; | ||
37 | |||
38 | e820.nr_map = 0; | ||
39 | add_memory_region(0, PFN_PHYS(max_pfn), E820_RAM); | ||
40 | |||
41 | return "Xen"; | ||
42 | } | ||
43 | |||
44 | static void xen_idle(void) | ||
45 | { | ||
46 | local_irq_disable(); | ||
47 | |||
48 | if (need_resched()) | ||
49 | local_irq_enable(); | ||
50 | else { | ||
51 | current_thread_info()->status &= ~TS_POLLING; | ||
52 | smp_mb__after_clear_bit(); | ||
53 | safe_halt(); | ||
54 | current_thread_info()->status |= TS_POLLING; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | void __init xen_arch_setup(void) | ||
59 | { | ||
60 | struct physdev_set_iopl set_iopl; | ||
61 | int rc; | ||
62 | |||
63 | HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments); | ||
64 | HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables); | ||
65 | |||
66 | if (!xen_feature(XENFEAT_auto_translated_physmap)) | ||
67 | HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_pae_extended_cr3); | ||
68 | |||
69 | HYPERVISOR_set_callbacks(__KERNEL_CS, (unsigned long)xen_hypervisor_callback, | ||
70 | __KERNEL_CS, (unsigned long)xen_failsafe_callback); | ||
71 | |||
72 | set_iopl.iopl = 1; | ||
73 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); | ||
74 | if (rc != 0) | ||
75 | printk(KERN_INFO "physdev_op failed %d\n", rc); | ||
76 | |||
77 | #ifdef CONFIG_ACPI | ||
78 | if (!(xen_start_info->flags & SIF_INITDOMAIN)) { | ||
79 | printk(KERN_INFO "ACPI in unprivileged domain disabled\n"); | ||
80 | disable_acpi(); | ||
81 | } | ||
82 | #endif | ||
83 | |||
84 | memcpy(boot_command_line, xen_start_info->cmd_line, | ||
85 | MAX_GUEST_CMDLINE > COMMAND_LINE_SIZE ? | ||
86 | COMMAND_LINE_SIZE : MAX_GUEST_CMDLINE); | ||
87 | |||
88 | pm_idle = xen_idle; | ||
89 | |||
90 | #ifdef CONFIG_SMP | ||
91 | /* fill cpus_possible with all available cpus */ | ||
92 | xen_fill_possible_map(); | ||
93 | #endif | ||
94 | |||
95 | paravirt_disable_iospace(); | ||
96 | } | ||
diff --git a/arch/i386/xen/smp.c b/arch/i386/xen/smp.c new file mode 100644 index 000000000000..557b8e24706a --- /dev/null +++ b/arch/i386/xen/smp.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* | ||
2 | * Xen SMP support | ||
3 | * | ||
4 | * This file implements the Xen versions of smp_ops. SMP under Xen is | ||
5 | * very straightforward. Bringing a CPU up is simply a matter of | ||
6 | * loading its initial context and setting it running. | ||
7 | * | ||
8 | * IPIs are handled through the Xen event mechanism. | ||
9 | * | ||
10 | * Because virtual CPUs can be scheduled onto any real CPU, there's no | ||
11 | * useful topology information for the kernel to make use of. As a | ||
12 | * result, all CPUs are treated as if they're single-core and | ||
13 | * single-threaded. | ||
14 | * | ||
15 | * This does not handle HOTPLUG_CPU yet. | ||
16 | */ | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/smp.h> | ||
20 | |||
21 | #include <asm/paravirt.h> | ||
22 | #include <asm/desc.h> | ||
23 | #include <asm/pgtable.h> | ||
24 | #include <asm/cpu.h> | ||
25 | |||
26 | #include <xen/interface/xen.h> | ||
27 | #include <xen/interface/vcpu.h> | ||
28 | |||
29 | #include <asm/xen/interface.h> | ||
30 | #include <asm/xen/hypercall.h> | ||
31 | |||
32 | #include <xen/page.h> | ||
33 | #include <xen/events.h> | ||
34 | |||
35 | #include "xen-ops.h" | ||
36 | #include "mmu.h" | ||
37 | |||
38 | static cpumask_t cpu_initialized_map; | ||
39 | static DEFINE_PER_CPU(int, resched_irq); | ||
40 | static DEFINE_PER_CPU(int, callfunc_irq); | ||
41 | |||
42 | /* | ||
43 | * Structure and data for smp_call_function(). This is designed to minimise | ||
44 | * static memory requirements. It also looks cleaner. | ||
45 | */ | ||
46 | static DEFINE_SPINLOCK(call_lock); | ||
47 | |||
48 | struct call_data_struct { | ||
49 | void (*func) (void *info); | ||
50 | void *info; | ||
51 | atomic_t started; | ||
52 | atomic_t finished; | ||
53 | int wait; | ||
54 | }; | ||
55 | |||
56 | static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id); | ||
57 | |||
58 | static struct call_data_struct *call_data; | ||
59 | |||
60 | /* | ||
61 | * Reschedule call back. Nothing to do, | ||
62 | * all the work is done automatically when | ||
63 | * we return from the interrupt. | ||
64 | */ | ||
65 | static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) | ||
66 | { | ||
67 | return IRQ_HANDLED; | ||
68 | } | ||
69 | |||
70 | static __cpuinit void cpu_bringup_and_idle(void) | ||
71 | { | ||
72 | int cpu = smp_processor_id(); | ||
73 | |||
74 | cpu_init(); | ||
75 | |||
76 | preempt_disable(); | ||
77 | per_cpu(cpu_state, cpu) = CPU_ONLINE; | ||
78 | |||
79 | xen_setup_cpu_clockevents(); | ||
80 | |||
81 | /* We can take interrupts now: we're officially "up". */ | ||
82 | local_irq_enable(); | ||
83 | |||
84 | wmb(); /* make sure everything is out */ | ||
85 | cpu_idle(); | ||
86 | } | ||
87 | |||
88 | static int xen_smp_intr_init(unsigned int cpu) | ||
89 | { | ||
90 | int rc; | ||
91 | const char *resched_name, *callfunc_name; | ||
92 | |||
93 | per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1; | ||
94 | |||
95 | resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); | ||
96 | rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, | ||
97 | cpu, | ||
98 | xen_reschedule_interrupt, | ||
99 | IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, | ||
100 | resched_name, | ||
101 | NULL); | ||
102 | if (rc < 0) | ||
103 | goto fail; | ||
104 | per_cpu(resched_irq, cpu) = rc; | ||
105 | |||
106 | callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu); | ||
107 | rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, | ||
108 | cpu, | ||
109 | xen_call_function_interrupt, | ||
110 | IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, | ||
111 | callfunc_name, | ||
112 | NULL); | ||
113 | if (rc < 0) | ||
114 | goto fail; | ||
115 | per_cpu(callfunc_irq, cpu) = rc; | ||
116 | |||
117 | return 0; | ||
118 | |||
119 | fail: | ||
120 | if (per_cpu(resched_irq, cpu) >= 0) | ||
121 | unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); | ||
122 | if (per_cpu(callfunc_irq, cpu) >= 0) | ||
123 | unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); | ||
124 | return rc; | ||
125 | } | ||
126 | |||
127 | void __init xen_fill_possible_map(void) | ||
128 | { | ||
129 | int i, rc; | ||
130 | |||
131 | for (i = 0; i < NR_CPUS; i++) { | ||
132 | rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL); | ||
133 | if (rc >= 0) | ||
134 | cpu_set(i, cpu_possible_map); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | void __init xen_smp_prepare_boot_cpu(void) | ||
139 | { | ||
140 | int cpu; | ||
141 | |||
142 | BUG_ON(smp_processor_id() != 0); | ||
143 | native_smp_prepare_boot_cpu(); | ||
144 | |||
145 | /* We've switched to the "real" per-cpu gdt, so make sure the | ||
146 | old memory can be recycled */ | ||
147 | make_lowmem_page_readwrite(&per_cpu__gdt_page); | ||
148 | |||
149 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | ||
150 | cpus_clear(cpu_sibling_map[cpu]); | ||
151 | cpus_clear(cpu_core_map[cpu]); | ||
152 | } | ||
153 | |||
154 | xen_setup_vcpu_info_placement(); | ||
155 | } | ||
156 | |||
157 | void __init xen_smp_prepare_cpus(unsigned int max_cpus) | ||
158 | { | ||
159 | unsigned cpu; | ||
160 | |||
161 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | ||
162 | cpus_clear(cpu_sibling_map[cpu]); | ||
163 | cpus_clear(cpu_core_map[cpu]); | ||
164 | } | ||
165 | |||
166 | smp_store_cpu_info(0); | ||
167 | set_cpu_sibling_map(0); | ||
168 | |||
169 | if (xen_smp_intr_init(0)) | ||
170 | BUG(); | ||
171 | |||
172 | cpu_initialized_map = cpumask_of_cpu(0); | ||
173 | |||
174 | /* Restrict the possible_map according to max_cpus. */ | ||
175 | while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) { | ||
176 | for (cpu = NR_CPUS-1; !cpu_isset(cpu, cpu_possible_map); cpu--) | ||
177 | continue; | ||
178 | cpu_clear(cpu, cpu_possible_map); | ||
179 | } | ||
180 | |||
181 | for_each_possible_cpu (cpu) { | ||
182 | struct task_struct *idle; | ||
183 | |||
184 | if (cpu == 0) | ||
185 | continue; | ||
186 | |||
187 | idle = fork_idle(cpu); | ||
188 | if (IS_ERR(idle)) | ||
189 | panic("failed fork for CPU %d", cpu); | ||
190 | |||
191 | cpu_set(cpu, cpu_present_map); | ||
192 | } | ||
193 | |||
194 | //init_xenbus_allowed_cpumask(); | ||
195 | } | ||
196 | |||
197 | static __cpuinit int | ||
198 | cpu_initialize_context(unsigned int cpu, struct task_struct *idle) | ||
199 | { | ||
200 | struct vcpu_guest_context *ctxt; | ||
201 | struct gdt_page *gdt = &per_cpu(gdt_page, cpu); | ||
202 | |||
203 | if (cpu_test_and_set(cpu, cpu_initialized_map)) | ||
204 | return 0; | ||
205 | |||
206 | ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); | ||
207 | if (ctxt == NULL) | ||
208 | return -ENOMEM; | ||
209 | |||
210 | ctxt->flags = VGCF_IN_KERNEL; | ||
211 | ctxt->user_regs.ds = __USER_DS; | ||
212 | ctxt->user_regs.es = __USER_DS; | ||
213 | ctxt->user_regs.fs = __KERNEL_PERCPU; | ||
214 | ctxt->user_regs.gs = 0; | ||
215 | ctxt->user_regs.ss = __KERNEL_DS; | ||
216 | ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle; | ||
217 | ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ | ||
218 | |||
219 | memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt)); | ||
220 | |||
221 | xen_copy_trap_info(ctxt->trap_ctxt); | ||
222 | |||
223 | ctxt->ldt_ents = 0; | ||
224 | |||
225 | BUG_ON((unsigned long)gdt->gdt & ~PAGE_MASK); | ||
226 | make_lowmem_page_readonly(gdt->gdt); | ||
227 | |||
228 | ctxt->gdt_frames[0] = virt_to_mfn(gdt->gdt); | ||
229 | ctxt->gdt_ents = ARRAY_SIZE(gdt->gdt); | ||
230 | |||
231 | ctxt->user_regs.cs = __KERNEL_CS; | ||
232 | ctxt->user_regs.esp = idle->thread.esp0 - sizeof(struct pt_regs); | ||
233 | |||
234 | ctxt->kernel_ss = __KERNEL_DS; | ||
235 | ctxt->kernel_sp = idle->thread.esp0; | ||
236 | |||
237 | ctxt->event_callback_cs = __KERNEL_CS; | ||
238 | ctxt->event_callback_eip = (unsigned long)xen_hypervisor_callback; | ||
239 | ctxt->failsafe_callback_cs = __KERNEL_CS; | ||
240 | ctxt->failsafe_callback_eip = (unsigned long)xen_failsafe_callback; | ||
241 | |||
242 | per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir); | ||
243 | ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir)); | ||
244 | |||
245 | if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, ctxt)) | ||
246 | BUG(); | ||
247 | |||
248 | kfree(ctxt); | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | int __cpuinit xen_cpu_up(unsigned int cpu) | ||
253 | { | ||
254 | struct task_struct *idle = idle_task(cpu); | ||
255 | int rc; | ||
256 | |||
257 | #if 0 | ||
258 | rc = cpu_up_check(cpu); | ||
259 | if (rc) | ||
260 | return rc; | ||
261 | #endif | ||
262 | |||
263 | init_gdt(cpu); | ||
264 | per_cpu(current_task, cpu) = idle; | ||
265 | irq_ctx_init(cpu); | ||
266 | xen_setup_timer(cpu); | ||
267 | |||
268 | /* make sure interrupts start blocked */ | ||
269 | per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1; | ||
270 | |||
271 | rc = cpu_initialize_context(cpu, idle); | ||
272 | if (rc) | ||
273 | return rc; | ||
274 | |||
275 | if (num_online_cpus() == 1) | ||
276 | alternatives_smp_switch(1); | ||
277 | |||
278 | rc = xen_smp_intr_init(cpu); | ||
279 | if (rc) | ||
280 | return rc; | ||
281 | |||
282 | smp_store_cpu_info(cpu); | ||
283 | set_cpu_sibling_map(cpu); | ||
284 | /* This must be done before setting cpu_online_map */ | ||
285 | wmb(); | ||
286 | |||
287 | cpu_set(cpu, cpu_online_map); | ||
288 | |||
289 | rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); | ||
290 | BUG_ON(rc); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | void xen_smp_cpus_done(unsigned int max_cpus) | ||
296 | { | ||
297 | } | ||
298 | |||
299 | static void stop_self(void *v) | ||
300 | { | ||
301 | int cpu = smp_processor_id(); | ||
302 | |||
303 | /* make sure we're not pinning something down */ | ||
304 | load_cr3(swapper_pg_dir); | ||
305 | /* should set up a minimal gdt */ | ||
306 | |||
307 | HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL); | ||
308 | BUG(); | ||
309 | } | ||
310 | |||
311 | void xen_smp_send_stop(void) | ||
312 | { | ||
313 | smp_call_function(stop_self, NULL, 0, 0); | ||
314 | } | ||
315 | |||
316 | void xen_smp_send_reschedule(int cpu) | ||
317 | { | ||
318 | xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR); | ||
319 | } | ||
320 | |||
321 | |||
322 | static void xen_send_IPI_mask(cpumask_t mask, enum ipi_vector vector) | ||
323 | { | ||
324 | unsigned cpu; | ||
325 | |||
326 | cpus_and(mask, mask, cpu_online_map); | ||
327 | |||
328 | for_each_cpu_mask(cpu, mask) | ||
329 | xen_send_IPI_one(cpu, vector); | ||
330 | } | ||
331 | |||
332 | static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id) | ||
333 | { | ||
334 | void (*func) (void *info) = call_data->func; | ||
335 | void *info = call_data->info; | ||
336 | int wait = call_data->wait; | ||
337 | |||
338 | /* | ||
339 | * Notify initiating CPU that I've grabbed the data and am | ||
340 | * about to execute the function | ||
341 | */ | ||
342 | mb(); | ||
343 | atomic_inc(&call_data->started); | ||
344 | /* | ||
345 | * At this point the info structure may be out of scope unless wait==1 | ||
346 | */ | ||
347 | irq_enter(); | ||
348 | (*func)(info); | ||
349 | irq_exit(); | ||
350 | |||
351 | if (wait) { | ||
352 | mb(); /* commit everything before setting finished */ | ||
353 | atomic_inc(&call_data->finished); | ||
354 | } | ||
355 | |||
356 | return IRQ_HANDLED; | ||
357 | } | ||
358 | |||
359 | int xen_smp_call_function_mask(cpumask_t mask, void (*func)(void *), | ||
360 | void *info, int wait) | ||
361 | { | ||
362 | struct call_data_struct data; | ||
363 | int cpus; | ||
364 | |||
365 | /* Holding any lock stops cpus from going down. */ | ||
366 | spin_lock(&call_lock); | ||
367 | |||
368 | cpu_clear(smp_processor_id(), mask); | ||
369 | |||
370 | cpus = cpus_weight(mask); | ||
371 | if (!cpus) { | ||
372 | spin_unlock(&call_lock); | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | /* Can deadlock when called with interrupts disabled */ | ||
377 | WARN_ON(irqs_disabled()); | ||
378 | |||
379 | data.func = func; | ||
380 | data.info = info; | ||
381 | atomic_set(&data.started, 0); | ||
382 | data.wait = wait; | ||
383 | if (wait) | ||
384 | atomic_set(&data.finished, 0); | ||
385 | |||
386 | call_data = &data; | ||
387 | mb(); /* write everything before IPI */ | ||
388 | |||
389 | /* Send a message to other CPUs and wait for them to respond */ | ||
390 | xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR); | ||
391 | |||
392 | /* Make sure other vcpus get a chance to run. | ||
393 | XXX too severe? Maybe we should check the other CPU's states? */ | ||
394 | HYPERVISOR_sched_op(SCHEDOP_yield, 0); | ||
395 | |||
396 | /* Wait for response */ | ||
397 | while (atomic_read(&data.started) != cpus || | ||
398 | (wait && atomic_read(&data.finished) != cpus)) | ||
399 | cpu_relax(); | ||
400 | |||
401 | spin_unlock(&call_lock); | ||
402 | |||
403 | return 0; | ||
404 | } | ||
diff --git a/arch/i386/xen/time.c b/arch/i386/xen/time.c new file mode 100644 index 000000000000..51fdabf1fd4d --- /dev/null +++ b/arch/i386/xen/time.c | |||
@@ -0,0 +1,590 @@ | |||
1 | /* | ||
2 | * Xen time implementation. | ||
3 | * | ||
4 | * This is implemented in terms of a clocksource driver which uses | ||
5 | * the hypervisor clock as a nanosecond timebase, and a clockevent | ||
6 | * driver which uses the hypervisor's timer mechanism. | ||
7 | * | ||
8 | * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/clocksource.h> | ||
13 | #include <linux/clockchips.h> | ||
14 | #include <linux/kernel_stat.h> | ||
15 | |||
16 | #include <asm/xen/hypervisor.h> | ||
17 | #include <asm/xen/hypercall.h> | ||
18 | |||
19 | #include <xen/events.h> | ||
20 | #include <xen/interface/xen.h> | ||
21 | #include <xen/interface/vcpu.h> | ||
22 | |||
23 | #include "xen-ops.h" | ||
24 | |||
25 | #define XEN_SHIFT 22 | ||
26 | |||
27 | /* Xen may fire a timer up to this many ns early */ | ||
28 | #define TIMER_SLOP 100000 | ||
29 | #define NS_PER_TICK (1000000000LL / HZ) | ||
30 | |||
31 | static cycle_t xen_clocksource_read(void); | ||
32 | |||
33 | /* These are perodically updated in shared_info, and then copied here. */ | ||
34 | struct shadow_time_info { | ||
35 | u64 tsc_timestamp; /* TSC at last update of time vals. */ | ||
36 | u64 system_timestamp; /* Time, in nanosecs, since boot. */ | ||
37 | u32 tsc_to_nsec_mul; | ||
38 | int tsc_shift; | ||
39 | u32 version; | ||
40 | }; | ||
41 | |||
42 | static DEFINE_PER_CPU(struct shadow_time_info, shadow_time); | ||
43 | |||
44 | /* runstate info updated by Xen */ | ||
45 | static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); | ||
46 | |||
47 | /* snapshots of runstate info */ | ||
48 | static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate_snapshot); | ||
49 | |||
50 | /* unused ns of stolen and blocked time */ | ||
51 | static DEFINE_PER_CPU(u64, residual_stolen); | ||
52 | static DEFINE_PER_CPU(u64, residual_blocked); | ||
53 | |||
54 | /* return an consistent snapshot of 64-bit time/counter value */ | ||
55 | static u64 get64(const u64 *p) | ||
56 | { | ||
57 | u64 ret; | ||
58 | |||
59 | if (BITS_PER_LONG < 64) { | ||
60 | u32 *p32 = (u32 *)p; | ||
61 | u32 h, l; | ||
62 | |||
63 | /* | ||
64 | * Read high then low, and then make sure high is | ||
65 | * still the same; this will only loop if low wraps | ||
66 | * and carries into high. | ||
67 | * XXX some clean way to make this endian-proof? | ||
68 | */ | ||
69 | do { | ||
70 | h = p32[1]; | ||
71 | barrier(); | ||
72 | l = p32[0]; | ||
73 | barrier(); | ||
74 | } while (p32[1] != h); | ||
75 | |||
76 | ret = (((u64)h) << 32) | l; | ||
77 | } else | ||
78 | ret = *p; | ||
79 | |||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Runstate accounting | ||
85 | */ | ||
86 | static void get_runstate_snapshot(struct vcpu_runstate_info *res) | ||
87 | { | ||
88 | u64 state_time; | ||
89 | struct vcpu_runstate_info *state; | ||
90 | |||
91 | BUG_ON(preemptible()); | ||
92 | |||
93 | state = &__get_cpu_var(runstate); | ||
94 | |||
95 | /* | ||
96 | * The runstate info is always updated by the hypervisor on | ||
97 | * the current CPU, so there's no need to use anything | ||
98 | * stronger than a compiler barrier when fetching it. | ||
99 | */ | ||
100 | do { | ||
101 | state_time = get64(&state->state_entry_time); | ||
102 | barrier(); | ||
103 | *res = *state; | ||
104 | barrier(); | ||
105 | } while (get64(&state->state_entry_time) != state_time); | ||
106 | } | ||
107 | |||
108 | static void setup_runstate_info(int cpu) | ||
109 | { | ||
110 | struct vcpu_register_runstate_memory_area area; | ||
111 | |||
112 | area.addr.v = &per_cpu(runstate, cpu); | ||
113 | |||
114 | if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, | ||
115 | cpu, &area)) | ||
116 | BUG(); | ||
117 | } | ||
118 | |||
119 | static void do_stolen_accounting(void) | ||
120 | { | ||
121 | struct vcpu_runstate_info state; | ||
122 | struct vcpu_runstate_info *snap; | ||
123 | s64 blocked, runnable, offline, stolen; | ||
124 | cputime_t ticks; | ||
125 | |||
126 | get_runstate_snapshot(&state); | ||
127 | |||
128 | WARN_ON(state.state != RUNSTATE_running); | ||
129 | |||
130 | snap = &__get_cpu_var(runstate_snapshot); | ||
131 | |||
132 | /* work out how much time the VCPU has not been runn*ing* */ | ||
133 | blocked = state.time[RUNSTATE_blocked] - snap->time[RUNSTATE_blocked]; | ||
134 | runnable = state.time[RUNSTATE_runnable] - snap->time[RUNSTATE_runnable]; | ||
135 | offline = state.time[RUNSTATE_offline] - snap->time[RUNSTATE_offline]; | ||
136 | |||
137 | *snap = state; | ||
138 | |||
139 | /* Add the appropriate number of ticks of stolen time, | ||
140 | including any left-overs from last time. Passing NULL to | ||
141 | account_steal_time accounts the time as stolen. */ | ||
142 | stolen = runnable + offline + __get_cpu_var(residual_stolen); | ||
143 | |||
144 | if (stolen < 0) | ||
145 | stolen = 0; | ||
146 | |||
147 | ticks = 0; | ||
148 | while (stolen >= NS_PER_TICK) { | ||
149 | ticks++; | ||
150 | stolen -= NS_PER_TICK; | ||
151 | } | ||
152 | __get_cpu_var(residual_stolen) = stolen; | ||
153 | account_steal_time(NULL, ticks); | ||
154 | |||
155 | /* Add the appropriate number of ticks of blocked time, | ||
156 | including any left-overs from last time. Passing idle to | ||
157 | account_steal_time accounts the time as idle/wait. */ | ||
158 | blocked += __get_cpu_var(residual_blocked); | ||
159 | |||
160 | if (blocked < 0) | ||
161 | blocked = 0; | ||
162 | |||
163 | ticks = 0; | ||
164 | while (blocked >= NS_PER_TICK) { | ||
165 | ticks++; | ||
166 | blocked -= NS_PER_TICK; | ||
167 | } | ||
168 | __get_cpu_var(residual_blocked) = blocked; | ||
169 | account_steal_time(idle_task(smp_processor_id()), ticks); | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Xen sched_clock implementation. Returns the number of unstolen | ||
174 | * nanoseconds, which is nanoseconds the VCPU spent in RUNNING+BLOCKED | ||
175 | * states. | ||
176 | */ | ||
177 | unsigned long long xen_sched_clock(void) | ||
178 | { | ||
179 | struct vcpu_runstate_info state; | ||
180 | cycle_t now; | ||
181 | u64 ret; | ||
182 | s64 offset; | ||
183 | |||
184 | /* | ||
185 | * Ideally sched_clock should be called on a per-cpu basis | ||
186 | * anyway, so preempt should already be disabled, but that's | ||
187 | * not current practice at the moment. | ||
188 | */ | ||
189 | preempt_disable(); | ||
190 | |||
191 | now = xen_clocksource_read(); | ||
192 | |||
193 | get_runstate_snapshot(&state); | ||
194 | |||
195 | WARN_ON(state.state != RUNSTATE_running); | ||
196 | |||
197 | offset = now - state.state_entry_time; | ||
198 | if (offset < 0) | ||
199 | offset = 0; | ||
200 | |||
201 | ret = state.time[RUNSTATE_blocked] + | ||
202 | state.time[RUNSTATE_running] + | ||
203 | offset; | ||
204 | |||
205 | preempt_enable(); | ||
206 | |||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | |||
211 | /* Get the CPU speed from Xen */ | ||
212 | unsigned long xen_cpu_khz(void) | ||
213 | { | ||
214 | u64 cpu_khz = 1000000ULL << 32; | ||
215 | const struct vcpu_time_info *info = | ||
216 | &HYPERVISOR_shared_info->vcpu_info[0].time; | ||
217 | |||
218 | do_div(cpu_khz, info->tsc_to_system_mul); | ||
219 | if (info->tsc_shift < 0) | ||
220 | cpu_khz <<= -info->tsc_shift; | ||
221 | else | ||
222 | cpu_khz >>= info->tsc_shift; | ||
223 | |||
224 | return cpu_khz; | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * Reads a consistent set of time-base values from Xen, into a shadow data | ||
229 | * area. | ||
230 | */ | ||
231 | static unsigned get_time_values_from_xen(void) | ||
232 | { | ||
233 | struct vcpu_time_info *src; | ||
234 | struct shadow_time_info *dst; | ||
235 | |||
236 | /* src is shared memory with the hypervisor, so we need to | ||
237 | make sure we get a consistent snapshot, even in the face of | ||
238 | being preempted. */ | ||
239 | src = &__get_cpu_var(xen_vcpu)->time; | ||
240 | dst = &__get_cpu_var(shadow_time); | ||
241 | |||
242 | do { | ||
243 | dst->version = src->version; | ||
244 | rmb(); /* fetch version before data */ | ||
245 | dst->tsc_timestamp = src->tsc_timestamp; | ||
246 | dst->system_timestamp = src->system_time; | ||
247 | dst->tsc_to_nsec_mul = src->tsc_to_system_mul; | ||
248 | dst->tsc_shift = src->tsc_shift; | ||
249 | rmb(); /* test version after fetching data */ | ||
250 | } while ((src->version & 1) | (dst->version ^ src->version)); | ||
251 | |||
252 | return dst->version; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, | ||
257 | * yielding a 64-bit result. | ||
258 | */ | ||
259 | static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift) | ||
260 | { | ||
261 | u64 product; | ||
262 | #ifdef __i386__ | ||
263 | u32 tmp1, tmp2; | ||
264 | #endif | ||
265 | |||
266 | if (shift < 0) | ||
267 | delta >>= -shift; | ||
268 | else | ||
269 | delta <<= shift; | ||
270 | |||
271 | #ifdef __i386__ | ||
272 | __asm__ ( | ||
273 | "mul %5 ; " | ||
274 | "mov %4,%%eax ; " | ||
275 | "mov %%edx,%4 ; " | ||
276 | "mul %5 ; " | ||
277 | "xor %5,%5 ; " | ||
278 | "add %4,%%eax ; " | ||
279 | "adc %5,%%edx ; " | ||
280 | : "=A" (product), "=r" (tmp1), "=r" (tmp2) | ||
281 | : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) ); | ||
282 | #elif __x86_64__ | ||
283 | __asm__ ( | ||
284 | "mul %%rdx ; shrd $32,%%rdx,%%rax" | ||
285 | : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) ); | ||
286 | #else | ||
287 | #error implement me! | ||
288 | #endif | ||
289 | |||
290 | return product; | ||
291 | } | ||
292 | |||
293 | static u64 get_nsec_offset(struct shadow_time_info *shadow) | ||
294 | { | ||
295 | u64 now, delta; | ||
296 | now = native_read_tsc(); | ||
297 | delta = now - shadow->tsc_timestamp; | ||
298 | return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift); | ||
299 | } | ||
300 | |||
301 | static cycle_t xen_clocksource_read(void) | ||
302 | { | ||
303 | struct shadow_time_info *shadow = &get_cpu_var(shadow_time); | ||
304 | cycle_t ret; | ||
305 | unsigned version; | ||
306 | |||
307 | do { | ||
308 | version = get_time_values_from_xen(); | ||
309 | barrier(); | ||
310 | ret = shadow->system_timestamp + get_nsec_offset(shadow); | ||
311 | barrier(); | ||
312 | } while (version != __get_cpu_var(xen_vcpu)->time.version); | ||
313 | |||
314 | put_cpu_var(shadow_time); | ||
315 | |||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | static void xen_read_wallclock(struct timespec *ts) | ||
320 | { | ||
321 | const struct shared_info *s = HYPERVISOR_shared_info; | ||
322 | u32 version; | ||
323 | u64 delta; | ||
324 | struct timespec now; | ||
325 | |||
326 | /* get wallclock at system boot */ | ||
327 | do { | ||
328 | version = s->wc_version; | ||
329 | rmb(); /* fetch version before time */ | ||
330 | now.tv_sec = s->wc_sec; | ||
331 | now.tv_nsec = s->wc_nsec; | ||
332 | rmb(); /* fetch time before checking version */ | ||
333 | } while ((s->wc_version & 1) | (version ^ s->wc_version)); | ||
334 | |||
335 | delta = xen_clocksource_read(); /* time since system boot */ | ||
336 | delta += now.tv_sec * (u64)NSEC_PER_SEC + now.tv_nsec; | ||
337 | |||
338 | now.tv_nsec = do_div(delta, NSEC_PER_SEC); | ||
339 | now.tv_sec = delta; | ||
340 | |||
341 | set_normalized_timespec(ts, now.tv_sec, now.tv_nsec); | ||
342 | } | ||
343 | |||
344 | unsigned long xen_get_wallclock(void) | ||
345 | { | ||
346 | struct timespec ts; | ||
347 | |||
348 | xen_read_wallclock(&ts); | ||
349 | |||
350 | return ts.tv_sec; | ||
351 | } | ||
352 | |||
353 | int xen_set_wallclock(unsigned long now) | ||
354 | { | ||
355 | /* do nothing for domU */ | ||
356 | return -1; | ||
357 | } | ||
358 | |||
359 | static struct clocksource xen_clocksource __read_mostly = { | ||
360 | .name = "xen", | ||
361 | .rating = 400, | ||
362 | .read = xen_clocksource_read, | ||
363 | .mask = ~0, | ||
364 | .mult = 1<<XEN_SHIFT, /* time directly in nanoseconds */ | ||
365 | .shift = XEN_SHIFT, | ||
366 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
367 | }; | ||
368 | |||
369 | /* | ||
370 | Xen clockevent implementation | ||
371 | |||
372 | Xen has two clockevent implementations: | ||
373 | |||
374 | The old timer_op one works with all released versions of Xen prior | ||
375 | to version 3.0.4. This version of the hypervisor provides a | ||
376 | single-shot timer with nanosecond resolution. However, sharing the | ||
377 | same event channel is a 100Hz tick which is delivered while the | ||
378 | vcpu is running. We don't care about or use this tick, but it will | ||
379 | cause the core time code to think the timer fired too soon, and | ||
380 | will end up resetting it each time. It could be filtered, but | ||
381 | doing so has complications when the ktime clocksource is not yet | ||
382 | the xen clocksource (ie, at boot time). | ||
383 | |||
384 | The new vcpu_op-based timer interface allows the tick timer period | ||
385 | to be changed or turned off. The tick timer is not useful as a | ||
386 | periodic timer because events are only delivered to running vcpus. | ||
387 | The one-shot timer can report when a timeout is in the past, so | ||
388 | set_next_event is capable of returning -ETIME when appropriate. | ||
389 | This interface is used when available. | ||
390 | */ | ||
391 | |||
392 | |||
393 | /* | ||
394 | Get a hypervisor absolute time. In theory we could maintain an | ||
395 | offset between the kernel's time and the hypervisor's time, and | ||
396 | apply that to a kernel's absolute timeout. Unfortunately the | ||
397 | hypervisor and kernel times can drift even if the kernel is using | ||
398 | the Xen clocksource, because ntp can warp the kernel's clocksource. | ||
399 | */ | ||
400 | static s64 get_abs_timeout(unsigned long delta) | ||
401 | { | ||
402 | return xen_clocksource_read() + delta; | ||
403 | } | ||
404 | |||
405 | static void xen_timerop_set_mode(enum clock_event_mode mode, | ||
406 | struct clock_event_device *evt) | ||
407 | { | ||
408 | switch (mode) { | ||
409 | case CLOCK_EVT_MODE_PERIODIC: | ||
410 | /* unsupported */ | ||
411 | WARN_ON(1); | ||
412 | break; | ||
413 | |||
414 | case CLOCK_EVT_MODE_ONESHOT: | ||
415 | break; | ||
416 | |||
417 | case CLOCK_EVT_MODE_UNUSED: | ||
418 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
419 | HYPERVISOR_set_timer_op(0); /* cancel timeout */ | ||
420 | break; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | static int xen_timerop_set_next_event(unsigned long delta, | ||
425 | struct clock_event_device *evt) | ||
426 | { | ||
427 | WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT); | ||
428 | |||
429 | if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0) | ||
430 | BUG(); | ||
431 | |||
432 | /* We may have missed the deadline, but there's no real way of | ||
433 | knowing for sure. If the event was in the past, then we'll | ||
434 | get an immediate interrupt. */ | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static const struct clock_event_device xen_timerop_clockevent = { | ||
440 | .name = "xen", | ||
441 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
442 | |||
443 | .max_delta_ns = 0xffffffff, | ||
444 | .min_delta_ns = TIMER_SLOP, | ||
445 | |||
446 | .mult = 1, | ||
447 | .shift = 0, | ||
448 | .rating = 500, | ||
449 | |||
450 | .set_mode = xen_timerop_set_mode, | ||
451 | .set_next_event = xen_timerop_set_next_event, | ||
452 | }; | ||
453 | |||
454 | |||
455 | |||
456 | static void xen_vcpuop_set_mode(enum clock_event_mode mode, | ||
457 | struct clock_event_device *evt) | ||
458 | { | ||
459 | int cpu = smp_processor_id(); | ||
460 | |||
461 | switch (mode) { | ||
462 | case CLOCK_EVT_MODE_PERIODIC: | ||
463 | WARN_ON(1); /* unsupported */ | ||
464 | break; | ||
465 | |||
466 | case CLOCK_EVT_MODE_ONESHOT: | ||
467 | if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL)) | ||
468 | BUG(); | ||
469 | break; | ||
470 | |||
471 | case CLOCK_EVT_MODE_UNUSED: | ||
472 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
473 | if (HYPERVISOR_vcpu_op(VCPUOP_stop_singleshot_timer, cpu, NULL) || | ||
474 | HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL)) | ||
475 | BUG(); | ||
476 | break; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | static int xen_vcpuop_set_next_event(unsigned long delta, | ||
481 | struct clock_event_device *evt) | ||
482 | { | ||
483 | int cpu = smp_processor_id(); | ||
484 | struct vcpu_set_singleshot_timer single; | ||
485 | int ret; | ||
486 | |||
487 | WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT); | ||
488 | |||
489 | single.timeout_abs_ns = get_abs_timeout(delta); | ||
490 | single.flags = VCPU_SSHOTTMR_future; | ||
491 | |||
492 | ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single); | ||
493 | |||
494 | BUG_ON(ret != 0 && ret != -ETIME); | ||
495 | |||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | static const struct clock_event_device xen_vcpuop_clockevent = { | ||
500 | .name = "xen", | ||
501 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
502 | |||
503 | .max_delta_ns = 0xffffffff, | ||
504 | .min_delta_ns = TIMER_SLOP, | ||
505 | |||
506 | .mult = 1, | ||
507 | .shift = 0, | ||
508 | .rating = 500, | ||
509 | |||
510 | .set_mode = xen_vcpuop_set_mode, | ||
511 | .set_next_event = xen_vcpuop_set_next_event, | ||
512 | }; | ||
513 | |||
514 | static const struct clock_event_device *xen_clockevent = | ||
515 | &xen_timerop_clockevent; | ||
516 | static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events); | ||
517 | |||
518 | static irqreturn_t xen_timer_interrupt(int irq, void *dev_id) | ||
519 | { | ||
520 | struct clock_event_device *evt = &__get_cpu_var(xen_clock_events); | ||
521 | irqreturn_t ret; | ||
522 | |||
523 | ret = IRQ_NONE; | ||
524 | if (evt->event_handler) { | ||
525 | evt->event_handler(evt); | ||
526 | ret = IRQ_HANDLED; | ||
527 | } | ||
528 | |||
529 | do_stolen_accounting(); | ||
530 | |||
531 | return ret; | ||
532 | } | ||
533 | |||
534 | void xen_setup_timer(int cpu) | ||
535 | { | ||
536 | const char *name; | ||
537 | struct clock_event_device *evt; | ||
538 | int irq; | ||
539 | |||
540 | printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu); | ||
541 | |||
542 | name = kasprintf(GFP_KERNEL, "timer%d", cpu); | ||
543 | if (!name) | ||
544 | name = "<timer kasprintf failed>"; | ||
545 | |||
546 | irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt, | ||
547 | IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, | ||
548 | name, NULL); | ||
549 | |||
550 | evt = &per_cpu(xen_clock_events, cpu); | ||
551 | memcpy(evt, xen_clockevent, sizeof(*evt)); | ||
552 | |||
553 | evt->cpumask = cpumask_of_cpu(cpu); | ||
554 | evt->irq = irq; | ||
555 | |||
556 | setup_runstate_info(cpu); | ||
557 | } | ||
558 | |||
559 | void xen_setup_cpu_clockevents(void) | ||
560 | { | ||
561 | BUG_ON(preemptible()); | ||
562 | |||
563 | clockevents_register_device(&__get_cpu_var(xen_clock_events)); | ||
564 | } | ||
565 | |||
566 | __init void xen_time_init(void) | ||
567 | { | ||
568 | int cpu = smp_processor_id(); | ||
569 | |||
570 | get_time_values_from_xen(); | ||
571 | |||
572 | clocksource_register(&xen_clocksource); | ||
573 | |||
574 | if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL) == 0) { | ||
575 | /* Successfully turned off 100Hz tick, so we have the | ||
576 | vcpuop-based timer interface */ | ||
577 | printk(KERN_DEBUG "Xen: using vcpuop timer interface\n"); | ||
578 | xen_clockevent = &xen_vcpuop_clockevent; | ||
579 | } | ||
580 | |||
581 | /* Set initial system time with full resolution */ | ||
582 | xen_read_wallclock(&xtime); | ||
583 | set_normalized_timespec(&wall_to_monotonic, | ||
584 | -xtime.tv_sec, -xtime.tv_nsec); | ||
585 | |||
586 | tsc_disable = 0; | ||
587 | |||
588 | xen_setup_timer(cpu); | ||
589 | xen_setup_cpu_clockevents(); | ||
590 | } | ||
diff --git a/arch/i386/xen/xen-asm.S b/arch/i386/xen/xen-asm.S new file mode 100644 index 000000000000..1a43b60c0c62 --- /dev/null +++ b/arch/i386/xen/xen-asm.S | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | Asm versions of Xen pv-ops, suitable for either direct use or inlining. | ||
3 | The inline versions are the same as the direct-use versions, with the | ||
4 | pre- and post-amble chopped off. | ||
5 | |||
6 | This code is encoded for size rather than absolute efficiency, | ||
7 | with a view to being able to inline as much as possible. | ||
8 | |||
9 | We only bother with direct forms (ie, vcpu in pda) of the operations | ||
10 | here; the indirect forms are better handled in C, since they're | ||
11 | generally too large to inline anyway. | ||
12 | */ | ||
13 | |||
14 | #include <linux/linkage.h> | ||
15 | |||
16 | #include <asm/asm-offsets.h> | ||
17 | #include <asm/thread_info.h> | ||
18 | #include <asm/percpu.h> | ||
19 | #include <asm/processor-flags.h> | ||
20 | #include <asm/segment.h> | ||
21 | |||
22 | #include <xen/interface/xen.h> | ||
23 | |||
24 | #define RELOC(x, v) .globl x##_reloc; x##_reloc=v | ||
25 | #define ENDPATCH(x) .globl x##_end; x##_end=. | ||
26 | |||
27 | /* Pseudo-flag used for virtual NMI, which we don't implement yet */ | ||
28 | #define XEN_EFLAGS_NMI 0x80000000 | ||
29 | |||
30 | /* | ||
31 | Enable events. This clears the event mask and tests the pending | ||
32 | event status with one and operation. If there are pending | ||
33 | events, then enter the hypervisor to get them handled. | ||
34 | */ | ||
35 | ENTRY(xen_irq_enable_direct) | ||
36 | /* Clear mask and test pending */ | ||
37 | andw $0x00ff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending | ||
38 | /* Preempt here doesn't matter because that will deal with | ||
39 | any pending interrupts. The pending check may end up being | ||
40 | run on the wrong CPU, but that doesn't hurt. */ | ||
41 | jz 1f | ||
42 | 2: call check_events | ||
43 | 1: | ||
44 | ENDPATCH(xen_irq_enable_direct) | ||
45 | ret | ||
46 | ENDPROC(xen_irq_enable_direct) | ||
47 | RELOC(xen_irq_enable_direct, 2b+1) | ||
48 | |||
49 | |||
50 | /* | ||
51 | Disabling events is simply a matter of making the event mask | ||
52 | non-zero. | ||
53 | */ | ||
54 | ENTRY(xen_irq_disable_direct) | ||
55 | movb $1, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask | ||
56 | ENDPATCH(xen_irq_disable_direct) | ||
57 | ret | ||
58 | ENDPROC(xen_irq_disable_direct) | ||
59 | RELOC(xen_irq_disable_direct, 0) | ||
60 | |||
61 | /* | ||
62 | (xen_)save_fl is used to get the current interrupt enable status. | ||
63 | Callers expect the status to be in X86_EFLAGS_IF, and other bits | ||
64 | may be set in the return value. We take advantage of this by | ||
65 | making sure that X86_EFLAGS_IF has the right value (and other bits | ||
66 | in that byte are 0), but other bits in the return value are | ||
67 | undefined. We need to toggle the state of the bit, because | ||
68 | Xen and x86 use opposite senses (mask vs enable). | ||
69 | */ | ||
70 | ENTRY(xen_save_fl_direct) | ||
71 | testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask | ||
72 | setz %ah | ||
73 | addb %ah,%ah | ||
74 | ENDPATCH(xen_save_fl_direct) | ||
75 | ret | ||
76 | ENDPROC(xen_save_fl_direct) | ||
77 | RELOC(xen_save_fl_direct, 0) | ||
78 | |||
79 | |||
80 | /* | ||
81 | In principle the caller should be passing us a value return | ||
82 | from xen_save_fl_direct, but for robustness sake we test only | ||
83 | the X86_EFLAGS_IF flag rather than the whole byte. After | ||
84 | setting the interrupt mask state, it checks for unmasked | ||
85 | pending events and enters the hypervisor to get them delivered | ||
86 | if so. | ||
87 | */ | ||
88 | ENTRY(xen_restore_fl_direct) | ||
89 | testb $X86_EFLAGS_IF>>8, %ah | ||
90 | setz PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask | ||
91 | /* Preempt here doesn't matter because that will deal with | ||
92 | any pending interrupts. The pending check may end up being | ||
93 | run on the wrong CPU, but that doesn't hurt. */ | ||
94 | |||
95 | /* check for unmasked and pending */ | ||
96 | cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending | ||
97 | jz 1f | ||
98 | 2: call check_events | ||
99 | 1: | ||
100 | ENDPATCH(xen_restore_fl_direct) | ||
101 | ret | ||
102 | ENDPROC(xen_restore_fl_direct) | ||
103 | RELOC(xen_restore_fl_direct, 2b+1) | ||
104 | |||
105 | /* | ||
106 | This is run where a normal iret would be run, with the same stack setup: | ||
107 | 8: eflags | ||
108 | 4: cs | ||
109 | esp-> 0: eip | ||
110 | |||
111 | This attempts to make sure that any pending events are dealt | ||
112 | with on return to usermode, but there is a small window in | ||
113 | which an event can happen just before entering usermode. If | ||
114 | the nested interrupt ends up setting one of the TIF_WORK_MASK | ||
115 | pending work flags, they will not be tested again before | ||
116 | returning to usermode. This means that a process can end up | ||
117 | with pending work, which will be unprocessed until the process | ||
118 | enters and leaves the kernel again, which could be an | ||
119 | unbounded amount of time. This means that a pending signal or | ||
120 | reschedule event could be indefinitely delayed. | ||
121 | |||
122 | The fix is to notice a nested interrupt in the critical | ||
123 | window, and if one occurs, then fold the nested interrupt into | ||
124 | the current interrupt stack frame, and re-process it | ||
125 | iteratively rather than recursively. This means that it will | ||
126 | exit via the normal path, and all pending work will be dealt | ||
127 | with appropriately. | ||
128 | |||
129 | Because the nested interrupt handler needs to deal with the | ||
130 | current stack state in whatever form its in, we keep things | ||
131 | simple by only using a single register which is pushed/popped | ||
132 | on the stack. | ||
133 | |||
134 | Non-direct iret could be done in the same way, but it would | ||
135 | require an annoying amount of code duplication. We'll assume | ||
136 | that direct mode will be the common case once the hypervisor | ||
137 | support becomes commonplace. | ||
138 | */ | ||
139 | ENTRY(xen_iret_direct) | ||
140 | /* test eflags for special cases */ | ||
141 | testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp) | ||
142 | jnz hyper_iret | ||
143 | |||
144 | push %eax | ||
145 | ESP_OFFSET=4 # bytes pushed onto stack | ||
146 | |||
147 | /* Store vcpu_info pointer for easy access. Do it this | ||
148 | way to avoid having to reload %fs */ | ||
149 | #ifdef CONFIG_SMP | ||
150 | GET_THREAD_INFO(%eax) | ||
151 | movl TI_cpu(%eax),%eax | ||
152 | movl __per_cpu_offset(,%eax,4),%eax | ||
153 | lea per_cpu__xen_vcpu_info(%eax),%eax | ||
154 | #else | ||
155 | movl $per_cpu__xen_vcpu_info, %eax | ||
156 | #endif | ||
157 | |||
158 | /* check IF state we're restoring */ | ||
159 | testb $X86_EFLAGS_IF>>8, 8+1+ESP_OFFSET(%esp) | ||
160 | |||
161 | /* Maybe enable events. Once this happens we could get a | ||
162 | recursive event, so the critical region starts immediately | ||
163 | afterwards. However, if that happens we don't end up | ||
164 | resuming the code, so we don't have to be worried about | ||
165 | being preempted to another CPU. */ | ||
166 | setz XEN_vcpu_info_mask(%eax) | ||
167 | xen_iret_start_crit: | ||
168 | |||
169 | /* check for unmasked and pending */ | ||
170 | cmpw $0x0001, XEN_vcpu_info_pending(%eax) | ||
171 | |||
172 | /* If there's something pending, mask events again so we | ||
173 | can jump back into xen_hypervisor_callback */ | ||
174 | sete XEN_vcpu_info_mask(%eax) | ||
175 | |||
176 | popl %eax | ||
177 | |||
178 | /* From this point on the registers are restored and the stack | ||
179 | updated, so we don't need to worry about it if we're preempted */ | ||
180 | iret_restore_end: | ||
181 | |||
182 | /* Jump to hypervisor_callback after fixing up the stack. | ||
183 | Events are masked, so jumping out of the critical | ||
184 | region is OK. */ | ||
185 | je xen_hypervisor_callback | ||
186 | |||
187 | iret | ||
188 | xen_iret_end_crit: | ||
189 | |||
190 | hyper_iret: | ||
191 | /* put this out of line since its very rarely used */ | ||
192 | jmp hypercall_page + __HYPERVISOR_iret * 32 | ||
193 | |||
194 | .globl xen_iret_start_crit, xen_iret_end_crit | ||
195 | |||
196 | /* | ||
197 | This is called by xen_hypervisor_callback in entry.S when it sees | ||
198 | that the EIP at the time of interrupt was between xen_iret_start_crit | ||
199 | and xen_iret_end_crit. We're passed the EIP in %eax so we can do | ||
200 | a more refined determination of what to do. | ||
201 | |||
202 | The stack format at this point is: | ||
203 | ---------------- | ||
204 | ss : (ss/esp may be present if we came from usermode) | ||
205 | esp : | ||
206 | eflags } outer exception info | ||
207 | cs } | ||
208 | eip } | ||
209 | ---------------- <- edi (copy dest) | ||
210 | eax : outer eax if it hasn't been restored | ||
211 | ---------------- | ||
212 | eflags } nested exception info | ||
213 | cs } (no ss/esp because we're nested | ||
214 | eip } from the same ring) | ||
215 | orig_eax }<- esi (copy src) | ||
216 | - - - - - - - - | ||
217 | fs } | ||
218 | es } | ||
219 | ds } SAVE_ALL state | ||
220 | eax } | ||
221 | : : | ||
222 | ebx } | ||
223 | ---------------- | ||
224 | return addr <- esp | ||
225 | ---------------- | ||
226 | |||
227 | In order to deliver the nested exception properly, we need to shift | ||
228 | everything from the return addr up to the error code so it | ||
229 | sits just under the outer exception info. This means that when we | ||
230 | handle the exception, we do it in the context of the outer exception | ||
231 | rather than starting a new one. | ||
232 | |||
233 | The only caveat is that if the outer eax hasn't been | ||
234 | restored yet (ie, it's still on stack), we need to insert | ||
235 | its value into the SAVE_ALL state before going on, since | ||
236 | it's usermode state which we eventually need to restore. | ||
237 | */ | ||
238 | ENTRY(xen_iret_crit_fixup) | ||
239 | /* offsets +4 for return address */ | ||
240 | |||
241 | /* | ||
242 | Paranoia: Make sure we're really coming from userspace. | ||
243 | One could imagine a case where userspace jumps into the | ||
244 | critical range address, but just before the CPU delivers a GP, | ||
245 | it decides to deliver an interrupt instead. Unlikely? | ||
246 | Definitely. Easy to avoid? Yes. The Intel documents | ||
247 | explicitly say that the reported EIP for a bad jump is the | ||
248 | jump instruction itself, not the destination, but some virtual | ||
249 | environments get this wrong. | ||
250 | */ | ||
251 | movl PT_CS+4(%esp), %ecx | ||
252 | andl $SEGMENT_RPL_MASK, %ecx | ||
253 | cmpl $USER_RPL, %ecx | ||
254 | je 2f | ||
255 | |||
256 | lea PT_ORIG_EAX+4(%esp), %esi | ||
257 | lea PT_EFLAGS+4(%esp), %edi | ||
258 | |||
259 | /* If eip is before iret_restore_end then stack | ||
260 | hasn't been restored yet. */ | ||
261 | cmp $iret_restore_end, %eax | ||
262 | jae 1f | ||
263 | |||
264 | movl 0+4(%edi),%eax /* copy EAX */ | ||
265 | movl %eax, PT_EAX+4(%esp) | ||
266 | |||
267 | lea ESP_OFFSET(%edi),%edi /* move dest up over saved regs */ | ||
268 | |||
269 | /* set up the copy */ | ||
270 | 1: std | ||
271 | mov $(PT_EIP+4) / 4, %ecx /* copy ret+saved regs up to orig_eax */ | ||
272 | rep movsl | ||
273 | cld | ||
274 | |||
275 | lea 4(%edi),%esp /* point esp to new frame */ | ||
276 | 2: ret | ||
277 | |||
278 | |||
279 | /* | ||
280 | Force an event check by making a hypercall, | ||
281 | but preserve regs before making the call. | ||
282 | */ | ||
283 | check_events: | ||
284 | push %eax | ||
285 | push %ecx | ||
286 | push %edx | ||
287 | call force_evtchn_callback | ||
288 | pop %edx | ||
289 | pop %ecx | ||
290 | pop %eax | ||
291 | ret | ||
diff --git a/arch/i386/xen/xen-head.S b/arch/i386/xen/xen-head.S new file mode 100644 index 000000000000..2998d55a0017 --- /dev/null +++ b/arch/i386/xen/xen-head.S | |||
@@ -0,0 +1,36 @@ | |||
1 | /* Xen-specific pieces of head.S, intended to be included in the right | ||
2 | place in head.S */ | ||
3 | |||
4 | #ifdef CONFIG_XEN | ||
5 | |||
6 | #include <linux/elfnote.h> | ||
7 | #include <asm/boot.h> | ||
8 | #include <xen/interface/elfnote.h> | ||
9 | |||
10 | ENTRY(startup_xen) | ||
11 | movl %esi,xen_start_info | ||
12 | cld | ||
13 | movl $(init_thread_union+THREAD_SIZE),%esp | ||
14 | jmp xen_start_kernel | ||
15 | |||
16 | .pushsection ".bss.page_aligned" | ||
17 | .align PAGE_SIZE_asm | ||
18 | ENTRY(hypercall_page) | ||
19 | .skip 0x1000 | ||
20 | .popsection | ||
21 | |||
22 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") | ||
23 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") | ||
24 | ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") | ||
25 | ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, .long __PAGE_OFFSET) | ||
26 | ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .long startup_xen) | ||
27 | ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long hypercall_page) | ||
28 | ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz "!writable_page_tables|pae_pgdir_above_4gb") | ||
29 | #ifdef CONFIG_X86_PAE | ||
30 | ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "yes") | ||
31 | #else | ||
32 | ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz "no") | ||
33 | #endif | ||
34 | ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic") | ||
35 | |||
36 | #endif /*CONFIG_XEN */ | ||
diff --git a/arch/i386/xen/xen-ops.h b/arch/i386/xen/xen-ops.h new file mode 100644 index 000000000000..b9aaea45f07f --- /dev/null +++ b/arch/i386/xen/xen-ops.h | |||
@@ -0,0 +1,71 @@ | |||
1 | #ifndef XEN_OPS_H | ||
2 | #define XEN_OPS_H | ||
3 | |||
4 | #include <linux/init.h> | ||
5 | |||
6 | /* These are code, but not functions. Defined in entry.S */ | ||
7 | extern const char xen_hypervisor_callback[]; | ||
8 | extern const char xen_failsafe_callback[]; | ||
9 | |||
10 | void xen_copy_trap_info(struct trap_info *traps); | ||
11 | |||
12 | DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu); | ||
13 | DECLARE_PER_CPU(unsigned long, xen_cr3); | ||
14 | |||
15 | extern struct start_info *xen_start_info; | ||
16 | extern struct shared_info *HYPERVISOR_shared_info; | ||
17 | |||
18 | char * __init xen_memory_setup(void); | ||
19 | void __init xen_arch_setup(void); | ||
20 | void __init xen_init_IRQ(void); | ||
21 | |||
22 | void xen_setup_timer(int cpu); | ||
23 | void xen_setup_cpu_clockevents(void); | ||
24 | unsigned long xen_cpu_khz(void); | ||
25 | void __init xen_time_init(void); | ||
26 | unsigned long xen_get_wallclock(void); | ||
27 | int xen_set_wallclock(unsigned long time); | ||
28 | unsigned long long xen_sched_clock(void); | ||
29 | |||
30 | void xen_mark_init_mm_pinned(void); | ||
31 | |||
32 | DECLARE_PER_CPU(enum paravirt_lazy_mode, xen_lazy_mode); | ||
33 | |||
34 | static inline unsigned xen_get_lazy_mode(void) | ||
35 | { | ||
36 | return x86_read_percpu(xen_lazy_mode); | ||
37 | } | ||
38 | |||
39 | void __init xen_fill_possible_map(void); | ||
40 | |||
41 | void __init xen_setup_vcpu_info_placement(void); | ||
42 | void xen_smp_prepare_boot_cpu(void); | ||
43 | void xen_smp_prepare_cpus(unsigned int max_cpus); | ||
44 | int xen_cpu_up(unsigned int cpu); | ||
45 | void xen_smp_cpus_done(unsigned int max_cpus); | ||
46 | |||
47 | void xen_smp_send_stop(void); | ||
48 | void xen_smp_send_reschedule(int cpu); | ||
49 | int xen_smp_call_function (void (*func) (void *info), void *info, int nonatomic, | ||
50 | int wait); | ||
51 | int xen_smp_call_function_single(int cpu, void (*func) (void *info), void *info, | ||
52 | int nonatomic, int wait); | ||
53 | |||
54 | int xen_smp_call_function_mask(cpumask_t mask, void (*func)(void *), | ||
55 | void *info, int wait); | ||
56 | |||
57 | |||
58 | /* Declare an asm function, along with symbols needed to make it | ||
59 | inlineable */ | ||
60 | #define DECL_ASM(ret, name, ...) \ | ||
61 | ret name(__VA_ARGS__); \ | ||
62 | extern char name##_end[]; \ | ||
63 | extern char name##_reloc[] \ | ||
64 | |||
65 | DECL_ASM(void, xen_irq_enable_direct, void); | ||
66 | DECL_ASM(void, xen_irq_disable_direct, void); | ||
67 | DECL_ASM(unsigned long, xen_save_fl_direct, void); | ||
68 | DECL_ASM(void, xen_restore_fl_direct, unsigned long); | ||
69 | |||
70 | void xen_iret_direct(void); | ||
71 | #endif /* XEN_OPS_H */ | ||
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index db9ddff95841..616c96e73483 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -582,8 +582,8 @@ menu "Instrumentation Support" | |||
582 | source "arch/ia64/oprofile/Kconfig" | 582 | source "arch/ia64/oprofile/Kconfig" |
583 | 583 | ||
584 | config KPROBES | 584 | config KPROBES |
585 | bool "Kprobes (EXPERIMENTAL)" | 585 | bool "Kprobes" |
586 | depends on KALLSYMS && EXPERIMENTAL && MODULES | 586 | depends on KALLSYMS && MODULES |
587 | help | 587 | help |
588 | Kprobes allows you to trap at almost any kernel address and | 588 | Kprobes allows you to trap at almost any kernel address and |
589 | execute a callback function. register_kprobe() establishes | 589 | execute a callback function. register_kprobe() establishes |
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index c1dca226b479..cd4adf52f174 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/efi.h> | 34 | #include <linux/efi.h> |
35 | #include <linux/nodemask.h> | 35 | #include <linux/nodemask.h> |
36 | #include <linux/bitops.h> /* hweight64() */ | 36 | #include <linux/bitops.h> /* hweight64() */ |
37 | #include <linux/crash_dump.h> | ||
37 | 38 | ||
38 | #include <asm/delay.h> /* ia64_get_itc() */ | 39 | #include <asm/delay.h> /* ia64_get_itc() */ |
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
@@ -43,6 +44,8 @@ | |||
43 | 44 | ||
44 | #include <asm/acpi-ext.h> | 45 | #include <asm/acpi-ext.h> |
45 | 46 | ||
47 | extern int swiotlb_late_init_with_default_size (size_t size); | ||
48 | |||
46 | #define PFX "IOC: " | 49 | #define PFX "IOC: " |
47 | 50 | ||
48 | /* | 51 | /* |
@@ -2026,11 +2029,24 @@ sba_init(void) | |||
2026 | if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb")) | 2029 | if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb")) |
2027 | return 0; | 2030 | return 0; |
2028 | 2031 | ||
2032 | #if defined(CONFIG_IA64_GENERIC) && defined(CONFIG_CRASH_DUMP) | ||
2033 | /* If we are booting a kdump kernel, the sba_iommu will | ||
2034 | * cause devices that were not shutdown properly to MCA | ||
2035 | * as soon as they are turned back on. Our only option for | ||
2036 | * a successful kdump kernel boot is to use the swiotlb. | ||
2037 | */ | ||
2038 | if (elfcorehdr_addr < ELFCORE_ADDR_MAX) { | ||
2039 | if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0) | ||
2040 | panic("Unable to initialize software I/O TLB:" | ||
2041 | " Try machvec=dig boot option"); | ||
2042 | machvec_init("dig"); | ||
2043 | return 0; | ||
2044 | } | ||
2045 | #endif | ||
2046 | |||
2029 | acpi_bus_register_driver(&acpi_sba_ioc_driver); | 2047 | acpi_bus_register_driver(&acpi_sba_ioc_driver); |
2030 | if (!ioc_list) { | 2048 | if (!ioc_list) { |
2031 | #ifdef CONFIG_IA64_GENERIC | 2049 | #ifdef CONFIG_IA64_GENERIC |
2032 | extern int swiotlb_late_init_with_default_size (size_t size); | ||
2033 | |||
2034 | /* | 2050 | /* |
2035 | * If we didn't find something sba_iommu can claim, we | 2051 | * If we didn't find something sba_iommu can claim, we |
2036 | * need to setup the swiotlb and switch to the dig machvec. | 2052 | * need to setup the swiotlb and switch to the dig machvec. |
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c index 300acd913d9c..1189d035d316 100644 --- a/arch/ia64/hp/sim/boot/fw-emu.c +++ b/arch/ia64/hp/sim/boot/fw-emu.c | |||
@@ -329,11 +329,6 @@ sys_fw_init (const char *args, int arglen) | |||
329 | strcpy(sal_systab->product_id, "HP-simulator"); | 329 | strcpy(sal_systab->product_id, "HP-simulator"); |
330 | #endif | 330 | #endif |
331 | 331 | ||
332 | #ifdef CONFIG_IA64_SDV | ||
333 | strcpy(sal_systab->oem_id, "Intel"); | ||
334 | strcpy(sal_systab->product_id, "SDV"); | ||
335 | #endif | ||
336 | |||
337 | /* fill in an entry point: */ | 332 | /* fill in an entry point: */ |
338 | sal_ed->type = SAL_DESC_ENTRY_POINT; | 333 | sal_ed->type = SAL_DESC_ENTRY_POINT; |
339 | sal_ed->pal_proc = __pa(pal_desc[0]); | 334 | sal_ed->pal_proc = __pa(pal_desc[0]); |
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 324ea7565e2c..ef252df50e1e 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c | |||
@@ -36,10 +36,6 @@ | |||
36 | #include <asm/hw_irq.h> | 36 | #include <asm/hw_irq.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | 38 | ||
39 | #ifdef CONFIG_KDB | ||
40 | # include <linux/kdb.h> | ||
41 | #endif | ||
42 | |||
43 | #undef SIMSERIAL_DEBUG /* define this to get some debug information */ | 39 | #undef SIMSERIAL_DEBUG /* define this to get some debug information */ |
44 | 40 | ||
45 | #define KEYBOARD_INTR 3 /* must match with simulator! */ | 41 | #define KEYBOARD_INTR 3 /* must match with simulator! */ |
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index 6f4d3d06f0ed..e1189ba1ca5e 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c | |||
@@ -195,62 +195,27 @@ ia64_elf32_init (struct pt_regs *regs) | |||
195 | ia32_load_state(current); | 195 | ia32_load_state(current); |
196 | } | 196 | } |
197 | 197 | ||
198 | /* | ||
199 | * Undo the override of setup_arg_pages() without this ia32_setup_arg_pages() | ||
200 | * will suffer infinite self recursion. | ||
201 | */ | ||
202 | #undef setup_arg_pages | ||
203 | |||
198 | int | 204 | int |
199 | ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) | 205 | ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) |
200 | { | 206 | { |
201 | unsigned long stack_base; | 207 | int ret; |
202 | struct vm_area_struct *mpnt; | 208 | |
203 | struct mm_struct *mm = current->mm; | 209 | ret = setup_arg_pages(bprm, IA32_STACK_TOP, executable_stack); |
204 | int i, ret; | 210 | if (!ret) { |
205 | 211 | /* | |
206 | stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE; | 212 | * Can't do it in ia64_elf32_init(). Needs to be done before |
207 | mm->arg_start = bprm->p + stack_base; | 213 | * calls to elf32_map() |
208 | 214 | */ | |
209 | bprm->p += stack_base; | 215 | current->thread.ppl = ia32_init_pp_list(); |
210 | if (bprm->loader) | ||
211 | bprm->loader += stack_base; | ||
212 | bprm->exec += stack_base; | ||
213 | |||
214 | mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); | ||
215 | if (!mpnt) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | down_write(¤t->mm->mmap_sem); | ||
219 | { | ||
220 | mpnt->vm_mm = current->mm; | ||
221 | mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; | ||
222 | mpnt->vm_end = IA32_STACK_TOP; | ||
223 | if (executable_stack == EXSTACK_ENABLE_X) | ||
224 | mpnt->vm_flags = VM_STACK_FLAGS | VM_EXEC; | ||
225 | else if (executable_stack == EXSTACK_DISABLE_X) | ||
226 | mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC; | ||
227 | else | ||
228 | mpnt->vm_flags = VM_STACK_FLAGS; | ||
229 | mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)? | ||
230 | PAGE_COPY_EXEC: PAGE_COPY; | ||
231 | if ((ret = insert_vm_struct(current->mm, mpnt))) { | ||
232 | up_write(¤t->mm->mmap_sem); | ||
233 | kmem_cache_free(vm_area_cachep, mpnt); | ||
234 | return ret; | ||
235 | } | ||
236 | current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt); | ||
237 | } | 216 | } |
238 | 217 | ||
239 | for (i = 0 ; i < MAX_ARG_PAGES ; i++) { | 218 | return ret; |
240 | struct page *page = bprm->page[i]; | ||
241 | if (page) { | ||
242 | bprm->page[i] = NULL; | ||
243 | install_arg_page(mpnt, page, stack_base); | ||
244 | } | ||
245 | stack_base += PAGE_SIZE; | ||
246 | } | ||
247 | up_write(¤t->mm->mmap_sem); | ||
248 | |||
249 | /* Can't do it in ia64_elf32_init(). Needs to be done before calls to | ||
250 | elf32_map() */ | ||
251 | current->thread.ppl = ia32_init_pp_list(); | ||
252 | |||
253 | return 0; | ||
254 | } | 219 | } |
255 | 220 | ||
256 | static void | 221 | static void |
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 75ec3478d8a2..73ca86d03810 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/efi.h> | 29 | #include <linux/efi.h> |
30 | #include <linux/kexec.h> | 30 | #include <linux/kexec.h> |
31 | #include <linux/mm.h> | ||
31 | 32 | ||
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
33 | #include <asm/kregs.h> | 34 | #include <asm/kregs.h> |
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 8589e84a27c6..3f926c2dc708 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
@@ -247,6 +247,9 @@ ENTRY(fsys_gettimeofday) | |||
247 | .time_redo: | 247 | .time_redo: |
248 | .pred.rel.mutex p8,p9,p10 | 248 | .pred.rel.mutex p8,p9,p10 |
249 | ld4.acq r28 = [r29] // xtime_lock.sequence. Must come first for locking purposes | 249 | ld4.acq r28 = [r29] // xtime_lock.sequence. Must come first for locking purposes |
250 | ;; | ||
251 | and r28 = ~1,r28 // Make sequence even to force retry if odd | ||
252 | ;; | ||
250 | (p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!! | 253 | (p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!! |
251 | add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20 | 254 | add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20 |
252 | (p9) ld8 r2 = [r30] // readq(ti->address). Could also have latency issues.. | 255 | (p9) ld8 r2 = [r30] // readq(ti->address). Could also have latency issues.. |
@@ -284,7 +287,6 @@ EX(.fail_efault, probe.w.fault r31, 3) // This takes 5 cycles and we have spare | |||
284 | (p15) ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET | 287 | (p15) ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET |
285 | (p7) cmp.ne p7,p0 = r25,r3 // if cmpxchg not successful redo | 288 | (p7) cmp.ne p7,p0 = r25,r3 // if cmpxchg not successful redo |
286 | // simulate tbit.nz.or p7,p0 = r28,0 | 289 | // simulate tbit.nz.or p7,p0 = r28,0 |
287 | and r28 = ~1,r28 // Make sequence even to force retry if odd | ||
288 | getf.sig r2 = f8 | 290 | getf.sig r2 = f8 |
289 | mf | 291 | mf |
290 | add r8 = r8,r18 // Add time interpolator offset | 292 | add r8 = r8,r18 // Add time interpolator offset |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 5bc46f151344..5dc98b5abcfb 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -936,10 +936,15 @@ static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg) | |||
936 | return; | 936 | return; |
937 | } | 937 | } |
938 | 938 | ||
939 | unsigned long arch_deref_entry_point(void *entry) | ||
940 | { | ||
941 | return ((struct fnptr *)entry)->ip; | ||
942 | } | ||
943 | |||
939 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 944 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
940 | { | 945 | { |
941 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 946 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
942 | unsigned long addr = ((struct fnptr *)(jp->entry))->ip; | 947 | unsigned long addr = arch_deref_entry_point(jp->entry); |
943 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 948 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
944 | struct param_bsp_cfm pa; | 949 | struct param_bsp_cfm pa; |
945 | int bytes; | 950 | int bytes; |
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 4d9864cc92c9..cf06fe799041 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -980,15 +980,6 @@ cpu_init (void) | |||
980 | pm_idle = default_idle; | 980 | pm_idle = default_idle; |
981 | } | 981 | } |
982 | 982 | ||
983 | /* | ||
984 | * On SMP systems, when the scheduler does migration-cost autodetection, | ||
985 | * it needs a way to flush as much of the CPU's caches as possible. | ||
986 | */ | ||
987 | void sched_cacheflush(void) | ||
988 | { | ||
989 | ia64_sal_cache_flush(3); | ||
990 | } | ||
991 | |||
992 | void __init | 983 | void __init |
993 | check_bugs (void) | 984 | check_bugs (void) |
994 | { | 985 | { |
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index b3a47f986e1e..9f72838db26e 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c | |||
@@ -82,7 +82,7 @@ static volatile struct call_data_struct *call_data; | |||
82 | #define IPI_KDUMP_CPU_STOP 3 | 82 | #define IPI_KDUMP_CPU_STOP 3 |
83 | 83 | ||
84 | /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ | 84 | /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ |
85 | static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; | 85 | static DEFINE_PER_CPU_SHARED_ALIGNED(u64, ipi_operation); |
86 | 86 | ||
87 | extern void cpu_halt (void); | 87 | extern void cpu_halt (void); |
88 | 88 | ||
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index 15ad85da15a9..3aeaf15e468b 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
@@ -69,6 +69,7 @@ die (const char *str, struct pt_regs *regs, long err) | |||
69 | 69 | ||
70 | bust_spinlocks(0); | 70 | bust_spinlocks(0); |
71 | die.lock_owner = -1; | 71 | die.lock_owner = -1; |
72 | add_taint(TAINT_DIE); | ||
72 | spin_unlock_irq(&die.lock); | 73 | spin_unlock_irq(&die.lock); |
73 | 74 | ||
74 | if (panic_on_oops) | 75 | if (panic_on_oops) |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 5a65965c8b53..860f251d2fc2 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -206,6 +206,7 @@ SECTIONS | |||
206 | { | 206 | { |
207 | __per_cpu_start = .; | 207 | __per_cpu_start = .; |
208 | *(.data.percpu) | 208 | *(.data.percpu) |
209 | *(.data.percpu.shared_aligned) | ||
209 | __per_cpu_end = .; | 210 | __per_cpu_end = .; |
210 | } | 211 | } |
211 | . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits | 212 | . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits |
diff --git a/arch/ia64/lib/checksum.c b/arch/ia64/lib/checksum.c index 4411d9baeb21..9fc955026f86 100644 --- a/arch/ia64/lib/checksum.c +++ b/arch/ia64/lib/checksum.c | |||
@@ -60,6 +60,7 @@ csum_tcpudp_nofold (__be32 saddr, __be32 daddr, unsigned short len, | |||
60 | result = (result & 0xffffffff) + (result >> 32); | 60 | result = (result & 0xffffffff) + (result >> 32); |
61 | return (__force __wsum)result; | 61 | return (__force __wsum)result; |
62 | } | 62 | } |
63 | EXPORT_SYMBOL(csum_tcpudp_nofold); | ||
63 | 64 | ||
64 | extern unsigned long do_csum (const unsigned char *, long); | 65 | extern unsigned long do_csum (const unsigned char *, long); |
65 | 66 | ||
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index b87f785c2416..73ccb6010c05 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c | |||
@@ -80,6 +80,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re | |||
80 | struct mm_struct *mm = current->mm; | 80 | struct mm_struct *mm = current->mm; |
81 | struct siginfo si; | 81 | struct siginfo si; |
82 | unsigned long mask; | 82 | unsigned long mask; |
83 | int fault; | ||
83 | 84 | ||
84 | /* mmap_sem is performance critical.... */ | 85 | /* mmap_sem is performance critical.... */ |
85 | prefetchw(&mm->mmap_sem); | 86 | prefetchw(&mm->mmap_sem); |
@@ -147,26 +148,25 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re | |||
147 | * sure we exit gracefully rather than endlessly redo the | 148 | * sure we exit gracefully rather than endlessly redo the |
148 | * fault. | 149 | * fault. |
149 | */ | 150 | */ |
150 | switch (handle_mm_fault(mm, vma, address, (mask & VM_WRITE) != 0)) { | 151 | fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) != 0); |
151 | case VM_FAULT_MINOR: | 152 | if (unlikely(fault & VM_FAULT_ERROR)) { |
152 | ++current->min_flt; | ||
153 | break; | ||
154 | case VM_FAULT_MAJOR: | ||
155 | ++current->maj_flt; | ||
156 | break; | ||
157 | case VM_FAULT_SIGBUS: | ||
158 | /* | 153 | /* |
159 | * We ran out of memory, or some other thing happened | 154 | * We ran out of memory, or some other thing happened |
160 | * to us that made us unable to handle the page fault | 155 | * to us that made us unable to handle the page fault |
161 | * gracefully. | 156 | * gracefully. |
162 | */ | 157 | */ |
163 | signal = SIGBUS; | 158 | if (fault & VM_FAULT_OOM) { |
164 | goto bad_area; | 159 | goto out_of_memory; |
165 | case VM_FAULT_OOM: | 160 | } else if (fault & VM_FAULT_SIGBUS) { |
166 | goto out_of_memory; | 161 | signal = SIGBUS; |
167 | default: | 162 | goto bad_area; |
163 | } | ||
168 | BUG(); | 164 | BUG(); |
169 | } | 165 | } |
166 | if (fault & VM_FAULT_MAJOR) | ||
167 | current->maj_flt++; | ||
168 | else | ||
169 | current->min_flt++; | ||
170 | up_read(&mm->mmap_sem); | 170 | up_read(&mm->mmap_sem); |
171 | return; | 171 | return; |
172 | 172 | ||
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 6da9854751cd..df8d5bed6119 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c | |||
@@ -750,9 +750,10 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) | |||
750 | goto error; | 750 | goto error; |
751 | } else | 751 | } else |
752 | if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { | 752 | if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { |
753 | int cpuobj_index = 0; | ||
754 | |||
753 | memset(p, 0, a.sz); | 755 | memset(p, 0, a.sz); |
754 | for (i = 0; i < nobj; i++) { | 756 | for (i = 0; i < nobj; i++) { |
755 | int cpuobj_index = 0; | ||
756 | if (!SN_HWPERF_IS_NODE(objs + i)) | 757 | if (!SN_HWPERF_IS_NODE(objs + i)) |
757 | continue; | 758 | continue; |
758 | node = sn_hwperf_obj_to_cnode(objs + i); | 759 | node = sn_hwperf_obj_to_cnode(objs + i); |
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 5f02b3144875..57a92ef31a90 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c | |||
@@ -595,7 +595,6 @@ void ptrace_disable(struct task_struct *child) | |||
595 | static int | 595 | static int |
596 | do_ptrace(long request, struct task_struct *child, long addr, long data) | 596 | do_ptrace(long request, struct task_struct *child, long addr, long data) |
597 | { | 597 | { |
598 | unsigned long tmp; | ||
599 | int ret; | 598 | int ret; |
600 | 599 | ||
601 | switch (request) { | 600 | switch (request) { |
@@ -604,11 +603,7 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) | |||
604 | */ | 603 | */ |
605 | case PTRACE_PEEKTEXT: | 604 | case PTRACE_PEEKTEXT: |
606 | case PTRACE_PEEKDATA: | 605 | case PTRACE_PEEKDATA: |
607 | ret = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | 606 | ret = generic_ptrace_peekdata(child, addr, data); |
608 | if (ret == sizeof(tmp)) | ||
609 | ret = put_user(tmp,(unsigned long __user *) data); | ||
610 | else | ||
611 | ret = -EIO; | ||
612 | break; | 607 | break; |
613 | 608 | ||
614 | /* | 609 | /* |
@@ -624,15 +619,9 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) | |||
624 | */ | 619 | */ |
625 | case PTRACE_POKETEXT: | 620 | case PTRACE_POKETEXT: |
626 | case PTRACE_POKEDATA: | 621 | case PTRACE_POKEDATA: |
627 | ret = access_process_vm(child, addr, &data, sizeof(data), 1); | 622 | ret = generic_ptrace_pokedata(child, addr, data); |
628 | if (ret == sizeof(data)) { | 623 | if (ret == 0 && request == PTRACE_POKETEXT) |
629 | ret = 0; | 624 | invalidate_cache(); |
630 | if (request == PTRACE_POKETEXT) { | ||
631 | invalidate_cache(); | ||
632 | } | ||
633 | } else { | ||
634 | ret = -EIO; | ||
635 | } | ||
636 | break; | 625 | break; |
637 | 626 | ||
638 | /* | 627 | /* |
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S index 4e2d5b9f0a9a..942a8c7a4417 100644 --- a/arch/m32r/kernel/vmlinux.lds.S +++ b/arch/m32r/kernel/vmlinux.lds.S | |||
@@ -110,10 +110,7 @@ SECTIONS | |||
110 | __initramfs_end = .; | 110 | __initramfs_end = .; |
111 | #endif | 111 | #endif |
112 | 112 | ||
113 | . = ALIGN(4096); | 113 | PERCPU(4096) |
114 | __per_cpu_start = .; | ||
115 | .data.percpu : { *(.data.percpu) } | ||
116 | __per_cpu_end = .; | ||
117 | . = ALIGN(4096); | 114 | . = ALIGN(4096); |
118 | __init_end = .; | 115 | __init_end = .; |
119 | /* freed after init ends here */ | 116 | /* freed after init ends here */ |
diff --git a/arch/m32r/m32104ut/defconfig.m32104ut b/arch/m32r/m32104ut/defconfig.m32104ut index 7b68fe8d921e..1f88f493a9e2 100644 --- a/arch/m32r/m32104ut/defconfig.m32104ut +++ b/arch/m32r/m32104ut/defconfig.m32104ut | |||
@@ -699,7 +699,6 @@ CONFIG_I2C_ALGOPCF=m | |||
699 | # I2C Hardware Bus support | 699 | # I2C Hardware Bus support |
700 | # | 700 | # |
701 | CONFIG_I2C_ELEKTOR=m | 701 | CONFIG_I2C_ELEKTOR=m |
702 | CONFIG_I2C_ISA=m | ||
703 | # CONFIG_I2C_OCORES is not set | 702 | # CONFIG_I2C_OCORES is not set |
704 | # CONFIG_I2C_PARPORT is not set | 703 | # CONFIG_I2C_PARPORT is not set |
705 | # CONFIG_I2C_PARPORT_LIGHT is not set | 704 | # CONFIG_I2C_PARPORT_LIGHT is not set |
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c index f3935ba24946..676a1c443d28 100644 --- a/arch/m32r/mm/fault.c +++ b/arch/m32r/mm/fault.c | |||
@@ -80,6 +80,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, | |||
80 | struct vm_area_struct * vma; | 80 | struct vm_area_struct * vma; |
81 | unsigned long page, addr; | 81 | unsigned long page, addr; |
82 | int write; | 82 | int write; |
83 | int fault; | ||
83 | siginfo_t info; | 84 | siginfo_t info; |
84 | 85 | ||
85 | /* | 86 | /* |
@@ -195,20 +196,18 @@ survive: | |||
195 | */ | 196 | */ |
196 | addr = (address & PAGE_MASK); | 197 | addr = (address & PAGE_MASK); |
197 | set_thread_fault_code(error_code); | 198 | set_thread_fault_code(error_code); |
198 | switch (handle_mm_fault(mm, vma, addr, write)) { | 199 | fault = handle_mm_fault(mm, vma, addr, write); |
199 | case VM_FAULT_MINOR: | 200 | if (unlikely(fault & VM_FAULT_ERROR)) { |
200 | tsk->min_flt++; | 201 | if (fault & VM_FAULT_OOM) |
201 | break; | ||
202 | case VM_FAULT_MAJOR: | ||
203 | tsk->maj_flt++; | ||
204 | break; | ||
205 | case VM_FAULT_SIGBUS: | ||
206 | goto do_sigbus; | ||
207 | case VM_FAULT_OOM: | ||
208 | goto out_of_memory; | 202 | goto out_of_memory; |
209 | default: | 203 | else if (fault & VM_FAULT_SIGBUS) |
210 | BUG(); | 204 | goto do_sigbus; |
205 | BUG(); | ||
211 | } | 206 | } |
207 | if (fault & VM_FAULT_MAJOR) | ||
208 | tsk->maj_flt++; | ||
209 | else | ||
210 | tsk->min_flt++; | ||
212 | set_thread_fault_code(0); | 211 | set_thread_fault_code(0); |
213 | up_read(&mm->mmap_sem); | 212 | up_read(&mm->mmap_sem); |
214 | return; | 213 | return; |
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index cdba9fd6d82f..2cf0690b7882 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
@@ -128,10 +128,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
128 | /* when I and D space are separate, these will need to be fixed. */ | 128 | /* when I and D space are separate, these will need to be fixed. */ |
129 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 129 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
130 | case PTRACE_PEEKDATA: | 130 | case PTRACE_PEEKDATA: |
131 | i = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | 131 | ret = generic_ptrace_peekdata(child, addr, data); |
132 | if (i != sizeof(tmp)) | ||
133 | goto out_eio; | ||
134 | ret = put_user(tmp, (unsigned long *)data); | ||
135 | break; | 132 | break; |
136 | 133 | ||
137 | /* read the word at location addr in the USER area. */ | 134 | /* read the word at location addr in the USER area. */ |
@@ -160,8 +157,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
160 | /* when I and D space are separate, this will have to be fixed. */ | 157 | /* when I and D space are separate, this will have to be fixed. */ |
161 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 158 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
162 | case PTRACE_POKEDATA: | 159 | case PTRACE_POKEDATA: |
163 | if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data)) | 160 | ret = generic_ptrace_pokedata(child, addr, data); |
164 | goto out_eio; | ||
165 | break; | 161 | break; |
166 | 162 | ||
167 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 163 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index a27a4fa33296..4e2752a0e89b 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c | |||
@@ -1170,6 +1170,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr) | |||
1170 | console_verbose(); | 1170 | console_verbose(); |
1171 | printk("%s: %08x\n",str,nr); | 1171 | printk("%s: %08x\n",str,nr); |
1172 | show_registers(fp); | 1172 | show_registers(fp); |
1173 | add_taint(TAINT_DIE); | ||
1173 | do_exit(SIGSEGV); | 1174 | do_exit(SIGSEGV); |
1174 | } | 1175 | } |
1175 | 1176 | ||
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index cf6bb51945a2..6216f12a756b 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c | |||
@@ -422,3 +422,4 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) | |||
422 | ); | 422 | ); |
423 | return(sum); | 423 | return(sum); |
424 | } | 424 | } |
425 | EXPORT_SYMBOL(csum_partial_copy_nocheck); | ||
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index 2adbeb16e1b8..578b48f47b9e 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c | |||
@@ -159,18 +159,17 @@ good_area: | |||
159 | #ifdef DEBUG | 159 | #ifdef DEBUG |
160 | printk("handle_mm_fault returns %d\n",fault); | 160 | printk("handle_mm_fault returns %d\n",fault); |
161 | #endif | 161 | #endif |
162 | switch (fault) { | 162 | if (unlikely(fault & VM_FAULT_ERROR)) { |
163 | case VM_FAULT_MINOR: | 163 | if (fault & VM_FAULT_OOM) |
164 | current->min_flt++; | 164 | goto out_of_memory; |
165 | break; | 165 | else if (fault & VM_FAULT_SIGBUS) |
166 | case VM_FAULT_MAJOR: | 166 | goto bus_err; |
167 | current->maj_flt++; | 167 | BUG(); |
168 | break; | ||
169 | case VM_FAULT_SIGBUS: | ||
170 | goto bus_err; | ||
171 | default: | ||
172 | goto out_of_memory; | ||
173 | } | 168 | } |
169 | if (fault & VM_FAULT_MAJOR) | ||
170 | current->maj_flt++; | ||
171 | else | ||
172 | current->min_flt++; | ||
174 | 173 | ||
175 | up_read(&mm->mmap_sem); | 174 | up_read(&mm->mmap_sem); |
176 | return 0; | 175 | return 0; |
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index adc64a2bafbb..1175ceff8b2a 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig | |||
@@ -45,6 +45,10 @@ config GENERIC_HWEIGHT | |||
45 | bool | 45 | bool |
46 | default y | 46 | default y |
47 | 47 | ||
48 | config GENERIC_HARDIRQS | ||
49 | bool | ||
50 | default y | ||
51 | |||
48 | config GENERIC_CALIBRATE_DELAY | 52 | config GENERIC_CALIBRATE_DELAY |
49 | bool | 53 | bool |
50 | default y | 54 | default y |
diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile index 1c6cd1ab571e..1524b39ad63f 100644 --- a/arch/m68knommu/kernel/Makefile +++ b/arch/m68knommu/kernel/Makefile | |||
@@ -4,8 +4,8 @@ | |||
4 | 4 | ||
5 | extra-y := vmlinux.lds | 5 | extra-y := vmlinux.lds |
6 | 6 | ||
7 | obj-y += dma.o entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \ | 7 | obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \ |
8 | setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o | 8 | semaphore.o setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o |
9 | 9 | ||
10 | obj-$(CONFIG_MODULES) += module.o | 10 | obj-$(CONFIG_MODULES) += module.o |
11 | obj-$(CONFIG_COMEMPCI) += comempci.o | 11 | obj-$(CONFIG_COMEMPCI) += comempci.o |
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c index 7cd183d346ef..d97b89bae53c 100644 --- a/arch/m68knommu/kernel/asm-offsets.c +++ b/arch/m68knommu/kernel/asm-offsets.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/hardirq.h> | 15 | #include <linux/hardirq.h> |
16 | #include <asm/bootinfo.h> | 16 | #include <asm/bootinfo.h> |
17 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
18 | #include <asm/irqnode.h> | ||
19 | #include <asm/thread_info.h> | 18 | #include <asm/thread_info.h> |
20 | 19 | ||
21 | #define DEFINE(sym, val) \ | 20 | #define DEFINE(sym, val) \ |
@@ -72,10 +71,6 @@ int main(void) | |||
72 | #else | 71 | #else |
73 | /* bitfields are a bit difficult */ | 72 | /* bitfields are a bit difficult */ |
74 | DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); | 73 | DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); |
75 | /* offsets into the irq_handler struct */ | ||
76 | DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler)); | ||
77 | DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id)); | ||
78 | DEFINE(IRQ_NEXT, offsetof(struct irq_node, next)); | ||
79 | #endif | 74 | #endif |
80 | 75 | ||
81 | /* offsets into the kernel_stat struct */ | 76 | /* offsets into the kernel_stat struct */ |
diff --git a/arch/m68knommu/kernel/irq.c b/arch/m68knommu/kernel/irq.c new file mode 100644 index 000000000000..bba1bb48a21f --- /dev/null +++ b/arch/m68knommu/kernel/irq.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * irq.c | ||
3 | * | ||
4 | * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com> | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive | ||
8 | * for more details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/kernel_stat.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <linux/seq_file.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/traps.h> | ||
20 | |||
21 | asmlinkage void do_IRQ(int irq, struct pt_regs *regs) | ||
22 | { | ||
23 | struct pt_regs *oldregs = set_irq_regs(regs); | ||
24 | |||
25 | irq_enter(); | ||
26 | __do_IRQ(irq); | ||
27 | irq_exit(); | ||
28 | |||
29 | set_irq_regs(oldregs); | ||
30 | } | ||
31 | |||
32 | void ack_bad_irq(unsigned int irq) | ||
33 | { | ||
34 | printk(KERN_ERR "IRQ: unexpected irq=%d\n", irq); | ||
35 | } | ||
36 | |||
37 | static struct irq_chip m_irq_chip = { | ||
38 | .name = "M68K-INTC", | ||
39 | .enable = enable_vector, | ||
40 | .disable = disable_vector, | ||
41 | .ack = ack_vector, | ||
42 | }; | ||
43 | |||
44 | void __init init_IRQ(void) | ||
45 | { | ||
46 | int irq; | ||
47 | |||
48 | init_vectors(); | ||
49 | |||
50 | for (irq = 0; (irq < NR_IRQS); irq++) { | ||
51 | irq_desc[irq].status = IRQ_DISABLED; | ||
52 | irq_desc[irq].action = NULL; | ||
53 | irq_desc[irq].depth = 1; | ||
54 | irq_desc[irq].chip = &m_irq_chip; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | int show_interrupts(struct seq_file *p, void *v) | ||
59 | { | ||
60 | struct irqaction *ap; | ||
61 | int irq = *((loff_t *) v); | ||
62 | |||
63 | if (irq == 0) | ||
64 | seq_puts(p, " CPU0\n"); | ||
65 | |||
66 | if (irq < NR_IRQS) { | ||
67 | ap = irq_desc[irq].action; | ||
68 | if (ap) { | ||
69 | seq_printf(p, "%3d: ", irq); | ||
70 | seq_printf(p, "%10u ", kstat_irqs(irq)); | ||
71 | seq_printf(p, "%14s ", irq_desc[irq].chip->name); | ||
72 | |||
73 | seq_printf(p, "%s", ap->name); | ||
74 | for (ap = ap->next; ap; ap = ap->next) | ||
75 | seq_printf(p, ", %s", ap->name); | ||
76 | seq_putc(p, '\n'); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c index 25327c9eadd7..f795062aba1e 100644 --- a/arch/m68knommu/kernel/m68k_ksyms.c +++ b/arch/m68knommu/kernel/m68k_ksyms.c | |||
@@ -81,8 +81,6 @@ EXPORT_SYMBOL(__mulsi3); | |||
81 | EXPORT_SYMBOL(__udivsi3); | 81 | EXPORT_SYMBOL(__udivsi3); |
82 | EXPORT_SYMBOL(__umodsi3); | 82 | EXPORT_SYMBOL(__umodsi3); |
83 | 83 | ||
84 | EXPORT_SYMBOL(is_in_rom); | ||
85 | |||
86 | #ifdef CONFIG_COLDFIRE | 84 | #ifdef CONFIG_COLDFIRE |
87 | extern unsigned int *dma_device_address; | 85 | extern unsigned int *dma_device_address; |
88 | extern unsigned long dma_base_addr, _ramend; | 86 | extern unsigned long dma_base_addr, _ramend; |
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index f54b6a3dfecb..ef70ca070ce2 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c | |||
@@ -106,17 +106,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
106 | switch (request) { | 106 | switch (request) { |
107 | /* when I and D space are separate, these will need to be fixed. */ | 107 | /* when I and D space are separate, these will need to be fixed. */ |
108 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 108 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
109 | case PTRACE_PEEKDATA: { | 109 | case PTRACE_PEEKDATA: |
110 | unsigned long tmp; | 110 | ret = generic_ptrace_peekdata(child, addr, data); |
111 | int copied; | ||
112 | |||
113 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
114 | ret = -EIO; | ||
115 | if (copied != sizeof(tmp)) | ||
116 | break; | ||
117 | ret = put_user(tmp,(unsigned long *) data); | ||
118 | break; | 111 | break; |
119 | } | ||
120 | 112 | ||
121 | /* read the word at location addr in the USER area. */ | 113 | /* read the word at location addr in the USER area. */ |
122 | case PTRACE_PEEKUSR: { | 114 | case PTRACE_PEEKUSR: { |
@@ -159,10 +151,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
159 | /* when I and D space are separate, this will have to be fixed. */ | 151 | /* when I and D space are separate, this will have to be fixed. */ |
160 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 152 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
161 | case PTRACE_POKEDATA: | 153 | case PTRACE_POKEDATA: |
162 | ret = 0; | 154 | ret = generic_ptrace_pokedata(child, addr, data); |
163 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
164 | break; | ||
165 | ret = -EIO; | ||
166 | break; | 155 | break; |
167 | 156 | ||
168 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 157 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index bed5f47bf568..437a061d8b94 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c | |||
@@ -62,8 +62,6 @@ static char const * const vec_names[] = { | |||
62 | 62 | ||
63 | void __init trap_init(void) | 63 | void __init trap_init(void) |
64 | { | 64 | { |
65 | if (mach_trap_init) | ||
66 | mach_trap_init(); | ||
67 | } | 65 | } |
68 | 66 | ||
69 | void die_if_kernel(char *str, struct pt_regs *fp, int nr) | 67 | void die_if_kernel(char *str, struct pt_regs *fp, int nr) |
@@ -82,7 +80,8 @@ void die_if_kernel(char *str, struct pt_regs *fp, int nr) | |||
82 | 80 | ||
83 | printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", | 81 | printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n", |
84 | current->comm, current->pid, PAGE_SIZE+(unsigned long)current); | 82 | current->comm, current->pid, PAGE_SIZE+(unsigned long)current); |
85 | show_stack(NULL, (unsigned long *)fp); | 83 | show_stack(NULL, (unsigned long *)(fp + 1)); |
84 | add_taint(TAINT_DIE); | ||
86 | do_exit(SIGSEGV); | 85 | do_exit(SIGSEGV); |
87 | } | 86 | } |
88 | 87 | ||
diff --git a/arch/m68knommu/mm/memory.c b/arch/m68knommu/mm/memory.c index 1a66b71035a4..f93b88b51f9f 100644 --- a/arch/m68knommu/mm/memory.c +++ b/arch/m68knommu/mm/memory.c | |||
@@ -33,23 +33,3 @@ unsigned long kernel_map(unsigned long paddr, unsigned long size, | |||
33 | return paddr; | 33 | return paddr; |
34 | } | 34 | } |
35 | 35 | ||
36 | |||
37 | int is_in_rom(unsigned long addr) | ||
38 | { | ||
39 | extern unsigned long _ramstart, _ramend; | ||
40 | |||
41 | /* | ||
42 | * What we are really trying to do is determine if addr is | ||
43 | * in an allocated kernel memory region. If not then assume | ||
44 | * we cannot free it or otherwise de-allocate it. Ideally | ||
45 | * we could restrict this to really being in a ROM or flash, | ||
46 | * but that would need to be done on a board by board basis, | ||
47 | * not globally. | ||
48 | */ | ||
49 | if ((addr < _ramstart) || (addr >= _ramend)) | ||
50 | return(1); | ||
51 | |||
52 | /* Default case, not in ROM */ | ||
53 | return(0); | ||
54 | } | ||
55 | |||
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile index 2fd37dcc309b..719a313494bc 100644 --- a/arch/m68knommu/platform/5307/Makefile +++ b/arch/m68knommu/platform/5307/Makefile | |||
@@ -16,7 +16,7 @@ ifdef CONFIG_FULLDEBUG | |||
16 | AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 | 16 | AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 |
17 | endif | 17 | endif |
18 | 18 | ||
19 | obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o | 19 | obj-$(CONFIG_COLDFIRE) += entry.o vectors.o |
20 | obj-$(CONFIG_M5206) += timers.o | 20 | obj-$(CONFIG_M5206) += timers.o |
21 | obj-$(CONFIG_M5206e) += timers.o | 21 | obj-$(CONFIG_M5206e) += timers.o |
22 | obj-$(CONFIG_M520x) += pit.o | 22 | obj-$(CONFIG_M520x) += pit.o |
diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S index f0dba84d9101..c358aebe0af3 100644 --- a/arch/m68knommu/platform/5307/entry.S +++ b/arch/m68knommu/platform/5307/entry.S | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/m68knommu/platform/5307/entry.S | 2 | * linux/arch/m68knommu/platform/5307/entry.S |
3 | * | 3 | * |
4 | * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) | 4 | * Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com) |
5 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, | 5 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, |
6 | * Kenneth Albanowski <kjahds@kjahds.com>, | 6 | * Kenneth Albanowski <kjahds@kjahds.com>, |
7 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) | 7 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) |
@@ -155,34 +155,21 @@ Lsignal_return: | |||
155 | 155 | ||
156 | /* | 156 | /* |
157 | * This is the generic interrupt handler (for all hardware interrupt | 157 | * This is the generic interrupt handler (for all hardware interrupt |
158 | * sources). It figures out the vector number and calls the appropriate | 158 | * sources). Calls upto high level code to do all the work. |
159 | * interrupt service routine directly. | ||
160 | */ | 159 | */ |
161 | ENTRY(inthandler) | 160 | ENTRY(inthandler) |
162 | SAVE_ALL | 161 | SAVE_ALL |
163 | moveq #-1,%d0 | 162 | moveq #-1,%d0 |
164 | movel %d0,%sp@(PT_ORIG_D0) | 163 | movel %d0,%sp@(PT_ORIG_D0) |
165 | addql #1,local_irq_count | ||
166 | 164 | ||
167 | movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */ | 165 | movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */ |
168 | andl #0x03fc,%d0 /* mask out vector only */ | 166 | andl #0x03fc,%d0 /* mask out vector only */ |
169 | 167 | ||
170 | leal per_cpu__kstat+STAT_IRQ,%a0 | 168 | movel %sp,%sp@- /* push regs arg */ |
171 | addql #1,%a0@(%d0) | ||
172 | |||
173 | lsrl #2,%d0 /* calculate real vector # */ | 169 | lsrl #2,%d0 /* calculate real vector # */ |
174 | movel %d0,%d1 /* calculate array offset */ | 170 | movel %d0,%sp@- /* push vector number */ |
175 | lsll #4,%d1 | 171 | jbsr do_IRQ /* call high level irq handler */ |
176 | lea irq_list,%a0 | 172 | lea %sp@(8),%sp /* pop args off stack */ |
177 | addl %d1,%a0 /* pointer to array struct */ | ||
178 | |||
179 | movel %sp,%sp@- /* push regs arg onto stack */ | ||
180 | movel %a0@(8),%sp@- /* push devid arg */ | ||
181 | movel %d0,%sp@- /* push vector # on stack */ | ||
182 | |||
183 | movel %a0@,%a0 /* get function to call */ | ||
184 | jbsr %a0@ /* call vector handler */ | ||
185 | lea %sp@(12),%sp /* pop parameters off stack */ | ||
186 | 173 | ||
187 | bra ret_from_interrupt /* this was fallthrough */ | 174 | bra ret_from_interrupt /* this was fallthrough */ |
188 | 175 | ||
@@ -198,24 +185,15 @@ ENTRY(fasthandler) | |||
198 | movew %sp@(PT_FORMATVEC),%d0 | 185 | movew %sp@(PT_FORMATVEC),%d0 |
199 | andl #0x03fc,%d0 /* mask out vector only */ | 186 | andl #0x03fc,%d0 /* mask out vector only */ |
200 | 187 | ||
201 | leal per_cpu__kstat+STAT_IRQ,%a0 | 188 | movel %sp,%sp@- /* push regs arg */ |
202 | addql #1,%a0@(%d0) | ||
203 | |||
204 | movel %sp,%sp@- /* push regs arg onto stack */ | ||
205 | clrl %sp@- /* push devid arg */ | ||
206 | lsrl #2,%d0 /* calculate real vector # */ | 189 | lsrl #2,%d0 /* calculate real vector # */ |
207 | movel %d0,%sp@- /* push vector # on stack */ | 190 | movel %d0,%sp@- /* push vector number */ |
208 | 191 | jbsr do_IRQ /* call high level irq handler */ | |
209 | lsll #4,%d0 /* adjust for array offset */ | 192 | lea %sp@(8),%sp /* pop args off stack */ |
210 | lea irq_list,%a0 | ||
211 | movel %a0@(%d0),%a0 /* get function to call */ | ||
212 | jbsr %a0@ /* call vector handler */ | ||
213 | lea %sp@(12),%sp /* pop parameters off stack */ | ||
214 | 193 | ||
215 | RESTORE_LOCAL | 194 | RESTORE_LOCAL |
216 | 195 | ||
217 | ENTRY(ret_from_interrupt) | 196 | ENTRY(ret_from_interrupt) |
218 | subql #1,local_irq_count | ||
219 | jeq 2f | 197 | jeq 2f |
220 | 1: | 198 | 1: |
221 | RESTORE_ALL | 199 | RESTORE_ALL |
diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c deleted file mode 100644 index 751633038c4b..000000000000 --- a/arch/m68knommu/platform/5307/ints.c +++ /dev/null | |||
@@ -1,279 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code | ||
3 | * | ||
4 | * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) | ||
5 | * Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>, | ||
6 | * Kenneth Albanowski <kjahds@kjahds.com>, | ||
7 | * Copyright (C) 2000 Lineo Inc. (www.lineo.com) | ||
8 | * | ||
9 | * Based on: | ||
10 | * | ||
11 | * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General Public | ||
14 | * License. See the file COPYING in the main directory of this archive | ||
15 | * for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/kernel_stat.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/irqnode.h> | ||
30 | #include <asm/traps.h> | ||
31 | #include <asm/page.h> | ||
32 | #include <asm/machdep.h> | ||
33 | |||
34 | /* | ||
35 | * This table stores the address info for each vector handler. | ||
36 | */ | ||
37 | struct irq_entry irq_list[SYS_IRQS]; | ||
38 | |||
39 | #define NUM_IRQ_NODES 16 | ||
40 | static irq_node_t nodes[NUM_IRQ_NODES]; | ||
41 | |||
42 | /* The number of spurious interrupts */ | ||
43 | volatile unsigned int num_spurious; | ||
44 | |||
45 | unsigned int local_irq_count[NR_CPUS]; | ||
46 | |||
47 | static irqreturn_t default_irq_handler(int irq, void *ptr) | ||
48 | { | ||
49 | #if 1 | ||
50 | printk(KERN_INFO "%s(%d): default irq handler vec=%d [0x%x]\n", | ||
51 | __FILE__, __LINE__, irq, irq); | ||
52 | #endif | ||
53 | return(IRQ_HANDLED); | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * void init_IRQ(void) | ||
58 | * | ||
59 | * Parameters: None | ||
60 | * | ||
61 | * Returns: Nothing | ||
62 | * | ||
63 | * This function should be called during kernel startup to initialize | ||
64 | * the IRQ handling routines. | ||
65 | */ | ||
66 | |||
67 | void __init init_IRQ(void) | ||
68 | { | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < SYS_IRQS; i++) { | ||
72 | if (mach_default_handler) | ||
73 | irq_list[i].handler = mach_default_handler; | ||
74 | else | ||
75 | irq_list[i].handler = default_irq_handler; | ||
76 | irq_list[i].flags = IRQ_FLG_STD; | ||
77 | irq_list[i].dev_id = NULL; | ||
78 | irq_list[i].devname = NULL; | ||
79 | } | ||
80 | |||
81 | for (i = 0; i < NUM_IRQ_NODES; i++) | ||
82 | nodes[i].handler = NULL; | ||
83 | |||
84 | if (mach_init_IRQ) | ||
85 | mach_init_IRQ(); | ||
86 | } | ||
87 | |||
88 | irq_node_t *new_irq_node(void) | ||
89 | { | ||
90 | irq_node_t *node; | ||
91 | short i; | ||
92 | |||
93 | for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) | ||
94 | if (!node->handler) | ||
95 | return node; | ||
96 | |||
97 | printk(KERN_INFO "new_irq_node: out of nodes\n"); | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | int request_irq( | ||
102 | unsigned int irq, | ||
103 | irq_handler_t handler, | ||
104 | unsigned long flags, | ||
105 | const char *devname, | ||
106 | void *dev_id) | ||
107 | { | ||
108 | if (irq < 0 || irq >= NR_IRQS) { | ||
109 | printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", __FUNCTION__, | ||
110 | irq, devname); | ||
111 | return -ENXIO; | ||
112 | } | ||
113 | |||
114 | if (!(irq_list[irq].flags & IRQ_FLG_STD)) { | ||
115 | if (irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
116 | printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n", | ||
117 | __FUNCTION__, irq, irq_list[irq].devname); | ||
118 | return -EBUSY; | ||
119 | } | ||
120 | if (flags & IRQ_FLG_REPLACE) { | ||
121 | printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n", | ||
122 | __FUNCTION__, devname, irq, irq_list[irq].devname); | ||
123 | return -EBUSY; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (flags & IRQ_FLG_FAST) { | ||
128 | extern asmlinkage void fasthandler(void); | ||
129 | extern void set_evector(int vecnum, void (*handler)(void)); | ||
130 | set_evector(irq, fasthandler); | ||
131 | } | ||
132 | |||
133 | irq_list[irq].handler = handler; | ||
134 | irq_list[irq].flags = flags; | ||
135 | irq_list[irq].dev_id = dev_id; | ||
136 | irq_list[irq].devname = devname; | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | EXPORT_SYMBOL(request_irq); | ||
141 | |||
142 | void free_irq(unsigned int irq, void *dev_id) | ||
143 | { | ||
144 | if (irq >= NR_IRQS) { | ||
145 | printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | if (irq_list[irq].dev_id != dev_id) | ||
150 | printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", | ||
151 | __FUNCTION__, irq, irq_list[irq].devname); | ||
152 | |||
153 | if (irq_list[irq].flags & IRQ_FLG_FAST) { | ||
154 | extern asmlinkage void inthandler(void); | ||
155 | extern void set_evector(int vecnum, void (*handler)(void)); | ||
156 | set_evector(irq, inthandler); | ||
157 | } | ||
158 | |||
159 | if (mach_default_handler) | ||
160 | irq_list[irq].handler = mach_default_handler; | ||
161 | else | ||
162 | irq_list[irq].handler = default_irq_handler; | ||
163 | irq_list[irq].flags = IRQ_FLG_STD; | ||
164 | irq_list[irq].dev_id = NULL; | ||
165 | irq_list[irq].devname = NULL; | ||
166 | } | ||
167 | |||
168 | EXPORT_SYMBOL(free_irq); | ||
169 | |||
170 | |||
171 | int sys_request_irq(unsigned int irq, irq_handler_t handler, | ||
172 | unsigned long flags, const char *devname, void *dev_id) | ||
173 | { | ||
174 | if (irq > IRQ7) { | ||
175 | printk(KERN_WARNING "%s: Incorrect IRQ %d from %s\n", | ||
176 | __FUNCTION__, irq, devname); | ||
177 | return -ENXIO; | ||
178 | } | ||
179 | |||
180 | #if 0 | ||
181 | if (!(irq_list[irq].flags & IRQ_FLG_STD)) { | ||
182 | if (irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
183 | printk(KERN_WARNING "%s: IRQ %d from %s is not replaceable\n", | ||
184 | __FUNCTION__, irq, irq_list[irq].devname); | ||
185 | return -EBUSY; | ||
186 | } | ||
187 | if (!(flags & IRQ_FLG_REPLACE)) { | ||
188 | printk(KERN_WARNING "%s: %s can't replace IRQ %d from %s\n", | ||
189 | __FUNCTION__, devname, irq, irq_list[irq].devname); | ||
190 | return -EBUSY; | ||
191 | } | ||
192 | } | ||
193 | #endif | ||
194 | |||
195 | irq_list[irq].handler = handler; | ||
196 | irq_list[irq].flags = flags; | ||
197 | irq_list[irq].dev_id = dev_id; | ||
198 | irq_list[irq].devname = devname; | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | void sys_free_irq(unsigned int irq, void *dev_id) | ||
203 | { | ||
204 | if (irq > IRQ7) { | ||
205 | printk(KERN_WARNING "%s: Incorrect IRQ %d\n", __FUNCTION__, irq); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | if (irq_list[irq].dev_id != dev_id) | ||
210 | printk(KERN_WARNING "%s: Removing probably wrong IRQ %d from %s\n", | ||
211 | __FUNCTION__, irq, irq_list[irq].devname); | ||
212 | |||
213 | irq_list[irq].handler = mach_default_handler; | ||
214 | irq_list[irq].flags = 0; | ||
215 | irq_list[irq].dev_id = NULL; | ||
216 | irq_list[irq].devname = NULL; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Do we need these probe functions on the m68k? | ||
221 | * | ||
222 | * ... may be useful with ISA devices | ||
223 | */ | ||
224 | unsigned long probe_irq_on (void) | ||
225 | { | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | EXPORT_SYMBOL(probe_irq_on); | ||
230 | |||
231 | int probe_irq_off (unsigned long irqs) | ||
232 | { | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | EXPORT_SYMBOL(probe_irq_off); | ||
237 | |||
238 | asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) | ||
239 | { | ||
240 | if (vec >= VEC_INT1 && vec <= VEC_INT7) { | ||
241 | vec -= VEC_SPUR; | ||
242 | kstat_cpu(0).irqs[vec]++; | ||
243 | irq_list[vec].handler(vec, irq_list[vec].dev_id); | ||
244 | } else { | ||
245 | if (mach_process_int) | ||
246 | mach_process_int(vec, fp); | ||
247 | else | ||
248 | panic("Can't process interrupt vector %ld\n", vec); | ||
249 | return; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | |||
254 | int show_interrupts(struct seq_file *p, void *v) | ||
255 | { | ||
256 | int i = *(loff_t *) v; | ||
257 | |||
258 | if (i < NR_IRQS) { | ||
259 | if (! (irq_list[i].flags & IRQ_FLG_STD)) { | ||
260 | seq_printf(p, "%3d: %10u ", i, | ||
261 | (i ? kstat_cpu(0).irqs[i] : num_spurious)); | ||
262 | if (irq_list[i].flags & IRQ_FLG_LOCK) | ||
263 | seq_printf(p, "L "); | ||
264 | else | ||
265 | seq_printf(p, " "); | ||
266 | seq_printf(p, "%s\n", irq_list[i].devname); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | if (i == NR_IRQS && mach_get_irq_list) | ||
271 | mach_get_irq_list(p, v); | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | void init_irq_proc(void) | ||
276 | { | ||
277 | /* Insert /proc/irq driver here */ | ||
278 | } | ||
279 | |||
diff --git a/arch/m68knommu/platform/5307/vectors.c b/arch/m68knommu/platform/5307/vectors.c index 2a8b0d044ce5..6cf894620234 100644 --- a/arch/m68knommu/platform/5307/vectors.c +++ b/arch/m68knommu/platform/5307/vectors.c | |||
@@ -3,23 +3,17 @@ | |||
3 | /* | 3 | /* |
4 | * linux/arch/m68knommu/platform/5307/vectors.c | 4 | * linux/arch/m68knommu/platform/5307/vectors.c |
5 | * | 5 | * |
6 | * Copyright (C) 1999-2003, Greg Ungerer <gerg@snapgear.com> | 6 | * Copyright (C) 1999-2007, Greg Ungerer <gerg@snapgear.com> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /***************************************************************************/ | 9 | /***************************************************************************/ |
10 | 10 | ||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/sched.h> | ||
13 | #include <linux/param.h> | ||
14 | #include <linux/init.h> | 12 | #include <linux/init.h> |
15 | #include <linux/unistd.h> | 13 | #include <linux/irq.h> |
16 | #include <linux/delay.h> | ||
17 | #include <asm/irq.h> | ||
18 | #include <asm/dma.h> | ||
19 | #include <asm/traps.h> | 14 | #include <asm/traps.h> |
20 | #include <asm/machdep.h> | 15 | #include <asm/machdep.h> |
21 | #include <asm/coldfire.h> | 16 | #include <asm/coldfire.h> |
22 | #include <asm/mcftimer.h> | ||
23 | #include <asm/mcfsim.h> | 17 | #include <asm/mcfsim.h> |
24 | #include <asm/mcfdma.h> | 18 | #include <asm/mcfdma.h> |
25 | #include <asm/mcfwdebug.h> | 19 | #include <asm/mcfwdebug.h> |
@@ -56,7 +50,7 @@ asmlinkage void trap(void); | |||
56 | asmlinkage void system_call(void); | 50 | asmlinkage void system_call(void); |
57 | asmlinkage void inthandler(void); | 51 | asmlinkage void inthandler(void); |
58 | 52 | ||
59 | void __init coldfire_trap_init(void) | 53 | void __init init_vectors(void) |
60 | { | 54 | { |
61 | int i; | 55 | int i; |
62 | 56 | ||
@@ -86,6 +80,23 @@ void __init coldfire_trap_init(void) | |||
86 | 80 | ||
87 | /***************************************************************************/ | 81 | /***************************************************************************/ |
88 | 82 | ||
83 | void enable_vector(unsigned int irq) | ||
84 | { | ||
85 | /* Currently no action on ColdFire */ | ||
86 | } | ||
87 | |||
88 | void disable_vector(unsigned int irq) | ||
89 | { | ||
90 | /* Currently no action on ColdFire */ | ||
91 | } | ||
92 | |||
93 | void ack_vector(unsigned int irq) | ||
94 | { | ||
95 | /* Currently no action on ColdFire */ | ||
96 | } | ||
97 | |||
98 | /***************************************************************************/ | ||
99 | |||
89 | void coldfire_reset(void) | 100 | void coldfire_reset(void) |
90 | { | 101 | { |
91 | HARD_RESET_NOW(); | 102 | HARD_RESET_NOW(); |
diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S index f97862715450..b1aef72f3baf 100644 --- a/arch/m68knommu/platform/68328/entry.S +++ b/arch/m68knommu/platform/68328/entry.S | |||
@@ -133,7 +133,6 @@ Lreturn: | |||
133 | */ | 133 | */ |
134 | inthandler1: | 134 | inthandler1: |
135 | SAVE_ALL | 135 | SAVE_ALL |
136 | addql #1,local_irq_count /* put exception # in d0*/ | ||
137 | movew %sp@(PT_VECTOR), %d0 | 136 | movew %sp@(PT_VECTOR), %d0 |
138 | and #0x3ff, %d0 | 137 | and #0x3ff, %d0 |
139 | 138 | ||
@@ -145,7 +144,6 @@ inthandler1: | |||
145 | 144 | ||
146 | inthandler2: | 145 | inthandler2: |
147 | SAVE_ALL | 146 | SAVE_ALL |
148 | addql #1,local_irq_count /* put exception # in d0*/ | ||
149 | movew %sp@(PT_VECTOR), %d0 | 147 | movew %sp@(PT_VECTOR), %d0 |
150 | and #0x3ff, %d0 | 148 | and #0x3ff, %d0 |
151 | 149 | ||
@@ -157,7 +155,6 @@ inthandler2: | |||
157 | 155 | ||
158 | inthandler3: | 156 | inthandler3: |
159 | SAVE_ALL | 157 | SAVE_ALL |
160 | addql #1,local_irq_count /* put exception # in d0*/ | ||
161 | movew %sp@(PT_VECTOR), %d0 | 158 | movew %sp@(PT_VECTOR), %d0 |
162 | and #0x3ff, %d0 | 159 | and #0x3ff, %d0 |
163 | 160 | ||
@@ -169,7 +166,6 @@ inthandler3: | |||
169 | 166 | ||
170 | inthandler4: | 167 | inthandler4: |
171 | SAVE_ALL | 168 | SAVE_ALL |
172 | addql #1,local_irq_count /* put exception # in d0*/ | ||
173 | movew %sp@(PT_VECTOR), %d0 | 169 | movew %sp@(PT_VECTOR), %d0 |
174 | and #0x3ff, %d0 | 170 | and #0x3ff, %d0 |
175 | 171 | ||
@@ -181,7 +177,6 @@ inthandler4: | |||
181 | 177 | ||
182 | inthandler5: | 178 | inthandler5: |
183 | SAVE_ALL | 179 | SAVE_ALL |
184 | addql #1,local_irq_count /* put exception # in d0*/ | ||
185 | movew %sp@(PT_VECTOR), %d0 | 180 | movew %sp@(PT_VECTOR), %d0 |
186 | and #0x3ff, %d0 | 181 | and #0x3ff, %d0 |
187 | 182 | ||
@@ -193,7 +188,6 @@ inthandler5: | |||
193 | 188 | ||
194 | inthandler6: | 189 | inthandler6: |
195 | SAVE_ALL | 190 | SAVE_ALL |
196 | addql #1,local_irq_count /* put exception # in d0*/ | ||
197 | movew %sp@(PT_VECTOR), %d0 | 191 | movew %sp@(PT_VECTOR), %d0 |
198 | and #0x3ff, %d0 | 192 | and #0x3ff, %d0 |
199 | 193 | ||
@@ -205,7 +199,6 @@ inthandler6: | |||
205 | 199 | ||
206 | inthandler7: | 200 | inthandler7: |
207 | SAVE_ALL | 201 | SAVE_ALL |
208 | addql #1,local_irq_count /* put exception # in d0*/ | ||
209 | movew %sp@(PT_VECTOR), %d0 | 202 | movew %sp@(PT_VECTOR), %d0 |
210 | and #0x3ff, %d0 | 203 | and #0x3ff, %d0 |
211 | 204 | ||
@@ -217,7 +210,6 @@ inthandler7: | |||
217 | 210 | ||
218 | inthandler: | 211 | inthandler: |
219 | SAVE_ALL | 212 | SAVE_ALL |
220 | addql #1,local_irq_count /* put exception # in d0*/ | ||
221 | movew %sp@(PT_VECTOR), %d0 | 213 | movew %sp@(PT_VECTOR), %d0 |
222 | and #0x3ff, %d0 | 214 | and #0x3ff, %d0 |
223 | 215 | ||
@@ -228,7 +220,6 @@ inthandler: | |||
228 | bra ret_from_interrupt | 220 | bra ret_from_interrupt |
229 | 221 | ||
230 | ret_from_interrupt: | 222 | ret_from_interrupt: |
231 | subql #1,local_irq_count | ||
232 | jeq 1f | 223 | jeq 1f |
233 | 2: | 224 | 2: |
234 | RESTORE_ALL | 225 | RESTORE_ALL |
@@ -238,7 +229,6 @@ ret_from_interrupt: | |||
238 | jhi 2b | 229 | jhi 2b |
239 | 230 | ||
240 | /* check if we need to do software interrupts */ | 231 | /* check if we need to do software interrupts */ |
241 | movel local_irq_count,%d0 | ||
242 | jeq ret_from_exception | 232 | jeq ret_from_exception |
243 | 233 | ||
244 | pea ret_from_exception | 234 | pea ret_from_exception |
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c index 3de6e337554e..72e56d554f4f 100644 --- a/arch/m68knommu/platform/68328/ints.c +++ b/arch/m68knommu/platform/68328/ints.c | |||
@@ -9,21 +9,14 @@ | |||
9 | * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> | 9 | * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/types.h> | 12 | #include <linux/types.h> |
14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
15 | #include <linux/sched.h> | 14 | #include <linux/init.h> |
16 | #include <linux/kernel_stat.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
19 | 16 | #include <linux/irq.h> | |
20 | #include <asm/system.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/irqnode.h> | ||
23 | #include <asm/traps.h> | 17 | #include <asm/traps.h> |
24 | #include <asm/io.h> | 18 | #include <asm/io.h> |
25 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
26 | #include <asm/setup.h> | ||
27 | 20 | ||
28 | #if defined(CONFIG_M68328) | 21 | #if defined(CONFIG_M68328) |
29 | #include <asm/MC68328.h> | 22 | #include <asm/MC68328.h> |
@@ -79,16 +72,12 @@ extern e_vector *_ramvec; | |||
79 | 72 | ||
80 | /* The number of spurious interrupts */ | 73 | /* The number of spurious interrupts */ |
81 | volatile unsigned int num_spurious; | 74 | volatile unsigned int num_spurious; |
82 | unsigned int local_irq_count[NR_CPUS]; | ||
83 | |||
84 | /* irq node variables for the 32 (potential) on chip sources */ | ||
85 | static irq_node_t int_irq_list[NR_IRQS]; | ||
86 | 75 | ||
87 | /* | 76 | /* |
88 | * This function should be called during kernel startup to initialize | 77 | * This function should be called during kernel startup to initialize |
89 | * the IRQ handling routines. | 78 | * the machine vector table. |
90 | */ | 79 | */ |
91 | void init_IRQ(void) | 80 | void __init init_vectors(void) |
92 | { | 81 | { |
93 | int i; | 82 | int i; |
94 | 83 | ||
@@ -108,96 +97,10 @@ void init_IRQ(void) | |||
108 | 97 | ||
109 | IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ | 98 | IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ |
110 | 99 | ||
111 | /* initialize handlers */ | ||
112 | for (i = 0; i < NR_IRQS; i++) { | ||
113 | int_irq_list[i].handler = bad_interrupt; | ||
114 | int_irq_list[i].flags = IRQ_FLG_STD; | ||
115 | int_irq_list[i].dev_id = NULL; | ||
116 | int_irq_list[i].devname = NULL; | ||
117 | } | ||
118 | |||
119 | /* turn off all interrupts */ | 100 | /* turn off all interrupts */ |
120 | IMR = ~0; | 101 | IMR = ~0; |
121 | } | 102 | } |
122 | 103 | ||
123 | int request_irq( | ||
124 | unsigned int irq, | ||
125 | irq_handler_t handler, | ||
126 | unsigned long flags, | ||
127 | const char *devname, | ||
128 | void *dev_id) | ||
129 | { | ||
130 | if (irq >= NR_IRQS) { | ||
131 | printk (KERN_ERR "%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname); | ||
132 | return -ENXIO; | ||
133 | } | ||
134 | |||
135 | if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) { | ||
136 | if (int_irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
137 | printk(KERN_ERR "%s: IRQ %d from %s is not replaceable\n", | ||
138 | __FUNCTION__, irq, int_irq_list[irq].devname); | ||
139 | return -EBUSY; | ||
140 | } | ||
141 | if (flags & IRQ_FLG_REPLACE) { | ||
142 | printk(KERN_ERR "%s: %s can't replace IRQ %d from %s\n", | ||
143 | __FUNCTION__, devname, irq, int_irq_list[irq].devname); | ||
144 | return -EBUSY; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | int_irq_list[irq].handler = handler; | ||
149 | int_irq_list[irq].flags = flags; | ||
150 | int_irq_list[irq].dev_id = dev_id; | ||
151 | int_irq_list[irq].devname = devname; | ||
152 | |||
153 | IMR &= ~(1<<irq); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | EXPORT_SYMBOL(request_irq); | ||
159 | |||
160 | void free_irq(unsigned int irq, void *dev_id) | ||
161 | { | ||
162 | if (irq >= NR_IRQS) { | ||
163 | printk (KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq); | ||
164 | return; | ||
165 | } | ||
166 | |||
167 | if (int_irq_list[irq].dev_id != dev_id) | ||
168 | printk(KERN_INFO "%s: removing probably wrong IRQ %d from %s\n", | ||
169 | __FUNCTION__, irq, int_irq_list[irq].devname); | ||
170 | |||
171 | int_irq_list[irq].handler = bad_interrupt; | ||
172 | int_irq_list[irq].flags = IRQ_FLG_STD; | ||
173 | int_irq_list[irq].dev_id = NULL; | ||
174 | int_irq_list[irq].devname = NULL; | ||
175 | |||
176 | IMR |= 1<<irq; | ||
177 | } | ||
178 | |||
179 | EXPORT_SYMBOL(free_irq); | ||
180 | |||
181 | int show_interrupts(struct seq_file *p, void *v) | ||
182 | { | ||
183 | int i = *(loff_t *) v; | ||
184 | |||
185 | if (i < NR_IRQS) { | ||
186 | if (int_irq_list[i].devname) { | ||
187 | seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]); | ||
188 | if (int_irq_list[i].flags & IRQ_FLG_LOCK) | ||
189 | seq_printf(p, "L "); | ||
190 | else | ||
191 | seq_printf(p, " "); | ||
192 | seq_printf(p, "%s\n", int_irq_list[i].devname); | ||
193 | } | ||
194 | } | ||
195 | if (i == NR_IRQS) | ||
196 | seq_printf(p, " : %10u spurious\n", num_spurious); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | /* The 68k family did not have a good way to determine the source | 104 | /* The 68k family did not have a good way to determine the source |
202 | * of interrupts until later in the family. The EC000 core does | 105 | * of interrupts until later in the family. The EC000 core does |
203 | * not provide the vector number on the stack, we vector everything | 106 | * not provide the vector number on the stack, we vector everything |
@@ -255,14 +158,23 @@ void process_int(int vec, struct pt_regs *fp) | |||
255 | irq++; | 158 | irq++; |
256 | } | 159 | } |
257 | 160 | ||
258 | kstat_cpu(0).irqs[irq]++; | 161 | do_IRQ(irq, fp); |
259 | |||
260 | if (int_irq_list[irq].handler) { | ||
261 | int_irq_list[irq].handler(irq, int_irq_list[irq].dev_id, fp); | ||
262 | } else { | ||
263 | printk(KERN_ERR "unregistered interrupt %d!\nTurning it off in the IMR...\n", irq); | ||
264 | IMR |= mask; | ||
265 | } | ||
266 | pend &= ~mask; | 162 | pend &= ~mask; |
267 | } | 163 | } |
268 | } | 164 | } |
165 | |||
166 | void enable_vector(unsigned int irq) | ||
167 | { | ||
168 | IMR &= ~(1<<irq); | ||
169 | } | ||
170 | |||
171 | void disable_vector(unsigned int irq) | ||
172 | { | ||
173 | IMR |= (1<<irq); | ||
174 | } | ||
175 | |||
176 | void ack_vector(unsigned int irq) | ||
177 | { | ||
178 | /* Nothing needed */ | ||
179 | } | ||
180 | |||
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S index f1af8977f294..55dfefe38642 100644 --- a/arch/m68knommu/platform/68360/entry.S +++ b/arch/m68knommu/platform/68360/entry.S | |||
@@ -120,23 +120,21 @@ Lreturn: | |||
120 | RESTORE_ALL | 120 | RESTORE_ALL |
121 | 121 | ||
122 | /* | 122 | /* |
123 | * This is the main interrupt handler, responsible for calling process_int() | 123 | * This is the main interrupt handler, responsible for calling do_IRQ() |
124 | */ | 124 | */ |
125 | inthandler: | 125 | inthandler: |
126 | SAVE_ALL | 126 | SAVE_ALL |
127 | addql #1,local_irq_count /* put exception # in d0*/ | ||
128 | movew %sp@(PT_VECTOR), %d0 | 127 | movew %sp@(PT_VECTOR), %d0 |
129 | and.l #0x3ff, %d0 | 128 | and.l #0x3ff, %d0 |
130 | lsr.l #0x02, %d0 | 129 | lsr.l #0x02, %d0 |
131 | 130 | ||
132 | movel %sp,%sp@- | 131 | movel %sp,%sp@- |
133 | movel %d0,%sp@- /* put vector # on stack*/ | 132 | movel %d0,%sp@- /* put vector # on stack*/ |
134 | jbsr process_int /* process the IRQ*/ | 133 | jbsr do_IRQ /* process the IRQ*/ |
135 | 3: addql #8,%sp /* pop parameters off stack*/ | 134 | 3: addql #8,%sp /* pop parameters off stack*/ |
136 | bra ret_from_interrupt | 135 | bra ret_from_interrupt |
137 | 136 | ||
138 | ret_from_interrupt: | 137 | ret_from_interrupt: |
139 | subql #1,local_irq_count | ||
140 | jeq 1f | 138 | jeq 1f |
141 | 2: | 139 | 2: |
142 | RESTORE_ALL | 140 | RESTORE_ALL |
diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c index 4df3c146eb74..c36781157e09 100644 --- a/arch/m68knommu/platform/68360/ints.c +++ b/arch/m68knommu/platform/68360/ints.c | |||
@@ -10,20 +10,13 @@ | |||
10 | * Copyright (c) 1999 D. Jeff Dionne <jeff@uclinux.org> | 10 | * Copyright (c) 1999 D. Jeff Dionne <jeff@uclinux.org> |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/types.h> | 13 | #include <linux/types.h> |
15 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
16 | #include <linux/sched.h> | 15 | #include <linux/init.h> |
17 | #include <linux/kernel_stat.h> | 16 | #include <linux/interrupt.h> |
18 | #include <linux/errno.h> | 17 | #include <linux/irq.h> |
19 | |||
20 | #include <asm/system.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/irqnode.h> | ||
23 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
24 | #include <asm/io.h> | ||
25 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
26 | #include <asm/setup.h> | ||
27 | #include <asm/m68360.h> | 20 | #include <asm/m68360.h> |
28 | 21 | ||
29 | /* from quicc/commproc.c: */ | 22 | /* from quicc/commproc.c: */ |
@@ -36,26 +29,19 @@ extern void cpm_interrupt_init(void); | |||
36 | asmlinkage void system_call(void); | 29 | asmlinkage void system_call(void); |
37 | asmlinkage void buserr(void); | 30 | asmlinkage void buserr(void); |
38 | asmlinkage void trap(void); | 31 | asmlinkage void trap(void); |
39 | asmlinkage irqreturn_t bad_interrupt(void); | 32 | asmlinkage void bad_interrupt(void); |
40 | asmlinkage irqreturn_t inthandler(void); | 33 | asmlinkage void inthandler(void); |
41 | 34 | ||
42 | extern void *_ramvec[]; | 35 | extern void *_ramvec[]; |
43 | 36 | ||
44 | /* The number of spurious interrupts */ | 37 | /* The number of spurious interrupts */ |
45 | volatile unsigned int num_spurious; | 38 | volatile unsigned int num_spurious; |
46 | unsigned int local_irq_count[NR_CPUS]; | ||
47 | |||
48 | /* irq node variables for the 32 (potential) on chip sources */ | ||
49 | static irq_node_t int_irq_list[INTERNAL_IRQS]; | ||
50 | |||
51 | static short int_irq_ablecount[INTERNAL_IRQS]; | ||
52 | 39 | ||
53 | /* | 40 | /* |
54 | * This function should be called during kernel startup to initialize | 41 | * This function should be called during kernel startup to initialize |
55 | * IRQ handling routines. | 42 | * the vector table. |
56 | */ | 43 | */ |
57 | 44 | void init_vectors(void) | |
58 | void init_IRQ(void) | ||
59 | { | 45 | { |
60 | int i; | 46 | int i; |
61 | int vba = (CPM_VECTOR_BASE<<4); | 47 | int vba = (CPM_VECTOR_BASE<<4); |
@@ -79,7 +65,6 @@ void init_IRQ(void) | |||
79 | _ramvec[32] = system_call; | 65 | _ramvec[32] = system_call; |
80 | _ramvec[33] = trap; | 66 | _ramvec[33] = trap; |
81 | 67 | ||
82 | |||
83 | cpm_interrupt_init(); | 68 | cpm_interrupt_init(); |
84 | 69 | ||
85 | /* set up CICR for vector base address and irq level */ | 70 | /* set up CICR for vector base address and irq level */ |
@@ -124,212 +109,20 @@ void init_IRQ(void) | |||
124 | 109 | ||
125 | /* turn off all CPM interrupts */ | 110 | /* turn off all CPM interrupts */ |
126 | pquicc->intr_cimr = 0x00000000; | 111 | pquicc->intr_cimr = 0x00000000; |
127 | |||
128 | /* initialize handlers */ | ||
129 | for (i = 0; i < INTERNAL_IRQS; i++) { | ||
130 | int_irq_list[i].handler = NULL; | ||
131 | int_irq_list[i].flags = IRQ_FLG_STD; | ||
132 | int_irq_list[i].dev_id = NULL; | ||
133 | int_irq_list[i].devname = NULL; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | #if 0 | ||
138 | void M68360_insert_irq(irq_node_t **list, irq_node_t *node) | ||
139 | { | ||
140 | unsigned long flags; | ||
141 | irq_node_t *cur; | ||
142 | |||
143 | if (!node->dev_id) | ||
144 | printk(KERN_INFO "%s: Warning: dev_id of %s is zero\n", | ||
145 | __FUNCTION__, node->devname); | ||
146 | |||
147 | local_irq_save(flags); | ||
148 | |||
149 | cur = *list; | ||
150 | |||
151 | while (cur) { | ||
152 | list = &cur->next; | ||
153 | cur = cur->next; | ||
154 | } | ||
155 | |||
156 | node->next = cur; | ||
157 | *list = node; | ||
158 | |||
159 | local_irq_restore(flags); | ||
160 | } | 112 | } |
161 | 113 | ||
162 | void M68360_delete_irq(irq_node_t **list, void *dev_id) | 114 | void enable_vector(unsigned int irq) |
163 | { | 115 | { |
164 | unsigned long flags; | 116 | pquicc->intr_cimr |= (1 << irq); |
165 | irq_node_t *node; | ||
166 | |||
167 | local_irq_save(flags); | ||
168 | |||
169 | for (node = *list; node; list = &node->next, node = *list) { | ||
170 | if (node->dev_id == dev_id) { | ||
171 | *list = node->next; | ||
172 | /* Mark it as free. */ | ||
173 | node->handler = NULL; | ||
174 | local_irq_restore(flags); | ||
175 | return; | ||
176 | } | ||
177 | } | ||
178 | local_irq_restore(flags); | ||
179 | printk (KERN_INFO "%s: tried to remove invalid irq\n", __FUNCTION__); | ||
180 | } | 117 | } |
181 | #endif | ||
182 | 118 | ||
183 | int request_irq( | 119 | void disable_vector(unsigned int irq) |
184 | unsigned int irq, | ||
185 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
186 | unsigned long flags, | ||
187 | const char *devname, | ||
188 | void *dev_id) | ||
189 | { | 120 | { |
190 | int mask = (1<<irq); | 121 | pquicc->intr_cimr &= ~(1 << irq); |
191 | |||
192 | irq += (CPM_VECTOR_BASE<<4); | ||
193 | |||
194 | if (irq >= INTERNAL_IRQS) { | ||
195 | printk (KERN_ERR "%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname); | ||
196 | return -ENXIO; | ||
197 | } | ||
198 | |||
199 | if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) { | ||
200 | if (int_irq_list[irq].flags & IRQ_FLG_LOCK) { | ||
201 | printk(KERN_ERR "%s: IRQ %d from %s is not replaceable\n", | ||
202 | __FUNCTION__, irq, int_irq_list[irq].devname); | ||
203 | return -EBUSY; | ||
204 | } | ||
205 | if (flags & IRQ_FLG_REPLACE) { | ||
206 | printk(KERN_ERR "%s: %s can't replace IRQ %d from %s\n", | ||
207 | __FUNCTION__, devname, irq, int_irq_list[irq].devname); | ||
208 | return -EBUSY; | ||
209 | } | ||
210 | } | ||
211 | int_irq_list[irq].handler = handler; | ||
212 | int_irq_list[irq].flags = flags; | ||
213 | int_irq_list[irq].dev_id = dev_id; | ||
214 | int_irq_list[irq].devname = devname; | ||
215 | |||
216 | /* enable in the CIMR */ | ||
217 | if (!int_irq_ablecount[irq]) | ||
218 | pquicc->intr_cimr |= mask; | ||
219 | /* *(volatile unsigned long *)0xfffff304 &= ~(1<<irq); */ | ||
220 | |||
221 | return 0; | ||
222 | } | 122 | } |
223 | 123 | ||
224 | EXPORT_SYMBOL(request_irq); | 124 | void ack_vector(unsigned int irq) |
225 | |||
226 | void free_irq(unsigned int irq, void *dev_id) | ||
227 | { | 125 | { |
228 | if (irq >= INTERNAL_IRQS) { | 126 | pquicc->intr_cisr = (1 << irq); |
229 | printk (KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | if (int_irq_list[irq].dev_id != dev_id) | ||
234 | printk(KERN_INFO "%s: removing probably wrong IRQ %d from %s\n", | ||
235 | __FUNCTION__, irq, int_irq_list[irq].devname); | ||
236 | int_irq_list[irq].handler = NULL; | ||
237 | int_irq_list[irq].flags = IRQ_FLG_STD; | ||
238 | int_irq_list[irq].dev_id = NULL; | ||
239 | int_irq_list[irq].devname = NULL; | ||
240 | |||
241 | *(volatile unsigned long *)0xfffff304 |= 1<<irq; | ||
242 | } | 127 | } |
243 | 128 | ||
244 | EXPORT_SYMBOL(free_irq); | ||
245 | |||
246 | #if 0 | ||
247 | /* | ||
248 | * Enable/disable a particular machine specific interrupt source. | ||
249 | * Note that this may affect other interrupts in case of a shared interrupt. | ||
250 | * This function should only be called for a _very_ short time to change some | ||
251 | * internal data, that may not be changed by the interrupt at the same time. | ||
252 | * int_(enable|disable)_irq calls may also be nested. | ||
253 | */ | ||
254 | void M68360_enable_irq(unsigned int irq) | ||
255 | { | ||
256 | if (irq >= INTERNAL_IRQS) { | ||
257 | printk(KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq); | ||
258 | return; | ||
259 | } | ||
260 | |||
261 | if (--int_irq_ablecount[irq]) | ||
262 | return; | ||
263 | |||
264 | /* enable the interrupt */ | ||
265 | *(volatile unsigned long *)0xfffff304 &= ~(1<<irq); | ||
266 | } | ||
267 | |||
268 | void M68360_disable_irq(unsigned int irq) | ||
269 | { | ||
270 | if (irq >= INTERNAL_IRQS) { | ||
271 | printk(KERN_ERR "%s: Unknown IRQ %d\n", __FUNCTION__, irq); | ||
272 | return; | ||
273 | } | ||
274 | |||
275 | if (int_irq_ablecount[irq]++) | ||
276 | return; | ||
277 | |||
278 | /* disable the interrupt */ | ||
279 | *(volatile unsigned long *)0xfffff304 |= 1<<irq; | ||
280 | } | ||
281 | #endif | ||
282 | |||
283 | int show_interrupts(struct seq_file *p, void *v) | ||
284 | { | ||
285 | int i = *(loff_t *) v; | ||
286 | |||
287 | if (i < NR_IRQS) { | ||
288 | if (int_irq_list[i].devname) { | ||
289 | seq_printf(p, "%3d: %10u ", i, kstat_cpu(0).irqs[i]); | ||
290 | if (int_irq_list[i].flags & IRQ_FLG_LOCK) | ||
291 | seq_printf(p, "L "); | ||
292 | else | ||
293 | seq_printf(p, " "); | ||
294 | seq_printf(p, "%s\n", int_irq_list[i].devname); | ||
295 | } | ||
296 | } | ||
297 | if (i == NR_IRQS) | ||
298 | seq_printf(p, " : %10u spurious\n", num_spurious); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | /* The 68k family did not have a good way to determine the source | ||
304 | * of interrupts until later in the family. The EC000 core does | ||
305 | * not provide the vector number on the stack, we vector everything | ||
306 | * into one vector and look in the blasted mask register... | ||
307 | * This code is designed to be fast, almost constant time, not clean! | ||
308 | */ | ||
309 | void process_int(int vec, struct pt_regs *fp) | ||
310 | { | ||
311 | int irq; | ||
312 | int mask; | ||
313 | |||
314 | /* unsigned long pend = *(volatile unsigned long *)0xfffff30c; */ | ||
315 | |||
316 | /* irq = vec + (CPM_VECTOR_BASE<<4); */ | ||
317 | irq = vec; | ||
318 | |||
319 | /* unsigned long pend = *(volatile unsigned long *)pquicc->intr_cipr; */ | ||
320 | |||
321 | /* Bugger all that weirdness. For the moment, I seem to know where I came from; | ||
322 | * vec is passed from a specific ISR, so I'll use it. */ | ||
323 | |||
324 | if (int_irq_list[irq].handler) { | ||
325 | int_irq_list[irq].handler(irq , int_irq_list[irq].dev_id, fp); | ||
326 | kstat_cpu(0).irqs[irq]++; | ||
327 | pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */ | ||
328 | } else { | ||
329 | printk(KERN_ERR "unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq); | ||
330 | /* *(volatile unsigned long *)0xfffff304 |= mask; */ | ||
331 | pquicc->intr_cimr &= ~(1 << vec); | ||
332 | num_spurious += 1; | ||
333 | } | ||
334 | return(IRQ_HANDLED); | ||
335 | } | ||
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c index 2f0e4c08eb04..56003188f17c 100644 --- a/arch/mips/basler/excite/excite_setup.c +++ b/arch/mips/basler/excite/excite_setup.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/tty.h> | 26 | #include <linux/tty.h> |
27 | #include <linux/serial_core.h> | 27 | #include <linux/serial_core.h> |
28 | #include <linux/serial.h> | 28 | #include <linux/serial.h> |
29 | #include <linux/serial_8250.h> | ||
29 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
30 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
31 | #include <asm/bootinfo.h> | 32 | #include <asm/bootinfo.h> |
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c index ea965529e5e0..ed58c13b6032 100644 --- a/arch/mips/gt64120/wrppmc/setup.c +++ b/arch/mips/gt64120/wrppmc/setup.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/tty.h> | 14 | #include <linux/tty.h> |
15 | #include <linux/serial.h> | 15 | #include <linux/serial.h> |
16 | #include <linux/serial_core.h> | 16 | #include <linux/serial_core.h> |
17 | #include <linux/serial_8250.h> | ||
17 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
18 | 19 | ||
19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index b5a7b46bbc49..893e7bccf226 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -174,17 +174,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
174 | switch (request) { | 174 | switch (request) { |
175 | /* when I and D space are separate, these will need to be fixed. */ | 175 | /* when I and D space are separate, these will need to be fixed. */ |
176 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 176 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
177 | case PTRACE_PEEKDATA: { | 177 | case PTRACE_PEEKDATA: |
178 | unsigned long tmp; | 178 | ret = generic_ptrace_peekdata(child, addr, data); |
179 | int copied; | ||
180 | |||
181 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
182 | ret = -EIO; | ||
183 | if (copied != sizeof(tmp)) | ||
184 | break; | ||
185 | ret = put_user(tmp,(unsigned long __user *) data); | ||
186 | break; | 179 | break; |
187 | } | ||
188 | 180 | ||
189 | /* Read the word at location addr in the USER area. */ | 181 | /* Read the word at location addr in the USER area. */ |
190 | case PTRACE_PEEKUSR: { | 182 | case PTRACE_PEEKUSR: { |
@@ -313,11 +305,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
313 | /* when I and D space are separate, this will have to be fixed. */ | 305 | /* when I and D space are separate, this will have to be fixed. */ |
314 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 306 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
315 | case PTRACE_POKEDATA: | 307 | case PTRACE_POKEDATA: |
316 | ret = 0; | 308 | ret = generic_ptrace_pokedata(child, addr, data); |
317 | if (access_process_vm(child, addr, &data, sizeof(data), 1) | ||
318 | == sizeof(data)) | ||
319 | break; | ||
320 | ret = -EIO; | ||
321 | break; | 309 | break; |
322 | 310 | ||
323 | case PTRACE_POKEUSR: { | 311 | case PTRACE_POKEUSR: { |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 37c562c4c817..ce277cb34dd0 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -326,6 +326,7 @@ void __noreturn die(const char * str, struct pt_regs * regs) | |||
326 | #endif /* CONFIG_MIPS_MT_SMTC */ | 326 | #endif /* CONFIG_MIPS_MT_SMTC */ |
327 | printk("%s[#%d]:\n", str, ++die_counter); | 327 | printk("%s[#%d]:\n", str, ++die_counter); |
328 | show_registers(regs); | 328 | show_registers(regs); |
329 | add_taint(TAINT_DIE); | ||
329 | spin_unlock_irq(&die_lock); | 330 | spin_unlock_irq(&die_lock); |
330 | 331 | ||
331 | if (in_interrupt()) | 332 | if (in_interrupt()) |
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 9b9992cd562a..bc9bae2a73f4 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S | |||
@@ -119,10 +119,7 @@ SECTIONS | |||
119 | .init.ramfs : { *(.init.ramfs) } | 119 | .init.ramfs : { *(.init.ramfs) } |
120 | __initramfs_end = .; | 120 | __initramfs_end = .; |
121 | #endif | 121 | #endif |
122 | . = ALIGN(_PAGE_SIZE); | 122 | PERCPU(_PAGE_SIZE) |
123 | __per_cpu_start = .; | ||
124 | .data.percpu : { *(.data.percpu) } | ||
125 | __per_cpu_end = .; | ||
126 | . = ALIGN(_PAGE_SIZE); | 123 | . = ALIGN(_PAGE_SIZE); |
127 | __init_end = .; | 124 | __init_end = .; |
128 | /* freed after init ends here */ | 125 | /* freed after init ends here */ |
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c index 1cc6ebbedfdd..c68358a476dd 100644 --- a/arch/mips/mips-boards/atlas/atlas_setup.c +++ b/arch/mips/mips-boards/atlas/atlas_setup.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/tty.h> | 22 | #include <linux/tty.h> |
23 | #include <linux/serial.h> | 23 | #include <linux/serial.h> |
24 | #include <linux/serial_core.h> | 24 | #include <linux/serial_core.h> |
25 | #include <linux/serial_8250.h> | ||
25 | 26 | ||
26 | #include <asm/cpu.h> | 27 | #include <asm/cpu.h> |
27 | #include <asm/bootinfo.h> | 28 | #include <asm/bootinfo.h> |
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c index bb801409d39b..5f70eaf01fab 100644 --- a/arch/mips/mips-boards/sead/sead_setup.c +++ b/arch/mips/mips-boards/sead/sead_setup.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/tty.h> | 23 | #include <linux/tty.h> |
24 | #include <linux/serial.h> | 24 | #include <linux/serial.h> |
25 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
26 | #include <linux/serial_8250.h> | ||
26 | 27 | ||
27 | #include <asm/cpu.h> | 28 | #include <asm/cpu.h> |
28 | #include <asm/bootinfo.h> | 29 | #include <asm/bootinfo.h> |
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c index 60e66906be65..17819b594105 100644 --- a/arch/mips/mipssim/sim_setup.c +++ b/arch/mips/mipssim/sim_setup.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/tty.h> | 26 | #include <linux/tty.h> |
27 | #include <linux/serial.h> | 27 | #include <linux/serial.h> |
28 | #include <linux/serial_core.h> | 28 | #include <linux/serial_core.h> |
29 | #include <linux/serial_8250.h> | ||
29 | 30 | ||
30 | #include <asm/cpu.h> | 31 | #include <asm/cpu.h> |
31 | #include <asm/bootinfo.h> | 32 | #include <asm/bootinfo.h> |
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 7ebea331edb8..521771b373de 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c | |||
@@ -39,6 +39,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, | |||
39 | struct mm_struct *mm = tsk->mm; | 39 | struct mm_struct *mm = tsk->mm; |
40 | const int field = sizeof(unsigned long) * 2; | 40 | const int field = sizeof(unsigned long) * 2; |
41 | siginfo_t info; | 41 | siginfo_t info; |
42 | int fault; | ||
42 | 43 | ||
43 | #if 0 | 44 | #if 0 |
44 | printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(), | 45 | printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(), |
@@ -102,20 +103,18 @@ survive: | |||
102 | * make sure we exit gracefully rather than endlessly redo | 103 | * make sure we exit gracefully rather than endlessly redo |
103 | * the fault. | 104 | * the fault. |
104 | */ | 105 | */ |
105 | switch (handle_mm_fault(mm, vma, address, write)) { | 106 | fault = handle_mm_fault(mm, vma, address, write); |
106 | case VM_FAULT_MINOR: | 107 | if (unlikely(fault & VM_FAULT_ERROR)) { |
107 | tsk->min_flt++; | 108 | if (fault & VM_FAULT_OOM) |
108 | break; | 109 | goto out_of_memory; |
109 | case VM_FAULT_MAJOR: | 110 | else if (fault & VM_FAULT_SIGBUS) |
110 | tsk->maj_flt++; | 111 | goto do_sigbus; |
111 | break; | ||
112 | case VM_FAULT_SIGBUS: | ||
113 | goto do_sigbus; | ||
114 | case VM_FAULT_OOM: | ||
115 | goto out_of_memory; | ||
116 | default: | ||
117 | BUG(); | 112 | BUG(); |
118 | } | 113 | } |
114 | if (fault & VM_FAULT_MAJOR) | ||
115 | tsk->maj_flt++; | ||
116 | else | ||
117 | tsk->min_flt++; | ||
119 | 118 | ||
120 | up_read(&mm->mmap_sem); | 119 | up_read(&mm->mmap_sem); |
121 | return; | 120 | return; |
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c index c41b53faa8f6..e25bac537d77 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
33 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
34 | #include <asm/serial.h> | 34 | #include <asm/serial.h> |
35 | #include <linux/serial_8250.h> | ||
35 | 36 | ||
36 | #include <msp_prom.h> | 37 | #include <msp_prom.h> |
37 | #include <msp_int.h> | 38 | #include <msp_int.h> |
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index 6a6e15e40009..f7f93ae24c34 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/tty.h> | 39 | #include <linux/tty.h> |
40 | #include <linux/serial.h> | 40 | #include <linux/serial.h> |
41 | #include <linux/serial_core.h> | 41 | #include <linux/serial_core.h> |
42 | #include <linux/serial_8250.h> | ||
42 | 43 | ||
43 | #include <asm/time.h> | 44 | #include <asm/time.h> |
44 | #include <asm/bootinfo.h> | 45 | #include <asm/bootinfo.h> |
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c index bdaac34ae708..89f29233cae1 100644 --- a/arch/mips/sibyte/bcm1480/setup.c +++ b/arch/mips/sibyte/bcm1480/setup.c | |||
@@ -31,6 +31,7 @@ | |||
31 | unsigned int sb1_pass; | 31 | unsigned int sb1_pass; |
32 | unsigned int soc_pass; | 32 | unsigned int soc_pass; |
33 | unsigned int soc_type; | 33 | unsigned int soc_type; |
34 | EXPORT_SYMBOL(soc_type); | ||
34 | unsigned int periph_rev; | 35 | unsigned int periph_rev; |
35 | unsigned int zbbus_mhz; | 36 | unsigned int zbbus_mhz; |
36 | 37 | ||
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c index f4a6169aa0a4..2d5c6d8b41f2 100644 --- a/arch/mips/sibyte/sb1250/setup.c +++ b/arch/mips/sibyte/sb1250/setup.c | |||
@@ -31,6 +31,7 @@ | |||
31 | unsigned int sb1_pass; | 31 | unsigned int sb1_pass; |
32 | unsigned int soc_pass; | 32 | unsigned int soc_pass; |
33 | unsigned int soc_type; | 33 | unsigned int soc_type; |
34 | EXPORT_SYMBOL(soc_type); | ||
34 | unsigned int periph_rev; | 35 | unsigned int periph_rev; |
35 | unsigned int zbbus_mhz; | 36 | unsigned int zbbus_mhz; |
36 | EXPORT_SYMBOL(zbbus_mhz); | 37 | EXPORT_SYMBOL(zbbus_mhz); |
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 8a0db376e91e..26ec774c5027 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c | |||
@@ -87,10 +87,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
87 | switch (request) { | 87 | switch (request) { |
88 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 88 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
89 | case PTRACE_PEEKDATA: { | 89 | case PTRACE_PEEKDATA: { |
90 | int copied; | ||
91 | |||
92 | #ifdef CONFIG_64BIT | 90 | #ifdef CONFIG_64BIT |
93 | if (__is_compat_task(child)) { | 91 | if (__is_compat_task(child)) { |
92 | int copied; | ||
94 | unsigned int tmp; | 93 | unsigned int tmp; |
95 | 94 | ||
96 | addr &= 0xffffffffL; | 95 | addr &= 0xffffffffL; |
@@ -105,15 +104,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
105 | } | 104 | } |
106 | else | 105 | else |
107 | #endif | 106 | #endif |
108 | { | 107 | ret = generic_ptrace_peekdata(child, addr, data); |
109 | unsigned long tmp; | ||
110 | |||
111 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
112 | ret = -EIO; | ||
113 | if (copied != sizeof(tmp)) | ||
114 | goto out_tsk; | ||
115 | ret = put_user(tmp,(unsigned long *) data); | ||
116 | } | ||
117 | goto out_tsk; | 108 | goto out_tsk; |
118 | } | 109 | } |
119 | 110 | ||
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index f9bca2d74b38..bbf029a184ac 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c | |||
@@ -264,6 +264,7 @@ KERN_CRIT " || ||\n"); | |||
264 | 264 | ||
265 | show_regs(regs); | 265 | show_regs(regs); |
266 | dump_stack(); | 266 | dump_stack(); |
267 | add_taint(TAINT_DIE); | ||
267 | 268 | ||
268 | if (in_interrupt()) | 269 | if (in_interrupt()) |
269 | panic("Fatal exception in interrupt"); | 270 | panic("Fatal exception in interrupt"); |
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index 322167737de7..cf780cb3b916 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c | |||
@@ -242,7 +242,7 @@ static void unwind_frame_regs(struct unwind_frame_info *info) | |||
242 | #ifdef CONFIG_KALLSYMS | 242 | #ifdef CONFIG_KALLSYMS |
243 | /* Handle some frequent special cases.... */ | 243 | /* Handle some frequent special cases.... */ |
244 | { | 244 | { |
245 | char symname[KSYM_NAME_LEN+1]; | 245 | char symname[KSYM_NAME_LEN]; |
246 | char *modname; | 246 | char *modname; |
247 | 247 | ||
248 | kallsyms_lookup(info->ip, NULL, NULL, &modname, | 248 | kallsyms_lookup(info->ip, NULL, NULL, &modname, |
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 4d96ba4b9849..d4e6a93c8d9a 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S | |||
@@ -181,10 +181,9 @@ SECTIONS | |||
181 | .init.ramfs : { *(.init.ramfs) } | 181 | .init.ramfs : { *(.init.ramfs) } |
182 | __initramfs_end = .; | 182 | __initramfs_end = .; |
183 | #endif | 183 | #endif |
184 | . = ALIGN(ASM_PAGE_SIZE); | 184 | |
185 | __per_cpu_start = .; | 185 | PERCPU(ASM_PAGE_SIZE) |
186 | .data.percpu : { *(.data.percpu) } | 186 | |
187 | __per_cpu_end = .; | ||
188 | . = ALIGN(ASM_PAGE_SIZE); | 187 | . = ALIGN(ASM_PAGE_SIZE); |
189 | __init_end = .; | 188 | __init_end = .; |
190 | /* freed after init ends here */ | 189 | /* freed after init ends here */ |
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index f6f67554c623..7899ab87785a 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c | |||
@@ -147,6 +147,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, | |||
147 | struct mm_struct *mm = tsk->mm; | 147 | struct mm_struct *mm = tsk->mm; |
148 | const struct exception_table_entry *fix; | 148 | const struct exception_table_entry *fix; |
149 | unsigned long acc_type; | 149 | unsigned long acc_type; |
150 | int fault; | ||
150 | 151 | ||
151 | if (in_atomic() || !mm) | 152 | if (in_atomic() || !mm) |
152 | goto no_context; | 153 | goto no_context; |
@@ -173,23 +174,23 @@ good_area: | |||
173 | * fault. | 174 | * fault. |
174 | */ | 175 | */ |
175 | 176 | ||
176 | switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) { | 177 | fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0); |
177 | case VM_FAULT_MINOR: | 178 | if (unlikely(fault & VM_FAULT_ERROR)) { |
178 | ++current->min_flt; | ||
179 | break; | ||
180 | case VM_FAULT_MAJOR: | ||
181 | ++current->maj_flt; | ||
182 | break; | ||
183 | case VM_FAULT_SIGBUS: | ||
184 | /* | 179 | /* |
185 | * We hit a shared mapping outside of the file, or some | 180 | * We hit a shared mapping outside of the file, or some |
186 | * other thing happened to us that made us unable to | 181 | * other thing happened to us that made us unable to |
187 | * handle the page fault gracefully. | 182 | * handle the page fault gracefully. |
188 | */ | 183 | */ |
189 | goto bad_area; | 184 | if (fault & VM_FAULT_OOM) |
190 | default: | 185 | goto out_of_memory; |
191 | goto out_of_memory; | 186 | else if (fault & VM_FAULT_SIGBUS) |
187 | goto bad_area; | ||
188 | BUG(); | ||
192 | } | 189 | } |
190 | if (fault & VM_FAULT_MAJOR) | ||
191 | current->maj_flt++; | ||
192 | else | ||
193 | current->min_flt++; | ||
193 | up_read(&mm->mmap_sem); | 194 | up_read(&mm->mmap_sem); |
194 | return; | 195 | return; |
195 | 196 | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6b8b83ebca75..d860b640a140 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -4,17 +4,7 @@ | |||
4 | 4 | ||
5 | mainmenu "Linux/PowerPC Kernel Configuration" | 5 | mainmenu "Linux/PowerPC Kernel Configuration" |
6 | 6 | ||
7 | config PPC64 | 7 | source "arch/powerpc/platforms/Kconfig.cputype" |
8 | bool "64-bit kernel" | ||
9 | default n | ||
10 | help | ||
11 | This option selects whether a 32-bit or a 64-bit kernel | ||
12 | will be built. | ||
13 | |||
14 | config PPC_PM_NEEDS_RTC_LIB | ||
15 | bool | ||
16 | select RTC_LIB | ||
17 | default y if PM | ||
18 | 8 | ||
19 | config PPC32 | 9 | config PPC32 |
20 | bool | 10 | bool |
@@ -135,123 +125,6 @@ config PPC64_SWSUSP | |||
135 | depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL)) | 125 | depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL)) |
136 | default y | 126 | default y |
137 | 127 | ||
138 | menu "Processor support" | ||
139 | choice | ||
140 | prompt "Processor Type" | ||
141 | depends on PPC32 | ||
142 | default 6xx | ||
143 | |||
144 | config CLASSIC32 | ||
145 | bool "52xx/6xx/7xx/74xx" | ||
146 | select PPC_FPU | ||
147 | select 6xx | ||
148 | help | ||
149 | There are four families of PowerPC chips supported. The more common | ||
150 | types (601, 603, 604, 740, 750, 7400), the Motorola embedded | ||
151 | versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC | ||
152 | embedded versions (403 and 405) and the high end 64 bit Power | ||
153 | processors (POWER 3, POWER4, and IBM PPC970 also known as G5). | ||
154 | |||
155 | This option is the catch-all for 6xx types, including some of the | ||
156 | embedded versions. Unless there is see an option for the specific | ||
157 | chip family you are using, you want this option. | ||
158 | |||
159 | You do not want this if you are building a kernel for a 64 bit | ||
160 | IBM RS/6000 or an Apple G5, choose 6xx. | ||
161 | |||
162 | If unsure, select this option | ||
163 | |||
164 | Note that the kernel runs in 32-bit mode even on 64-bit chips. | ||
165 | |||
166 | config PPC_82xx | ||
167 | bool "Freescale 82xx" | ||
168 | select 6xx | ||
169 | select PPC_FPU | ||
170 | |||
171 | config PPC_83xx | ||
172 | bool "Freescale 83xx" | ||
173 | select 6xx | ||
174 | select FSL_SOC | ||
175 | select 83xx | ||
176 | select PPC_FPU | ||
177 | select WANT_DEVICE_TREE | ||
178 | |||
179 | config PPC_85xx | ||
180 | bool "Freescale 85xx" | ||
181 | select E500 | ||
182 | select FSL_SOC | ||
183 | select 85xx | ||
184 | select WANT_DEVICE_TREE | ||
185 | |||
186 | config PPC_86xx | ||
187 | bool "Freescale 86xx" | ||
188 | select 6xx | ||
189 | select FSL_SOC | ||
190 | select FSL_PCIE | ||
191 | select PPC_FPU | ||
192 | select ALTIVEC | ||
193 | help | ||
194 | The Freescale E600 SoCs have 74xx cores. | ||
195 | |||
196 | config PPC_8xx | ||
197 | bool "Freescale 8xx" | ||
198 | select FSL_SOC | ||
199 | select 8xx | ||
200 | |||
201 | config 40x | ||
202 | bool "AMCC 40x" | ||
203 | select PPC_DCR_NATIVE | ||
204 | |||
205 | config 44x | ||
206 | bool "AMCC 44x" | ||
207 | select PPC_DCR_NATIVE | ||
208 | select WANT_DEVICE_TREE | ||
209 | |||
210 | config E200 | ||
211 | bool "Freescale e200" | ||
212 | |||
213 | endchoice | ||
214 | |||
215 | config POWER4_ONLY | ||
216 | bool "Optimize for POWER4" | ||
217 | depends on PPC64 | ||
218 | default n | ||
219 | ---help--- | ||
220 | Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. | ||
221 | The resulting binary will not work on POWER3 or RS64 processors | ||
222 | when compiled with binutils 2.15 or later. | ||
223 | |||
224 | config POWER3 | ||
225 | bool | ||
226 | depends on PPC64 | ||
227 | default y if !POWER4_ONLY | ||
228 | |||
229 | config POWER4 | ||
230 | depends on PPC64 | ||
231 | def_bool y | ||
232 | |||
233 | config 6xx | ||
234 | bool | ||
235 | |||
236 | # this is temp to handle compat with arch=ppc | ||
237 | config 8xx | ||
238 | bool | ||
239 | |||
240 | # this is temp to handle compat with arch=ppc | ||
241 | config 83xx | ||
242 | bool | ||
243 | |||
244 | # this is temp to handle compat with arch=ppc | ||
245 | config 85xx | ||
246 | bool | ||
247 | |||
248 | config E500 | ||
249 | bool | ||
250 | |||
251 | config PPC_FPU | ||
252 | bool | ||
253 | default y if PPC64 | ||
254 | |||
255 | config PPC_DCR_NATIVE | 128 | config PPC_DCR_NATIVE |
256 | bool | 129 | bool |
257 | default n | 130 | default n |
@@ -270,134 +143,6 @@ config PPC_OF_PLATFORM_PCI | |||
270 | depends on PPC64 # not supported on 32 bits yet | 143 | depends on PPC64 # not supported on 32 bits yet |
271 | default n | 144 | default n |
272 | 145 | ||
273 | config 4xx | ||
274 | bool | ||
275 | depends on 40x || 44x | ||
276 | default y | ||
277 | |||
278 | config BOOKE | ||
279 | bool | ||
280 | depends on E200 || E500 || 44x | ||
281 | default y | ||
282 | |||
283 | config FSL_BOOKE | ||
284 | bool | ||
285 | depends on E200 || E500 | ||
286 | default y | ||
287 | |||
288 | config PTE_64BIT | ||
289 | bool | ||
290 | depends on 44x || E500 | ||
291 | default y if 44x | ||
292 | default y if E500 && PHYS_64BIT | ||
293 | |||
294 | config PHYS_64BIT | ||
295 | bool 'Large physical address support' if E500 | ||
296 | depends on 44x || E500 | ||
297 | select RESOURCES_64BIT | ||
298 | default y if 44x | ||
299 | ---help--- | ||
300 | This option enables kernel support for larger than 32-bit physical | ||
301 | addresses. This features is not be available on all e500 cores. | ||
302 | |||
303 | If in doubt, say N here. | ||
304 | |||
305 | config ALTIVEC | ||
306 | bool "AltiVec Support" | ||
307 | depends on CLASSIC32 || POWER4 | ||
308 | ---help--- | ||
309 | This option enables kernel support for the Altivec extensions to the | ||
310 | PowerPC processor. The kernel currently supports saving and restoring | ||
311 | altivec registers, and turning on the 'altivec enable' bit so user | ||
312 | processes can execute altivec instructions. | ||
313 | |||
314 | This option is only usefully if you have a processor that supports | ||
315 | altivec (G4, otherwise known as 74xx series), but does not have | ||
316 | any affect on a non-altivec cpu (it does, however add code to the | ||
317 | kernel). | ||
318 | |||
319 | If in doubt, say Y here. | ||
320 | |||
321 | config SPE | ||
322 | bool "SPE Support" | ||
323 | depends on E200 || E500 | ||
324 | default y | ||
325 | ---help--- | ||
326 | This option enables kernel support for the Signal Processing | ||
327 | Extensions (SPE) to the PowerPC processor. The kernel currently | ||
328 | supports saving and restoring SPE registers, and turning on the | ||
329 | 'spe enable' bit so user processes can execute SPE instructions. | ||
330 | |||
331 | This option is only useful if you have a processor that supports | ||
332 | SPE (e500, otherwise known as 85xx series), but does not have any | ||
333 | effect on a non-spe cpu (it does, however add code to the kernel). | ||
334 | |||
335 | If in doubt, say Y here. | ||
336 | |||
337 | config PPC_STD_MMU | ||
338 | bool | ||
339 | depends on 6xx || POWER3 || POWER4 || PPC64 | ||
340 | default y | ||
341 | |||
342 | config PPC_STD_MMU_32 | ||
343 | def_bool y | ||
344 | depends on PPC_STD_MMU && PPC32 | ||
345 | |||
346 | config PPC_MM_SLICES | ||
347 | bool | ||
348 | default y if HUGETLB_PAGE | ||
349 | default n | ||
350 | |||
351 | config VIRT_CPU_ACCOUNTING | ||
352 | bool "Deterministic task and CPU time accounting" | ||
353 | depends on PPC64 | ||
354 | default y | ||
355 | help | ||
356 | Select this option to enable more accurate task and CPU time | ||
357 | accounting. This is done by reading a CPU counter on each | ||
358 | kernel entry and exit and on transitions within the kernel | ||
359 | between system, softirq and hardirq state, so there is a | ||
360 | small performance impact. This also enables accounting of | ||
361 | stolen time on logically-partitioned systems running on | ||
362 | IBM POWER5-based machines. | ||
363 | |||
364 | If in doubt, say Y here. | ||
365 | |||
366 | config SMP | ||
367 | depends on PPC_STD_MMU | ||
368 | bool "Symmetric multi-processing support" | ||
369 | ---help--- | ||
370 | This enables support for systems with more than one CPU. If you have | ||
371 | a system with only one CPU, say N. If you have a system with more | ||
372 | than one CPU, say Y. Note that the kernel does not currently | ||
373 | support SMP machines with 603/603e/603ev or PPC750 ("G3") processors | ||
374 | since they have inadequate hardware support for multiprocessor | ||
375 | operation. | ||
376 | |||
377 | If you say N here, the kernel will run on single and multiprocessor | ||
378 | machines, but will use only one CPU of a multiprocessor machine. If | ||
379 | you say Y here, the kernel will run on single-processor machines. | ||
380 | On a single-processor machine, the kernel will run faster if you say | ||
381 | N here. | ||
382 | |||
383 | If you don't know what to do here, say N. | ||
384 | |||
385 | config NR_CPUS | ||
386 | int "Maximum number of CPUs (2-128)" | ||
387 | range 2 128 | ||
388 | depends on SMP | ||
389 | default "32" if PPC64 | ||
390 | default "4" | ||
391 | |||
392 | config NOT_COHERENT_CACHE | ||
393 | bool | ||
394 | depends on 4xx || 8xx || E200 | ||
395 | default y | ||
396 | |||
397 | config CONFIG_CHECK_CACHE_COHERENCY | ||
398 | bool | ||
399 | endmenu | ||
400 | |||
401 | source "init/Kconfig" | 146 | source "init/Kconfig" |
402 | 147 | ||
403 | source "arch/powerpc/platforms/Kconfig" | 148 | source "arch/powerpc/platforms/Kconfig" |
@@ -677,10 +422,6 @@ config SBUS | |||
677 | config FSL_SOC | 422 | config FSL_SOC |
678 | bool | 423 | bool |
679 | 424 | ||
680 | config FSL_PCIE | ||
681 | bool | ||
682 | depends on PPC_86xx | ||
683 | |||
684 | # Yes MCA RS/6000s exist but Linux-PPC does not currently support any | 425 | # Yes MCA RS/6000s exist but Linux-PPC does not currently support any |
685 | config MCA | 426 | config MCA |
686 | bool | 427 | bool |
@@ -688,10 +429,10 @@ config MCA | |||
688 | config PCI | 429 | config PCI |
689 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ | 430 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ |
690 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ | 431 | || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ |
691 | || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY | 432 | || PPC_PS3 |
692 | default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ | 433 | default y if !40x && !CPM2 && !8xx && !PPC_83xx \ |
693 | && !PPC_85xx && !PPC_86xx | 434 | && !PPC_85xx && !PPC_86xx |
694 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS | 435 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx |
695 | default PCI_QSPAN if !4xx && !CPM2 && 8xx | 436 | default PCI_QSPAN if !4xx && !CPM2 && 8xx |
696 | select ARCH_SUPPORTS_MSI | 437 | select ARCH_SUPPORTS_MSI |
697 | help | 438 | help |
@@ -899,8 +640,8 @@ menu "Instrumentation Support" | |||
899 | source "arch/powerpc/oprofile/Kconfig" | 640 | source "arch/powerpc/oprofile/Kconfig" |
900 | 641 | ||
901 | config KPROBES | 642 | config KPROBES |
902 | bool "Kprobes (EXPERIMENTAL)" | 643 | bool "Kprobes" |
903 | depends on !BOOKE && !4xx && KALLSYMS && EXPERIMENTAL && MODULES | 644 | depends on !BOOKE && !4xx && KALLSYMS && MODULES |
904 | help | 645 | help |
905 | Kprobes allows you to trap at almost any kernel address and | 646 | Kprobes allows you to trap at almost any kernel address and |
906 | execute a callback function. register_kprobe() establishes | 647 | execute a callback function. register_kprobe() establishes |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 85be60504eb4..6c1e36c33faa 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) | |||
148 | 148 | ||
149 | CPPFLAGS_vmlinux.lds := -Upowerpc | 149 | CPPFLAGS_vmlinux.lds := -Upowerpc |
150 | 150 | ||
151 | BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage | 151 | BOOT_TARGETS = zImage zImage.initrd uImage |
152 | 152 | ||
153 | PHONY += $(BOOT_TARGETS) | 153 | PHONY += $(BOOT_TARGETS) |
154 | 154 | ||
diff --git a/arch/powerpc/boot/44x.c b/arch/powerpc/boot/44x.c index d51377d9024f..9f64e840bef6 100644 --- a/arch/powerpc/boot/44x.c +++ b/arch/powerpc/boot/44x.c | |||
@@ -38,3 +38,48 @@ void ibm44x_fixup_memsize(void) | |||
38 | 38 | ||
39 | dt_fixup_memory(0, memsize); | 39 | dt_fixup_memory(0, memsize); |
40 | } | 40 | } |
41 | |||
42 | #define SPRN_DBCR0 0x134 | ||
43 | #define DBCR0_RST_SYSTEM 0x30000000 | ||
44 | |||
45 | void ibm44x_dbcr_reset(void) | ||
46 | { | ||
47 | unsigned long tmp; | ||
48 | |||
49 | asm volatile ( | ||
50 | "mfspr %0,%1\n" | ||
51 | "oris %0,%0,%2@h\n" | ||
52 | "mtspr %1,%0" | ||
53 | : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) | ||
54 | ); | ||
55 | |||
56 | } | ||
57 | |||
58 | /* Read 4xx EBC bus bridge registers to get mappings of the peripheral | ||
59 | * banks into the OPB address space */ | ||
60 | void ibm4xx_fixup_ebc_ranges(const char *ebc) | ||
61 | { | ||
62 | void *devp; | ||
63 | u32 bxcr; | ||
64 | u32 ranges[EBC_NUM_BANKS*4]; | ||
65 | u32 *p = ranges; | ||
66 | int i; | ||
67 | |||
68 | for (i = 0; i < EBC_NUM_BANKS; i++) { | ||
69 | mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i)); | ||
70 | bxcr = mfdcr(DCRN_EBC0_CFGDATA); | ||
71 | |||
72 | if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) { | ||
73 | *p++ = i; | ||
74 | *p++ = 0; | ||
75 | *p++ = bxcr & EBC_BXCR_BAS; | ||
76 | *p++ = EBC_BXCR_BANK_SIZE(bxcr); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | devp = finddevice(ebc); | ||
81 | if (! devp) | ||
82 | fatal("Couldn't locate EBC node %s\n\r", ebc); | ||
83 | |||
84 | setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32)); | ||
85 | } | ||
diff --git a/arch/powerpc/boot/44x.h b/arch/powerpc/boot/44x.h index 7b129ad043e1..577982c9a3cd 100644 --- a/arch/powerpc/boot/44x.h +++ b/arch/powerpc/boot/44x.h | |||
@@ -11,6 +11,9 @@ | |||
11 | #define _PPC_BOOT_44X_H_ | 11 | #define _PPC_BOOT_44X_H_ |
12 | 12 | ||
13 | void ibm44x_fixup_memsize(void); | 13 | void ibm44x_fixup_memsize(void); |
14 | void ibm4xx_fixup_ebc_ranges(const char *ebc); | ||
15 | |||
16 | void ibm44x_dbcr_reset(void); | ||
14 | void ebony_init(void *mac0, void *mac1); | 17 | void ebony_init(void *mac0, void *mac1); |
15 | 18 | ||
16 | #endif /* _PPC_BOOT_44X_H_ */ | 19 | #endif /* _PPC_BOOT_44X_H_ */ |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index ff2701949ee1..61a6f34ca5ed 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -43,10 +43,11 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ | |||
43 | 43 | ||
44 | src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ | 44 | src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ |
45 | ns16550.c serial.c simple_alloc.c div64.S util.S \ | 45 | ns16550.c serial.c simple_alloc.c div64.S util.S \ |
46 | gunzip_util.c elf_util.c $(zlib) devtree.c \ | 46 | gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ |
47 | 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c | 47 | 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c |
48 | src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ | 48 | src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ |
49 | cuboot-ebony.c treeboot-ebony.c prpmc2800.c | 49 | cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ |
50 | ps3-head.S ps3-hvcall.S ps3.c | ||
50 | src-boot := $(src-wlib) $(src-plat) empty.c | 51 | src-boot := $(src-wlib) $(src-plat) empty.c |
51 | 52 | ||
52 | src-boot := $(addprefix $(obj)/, $(src-boot)) | 53 | src-boot := $(addprefix $(obj)/, $(src-boot)) |
@@ -75,11 +76,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/% | |||
75 | $(obj)/empty.c: | 76 | $(obj)/empty.c: |
76 | @touch $@ | 77 | @touch $@ |
77 | 78 | ||
78 | $(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S | 79 | $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S |
79 | @cp $< $@ | 80 | @cp $< $@ |
80 | 81 | ||
81 | clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ | 82 | clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ |
82 | empty.c zImage.coff.lds zImage.lds | 83 | empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds |
83 | 84 | ||
84 | quiet_cmd_bootcc = BOOTCC $@ | 85 | quiet_cmd_bootcc = BOOTCC $@ |
85 | cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< | 86 | cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< |
@@ -102,7 +103,7 @@ hostprogs-y := addnote addRamDisk hack-coff mktree | |||
102 | 103 | ||
103 | targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) | 104 | targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) |
104 | extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ | 105 | extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ |
105 | $(obj)/zImage.lds $(obj)/zImage.coff.lds | 106 | $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds |
106 | 107 | ||
107 | wrapper :=$(srctree)/$(src)/wrapper | 108 | wrapper :=$(srctree)/$(src)/wrapper |
108 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ | 109 | wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ |
@@ -132,7 +133,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries | |||
132 | image-$(CONFIG_PPC_CHRP) += zImage.chrp | 133 | image-$(CONFIG_PPC_CHRP) += zImage.chrp |
133 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp | 134 | image-$(CONFIG_PPC_EFIKA) += zImage.chrp |
134 | image-$(CONFIG_PPC_PMAC) += zImage.pmac | 135 | image-$(CONFIG_PPC_PMAC) += zImage.pmac |
135 | image-$(CONFIG_PPC_HOLLY) += zImage.holly-elf | 136 | image-$(CONFIG_PPC_HOLLY) += zImage.holly |
136 | image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 | 137 | image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 |
137 | image-$(CONFIG_PPC_ISERIES) += zImage.iseries | 138 | image-$(CONFIG_PPC_ISERIES) += zImage.iseries |
138 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage | 139 | image-$(CONFIG_DEFAULT_UIMAGE) += uImage |
@@ -157,55 +158,43 @@ targets += $(image-y) $(initrd-y) | |||
157 | 158 | ||
158 | $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz | 159 | $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz |
159 | 160 | ||
160 | dts- := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-)) | 161 | # If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an |
161 | dts-y := $(patsubst zImage%, zImage.dts%, $(image-y)) | 162 | # empty string, define 'dts' to be path to the dts |
162 | dts-y := $(filter-out $(image-y), $(dts-y)) | 163 | # CONFIG_DEVICE_TREE will have "" around it, make sure to strip them |
163 | targets += $(image-y) $(dts-y) | 164 | ifeq ($(CONFIG_WANT_DEVICE_TREE),y) |
164 | 165 | ifneq ($(CONFIG_DEVICE_TREE),"") | |
165 | dts_initrd- := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-)) | 166 | dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ |
166 | dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y)) | 167 | ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) |
167 | dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y)) | 168 | endif |
168 | targets += $(image-y) $(dts_initrd-y) | 169 | endif |
169 | |||
170 | $(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz | ||
171 | 170 | ||
172 | # Don't put the ramdisk on the pattern rule; when its missing make will try | 171 | # Don't put the ramdisk on the pattern rule; when its missing make will try |
173 | # the pattern rule with less dependencies that also matches (even with the | 172 | # the pattern rule with less dependencies that also matches (even with the |
174 | # hard dependency listed). | 173 | # hard dependency listed). |
175 | $(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz | 174 | $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts) |
176 | $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) | 175 | $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) |
177 | 176 | ||
178 | $(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts) | 177 | $(obj)/zImage.%: vmlinux $(wrapperbits) $(dts) |
179 | $(call if_changed,wrap,$*,$(dts)) | 178 | $(call if_changed,wrap,$*,$(dts)) |
180 | 179 | ||
181 | $(obj)/zImage.initrd.%: vmlinux $(wrapperbits) | 180 | # This cannot be in the root of $(src) as the zImage rule always adds a $(obj) |
182 | $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) | 181 | # prefix |
183 | 182 | $(obj)/vmlinux.strip: vmlinux | |
184 | $(obj)/zImage.%: vmlinux $(wrapperbits) | ||
185 | $(call if_changed,wrap,$*) | ||
186 | |||
187 | $(obj)/zImage.iseries: vmlinux | ||
188 | $(STRIP) -s -R .comment $< -o $@ | 183 | $(STRIP) -s -R .comment $< -o $@ |
189 | 184 | ||
190 | $(obj)/zImage.ps3: vmlinux | 185 | $(obj)/zImage.iseries: vmlinux |
191 | $(STRIP) -s -R .comment $< -o $@ | 186 | $(STRIP) -s -R .comment $< -o $@ |
192 | 187 | ||
193 | $(obj)/zImage.initrd.ps3: vmlinux | 188 | $(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts |
194 | @echo " WARNING zImage.initrd.ps3 not supported (yet)" | 189 | $(STRIP) -s -R .comment $< -o vmlinux.strip |
195 | 190 | $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,) | |
196 | $(obj)/zImage.holly-elf: vmlinux $(wrapperbits) | ||
197 | $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,) | ||
198 | 191 | ||
199 | $(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz | 192 | $(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz |
200 | $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz) | 193 | $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz) |
201 | 194 | ||
202 | $(obj)/uImage: vmlinux $(wrapperbits) | 195 | $(obj)/uImage: vmlinux $(wrapperbits) |
203 | $(call if_changed,wrap,uboot) | 196 | $(call if_changed,wrap,uboot) |
204 | 197 | ||
205 | # CONFIG_DEVICE_TREE will have "" around it, make sure to strip them | ||
206 | dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ | ||
207 | ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) | ||
208 | |||
209 | $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits) | 198 | $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits) |
210 | $(call if_changed,wrap,cuboot-$*,$(dts)) | 199 | $(call if_changed,wrap,cuboot-$*,$(dts)) |
211 | 200 | ||
@@ -215,22 +204,22 @@ $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits) | |||
215 | $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits) | 204 | $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits) |
216 | $(call if_changed,wrap,treeboot-$*,$(dts)) | 205 | $(call if_changed,wrap,treeboot-$*,$(dts)) |
217 | 206 | ||
207 | # If there isn't a platform selected then just strip the vmlinux. | ||
208 | ifeq (,$(image-y)) | ||
209 | image-y := vmlinux.strip | ||
210 | endif | ||
211 | |||
218 | $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) | 212 | $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) |
219 | @rm -f $@; ln $< $@ | 213 | @rm -f $@; ln $< $@ |
220 | $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) | 214 | $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) |
221 | @rm -f $@; ln $< $@ | 215 | @rm -f $@; ln $< $@ |
222 | $(obj)/zImage.dts: $(addprefix $(obj)/, $(dts-y)) | ||
223 | @rm -f $@; ln $< $@ | ||
224 | $(obj)/zImage.dts_initrd: $(addprefix $(obj)/, $(dts_initrd-y)) | ||
225 | @rm -f $@; ln $< $@ | ||
226 | |||
227 | 216 | ||
228 | install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) | 217 | install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) |
229 | sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< | 218 | sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< |
230 | 219 | ||
231 | # anything not in $(targets) | 220 | # anything not in $(targets) |
232 | clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \ | 221 | clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \ |
233 | treeImage.* zImage.dts zImage.dts_initrd | 222 | otheros.bld |
234 | 223 | ||
235 | # clean up files cached by wrapper | 224 | # clean up files cached by wrapper |
236 | clean-kernel := vmlinux.strip vmlinux.bin | 225 | clean-kernel := vmlinux.strip vmlinux.bin |
diff --git a/arch/powerpc/boot/cuboot-83xx.c b/arch/powerpc/boot/cuboot-83xx.c index 9af554eea54b..296025d8b295 100644 --- a/arch/powerpc/boot/cuboot-83xx.c +++ b/arch/powerpc/boot/cuboot-83xx.c | |||
@@ -12,12 +12,12 @@ | |||
12 | 12 | ||
13 | #include "ops.h" | 13 | #include "ops.h" |
14 | #include "stdio.h" | 14 | #include "stdio.h" |
15 | #include "cuboot.h" | ||
15 | 16 | ||
16 | #define TARGET_83xx | 17 | #define TARGET_83xx |
17 | #include "ppcboot.h" | 18 | #include "ppcboot.h" |
18 | 19 | ||
19 | static bd_t bd; | 20 | static bd_t bd; |
20 | extern char _end[]; | ||
21 | extern char _dtb_start[], _dtb_end[]; | 21 | extern char _dtb_start[], _dtb_end[]; |
22 | 22 | ||
23 | static void platform_fixups(void) | 23 | static void platform_fixups(void) |
@@ -52,16 +52,7 @@ static void platform_fixups(void) | |||
52 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 52 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
53 | unsigned long r6, unsigned long r7) | 53 | unsigned long r6, unsigned long r7) |
54 | { | 54 | { |
55 | unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | 55 | CUBOOT_INIT(); |
56 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
57 | |||
58 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||
59 | loader_info.initrd_addr = r4; | ||
60 | loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||
61 | loader_info.cmdline = (char *)r6; | ||
62 | loader_info.cmdline_len = r7 - r6; | ||
63 | |||
64 | simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||
65 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | 56 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); |
66 | serial_console_init(); | 57 | serial_console_init(); |
67 | platform_ops.fixups = platform_fixups; | 58 | platform_ops.fixups = platform_fixups; |
diff --git a/arch/powerpc/boot/cuboot-85xx.c b/arch/powerpc/boot/cuboot-85xx.c index e2560317f278..10f0f697c935 100644 --- a/arch/powerpc/boot/cuboot-85xx.c +++ b/arch/powerpc/boot/cuboot-85xx.c | |||
@@ -12,12 +12,12 @@ | |||
12 | 12 | ||
13 | #include "ops.h" | 13 | #include "ops.h" |
14 | #include "stdio.h" | 14 | #include "stdio.h" |
15 | #include "cuboot.h" | ||
15 | 16 | ||
16 | #define TARGET_85xx | 17 | #define TARGET_85xx |
17 | #include "ppcboot.h" | 18 | #include "ppcboot.h" |
18 | 19 | ||
19 | static bd_t bd; | 20 | static bd_t bd; |
20 | extern char _end[]; | ||
21 | extern char _dtb_start[], _dtb_end[]; | 21 | extern char _dtb_start[], _dtb_end[]; |
22 | 22 | ||
23 | static void platform_fixups(void) | 23 | static void platform_fixups(void) |
@@ -53,16 +53,7 @@ static void platform_fixups(void) | |||
53 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 53 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
54 | unsigned long r6, unsigned long r7) | 54 | unsigned long r6, unsigned long r7) |
55 | { | 55 | { |
56 | unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | 56 | CUBOOT_INIT(); |
57 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
58 | |||
59 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||
60 | loader_info.initrd_addr = r4; | ||
61 | loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||
62 | loader_info.cmdline = (char *)r6; | ||
63 | loader_info.cmdline_len = r7 - r6; | ||
64 | |||
65 | simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||
66 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | 57 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); |
67 | serial_console_init(); | 58 | serial_console_init(); |
68 | platform_ops.fixups = platform_fixups; | 59 | platform_ops.fixups = platform_fixups; |
diff --git a/arch/powerpc/boot/cuboot-ebony.c b/arch/powerpc/boot/cuboot-ebony.c index 4464c5f67acb..c5f37ce172ea 100644 --- a/arch/powerpc/boot/cuboot-ebony.c +++ b/arch/powerpc/boot/cuboot-ebony.c | |||
@@ -15,28 +15,16 @@ | |||
15 | #include "ops.h" | 15 | #include "ops.h" |
16 | #include "stdio.h" | 16 | #include "stdio.h" |
17 | #include "44x.h" | 17 | #include "44x.h" |
18 | #include "cuboot.h" | ||
18 | 19 | ||
19 | #define TARGET_44x | 20 | #define TARGET_44x |
20 | #include "ppcboot.h" | 21 | #include "ppcboot.h" |
21 | 22 | ||
22 | static bd_t bd; | 23 | static bd_t bd; |
23 | extern char _end[]; | ||
24 | |||
25 | BSS_STACK(4096); | ||
26 | 24 | ||
27 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 25 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
28 | unsigned long r6, unsigned long r7) | 26 | unsigned long r6, unsigned long r7) |
29 | { | 27 | { |
30 | unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; | 28 | CUBOOT_INIT(); |
31 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
32 | |||
33 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); | ||
34 | loader_info.initrd_addr = r4; | ||
35 | loader_info.initrd_size = r4 ? r5 : 0; | ||
36 | loader_info.cmdline = (char *)r6; | ||
37 | loader_info.cmdline_len = r7 - r6; | ||
38 | |||
39 | simple_alloc_init(_end, avail_ram, 32, 64); | ||
40 | |||
41 | ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr); | 29 | ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr); |
42 | } | 30 | } |
diff --git a/arch/powerpc/boot/cuboot.c b/arch/powerpc/boot/cuboot.c new file mode 100644 index 000000000000..65795468ad6f --- /dev/null +++ b/arch/powerpc/boot/cuboot.c | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Compatibility for old (not device tree aware) U-Boot versions | ||
3 | * | ||
4 | * Author: Scott Wood <scottwood@freescale.com> | ||
5 | * Consolidated using macros by David Gibson <david@gibson.dropbear.id.au> | ||
6 | * | ||
7 | * Copyright 2007 David Gibson, IBM Corporation. | ||
8 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include "ops.h" | ||
16 | #include "stdio.h" | ||
17 | |||
18 | #include "ppcboot.h" | ||
19 | |||
20 | extern char _end[]; | ||
21 | extern char _dtb_start[], _dtb_end[]; | ||
22 | |||
23 | void cuboot_init(unsigned long r4, unsigned long r5, | ||
24 | unsigned long r6, unsigned long r7, | ||
25 | unsigned long end_of_ram) | ||
26 | { | ||
27 | unsigned long avail_ram = end_of_ram - (unsigned long)_end; | ||
28 | |||
29 | loader_info.initrd_addr = r4; | ||
30 | loader_info.initrd_size = r4 ? r5 - r4 : 0; | ||
31 | loader_info.cmdline = (char *)r6; | ||
32 | loader_info.cmdline_len = r7 - r6; | ||
33 | |||
34 | simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); | ||
35 | } | ||
diff --git a/arch/powerpc/boot/cuboot.h b/arch/powerpc/boot/cuboot.h new file mode 100644 index 000000000000..cd2aa7f348f3 --- /dev/null +++ b/arch/powerpc/boot/cuboot.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _PPC_BOOT_CUBOOT_H_ | ||
2 | #define _PPC_BOOT_CUBOOT_H_ | ||
3 | |||
4 | void cuboot_init(unsigned long r4, unsigned long r5, | ||
5 | unsigned long r6, unsigned long r7, | ||
6 | unsigned long end_of_ram); | ||
7 | |||
8 | #define CUBOOT_INIT() \ | ||
9 | do { \ | ||
10 | memcpy(&bd, (bd_t *)r3, sizeof(bd)); \ | ||
11 | cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \ | ||
12 | } while (0) | ||
13 | |||
14 | #endif /* _PPC_BOOT_CUBOOT_H_ */ | ||
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h index 877bc97b1e97..14b44aa96fea 100644 --- a/arch/powerpc/boot/dcr.h +++ b/arch/powerpc/boot/dcr.h | |||
@@ -26,6 +26,43 @@ static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2C | |||
26 | #define SDRAM_CONFIG_BANK_SIZE(reg) \ | 26 | #define SDRAM_CONFIG_BANK_SIZE(reg) \ |
27 | (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17)) | 27 | (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17)) |
28 | 28 | ||
29 | /* 440GP External Bus Controller (EBC) */ | ||
30 | #define DCRN_EBC0_CFGADDR 0x012 | ||
31 | #define DCRN_EBC0_CFGDATA 0x013 | ||
32 | #define EBC_NUM_BANKS 8 | ||
33 | #define EBC_B0CR 0x00 | ||
34 | #define EBC_B1CR 0x01 | ||
35 | #define EBC_B2CR 0x02 | ||
36 | #define EBC_B3CR 0x03 | ||
37 | #define EBC_B4CR 0x04 | ||
38 | #define EBC_B5CR 0x05 | ||
39 | #define EBC_B6CR 0x06 | ||
40 | #define EBC_B7CR 0x07 | ||
41 | #define EBC_BXCR(n) (n) | ||
42 | #define EBC_BXCR_BAS 0xfff00000 | ||
43 | #define EBC_BXCR_BS 0x000e0000 | ||
44 | #define EBC_BXCR_BANK_SIZE(reg) \ | ||
45 | (0x100000 << (((reg) & EBC_BXCR_BS) >> 17)) | ||
46 | #define EBC_BXCR_BU 0x00018000 | ||
47 | #define EBC_BXCR_BU_OFF 0x00000000 | ||
48 | #define EBC_BXCR_BU_RO 0x00008000 | ||
49 | #define EBC_BXCR_BU_WO 0x00010000 | ||
50 | #define EBC_BXCR_BU_RW 0x00018000 | ||
51 | #define EBC_BXCR_BW 0x00006000 | ||
52 | #define EBC_B0AP 0x10 | ||
53 | #define EBC_B1AP 0x11 | ||
54 | #define EBC_B2AP 0x12 | ||
55 | #define EBC_B3AP 0x13 | ||
56 | #define EBC_B4AP 0x14 | ||
57 | #define EBC_B5AP 0x15 | ||
58 | #define EBC_B6AP 0x16 | ||
59 | #define EBC_B7AP 0x17 | ||
60 | #define EBC_BXAP(n) (0x10+(n)) | ||
61 | #define EBC_BEAR 0x20 | ||
62 | #define EBC_BESR 0x21 | ||
63 | #define EBC_CFG 0x23 | ||
64 | #define EBC_CID 0x24 | ||
65 | |||
29 | /* 440GP Clock, PM, chip control */ | 66 | /* 440GP Clock, PM, chip control */ |
30 | #define DCRN_CPC0_SR 0x0b0 | 67 | #define DCRN_CPC0_SR 0x0b0 |
31 | #define DCRN_CPC0_ER 0x0b1 | 68 | #define DCRN_CPC0_ER 0x0b1 |
diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts index 0ec02f4726b5..c5f99613fc7b 100644 --- a/arch/powerpc/boot/dts/ebony.dts +++ b/arch/powerpc/boot/dts/ebony.dts | |||
@@ -31,8 +31,8 @@ | |||
31 | reg = <0>; | 31 | reg = <0>; |
32 | clock-frequency = <0>; // Filled in by zImage | 32 | clock-frequency = <0>; // Filled in by zImage |
33 | timebase-frequency = <0>; // Filled in by zImage | 33 | timebase-frequency = <0>; // Filled in by zImage |
34 | i-cache-line-size = <32>; | 34 | i-cache-line-size = <20>; |
35 | d-cache-line-size = <32>; | 35 | d-cache-line-size = <20>; |
36 | i-cache-size = <8000>; /* 32 kB */ | 36 | i-cache-size = <8000>; /* 32 kB */ |
37 | d-cache-size = <8000>; /* 32 kB */ | 37 | d-cache-size = <8000>; /* 32 kB */ |
38 | dcr-controller; | 38 | dcr-controller; |
@@ -135,11 +135,9 @@ | |||
135 | #address-cells = <2>; | 135 | #address-cells = <2>; |
136 | #size-cells = <1>; | 136 | #size-cells = <1>; |
137 | clock-frequency = <0>; // Filled in by zImage | 137 | clock-frequency = <0>; // Filled in by zImage |
138 | ranges = <0 00000000 fff00000 100000 | 138 | // ranges property is supplied by zImage |
139 | 1 00000000 48000000 100000 | 139 | // based on firmware's configuration of the |
140 | 2 00000000 ff800000 400000 | 140 | // EBC bridge |
141 | 3 00000000 48200000 100000 | ||
142 | 7 00000000 48300000 100000>; | ||
143 | interrupts = <5 4>; | 141 | interrupts = <5 4>; |
144 | interrupt-parent = <&UIC1>; | 142 | interrupt-parent = <&UIC1>; |
145 | 143 | ||
diff --git a/arch/powerpc/boot/dts/holly.dts b/arch/powerpc/boot/dts/holly.dts index 254499b107f4..80a4fab8ee37 100644 --- a/arch/powerpc/boot/dts/holly.dts +++ b/arch/powerpc/boot/dts/holly.dts | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | tsi109@c0000000 { | 47 | tsi109@c0000000 { |
48 | device_type = "tsi-bridge"; | 48 | device_type = "tsi-bridge"; |
49 | compatible = "tsi-bridge"; | 49 | compatible = "tsi109-bridge", "tsi108-bridge"; |
50 | #address-cells = <1>; | 50 | #address-cells = <1>; |
51 | #size-cells = <1>; | 51 | #size-cells = <1>; |
52 | ranges = <00000000 c0000000 00010000>; | 52 | ranges = <00000000 c0000000 00010000>; |
@@ -54,52 +54,55 @@ | |||
54 | 54 | ||
55 | i2c@7000 { | 55 | i2c@7000 { |
56 | device_type = "i2c"; | 56 | device_type = "i2c"; |
57 | compatible = "tsi-i2c"; | 57 | compatible = "tsi109-i2c", "tsi108-i2c"; |
58 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 58 | interrupt-parent = <&MPIC>; |
59 | interrupts = <e 2>; | 59 | interrupts = <e 2>; |
60 | reg = <7000 400>; | 60 | reg = <7000 400>; |
61 | }; | 61 | }; |
62 | 62 | ||
63 | mdio@6000 { | 63 | MDIO: mdio@6000 { |
64 | device_type = "mdio"; | 64 | device_type = "mdio"; |
65 | compatible = "tsi-ethernet"; | 65 | compatible = "tsi109-mdio", "tsi108-mdio"; |
66 | reg = <6000 50>; | ||
67 | #address-cells = <1>; | ||
68 | #size-cells = <0>; | ||
66 | 69 | ||
67 | PHY1: ethernet-phy@6000 { | 70 | PHY1: ethernet-phy@1 { |
68 | device_type = "ethernet-phy"; | 71 | compatible = "bcm5461a"; |
69 | compatible = "bcm54xx"; | 72 | reg = <1>; |
70 | reg = <6000 50>; | 73 | txc-rxc-delay-disable; |
71 | phy-id = <1>; | ||
72 | }; | 74 | }; |
73 | 75 | ||
74 | PHY2: ethernet-phy@6400 { | 76 | PHY2: ethernet-phy@2 { |
75 | device_type = "ethernet-phy"; | 77 | compatible = "bcm5461a"; |
76 | compatible = "bcm54xx"; | 78 | reg = <2>; |
77 | reg = <6000 50>; | 79 | txc-rxc-delay-disable; |
78 | phy-id = <2>; | ||
79 | }; | 80 | }; |
80 | }; | 81 | }; |
81 | 82 | ||
82 | ethernet@6200 { | 83 | ethernet@6200 { |
83 | device_type = "network"; | 84 | device_type = "network"; |
84 | compatible = "tsi-ethernet"; | 85 | compatible = "tsi109-ethernet", "tsi108-ethernet"; |
85 | #address-cells = <1>; | 86 | #address-cells = <1>; |
86 | #size-cells = <0>; | 87 | #size-cells = <0>; |
87 | reg = <6000 200>; | 88 | reg = <6000 200>; |
88 | local-mac-address = [ 00 00 00 00 00 00 ]; | 89 | local-mac-address = [ 00 00 00 00 00 00 ]; |
89 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 90 | interrupt-parent = <&MPIC>; |
90 | interrupts = <10 2>; | 91 | interrupts = <10 2>; |
92 | mdio-handle = <&MDIO>; | ||
91 | phy-handle = <&PHY1>; | 93 | phy-handle = <&PHY1>; |
92 | }; | 94 | }; |
93 | 95 | ||
94 | ethernet@6600 { | 96 | ethernet@6600 { |
95 | device_type = "network"; | 97 | device_type = "network"; |
96 | compatible = "tsi-ethernet"; | 98 | compatible = "tsi109-ethernet", "tsi108-ethernet"; |
97 | #address-cells = <1>; | 99 | #address-cells = <1>; |
98 | #size-cells = <0>; | 100 | #size-cells = <0>; |
99 | reg = <6400 200>; | 101 | reg = <6400 200>; |
100 | local-mac-address = [ 00 00 00 00 00 00 ]; | 102 | local-mac-address = [ 00 00 00 00 00 00 ]; |
101 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 103 | interrupt-parent = <&MPIC>; |
102 | interrupts = <11 2>; | 104 | interrupts = <11 2>; |
105 | mdio-handle = <&MDIO>; | ||
103 | phy-handle = <&PHY2>; | 106 | phy-handle = <&PHY2>; |
104 | }; | 107 | }; |
105 | 108 | ||
@@ -110,7 +113,7 @@ | |||
110 | virtual-reg = <c0007808>; | 113 | virtual-reg = <c0007808>; |
111 | clock-frequency = <3F9C6000>; | 114 | clock-frequency = <3F9C6000>; |
112 | current-speed = <1c200>; | 115 | current-speed = <1c200>; |
113 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 116 | interrupt-parent = <&MPIC>; |
114 | interrupts = <c 2>; | 117 | interrupts = <c 2>; |
115 | }; | 118 | }; |
116 | 119 | ||
@@ -121,7 +124,7 @@ | |||
121 | virtual-reg = <c0007c08>; | 124 | virtual-reg = <c0007c08>; |
122 | clock-frequency = <3F9C6000>; | 125 | clock-frequency = <3F9C6000>; |
123 | current-speed = <1c200>; | 126 | current-speed = <1c200>; |
124 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 127 | interrupt-parent = <&MPIC>; |
125 | interrupts = <d 2>; | 128 | interrupts = <d 2>; |
126 | }; | 129 | }; |
127 | 130 | ||
@@ -136,7 +139,7 @@ | |||
136 | 139 | ||
137 | pci@1000 { | 140 | pci@1000 { |
138 | device_type = "pci"; | 141 | device_type = "pci"; |
139 | compatible = "tsi109"; | 142 | compatible = "tsi109-pci", "tsi108-pci"; |
140 | #interrupt-cells = <1>; | 143 | #interrupt-cells = <1>; |
141 | #size-cells = <2>; | 144 | #size-cells = <2>; |
142 | #address-cells = <3>; | 145 | #address-cells = <3>; |
@@ -150,7 +153,7 @@ | |||
150 | ranges = <02000000 0 40000000 40000000 0 10000000 | 153 | ranges = <02000000 0 40000000 40000000 0 10000000 |
151 | 01000000 0 00000000 7e000000 0 00010000>; | 154 | 01000000 0 00000000 7e000000 0 00010000>; |
152 | clock-frequency = <7f28154>; | 155 | clock-frequency = <7f28154>; |
153 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 156 | interrupt-parent = <&MPIC>; |
154 | interrupts = <17 2>; | 157 | interrupts = <17 2>; |
155 | interrupt-map-mask = <f800 0 0 7>; | 158 | interrupt-map-mask = <f800 0 0 7>; |
156 | /*----------------------------------------------------+ | 159 | /*----------------------------------------------------+ |
@@ -186,13 +189,12 @@ | |||
186 | #address-cells = <0>; | 189 | #address-cells = <0>; |
187 | #interrupt-cells = <2>; | 190 | #interrupt-cells = <2>; |
188 | interrupts = <17 2>; | 191 | interrupts = <17 2>; |
189 | interrupt-parent = < &/tsi109@c0000000/pic@7400 >; | 192 | interrupt-parent = <&MPIC>; |
190 | }; | 193 | }; |
191 | }; | 194 | }; |
192 | }; | 195 | }; |
193 | 196 | ||
194 | chosen { | 197 | chosen { |
195 | linux,stdout-path = "/tsi109@c0000000/serial@7808"; | 198 | linux,stdout-path = "/tsi109@c0000000/serial@7808"; |
196 | bootargs = "console=ttyS0,115200"; | ||
197 | }; | 199 | }; |
198 | }; | 200 | }; |
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts index 765c306ecf80..0e3d314a7158 100644 --- a/arch/powerpc/boot/dts/mpc7448hpc2.dts +++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts | |||
@@ -45,7 +45,7 @@ | |||
45 | #address-cells = <1>; | 45 | #address-cells = <1>; |
46 | #size-cells = <1>; | 46 | #size-cells = <1>; |
47 | #interrupt-cells = <2>; | 47 | #interrupt-cells = <2>; |
48 | device_type = "tsi-bridge"; | 48 | device_type = "tsi108-bridge"; |
49 | ranges = <00000000 c0000000 00010000>; | 49 | ranges = <00000000 c0000000 00010000>; |
50 | reg = <c0000000 00010000>; | 50 | reg = <c0000000 00010000>; |
51 | bus-frequency = <0>; | 51 | bus-frequency = <0>; |
@@ -55,27 +55,26 @@ | |||
55 | interrupts = <E 0>; | 55 | interrupts = <E 0>; |
56 | reg = <7000 400>; | 56 | reg = <7000 400>; |
57 | device_type = "i2c"; | 57 | device_type = "i2c"; |
58 | compatible = "tsi-i2c"; | 58 | compatible = "tsi108-i2c"; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | mdio@6000 { | 61 | MDIO: mdio@6000 { |
62 | device_type = "mdio"; | 62 | device_type = "mdio"; |
63 | compatible = "tsi-ethernet"; | 63 | compatible = "tsi108-mdio"; |
64 | reg = <6000 50>; | ||
65 | #address-cells = <1>; | ||
66 | #size-cells = <0>; | ||
64 | 67 | ||
65 | phy8: ethernet-phy@6000 { | 68 | phy8: ethernet-phy@8 { |
66 | interrupt-parent = <&mpic>; | 69 | interrupt-parent = <&mpic>; |
67 | interrupts = <2 1>; | 70 | interrupts = <2 1>; |
68 | reg = <6000 50>; | 71 | reg = <8>; |
69 | phy-id = <8>; | ||
70 | device_type = "ethernet-phy"; | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | phy9: ethernet-phy@6400 { | 74 | phy9: ethernet-phy@9 { |
74 | interrupt-parent = <&mpic>; | 75 | interrupt-parent = <&mpic>; |
75 | interrupts = <2 1>; | 76 | interrupts = <2 1>; |
76 | reg = <6000 50>; | 77 | reg = <9>; |
77 | phy-id = <9>; | ||
78 | device_type = "ethernet-phy"; | ||
79 | }; | 78 | }; |
80 | 79 | ||
81 | }; | 80 | }; |
@@ -83,12 +82,12 @@ | |||
83 | ethernet@6200 { | 82 | ethernet@6200 { |
84 | #size-cells = <0>; | 83 | #size-cells = <0>; |
85 | device_type = "network"; | 84 | device_type = "network"; |
86 | model = "TSI-ETH"; | 85 | compatible = "tsi108-ethernet"; |
87 | compatible = "tsi-ethernet"; | ||
88 | reg = <6000 200>; | 86 | reg = <6000 200>; |
89 | address = [ 00 06 D2 00 00 01 ]; | 87 | address = [ 00 06 D2 00 00 01 ]; |
90 | interrupts = <10 2>; | 88 | interrupts = <10 2>; |
91 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
90 | mdio-handle = <&MDIO>; | ||
92 | phy-handle = <&phy8>; | 91 | phy-handle = <&phy8>; |
93 | }; | 92 | }; |
94 | 93 | ||
@@ -96,12 +95,12 @@ | |||
96 | #address-cells = <1>; | 95 | #address-cells = <1>; |
97 | #size-cells = <0>; | 96 | #size-cells = <0>; |
98 | device_type = "network"; | 97 | device_type = "network"; |
99 | model = "TSI-ETH"; | 98 | compatible = "tsi108-ethernet"; |
100 | compatible = "tsi-ethernet"; | ||
101 | reg = <6400 200>; | 99 | reg = <6400 200>; |
102 | address = [ 00 06 D2 00 00 02 ]; | 100 | address = [ 00 06 D2 00 00 02 ]; |
103 | interrupts = <11 2>; | 101 | interrupts = <11 2>; |
104 | interrupt-parent = <&mpic>; | 102 | interrupt-parent = <&mpic>; |
103 | mdio-handle = <&MDIO>; | ||
105 | phy-handle = <&phy9>; | 104 | phy-handle = <&phy9>; |
106 | }; | 105 | }; |
107 | 106 | ||
@@ -135,7 +134,7 @@ | |||
135 | big-endian; | 134 | big-endian; |
136 | }; | 135 | }; |
137 | pci@1000 { | 136 | pci@1000 { |
138 | compatible = "tsi10x"; | 137 | compatible = "tsi108-pci"; |
139 | device_type = "pci"; | 138 | device_type = "pci"; |
140 | #interrupt-cells = <1>; | 139 | #interrupt-cells = <1>; |
141 | #size-cells = <2>; | 140 | #size-cells = <2>; |
diff --git a/arch/powerpc/boot/dts/mpc8272ads.dts b/arch/powerpc/boot/dts/mpc8272ads.dts index 423eedcf634f..1934b800278e 100644 --- a/arch/powerpc/boot/dts/mpc8272ads.dts +++ b/arch/powerpc/boot/dts/mpc8272ads.dts | |||
@@ -14,12 +14,10 @@ | |||
14 | compatible = "MPC8260ADS"; | 14 | compatible = "MPC8260ADS"; |
15 | #address-cells = <1>; | 15 | #address-cells = <1>; |
16 | #size-cells = <1>; | 16 | #size-cells = <1>; |
17 | linux,phandle = <100>; | ||
18 | 17 | ||
19 | cpus { | 18 | cpus { |
20 | #address-cells = <1>; | 19 | #address-cells = <1>; |
21 | #size-cells = <0>; | 20 | #size-cells = <0>; |
22 | linux,phandle = <200>; | ||
23 | 21 | ||
24 | PowerPC,8272@0 { | 22 | PowerPC,8272@0 { |
25 | device_type = "cpu"; | 23 | device_type = "cpu"; |
@@ -32,12 +30,10 @@ | |||
32 | bus-frequency = <0>; | 30 | bus-frequency = <0>; |
33 | clock-frequency = <0>; | 31 | clock-frequency = <0>; |
34 | 32-bit; | 32 | 32-bit; |
35 | linux,phandle = <201>; | ||
36 | }; | 33 | }; |
37 | }; | 34 | }; |
38 | 35 | ||
39 | interrupt-controller@f8200000 { | 36 | pci_pic: interrupt-controller@f8200000 { |
40 | linux,phandle = <f8200000>; | ||
41 | #address-cells = <0>; | 37 | #address-cells = <0>; |
42 | #interrupt-cells = <2>; | 38 | #interrupt-cells = <2>; |
43 | interrupt-controller; | 39 | interrupt-controller; |
@@ -47,15 +43,13 @@ | |||
47 | }; | 43 | }; |
48 | memory { | 44 | memory { |
49 | device_type = "memory"; | 45 | device_type = "memory"; |
50 | linux,phandle = <300>; | ||
51 | reg = <00000000 4000000 f4500000 00000020>; | 46 | reg = <00000000 4000000 f4500000 00000020>; |
52 | }; | 47 | }; |
53 | 48 | ||
54 | chosen { | 49 | chosen { |
55 | name = "chosen"; | 50 | name = "chosen"; |
56 | linux,platform = <0>; | 51 | linux,platform = <0>; |
57 | interrupt-controller = <10c00>; | 52 | interrupt-controller = <&Cpm_pic>; |
58 | linux,phandle = <400>; | ||
59 | }; | 53 | }; |
60 | 54 | ||
61 | soc8272@f0000000 { | 55 | soc8272@f0000000 { |
@@ -70,20 +64,17 @@ | |||
70 | device_type = "mdio"; | 64 | device_type = "mdio"; |
71 | compatible = "fs_enet"; | 65 | compatible = "fs_enet"; |
72 | reg = <0 0>; | 66 | reg = <0 0>; |
73 | linux,phandle = <24520>; | ||
74 | #address-cells = <1>; | 67 | #address-cells = <1>; |
75 | #size-cells = <0>; | 68 | #size-cells = <0>; |
76 | ethernet-phy@0 { | 69 | phy0:ethernet-phy@0 { |
77 | linux,phandle = <2452000>; | 70 | interrupt-parent = <&Cpm_pic>; |
78 | interrupt-parent = <10c00>; | ||
79 | interrupts = <17 4>; | 71 | interrupts = <17 4>; |
80 | reg = <0>; | 72 | reg = <0>; |
81 | bitbang = [ 12 12 13 02 02 01 ]; | 73 | bitbang = [ 12 12 13 02 02 01 ]; |
82 | device_type = "ethernet-phy"; | 74 | device_type = "ethernet-phy"; |
83 | }; | 75 | }; |
84 | ethernet-phy@1 { | 76 | phy1:ethernet-phy@1 { |
85 | linux,phandle = <2452001>; | 77 | interrupt-parent = <&Cpm_pic>; |
86 | interrupt-parent = <10c00>; | ||
87 | interrupts = <17 4>; | 78 | interrupts = <17 4>; |
88 | bitbang = [ 12 12 13 02 02 01 ]; | 79 | bitbang = [ 12 12 13 02 02 01 ]; |
89 | reg = <3>; | 80 | reg = <3>; |
@@ -101,8 +92,8 @@ | |||
101 | reg = <11300 20 8400 100 11380 30>; | 92 | reg = <11300 20 8400 100 11380 30>; |
102 | mac-address = [ 00 11 2F 99 43 54 ]; | 93 | mac-address = [ 00 11 2F 99 43 54 ]; |
103 | interrupts = <20 2>; | 94 | interrupts = <20 2>; |
104 | interrupt-parent = <10c00>; | 95 | interrupt-parent = <&Cpm_pic>; |
105 | phy-handle = <2452000>; | 96 | phy-handle = <&Phy0>; |
106 | rx-clock = <13>; | 97 | rx-clock = <13>; |
107 | tx-clock = <12>; | 98 | tx-clock = <12>; |
108 | }; | 99 | }; |
@@ -115,14 +106,13 @@ | |||
115 | reg = <11320 20 8500 100 113b0 30>; | 106 | reg = <11320 20 8500 100 113b0 30>; |
116 | mac-address = [ 00 11 2F 99 44 54 ]; | 107 | mac-address = [ 00 11 2F 99 44 54 ]; |
117 | interrupts = <21 2>; | 108 | interrupts = <21 2>; |
118 | interrupt-parent = <10c00>; | 109 | interrupt-parent = <&Cpm_pic>; |
119 | phy-handle = <2452001>; | 110 | phy-handle = <&Phy1>; |
120 | rx-clock = <17>; | 111 | rx-clock = <17>; |
121 | tx-clock = <18>; | 112 | tx-clock = <18>; |
122 | }; | 113 | }; |
123 | 114 | ||
124 | cpm@f0000000 { | 115 | cpm@f0000000 { |
125 | linux,phandle = <f0000000>; | ||
126 | #address-cells = <1>; | 116 | #address-cells = <1>; |
127 | #size-cells = <1>; | 117 | #size-cells = <1>; |
128 | #interrupt-cells = <2>; | 118 | #interrupt-cells = <2>; |
@@ -142,7 +132,7 @@ | |||
142 | reg = <11a00 20 8000 100>; | 132 | reg = <11a00 20 8000 100>; |
143 | current-speed = <1c200>; | 133 | current-speed = <1c200>; |
144 | interrupts = <28 2>; | 134 | interrupts = <28 2>; |
145 | interrupt-parent = <10c00>; | 135 | interrupt-parent = <&Cpm_pic>; |
146 | clock-setup = <0 00ffffff>; | 136 | clock-setup = <0 00ffffff>; |
147 | rx-clock = <1>; | 137 | rx-clock = <1>; |
148 | tx-clock = <1>; | 138 | tx-clock = <1>; |
@@ -156,15 +146,14 @@ | |||
156 | reg = <11a60 20 8300 100>; | 146 | reg = <11a60 20 8300 100>; |
157 | current-speed = <1c200>; | 147 | current-speed = <1c200>; |
158 | interrupts = <2b 2>; | 148 | interrupts = <2b 2>; |
159 | interrupt-parent = <10c00>; | 149 | interrupt-parent = <&Cpm_pic>; |
160 | clock-setup = <1b ffffff00>; | 150 | clock-setup = <1b ffffff00>; |
161 | rx-clock = <4>; | 151 | rx-clock = <4>; |
162 | tx-clock = <4>; | 152 | tx-clock = <4>; |
163 | }; | 153 | }; |
164 | 154 | ||
165 | }; | 155 | }; |
166 | interrupt-controller@10c00 { | 156 | cpm_pic:interrupt-controller@10c00 { |
167 | linux,phandle = <10c00>; | ||
168 | #address-cells = <0>; | 157 | #address-cells = <0>; |
169 | #interrupt-cells = <2>; | 158 | #interrupt-cells = <2>; |
170 | interrupt-controller; | 159 | interrupt-controller; |
@@ -174,7 +163,6 @@ | |||
174 | compatible = "CPM2"; | 163 | compatible = "CPM2"; |
175 | }; | 164 | }; |
176 | pci@0500 { | 165 | pci@0500 { |
177 | linux,phandle = <0500>; | ||
178 | #interrupt-cells = <1>; | 166 | #interrupt-cells = <1>; |
179 | #size-cells = <2>; | 167 | #size-cells = <2>; |
180 | #address-cells = <3>; | 168 | #address-cells = <3>; |
@@ -202,7 +190,7 @@ | |||
202 | c000 0 0 2 f8200000 43 8 | 190 | c000 0 0 2 f8200000 43 8 |
203 | c000 0 0 3 f8200000 40 8 | 191 | c000 0 0 3 f8200000 40 8 |
204 | c000 0 0 4 f8200000 41 8>; | 192 | c000 0 0 4 f8200000 41 8>; |
205 | interrupt-parent = <10c00>; | 193 | interrupt-parent = <&Cpm_pic>; |
206 | interrupts = <14 8>; | 194 | interrupts = <14 8>; |
207 | bus-range = <0 0>; | 195 | bus-range = <0 0>; |
208 | ranges = <02000000 0 80000000 80000000 0 40000000 | 196 | ranges = <02000000 0 80000000 80000000 0 40000000 |
@@ -216,7 +204,7 @@ | |||
216 | compatible = "talitos"; | 204 | compatible = "talitos"; |
217 | reg = <30000 10000>; | 205 | reg = <30000 10000>; |
218 | interrupts = <b 2>; | 206 | interrupts = <b 2>; |
219 | interrupt-parent = <10c00>; | 207 | interrupt-parent = <&Cpm_pic>; |
220 | num-channels = <4>; | 208 | num-channels = <4>; |
221 | channel-fifo-len = <18>; | 209 | channel-fifo-len = <18>; |
222 | exec-units-mask = <0000007e>; | 210 | exec-units-mask = <0000007e>; |
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 112dd5198fe2..4fc0c4d34aa8 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts | |||
@@ -272,7 +272,13 @@ | |||
272 | reg = <2200 200>; | 272 | reg = <2200 200>; |
273 | interrupts = <22>; | 273 | interrupts = <22>; |
274 | interrupt-parent = < &qeic >; | 274 | interrupt-parent = < &qeic >; |
275 | mac-address = [ 00 04 9f 00 23 23 ]; | 275 | /* |
276 | * mac-address is deprecated and will be removed | ||
277 | * in 2.6.25. Only recent versions of | ||
278 | * U-Boot support local-mac-address, however. | ||
279 | */ | ||
280 | mac-address = [ 00 00 00 00 00 00 ]; | ||
281 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
276 | rx-clock = <19>; | 282 | rx-clock = <19>; |
277 | tx-clock = <1a>; | 283 | tx-clock = <1a>; |
278 | phy-handle = < &phy3 >; | 284 | phy-handle = < &phy3 >; |
@@ -287,7 +293,13 @@ | |||
287 | reg = <3000 200>; | 293 | reg = <3000 200>; |
288 | interrupts = <23>; | 294 | interrupts = <23>; |
289 | interrupt-parent = < &qeic >; | 295 | interrupt-parent = < &qeic >; |
290 | mac-address = [ 00 11 22 33 44 55 ]; | 296 | /* |
297 | * mac-address is deprecated and will be removed | ||
298 | * in 2.6.25. Only recent versions of | ||
299 | * U-Boot support local-mac-address, however. | ||
300 | */ | ||
301 | mac-address = [ 00 00 00 00 00 00 ]; | ||
302 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
291 | rx-clock = <17>; | 303 | rx-clock = <17>; |
292 | tx-clock = <18>; | 304 | tx-clock = <18>; |
293 | phy-handle = < &phy4 >; | 305 | phy-handle = < &phy4 >; |
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index be4c35784e49..447c03ffabbc 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts | |||
@@ -231,7 +231,13 @@ | |||
231 | reg = <3000 200>; | 231 | reg = <3000 200>; |
232 | interrupts = <21>; | 232 | interrupts = <21>; |
233 | interrupt-parent = <&qeic>; | 233 | interrupt-parent = <&qeic>; |
234 | mac-address = [ 00 04 9f ef 03 02 ]; | 234 | /* |
235 | * mac-address is deprecated and will be removed | ||
236 | * in 2.6.25. Only recent versions of | ||
237 | * U-Boot support local-mac-address, however. | ||
238 | */ | ||
239 | mac-address = [ 00 00 00 00 00 00 ]; | ||
240 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
235 | rx-clock = <20>; | 241 | rx-clock = <20>; |
236 | tx-clock = <13>; | 242 | tx-clock = <13>; |
237 | phy-handle = <&phy00>; | 243 | phy-handle = <&phy00>; |
@@ -246,7 +252,13 @@ | |||
246 | reg = <2200 200>; | 252 | reg = <2200 200>; |
247 | interrupts = <22>; | 253 | interrupts = <22>; |
248 | interrupt-parent = <&qeic>; | 254 | interrupt-parent = <&qeic>; |
249 | mac-address = [ 00 04 9f ef 03 01 ]; | 255 | /* |
256 | * mac-address is deprecated and will be removed | ||
257 | * in 2.6.25. Only recent versions of | ||
258 | * U-Boot support local-mac-address, however. | ||
259 | */ | ||
260 | mac-address = [ 00 00 00 00 00 00 ]; | ||
261 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
250 | rx-clock = <19>; | 262 | rx-clock = <19>; |
251 | tx-clock = <1a>; | 263 | tx-clock = <1a>; |
252 | phy-handle = <&phy04>; | 264 | phy-handle = <&phy04>; |
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index db0d00303275..ae9bca575453 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts | |||
@@ -131,6 +131,11 @@ | |||
131 | model = "TSEC"; | 131 | model = "TSEC"; |
132 | compatible = "gianfar"; | 132 | compatible = "gianfar"; |
133 | reg = <24000 1000>; | 133 | reg = <24000 1000>; |
134 | /* | ||
135 | * address is deprecated and will be removed | ||
136 | * in 2.6.25. Only recent versions of | ||
137 | * U-Boot support local-mac-address, however. | ||
138 | */ | ||
134 | address = [ 00 00 00 00 00 00 ]; | 139 | address = [ 00 00 00 00 00 00 ]; |
135 | local-mac-address = [ 00 00 00 00 00 00 ]; | 140 | local-mac-address = [ 00 00 00 00 00 00 ]; |
136 | interrupts = <20 8 21 8 22 8>; | 141 | interrupts = <20 8 21 8 22 8>; |
@@ -145,6 +150,11 @@ | |||
145 | model = "TSEC"; | 150 | model = "TSEC"; |
146 | compatible = "gianfar"; | 151 | compatible = "gianfar"; |
147 | reg = <25000 1000>; | 152 | reg = <25000 1000>; |
153 | /* | ||
154 | * address is deprecated and will be removed | ||
155 | * in 2.6.25. Only recent versions of | ||
156 | * U-Boot support local-mac-address, however. | ||
157 | */ | ||
148 | address = [ 00 00 00 00 00 00 ]; | 158 | address = [ 00 00 00 00 00 00 ]; |
149 | local-mac-address = [ 00 00 00 00 00 00 ]; | 159 | local-mac-address = [ 00 00 00 00 00 00 ]; |
150 | interrupts = <23 8 24 8 25 8>; | 160 | interrupts = <23 8 24 8 25 8>; |
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index df773fafe9d1..310e877826b4 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts | |||
@@ -136,6 +136,11 @@ | |||
136 | model = "TSEC"; | 136 | model = "TSEC"; |
137 | compatible = "gianfar"; | 137 | compatible = "gianfar"; |
138 | reg = <24000 1000>; | 138 | reg = <24000 1000>; |
139 | /* | ||
140 | * address is deprecated and will be removed | ||
141 | * in 2.6.25. Only recent versions of | ||
142 | * U-Boot support local-mac-address, however. | ||
143 | */ | ||
139 | address = [ 00 00 00 00 00 00 ]; | 144 | address = [ 00 00 00 00 00 00 ]; |
140 | local-mac-address = [ 00 00 00 00 00 00 ]; | 145 | local-mac-address = [ 00 00 00 00 00 00 ]; |
141 | interrupts = <20 8 21 8 22 8>; | 146 | interrupts = <20 8 21 8 22 8>; |
@@ -150,6 +155,11 @@ | |||
150 | model = "TSEC"; | 155 | model = "TSEC"; |
151 | compatible = "gianfar"; | 156 | compatible = "gianfar"; |
152 | reg = <25000 1000>; | 157 | reg = <25000 1000>; |
158 | /* | ||
159 | * address is deprecated and will be removed | ||
160 | * in 2.6.25. Only recent versions of | ||
161 | * U-Boot support local-mac-address, however. | ||
162 | */ | ||
153 | address = [ 00 00 00 00 00 00 ]; | 163 | address = [ 00 00 00 00 00 00 ]; |
154 | local-mac-address = [ 00 00 00 00 00 00 ]; | 164 | local-mac-address = [ 00 00 00 00 00 00 ]; |
155 | interrupts = <23 8 24 8 25 8>; | 165 | interrupts = <23 8 24 8 25 8>; |
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 38c8594df3a4..1e914f31dd92 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts | |||
@@ -301,7 +301,13 @@ | |||
301 | reg = <2000 200>; | 301 | reg = <2000 200>; |
302 | interrupts = <20>; | 302 | interrupts = <20>; |
303 | interrupt-parent = < &qeic >; | 303 | interrupt-parent = < &qeic >; |
304 | mac-address = [ 00 04 9f 00 23 23 ]; | 304 | /* |
305 | * mac-address is deprecated and will be removed | ||
306 | * in 2.6.25. Only recent versions of | ||
307 | * U-Boot support local-mac-address, however. | ||
308 | */ | ||
309 | mac-address = [ 00 00 00 00 00 00 ]; | ||
310 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
305 | rx-clock = <0>; | 311 | rx-clock = <0>; |
306 | tx-clock = <19>; | 312 | tx-clock = <19>; |
307 | phy-handle = < &phy0 >; | 313 | phy-handle = < &phy0 >; |
@@ -317,7 +323,13 @@ | |||
317 | reg = <3000 200>; | 323 | reg = <3000 200>; |
318 | interrupts = <21>; | 324 | interrupts = <21>; |
319 | interrupt-parent = < &qeic >; | 325 | interrupt-parent = < &qeic >; |
320 | mac-address = [ 00 11 22 33 44 55 ]; | 326 | /* |
327 | * mac-address is deprecated and will be removed | ||
328 | * in 2.6.25. Only recent versions of | ||
329 | * U-Boot support local-mac-address, however. | ||
330 | */ | ||
331 | mac-address = [ 00 00 00 00 00 00 ]; | ||
332 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
321 | rx-clock = <0>; | 333 | rx-clock = <0>; |
322 | tx-clock = <14>; | 334 | tx-clock = <14>; |
323 | phy-handle = < &phy1 >; | 335 | phy-handle = < &phy1 >; |
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts index d91e81c009f5..364a969f5c2f 100644 --- a/arch/powerpc/boot/dts/mpc8540ads.dts +++ b/arch/powerpc/boot/dts/mpc8540ads.dts | |||
@@ -52,7 +52,7 @@ | |||
52 | compatible = "fsl,8540-memory-controller"; | 52 | compatible = "fsl,8540-memory-controller"; |
53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
@@ -61,14 +61,14 @@ | |||
61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | i2c@3000 { | 67 | i2c@3000 { |
68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
73 | dfsrr; | 73 | dfsrr; |
74 | }; | 74 | }; |
@@ -81,19 +81,19 @@ | |||
81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
84 | interrupts = <35 1>; | 84 | interrupts = <5 1>; |
85 | reg = <0>; | 85 | reg = <0>; |
86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
87 | }; | 87 | }; |
88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
90 | interrupts = <35 1>; | 90 | interrupts = <5 1>; |
91 | reg = <1>; | 91 | reg = <1>; |
92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
93 | }; | 93 | }; |
94 | phy3: ethernet-phy@3 { | 94 | phy3: ethernet-phy@3 { |
95 | interrupt-parent = <&mpic>; | 95 | interrupt-parent = <&mpic>; |
96 | interrupts = <37 1>; | 96 | interrupts = <7 1>; |
97 | reg = <3>; | 97 | reg = <3>; |
98 | device_type = "ethernet-phy"; | 98 | device_type = "ethernet-phy"; |
99 | }; | 99 | }; |
@@ -106,9 +106,14 @@ | |||
106 | model = "TSEC"; | 106 | model = "TSEC"; |
107 | compatible = "gianfar"; | 107 | compatible = "gianfar"; |
108 | reg = <24000 1000>; | 108 | reg = <24000 1000>; |
109 | address = [ 00 E0 0C 00 73 00 ]; | 109 | /* |
110 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 110 | * address is deprecated and will be removed |
111 | interrupts = <d 2 e 2 12 2>; | 111 | * in 2.6.25. Only recent versions of |
112 | * U-Boot support local-mac-address, however. | ||
113 | */ | ||
114 | address = [ 00 00 00 00 00 00 ]; | ||
115 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
116 | interrupts = <1d 2 1e 2 22 2>; | ||
112 | interrupt-parent = <&mpic>; | 117 | interrupt-parent = <&mpic>; |
113 | phy-handle = <&phy0>; | 118 | phy-handle = <&phy0>; |
114 | }; | 119 | }; |
@@ -120,9 +125,14 @@ | |||
120 | model = "TSEC"; | 125 | model = "TSEC"; |
121 | compatible = "gianfar"; | 126 | compatible = "gianfar"; |
122 | reg = <25000 1000>; | 127 | reg = <25000 1000>; |
123 | address = [ 00 E0 0C 00 73 01 ]; | 128 | /* |
124 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 129 | * address is deprecated and will be removed |
125 | interrupts = <13 2 14 2 18 2>; | 130 | * in 2.6.25. Only recent versions of |
131 | * U-Boot support local-mac-address, however. | ||
132 | */ | ||
133 | address = [ 00 00 00 00 00 00 ]; | ||
134 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
135 | interrupts = <23 2 24 2 28 2>; | ||
126 | interrupt-parent = <&mpic>; | 136 | interrupt-parent = <&mpic>; |
127 | phy-handle = <&phy1>; | 137 | phy-handle = <&phy1>; |
128 | }; | 138 | }; |
@@ -134,9 +144,14 @@ | |||
134 | model = "FEC"; | 144 | model = "FEC"; |
135 | compatible = "gianfar"; | 145 | compatible = "gianfar"; |
136 | reg = <26000 1000>; | 146 | reg = <26000 1000>; |
137 | address = [ 00 E0 0C 00 73 02 ]; | 147 | /* |
138 | local-mac-address = [ 00 E0 0C 00 73 02 ]; | 148 | * address is deprecated and will be removed |
139 | interrupts = <19 2>; | 149 | * in 2.6.25. Only recent versions of |
150 | * U-Boot support local-mac-address, however. | ||
151 | */ | ||
152 | address = [ 00 00 00 00 00 00 ]; | ||
153 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
154 | interrupts = <29 2>; | ||
140 | interrupt-parent = <&mpic>; | 155 | interrupt-parent = <&mpic>; |
141 | phy-handle = <&phy3>; | 156 | phy-handle = <&phy3>; |
142 | }; | 157 | }; |
@@ -146,7 +161,7 @@ | |||
146 | compatible = "ns16550"; | 161 | compatible = "ns16550"; |
147 | reg = <4500 100>; // reg base, size | 162 | reg = <4500 100>; // reg base, size |
148 | clock-frequency = <0>; // should we fill in in uboot? | 163 | clock-frequency = <0>; // should we fill in in uboot? |
149 | interrupts = <1a 2>; | 164 | interrupts = <2a 2>; |
150 | interrupt-parent = <&mpic>; | 165 | interrupt-parent = <&mpic>; |
151 | }; | 166 | }; |
152 | 167 | ||
@@ -155,7 +170,7 @@ | |||
155 | compatible = "ns16550"; | 170 | compatible = "ns16550"; |
156 | reg = <4600 100>; // reg base, size | 171 | reg = <4600 100>; // reg base, size |
157 | clock-frequency = <0>; // should we fill in in uboot? | 172 | clock-frequency = <0>; // should we fill in in uboot? |
158 | interrupts = <1a 2>; | 173 | interrupts = <2a 2>; |
159 | interrupt-parent = <&mpic>; | 174 | interrupt-parent = <&mpic>; |
160 | }; | 175 | }; |
161 | pci@8000 { | 176 | pci@8000 { |
@@ -163,78 +178,78 @@ | |||
163 | interrupt-map = < | 178 | interrupt-map = < |
164 | 179 | ||
165 | /* IDSEL 0x02 */ | 180 | /* IDSEL 0x02 */ |
166 | 1000 0 0 1 &mpic 31 1 | 181 | 1000 0 0 1 &mpic 1 1 |
167 | 1000 0 0 2 &mpic 32 1 | 182 | 1000 0 0 2 &mpic 2 1 |
168 | 1000 0 0 3 &mpic 33 1 | 183 | 1000 0 0 3 &mpic 3 1 |
169 | 1000 0 0 4 &mpic 34 1 | 184 | 1000 0 0 4 &mpic 4 1 |
170 | 185 | ||
171 | /* IDSEL 0x03 */ | 186 | /* IDSEL 0x03 */ |
172 | 1800 0 0 1 &mpic 34 1 | 187 | 1800 0 0 1 &mpic 4 1 |
173 | 1800 0 0 2 &mpic 31 1 | 188 | 1800 0 0 2 &mpic 1 1 |
174 | 1800 0 0 3 &mpic 32 1 | 189 | 1800 0 0 3 &mpic 2 1 |
175 | 1800 0 0 4 &mpic 33 1 | 190 | 1800 0 0 4 &mpic 3 1 |
176 | 191 | ||
177 | /* IDSEL 0x04 */ | 192 | /* IDSEL 0x04 */ |
178 | 2000 0 0 1 &mpic 33 1 | 193 | 2000 0 0 1 &mpic 3 1 |
179 | 2000 0 0 2 &mpic 34 1 | 194 | 2000 0 0 2 &mpic 4 1 |
180 | 2000 0 0 3 &mpic 31 1 | 195 | 2000 0 0 3 &mpic 1 1 |
181 | 2000 0 0 4 &mpic 32 1 | 196 | 2000 0 0 4 &mpic 2 1 |
182 | 197 | ||
183 | /* IDSEL 0x05 */ | 198 | /* IDSEL 0x05 */ |
184 | 2800 0 0 1 &mpic 32 1 | 199 | 2800 0 0 1 &mpic 2 1 |
185 | 2800 0 0 2 &mpic 33 1 | 200 | 2800 0 0 2 &mpic 3 1 |
186 | 2800 0 0 3 &mpic 34 1 | 201 | 2800 0 0 3 &mpic 4 1 |
187 | 2800 0 0 4 &mpic 31 1 | 202 | 2800 0 0 4 &mpic 1 1 |
188 | 203 | ||
189 | /* IDSEL 0x0c */ | 204 | /* IDSEL 0x0c */ |
190 | 6000 0 0 1 &mpic 31 1 | 205 | 6000 0 0 1 &mpic 1 1 |
191 | 6000 0 0 2 &mpic 32 1 | 206 | 6000 0 0 2 &mpic 2 1 |
192 | 6000 0 0 3 &mpic 33 1 | 207 | 6000 0 0 3 &mpic 3 1 |
193 | 6000 0 0 4 &mpic 34 1 | 208 | 6000 0 0 4 &mpic 4 1 |
194 | 209 | ||
195 | /* IDSEL 0x0d */ | 210 | /* IDSEL 0x0d */ |
196 | 6800 0 0 1 &mpic 34 1 | 211 | 6800 0 0 1 &mpic 4 1 |
197 | 6800 0 0 2 &mpic 31 1 | 212 | 6800 0 0 2 &mpic 1 1 |
198 | 6800 0 0 3 &mpic 32 1 | 213 | 6800 0 0 3 &mpic 2 1 |
199 | 6800 0 0 4 &mpic 33 1 | 214 | 6800 0 0 4 &mpic 3 1 |
200 | 215 | ||
201 | /* IDSEL 0x0e */ | 216 | /* IDSEL 0x0e */ |
202 | 7000 0 0 1 &mpic 33 1 | 217 | 7000 0 0 1 &mpic 3 1 |
203 | 7000 0 0 2 &mpic 34 1 | 218 | 7000 0 0 2 &mpic 4 1 |
204 | 7000 0 0 3 &mpic 31 1 | 219 | 7000 0 0 3 &mpic 1 1 |
205 | 7000 0 0 4 &mpic 32 1 | 220 | 7000 0 0 4 &mpic 2 1 |
206 | 221 | ||
207 | /* IDSEL 0x0f */ | 222 | /* IDSEL 0x0f */ |
208 | 7800 0 0 1 &mpic 32 1 | 223 | 7800 0 0 1 &mpic 2 1 |
209 | 7800 0 0 2 &mpic 33 1 | 224 | 7800 0 0 2 &mpic 3 1 |
210 | 7800 0 0 3 &mpic 34 1 | 225 | 7800 0 0 3 &mpic 4 1 |
211 | 7800 0 0 4 &mpic 31 1 | 226 | 7800 0 0 4 &mpic 1 1 |
212 | 227 | ||
213 | /* IDSEL 0x12 */ | 228 | /* IDSEL 0x12 */ |
214 | 9000 0 0 1 &mpic 31 1 | 229 | 9000 0 0 1 &mpic 1 1 |
215 | 9000 0 0 2 &mpic 32 1 | 230 | 9000 0 0 2 &mpic 2 1 |
216 | 9000 0 0 3 &mpic 33 1 | 231 | 9000 0 0 3 &mpic 3 1 |
217 | 9000 0 0 4 &mpic 34 1 | 232 | 9000 0 0 4 &mpic 4 1 |
218 | 233 | ||
219 | /* IDSEL 0x13 */ | 234 | /* IDSEL 0x13 */ |
220 | 9800 0 0 1 &mpic 34 1 | 235 | 9800 0 0 1 &mpic 4 1 |
221 | 9800 0 0 2 &mpic 31 1 | 236 | 9800 0 0 2 &mpic 1 1 |
222 | 9800 0 0 3 &mpic 32 1 | 237 | 9800 0 0 3 &mpic 2 1 |
223 | 9800 0 0 4 &mpic 33 1 | 238 | 9800 0 0 4 &mpic 3 1 |
224 | 239 | ||
225 | /* IDSEL 0x14 */ | 240 | /* IDSEL 0x14 */ |
226 | a000 0 0 1 &mpic 33 1 | 241 | a000 0 0 1 &mpic 3 1 |
227 | a000 0 0 2 &mpic 34 1 | 242 | a000 0 0 2 &mpic 4 1 |
228 | a000 0 0 3 &mpic 31 1 | 243 | a000 0 0 3 &mpic 1 1 |
229 | a000 0 0 4 &mpic 32 1 | 244 | a000 0 0 4 &mpic 2 1 |
230 | 245 | ||
231 | /* IDSEL 0x15 */ | 246 | /* IDSEL 0x15 */ |
232 | a800 0 0 1 &mpic 32 1 | 247 | a800 0 0 1 &mpic 2 1 |
233 | a800 0 0 2 &mpic 33 1 | 248 | a800 0 0 2 &mpic 3 1 |
234 | a800 0 0 3 &mpic 34 1 | 249 | a800 0 0 3 &mpic 4 1 |
235 | a800 0 0 4 &mpic 31 1>; | 250 | a800 0 0 4 &mpic 1 1>; |
236 | interrupt-parent = <&mpic>; | 251 | interrupt-parent = <&mpic>; |
237 | interrupts = <08 2>; | 252 | interrupts = <18 2>; |
238 | bus-range = <0 0>; | 253 | bus-range = <0 0>; |
239 | ranges = <02000000 0 80000000 80000000 0 20000000 | 254 | ranges = <02000000 0 80000000 80000000 0 20000000 |
240 | 01000000 0 00000000 e2000000 0 00100000>; | 255 | 01000000 0 00000000 e2000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts index 4f2c3af2e052..070206fffe88 100644 --- a/arch/powerpc/boot/dts/mpc8541cds.dts +++ b/arch/powerpc/boot/dts/mpc8541cds.dts | |||
@@ -52,7 +52,7 @@ | |||
52 | compatible = "fsl,8541-memory-controller"; | 52 | compatible = "fsl,8541-memory-controller"; |
53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
@@ -61,14 +61,14 @@ | |||
61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | i2c@3000 { | 67 | i2c@3000 { |
68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
73 | dfsrr; | 73 | dfsrr; |
74 | }; | 74 | }; |
@@ -81,13 +81,13 @@ | |||
81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
84 | interrupts = <35 0>; | 84 | interrupts = <5 1>; |
85 | reg = <0>; | 85 | reg = <0>; |
86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
87 | }; | 87 | }; |
88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
90 | interrupts = <35 0>; | 90 | interrupts = <5 1>; |
91 | reg = <1>; | 91 | reg = <1>; |
92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
93 | }; | 93 | }; |
@@ -100,8 +100,8 @@ | |||
100 | model = "TSEC"; | 100 | model = "TSEC"; |
101 | compatible = "gianfar"; | 101 | compatible = "gianfar"; |
102 | reg = <24000 1000>; | 102 | reg = <24000 1000>; |
103 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 103 | local-mac-address = [ 00 00 00 00 00 00 ]; |
104 | interrupts = <d 2 e 2 12 2>; | 104 | interrupts = <1d 2 1e 2 22 2>; |
105 | interrupt-parent = <&mpic>; | 105 | interrupt-parent = <&mpic>; |
106 | phy-handle = <&phy0>; | 106 | phy-handle = <&phy0>; |
107 | }; | 107 | }; |
@@ -113,8 +113,8 @@ | |||
113 | model = "TSEC"; | 113 | model = "TSEC"; |
114 | compatible = "gianfar"; | 114 | compatible = "gianfar"; |
115 | reg = <25000 1000>; | 115 | reg = <25000 1000>; |
116 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 116 | local-mac-address = [ 00 00 00 00 00 00 ]; |
117 | interrupts = <13 2 14 2 18 2>; | 117 | interrupts = <23 2 24 2 28 2>; |
118 | interrupt-parent = <&mpic>; | 118 | interrupt-parent = <&mpic>; |
119 | phy-handle = <&phy1>; | 119 | phy-handle = <&phy1>; |
120 | }; | 120 | }; |
@@ -124,7 +124,7 @@ | |||
124 | compatible = "ns16550"; | 124 | compatible = "ns16550"; |
125 | reg = <4500 100>; // reg base, size | 125 | reg = <4500 100>; // reg base, size |
126 | clock-frequency = <0>; // should we fill in in uboot? | 126 | clock-frequency = <0>; // should we fill in in uboot? |
127 | interrupts = <1a 2>; | 127 | interrupts = <2a 2>; |
128 | interrupt-parent = <&mpic>; | 128 | interrupt-parent = <&mpic>; |
129 | }; | 129 | }; |
130 | 130 | ||
@@ -133,7 +133,7 @@ | |||
133 | compatible = "ns16550"; | 133 | compatible = "ns16550"; |
134 | reg = <4600 100>; // reg base, size | 134 | reg = <4600 100>; // reg base, size |
135 | clock-frequency = <0>; // should we fill in in uboot? | 135 | clock-frequency = <0>; // should we fill in in uboot? |
136 | interrupts = <1a 2>; | 136 | interrupts = <2a 2>; |
137 | interrupt-parent = <&mpic>; | 137 | interrupt-parent = <&mpic>; |
138 | }; | 138 | }; |
139 | 139 | ||
@@ -142,49 +142,49 @@ | |||
142 | interrupt-map = < | 142 | interrupt-map = < |
143 | 143 | ||
144 | /* IDSEL 0x10 */ | 144 | /* IDSEL 0x10 */ |
145 | 08000 0 0 1 &mpic 30 1 | 145 | 08000 0 0 1 &mpic 0 1 |
146 | 08000 0 0 2 &mpic 31 1 | 146 | 08000 0 0 2 &mpic 1 1 |
147 | 08000 0 0 3 &mpic 32 1 | 147 | 08000 0 0 3 &mpic 2 1 |
148 | 08000 0 0 4 &mpic 33 1 | 148 | 08000 0 0 4 &mpic 3 1 |
149 | 149 | ||
150 | /* IDSEL 0x11 */ | 150 | /* IDSEL 0x11 */ |
151 | 08800 0 0 1 &mpic 30 1 | 151 | 08800 0 0 1 &mpic 0 1 |
152 | 08800 0 0 2 &mpic 31 1 | 152 | 08800 0 0 2 &mpic 1 1 |
153 | 08800 0 0 3 &mpic 32 1 | 153 | 08800 0 0 3 &mpic 2 1 |
154 | 08800 0 0 4 &mpic 33 1 | 154 | 08800 0 0 4 &mpic 3 1 |
155 | 155 | ||
156 | /* IDSEL 0x12 (Slot 1) */ | 156 | /* IDSEL 0x12 (Slot 1) */ |
157 | 09000 0 0 1 &mpic 30 1 | 157 | 09000 0 0 1 &mpic 0 1 |
158 | 09000 0 0 2 &mpic 31 1 | 158 | 09000 0 0 2 &mpic 1 1 |
159 | 09000 0 0 3 &mpic 32 1 | 159 | 09000 0 0 3 &mpic 2 1 |
160 | 09000 0 0 4 &mpic 33 1 | 160 | 09000 0 0 4 &mpic 3 1 |
161 | 161 | ||
162 | /* IDSEL 0x13 (Slot 2) */ | 162 | /* IDSEL 0x13 (Slot 2) */ |
163 | 09800 0 0 1 &mpic 31 1 | 163 | 09800 0 0 1 &mpic 1 1 |
164 | 09800 0 0 2 &mpic 32 1 | 164 | 09800 0 0 2 &mpic 2 1 |
165 | 09800 0 0 3 &mpic 33 1 | 165 | 09800 0 0 3 &mpic 3 1 |
166 | 09800 0 0 4 &mpic 30 1 | 166 | 09800 0 0 4 &mpic 0 1 |
167 | 167 | ||
168 | /* IDSEL 0x14 (Slot 3) */ | 168 | /* IDSEL 0x14 (Slot 3) */ |
169 | 0a000 0 0 1 &mpic 32 1 | 169 | 0a000 0 0 1 &mpic 2 1 |
170 | 0a000 0 0 2 &mpic 33 1 | 170 | 0a000 0 0 2 &mpic 3 1 |
171 | 0a000 0 0 3 &mpic 30 1 | 171 | 0a000 0 0 3 &mpic 0 1 |
172 | 0a000 0 0 4 &mpic 31 1 | 172 | 0a000 0 0 4 &mpic 1 1 |
173 | 173 | ||
174 | /* IDSEL 0x15 (Slot 4) */ | 174 | /* IDSEL 0x15 (Slot 4) */ |
175 | 0a800 0 0 1 &mpic 33 1 | 175 | 0a800 0 0 1 &mpic 3 1 |
176 | 0a800 0 0 2 &mpic 30 1 | 176 | 0a800 0 0 2 &mpic 0 1 |
177 | 0a800 0 0 3 &mpic 31 1 | 177 | 0a800 0 0 3 &mpic 1 1 |
178 | 0a800 0 0 4 &mpic 32 1 | 178 | 0a800 0 0 4 &mpic 2 1 |
179 | 179 | ||
180 | /* Bus 1 (Tundra Bridge) */ | 180 | /* Bus 1 (Tundra Bridge) */ |
181 | /* IDSEL 0x12 (ISA bridge) */ | 181 | /* IDSEL 0x12 (ISA bridge) */ |
182 | 19000 0 0 1 &mpic 30 1 | 182 | 19000 0 0 1 &mpic 0 1 |
183 | 19000 0 0 2 &mpic 31 1 | 183 | 19000 0 0 2 &mpic 1 1 |
184 | 19000 0 0 3 &mpic 32 1 | 184 | 19000 0 0 3 &mpic 2 1 |
185 | 19000 0 0 4 &mpic 33 1>; | 185 | 19000 0 0 4 &mpic 3 1>; |
186 | interrupt-parent = <&mpic>; | 186 | interrupt-parent = <&mpic>; |
187 | interrupts = <08 2>; | 187 | interrupts = <18 2>; |
188 | bus-range = <0 0>; | 188 | bus-range = <0 0>; |
189 | ranges = <02000000 0 80000000 80000000 0 20000000 | 189 | ranges = <02000000 0 80000000 80000000 0 20000000 |
190 | 01000000 0 00000000 e2000000 0 00100000>; | 190 | 01000000 0 00000000 e2000000 0 00100000>; |
@@ -216,12 +216,12 @@ | |||
216 | interrupt-map = < | 216 | interrupt-map = < |
217 | 217 | ||
218 | /* IDSEL 0x15 */ | 218 | /* IDSEL 0x15 */ |
219 | a800 0 0 1 &mpic 3b 1 | 219 | a800 0 0 1 &mpic b 1 |
220 | a800 0 0 2 &mpic 3b 1 | 220 | a800 0 0 2 &mpic b 1 |
221 | a800 0 0 3 &mpic 3b 1 | 221 | a800 0 0 3 &mpic b 1 |
222 | a800 0 0 4 &mpic 3b 1>; | 222 | a800 0 0 4 &mpic b 1>; |
223 | interrupt-parent = <&mpic>; | 223 | interrupt-parent = <&mpic>; |
224 | interrupts = <09 2>; | 224 | interrupts = <19 2>; |
225 | bus-range = <0 0>; | 225 | bus-range = <0 0>; |
226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 | 226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 |
227 | 01000000 0 00000000 e3000000 0 00100000>; | 227 | 01000000 0 00000000 e3000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts index 3033599e74e8..828592592460 100644 --- a/arch/powerpc/boot/dts/mpc8544ds.dts +++ b/arch/powerpc/boot/dts/mpc8544ds.dts | |||
@@ -52,7 +52,7 @@ | |||
52 | compatible = "fsl,8544-memory-controller"; | 52 | compatible = "fsl,8544-memory-controller"; |
53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
@@ -61,14 +61,14 @@ | |||
61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | i2c@3000 { | 67 | i2c@3000 { |
68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
73 | dfsrr; | 73 | dfsrr; |
74 | }; | 74 | }; |
@@ -81,13 +81,13 @@ | |||
81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
84 | interrupts = <3a 1>; | 84 | interrupts = <a 1>; |
85 | reg = <0>; | 85 | reg = <0>; |
86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
87 | }; | 87 | }; |
88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
90 | interrupts = <3a 1>; | 90 | interrupts = <a 1>; |
91 | reg = <1>; | 91 | reg = <1>; |
92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
93 | }; | 93 | }; |
@@ -101,7 +101,7 @@ | |||
101 | compatible = "gianfar"; | 101 | compatible = "gianfar"; |
102 | reg = <24000 1000>; | 102 | reg = <24000 1000>; |
103 | local-mac-address = [ 00 00 00 00 00 00 ]; | 103 | local-mac-address = [ 00 00 00 00 00 00 ]; |
104 | interrupts = <d 2 e 2 12 2>; | 104 | interrupts = <1d 2 1e 2 22 2>; |
105 | interrupt-parent = <&mpic>; | 105 | interrupt-parent = <&mpic>; |
106 | phy-handle = <&phy0>; | 106 | phy-handle = <&phy0>; |
107 | }; | 107 | }; |
@@ -114,7 +114,7 @@ | |||
114 | compatible = "gianfar"; | 114 | compatible = "gianfar"; |
115 | reg = <26000 1000>; | 115 | reg = <26000 1000>; |
116 | local-mac-address = [ 00 00 00 00 00 00 ]; | 116 | local-mac-address = [ 00 00 00 00 00 00 ]; |
117 | interrupts = <f 2 10 2 11 2>; | 117 | interrupts = <1f 2 20 2 21 2>; |
118 | interrupt-parent = <&mpic>; | 118 | interrupt-parent = <&mpic>; |
119 | phy-handle = <&phy1>; | 119 | phy-handle = <&phy1>; |
120 | }; | 120 | }; |
@@ -124,7 +124,7 @@ | |||
124 | compatible = "ns16550"; | 124 | compatible = "ns16550"; |
125 | reg = <4500 100>; | 125 | reg = <4500 100>; |
126 | clock-frequency = <0>; | 126 | clock-frequency = <0>; |
127 | interrupts = <1a 2>; | 127 | interrupts = <2a 2>; |
128 | interrupt-parent = <&mpic>; | 128 | interrupt-parent = <&mpic>; |
129 | }; | 129 | }; |
130 | 130 | ||
@@ -133,7 +133,7 @@ | |||
133 | compatible = "ns16550"; | 133 | compatible = "ns16550"; |
134 | reg = <4600 100>; | 134 | reg = <4600 100>; |
135 | clock-frequency = <0>; | 135 | clock-frequency = <0>; |
136 | interrupts = <1a 2>; | 136 | interrupts = <2a 2>; |
137 | interrupt-parent = <&mpic>; | 137 | interrupt-parent = <&mpic>; |
138 | }; | 138 | }; |
139 | 139 | ||
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts index ad96381033c0..9d0b84b66cd4 100644 --- a/arch/powerpc/boot/dts/mpc8548cds.dts +++ b/arch/powerpc/boot/dts/mpc8548cds.dts | |||
@@ -52,7 +52,7 @@ | |||
52 | compatible = "fsl,8548-memory-controller"; | 52 | compatible = "fsl,8548-memory-controller"; |
53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
@@ -61,14 +61,14 @@ | |||
61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
62 | cache-size = <80000>; // L2, 512K | 62 | cache-size = <80000>; // L2, 512K |
63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | i2c@3000 { | 67 | i2c@3000 { |
68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
73 | dfsrr; | 73 | dfsrr; |
74 | }; | 74 | }; |
@@ -81,25 +81,25 @@ | |||
81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
84 | interrupts = <35 0>; | 84 | interrupts = <5 1>; |
85 | reg = <0>; | 85 | reg = <0>; |
86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
87 | }; | 87 | }; |
88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
90 | interrupts = <35 0>; | 90 | interrupts = <5 1>; |
91 | reg = <1>; | 91 | reg = <1>; |
92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
93 | }; | 93 | }; |
94 | phy2: ethernet-phy@2 { | 94 | phy2: ethernet-phy@2 { |
95 | interrupt-parent = <&mpic>; | 95 | interrupt-parent = <&mpic>; |
96 | interrupts = <35 0>; | 96 | interrupts = <5 1>; |
97 | reg = <2>; | 97 | reg = <2>; |
98 | device_type = "ethernet-phy"; | 98 | device_type = "ethernet-phy"; |
99 | }; | 99 | }; |
100 | phy3: ethernet-phy@3 { | 100 | phy3: ethernet-phy@3 { |
101 | interrupt-parent = <&mpic>; | 101 | interrupt-parent = <&mpic>; |
102 | interrupts = <35 0>; | 102 | interrupts = <5 1>; |
103 | reg = <3>; | 103 | reg = <3>; |
104 | device_type = "ethernet-phy"; | 104 | device_type = "ethernet-phy"; |
105 | }; | 105 | }; |
@@ -112,8 +112,8 @@ | |||
112 | model = "eTSEC"; | 112 | model = "eTSEC"; |
113 | compatible = "gianfar"; | 113 | compatible = "gianfar"; |
114 | reg = <24000 1000>; | 114 | reg = <24000 1000>; |
115 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 115 | local-mac-address = [ 00 00 00 00 00 00 ]; |
116 | interrupts = <d 2 e 2 12 2>; | 116 | interrupts = <1d 2 1e 2 22 2>; |
117 | interrupt-parent = <&mpic>; | 117 | interrupt-parent = <&mpic>; |
118 | phy-handle = <&phy0>; | 118 | phy-handle = <&phy0>; |
119 | }; | 119 | }; |
@@ -125,8 +125,8 @@ | |||
125 | model = "eTSEC"; | 125 | model = "eTSEC"; |
126 | compatible = "gianfar"; | 126 | compatible = "gianfar"; |
127 | reg = <25000 1000>; | 127 | reg = <25000 1000>; |
128 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 128 | local-mac-address = [ 00 00 00 00 00 00 ]; |
129 | interrupts = <13 2 14 2 18 2>; | 129 | interrupts = <23 2 24 2 28 2>; |
130 | interrupt-parent = <&mpic>; | 130 | interrupt-parent = <&mpic>; |
131 | phy-handle = <&phy1>; | 131 | phy-handle = <&phy1>; |
132 | }; | 132 | }; |
@@ -139,8 +139,8 @@ | |||
139 | model = "eTSEC"; | 139 | model = "eTSEC"; |
140 | compatible = "gianfar"; | 140 | compatible = "gianfar"; |
141 | reg = <26000 1000>; | 141 | reg = <26000 1000>; |
142 | local-mac-address = [ 00 E0 0C 00 73 02 ]; | 142 | local-mac-address = [ 00 00 00 00 00 00 ]; |
143 | interrupts = <f 2 10 2 11 2>; | 143 | interrupts = <1f 2 20 2 21 2>; |
144 | interrupt-parent = <&mpic>; | 144 | interrupt-parent = <&mpic>; |
145 | phy-handle = <&phy2>; | 145 | phy-handle = <&phy2>; |
146 | }; | 146 | }; |
@@ -152,8 +152,8 @@ | |||
152 | model = "eTSEC"; | 152 | model = "eTSEC"; |
153 | compatible = "gianfar"; | 153 | compatible = "gianfar"; |
154 | reg = <27000 1000>; | 154 | reg = <27000 1000>; |
155 | local-mac-address = [ 00 E0 0C 00 73 03 ]; | 155 | local-mac-address = [ 00 00 00 00 00 00 ]; |
156 | interrupts = <15 2 16 2 17 2>; | 156 | interrupts = <25 2 26 2 27 2>; |
157 | interrupt-parent = <&mpic>; | 157 | interrupt-parent = <&mpic>; |
158 | phy-handle = <&phy3>; | 158 | phy-handle = <&phy3>; |
159 | }; | 159 | }; |
@@ -164,7 +164,7 @@ | |||
164 | compatible = "ns16550"; | 164 | compatible = "ns16550"; |
165 | reg = <4500 100>; // reg base, size | 165 | reg = <4500 100>; // reg base, size |
166 | clock-frequency = <0>; // should we fill in in uboot? | 166 | clock-frequency = <0>; // should we fill in in uboot? |
167 | interrupts = <1a 2>; | 167 | interrupts = <2a 2>; |
168 | interrupt-parent = <&mpic>; | 168 | interrupt-parent = <&mpic>; |
169 | }; | 169 | }; |
170 | 170 | ||
@@ -173,58 +173,64 @@ | |||
173 | compatible = "ns16550"; | 173 | compatible = "ns16550"; |
174 | reg = <4600 100>; // reg base, size | 174 | reg = <4600 100>; // reg base, size |
175 | clock-frequency = <0>; // should we fill in in uboot? | 175 | clock-frequency = <0>; // should we fill in in uboot? |
176 | interrupts = <1a 2>; | 176 | interrupts = <2a 2>; |
177 | interrupt-parent = <&mpic>; | 177 | interrupt-parent = <&mpic>; |
178 | }; | 178 | }; |
179 | 179 | ||
180 | global-utilities@e0000 { //global utilities reg | ||
181 | compatible = "fsl,mpc8548-guts"; | ||
182 | reg = <e0000 1000>; | ||
183 | fsl,has-rstcr; | ||
184 | }; | ||
185 | |||
180 | pci1: pci@8000 { | 186 | pci1: pci@8000 { |
181 | interrupt-map-mask = <1f800 0 0 7>; | 187 | interrupt-map-mask = <1f800 0 0 7>; |
182 | interrupt-map = < | 188 | interrupt-map = < |
183 | 189 | ||
184 | /* IDSEL 0x10 */ | 190 | /* IDSEL 0x10 */ |
185 | 08000 0 0 1 &mpic 30 1 | 191 | 08000 0 0 1 &mpic 0 1 |
186 | 08000 0 0 2 &mpic 31 1 | 192 | 08000 0 0 2 &mpic 1 1 |
187 | 08000 0 0 3 &mpic 32 1 | 193 | 08000 0 0 3 &mpic 2 1 |
188 | 08000 0 0 4 &mpic 33 1 | 194 | 08000 0 0 4 &mpic 3 1 |
189 | 195 | ||
190 | /* IDSEL 0x11 */ | 196 | /* IDSEL 0x11 */ |
191 | 08800 0 0 1 &mpic 30 1 | 197 | 08800 0 0 1 &mpic 0 1 |
192 | 08800 0 0 2 &mpic 31 1 | 198 | 08800 0 0 2 &mpic 1 1 |
193 | 08800 0 0 3 &mpic 32 1 | 199 | 08800 0 0 3 &mpic 2 1 |
194 | 08800 0 0 4 &mpic 33 1 | 200 | 08800 0 0 4 &mpic 3 1 |
195 | 201 | ||
196 | /* IDSEL 0x12 (Slot 1) */ | 202 | /* IDSEL 0x12 (Slot 1) */ |
197 | 09000 0 0 1 &mpic 30 1 | 203 | 09000 0 0 1 &mpic 0 1 |
198 | 09000 0 0 2 &mpic 31 1 | 204 | 09000 0 0 2 &mpic 1 1 |
199 | 09000 0 0 3 &mpic 32 1 | 205 | 09000 0 0 3 &mpic 2 1 |
200 | 09000 0 0 4 &mpic 33 1 | 206 | 09000 0 0 4 &mpic 3 1 |
201 | 207 | ||
202 | /* IDSEL 0x13 (Slot 2) */ | 208 | /* IDSEL 0x13 (Slot 2) */ |
203 | 09800 0 0 1 &mpic 31 1 | 209 | 09800 0 0 1 &mpic 1 1 |
204 | 09800 0 0 2 &mpic 32 1 | 210 | 09800 0 0 2 &mpic 2 1 |
205 | 09800 0 0 3 &mpic 33 1 | 211 | 09800 0 0 3 &mpic 3 1 |
206 | 09800 0 0 4 &mpic 30 1 | 212 | 09800 0 0 4 &mpic 0 1 |
207 | 213 | ||
208 | /* IDSEL 0x14 (Slot 3) */ | 214 | /* IDSEL 0x14 (Slot 3) */ |
209 | 0a000 0 0 1 &mpic 32 1 | 215 | 0a000 0 0 1 &mpic 2 1 |
210 | 0a000 0 0 2 &mpic 33 1 | 216 | 0a000 0 0 2 &mpic 3 1 |
211 | 0a000 0 0 3 &mpic 30 1 | 217 | 0a000 0 0 3 &mpic 0 1 |
212 | 0a000 0 0 4 &mpic 31 1 | 218 | 0a000 0 0 4 &mpic 1 1 |
213 | 219 | ||
214 | /* IDSEL 0x15 (Slot 4) */ | 220 | /* IDSEL 0x15 (Slot 4) */ |
215 | 0a800 0 0 1 &mpic 33 1 | 221 | 0a800 0 0 1 &mpic 3 1 |
216 | 0a800 0 0 2 &mpic 30 1 | 222 | 0a800 0 0 2 &mpic 0 1 |
217 | 0a800 0 0 3 &mpic 31 1 | 223 | 0a800 0 0 3 &mpic 1 1 |
218 | 0a800 0 0 4 &mpic 32 1 | 224 | 0a800 0 0 4 &mpic 2 1 |
219 | 225 | ||
220 | /* Bus 1 (Tundra Bridge) */ | 226 | /* Bus 1 (Tundra Bridge) */ |
221 | /* IDSEL 0x12 (ISA bridge) */ | 227 | /* IDSEL 0x12 (ISA bridge) */ |
222 | 19000 0 0 1 &mpic 30 1 | 228 | 19000 0 0 1 &mpic 0 1 |
223 | 19000 0 0 2 &mpic 31 1 | 229 | 19000 0 0 2 &mpic 1 1 |
224 | 19000 0 0 3 &mpic 32 1 | 230 | 19000 0 0 3 &mpic 2 1 |
225 | 19000 0 0 4 &mpic 33 1>; | 231 | 19000 0 0 4 &mpic 3 1>; |
226 | interrupt-parent = <&mpic>; | 232 | interrupt-parent = <&mpic>; |
227 | interrupts = <08 2>; | 233 | interrupts = <18 2>; |
228 | bus-range = <0 0>; | 234 | bus-range = <0 0>; |
229 | ranges = <02000000 0 80000000 80000000 0 20000000 | 235 | ranges = <02000000 0 80000000 80000000 0 20000000 |
230 | 01000000 0 00000000 e2000000 0 00100000>; | 236 | 01000000 0 00000000 e2000000 0 00100000>; |
@@ -256,12 +262,12 @@ | |||
256 | interrupt-map = < | 262 | interrupt-map = < |
257 | 263 | ||
258 | /* IDSEL 0x15 */ | 264 | /* IDSEL 0x15 */ |
259 | a800 0 0 1 &mpic 3b 1 | 265 | a800 0 0 1 &mpic b 1 |
260 | a800 0 0 2 &mpic 3b 1 | 266 | a800 0 0 2 &mpic b 1 |
261 | a800 0 0 3 &mpic 3b 1 | 267 | a800 0 0 3 &mpic b 1 |
262 | a800 0 0 4 &mpic 3b 1>; | 268 | a800 0 0 4 &mpic b 1>; |
263 | interrupt-parent = <&mpic>; | 269 | interrupt-parent = <&mpic>; |
264 | interrupts = <09 2>; | 270 | interrupts = <19 2>; |
265 | bus-range = <0 0>; | 271 | bus-range = <0 0>; |
266 | ranges = <02000000 0 a0000000 a0000000 0 20000000 | 272 | ranges = <02000000 0 a0000000 a0000000 0 20000000 |
267 | 01000000 0 00000000 e3000000 0 00100000>; | 273 | 01000000 0 00000000 e3000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts index 951ed92f1154..17e45d9a382a 100644 --- a/arch/powerpc/boot/dts/mpc8555cds.dts +++ b/arch/powerpc/boot/dts/mpc8555cds.dts | |||
@@ -52,7 +52,7 @@ | |||
52 | compatible = "fsl,8555-memory-controller"; | 52 | compatible = "fsl,8555-memory-controller"; |
53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
@@ -61,14 +61,14 @@ | |||
61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | i2c@3000 { | 67 | i2c@3000 { |
68 | device_type = "i2c"; | 68 | device_type = "i2c"; |
69 | compatible = "fsl-i2c"; | 69 | compatible = "fsl-i2c"; |
70 | reg = <3000 100>; | 70 | reg = <3000 100>; |
71 | interrupts = <1b 2>; | 71 | interrupts = <2b 2>; |
72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
73 | dfsrr; | 73 | dfsrr; |
74 | }; | 74 | }; |
@@ -81,13 +81,13 @@ | |||
81 | reg = <24520 20>; | 81 | reg = <24520 20>; |
82 | phy0: ethernet-phy@0 { | 82 | phy0: ethernet-phy@0 { |
83 | interrupt-parent = <&mpic>; | 83 | interrupt-parent = <&mpic>; |
84 | interrupts = <35 0>; | 84 | interrupts = <5 1>; |
85 | reg = <0>; | 85 | reg = <0>; |
86 | device_type = "ethernet-phy"; | 86 | device_type = "ethernet-phy"; |
87 | }; | 87 | }; |
88 | phy1: ethernet-phy@1 { | 88 | phy1: ethernet-phy@1 { |
89 | interrupt-parent = <&mpic>; | 89 | interrupt-parent = <&mpic>; |
90 | interrupts = <35 0>; | 90 | interrupts = <5 1>; |
91 | reg = <1>; | 91 | reg = <1>; |
92 | device_type = "ethernet-phy"; | 92 | device_type = "ethernet-phy"; |
93 | }; | 93 | }; |
@@ -100,8 +100,8 @@ | |||
100 | model = "TSEC"; | 100 | model = "TSEC"; |
101 | compatible = "gianfar"; | 101 | compatible = "gianfar"; |
102 | reg = <24000 1000>; | 102 | reg = <24000 1000>; |
103 | local-mac-address = [ 00 E0 0C 00 73 00 ]; | 103 | local-mac-address = [ 00 00 00 00 00 00 ]; |
104 | interrupts = <0d 2 0e 2 12 2>; | 104 | interrupts = <1d 2 1e 2 22 2>; |
105 | interrupt-parent = <&mpic>; | 105 | interrupt-parent = <&mpic>; |
106 | phy-handle = <&phy0>; | 106 | phy-handle = <&phy0>; |
107 | }; | 107 | }; |
@@ -113,8 +113,8 @@ | |||
113 | model = "TSEC"; | 113 | model = "TSEC"; |
114 | compatible = "gianfar"; | 114 | compatible = "gianfar"; |
115 | reg = <25000 1000>; | 115 | reg = <25000 1000>; |
116 | local-mac-address = [ 00 E0 0C 00 73 01 ]; | 116 | local-mac-address = [ 00 00 00 00 00 00 ]; |
117 | interrupts = <13 2 14 2 18 2>; | 117 | interrupts = <23 2 24 2 28 2>; |
118 | interrupt-parent = <&mpic>; | 118 | interrupt-parent = <&mpic>; |
119 | phy-handle = <&phy1>; | 119 | phy-handle = <&phy1>; |
120 | }; | 120 | }; |
@@ -124,7 +124,7 @@ | |||
124 | compatible = "ns16550"; | 124 | compatible = "ns16550"; |
125 | reg = <4500 100>; // reg base, size | 125 | reg = <4500 100>; // reg base, size |
126 | clock-frequency = <0>; // should we fill in in uboot? | 126 | clock-frequency = <0>; // should we fill in in uboot? |
127 | interrupts = <1a 2>; | 127 | interrupts = <2a 2>; |
128 | interrupt-parent = <&mpic>; | 128 | interrupt-parent = <&mpic>; |
129 | }; | 129 | }; |
130 | 130 | ||
@@ -133,7 +133,7 @@ | |||
133 | compatible = "ns16550"; | 133 | compatible = "ns16550"; |
134 | reg = <4600 100>; // reg base, size | 134 | reg = <4600 100>; // reg base, size |
135 | clock-frequency = <0>; // should we fill in in uboot? | 135 | clock-frequency = <0>; // should we fill in in uboot? |
136 | interrupts = <1a 2>; | 136 | interrupts = <2a 2>; |
137 | interrupt-parent = <&mpic>; | 137 | interrupt-parent = <&mpic>; |
138 | }; | 138 | }; |
139 | 139 | ||
@@ -142,49 +142,49 @@ | |||
142 | interrupt-map = < | 142 | interrupt-map = < |
143 | 143 | ||
144 | /* IDSEL 0x10 */ | 144 | /* IDSEL 0x10 */ |
145 | 08000 0 0 1 &mpic 30 1 | 145 | 08000 0 0 1 &mpic 0 1 |
146 | 08000 0 0 2 &mpic 31 1 | 146 | 08000 0 0 2 &mpic 1 1 |
147 | 08000 0 0 3 &mpic 32 1 | 147 | 08000 0 0 3 &mpic 2 1 |
148 | 08000 0 0 4 &mpic 33 1 | 148 | 08000 0 0 4 &mpic 3 1 |
149 | 149 | ||
150 | /* IDSEL 0x11 */ | 150 | /* IDSEL 0x11 */ |
151 | 08800 0 0 1 &mpic 30 1 | 151 | 08800 0 0 1 &mpic 0 1 |
152 | 08800 0 0 2 &mpic 31 1 | 152 | 08800 0 0 2 &mpic 1 1 |
153 | 08800 0 0 3 &mpic 32 1 | 153 | 08800 0 0 3 &mpic 2 1 |
154 | 08800 0 0 4 &mpic 33 1 | 154 | 08800 0 0 4 &mpic 3 1 |
155 | 155 | ||
156 | /* IDSEL 0x12 (Slot 1) */ | 156 | /* IDSEL 0x12 (Slot 1) */ |
157 | 09000 0 0 1 &mpic 30 1 | 157 | 09000 0 0 1 &mpic 0 1 |
158 | 09000 0 0 2 &mpic 31 1 | 158 | 09000 0 0 2 &mpic 1 1 |
159 | 09000 0 0 3 &mpic 32 1 | 159 | 09000 0 0 3 &mpic 2 1 |
160 | 09000 0 0 4 &mpic 33 1 | 160 | 09000 0 0 4 &mpic 3 1 |
161 | 161 | ||
162 | /* IDSEL 0x13 (Slot 2) */ | 162 | /* IDSEL 0x13 (Slot 2) */ |
163 | 09800 0 0 1 &mpic 31 1 | 163 | 09800 0 0 1 &mpic 1 1 |
164 | 09800 0 0 2 &mpic 32 1 | 164 | 09800 0 0 2 &mpic 2 1 |
165 | 09800 0 0 3 &mpic 33 1 | 165 | 09800 0 0 3 &mpic 3 1 |
166 | 09800 0 0 4 &mpic 30 1 | 166 | 09800 0 0 4 &mpic 0 1 |
167 | 167 | ||
168 | /* IDSEL 0x14 (Slot 3) */ | 168 | /* IDSEL 0x14 (Slot 3) */ |
169 | 0a000 0 0 1 &mpic 32 1 | 169 | 0a000 0 0 1 &mpic 2 1 |
170 | 0a000 0 0 2 &mpic 33 1 | 170 | 0a000 0 0 2 &mpic 3 1 |
171 | 0a000 0 0 3 &mpic 30 1 | 171 | 0a000 0 0 3 &mpic 0 1 |
172 | 0a000 0 0 4 &mpic 31 1 | 172 | 0a000 0 0 4 &mpic 1 1 |
173 | 173 | ||
174 | /* IDSEL 0x15 (Slot 4) */ | 174 | /* IDSEL 0x15 (Slot 4) */ |
175 | 0a800 0 0 1 &mpic 33 1 | 175 | 0a800 0 0 1 &mpic 3 1 |
176 | 0a800 0 0 2 &mpic 30 1 | 176 | 0a800 0 0 2 &mpic 0 1 |
177 | 0a800 0 0 3 &mpic 31 1 | 177 | 0a800 0 0 3 &mpic 1 1 |
178 | 0a800 0 0 4 &mpic 32 1 | 178 | 0a800 0 0 4 &mpic 2 1 |
179 | 179 | ||
180 | /* Bus 1 (Tundra Bridge) */ | 180 | /* Bus 1 (Tundra Bridge) */ |
181 | /* IDSEL 0x12 (ISA bridge) */ | 181 | /* IDSEL 0x12 (ISA bridge) */ |
182 | 19000 0 0 1 &mpic 30 1 | 182 | 19000 0 0 1 &mpic 0 1 |
183 | 19000 0 0 2 &mpic 31 1 | 183 | 19000 0 0 2 &mpic 1 1 |
184 | 19000 0 0 3 &mpic 32 1 | 184 | 19000 0 0 3 &mpic 2 1 |
185 | 19000 0 0 4 &mpic 33 1>; | 185 | 19000 0 0 4 &mpic 3 1>; |
186 | interrupt-parent = <&mpic>; | 186 | interrupt-parent = <&mpic>; |
187 | interrupts = <08 2>; | 187 | interrupts = <18 2>; |
188 | bus-range = <0 0>; | 188 | bus-range = <0 0>; |
189 | ranges = <02000000 0 80000000 80000000 0 20000000 | 189 | ranges = <02000000 0 80000000 80000000 0 20000000 |
190 | 01000000 0 00000000 e2000000 0 00100000>; | 190 | 01000000 0 00000000 e2000000 0 00100000>; |
@@ -216,12 +216,12 @@ | |||
216 | interrupt-map = < | 216 | interrupt-map = < |
217 | 217 | ||
218 | /* IDSEL 0x15 */ | 218 | /* IDSEL 0x15 */ |
219 | a800 0 0 1 &mpic 3b 1 | 219 | a800 0 0 1 &mpic b 1 |
220 | a800 0 0 2 &mpic 3b 1 | 220 | a800 0 0 2 &mpic b 1 |
221 | a800 0 0 3 &mpic 3b 1 | 221 | a800 0 0 3 &mpic b 1 |
222 | a800 0 0 4 &mpic 3b 1>; | 222 | a800 0 0 4 &mpic b 1>; |
223 | interrupt-parent = <&mpic>; | 223 | interrupt-parent = <&mpic>; |
224 | interrupts = <09 2>; | 224 | interrupts = <19 2>; |
225 | bus-range = <0 0>; | 225 | bus-range = <0 0>; |
226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 | 226 | ranges = <02000000 0 a0000000 a0000000 0 20000000 |
227 | 01000000 0 00000000 e3000000 0 00100000>; | 227 | 01000000 0 00000000 e3000000 0 00100000>; |
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts index 80682152b0cf..21ccaaa27993 100644 --- a/arch/powerpc/boot/dts/mpc8560ads.dts +++ b/arch/powerpc/boot/dts/mpc8560ads.dts | |||
@@ -52,7 +52,7 @@ | |||
52 | compatible = "fsl,8540-memory-controller"; | 52 | compatible = "fsl,8540-memory-controller"; |
53 | reg = <2000 1000>; | 53 | reg = <2000 1000>; |
54 | interrupt-parent = <&mpic>; | 54 | interrupt-parent = <&mpic>; |
55 | interrupts = <2 2>; | 55 | interrupts = <12 2>; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | l2-cache-controller@20000 { | 58 | l2-cache-controller@20000 { |
@@ -61,7 +61,7 @@ | |||
61 | cache-line-size = <20>; // 32 bytes | 61 | cache-line-size = <20>; // 32 bytes |
62 | cache-size = <40000>; // L2, 256K | 62 | cache-size = <40000>; // L2, 256K |
63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
64 | interrupts = <0 2>; | 64 | interrupts = <10 2>; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | mdio@24520 { | 67 | mdio@24520 { |
@@ -72,25 +72,25 @@ | |||
72 | #size-cells = <0>; | 72 | #size-cells = <0>; |
73 | phy0: ethernet-phy@0 { | 73 | phy0: ethernet-phy@0 { |
74 | interrupt-parent = <&mpic>; | 74 | interrupt-parent = <&mpic>; |
75 | interrupts = <35 1>; | 75 | interrupts = <5 1>; |
76 | reg = <0>; | 76 | reg = <0>; |
77 | device_type = "ethernet-phy"; | 77 | device_type = "ethernet-phy"; |
78 | }; | 78 | }; |
79 | phy1: ethernet-phy@1 { | 79 | phy1: ethernet-phy@1 { |
80 | interrupt-parent = <&mpic>; | 80 | interrupt-parent = <&mpic>; |
81 | interrupts = <35 1>; | 81 | interrupts = <5 1>; |
82 | reg = <1>; | 82 | reg = <1>; |
83 | device_type = "ethernet-phy"; | 83 | device_type = "ethernet-phy"; |
84 | }; | 84 | }; |
85 | phy2: ethernet-phy@2 { | 85 | phy2: ethernet-phy@2 { |
86 | interrupt-parent = <&mpic>; | 86 | interrupt-parent = <&mpic>; |
87 | interrupts = <37 1>; | 87 | interrupts = <7 1>; |
88 | reg = <2>; | 88 | reg = <2>; |
89 | device_type = "ethernet-phy"; | 89 | device_type = "ethernet-phy"; |
90 | }; | 90 | }; |
91 | phy3: ethernet-phy@3 { | 91 | phy3: ethernet-phy@3 { |
92 | interrupt-parent = <&mpic>; | 92 | interrupt-parent = <&mpic>; |
93 | interrupts = <37 1>; | 93 | interrupts = <7 1>; |
94 | reg = <3>; | 94 | reg = <3>; |
95 | device_type = "ethernet-phy"; | 95 | device_type = "ethernet-phy"; |
96 | }; | 96 | }; |
@@ -101,8 +101,14 @@ | |||
101 | model = "TSEC"; | 101 | model = "TSEC"; |
102 | compatible = "gianfar"; | 102 | compatible = "gianfar"; |
103 | reg = <24000 1000>; | 103 | reg = <24000 1000>; |
104 | address = [ 00 00 0C 00 00 FD ]; | 104 | /* |
105 | interrupts = <d 2 e 2 12 2>; | 105 | * address is deprecated and will be removed |
106 | * in 2.6.25. Only recent versions of | ||
107 | * U-Boot support local-mac-address, however. | ||
108 | */ | ||
109 | address = [ 00 00 00 00 00 00 ]; | ||
110 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
111 | interrupts = <1d 2 1e 2 22 2>; | ||
106 | interrupt-parent = <&mpic>; | 112 | interrupt-parent = <&mpic>; |
107 | phy-handle = <&phy0>; | 113 | phy-handle = <&phy0>; |
108 | }; | 114 | }; |
@@ -114,8 +120,14 @@ | |||
114 | model = "TSEC"; | 120 | model = "TSEC"; |
115 | compatible = "gianfar"; | 121 | compatible = "gianfar"; |
116 | reg = <25000 1000>; | 122 | reg = <25000 1000>; |
117 | address = [ 00 00 0C 00 01 FD ]; | 123 | /* |
118 | interrupts = <13 2 14 2 18 2>; | 124 | * address is deprecated and will be removed |
125 | * in 2.6.25. Only recent versions of | ||
126 | * U-Boot support local-mac-address, however. | ||
127 | */ | ||
128 | address = [ 00 00 00 00 00 00 ]; | ||
129 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
130 | interrupts = <23 2 24 2 28 2>; | ||
119 | interrupt-parent = <&mpic>; | 131 | interrupt-parent = <&mpic>; |
120 | phy-handle = <&phy1>; | 132 | phy-handle = <&phy1>; |
121 | }; | 133 | }; |
@@ -132,79 +144,79 @@ | |||
132 | interrupt-map = < | 144 | interrupt-map = < |
133 | 145 | ||
134 | /* IDSEL 0x2 */ | 146 | /* IDSEL 0x2 */ |
135 | 1000 0 0 1 &mpic 31 1 | 147 | 1000 0 0 1 &mpic 1 1 |
136 | 1000 0 0 2 &mpic 32 1 | 148 | 1000 0 0 2 &mpic 2 1 |
137 | 1000 0 0 3 &mpic 33 1 | 149 | 1000 0 0 3 &mpic 3 1 |
138 | 1000 0 0 4 &mpic 34 1 | 150 | 1000 0 0 4 &mpic 4 1 |
139 | 151 | ||
140 | /* IDSEL 0x3 */ | 152 | /* IDSEL 0x3 */ |
141 | 1800 0 0 1 &mpic 34 1 | 153 | 1800 0 0 1 &mpic 4 1 |
142 | 1800 0 0 2 &mpic 31 1 | 154 | 1800 0 0 2 &mpic 1 1 |
143 | 1800 0 0 3 &mpic 32 1 | 155 | 1800 0 0 3 &mpic 2 1 |
144 | 1800 0 0 4 &mpic 33 1 | 156 | 1800 0 0 4 &mpic 3 1 |
145 | 157 | ||
146 | /* IDSEL 0x4 */ | 158 | /* IDSEL 0x4 */ |
147 | 2000 0 0 1 &mpic 33 1 | 159 | 2000 0 0 1 &mpic 3 1 |
148 | 2000 0 0 2 &mpic 34 1 | 160 | 2000 0 0 2 &mpic 4 1 |
149 | 2000 0 0 3 &mpic 31 1 | 161 | 2000 0 0 3 &mpic 1 1 |
150 | 2000 0 0 4 &mpic 32 1 | 162 | 2000 0 0 4 &mpic 2 1 |
151 | 163 | ||
152 | /* IDSEL 0x5 */ | 164 | /* IDSEL 0x5 */ |
153 | 2800 0 0 1 &mpic 32 1 | 165 | 2800 0 0 1 &mpic 2 1 |
154 | 2800 0 0 2 &mpic 33 1 | 166 | 2800 0 0 2 &mpic 3 1 |
155 | 2800 0 0 3 &mpic 34 1 | 167 | 2800 0 0 3 &mpic 4 1 |
156 | 2800 0 0 4 &mpic 31 1 | 168 | 2800 0 0 4 &mpic 1 1 |
157 | 169 | ||
158 | /* IDSEL 12 */ | 170 | /* IDSEL 12 */ |
159 | 6000 0 0 1 &mpic 31 1 | 171 | 6000 0 0 1 &mpic 1 1 |
160 | 6000 0 0 2 &mpic 32 1 | 172 | 6000 0 0 2 &mpic 2 1 |
161 | 6000 0 0 3 &mpic 33 1 | 173 | 6000 0 0 3 &mpic 3 1 |
162 | 6000 0 0 4 &mpic 34 1 | 174 | 6000 0 0 4 &mpic 4 1 |
163 | 175 | ||
164 | /* IDSEL 13 */ | 176 | /* IDSEL 13 */ |
165 | 6800 0 0 1 &mpic 34 1 | 177 | 6800 0 0 1 &mpic 4 1 |
166 | 6800 0 0 2 &mpic 31 1 | 178 | 6800 0 0 2 &mpic 1 1 |
167 | 6800 0 0 3 &mpic 32 1 | 179 | 6800 0 0 3 &mpic 2 1 |
168 | 6800 0 0 4 &mpic 33 1 | 180 | 6800 0 0 4 &mpic 3 1 |
169 | 181 | ||
170 | /* IDSEL 14*/ | 182 | /* IDSEL 14*/ |
171 | 7000 0 0 1 &mpic 33 1 | 183 | 7000 0 0 1 &mpic 3 1 |
172 | 7000 0 0 2 &mpic 34 1 | 184 | 7000 0 0 2 &mpic 4 1 |
173 | 7000 0 0 3 &mpic 31 1 | 185 | 7000 0 0 3 &mpic 1 1 |
174 | 7000 0 0 4 &mpic 32 1 | 186 | 7000 0 0 4 &mpic 2 1 |
175 | 187 | ||
176 | /* IDSEL 15 */ | 188 | /* IDSEL 15 */ |
177 | 7800 0 0 1 &mpic 32 1 | 189 | 7800 0 0 1 &mpic 2 1 |
178 | 7800 0 0 2 &mpic 33 1 | 190 | 7800 0 0 2 &mpic 3 1 |
179 | 7800 0 0 3 &mpic 34 1 | 191 | 7800 0 0 3 &mpic 4 1 |
180 | 7800 0 0 4 &mpic 31 1 | 192 | 7800 0 0 4 &mpic 1 1 |
181 | 193 | ||
182 | /* IDSEL 18 */ | 194 | /* IDSEL 18 */ |
183 | 9000 0 0 1 &mpic 31 1 | 195 | 9000 0 0 1 &mpic 1 1 |
184 | 9000 0 0 2 &mpic 32 1 | 196 | 9000 0 0 2 &mpic 2 1 |
185 | 9000 0 0 3 &mpic 33 1 | 197 | 9000 0 0 3 &mpic 3 1 |
186 | 9000 0 0 4 &mpic 34 1 | 198 | 9000 0 0 4 &mpic 4 1 |
187 | 199 | ||
188 | /* IDSEL 19 */ | 200 | /* IDSEL 19 */ |
189 | 9800 0 0 1 &mpic 34 1 | 201 | 9800 0 0 1 &mpic 4 1 |
190 | 9800 0 0 2 &mpic 31 1 | 202 | 9800 0 0 2 &mpic 1 1 |
191 | 9800 0 0 3 &mpic 32 1 | 203 | 9800 0 0 3 &mpic 2 1 |
192 | 9800 0 0 4 &mpic 33 1 | 204 | 9800 0 0 4 &mpic 3 1 |
193 | 205 | ||
194 | /* IDSEL 20 */ | 206 | /* IDSEL 20 */ |
195 | a000 0 0 1 &mpic 33 1 | 207 | a000 0 0 1 &mpic 3 1 |
196 | a000 0 0 2 &mpic 34 1 | 208 | a000 0 0 2 &mpic 4 1 |
197 | a000 0 0 3 &mpic 31 1 | 209 | a000 0 0 3 &mpic 1 1 |
198 | a000 0 0 4 &mpic 32 1 | 210 | a000 0 0 4 &mpic 2 1 |
199 | 211 | ||
200 | /* IDSEL 21 */ | 212 | /* IDSEL 21 */ |
201 | a800 0 0 1 &mpic 32 1 | 213 | a800 0 0 1 &mpic 2 1 |
202 | a800 0 0 2 &mpic 33 1 | 214 | a800 0 0 2 &mpic 3 1 |
203 | a800 0 0 3 &mpic 34 1 | 215 | a800 0 0 3 &mpic 4 1 |
204 | a800 0 0 4 &mpic 31 1>; | 216 | a800 0 0 4 &mpic 1 1>; |
205 | 217 | ||
206 | interrupt-parent = <&mpic>; | 218 | interrupt-parent = <&mpic>; |
207 | interrupts = <8 0>; | 219 | interrupts = <18 2>; |
208 | bus-range = <0 0>; | 220 | bus-range = <0 0>; |
209 | ranges = <02000000 0 80000000 80000000 0 20000000 | 221 | ranges = <02000000 0 80000000 80000000 0 20000000 |
210 | 01000000 0 00000000 e2000000 0 01000000>; | 222 | 01000000 0 00000000 e2000000 0 01000000>; |
@@ -234,7 +246,7 @@ | |||
234 | interrupt-controller; | 246 | interrupt-controller; |
235 | #address-cells = <0>; | 247 | #address-cells = <0>; |
236 | #interrupt-cells = <2>; | 248 | #interrupt-cells = <2>; |
237 | interrupts = <1e 0>; | 249 | interrupts = <2e 2>; |
238 | interrupt-parent = <&mpic>; | 250 | interrupt-parent = <&mpic>; |
239 | reg = <90c00 80>; | 251 | reg = <90c00 80>; |
240 | built-in; | 252 | built-in; |
@@ -275,7 +287,13 @@ | |||
275 | model = "FCC"; | 287 | model = "FCC"; |
276 | device-id = <2>; | 288 | device-id = <2>; |
277 | reg = <91320 20 88500 100 913a0 30>; | 289 | reg = <91320 20 88500 100 913a0 30>; |
278 | mac-address = [ 00 00 0C 00 02 FD ]; | 290 | /* |
291 | * mac-address is deprecated and will be removed | ||
292 | * in 2.6.25. Only recent versions of | ||
293 | * U-Boot support local-mac-address, however. | ||
294 | */ | ||
295 | mac-address = [ 00 00 00 00 00 00 ]; | ||
296 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
279 | clock-setup = <ff00ffff 250000>; | 297 | clock-setup = <ff00ffff 250000>; |
280 | rx-clock = <15>; | 298 | rx-clock = <15>; |
281 | tx-clock = <16>; | 299 | tx-clock = <16>; |
@@ -290,7 +308,13 @@ | |||
290 | model = "FCC"; | 308 | model = "FCC"; |
291 | device-id = <3>; | 309 | device-id = <3>; |
292 | reg = <91340 20 88600 100 913d0 30>; | 310 | reg = <91340 20 88600 100 913d0 30>; |
293 | mac-address = [ 00 00 0C 00 03 FD ]; | 311 | /* |
312 | * mac-address is deprecated and will be removed | ||
313 | * in 2.6.25. Only recent versions of | ||
314 | * U-Boot support local-mac-address, however. | ||
315 | */ | ||
316 | mac-address = [ 00 00 00 00 00 00 ]; | ||
317 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
294 | clock-setup = <ffff00ff 3700>; | 318 | clock-setup = <ffff00ff 3700>; |
295 | rx-clock = <17>; | 319 | rx-clock = <17>; |
296 | tx-clock = <18>; | 320 | tx-clock = <18>; |
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index a123ec9456bc..6bb18f2807a8 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts | |||
@@ -61,7 +61,7 @@ | |||
61 | compatible = "fsl,8568-memory-controller"; | 61 | compatible = "fsl,8568-memory-controller"; |
62 | reg = <2000 1000>; | 62 | reg = <2000 1000>; |
63 | interrupt-parent = <&mpic>; | 63 | interrupt-parent = <&mpic>; |
64 | interrupts = <2 2>; | 64 | interrupts = <12 2>; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | l2-cache-controller@20000 { | 67 | l2-cache-controller@20000 { |
@@ -70,14 +70,14 @@ | |||
70 | cache-line-size = <20>; // 32 bytes | 70 | cache-line-size = <20>; // 32 bytes |
71 | cache-size = <80000>; // L2, 512K | 71 | cache-size = <80000>; // L2, 512K |
72 | interrupt-parent = <&mpic>; | 72 | interrupt-parent = <&mpic>; |
73 | interrupts = <0 2>; | 73 | interrupts = <10 2>; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | i2c@3000 { | 76 | i2c@3000 { |
77 | device_type = "i2c"; | 77 | device_type = "i2c"; |
78 | compatible = "fsl-i2c"; | 78 | compatible = "fsl-i2c"; |
79 | reg = <3000 100>; | 79 | reg = <3000 100>; |
80 | interrupts = <1b 2>; | 80 | interrupts = <2b 2>; |
81 | interrupt-parent = <&mpic>; | 81 | interrupt-parent = <&mpic>; |
82 | dfsrr; | 82 | dfsrr; |
83 | }; | 83 | }; |
@@ -86,7 +86,7 @@ | |||
86 | device_type = "i2c"; | 86 | device_type = "i2c"; |
87 | compatible = "fsl-i2c"; | 87 | compatible = "fsl-i2c"; |
88 | reg = <3100 100>; | 88 | reg = <3100 100>; |
89 | interrupts = <1b 2>; | 89 | interrupts = <2b 2>; |
90 | interrupt-parent = <&mpic>; | 90 | interrupt-parent = <&mpic>; |
91 | dfsrr; | 91 | dfsrr; |
92 | }; | 92 | }; |
@@ -99,25 +99,25 @@ | |||
99 | reg = <24520 20>; | 99 | reg = <24520 20>; |
100 | phy0: ethernet-phy@0 { | 100 | phy0: ethernet-phy@0 { |
101 | interrupt-parent = <&mpic>; | 101 | interrupt-parent = <&mpic>; |
102 | interrupts = <31 1>; | 102 | interrupts = <1 1>; |
103 | reg = <0>; | 103 | reg = <0>; |
104 | device_type = "ethernet-phy"; | 104 | device_type = "ethernet-phy"; |
105 | }; | 105 | }; |
106 | phy1: ethernet-phy@1 { | 106 | phy1: ethernet-phy@1 { |
107 | interrupt-parent = <&mpic>; | 107 | interrupt-parent = <&mpic>; |
108 | interrupts = <32 1>; | 108 | interrupts = <2 1>; |
109 | reg = <1>; | 109 | reg = <1>; |
110 | device_type = "ethernet-phy"; | 110 | device_type = "ethernet-phy"; |
111 | }; | 111 | }; |
112 | phy2: ethernet-phy@2 { | 112 | phy2: ethernet-phy@2 { |
113 | interrupt-parent = <&mpic>; | 113 | interrupt-parent = <&mpic>; |
114 | interrupts = <31 1>; | 114 | interrupts = <1 1>; |
115 | reg = <2>; | 115 | reg = <2>; |
116 | device_type = "ethernet-phy"; | 116 | device_type = "ethernet-phy"; |
117 | }; | 117 | }; |
118 | phy3: ethernet-phy@3 { | 118 | phy3: ethernet-phy@3 { |
119 | interrupt-parent = <&mpic>; | 119 | interrupt-parent = <&mpic>; |
120 | interrupts = <32 1>; | 120 | interrupts = <2 1>; |
121 | reg = <3>; | 121 | reg = <3>; |
122 | device_type = "ethernet-phy"; | 122 | device_type = "ethernet-phy"; |
123 | }; | 123 | }; |
@@ -130,8 +130,14 @@ | |||
130 | model = "eTSEC"; | 130 | model = "eTSEC"; |
131 | compatible = "gianfar"; | 131 | compatible = "gianfar"; |
132 | reg = <24000 1000>; | 132 | reg = <24000 1000>; |
133 | /* | ||
134 | * mac-address is deprecated and will be removed | ||
135 | * in 2.6.25. Only recent versions of | ||
136 | * U-Boot support local-mac-address, however. | ||
137 | */ | ||
133 | mac-address = [ 00 00 00 00 00 00 ]; | 138 | mac-address = [ 00 00 00 00 00 00 ]; |
134 | interrupts = <d 2 e 2 12 2>; | 139 | local-mac-address = [ 00 00 00 00 00 00 ]; |
140 | interrupts = <1d 2 1e 2 22 2>; | ||
135 | interrupt-parent = <&mpic>; | 141 | interrupt-parent = <&mpic>; |
136 | phy-handle = <&phy2>; | 142 | phy-handle = <&phy2>; |
137 | }; | 143 | }; |
@@ -143,8 +149,14 @@ | |||
143 | model = "eTSEC"; | 149 | model = "eTSEC"; |
144 | compatible = "gianfar"; | 150 | compatible = "gianfar"; |
145 | reg = <25000 1000>; | 151 | reg = <25000 1000>; |
146 | mac-address = [ 00 00 00 00 00 00]; | 152 | /* |
147 | interrupts = <13 2 14 2 18 2>; | 153 | * mac-address is deprecated and will be removed |
154 | * in 2.6.25. Only recent versions of | ||
155 | * U-Boot support local-mac-address, however. | ||
156 | */ | ||
157 | mac-address = [ 00 00 00 00 00 00 ]; | ||
158 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
159 | interrupts = <23 2 24 2 28 2>; | ||
148 | interrupt-parent = <&mpic>; | 160 | interrupt-parent = <&mpic>; |
149 | phy-handle = <&phy3>; | 161 | phy-handle = <&phy3>; |
150 | }; | 162 | }; |
@@ -154,7 +166,7 @@ | |||
154 | compatible = "ns16550"; | 166 | compatible = "ns16550"; |
155 | reg = <4500 100>; | 167 | reg = <4500 100>; |
156 | clock-frequency = <0>; | 168 | clock-frequency = <0>; |
157 | interrupts = <1a 2>; | 169 | interrupts = <2a 2>; |
158 | interrupt-parent = <&mpic>; | 170 | interrupt-parent = <&mpic>; |
159 | }; | 171 | }; |
160 | 172 | ||
@@ -163,7 +175,7 @@ | |||
163 | compatible = "ns16550"; | 175 | compatible = "ns16550"; |
164 | reg = <4600 100>; | 176 | reg = <4600 100>; |
165 | clock-frequency = <0>; | 177 | clock-frequency = <0>; |
166 | interrupts = <1a 2>; | 178 | interrupts = <2a 2>; |
167 | interrupt-parent = <&mpic>; | 179 | interrupt-parent = <&mpic>; |
168 | }; | 180 | }; |
169 | 181 | ||
@@ -172,7 +184,7 @@ | |||
172 | model = "SEC2"; | 184 | model = "SEC2"; |
173 | compatible = "talitos"; | 185 | compatible = "talitos"; |
174 | reg = <30000 f000>; | 186 | reg = <30000 f000>; |
175 | interrupts = <1d 2>; | 187 | interrupts = <2d 2>; |
176 | interrupt-parent = <&mpic>; | 188 | interrupt-parent = <&mpic>; |
177 | num-channels = <4>; | 189 | num-channels = <4>; |
178 | channel-fifo-len = <18>; | 190 | channel-fifo-len = <18>; |
@@ -300,7 +312,13 @@ | |||
300 | reg = <2000 200>; | 312 | reg = <2000 200>; |
301 | interrupts = <20>; | 313 | interrupts = <20>; |
302 | interrupt-parent = <&qeic>; | 314 | interrupt-parent = <&qeic>; |
303 | mac-address = [ 00 04 9f 00 23 23 ]; | 315 | /* |
316 | * mac-address is deprecated and will be removed | ||
317 | * in 2.6.25. Only recent versions of | ||
318 | * U-Boot support local-mac-address, however. | ||
319 | */ | ||
320 | mac-address = [ 00 00 00 00 00 00 ]; | ||
321 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
304 | rx-clock = <0>; | 322 | rx-clock = <0>; |
305 | tx-clock = <19>; | 323 | tx-clock = <19>; |
306 | phy-handle = <&qe_phy0>; | 324 | phy-handle = <&qe_phy0>; |
@@ -316,7 +334,13 @@ | |||
316 | reg = <3000 200>; | 334 | reg = <3000 200>; |
317 | interrupts = <21>; | 335 | interrupts = <21>; |
318 | interrupt-parent = <&qeic>; | 336 | interrupt-parent = <&qeic>; |
319 | mac-address = [ 00 11 22 33 44 55 ]; | 337 | /* |
338 | * mac-address is deprecated and will be removed | ||
339 | * in 2.6.25. Only recent versions of | ||
340 | * U-Boot support local-mac-address, however. | ||
341 | */ | ||
342 | mac-address = [ 00 00 00 00 00 00 ]; | ||
343 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
320 | rx-clock = <0>; | 344 | rx-clock = <0>; |
321 | tx-clock = <14>; | 345 | tx-clock = <14>; |
322 | phy-handle = <&qe_phy1>; | 346 | phy-handle = <&qe_phy1>; |
@@ -335,25 +359,25 @@ | |||
335 | * gianfar's MDIO bus */ | 359 | * gianfar's MDIO bus */ |
336 | qe_phy0: ethernet-phy@00 { | 360 | qe_phy0: ethernet-phy@00 { |
337 | interrupt-parent = <&mpic>; | 361 | interrupt-parent = <&mpic>; |
338 | interrupts = <31 1>; | 362 | interrupts = <1 1>; |
339 | reg = <0>; | 363 | reg = <0>; |
340 | device_type = "ethernet-phy"; | 364 | device_type = "ethernet-phy"; |
341 | }; | 365 | }; |
342 | qe_phy1: ethernet-phy@01 { | 366 | qe_phy1: ethernet-phy@01 { |
343 | interrupt-parent = <&mpic>; | 367 | interrupt-parent = <&mpic>; |
344 | interrupts = <32 1>; | 368 | interrupts = <2 1>; |
345 | reg = <1>; | 369 | reg = <1>; |
346 | device_type = "ethernet-phy"; | 370 | device_type = "ethernet-phy"; |
347 | }; | 371 | }; |
348 | qe_phy2: ethernet-phy@02 { | 372 | qe_phy2: ethernet-phy@02 { |
349 | interrupt-parent = <&mpic>; | 373 | interrupt-parent = <&mpic>; |
350 | interrupts = <31 1>; | 374 | interrupts = <1 1>; |
351 | reg = <2>; | 375 | reg = <2>; |
352 | device_type = "ethernet-phy"; | 376 | device_type = "ethernet-phy"; |
353 | }; | 377 | }; |
354 | qe_phy3: ethernet-phy@03 { | 378 | qe_phy3: ethernet-phy@03 { |
355 | interrupt-parent = <&mpic>; | 379 | interrupt-parent = <&mpic>; |
356 | interrupts = <32 1>; | 380 | interrupts = <2 1>; |
357 | reg = <3>; | 381 | reg = <3>; |
358 | device_type = "ethernet-phy"; | 382 | device_type = "ethernet-phy"; |
359 | }; | 383 | }; |
@@ -367,7 +391,7 @@ | |||
367 | reg = <80 80>; | 391 | reg = <80 80>; |
368 | built-in; | 392 | built-in; |
369 | big-endian; | 393 | big-endian; |
370 | interrupts = <1e 2 1e 2>; //high:30 low:30 | 394 | interrupts = <2e 2 2e 2>; //high:30 low:30 |
371 | interrupt-parent = <&mpic>; | 395 | interrupt-parent = <&mpic>; |
372 | }; | 396 | }; |
373 | 397 | ||
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts index 260b264c869e..6a78a2b37c08 100644 --- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts | |||
@@ -56,8 +56,12 @@ | |||
56 | #size-cells = <1>; | 56 | #size-cells = <1>; |
57 | #interrupt-cells = <2>; | 57 | #interrupt-cells = <2>; |
58 | device_type = "soc"; | 58 | device_type = "soc"; |
59 | ranges = <0 f8000000 00100000>; | 59 | ranges = <00001000 f8001000 000ff000 |
60 | reg = <f8000000 00100000>; // CCSRBAR 1M | 60 | 80000000 80000000 20000000 |
61 | e2000000 e2000000 00100000 | ||
62 | a0000000 a0000000 20000000 | ||
63 | e3000000 e3000000 00100000>; | ||
64 | reg = <f8000000 00001000>; // CCSRBAR | ||
61 | bus-frequency = <0>; | 65 | bus-frequency = <0>; |
62 | 66 | ||
63 | i2c@3000 { | 67 | i2c@3000 { |
@@ -86,25 +90,25 @@ | |||
86 | reg = <24520 20>; | 90 | reg = <24520 20>; |
87 | phy0: ethernet-phy@0 { | 91 | phy0: ethernet-phy@0 { |
88 | interrupt-parent = <&mpic>; | 92 | interrupt-parent = <&mpic>; |
89 | interrupts = <4a 1>; | 93 | interrupts = <a 1>; |
90 | reg = <0>; | 94 | reg = <0>; |
91 | device_type = "ethernet-phy"; | 95 | device_type = "ethernet-phy"; |
92 | }; | 96 | }; |
93 | phy1: ethernet-phy@1 { | 97 | phy1: ethernet-phy@1 { |
94 | interrupt-parent = <&mpic>; | 98 | interrupt-parent = <&mpic>; |
95 | interrupts = <4a 1>; | 99 | interrupts = <a 1>; |
96 | reg = <1>; | 100 | reg = <1>; |
97 | device_type = "ethernet-phy"; | 101 | device_type = "ethernet-phy"; |
98 | }; | 102 | }; |
99 | phy2: ethernet-phy@2 { | 103 | phy2: ethernet-phy@2 { |
100 | interrupt-parent = <&mpic>; | 104 | interrupt-parent = <&mpic>; |
101 | interrupts = <4a 1>; | 105 | interrupts = <a 1>; |
102 | reg = <2>; | 106 | reg = <2>; |
103 | device_type = "ethernet-phy"; | 107 | device_type = "ethernet-phy"; |
104 | }; | 108 | }; |
105 | phy3: ethernet-phy@3 { | 109 | phy3: ethernet-phy@3 { |
106 | interrupt-parent = <&mpic>; | 110 | interrupt-parent = <&mpic>; |
107 | interrupts = <4a 1>; | 111 | interrupts = <a 1>; |
108 | reg = <3>; | 112 | reg = <3>; |
109 | device_type = "ethernet-phy"; | 113 | device_type = "ethernet-phy"; |
110 | }; | 114 | }; |
@@ -117,10 +121,17 @@ | |||
117 | model = "TSEC"; | 121 | model = "TSEC"; |
118 | compatible = "gianfar"; | 122 | compatible = "gianfar"; |
119 | reg = <24000 1000>; | 123 | reg = <24000 1000>; |
120 | mac-address = [ 00 E0 0C 00 73 00 ]; | 124 | /* |
125 | * mac-address is deprecated and will be removed | ||
126 | * in 2.6.25. Only recent versions of | ||
127 | * U-Boot support local-mac-address, however. | ||
128 | */ | ||
129 | mac-address = [ 00 00 00 00 00 00 ]; | ||
130 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
121 | interrupts = <1d 2 1e 2 22 2>; | 131 | interrupts = <1d 2 1e 2 22 2>; |
122 | interrupt-parent = <&mpic>; | 132 | interrupt-parent = <&mpic>; |
123 | phy-handle = <&phy0>; | 133 | phy-handle = <&phy0>; |
134 | phy-connection-type = "rgmii-id"; | ||
124 | }; | 135 | }; |
125 | 136 | ||
126 | ethernet@25000 { | 137 | ethernet@25000 { |
@@ -130,10 +141,17 @@ | |||
130 | model = "TSEC"; | 141 | model = "TSEC"; |
131 | compatible = "gianfar"; | 142 | compatible = "gianfar"; |
132 | reg = <25000 1000>; | 143 | reg = <25000 1000>; |
133 | mac-address = [ 00 E0 0C 00 73 01 ]; | 144 | /* |
145 | * mac-address is deprecated and will be removed | ||
146 | * in 2.6.25. Only recent versions of | ||
147 | * U-Boot support local-mac-address, however. | ||
148 | */ | ||
149 | mac-address = [ 00 00 00 00 00 00 ]; | ||
150 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
134 | interrupts = <23 2 24 2 28 2>; | 151 | interrupts = <23 2 24 2 28 2>; |
135 | interrupt-parent = <&mpic>; | 152 | interrupt-parent = <&mpic>; |
136 | phy-handle = <&phy1>; | 153 | phy-handle = <&phy1>; |
154 | phy-connection-type = "rgmii-id"; | ||
137 | }; | 155 | }; |
138 | 156 | ||
139 | ethernet@26000 { | 157 | ethernet@26000 { |
@@ -143,10 +161,17 @@ | |||
143 | model = "TSEC"; | 161 | model = "TSEC"; |
144 | compatible = "gianfar"; | 162 | compatible = "gianfar"; |
145 | reg = <26000 1000>; | 163 | reg = <26000 1000>; |
146 | mac-address = [ 00 E0 0C 00 02 FD ]; | 164 | /* |
165 | * mac-address is deprecated and will be removed | ||
166 | * in 2.6.25. Only recent versions of | ||
167 | * U-Boot support local-mac-address, however. | ||
168 | */ | ||
169 | mac-address = [ 00 00 00 00 00 00 ]; | ||
170 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
147 | interrupts = <1F 2 20 2 21 2>; | 171 | interrupts = <1F 2 20 2 21 2>; |
148 | interrupt-parent = <&mpic>; | 172 | interrupt-parent = <&mpic>; |
149 | phy-handle = <&phy2>; | 173 | phy-handle = <&phy2>; |
174 | phy-connection-type = "rgmii-id"; | ||
150 | }; | 175 | }; |
151 | 176 | ||
152 | ethernet@27000 { | 177 | ethernet@27000 { |
@@ -156,10 +181,17 @@ | |||
156 | model = "TSEC"; | 181 | model = "TSEC"; |
157 | compatible = "gianfar"; | 182 | compatible = "gianfar"; |
158 | reg = <27000 1000>; | 183 | reg = <27000 1000>; |
159 | mac-address = [ 00 E0 0C 00 03 FD ]; | 184 | /* |
185 | * mac-address is deprecated and will be removed | ||
186 | * in 2.6.25. Only recent versions of | ||
187 | * U-Boot support local-mac-address, however. | ||
188 | */ | ||
189 | mac-address = [ 00 00 00 00 00 00 ]; | ||
190 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
160 | interrupts = <25 2 26 2 27 2>; | 191 | interrupts = <25 2 26 2 27 2>; |
161 | interrupt-parent = <&mpic>; | 192 | interrupt-parent = <&mpic>; |
162 | phy-handle = <&phy3>; | 193 | phy-handle = <&phy3>; |
194 | phy-connection-type = "rgmii-id"; | ||
163 | }; | 195 | }; |
164 | serial@4500 { | 196 | serial@4500 { |
165 | device_type = "serial"; | 197 | device_type = "serial"; |
@@ -186,7 +218,7 @@ | |||
186 | #size-cells = <2>; | 218 | #size-cells = <2>; |
187 | #address-cells = <3>; | 219 | #address-cells = <3>; |
188 | reg = <8000 1000>; | 220 | reg = <8000 1000>; |
189 | bus-range = <0 fe>; | 221 | bus-range = <0 ff>; |
190 | ranges = <02000000 0 80000000 80000000 0 20000000 | 222 | ranges = <02000000 0 80000000 80000000 0 20000000 |
191 | 01000000 0 00000000 e2000000 0 00100000>; | 223 | 01000000 0 00000000 e2000000 0 00100000>; |
192 | clock-frequency = <1fca055>; | 224 | clock-frequency = <1fca055>; |
@@ -285,17 +317,84 @@ | |||
285 | f800 0 0 3 &i8259 0 0 | 317 | f800 0 0 3 &i8259 0 0 |
286 | f800 0 0 4 &i8259 0 0 | 318 | f800 0 0 4 &i8259 0 0 |
287 | >; | 319 | >; |
288 | i8259: i8259@4d0 { | 320 | uli1575@0 { |
289 | clock-frequency = <0>; | 321 | reg = <0 0 0 0 0>; |
290 | interrupt-controller; | 322 | #size-cells = <2>; |
291 | device_type = "interrupt-controller"; | 323 | #address-cells = <3>; |
292 | #address-cells = <0>; | 324 | ranges = <02000000 0 80000000 |
293 | #interrupt-cells = <2>; | 325 | 02000000 0 80000000 |
294 | built-in; | 326 | 0 20000000 |
295 | compatible = "chrp,iic"; | 327 | 01000000 0 00000000 |
296 | big-endian; | 328 | 01000000 0 00000000 |
297 | interrupts = <49 2>; | 329 | 0 00100000>; |
298 | interrupt-parent = <&mpic>; | 330 | |
331 | pci_bridge@0 { | ||
332 | reg = <0 0 0 0 0>; | ||
333 | #size-cells = <2>; | ||
334 | #address-cells = <3>; | ||
335 | ranges = <02000000 0 80000000 | ||
336 | 02000000 0 80000000 | ||
337 | 0 20000000 | ||
338 | 01000000 0 00000000 | ||
339 | 01000000 0 00000000 | ||
340 | 0 00100000>; | ||
341 | |||
342 | isa@1e { | ||
343 | device_type = "isa"; | ||
344 | #interrupt-cells = <2>; | ||
345 | #size-cells = <1>; | ||
346 | #address-cells = <2>; | ||
347 | reg = <f000 0 0 0 0>; | ||
348 | ranges = <1 0 01000000 0 0 | ||
349 | 00001000>; | ||
350 | interrupt-parent = <&i8259>; | ||
351 | |||
352 | i8259: interrupt-controller@20 { | ||
353 | reg = <1 20 2 | ||
354 | 1 a0 2 | ||
355 | 1 4d0 2>; | ||
356 | clock-frequency = <0>; | ||
357 | interrupt-controller; | ||
358 | device_type = "interrupt-controller"; | ||
359 | #address-cells = <0>; | ||
360 | #interrupt-cells = <2>; | ||
361 | built-in; | ||
362 | compatible = "chrp,iic"; | ||
363 | interrupts = <9 2>; | ||
364 | interrupt-parent = | ||
365 | <&mpic>; | ||
366 | }; | ||
367 | |||
368 | i8042@60 { | ||
369 | #size-cells = <0>; | ||
370 | #address-cells = <1>; | ||
371 | reg = <1 60 1 1 64 1>; | ||
372 | interrupts = <1 3 c 3>; | ||
373 | interrupt-parent = | ||
374 | <&i8259>; | ||
375 | |||
376 | keyboard@0 { | ||
377 | reg = <0>; | ||
378 | compatible = "pnpPNP,303"; | ||
379 | }; | ||
380 | |||
381 | mouse@1 { | ||
382 | reg = <1>; | ||
383 | compatible = "pnpPNP,f03"; | ||
384 | }; | ||
385 | }; | ||
386 | |||
387 | rtc@70 { | ||
388 | compatible = | ||
389 | "pnpPNP,b00"; | ||
390 | reg = <1 70 2>; | ||
391 | }; | ||
392 | |||
393 | gpio@400 { | ||
394 | reg = <1 400 80>; | ||
395 | }; | ||
396 | }; | ||
397 | }; | ||
299 | }; | 398 | }; |
300 | 399 | ||
301 | }; | 400 | }; |
@@ -316,10 +415,10 @@ | |||
316 | interrupt-map-mask = <f800 0 0 7>; | 415 | interrupt-map-mask = <f800 0 0 7>; |
317 | interrupt-map = < | 416 | interrupt-map = < |
318 | /* IDSEL 0x0 */ | 417 | /* IDSEL 0x0 */ |
319 | 0000 0 0 1 &mpic 44 1 | 418 | 0000 0 0 1 &mpic 4 1 |
320 | 0000 0 0 2 &mpic 45 1 | 419 | 0000 0 0 2 &mpic 5 1 |
321 | 0000 0 0 3 &mpic 46 1 | 420 | 0000 0 0 3 &mpic 6 1 |
322 | 0000 0 0 4 &mpic 47 1 | 421 | 0000 0 0 4 &mpic 7 1 |
323 | >; | 422 | >; |
324 | }; | 423 | }; |
325 | 424 | ||
diff --git a/arch/powerpc/boot/dts/mpc866ads.dts b/arch/powerpc/boot/dts/mpc866ads.dts index c0d06fd12927..e5e7726ddb03 100644 --- a/arch/powerpc/boot/dts/mpc866ads.dts +++ b/arch/powerpc/boot/dts/mpc866ads.dts | |||
@@ -15,12 +15,10 @@ | |||
15 | compatible = "mpc8xx"; | 15 | compatible = "mpc8xx"; |
16 | #address-cells = <1>; | 16 | #address-cells = <1>; |
17 | #size-cells = <1>; | 17 | #size-cells = <1>; |
18 | linux,phandle = <100>; | ||
19 | 18 | ||
20 | cpus { | 19 | cpus { |
21 | #address-cells = <1>; | 20 | #address-cells = <1>; |
22 | #size-cells = <0>; | 21 | #size-cells = <0>; |
23 | linux,phandle = <200>; | ||
24 | 22 | ||
25 | PowerPC,866@0 { | 23 | PowerPC,866@0 { |
26 | device_type = "cpu"; | 24 | device_type = "cpu"; |
@@ -34,14 +32,12 @@ | |||
34 | clock-frequency = <0>; | 32 | clock-frequency = <0>; |
35 | 32-bit; | 33 | 32-bit; |
36 | interrupts = <f 2>; // decrementer interrupt | 34 | interrupts = <f 2>; // decrementer interrupt |
37 | interrupt-parent = <ff000000>; | 35 | interrupt-parent = <&Mpc8xx_pic>; |
38 | linux,phandle = <201>; | ||
39 | }; | 36 | }; |
40 | }; | 37 | }; |
41 | 38 | ||
42 | memory { | 39 | memory { |
43 | device_type = "memory"; | 40 | device_type = "memory"; |
44 | linux,phandle = <300>; | ||
45 | reg = <00000000 800000>; | 41 | reg = <00000000 800000>; |
46 | }; | 42 | }; |
47 | 43 | ||
@@ -57,11 +53,9 @@ | |||
57 | device_type = "mdio"; | 53 | device_type = "mdio"; |
58 | compatible = "fs_enet"; | 54 | compatible = "fs_enet"; |
59 | reg = <e80 8>; | 55 | reg = <e80 8>; |
60 | linux,phandle = <e80>; | ||
61 | #address-cells = <1>; | 56 | #address-cells = <1>; |
62 | #size-cells = <0>; | 57 | #size-cells = <0>; |
63 | ethernet-phy@f { | 58 | phy: ethernet-phy@f { |
64 | linux,phandle = <e800f>; | ||
65 | reg = <f>; | 59 | reg = <f>; |
66 | device_type = "ethernet-phy"; | 60 | device_type = "ethernet-phy"; |
67 | }; | 61 | }; |
@@ -75,12 +69,11 @@ | |||
75 | reg = <e00 188>; | 69 | reg = <e00 188>; |
76 | mac-address = [ 00 00 0C 00 01 FD ]; | 70 | mac-address = [ 00 00 0C 00 01 FD ]; |
77 | interrupts = <3 1>; | 71 | interrupts = <3 1>; |
78 | interrupt-parent = <ff000000>; | 72 | interrupt-parent = <&Mpc8xx_pic>; |
79 | phy-handle = <e800f>; | 73 | phy-handle = <&Phy>; |
80 | }; | 74 | }; |
81 | 75 | ||
82 | pic@ff000000 { | 76 | mpc8xx_pic: pic@ff000000 { |
83 | linux,phandle = <ff000000>; | ||
84 | interrupt-controller; | 77 | interrupt-controller; |
85 | #address-cells = <0>; | 78 | #address-cells = <0>; |
86 | #interrupt-cells = <2>; | 79 | #interrupt-cells = <2>; |
@@ -91,7 +84,6 @@ | |||
91 | }; | 84 | }; |
92 | 85 | ||
93 | cpm@ff000000 { | 86 | cpm@ff000000 { |
94 | linux,phandle = <ff000000>; | ||
95 | #address-cells = <1>; | 87 | #address-cells = <1>; |
96 | #size-cells = <1>; | 88 | #size-cells = <1>; |
97 | #interrupt-cells = <2>; | 89 | #interrupt-cells = <2>; |
@@ -102,15 +94,14 @@ | |||
102 | command-proc = <9c0>; | 94 | command-proc = <9c0>; |
103 | brg-frequency = <0>; | 95 | brg-frequency = <0>; |
104 | interrupts = <0 2>; // cpm error interrupt | 96 | interrupts = <0 2>; // cpm error interrupt |
105 | interrupt-parent = <930>; | 97 | interrupt-parent = <&Cpm_pic>; |
106 | 98 | ||
107 | pic@930 { | 99 | cpm_pic: pic@930 { |
108 | linux,phandle = <930>; | ||
109 | interrupt-controller; | 100 | interrupt-controller; |
110 | #address-cells = <0>; | 101 | #address-cells = <0>; |
111 | #interrupt-cells = <2>; | 102 | #interrupt-cells = <2>; |
112 | interrupts = <5 2 0 2>; | 103 | interrupts = <5 2 0 2>; |
113 | interrupt-parent = <ff000000>; | 104 | interrupt-parent = <&Mpc8xx_pic>; |
114 | reg = <930 20>; | 105 | reg = <930 20>; |
115 | built-in; | 106 | built-in; |
116 | device_type = "cpm-pic"; | 107 | device_type = "cpm-pic"; |
@@ -128,7 +119,7 @@ | |||
128 | tx-clock = <1>; | 119 | tx-clock = <1>; |
129 | current-speed = <0>; | 120 | current-speed = <0>; |
130 | interrupts = <4 3>; | 121 | interrupts = <4 3>; |
131 | interrupt-parent = <930>; | 122 | interrupt-parent = <&Cpm_pic>; |
132 | }; | 123 | }; |
133 | 124 | ||
134 | smc@a90 { | 125 | smc@a90 { |
@@ -142,7 +133,7 @@ | |||
142 | tx-clock = <2>; | 133 | tx-clock = <2>; |
143 | current-speed = <0>; | 134 | current-speed = <0>; |
144 | interrupts = <3 3>; | 135 | interrupts = <3 3>; |
145 | interrupt-parent = <930>; | 136 | interrupt-parent = <&Cpm_pic>; |
146 | }; | 137 | }; |
147 | 138 | ||
148 | scc@a00 { | 139 | scc@a00 { |
@@ -153,7 +144,7 @@ | |||
153 | reg = <a00 18 3c00 80>; | 144 | reg = <a00 18 3c00 80>; |
154 | mac-address = [ 00 00 0C 00 03 FD ]; | 145 | mac-address = [ 00 00 0C 00 03 FD ]; |
155 | interrupts = <1e 3>; | 146 | interrupts = <1e 3>; |
156 | interrupt-parent = <930>; | 147 | interrupt-parent = <&Cpm_pic>; |
157 | }; | 148 | }; |
158 | }; | 149 | }; |
159 | }; | 150 | }; |
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts index 110bf6170603..dc7ab9c80611 100644 --- a/arch/powerpc/boot/dts/mpc885ads.dts +++ b/arch/powerpc/boot/dts/mpc885ads.dts | |||
@@ -15,12 +15,10 @@ | |||
15 | compatible = "mpc8xx"; | 15 | compatible = "mpc8xx"; |
16 | #address-cells = <1>; | 16 | #address-cells = <1>; |
17 | #size-cells = <1>; | 17 | #size-cells = <1>; |
18 | linux,phandle = <100>; | ||
19 | 18 | ||
20 | cpus { | 19 | cpus { |
21 | #address-cells = <1>; | 20 | #address-cells = <1>; |
22 | #size-cells = <0>; | 21 | #size-cells = <0>; |
23 | linux,phandle = <200>; | ||
24 | 22 | ||
25 | PowerPC,885@0 { | 23 | PowerPC,885@0 { |
26 | device_type = "cpu"; | 24 | device_type = "cpu"; |
@@ -34,14 +32,12 @@ | |||
34 | clock-frequency = <0>; | 32 | clock-frequency = <0>; |
35 | 32-bit; | 33 | 32-bit; |
36 | interrupts = <f 2>; // decrementer interrupt | 34 | interrupts = <f 2>; // decrementer interrupt |
37 | interrupt-parent = <ff000000>; | 35 | interrupt-parent = <&Mpc8xx_pic>; |
38 | linux,phandle = <201>; | ||
39 | }; | 36 | }; |
40 | }; | 37 | }; |
41 | 38 | ||
42 | memory { | 39 | memory { |
43 | device_type = "memory"; | 40 | device_type = "memory"; |
44 | linux,phandle = <300>; | ||
45 | reg = <00000000 800000>; | 41 | reg = <00000000 800000>; |
46 | }; | 42 | }; |
47 | 43 | ||
@@ -57,21 +53,17 @@ | |||
57 | device_type = "mdio"; | 53 | device_type = "mdio"; |
58 | compatible = "fs_enet"; | 54 | compatible = "fs_enet"; |
59 | reg = <e80 8>; | 55 | reg = <e80 8>; |
60 | linux,phandle = <e80>; | ||
61 | #address-cells = <1>; | 56 | #address-cells = <1>; |
62 | #size-cells = <0>; | 57 | #size-cells = <0>; |
63 | ethernet-phy@0 { | 58 | Phy0: ethernet-phy@0 { |
64 | linux,phandle = <e8000>; | ||
65 | reg = <0>; | 59 | reg = <0>; |
66 | device_type = "ethernet-phy"; | 60 | device_type = "ethernet-phy"; |
67 | }; | 61 | }; |
68 | ethernet-phy@1 { | 62 | Phy1: ethernet-phy@1 { |
69 | linux,phandle = <e8001>; | ||
70 | reg = <1>; | 63 | reg = <1>; |
71 | device_type = "ethernet-phy"; | 64 | device_type = "ethernet-phy"; |
72 | }; | 65 | }; |
73 | ethernet-phy@2 { | 66 | Phy2: ethernet-phy@2 { |
74 | linux,phandle = <e8002>; | ||
75 | reg = <2>; | 67 | reg = <2>; |
76 | device_type = "ethernet-phy"; | 68 | device_type = "ethernet-phy"; |
77 | }; | 69 | }; |
@@ -85,8 +77,8 @@ | |||
85 | reg = <e00 188>; | 77 | reg = <e00 188>; |
86 | mac-address = [ 00 00 0C 00 01 FD ]; | 78 | mac-address = [ 00 00 0C 00 01 FD ]; |
87 | interrupts = <3 1>; | 79 | interrupts = <3 1>; |
88 | interrupt-parent = <ff000000>; | 80 | interrupt-parent = <&Mpc8xx_pic>; |
89 | phy-handle = <e8000>; | 81 | phy-handle = <&Phy1>; |
90 | }; | 82 | }; |
91 | 83 | ||
92 | fec@1e00 { | 84 | fec@1e00 { |
@@ -97,12 +89,11 @@ | |||
97 | reg = <1e00 188>; | 89 | reg = <1e00 188>; |
98 | mac-address = [ 00 00 0C 00 02 FD ]; | 90 | mac-address = [ 00 00 0C 00 02 FD ]; |
99 | interrupts = <7 1>; | 91 | interrupts = <7 1>; |
100 | interrupt-parent = <ff000000>; | 92 | interrupt-parent = <&Mpc8xx_pic>; |
101 | phy-handle = <e8001>; | 93 | phy-handle = <&Phy2>; |
102 | }; | 94 | }; |
103 | 95 | ||
104 | pic@ff000000 { | 96 | Mpc8xx_pic: pic@ff000000 { |
105 | linux,phandle = <ff000000>; | ||
106 | interrupt-controller; | 97 | interrupt-controller; |
107 | #address-cells = <0>; | 98 | #address-cells = <0>; |
108 | #interrupt-cells = <2>; | 99 | #interrupt-cells = <2>; |
@@ -112,8 +103,18 @@ | |||
112 | compatible = "CPM"; | 103 | compatible = "CPM"; |
113 | }; | 104 | }; |
114 | 105 | ||
106 | pcmcia@0080 { | ||
107 | #address-cells = <3>; | ||
108 | #interrupt-cells = <1>; | ||
109 | #size-cells = <2>; | ||
110 | compatible = "fsl,pq-pcmcia"; | ||
111 | device_type = "pcmcia"; | ||
112 | reg = <80 80>; | ||
113 | interrupt-parent = <&Mpc8xx_pic>; | ||
114 | interrupts = <d 1>; | ||
115 | }; | ||
116 | |||
115 | cpm@ff000000 { | 117 | cpm@ff000000 { |
116 | linux,phandle = <ff000000>; | ||
117 | #address-cells = <1>; | 118 | #address-cells = <1>; |
118 | #size-cells = <1>; | 119 | #size-cells = <1>; |
119 | #interrupt-cells = <2>; | 120 | #interrupt-cells = <2>; |
@@ -124,15 +125,14 @@ | |||
124 | command-proc = <9c0>; | 125 | command-proc = <9c0>; |
125 | brg-frequency = <0>; | 126 | brg-frequency = <0>; |
126 | interrupts = <0 2>; // cpm error interrupt | 127 | interrupts = <0 2>; // cpm error interrupt |
127 | interrupt-parent = <930>; | 128 | interrupt-parent = <&Cpm_pic>; |
128 | 129 | ||
129 | pic@930 { | 130 | Cpm_pic: pic@930 { |
130 | linux,phandle = <930>; | ||
131 | interrupt-controller; | 131 | interrupt-controller; |
132 | #address-cells = <0>; | 132 | #address-cells = <0>; |
133 | #interrupt-cells = <2>; | 133 | #interrupt-cells = <2>; |
134 | interrupts = <5 2 0 2>; | 134 | interrupts = <5 2 0 2>; |
135 | interrupt-parent = <ff000000>; | 135 | interrupt-parent = <&Mpc8xx_pic>; |
136 | reg = <930 20>; | 136 | reg = <930 20>; |
137 | built-in; | 137 | built-in; |
138 | device_type = "cpm-pic"; | 138 | device_type = "cpm-pic"; |
@@ -150,7 +150,7 @@ | |||
150 | tx-clock = <1>; | 150 | tx-clock = <1>; |
151 | current-speed = <0>; | 151 | current-speed = <0>; |
152 | interrupts = <4 3>; | 152 | interrupts = <4 3>; |
153 | interrupt-parent = <930>; | 153 | interrupt-parent = <&Cpm_pic>; |
154 | }; | 154 | }; |
155 | 155 | ||
156 | smc@a90 { | 156 | smc@a90 { |
@@ -164,7 +164,7 @@ | |||
164 | tx-clock = <2>; | 164 | tx-clock = <2>; |
165 | current-speed = <0>; | 165 | current-speed = <0>; |
166 | interrupts = <3 3>; | 166 | interrupts = <3 3>; |
167 | interrupt-parent = <930>; | 167 | interrupt-parent = <&Cpm_pic>; |
168 | }; | 168 | }; |
169 | 169 | ||
170 | scc@a40 { | 170 | scc@a40 { |
@@ -175,8 +175,8 @@ | |||
175 | reg = <a40 18 3e00 80>; | 175 | reg = <a40 18 3e00 80>; |
176 | mac-address = [ 00 00 0C 00 03 FD ]; | 176 | mac-address = [ 00 00 0C 00 03 FD ]; |
177 | interrupts = <1c 3>; | 177 | interrupts = <1c 3>; |
178 | interrupt-parent = <930>; | 178 | interrupt-parent = <&Cpm_pic>; |
179 | phy-handle = <e8002>; | 179 | phy-handle = <&Phy2>; |
180 | }; | 180 | }; |
181 | }; | 181 | }; |
182 | }; | 182 | }; |
diff --git a/arch/powerpc/boot/dts/prpmc2800.dts b/arch/powerpc/boot/dts/prpmc2800.dts index 568965a022b9..699d0df574d5 100644 --- a/arch/powerpc/boot/dts/prpmc2800.dts +++ b/arch/powerpc/boot/dts/prpmc2800.dts | |||
@@ -309,7 +309,7 @@ | |||
309 | }; | 309 | }; |
310 | 310 | ||
311 | chosen { | 311 | chosen { |
312 | bootargs = "ip=on console=ttyMM0"; | 312 | bootargs = "ip=on"; |
313 | linux,stdout-path = "/mv64x60@f1000000/mpsc@8000"; | 313 | linux,stdout-path = "/mv64x60@f1000000/mpsc@8000"; |
314 | }; | 314 | }; |
315 | }; | 315 | }; |
diff --git a/arch/powerpc/boot/dts/ps3.dts b/arch/powerpc/boot/dts/ps3.dts new file mode 100644 index 000000000000..379ded282d5e --- /dev/null +++ b/arch/powerpc/boot/dts/ps3.dts | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * PS3 Game Console device tree. | ||
3 | * | ||
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2007 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | / { | ||
22 | model = "SonyPS3"; | ||
23 | compatible = "sony,ps3"; | ||
24 | #size-cells = <2>; | ||
25 | #address-cells = <2>; | ||
26 | |||
27 | chosen { | ||
28 | }; | ||
29 | |||
30 | /* | ||
31 | * We'll get the size of the bootmem block from lv1 after startup, | ||
32 | * so we'll put a null entry here. | ||
33 | */ | ||
34 | |||
35 | memory { | ||
36 | device_type = "memory"; | ||
37 | reg = <0 0 0 0>; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * The boot cpu is always zero for PS3. | ||
42 | * | ||
43 | * dtc expects a clock-frequency and timebase-frequency entries, so | ||
44 | * we'll put a null entries here. These will be initialized after | ||
45 | * startup with data from lv1. | ||
46 | * | ||
47 | * Seems the only way currently to indicate a processor has multiple | ||
48 | * threads is with an ibm,ppc-interrupt-server#s entry. We'll put one | ||
49 | * here so we can bring up both of ours. See smp_setup_cpu_maps(). | ||
50 | */ | ||
51 | |||
52 | cpus { | ||
53 | #size-cells = <0>; | ||
54 | #address-cells = <1>; | ||
55 | |||
56 | cpu@0 { | ||
57 | device_type = "cpu"; | ||
58 | reg = <0>; | ||
59 | ibm,ppc-interrupt-server#s = <0 1>; | ||
60 | clock-frequency = <0>; | ||
61 | timebase-frequency = <0>; | ||
62 | i-cache-size = <8000>; | ||
63 | d-cache-size = <8000>; | ||
64 | i-cache-line-size = <80>; | ||
65 | d-cache-line-size = <80>; | ||
66 | }; | ||
67 | }; | ||
68 | }; | ||
diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c index b1251ee7a102..75daedafd0a4 100644 --- a/arch/powerpc/boot/ebony.c +++ b/arch/powerpc/boot/ebony.c | |||
@@ -100,28 +100,13 @@ static void ebony_fixups(void) | |||
100 | ibm440gp_fixup_clocks(sysclk, 6 * 1843200); | 100 | ibm440gp_fixup_clocks(sysclk, 6 * 1843200); |
101 | ibm44x_fixup_memsize(); | 101 | ibm44x_fixup_memsize(); |
102 | dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); | 102 | dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); |
103 | } | 103 | ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); |
104 | |||
105 | #define SPRN_DBCR0 0x134 | ||
106 | #define DBCR0_RST_SYSTEM 0x30000000 | ||
107 | |||
108 | static void ebony_exit(void) | ||
109 | { | ||
110 | unsigned long tmp; | ||
111 | |||
112 | asm volatile ( | ||
113 | "mfspr %0,%1\n" | ||
114 | "oris %0,%0,%2@h\n" | ||
115 | "mtspr %1,%0" | ||
116 | : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) | ||
117 | ); | ||
118 | |||
119 | } | 104 | } |
120 | 105 | ||
121 | void ebony_init(void *mac0, void *mac1) | 106 | void ebony_init(void *mac0, void *mac1) |
122 | { | 107 | { |
123 | platform_ops.fixups = ebony_fixups; | 108 | platform_ops.fixups = ebony_fixups; |
124 | platform_ops.exit = ebony_exit; | 109 | platform_ops.exit = ibm44x_dbcr_reset; |
125 | ebony_mac0 = mac0; | 110 | ebony_mac0 = mac0; |
126 | ebony_mac1 = mac1; | 111 | ebony_mac1 = mac1; |
127 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); | 112 | ft_init(_dtb_start, _dtb_end - _dtb_start, 32); |
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 56b56a8d4b23..416dc3857bfe 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
@@ -36,8 +36,6 @@ struct addr_range { | |||
36 | unsigned long size; | 36 | unsigned long size; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); | ||
40 | |||
41 | #undef DEBUG | 39 | #undef DEBUG |
42 | 40 | ||
43 | static struct addr_range prep_kernel(void) | 41 | static struct addr_range prep_kernel(void) |
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index d16ee3e3f868..385e08b83b7e 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c | |||
@@ -15,8 +15,7 @@ | |||
15 | #include "page.h" | 15 | #include "page.h" |
16 | #include "ops.h" | 16 | #include "ops.h" |
17 | 17 | ||
18 | typedef void *ihandle; | 18 | #include "of.h" |
19 | typedef void *phandle; | ||
20 | 19 | ||
21 | extern char _end[]; | 20 | extern char _end[]; |
22 | 21 | ||
@@ -25,154 +24,10 @@ extern char _end[]; | |||
25 | #define RAM_END (512<<20) /* Fixme: use OF */ | 24 | #define RAM_END (512<<20) /* Fixme: use OF */ |
26 | #define ONE_MB 0x100000 | 25 | #define ONE_MB 0x100000 |
27 | 26 | ||
28 | int (*prom) (void *); | ||
29 | 27 | ||
30 | 28 | ||
31 | static unsigned long claim_base; | 29 | static unsigned long claim_base; |
32 | 30 | ||
33 | static int call_prom(const char *service, int nargs, int nret, ...) | ||
34 | { | ||
35 | int i; | ||
36 | struct prom_args { | ||
37 | const char *service; | ||
38 | int nargs; | ||
39 | int nret; | ||
40 | unsigned int args[12]; | ||
41 | } args; | ||
42 | va_list list; | ||
43 | |||
44 | args.service = service; | ||
45 | args.nargs = nargs; | ||
46 | args.nret = nret; | ||
47 | |||
48 | va_start(list, nret); | ||
49 | for (i = 0; i < nargs; i++) | ||
50 | args.args[i] = va_arg(list, unsigned int); | ||
51 | va_end(list); | ||
52 | |||
53 | for (i = 0; i < nret; i++) | ||
54 | args.args[nargs+i] = 0; | ||
55 | |||
56 | if (prom(&args) < 0) | ||
57 | return -1; | ||
58 | |||
59 | return (nret > 0)? args.args[nargs]: 0; | ||
60 | } | ||
61 | |||
62 | static int call_prom_ret(const char *service, int nargs, int nret, | ||
63 | unsigned int *rets, ...) | ||
64 | { | ||
65 | int i; | ||
66 | struct prom_args { | ||
67 | const char *service; | ||
68 | int nargs; | ||
69 | int nret; | ||
70 | unsigned int args[12]; | ||
71 | } args; | ||
72 | va_list list; | ||
73 | |||
74 | args.service = service; | ||
75 | args.nargs = nargs; | ||
76 | args.nret = nret; | ||
77 | |||
78 | va_start(list, rets); | ||
79 | for (i = 0; i < nargs; i++) | ||
80 | args.args[i] = va_arg(list, unsigned int); | ||
81 | va_end(list); | ||
82 | |||
83 | for (i = 0; i < nret; i++) | ||
84 | args.args[nargs+i] = 0; | ||
85 | |||
86 | if (prom(&args) < 0) | ||
87 | return -1; | ||
88 | |||
89 | if (rets != (void *) 0) | ||
90 | for (i = 1; i < nret; ++i) | ||
91 | rets[i-1] = args.args[nargs+i]; | ||
92 | |||
93 | return (nret > 0)? args.args[nargs]: 0; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Older OF's require that when claiming a specific range of addresses, | ||
98 | * we claim the physical space in the /memory node and the virtual | ||
99 | * space in the chosen mmu node, and then do a map operation to | ||
100 | * map virtual to physical. | ||
101 | */ | ||
102 | static int need_map = -1; | ||
103 | static ihandle chosen_mmu; | ||
104 | static phandle memory; | ||
105 | |||
106 | /* returns true if s2 is a prefix of s1 */ | ||
107 | static int string_match(const char *s1, const char *s2) | ||
108 | { | ||
109 | for (; *s2; ++s2) | ||
110 | if (*s1++ != *s2) | ||
111 | return 0; | ||
112 | return 1; | ||
113 | } | ||
114 | |||
115 | static int check_of_version(void) | ||
116 | { | ||
117 | phandle oprom, chosen; | ||
118 | char version[64]; | ||
119 | |||
120 | oprom = finddevice("/openprom"); | ||
121 | if (oprom == (phandle) -1) | ||
122 | return 0; | ||
123 | if (getprop(oprom, "model", version, sizeof(version)) <= 0) | ||
124 | return 0; | ||
125 | version[sizeof(version)-1] = 0; | ||
126 | printf("OF version = '%s'\r\n", version); | ||
127 | if (!string_match(version, "Open Firmware, 1.") | ||
128 | && !string_match(version, "FirmWorks,3.")) | ||
129 | return 0; | ||
130 | chosen = finddevice("/chosen"); | ||
131 | if (chosen == (phandle) -1) { | ||
132 | chosen = finddevice("/chosen@0"); | ||
133 | if (chosen == (phandle) -1) { | ||
134 | printf("no chosen\n"); | ||
135 | return 0; | ||
136 | } | ||
137 | } | ||
138 | if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||
139 | printf("no mmu\n"); | ||
140 | return 0; | ||
141 | } | ||
142 | memory = (ihandle) call_prom("open", 1, 1, "/memory"); | ||
143 | if (memory == (ihandle) -1) { | ||
144 | memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); | ||
145 | if (memory == (ihandle) -1) { | ||
146 | printf("no memory node\n"); | ||
147 | return 0; | ||
148 | } | ||
149 | } | ||
150 | printf("old OF detected\r\n"); | ||
151 | return 1; | ||
152 | } | ||
153 | |||
154 | static void *claim(unsigned long virt, unsigned long size, unsigned long align) | ||
155 | { | ||
156 | int ret; | ||
157 | unsigned int result; | ||
158 | |||
159 | if (need_map < 0) | ||
160 | need_map = check_of_version(); | ||
161 | if (align || !need_map) | ||
162 | return (void *) call_prom("claim", 3, 1, virt, size, align); | ||
163 | |||
164 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, | ||
165 | align, size, virt); | ||
166 | if (ret != 0 || result == -1) | ||
167 | return (void *) -1; | ||
168 | ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||
169 | align, size, virt); | ||
170 | /* 0x12 == coherent + read/write */ | ||
171 | ret = call_prom("call-method", 6, 1, "map", chosen_mmu, | ||
172 | 0x12, size, virt, virt); | ||
173 | return (void *) virt; | ||
174 | } | ||
175 | |||
176 | static void *of_try_claim(unsigned long size) | 31 | static void *of_try_claim(unsigned long size) |
177 | { | 32 | { |
178 | unsigned long addr = 0; | 33 | unsigned long addr = 0; |
@@ -184,7 +39,7 @@ static void *of_try_claim(unsigned long size) | |||
184 | #ifdef DEBUG | 39 | #ifdef DEBUG |
185 | printf(" trying: 0x%08lx\n\r", claim_base); | 40 | printf(" trying: 0x%08lx\n\r", claim_base); |
186 | #endif | 41 | #endif |
187 | addr = (unsigned long)claim(claim_base, size, 0); | 42 | addr = (unsigned long)of_claim(claim_base, size, 0); |
188 | if ((void *)addr != (void *)-1) | 43 | if ((void *)addr != (void *)-1) |
189 | break; | 44 | break; |
190 | } | 45 | } |
@@ -208,64 +63,6 @@ static void of_image_hdr(const void *hdr) | |||
208 | } | 63 | } |
209 | } | 64 | } |
210 | 65 | ||
211 | static void *of_vmlinux_alloc(unsigned long size) | ||
212 | { | ||
213 | void *p = malloc(size); | ||
214 | |||
215 | if (!p) | ||
216 | fatal("Can't allocate memory for kernel image!\n\r"); | ||
217 | |||
218 | return p; | ||
219 | } | ||
220 | |||
221 | static void of_exit(void) | ||
222 | { | ||
223 | call_prom("exit", 0, 0); | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * OF device tree routines | ||
228 | */ | ||
229 | static void *of_finddevice(const char *name) | ||
230 | { | ||
231 | return (phandle) call_prom("finddevice", 1, 1, name); | ||
232 | } | ||
233 | |||
234 | static int of_getprop(const void *phandle, const char *name, void *buf, | ||
235 | const int buflen) | ||
236 | { | ||
237 | return call_prom("getprop", 4, 1, phandle, name, buf, buflen); | ||
238 | } | ||
239 | |||
240 | static int of_setprop(const void *phandle, const char *name, const void *buf, | ||
241 | const int buflen) | ||
242 | { | ||
243 | return call_prom("setprop", 4, 1, phandle, name, buf, buflen); | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * OF console routines | ||
248 | */ | ||
249 | static void *of_stdout_handle; | ||
250 | |||
251 | static int of_console_open(void) | ||
252 | { | ||
253 | void *devp; | ||
254 | |||
255 | if (((devp = finddevice("/chosen")) != NULL) | ||
256 | && (getprop(devp, "stdout", &of_stdout_handle, | ||
257 | sizeof(of_stdout_handle)) | ||
258 | == sizeof(of_stdout_handle))) | ||
259 | return 0; | ||
260 | |||
261 | return -1; | ||
262 | } | ||
263 | |||
264 | static void of_console_write(char *buf, int len) | ||
265 | { | ||
266 | call_prom("write", 3, 1, of_stdout_handle, buf, len); | ||
267 | } | ||
268 | |||
269 | void platform_init(unsigned long a1, unsigned long a2, void *promptr) | 66 | void platform_init(unsigned long a1, unsigned long a2, void *promptr) |
270 | { | 67 | { |
271 | platform_ops.image_hdr = of_image_hdr; | 68 | platform_ops.image_hdr = of_image_hdr; |
@@ -277,10 +74,9 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr) | |||
277 | dt_ops.getprop = of_getprop; | 74 | dt_ops.getprop = of_getprop; |
278 | dt_ops.setprop = of_setprop; | 75 | dt_ops.setprop = of_setprop; |
279 | 76 | ||
280 | console_ops.open = of_console_open; | 77 | of_console_init(); |
281 | console_ops.write = of_console_write; | ||
282 | 78 | ||
283 | prom = (int (*)(void *))promptr; | 79 | of_init(promptr); |
284 | loader_info.promptr = promptr; | 80 | loader_info.promptr = promptr; |
285 | if (a1 && a2 && a2 != 0xdeadbeef) { | 81 | if (a1 && a2 && a2 != 0xdeadbeef) { |
286 | loader_info.initrd_addr = a1; | 82 | loader_info.initrd_addr = a1; |
diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h new file mode 100644 index 000000000000..e4c68f7391c5 --- /dev/null +++ b/arch/powerpc/boot/of.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _PPC_BOOT_OF_H_ | ||
2 | #define _PPC_BOOT_OF_H_ | ||
3 | |||
4 | typedef void *phandle; | ||
5 | typedef void *ihandle; | ||
6 | |||
7 | void of_init(void *promptr); | ||
8 | int of_call_prom(const char *service, int nargs, int nret, ...); | ||
9 | void *of_claim(unsigned long virt, unsigned long size, unsigned long align); | ||
10 | void *of_vmlinux_alloc(unsigned long size); | ||
11 | void of_exit(void); | ||
12 | void *of_finddevice(const char *name); | ||
13 | int of_getprop(const void *phandle, const char *name, void *buf, | ||
14 | const int buflen); | ||
15 | int of_setprop(const void *phandle, const char *name, const void *buf, | ||
16 | const int buflen); | ||
17 | |||
18 | /* Console functions */ | ||
19 | void of_console_init(void); | ||
20 | |||
21 | #endif /* _PPC_BOOT_OF_H_ */ | ||
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c new file mode 100644 index 000000000000..ce0e02424453 --- /dev/null +++ b/arch/powerpc/boot/ofconsole.c | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * OF console routines | ||
3 | * | ||
4 | * Copyright (C) Paul Mackerras 1997. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <stddef.h> | ||
12 | #include "types.h" | ||
13 | #include "elf.h" | ||
14 | #include "string.h" | ||
15 | #include "stdio.h" | ||
16 | #include "page.h" | ||
17 | #include "ops.h" | ||
18 | |||
19 | #include "of.h" | ||
20 | |||
21 | static void *of_stdout_handle; | ||
22 | |||
23 | static int of_console_open(void) | ||
24 | { | ||
25 | void *devp; | ||
26 | |||
27 | if (((devp = of_finddevice("/chosen")) != NULL) | ||
28 | && (of_getprop(devp, "stdout", &of_stdout_handle, | ||
29 | sizeof(of_stdout_handle)) | ||
30 | == sizeof(of_stdout_handle))) | ||
31 | return 0; | ||
32 | |||
33 | return -1; | ||
34 | } | ||
35 | |||
36 | static void of_console_write(const char *buf, int len) | ||
37 | { | ||
38 | of_call_prom("write", 3, 1, of_stdout_handle, buf, len); | ||
39 | } | ||
40 | |||
41 | void of_console_init(void) | ||
42 | { | ||
43 | console_ops.open = of_console_open; | ||
44 | console_ops.write = of_console_write; | ||
45 | } | ||
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c new file mode 100644 index 000000000000..95b8fd69a403 --- /dev/null +++ b/arch/powerpc/boot/oflib.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Copyright (C) Paul Mackerras 1997. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | #include <stddef.h> | ||
10 | #include "types.h" | ||
11 | #include "elf.h" | ||
12 | #include "string.h" | ||
13 | #include "stdio.h" | ||
14 | #include "page.h" | ||
15 | #include "ops.h" | ||
16 | |||
17 | #include "of.h" | ||
18 | |||
19 | static int (*prom) (void *); | ||
20 | |||
21 | void of_init(void *promptr) | ||
22 | { | ||
23 | prom = (int (*)(void *))promptr; | ||
24 | } | ||
25 | |||
26 | int of_call_prom(const char *service, int nargs, int nret, ...) | ||
27 | { | ||
28 | int i; | ||
29 | struct prom_args { | ||
30 | const char *service; | ||
31 | int nargs; | ||
32 | int nret; | ||
33 | unsigned int args[12]; | ||
34 | } args; | ||
35 | va_list list; | ||
36 | |||
37 | args.service = service; | ||
38 | args.nargs = nargs; | ||
39 | args.nret = nret; | ||
40 | |||
41 | va_start(list, nret); | ||
42 | for (i = 0; i < nargs; i++) | ||
43 | args.args[i] = va_arg(list, unsigned int); | ||
44 | va_end(list); | ||
45 | |||
46 | for (i = 0; i < nret; i++) | ||
47 | args.args[nargs+i] = 0; | ||
48 | |||
49 | if (prom(&args) < 0) | ||
50 | return -1; | ||
51 | |||
52 | return (nret > 0)? args.args[nargs]: 0; | ||
53 | } | ||
54 | |||
55 | static int of_call_prom_ret(const char *service, int nargs, int nret, | ||
56 | unsigned int *rets, ...) | ||
57 | { | ||
58 | int i; | ||
59 | struct prom_args { | ||
60 | const char *service; | ||
61 | int nargs; | ||
62 | int nret; | ||
63 | unsigned int args[12]; | ||
64 | } args; | ||
65 | va_list list; | ||
66 | |||
67 | args.service = service; | ||
68 | args.nargs = nargs; | ||
69 | args.nret = nret; | ||
70 | |||
71 | va_start(list, rets); | ||
72 | for (i = 0; i < nargs; i++) | ||
73 | args.args[i] = va_arg(list, unsigned int); | ||
74 | va_end(list); | ||
75 | |||
76 | for (i = 0; i < nret; i++) | ||
77 | args.args[nargs+i] = 0; | ||
78 | |||
79 | if (prom(&args) < 0) | ||
80 | return -1; | ||
81 | |||
82 | if (rets != (void *) 0) | ||
83 | for (i = 1; i < nret; ++i) | ||
84 | rets[i-1] = args.args[nargs+i]; | ||
85 | |||
86 | return (nret > 0)? args.args[nargs]: 0; | ||
87 | } | ||
88 | |||
89 | /* returns true if s2 is a prefix of s1 */ | ||
90 | static int string_match(const char *s1, const char *s2) | ||
91 | { | ||
92 | for (; *s2; ++s2) | ||
93 | if (*s1++ != *s2) | ||
94 | return 0; | ||
95 | return 1; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Older OF's require that when claiming a specific range of addresses, | ||
100 | * we claim the physical space in the /memory node and the virtual | ||
101 | * space in the chosen mmu node, and then do a map operation to | ||
102 | * map virtual to physical. | ||
103 | */ | ||
104 | static int need_map = -1; | ||
105 | static ihandle chosen_mmu; | ||
106 | static phandle memory; | ||
107 | |||
108 | static int check_of_version(void) | ||
109 | { | ||
110 | phandle oprom, chosen; | ||
111 | char version[64]; | ||
112 | |||
113 | oprom = of_finddevice("/openprom"); | ||
114 | if (oprom == (phandle) -1) | ||
115 | return 0; | ||
116 | if (of_getprop(oprom, "model", version, sizeof(version)) <= 0) | ||
117 | return 0; | ||
118 | version[sizeof(version)-1] = 0; | ||
119 | printf("OF version = '%s'\r\n", version); | ||
120 | if (!string_match(version, "Open Firmware, 1.") | ||
121 | && !string_match(version, "FirmWorks,3.")) | ||
122 | return 0; | ||
123 | chosen = of_finddevice("/chosen"); | ||
124 | if (chosen == (phandle) -1) { | ||
125 | chosen = of_finddevice("/chosen@0"); | ||
126 | if (chosen == (phandle) -1) { | ||
127 | printf("no chosen\n"); | ||
128 | return 0; | ||
129 | } | ||
130 | } | ||
131 | if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { | ||
132 | printf("no mmu\n"); | ||
133 | return 0; | ||
134 | } | ||
135 | memory = (ihandle) of_call_prom("open", 1, 1, "/memory"); | ||
136 | if (memory == (ihandle) -1) { | ||
137 | memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0"); | ||
138 | if (memory == (ihandle) -1) { | ||
139 | printf("no memory node\n"); | ||
140 | return 0; | ||
141 | } | ||
142 | } | ||
143 | printf("old OF detected\r\n"); | ||
144 | return 1; | ||
145 | } | ||
146 | |||
147 | void *of_claim(unsigned long virt, unsigned long size, unsigned long align) | ||
148 | { | ||
149 | int ret; | ||
150 | unsigned int result; | ||
151 | |||
152 | if (need_map < 0) | ||
153 | need_map = check_of_version(); | ||
154 | if (align || !need_map) | ||
155 | return (void *) of_call_prom("claim", 3, 1, virt, size, align); | ||
156 | |||
157 | ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory, | ||
158 | align, size, virt); | ||
159 | if (ret != 0 || result == -1) | ||
160 | return (void *) -1; | ||
161 | ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, | ||
162 | align, size, virt); | ||
163 | /* 0x12 == coherent + read/write */ | ||
164 | ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu, | ||
165 | 0x12, size, virt, virt); | ||
166 | return (void *) virt; | ||
167 | } | ||
168 | |||
169 | void *of_vmlinux_alloc(unsigned long size) | ||
170 | { | ||
171 | void *p = malloc(size); | ||
172 | |||
173 | if (!p) | ||
174 | fatal("Can't allocate memory for kernel image!\n\r"); | ||
175 | |||
176 | return p; | ||
177 | } | ||
178 | |||
179 | void of_exit(void) | ||
180 | { | ||
181 | of_call_prom("exit", 0, 0); | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * OF device tree routines | ||
186 | */ | ||
187 | void *of_finddevice(const char *name) | ||
188 | { | ||
189 | return (phandle) of_call_prom("finddevice", 1, 1, name); | ||
190 | } | ||
191 | |||
192 | int of_getprop(const void *phandle, const char *name, void *buf, | ||
193 | const int buflen) | ||
194 | { | ||
195 | return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen); | ||
196 | } | ||
197 | |||
198 | int of_setprop(const void *phandle, const char *name, const void *buf, | ||
199 | const int buflen) | ||
200 | { | ||
201 | return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen); | ||
202 | } | ||
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index 959124f3f9af..86077066cd7c 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #define MAX_PATH_LEN 256 | 19 | #define MAX_PATH_LEN 256 |
20 | #define MAX_PROP_LEN 256 /* What should this be? */ | 20 | #define MAX_PROP_LEN 256 /* What should this be? */ |
21 | 21 | ||
22 | typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5); | ||
23 | |||
22 | /* Platform specific operations */ | 24 | /* Platform specific operations */ |
23 | struct platform_ops { | 25 | struct platform_ops { |
24 | void (*fixups)(void); | 26 | void (*fixups)(void); |
@@ -51,7 +53,7 @@ extern struct dt_ops dt_ops; | |||
51 | /* Console operations */ | 53 | /* Console operations */ |
52 | struct console_ops { | 54 | struct console_ops { |
53 | int (*open)(void); | 55 | int (*open)(void); |
54 | void (*write)(char *buf, int len); | 56 | void (*write)(const char *buf, int len); |
55 | void (*edit_cmdline)(char *buf, int len); | 57 | void (*edit_cmdline)(char *buf, int len); |
56 | void (*close)(void); | 58 | void (*close)(void); |
57 | void *data; | 59 | void *data; |
diff --git a/arch/powerpc/boot/ps3-head.S b/arch/powerpc/boot/ps3-head.S new file mode 100644 index 000000000000..1a6d64a68df5 --- /dev/null +++ b/arch/powerpc/boot/ps3-head.S | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * PS3 bootwrapper entry. | ||
3 | * | ||
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2007 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ppc_asm.h" | ||
22 | |||
23 | .text | ||
24 | |||
25 | /* | ||
26 | * __system_reset_overlay - The PS3 first stage entry. | ||
27 | * | ||
28 | * The bootwraper build script copies the 0x100 bytes at symbol | ||
29 | * __system_reset_overlay to offset 0x100 of the rom image. | ||
30 | * | ||
31 | * The PS3 has a single processor with two threads. | ||
32 | */ | ||
33 | |||
34 | .globl __system_reset_overlay | ||
35 | __system_reset_overlay: | ||
36 | |||
37 | /* Switch to 32-bit mode. */ | ||
38 | |||
39 | mfmsr r9 | ||
40 | clrldi r9,r9,1 | ||
41 | mtmsrd r9 | ||
42 | nop | ||
43 | |||
44 | /* Get thread number in r3 and branch. */ | ||
45 | |||
46 | mfspr r3, 0x88 | ||
47 | cntlzw. r3, r3 | ||
48 | li r4, 0 | ||
49 | li r5, 0 | ||
50 | beq 1f | ||
51 | |||
52 | /* Secondary goes to __secondary_hold in kernel. */ | ||
53 | |||
54 | li r4, 0x60 | ||
55 | mtctr r4 | ||
56 | bctr | ||
57 | |||
58 | /* Primary delays then goes to _zimage_start in wrapper. */ | ||
59 | 1: | ||
60 | or 31, 31, 31 /* db16cyc */ | ||
61 | or 31, 31, 31 /* db16cyc */ | ||
62 | |||
63 | lis r4, _zimage_start@ha | ||
64 | addi r4, r4, _zimage_start@l | ||
65 | mtctr r4 | ||
66 | bctr | ||
67 | |||
68 | /* | ||
69 | * __system_reset_kernel - Place holder for the kernel reset vector. | ||
70 | * | ||
71 | * The bootwrapper build script copies 0x100 bytes from offset 0x100 | ||
72 | * of the rom image to the symbol __system_reset_kernel. At runtime | ||
73 | * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel | ||
74 | * to ram address 0x100. This symbol must occupy 0x100 bytes. | ||
75 | */ | ||
76 | |||
77 | .globl __system_reset_kernel | ||
78 | __system_reset_kernel: | ||
79 | |||
80 | . = __system_reset_kernel + 0x100 | ||
diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S new file mode 100644 index 000000000000..c8b7df3210d1 --- /dev/null +++ b/arch/powerpc/boot/ps3-hvcall.S | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * PS3 bootwrapper hvcalls. | ||
3 | * | ||
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2007 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include "ppc_asm.h" | ||
22 | |||
23 | /* | ||
24 | * The PS3 hypervisor uses a 64 bit "C" language calling convention. | ||
25 | * The routines here marshal arguments between the 32 bit wrapper | ||
26 | * program and the 64 bit hvcalls. | ||
27 | * | ||
28 | * wrapper lv1 | ||
29 | * 32-bit (h,l) 64-bit | ||
30 | * | ||
31 | * 1: r3,r4 <-> r3 | ||
32 | * 2: r5,r6 <-> r4 | ||
33 | * 3: r7,r8 <-> r5 | ||
34 | * 4: r9,r10 <-> r6 | ||
35 | * 5: 8(r1),12(r1) <-> r7 | ||
36 | * 6: 16(r1),20(r1) <-> r8 | ||
37 | * 7: 24(r1),28(r1) <-> r9 | ||
38 | * 8: 32(r1),36(r1) <-> r10 | ||
39 | * | ||
40 | */ | ||
41 | |||
42 | .macro GLOBAL name | ||
43 | .section ".text" | ||
44 | .balign 4 | ||
45 | .globl \name | ||
46 | \name: | ||
47 | .endm | ||
48 | |||
49 | .macro NO_SUPPORT name | ||
50 | GLOBAL \name | ||
51 | b ps3_no_support | ||
52 | .endm | ||
53 | |||
54 | .macro HVCALL num | ||
55 | li r11, \num | ||
56 | .long 0x44000022 | ||
57 | extsw r3, r3 | ||
58 | .endm | ||
59 | |||
60 | .macro SAVE_LR offset=4 | ||
61 | mflr r0 | ||
62 | stw r0, \offset(r1) | ||
63 | .endm | ||
64 | |||
65 | .macro LOAD_LR offset=4 | ||
66 | lwz r0, \offset(r1) | ||
67 | mtlr r0 | ||
68 | .endm | ||
69 | |||
70 | .macro LOAD_64_REG target,high,low | ||
71 | sldi r11, \high, 32 | ||
72 | or \target, r11, \low | ||
73 | .endm | ||
74 | |||
75 | .macro LOAD_64_STACK target,offset | ||
76 | ld \target, \offset(r1) | ||
77 | .endm | ||
78 | |||
79 | .macro LOAD_R3 | ||
80 | LOAD_64_REG r3,r3,r4 | ||
81 | .endm | ||
82 | |||
83 | .macro LOAD_R4 | ||
84 | LOAD_64_REG r4,r5,r6 | ||
85 | .endm | ||
86 | |||
87 | .macro LOAD_R5 | ||
88 | LOAD_64_REG r5,r7,r8 | ||
89 | .endm | ||
90 | |||
91 | .macro LOAD_R6 | ||
92 | LOAD_64_REG r6,r9,r10 | ||
93 | .endm | ||
94 | |||
95 | .macro LOAD_R7 | ||
96 | LOAD_64_STACK r7,8 | ||
97 | .endm | ||
98 | |||
99 | .macro LOAD_R8 | ||
100 | LOAD_64_STACK r8,16 | ||
101 | .endm | ||
102 | |||
103 | .macro LOAD_R9 | ||
104 | LOAD_64_STACK r9,24 | ||
105 | .endm | ||
106 | |||
107 | .macro LOAD_R10 | ||
108 | LOAD_64_STACK r10,32 | ||
109 | .endm | ||
110 | |||
111 | .macro LOAD_REGS_0 | ||
112 | stwu 1,-16(1) | ||
113 | stw 3, 8(1) | ||
114 | .endm | ||
115 | |||
116 | .macro LOAD_REGS_5 | ||
117 | LOAD_R3 | ||
118 | LOAD_R4 | ||
119 | LOAD_R5 | ||
120 | LOAD_R6 | ||
121 | LOAD_R7 | ||
122 | .endm | ||
123 | |||
124 | .macro LOAD_REGS_6 | ||
125 | LOAD_REGS_5 | ||
126 | LOAD_R8 | ||
127 | .endm | ||
128 | |||
129 | .macro LOAD_REGS_8 | ||
130 | LOAD_REGS_6 | ||
131 | LOAD_R9 | ||
132 | LOAD_R10 | ||
133 | .endm | ||
134 | |||
135 | .macro STORE_REGS_0_1 | ||
136 | lwz r11, 8(r1) | ||
137 | std r4, 0(r11) | ||
138 | mr r4, r3 | ||
139 | li r3, 0 | ||
140 | addi r1,r1,16 | ||
141 | .endm | ||
142 | |||
143 | .macro STORE_REGS_5_2 | ||
144 | lwz r11, 16(r1) | ||
145 | std r4, 0(r11) | ||
146 | lwz r11, 24(r1) | ||
147 | std r5, 0(r11) | ||
148 | .endm | ||
149 | |||
150 | .macro STORE_REGS_6_1 | ||
151 | lwz r11, 24(r1) | ||
152 | std r4, 0(r11) | ||
153 | .endm | ||
154 | |||
155 | GLOBAL lv1_get_logical_ppe_id | ||
156 | SAVE_LR | ||
157 | LOAD_REGS_0 | ||
158 | HVCALL 69 | ||
159 | STORE_REGS_0_1 | ||
160 | LOAD_LR | ||
161 | blr | ||
162 | |||
163 | GLOBAL lv1_get_logical_partition_id | ||
164 | SAVE_LR | ||
165 | LOAD_REGS_0 | ||
166 | HVCALL 74 | ||
167 | STORE_REGS_0_1 | ||
168 | LOAD_LR | ||
169 | blr | ||
170 | |||
171 | GLOBAL lv1_get_repository_node_value | ||
172 | SAVE_LR | ||
173 | LOAD_REGS_5 | ||
174 | HVCALL 91 | ||
175 | STORE_REGS_5_2 | ||
176 | LOAD_LR | ||
177 | blr | ||
178 | |||
179 | GLOBAL lv1_panic | ||
180 | SAVE_LR | ||
181 | LOAD_REGS_8 | ||
182 | HVCALL 255 | ||
183 | LOAD_LR | ||
184 | blr | ||
diff --git a/arch/powerpc/boot/ps3.c b/arch/powerpc/boot/ps3.c new file mode 100644 index 000000000000..893d59339c26 --- /dev/null +++ b/arch/powerpc/boot/ps3.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * PS3 bootwrapper support. | ||
3 | * | ||
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2007 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <stdarg.h> | ||
22 | #include <stddef.h> | ||
23 | #include "types.h" | ||
24 | #include "elf.h" | ||
25 | #include "string.h" | ||
26 | #include "stdio.h" | ||
27 | #include "page.h" | ||
28 | #include "ops.h" | ||
29 | |||
30 | extern s64 lv1_panic(u64 in_1); | ||
31 | extern s64 lv1_get_logical_partition_id(u64 *out_1); | ||
32 | extern s64 lv1_get_logical_ppe_id(u64 *out_1); | ||
33 | extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3, | ||
34 | u64 in_4, u64 in_5, u64 *out_1, u64 *out_2); | ||
35 | |||
36 | #ifdef DEBUG | ||
37 | #define DBG(fmt...) printf(fmt) | ||
38 | #else | ||
39 | static inline int __attribute__ ((format (printf, 1, 2))) DBG( | ||
40 | const char *fmt, ...) {return 0;} | ||
41 | #endif | ||
42 | |||
43 | BSS_STACK(4096); | ||
44 | |||
45 | /* A buffer that may be edited by tools operating on a zImage binary so as to | ||
46 | * edit the command line passed to vmlinux (by setting /chosen/bootargs). | ||
47 | * The buffer is put in it's own section so that tools may locate it easier. | ||
48 | */ | ||
49 | static char cmdline[COMMAND_LINE_SIZE] | ||
50 | __attribute__((__section__("__builtin_cmdline"))); | ||
51 | |||
52 | static void prep_cmdline(void *chosen) | ||
53 | { | ||
54 | if (cmdline[0] == '\0') | ||
55 | getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1); | ||
56 | else | ||
57 | setprop_str(chosen, "bootargs", cmdline); | ||
58 | |||
59 | printf("cmdline: '%s'\n", cmdline); | ||
60 | } | ||
61 | |||
62 | static void ps3_console_write(const char *buf, int len) | ||
63 | { | ||
64 | } | ||
65 | |||
66 | static void ps3_exit(void) | ||
67 | { | ||
68 | printf("ps3_exit\n"); | ||
69 | |||
70 | /* lv1_panic will shutdown the lpar. */ | ||
71 | |||
72 | lv1_panic(0); /* zero = do not reboot */ | ||
73 | while (1); | ||
74 | } | ||
75 | |||
76 | static int ps3_repository_read_rm_size(u64 *rm_size) | ||
77 | { | ||
78 | s64 result; | ||
79 | u64 lpar_id; | ||
80 | u64 ppe_id; | ||
81 | u64 v2; | ||
82 | |||
83 | result = lv1_get_logical_partition_id(&lpar_id); | ||
84 | |||
85 | if (result) | ||
86 | return -1; | ||
87 | |||
88 | result = lv1_get_logical_ppe_id(&ppe_id); | ||
89 | |||
90 | if (result) | ||
91 | return -1; | ||
92 | |||
93 | /* | ||
94 | * n1: 0000000062690000 : ....bi.. | ||
95 | * n2: 7075000000000000 : pu...... | ||
96 | * n3: 0000000000000001 : ........ | ||
97 | * n4: 726d5f73697a6500 : rm_size. | ||
98 | */ | ||
99 | |||
100 | result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL, | ||
101 | 0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size, | ||
102 | &v2); | ||
103 | |||
104 | printf("%s:%d: ppe_id %lu \n", __func__, __LINE__, | ||
105 | (unsigned long)ppe_id); | ||
106 | printf("%s:%d: lpar_id %lu \n", __func__, __LINE__, | ||
107 | (unsigned long)lpar_id); | ||
108 | printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size); | ||
109 | |||
110 | return result ? -1 : 0; | ||
111 | } | ||
112 | |||
113 | void ps3_copy_vectors(void) | ||
114 | { | ||
115 | extern char __system_reset_kernel[]; | ||
116 | |||
117 | memcpy((void *)0x100, __system_reset_kernel, 0x100); | ||
118 | flush_cache((void *)0x100, 0x100); | ||
119 | } | ||
120 | |||
121 | void platform_init(void) | ||
122 | { | ||
123 | extern char _end[]; | ||
124 | extern char _dtb_start[]; | ||
125 | extern char _initrd_start[]; | ||
126 | extern char _initrd_end[]; | ||
127 | const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */ | ||
128 | void *chosen; | ||
129 | unsigned long ft_addr; | ||
130 | u64 rm_size; | ||
131 | |||
132 | console_ops.write = ps3_console_write; | ||
133 | platform_ops.exit = ps3_exit; | ||
134 | |||
135 | printf("\n-- PS3 bootwrapper --\n"); | ||
136 | |||
137 | simple_alloc_init(_end, heapsize, 32, 64); | ||
138 | ft_init(_dtb_start, 0, 4); | ||
139 | |||
140 | chosen = finddevice("/chosen"); | ||
141 | |||
142 | ps3_repository_read_rm_size(&rm_size); | ||
143 | dt_fixup_memory(0, rm_size); | ||
144 | |||
145 | if (_initrd_end > _initrd_start) { | ||
146 | setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start)); | ||
147 | setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end)); | ||
148 | } | ||
149 | |||
150 | prep_cmdline(chosen); | ||
151 | |||
152 | ft_addr = dt_ops.finalize(); | ||
153 | |||
154 | ps3_copy_vectors(); | ||
155 | |||
156 | printf(" flat tree at 0x%lx\n\r", ft_addr); | ||
157 | |||
158 | ((kernel_entry_t)0)(ft_addr, 0, NULL); | ||
159 | |||
160 | ps3_exit(); | ||
161 | } | ||
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c index 7fd32330a9a5..eaa0d3ae3518 100644 --- a/arch/powerpc/boot/serial.c +++ b/arch/powerpc/boot/serial.c | |||
@@ -27,7 +27,7 @@ static int serial_open(void) | |||
27 | return scdp->open(); | 27 | return scdp->open(); |
28 | } | 28 | } |
29 | 29 | ||
30 | static void serial_write(char *buf, int len) | 30 | static void serial_write(const char *buf, int len) |
31 | { | 31 | { |
32 | struct serial_console_data *scdp = console_ops.data; | 32 | struct serial_console_data *scdp = console_ops.data; |
33 | 33 | ||
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c index 0a9feeb98342..5b57800bbc67 100644 --- a/arch/powerpc/boot/stdio.c +++ b/arch/powerpc/boot/stdio.c | |||
@@ -190,7 +190,11 @@ int vsprintf(char *buf, const char *fmt, va_list args) | |||
190 | 190 | ||
191 | /* get the conversion qualifier */ | 191 | /* get the conversion qualifier */ |
192 | qualifier = -1; | 192 | qualifier = -1; |
193 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { | 193 | if (*fmt == 'l' && *(fmt + 1) == 'l') { |
194 | qualifier = 'q'; | ||
195 | fmt += 2; | ||
196 | } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' | ||
197 | || *fmt == 'Z') { | ||
194 | qualifier = *fmt; | 198 | qualifier = *fmt; |
195 | ++fmt; | 199 | ++fmt; |
196 | } | 200 | } |
@@ -281,6 +285,10 @@ int vsprintf(char *buf, const char *fmt, va_list args) | |||
281 | num = va_arg(args, unsigned long); | 285 | num = va_arg(args, unsigned long); |
282 | if (flags & SIGN) | 286 | if (flags & SIGN) |
283 | num = (signed long) num; | 287 | num = (signed long) num; |
288 | } else if (qualifier == 'q') { | ||
289 | num = va_arg(args, unsigned long long); | ||
290 | if (flags & SIGN) | ||
291 | num = (signed long long) num; | ||
284 | } else if (qualifier == 'Z') { | 292 | } else if (qualifier == 'Z') { |
285 | num = va_arg(args, size_t); | 293 | num = va_arg(args, size_t); |
286 | } else if (qualifier == 'h') { | 294 | } else if (qualifier == 'h') { |
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h index 79d26e708677..31393d17a9c1 100644 --- a/arch/powerpc/boot/types.h +++ b/arch/powerpc/boot/types.h | |||
@@ -7,6 +7,10 @@ typedef unsigned char u8; | |||
7 | typedef unsigned short u16; | 7 | typedef unsigned short u16; |
8 | typedef unsigned int u32; | 8 | typedef unsigned int u32; |
9 | typedef unsigned long long u64; | 9 | typedef unsigned long long u64; |
10 | typedef signed char s8; | ||
11 | typedef short s16; | ||
12 | typedef int s32; | ||
13 | typedef long long s64; | ||
10 | 14 | ||
11 | #define min(x,y) ({ \ | 15 | #define min(x,y) ({ \ |
12 | typeof(x) _x = (x); \ | 16 | typeof(x) _x = (x); \ |
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index da77adc73078..65f685479175 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper | |||
@@ -144,6 +144,15 @@ miboot|uboot) | |||
144 | cuboot*) | 144 | cuboot*) |
145 | gzip= | 145 | gzip= |
146 | ;; | 146 | ;; |
147 | ps3) | ||
148 | platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o" | ||
149 | lds=$object/zImage.ps3.lds | ||
150 | gzip= | ||
151 | ext=bin | ||
152 | objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data" | ||
153 | ksection=.kernel:vmlinux.bin | ||
154 | isection=.kernel:initrd | ||
155 | ;; | ||
147 | esac | 156 | esac |
148 | 157 | ||
149 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" | 158 | vmz="$tmpdir/`basename \"$kernel\"`.$ext" |
@@ -239,4 +248,50 @@ treeboot*) | |||
239 | fi | 248 | fi |
240 | exit 0 | 249 | exit 0 |
241 | ;; | 250 | ;; |
251 | ps3) | ||
252 | # The ps3's loader supports loading gzipped binary images from flash | ||
253 | # rom to addr zero. The loader enters the image at addr 0x100. A | ||
254 | # bootwrapper overlay is use to arrange for the kernel to be loaded | ||
255 | # to addr zero and to have a suitable bootwrapper entry at 0x100. | ||
256 | # To construct the rom image, 0x100 bytes from offset 0x100 in the | ||
257 | # kernel is copied to the bootwrapper symbol __system_reset_kernel. | ||
258 | # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is | ||
259 | # then copied to offset 0x100. At runtime the bootwrapper program | ||
260 | # copies the 0x100 bytes at __system_reset_kernel to addr 0x100. | ||
261 | |||
262 | system_reset_overlay=0x`${CROSS}nm "$ofile" \ | ||
263 | | grep ' __system_reset_overlay$' \ | ||
264 | | cut -d' ' -f1` | ||
265 | system_reset_overlay=`printf "%d" $system_reset_overlay` | ||
266 | system_reset_kernel=0x`${CROSS}nm "$ofile" \ | ||
267 | | grep ' __system_reset_kernel$' \ | ||
268 | | cut -d' ' -f1` | ||
269 | system_reset_kernel=`printf "%d" $system_reset_kernel` | ||
270 | overlay_dest="256" | ||
271 | overlay_size="256" | ||
272 | |||
273 | rm -f "$object/otheros.bld" | ||
274 | |||
275 | ${CROSS}objcopy -O binary "$ofile" "$ofile.bin" | ||
276 | |||
277 | msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ | ||
278 | skip=$overlay_dest seek=$system_reset_kernel \ | ||
279 | count=$overlay_size bs=1 2>&1) | ||
280 | |||
281 | if [ $? -ne "0" ]; then | ||
282 | echo $msg | ||
283 | exit 1 | ||
284 | fi | ||
285 | |||
286 | msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ | ||
287 | skip=$system_reset_overlay seek=$overlay_dest \ | ||
288 | count=$overlay_size bs=1 2>&1) | ||
289 | |||
290 | if [ $? -ne "0" ]; then | ||
291 | echo $msg | ||
292 | exit 2 | ||
293 | fi | ||
294 | |||
295 | gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld" | ||
296 | ;; | ||
242 | esac | 297 | esac |
diff --git a/arch/powerpc/boot/zImage.ps3.lds.S b/arch/powerpc/boot/zImage.ps3.lds.S new file mode 100644 index 000000000000..aaa469c1e60d --- /dev/null +++ b/arch/powerpc/boot/zImage.ps3.lds.S | |||
@@ -0,0 +1,50 @@ | |||
1 | OUTPUT_ARCH(powerpc:common) | ||
2 | ENTRY(_zimage_start) | ||
3 | EXTERN(_zimage_start) | ||
4 | SECTIONS | ||
5 | { | ||
6 | _vmlinux_start = .; | ||
7 | .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) } | ||
8 | _vmlinux_end = .; | ||
9 | |||
10 | . = ALIGN(4096); | ||
11 | _dtb_start = .; | ||
12 | .kernel:dtb : { *(.kernel:dtb) } | ||
13 | _dtb_end = .; | ||
14 | |||
15 | . = ALIGN(4096); | ||
16 | _initrd_start = .; | ||
17 | .kernel:initrd : { *(.kernel:initrd) } | ||
18 | _initrd_end = .; | ||
19 | |||
20 | _start = .; | ||
21 | .text : | ||
22 | { | ||
23 | *(.text) | ||
24 | *(.fixup) | ||
25 | } | ||
26 | _etext = .; | ||
27 | . = ALIGN(4096); | ||
28 | .data : | ||
29 | { | ||
30 | *(.rodata*) | ||
31 | *(.data*) | ||
32 | *(.sdata*) | ||
33 | __got2_start = .; | ||
34 | *(.got2) | ||
35 | __got2_end = .; | ||
36 | } | ||
37 | |||
38 | . = ALIGN(4096); | ||
39 | _edata = .; | ||
40 | |||
41 | . = ALIGN(4096); | ||
42 | __bss_start = .; | ||
43 | .bss : | ||
44 | { | ||
45 | *(.sbss) | ||
46 | *(.bss) | ||
47 | } | ||
48 | . = ALIGN(4096); | ||
49 | _end = . ; | ||
50 | } | ||
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig index 32781849ad4c..04b94f884aae 100644 --- a/arch/powerpc/configs/holly_defconfig +++ b/arch/powerpc/configs/holly_defconfig | |||
@@ -190,10 +190,12 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 | |||
190 | # CONFIG_RESOURCES_64BIT is not set | 190 | # CONFIG_RESOURCES_64BIT is not set |
191 | CONFIG_ZONE_DMA_FLAG=1 | 191 | CONFIG_ZONE_DMA_FLAG=1 |
192 | CONFIG_PROC_DEVICETREE=y | 192 | CONFIG_PROC_DEVICETREE=y |
193 | # CONFIG_CMDLINE_BOOL is not set | 193 | CONFIG_CMDLINE_BOOL=y |
194 | CONFIG_CMDLINE="console=ttyS0,115200" | ||
194 | # CONFIG_PM is not set | 195 | # CONFIG_PM is not set |
195 | # CONFIG_SECCOMP is not set | 196 | # CONFIG_SECCOMP is not set |
196 | # CONFIG_WANT_DEVICE_TREE is not set | 197 | CONFIG_WANT_DEVICE_TREE=y |
198 | CONFIG_DEVICE_TREE="holly.dts" | ||
197 | CONFIG_ISA_DMA_API=y | 199 | CONFIG_ISA_DMA_API=y |
198 | 200 | ||
199 | # | 201 | # |
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 956d1df61e0f..d0b43df44426 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig | |||
@@ -156,7 +156,11 @@ CONFIG_PS3_HTAB_SIZE=20 | |||
156 | CONFIG_PS3_USE_LPAR_ADDR=y | 156 | CONFIG_PS3_USE_LPAR_ADDR=y |
157 | CONFIG_PS3_VUART=y | 157 | CONFIG_PS3_VUART=y |
158 | CONFIG_PS3_PS3AV=y | 158 | CONFIG_PS3_PS3AV=y |
159 | CONFIG_PS3_SYS_MANAGER=y | 159 | CONFIG_PS3_SYS_MANAGER=m |
160 | CONFIG_PS3_STORAGE=y | ||
161 | CONFIG_PS3_DISK=y | ||
162 | CONFIG_PS3_ROM=y | ||
163 | CONFIG_PS3_FLASH=y | ||
160 | CONFIG_PPC_CELL=y | 164 | CONFIG_PPC_CELL=y |
161 | # CONFIG_PPC_CELL_NATIVE is not set | 165 | # CONFIG_PPC_CELL_NATIVE is not set |
162 | # CONFIG_PPC_IBM_CELL_BLADE is not set | 166 | # CONFIG_PPC_IBM_CELL_BLADE is not set |
@@ -335,7 +339,7 @@ CONFIG_BT=m | |||
335 | CONFIG_BT_L2CAP=m | 339 | CONFIG_BT_L2CAP=m |
336 | CONFIG_BT_SCO=m | 340 | CONFIG_BT_SCO=m |
337 | CONFIG_BT_RFCOMM=m | 341 | CONFIG_BT_RFCOMM=m |
338 | # CONFIG_BT_RFCOMM_TTY is not set | 342 | CONFIG_BT_RFCOMM_TTY=y |
339 | # CONFIG_BT_BNEP is not set | 343 | # CONFIG_BT_BNEP is not set |
340 | CONFIG_BT_HIDP=m | 344 | CONFIG_BT_HIDP=m |
341 | 345 | ||
@@ -344,7 +348,9 @@ CONFIG_BT_HIDP=m | |||
344 | # | 348 | # |
345 | CONFIG_BT_HCIUSB=m | 349 | CONFIG_BT_HCIUSB=m |
346 | CONFIG_BT_HCIUSB_SCO=y | 350 | CONFIG_BT_HCIUSB_SCO=y |
347 | # CONFIG_BT_HCIUART is not set | 351 | CONFIG_BT_HCIUART=m |
352 | CONFIG_BT_HCIUART_H4=y | ||
353 | CONFIG_BT_HCIUART_BCSP=y | ||
348 | # CONFIG_BT_HCIBCM203X is not set | 354 | # CONFIG_BT_HCIBCM203X is not set |
349 | # CONFIG_BT_HCIBPA10X is not set | 355 | # CONFIG_BT_HCIBPA10X is not set |
350 | # CONFIG_BT_HCIBFUSB is not set | 356 | # CONFIG_BT_HCIBFUSB is not set |
@@ -435,7 +441,7 @@ CONFIG_CHR_DEV_SG=m | |||
435 | # | 441 | # |
436 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | 442 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs |
437 | # | 443 | # |
438 | # CONFIG_SCSI_MULTI_LUN is not set | 444 | CONFIG_SCSI_MULTI_LUN=y |
439 | # CONFIG_SCSI_CONSTANTS is not set | 445 | # CONFIG_SCSI_CONSTANTS is not set |
440 | # CONFIG_SCSI_LOGGING is not set | 446 | # CONFIG_SCSI_LOGGING is not set |
441 | # CONFIG_SCSI_SCAN_ASYNC is not set | 447 | # CONFIG_SCSI_SCAN_ASYNC is not set |
@@ -479,6 +485,7 @@ CONFIG_NETDEVICES=y | |||
479 | CONFIG_MII=m | 485 | CONFIG_MII=m |
480 | CONFIG_NETDEV_1000=y | 486 | CONFIG_NETDEV_1000=y |
481 | CONFIG_NETDEV_10000=y | 487 | CONFIG_NETDEV_10000=y |
488 | CONFIG_GELIC_NET=y | ||
482 | 489 | ||
483 | # | 490 | # |
484 | # Wireless LAN | 491 | # Wireless LAN |
@@ -546,7 +553,27 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | |||
546 | # | 553 | # |
547 | # CONFIG_INPUT_KEYBOARD is not set | 554 | # CONFIG_INPUT_KEYBOARD is not set |
548 | # CONFIG_INPUT_MOUSE is not set | 555 | # CONFIG_INPUT_MOUSE is not set |
549 | # CONFIG_INPUT_JOYSTICK is not set | 556 | CONFIG_INPUT_JOYSTICK=y |
557 | # CONFIG_JOYSTICK_ANALOG is not set | ||
558 | # CONFIG_JOYSTICK_A3D is not set | ||
559 | # CONFIG_JOYSTICK_ADI is not set | ||
560 | # CONFIG_JOYSTICK_COBRA is not set | ||
561 | # CONFIG_JOYSTICK_GF2K is not set | ||
562 | # CONFIG_JOYSTICK_GRIP is not set | ||
563 | # CONFIG_JOYSTICK_GRIP_MP is not set | ||
564 | # CONFIG_JOYSTICK_GUILLEMOT is not set | ||
565 | # CONFIG_JOYSTICK_INTERACT is not set | ||
566 | # CONFIG_JOYSTICK_SIDEWINDER is not set | ||
567 | # CONFIG_JOYSTICK_TMDC is not set | ||
568 | # CONFIG_JOYSTICK_IFORCE is not set | ||
569 | # CONFIG_JOYSTICK_WARRIOR is not set | ||
570 | # CONFIG_JOYSTICK_MAGELLAN is not set | ||
571 | # CONFIG_JOYSTICK_SPACEORB is not set | ||
572 | # CONFIG_JOYSTICK_SPACEBALL is not set | ||
573 | # CONFIG_JOYSTICK_STINGER is not set | ||
574 | # CONFIG_JOYSTICK_TWIDJOY is not set | ||
575 | # CONFIG_JOYSTICK_JOYDUMP is not set | ||
576 | # CONFIG_JOYSTICK_XPAD is not set | ||
550 | # CONFIG_INPUT_TABLET is not set | 577 | # CONFIG_INPUT_TABLET is not set |
551 | # CONFIG_INPUT_TOUCHSCREEN is not set | 578 | # CONFIG_INPUT_TOUCHSCREEN is not set |
552 | # CONFIG_INPUT_MISC is not set | 579 | # CONFIG_INPUT_MISC is not set |
@@ -563,7 +590,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | |||
563 | CONFIG_VT=y | 590 | CONFIG_VT=y |
564 | CONFIG_VT_CONSOLE=y | 591 | CONFIG_VT_CONSOLE=y |
565 | CONFIG_HW_CONSOLE=y | 592 | CONFIG_HW_CONSOLE=y |
566 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | 593 | CONFIG_VT_HW_CONSOLE_BINDING=y |
567 | # CONFIG_SERIAL_NONSTANDARD is not set | 594 | # CONFIG_SERIAL_NONSTANDARD is not set |
568 | 595 | ||
569 | # | 596 | # |
@@ -1086,7 +1113,7 @@ CONFIG_HAS_DMA=y | |||
1086 | # | 1113 | # |
1087 | # CONFIG_PRINTK_TIME is not set | 1114 | # CONFIG_PRINTK_TIME is not set |
1088 | CONFIG_ENABLE_MUST_CHECK=y | 1115 | CONFIG_ENABLE_MUST_CHECK=y |
1089 | # CONFIG_MAGIC_SYSRQ is not set | 1116 | CONFIG_MAGIC_SYSRQ=y |
1090 | # CONFIG_UNUSED_SYMBOLS is not set | 1117 | # CONFIG_UNUSED_SYMBOLS is not set |
1091 | # CONFIG_DEBUG_FS is not set | 1118 | # CONFIG_DEBUG_FS is not set |
1092 | # CONFIG_HEADERS_CHECK is not set | 1119 | # CONFIG_HEADERS_CHECK is not set |
@@ -1116,16 +1143,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y | |||
1116 | # CONFIG_DEBUGGER is not set | 1143 | # CONFIG_DEBUGGER is not set |
1117 | CONFIG_IRQSTACKS=y | 1144 | CONFIG_IRQSTACKS=y |
1118 | # CONFIG_BOOTX_TEXT is not set | 1145 | # CONFIG_BOOTX_TEXT is not set |
1119 | CONFIG_PPC_EARLY_DEBUG=y | 1146 | # CONFIG_PPC_EARLY_DEBUG is not set |
1120 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
1121 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
1122 | # CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set | ||
1123 | # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set | ||
1124 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
1125 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
1126 | # CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set | ||
1127 | # CONFIG_PPC_EARLY_DEBUG_BEAT is not set | ||
1128 | # CONFIG_PPC_EARLY_DEBUG_44x is not set | ||
1129 | 1147 | ||
1130 | # | 1148 | # |
1131 | # Security options | 1149 | # Security options |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 3e779f07f21b..42c42ecad00c 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -12,7 +12,8 @@ endif | |||
12 | 12 | ||
13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ | 13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ |
14 | irq.o align.o signal_32.o pmc.o vdso.o \ | 14 | irq.o align.o signal_32.o pmc.o vdso.o \ |
15 | init_task.o process.o systbl.o idle.o | 15 | init_task.o process.o systbl.o idle.o \ |
16 | signal.o | ||
16 | obj-y += vdso32/ | 17 | obj-y += vdso32/ |
17 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 18 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ |
18 | signal_64.o ptrace32.o \ | 19 | signal_64.o ptrace32.o \ |
@@ -65,9 +66,9 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o | |||
65 | module-$(CONFIG_PPC64) += module_64.o | 66 | module-$(CONFIG_PPC64) += module_64.o |
66 | obj-$(CONFIG_MODULES) += $(module-y) | 67 | obj-$(CONFIG_MODULES) += $(module-y) |
67 | 68 | ||
68 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o | 69 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o isa-bridge.o |
69 | pci32-$(CONFIG_PPC32) := pci_32.o | 70 | pci32-$(CONFIG_PPC32) := pci_32.o |
70 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) | 71 | obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) pci-common.o |
71 | obj-$(CONFIG_PCI_MSI) += msi.o | 72 | obj-$(CONFIG_PCI_MSI) += msi.o |
72 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o | 73 | kexec-$(CONFIG_PPC64) := machine_kexec_64.o |
73 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o | 74 | kexec-$(CONFIG_PPC32) := machine_kexec_32.o |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index b2b5d664d328..b1f8000952f3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -294,6 +294,21 @@ static struct cpu_spec cpu_specs[] = { | |||
294 | .oprofile_mmcra_sipr = MMCRA_SIPR, | 294 | .oprofile_mmcra_sipr = MMCRA_SIPR, |
295 | .platform = "power5", | 295 | .platform = "power5", |
296 | }, | 296 | }, |
297 | { /* Power5++ */ | ||
298 | .pvr_mask = 0xffffff00, | ||
299 | .pvr_value = 0x003b0300, | ||
300 | .cpu_name = "POWER5+ (gs)", | ||
301 | .cpu_features = CPU_FTRS_POWER5, | ||
302 | .cpu_user_features = COMMON_USER_POWER5_PLUS, | ||
303 | .icache_bsize = 128, | ||
304 | .dcache_bsize = 128, | ||
305 | .num_pmcs = 6, | ||
306 | .oprofile_cpu_type = "ppc64/power5++", | ||
307 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
308 | .oprofile_mmcra_sihv = MMCRA_SIHV, | ||
309 | .oprofile_mmcra_sipr = MMCRA_SIPR, | ||
310 | .platform = "power5+", | ||
311 | }, | ||
297 | { /* Power5 GS */ | 312 | { /* Power5 GS */ |
298 | .pvr_mask = 0xffff0000, | 313 | .pvr_mask = 0xffff0000, |
299 | .pvr_value = 0x003b0000, | 314 | .pvr_value = 0x003b0000, |
@@ -1178,8 +1193,8 @@ static struct cpu_spec cpu_specs[] = { | |||
1178 | .platform = "ppc440", | 1193 | .platform = "ppc440", |
1179 | }, | 1194 | }, |
1180 | { /* 440SP Rev. A */ | 1195 | { /* 440SP Rev. A */ |
1181 | .pvr_mask = 0xff000fff, | 1196 | .pvr_mask = 0xfff00fff, |
1182 | .pvr_value = 0x53000891, | 1197 | .pvr_value = 0x53200891, |
1183 | .cpu_name = "440SP Rev. A", | 1198 | .cpu_name = "440SP Rev. A", |
1184 | .cpu_features = CPU_FTRS_44X, | 1199 | .cpu_features = CPU_FTRS_44X, |
1185 | .cpu_user_features = COMMON_USER_BOOKE, | 1200 | .cpu_user_features = COMMON_USER_BOOKE, |
@@ -1188,9 +1203,19 @@ static struct cpu_spec cpu_specs[] = { | |||
1188 | .platform = "ppc440", | 1203 | .platform = "ppc440", |
1189 | }, | 1204 | }, |
1190 | { /* 440SPe Rev. A */ | 1205 | { /* 440SPe Rev. A */ |
1191 | .pvr_mask = 0xff000fff, | 1206 | .pvr_mask = 0xfff00fff, |
1192 | .pvr_value = 0x53000890, | 1207 | .pvr_value = 0x53400890, |
1193 | .cpu_name = "440SPe Rev. A", | 1208 | .cpu_name = "440SPe Rev. A", |
1209 | .cpu_features = CPU_FTRS_44X, | ||
1210 | .cpu_user_features = COMMON_USER_BOOKE, | ||
1211 | .icache_bsize = 32, | ||
1212 | .dcache_bsize = 32, | ||
1213 | .platform = "ppc440", | ||
1214 | }, | ||
1215 | { /* 440SPe Rev. B */ | ||
1216 | .pvr_mask = 0xfff00fff, | ||
1217 | .pvr_value = 0x53400891, | ||
1218 | .cpu_name = "440SPe Rev. B", | ||
1194 | .cpu_features = CPU_FTRS_44X, | 1219 | .cpu_features = CPU_FTRS_44X, |
1195 | .cpu_user_features = COMMON_USER_BOOKE, | 1220 | .cpu_user_features = COMMON_USER_BOOKE, |
1196 | .icache_bsize = 32, | 1221 | .icache_bsize = 32, |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index c897203198b1..7d73a13450b0 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
@@ -9,7 +9,6 @@ | |||
9 | * rewritten by Paul Mackerras. | 9 | * rewritten by Paul Mackerras. |
10 | * Copyright (C) 1996 Paul Mackerras. | 10 | * Copyright (C) 1996 Paul Mackerras. |
11 | * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). | 11 | * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). |
12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
13 | * | 12 | * |
14 | * This file contains the low-level support and setup for the | 13 | * This file contains the low-level support and setup for the |
15 | * PowerPC platform, including trap and interrupt dispatch. | 14 | * PowerPC platform, including trap and interrupt dispatch. |
@@ -32,10 +31,6 @@ | |||
32 | #include <asm/ppc_asm.h> | 31 | #include <asm/ppc_asm.h> |
33 | #include <asm/asm-offsets.h> | 32 | #include <asm/asm-offsets.h> |
34 | 33 | ||
35 | #ifdef CONFIG_APUS | ||
36 | #include <asm/amigappc.h> | ||
37 | #endif | ||
38 | |||
39 | /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */ | 34 | /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */ |
40 | #define LOAD_BAT(n, reg, RA, RB) \ | 35 | #define LOAD_BAT(n, reg, RA, RB) \ |
41 | /* see the comment for clear_bats() -- Cort */ \ | 36 | /* see the comment for clear_bats() -- Cort */ \ |
@@ -92,11 +87,6 @@ _start: | |||
92 | * r4: virtual address of boot_infos_t | 87 | * r4: virtual address of boot_infos_t |
93 | * r5: 0 | 88 | * r5: 0 |
94 | * | 89 | * |
95 | * APUS | ||
96 | * r3: 'APUS' | ||
97 | * r4: physical address of memory base | ||
98 | * Linux/m68k style BootInfo structure at &_end. | ||
99 | * | ||
100 | * PREP | 90 | * PREP |
101 | * This is jumped to on prep systems right after the kernel is relocated | 91 | * This is jumped to on prep systems right after the kernel is relocated |
102 | * to its proper place in memory by the boot loader. The expected layout | 92 | * to its proper place in memory by the boot loader. The expected layout |
@@ -150,14 +140,6 @@ __start: | |||
150 | */ | 140 | */ |
151 | bl early_init | 141 | bl early_init |
152 | 142 | ||
153 | #ifdef CONFIG_APUS | ||
154 | /* On APUS the __va/__pa constants need to be set to the correct | ||
155 | * values before continuing. | ||
156 | */ | ||
157 | mr r4,r30 | ||
158 | bl fix_mem_constants | ||
159 | #endif /* CONFIG_APUS */ | ||
160 | |||
161 | /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains | 143 | /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains |
162 | * the physical address we are running at, returned by early_init() | 144 | * the physical address we are running at, returned by early_init() |
163 | */ | 145 | */ |
@@ -167,7 +149,7 @@ __after_mmu_off: | |||
167 | bl flush_tlbs | 149 | bl flush_tlbs |
168 | 150 | ||
169 | bl initial_bats | 151 | bl initial_bats |
170 | #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) | 152 | #if defined(CONFIG_BOOTX_TEXT) |
171 | bl setup_disp_bat | 153 | bl setup_disp_bat |
172 | #endif | 154 | #endif |
173 | 155 | ||
@@ -183,7 +165,6 @@ __after_mmu_off: | |||
183 | #endif /* CONFIG_6xx */ | 165 | #endif /* CONFIG_6xx */ |
184 | 166 | ||
185 | 167 | ||
186 | #ifndef CONFIG_APUS | ||
187 | /* | 168 | /* |
188 | * We need to run with _start at physical address 0. | 169 | * We need to run with _start at physical address 0. |
189 | * On CHRP, we are loaded at 0x10000 since OF on CHRP uses | 170 | * On CHRP, we are loaded at 0x10000 since OF on CHRP uses |
@@ -196,7 +177,6 @@ __after_mmu_off: | |||
196 | addis r4,r3,KERNELBASE@h /* current address of _start */ | 177 | addis r4,r3,KERNELBASE@h /* current address of _start */ |
197 | cmpwi 0,r4,0 /* are we already running at 0? */ | 178 | cmpwi 0,r4,0 /* are we already running at 0? */ |
198 | bne relocate_kernel | 179 | bne relocate_kernel |
199 | #endif /* CONFIG_APUS */ | ||
200 | /* | 180 | /* |
201 | * we now have the 1st 16M of ram mapped with the bats. | 181 | * we now have the 1st 16M of ram mapped with the bats. |
202 | * prep needs the mmu to be turned on here, but pmac already has it on. | 182 | * prep needs the mmu to be turned on here, but pmac already has it on. |
@@ -881,85 +861,6 @@ _GLOBAL(copy_and_flush) | |||
881 | addi r6,r6,4 | 861 | addi r6,r6,4 |
882 | blr | 862 | blr |
883 | 863 | ||
884 | #ifdef CONFIG_APUS | ||
885 | /* | ||
886 | * On APUS the physical base address of the kernel is not known at compile | ||
887 | * time, which means the __pa/__va constants used are incorrect. In the | ||
888 | * __init section is recorded the virtual addresses of instructions using | ||
889 | * these constants, so all that has to be done is fix these before | ||
890 | * continuing the kernel boot. | ||
891 | * | ||
892 | * r4 = The physical address of the kernel base. | ||
893 | */ | ||
894 | fix_mem_constants: | ||
895 | mr r10,r4 | ||
896 | addis r10,r10,-KERNELBASE@h /* virt_to_phys constant */ | ||
897 | neg r11,r10 /* phys_to_virt constant */ | ||
898 | |||
899 | lis r12,__vtop_table_begin@h | ||
900 | ori r12,r12,__vtop_table_begin@l | ||
901 | add r12,r12,r10 /* table begin phys address */ | ||
902 | lis r13,__vtop_table_end@h | ||
903 | ori r13,r13,__vtop_table_end@l | ||
904 | add r13,r13,r10 /* table end phys address */ | ||
905 | subi r12,r12,4 | ||
906 | subi r13,r13,4 | ||
907 | 1: lwzu r14,4(r12) /* virt address of instruction */ | ||
908 | add r14,r14,r10 /* phys address of instruction */ | ||
909 | lwz r15,0(r14) /* instruction, now insert top */ | ||
910 | rlwimi r15,r10,16,16,31 /* half of vp const in low half */ | ||
911 | stw r15,0(r14) /* of instruction and restore. */ | ||
912 | dcbst r0,r14 /* write it to memory */ | ||
913 | sync | ||
914 | icbi r0,r14 /* flush the icache line */ | ||
915 | cmpw r12,r13 | ||
916 | bne 1b | ||
917 | sync /* additional sync needed on g4 */ | ||
918 | isync | ||
919 | |||
920 | /* | ||
921 | * Map the memory where the exception handlers will | ||
922 | * be copied to when hash constants have been patched. | ||
923 | */ | ||
924 | #ifdef CONFIG_APUS_FAST_EXCEPT | ||
925 | lis r8,0xfff0 | ||
926 | #else | ||
927 | lis r8,0 | ||
928 | #endif | ||
929 | ori r8,r8,0x2 /* 128KB, supervisor */ | ||
930 | mtspr SPRN_DBAT3U,r8 | ||
931 | mtspr SPRN_DBAT3L,r8 | ||
932 | |||
933 | lis r12,__ptov_table_begin@h | ||
934 | ori r12,r12,__ptov_table_begin@l | ||
935 | add r12,r12,r10 /* table begin phys address */ | ||
936 | lis r13,__ptov_table_end@h | ||
937 | ori r13,r13,__ptov_table_end@l | ||
938 | add r13,r13,r10 /* table end phys address */ | ||
939 | subi r12,r12,4 | ||
940 | subi r13,r13,4 | ||
941 | 1: lwzu r14,4(r12) /* virt address of instruction */ | ||
942 | add r14,r14,r10 /* phys address of instruction */ | ||
943 | lwz r15,0(r14) /* instruction, now insert top */ | ||
944 | rlwimi r15,r11,16,16,31 /* half of pv const in low half*/ | ||
945 | stw r15,0(r14) /* of instruction and restore. */ | ||
946 | dcbst r0,r14 /* write it to memory */ | ||
947 | sync | ||
948 | icbi r0,r14 /* flush the icache line */ | ||
949 | cmpw r12,r13 | ||
950 | bne 1b | ||
951 | |||
952 | sync /* additional sync needed on g4 */ | ||
953 | isync /* No speculative loading until now */ | ||
954 | blr | ||
955 | |||
956 | /*********************************************************************** | ||
957 | * Please note that on APUS the exception handlers are located at the | ||
958 | * physical address 0xfff0000. For this reason, the exception handlers | ||
959 | * cannot use relative branches to access the code below. | ||
960 | ***********************************************************************/ | ||
961 | #endif /* CONFIG_APUS */ | ||
962 | |||
963 | #ifdef CONFIG_SMP | 864 | #ifdef CONFIG_SMP |
964 | #ifdef CONFIG_GEMINI | 865 | #ifdef CONFIG_GEMINI |
965 | .globl __secondary_start_gemini | 866 | .globl __secondary_start_gemini |
@@ -1135,19 +1036,6 @@ start_here: | |||
1135 | bl __save_cpu_setup | 1036 | bl __save_cpu_setup |
1136 | bl MMU_init | 1037 | bl MMU_init |
1137 | 1038 | ||
1138 | #ifdef CONFIG_APUS | ||
1139 | /* Copy exception code to exception vector base on APUS. */ | ||
1140 | lis r4,KERNELBASE@h | ||
1141 | #ifdef CONFIG_APUS_FAST_EXCEPT | ||
1142 | lis r3,0xfff0 /* Copy to 0xfff00000 */ | ||
1143 | #else | ||
1144 | lis r3,0 /* Copy to 0x00000000 */ | ||
1145 | #endif | ||
1146 | li r5,0x4000 /* # bytes of memory to copy */ | ||
1147 | li r6,0 | ||
1148 | bl copy_and_flush /* copy the first 0x4000 bytes */ | ||
1149 | #endif /* CONFIG_APUS */ | ||
1150 | |||
1151 | /* | 1039 | /* |
1152 | * Go back to running unmapped so we can load up new values | 1040 | * Go back to running unmapped so we can load up new values |
1153 | * for SDR1 (hash table pointer) and the segment registers | 1041 | * for SDR1 (hash table pointer) and the segment registers |
@@ -1324,11 +1212,7 @@ initial_bats: | |||
1324 | #else | 1212 | #else |
1325 | ori r8,r8,2 /* R/W access */ | 1213 | ori r8,r8,2 /* R/W access */ |
1326 | #endif /* CONFIG_SMP */ | 1214 | #endif /* CONFIG_SMP */ |
1327 | #ifdef CONFIG_APUS | ||
1328 | ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */ | ||
1329 | #else | ||
1330 | ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ | 1215 | ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ |
1331 | #endif /* CONFIG_APUS */ | ||
1332 | 1216 | ||
1333 | mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ | 1217 | mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ |
1334 | mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */ | 1218 | mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */ |
@@ -1338,7 +1222,7 @@ initial_bats: | |||
1338 | blr | 1222 | blr |
1339 | 1223 | ||
1340 | 1224 | ||
1341 | #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) | 1225 | #ifdef CONFIG_BOOTX_TEXT |
1342 | setup_disp_bat: | 1226 | setup_disp_bat: |
1343 | /* | 1227 | /* |
1344 | * setup the display bat prepared for us in prom.c | 1228 | * setup the display bat prepared for us in prom.c |
@@ -1362,7 +1246,7 @@ setup_disp_bat: | |||
1362 | 1: mtspr SPRN_IBAT3L,r8 | 1246 | 1: mtspr SPRN_IBAT3L,r8 |
1363 | mtspr SPRN_IBAT3U,r11 | 1247 | mtspr SPRN_IBAT3U,r11 |
1364 | blr | 1248 | blr |
1365 | #endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */ | 1249 | #endif /* CONFIG_BOOTX_TEXT */ |
1366 | 1250 | ||
1367 | #ifdef CONFIG_8260 | 1251 | #ifdef CONFIG_8260 |
1368 | /* Jump into the system reset for the rom. | 1252 | /* Jump into the system reset for the rom. |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 1111fcec7673..8cdd48ea4391 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -103,8 +103,8 @@ __secondary_hold_acknowledge: | |||
103 | 103 | ||
104 | . = 0x60 | 104 | . = 0x60 |
105 | /* | 105 | /* |
106 | * The following code is used on pSeries to hold secondary processors | 106 | * The following code is used to hold secondary processors |
107 | * in a spin loop after they have been freed from OpenFirmware, but | 107 | * in a spin loop after they have entered the kernel, but |
108 | * before the bulk of the kernel has been relocated. This code | 108 | * before the bulk of the kernel has been relocated. This code |
109 | * is relocated to physical address 0x60 before prom_init is run. | 109 | * is relocated to physical address 0x60 before prom_init is run. |
110 | * All of it must fit below the first exception vector at 0x100. | 110 | * All of it must fit below the first exception vector at 0x100. |
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index 34ae11494ddc..e31aca9208eb 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c | |||
@@ -35,7 +35,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count) | |||
35 | asm volatile("sync"); | 35 | asm volatile("sync"); |
36 | do { | 36 | do { |
37 | tmp = *port; | 37 | tmp = *port; |
38 | asm volatile("eieio"); | 38 | eieio(); |
39 | *tbuf++ = tmp; | 39 | *tbuf++ = tmp; |
40 | } while (--count != 0); | 40 | } while (--count != 0); |
41 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | 41 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); |
@@ -66,7 +66,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count) | |||
66 | asm volatile("sync"); | 66 | asm volatile("sync"); |
67 | do { | 67 | do { |
68 | tmp = *port; | 68 | tmp = *port; |
69 | asm volatile("eieio"); | 69 | eieio(); |
70 | *tbuf++ = tmp; | 70 | *tbuf++ = tmp; |
71 | } while (--count != 0); | 71 | } while (--count != 0); |
72 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | 72 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); |
@@ -97,7 +97,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count) | |||
97 | asm volatile("sync"); | 97 | asm volatile("sync"); |
98 | do { | 98 | do { |
99 | tmp = *port; | 99 | tmp = *port; |
100 | asm volatile("eieio"); | 100 | eieio(); |
101 | *tbuf++ = tmp; | 101 | *tbuf++ = tmp; |
102 | } while (--count != 0); | 102 | } while (--count != 0); |
103 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); | 103 | asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); |
@@ -155,21 +155,21 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src, | |||
155 | __asm__ __volatile__ ("sync" : : : "memory"); | 155 | __asm__ __volatile__ ("sync" : : : "memory"); |
156 | while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { | 156 | while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { |
157 | *((u8 *)dest) = *((volatile u8 *)vsrc); | 157 | *((u8 *)dest) = *((volatile u8 *)vsrc); |
158 | __asm__ __volatile__ ("eieio" : : : "memory"); | 158 | eieio(); |
159 | vsrc++; | 159 | vsrc++; |
160 | dest++; | 160 | dest++; |
161 | n--; | 161 | n--; |
162 | } | 162 | } |
163 | while(n > 4) { | 163 | while(n > 4) { |
164 | *((u32 *)dest) = *((volatile u32 *)vsrc); | 164 | *((u32 *)dest) = *((volatile u32 *)vsrc); |
165 | __asm__ __volatile__ ("eieio" : : : "memory"); | 165 | eieio(); |
166 | vsrc += 4; | 166 | vsrc += 4; |
167 | dest += 4; | 167 | dest += 4; |
168 | n -= 4; | 168 | n -= 4; |
169 | } | 169 | } |
170 | while(n) { | 170 | while(n) { |
171 | *((u8 *)dest) = *((volatile u8 *)vsrc); | 171 | *((u8 *)dest) = *((volatile u8 *)vsrc); |
172 | __asm__ __volatile__ ("eieio" : : : "memory"); | 172 | eieio(); |
173 | vsrc++; | 173 | vsrc++; |
174 | dest++; | 174 | dest++; |
175 | n--; | 175 | n--; |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index c2b84c64db20..2fc87862146c 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * Copyright (C) 1996-2001 Cort Dougan | 7 | * Copyright (C) 1996-2001 Cort Dougan |
8 | * Adapted for Power Macintosh by Paul Mackerras | 8 | * Adapted for Power Macintosh by Paul Mackerras |
9 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | 9 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) |
10 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
11 | * | 10 | * |
12 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 12 | * modify it under the terms of the GNU General Public License |
@@ -337,7 +336,8 @@ void do_IRQ(struct pt_regs *regs) | |||
337 | 336 | ||
338 | void __init init_IRQ(void) | 337 | void __init init_IRQ(void) |
339 | { | 338 | { |
340 | ppc_md.init_IRQ(); | 339 | if (ppc_md.init_IRQ) |
340 | ppc_md.init_IRQ(); | ||
341 | #ifdef CONFIG_PPC64 | 341 | #ifdef CONFIG_PPC64 |
342 | irq_ctx_init(); | 342 | irq_ctx_init(); |
343 | #endif | 343 | #endif |
@@ -597,6 +597,49 @@ static void irq_radix_rdunlock(unsigned long flags) | |||
597 | local_irq_restore(flags); | 597 | local_irq_restore(flags); |
598 | } | 598 | } |
599 | 599 | ||
600 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, | ||
601 | irq_hw_number_t hwirq) | ||
602 | { | ||
603 | /* Clear IRQ_NOREQUEST flag */ | ||
604 | get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | ||
605 | |||
606 | /* map it */ | ||
607 | smp_wmb(); | ||
608 | irq_map[virq].hwirq = hwirq; | ||
609 | smp_mb(); | ||
610 | |||
611 | if (host->ops->map(host, virq, hwirq)) { | ||
612 | pr_debug("irq: -> mapping failed, freeing\n"); | ||
613 | irq_free_virt(virq, 1); | ||
614 | return -1; | ||
615 | } | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | unsigned int irq_create_direct_mapping(struct irq_host *host) | ||
621 | { | ||
622 | unsigned int virq; | ||
623 | |||
624 | if (host == NULL) | ||
625 | host = irq_default_host; | ||
626 | |||
627 | BUG_ON(host == NULL); | ||
628 | WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP); | ||
629 | |||
630 | virq = irq_alloc_virt(host, 1, 0); | ||
631 | if (virq == NO_IRQ) { | ||
632 | pr_debug("irq: create_direct virq allocation failed\n"); | ||
633 | return NO_IRQ; | ||
634 | } | ||
635 | |||
636 | pr_debug("irq: create_direct obtained virq %d\n", virq); | ||
637 | |||
638 | if (irq_setup_virq(host, virq, virq)) | ||
639 | return NO_IRQ; | ||
640 | |||
641 | return virq; | ||
642 | } | ||
600 | 643 | ||
601 | unsigned int irq_create_mapping(struct irq_host *host, | 644 | unsigned int irq_create_mapping(struct irq_host *host, |
602 | irq_hw_number_t hwirq) | 645 | irq_hw_number_t hwirq) |
@@ -645,18 +688,9 @@ unsigned int irq_create_mapping(struct irq_host *host, | |||
645 | } | 688 | } |
646 | pr_debug("irq: -> obtained virq %d\n", virq); | 689 | pr_debug("irq: -> obtained virq %d\n", virq); |
647 | 690 | ||
648 | /* Clear IRQ_NOREQUEST flag */ | 691 | if (irq_setup_virq(host, virq, hwirq)) |
649 | get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | ||
650 | |||
651 | /* map it */ | ||
652 | smp_wmb(); | ||
653 | irq_map[virq].hwirq = hwirq; | ||
654 | smp_mb(); | ||
655 | if (host->ops->map(host, virq, hwirq)) { | ||
656 | pr_debug("irq: -> mapping failed, freeing\n"); | ||
657 | irq_free_virt(virq, 1); | ||
658 | return NO_IRQ; | 692 | return NO_IRQ; |
659 | } | 693 | |
660 | return virq; | 694 | return virq; |
661 | } | 695 | } |
662 | EXPORT_SYMBOL_GPL(irq_create_mapping); | 696 | EXPORT_SYMBOL_GPL(irq_create_mapping); |
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c new file mode 100644 index 000000000000..f0f49d1be3d5 --- /dev/null +++ b/arch/powerpc/kernel/isa-bridge.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Routines for tracking a legacy ISA bridge | ||
3 | * | ||
4 | * Copyrigh 2007 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. | ||
5 | * | ||
6 | * Some bits and pieces moved over from pci_64.c | ||
7 | * | ||
8 | * Copyrigh 2003 Anton Blanchard <anton@au.ibm.com>, IBM Corp. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #define DEBUG | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/notifier.h> | ||
24 | |||
25 | #include <asm/processor.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/prom.h> | ||
28 | #include <asm/pci-bridge.h> | ||
29 | #include <asm/machdep.h> | ||
30 | #include <asm/ppc-pci.h> | ||
31 | #include <asm/firmware.h> | ||
32 | |||
33 | unsigned long isa_io_base; /* NULL if no ISA bus */ | ||
34 | EXPORT_SYMBOL(isa_io_base); | ||
35 | |||
36 | /* Cached ISA bridge dev. */ | ||
37 | static struct device_node *isa_bridge_devnode; | ||
38 | struct pci_dev *isa_bridge_pcidev; | ||
39 | EXPORT_SYMBOL_GPL(isa_bridge_pcidev); | ||
40 | |||
41 | #define ISA_SPACE_MASK 0x1 | ||
42 | #define ISA_SPACE_IO 0x1 | ||
43 | |||
44 | static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, | ||
45 | unsigned long phb_io_base_phys) | ||
46 | { | ||
47 | /* We should get some saner parsing here and remove these structs */ | ||
48 | struct pci_address { | ||
49 | u32 a_hi; | ||
50 | u32 a_mid; | ||
51 | u32 a_lo; | ||
52 | }; | ||
53 | |||
54 | struct isa_address { | ||
55 | u32 a_hi; | ||
56 | u32 a_lo; | ||
57 | }; | ||
58 | |||
59 | struct isa_range { | ||
60 | struct isa_address isa_addr; | ||
61 | struct pci_address pci_addr; | ||
62 | unsigned int size; | ||
63 | }; | ||
64 | |||
65 | const struct isa_range *range; | ||
66 | unsigned long pci_addr; | ||
67 | unsigned int isa_addr; | ||
68 | unsigned int size; | ||
69 | int rlen = 0; | ||
70 | |||
71 | range = of_get_property(isa_node, "ranges", &rlen); | ||
72 | if (range == NULL || (rlen < sizeof(struct isa_range))) | ||
73 | goto inval_range; | ||
74 | |||
75 | /* From "ISA Binding to 1275" | ||
76 | * The ranges property is laid out as an array of elements, | ||
77 | * each of which comprises: | ||
78 | * cells 0 - 1: an ISA address | ||
79 | * cells 2 - 4: a PCI address | ||
80 | * (size depending on dev->n_addr_cells) | ||
81 | * cell 5: the size of the range | ||
82 | */ | ||
83 | if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) { | ||
84 | range++; | ||
85 | rlen -= sizeof(struct isa_range); | ||
86 | if (rlen < sizeof(struct isa_range)) | ||
87 | goto inval_range; | ||
88 | } | ||
89 | if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) | ||
90 | goto inval_range; | ||
91 | |||
92 | isa_addr = range->isa_addr.a_lo; | ||
93 | pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | | ||
94 | range->pci_addr.a_lo; | ||
95 | |||
96 | /* Assume these are both zero. Note: We could fix that and | ||
97 | * do a proper parsing instead ... oh well, that will do for | ||
98 | * now as nobody uses fancy mappings for ISA bridges | ||
99 | */ | ||
100 | if ((pci_addr != 0) || (isa_addr != 0)) { | ||
101 | printk(KERN_ERR "unexpected isa to pci mapping: %s\n", | ||
102 | __FUNCTION__); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | /* Align size and make sure it's cropped to 64K */ | ||
107 | size = PAGE_ALIGN(range->size); | ||
108 | if (size > 0x10000) | ||
109 | size = 0x10000; | ||
110 | |||
111 | printk(KERN_ERR "no ISA IO ranges or unexpected isa range," | ||
112 | "mapping 64k\n"); | ||
113 | |||
114 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | ||
115 | size, _PAGE_NO_CACHE|_PAGE_GUARDED); | ||
116 | return; | ||
117 | |||
118 | inval_range: | ||
119 | printk(KERN_ERR "no ISA IO ranges or unexpected isa range," | ||
120 | "mapping 64k\n"); | ||
121 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | ||
122 | 0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED); | ||
123 | } | ||
124 | |||
125 | |||
126 | /** | ||
127 | * isa_bridge_find_early - Find and map the ISA IO space early before | ||
128 | * main PCI discovery. This is optionally called by | ||
129 | * the arch code when adding PCI PHBs to get early | ||
130 | * access to ISA IO ports | ||
131 | */ | ||
132 | void __init isa_bridge_find_early(struct pci_controller *hose) | ||
133 | { | ||
134 | struct device_node *np, *parent = NULL, *tmp; | ||
135 | |||
136 | /* If we already have an ISA bridge, bail off */ | ||
137 | if (isa_bridge_devnode != NULL) | ||
138 | return; | ||
139 | |||
140 | /* For each "isa" node in the system. Note : we do a search by | ||
141 | * type and not by name. It might be better to do by name but that's | ||
142 | * what the code used to do and I don't want to break too much at | ||
143 | * once. We can look into changing that separately | ||
144 | */ | ||
145 | for_each_node_by_type(np, "isa") { | ||
146 | /* Look for our hose being a parent */ | ||
147 | for (parent = of_get_parent(np); parent;) { | ||
148 | if (parent == hose->arch_data) { | ||
149 | of_node_put(parent); | ||
150 | break; | ||
151 | } | ||
152 | tmp = parent; | ||
153 | parent = of_get_parent(parent); | ||
154 | of_node_put(tmp); | ||
155 | } | ||
156 | if (parent != NULL) | ||
157 | break; | ||
158 | } | ||
159 | if (np == NULL) | ||
160 | return; | ||
161 | isa_bridge_devnode = np; | ||
162 | |||
163 | /* Now parse the "ranges" property and setup the ISA mapping */ | ||
164 | pci_process_ISA_OF_ranges(np, hose->io_base_phys); | ||
165 | |||
166 | /* Set the global ISA io base to indicate we have an ISA bridge */ | ||
167 | isa_io_base = ISA_IO_BASE; | ||
168 | |||
169 | pr_debug("ISA bridge (early) is %s\n", np->full_name); | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * isa_bridge_find_late - Find and map the ISA IO space upon discovery of | ||
174 | * a new ISA bridge | ||
175 | */ | ||
176 | static void __devinit isa_bridge_find_late(struct pci_dev *pdev, | ||
177 | struct device_node *devnode) | ||
178 | { | ||
179 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | ||
180 | |||
181 | /* Store ISA device node and PCI device */ | ||
182 | isa_bridge_devnode = of_node_get(devnode); | ||
183 | isa_bridge_pcidev = pdev; | ||
184 | |||
185 | /* Now parse the "ranges" property and setup the ISA mapping */ | ||
186 | pci_process_ISA_OF_ranges(devnode, hose->io_base_phys); | ||
187 | |||
188 | /* Set the global ISA io base to indicate we have an ISA bridge */ | ||
189 | isa_io_base = ISA_IO_BASE; | ||
190 | |||
191 | pr_debug("ISA bridge (late) is %s on %s\n", | ||
192 | devnode->full_name, pci_name(pdev)); | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * isa_bridge_remove - Remove/unmap an ISA bridge | ||
197 | */ | ||
198 | static void isa_bridge_remove(void) | ||
199 | { | ||
200 | pr_debug("ISA bridge removed !\n"); | ||
201 | |||
202 | /* Clear the global ISA io base to indicate that we have no more | ||
203 | * ISA bridge. Note that drivers don't quite handle that, though | ||
204 | * we should probably do something about it. But do we ever really | ||
205 | * have ISA bridges being removed on machines using legacy devices ? | ||
206 | */ | ||
207 | isa_io_base = ISA_IO_BASE; | ||
208 | |||
209 | /* Clear references to the bridge */ | ||
210 | of_node_put(isa_bridge_devnode); | ||
211 | isa_bridge_devnode = NULL; | ||
212 | isa_bridge_pcidev = NULL; | ||
213 | |||
214 | /* Unmap the ISA area */ | ||
215 | __iounmap_at((void *)ISA_IO_BASE, 0x10000); | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * isa_bridge_notify - Get notified of PCI devices addition/removal | ||
220 | */ | ||
221 | static int __devinit isa_bridge_notify(struct notifier_block *nb, | ||
222 | unsigned long action, void *data) | ||
223 | { | ||
224 | struct device *dev = data; | ||
225 | struct pci_dev *pdev = to_pci_dev(dev); | ||
226 | struct device_node *devnode = pci_device_to_OF_node(pdev); | ||
227 | |||
228 | switch(action) { | ||
229 | case BUS_NOTIFY_ADD_DEVICE: | ||
230 | /* Check if we have an early ISA device, without PCI dev */ | ||
231 | if (isa_bridge_devnode && isa_bridge_devnode == devnode && | ||
232 | !isa_bridge_pcidev) { | ||
233 | pr_debug("ISA bridge PCI attached: %s\n", | ||
234 | pci_name(pdev)); | ||
235 | isa_bridge_pcidev = pdev; | ||
236 | } | ||
237 | |||
238 | /* Check if we have no ISA device, and this happens to be one, | ||
239 | * register it as such if it has an OF device | ||
240 | */ | ||
241 | if (!isa_bridge_devnode && devnode && devnode->type && | ||
242 | !strcmp(devnode->type, "isa")) | ||
243 | isa_bridge_find_late(pdev, devnode); | ||
244 | |||
245 | return 0; | ||
246 | case BUS_NOTIFY_DEL_DEVICE: | ||
247 | /* Check if this our existing ISA device */ | ||
248 | if (pdev == isa_bridge_pcidev || | ||
249 | (devnode && devnode == isa_bridge_devnode)) | ||
250 | isa_bridge_remove(); | ||
251 | return 0; | ||
252 | } | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static struct notifier_block isa_bridge_notifier = { | ||
257 | .notifier_call = isa_bridge_notify | ||
258 | }; | ||
259 | |||
260 | /** | ||
261 | * isa_bridge_init - register to be notified of ISA bridge addition/removal | ||
262 | * | ||
263 | */ | ||
264 | static int __init isa_bridge_init(void) | ||
265 | { | ||
266 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
267 | return 0; | ||
268 | bus_register_notifier(&pci_bus_type, &isa_bridge_notifier); | ||
269 | return 0; | ||
270 | } | ||
271 | arch_initcall(isa_bridge_init); | ||
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 0c96611f02f4..440f5a87271f 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -492,6 +492,13 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
492 | return ret; | 492 | return ret; |
493 | } | 493 | } |
494 | 494 | ||
495 | #ifdef CONFIG_PPC64 | ||
496 | unsigned long arch_deref_entry_point(void *entry) | ||
497 | { | ||
498 | return (unsigned long)(((func_descr_t *)entry)->entry); | ||
499 | } | ||
500 | #endif | ||
501 | |||
495 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 502 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
496 | { | 503 | { |
497 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 504 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
@@ -500,11 +507,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
500 | memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs)); | 507 | memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs)); |
501 | 508 | ||
502 | /* setup return addr to the jprobe handler routine */ | 509 | /* setup return addr to the jprobe handler routine */ |
510 | regs->nip = arch_deref_entry_point(jp->entry); | ||
503 | #ifdef CONFIG_PPC64 | 511 | #ifdef CONFIG_PPC64 |
504 | regs->nip = (unsigned long)(((func_descr_t *)jp->entry)->entry); | ||
505 | regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc); | 512 | regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc); |
506 | #else | ||
507 | regs->nip = (unsigned long)jp->entry; | ||
508 | #endif | 513 | #endif |
509 | 514 | ||
510 | return 1; | 515 | return 1; |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index c492cee90e0f..6444eaa30a2f 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -248,7 +248,7 @@ static void parse_system_parameter_string(struct seq_file *m) | |||
248 | } else { | 248 | } else { |
249 | int splpar_strlen; | 249 | int splpar_strlen; |
250 | int idx, w_idx; | 250 | int idx, w_idx; |
251 | char *workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); | 251 | char *workbuffer = kzalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); |
252 | if (!workbuffer) { | 252 | if (!workbuffer) { |
253 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", | 253 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", |
254 | __FILE__, __FUNCTION__, __LINE__); | 254 | __FILE__, __FUNCTION__, __LINE__); |
@@ -261,7 +261,6 @@ static void parse_system_parameter_string(struct seq_file *m) | |||
261 | splpar_strlen = local_buffer[0] * 256 + local_buffer[1]; | 261 | splpar_strlen = local_buffer[0] * 256 + local_buffer[1]; |
262 | local_buffer += 2; /* step over strlen value */ | 262 | local_buffer += 2; /* step over strlen value */ |
263 | 263 | ||
264 | memset(workbuffer, 0, SPLPAR_MAXLENGTH); | ||
265 | w_idx = 0; | 264 | w_idx = 0; |
266 | idx = 0; | 265 | idx = 0; |
267 | while ((*local_buffer) && (idx < splpar_strlen)) { | 266 | while ((*local_buffer) && (idx < splpar_strlen)) { |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 98decf8ebff4..e708ab7ca9e8 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -392,7 +392,7 @@ BEGIN_FTR_SECTION | |||
392 | mtspr SPRN_L1CSR0,r3 | 392 | mtspr SPRN_L1CSR0,r3 |
393 | isync | 393 | isync |
394 | blr | 394 | blr |
395 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 395 | END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) |
396 | mfspr r3,SPRN_L1CSR1 | 396 | mfspr r3,SPRN_L1CSR1 |
397 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR | 397 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR |
398 | mtspr SPRN_L1CSR1,r3 | 398 | mtspr SPRN_L1CSR1,r3 |
@@ -419,7 +419,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
419 | _GLOBAL(__flush_icache_range) | 419 | _GLOBAL(__flush_icache_range) |
420 | BEGIN_FTR_SECTION | 420 | BEGIN_FTR_SECTION |
421 | blr /* for 601, do nothing */ | 421 | blr /* for 601, do nothing */ |
422 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 422 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
423 | li r5,L1_CACHE_BYTES-1 | 423 | li r5,L1_CACHE_BYTES-1 |
424 | andc r3,r3,r5 | 424 | andc r3,r3,r5 |
425 | subf r4,r3,r4 | 425 | subf r4,r3,r4 |
@@ -514,8 +514,8 @@ _GLOBAL(invalidate_dcache_range) | |||
514 | */ | 514 | */ |
515 | _GLOBAL(__flush_dcache_icache) | 515 | _GLOBAL(__flush_dcache_icache) |
516 | BEGIN_FTR_SECTION | 516 | BEGIN_FTR_SECTION |
517 | blr /* for 601, do nothing */ | 517 | blr |
518 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 518 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
519 | rlwinm r3,r3,0,0,19 /* Get page base address */ | 519 | rlwinm r3,r3,0,0,19 /* Get page base address */ |
520 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ | 520 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ |
521 | mtctr r4 | 521 | mtctr r4 |
@@ -543,7 +543,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
543 | _GLOBAL(__flush_dcache_icache_phys) | 543 | _GLOBAL(__flush_dcache_icache_phys) |
544 | BEGIN_FTR_SECTION | 544 | BEGIN_FTR_SECTION |
545 | blr /* for 601, do nothing */ | 545 | blr /* for 601, do nothing */ |
546 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 546 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
547 | mfmsr r10 | 547 | mfmsr r10 |
548 | rlwinm r0,r10,0,28,26 /* clear DR */ | 548 | rlwinm r0,r10,0,28,26 /* clear DR */ |
549 | mtmsr r0 | 549 | mtmsr r0 |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 519861da0423..bbb3ba54c51c 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -646,6 +646,19 @@ _GLOBAL(kexec_sequence) | |||
646 | /* turn off mmu */ | 646 | /* turn off mmu */ |
647 | bl real_mode | 647 | bl real_mode |
648 | 648 | ||
649 | /* copy 0x100 bytes starting at start to 0 */ | ||
650 | li r3,0 | ||
651 | mr r4,r30 /* start, aka phys mem offset */ | ||
652 | li r5,0x100 | ||
653 | li r6,0 | ||
654 | bl .copy_and_flush /* (dest, src, copy limit, start offset) */ | ||
655 | 1: /* assume normal blr return */ | ||
656 | |||
657 | /* release other cpus to the new kernel secondary start at 0x60 */ | ||
658 | mflr r5 | ||
659 | li r6,1 | ||
660 | stw r6,kexec_flag-1b(5) | ||
661 | |||
649 | /* clear out hardware hash page table and tlb */ | 662 | /* clear out hardware hash page table and tlb */ |
650 | ld r5,0(r27) /* deref function descriptor */ | 663 | ld r5,0(r27) /* deref function descriptor */ |
651 | mtctr r5 | 664 | mtctr r5 |
@@ -676,19 +689,6 @@ _GLOBAL(kexec_sequence) | |||
676 | * are the boot cpu ????? | 689 | * are the boot cpu ????? |
677 | * other device tree differences (prop sizes, va vs pa, etc)... | 690 | * other device tree differences (prop sizes, va vs pa, etc)... |
678 | */ | 691 | */ |
679 | |||
680 | /* copy 0x100 bytes starting at start to 0 */ | ||
681 | li r3,0 | ||
682 | mr r4,r30 | ||
683 | li r5,0x100 | ||
684 | li r6,0 | ||
685 | bl .copy_and_flush /* (dest, src, copy limit, start offset) */ | ||
686 | 1: /* assume normal blr return */ | ||
687 | |||
688 | /* release other cpus to the new kernel secondary start at 0x60 */ | ||
689 | mflr r5 | ||
690 | li r6,1 | ||
691 | stw r6,kexec_flag-1b(5) | ||
692 | mr r3,r25 # my phys cpu | 692 | mr r3,r25 # my phys cpu |
693 | mr r4,r30 # start, aka phys mem offset | 693 | mr r4,r30 # start, aka phys mem offset |
694 | mtlr 4 | 694 | mtlr 4 |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index d454f61c9c7c..8ded4e7dc87e 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
@@ -222,10 +222,9 @@ struct of_device* of_platform_device_create(struct device_node *np, | |||
222 | { | 222 | { |
223 | struct of_device *dev; | 223 | struct of_device *dev; |
224 | 224 | ||
225 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | 225 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
226 | if (!dev) | 226 | if (!dev) |
227 | return NULL; | 227 | return NULL; |
228 | memset(dev, 0, sizeof(*dev)); | ||
229 | 228 | ||
230 | dev->node = of_node_get(np); | 229 | dev->node = of_node_get(np); |
231 | dev->dma_mask = 0xffffffffUL; | 230 | dev->dma_mask = 0xffffffffUL; |
@@ -427,14 +426,6 @@ static int __devinit of_pci_phb_probe(struct of_device *dev, | |||
427 | /* Process "ranges" property */ | 426 | /* Process "ranges" property */ |
428 | pci_process_bridge_OF_ranges(phb, dev->node, 0); | 427 | pci_process_bridge_OF_ranges(phb, dev->node, 0); |
429 | 428 | ||
430 | /* Setup IO space. We use the non-dynamic version of that code here, | ||
431 | * which doesn't quite support unplugging. Next kernel release will | ||
432 | * have a better fix for this. | ||
433 | * Note also that we don't do ISA, this will also be fixed with a | ||
434 | * more massive rework. | ||
435 | */ | ||
436 | pci_setup_phb_io(phb, pci_io_base == 0); | ||
437 | |||
438 | /* Init pci_dn data structures */ | 429 | /* Init pci_dn data structures */ |
439 | pci_devs_phb_init_dynamic(phb); | 430 | pci_devs_phb_init_dynamic(phb); |
440 | 431 | ||
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c new file mode 100644 index 000000000000..94b4a028232a --- /dev/null +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -0,0 +1,457 @@ | |||
1 | /* | ||
2 | * Contains common pci routines for ALL ppc platform | ||
3 | * (based on pci_32.c and pci_64.c) | ||
4 | * | ||
5 | * Port for PPC64 David Engebretsen, IBM Corp. | ||
6 | * Contains common pci routines for ppc64 platform, pSeries and iSeries brands. | ||
7 | * | ||
8 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | ||
9 | * Rework, based on alpha PCI code. | ||
10 | * | ||
11 | * Common pmac/prep/chrp pci routines. -- Cort | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version | ||
16 | * 2 of the License, or (at your option) any later version. | ||
17 | */ | ||
18 | |||
19 | #undef DEBUG | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/bootmem.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/syscalls.h> | ||
29 | #include <linux/irq.h> | ||
30 | #include <linux/vmalloc.h> | ||
31 | |||
32 | #include <asm/processor.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/prom.h> | ||
35 | #include <asm/pci-bridge.h> | ||
36 | #include <asm/byteorder.h> | ||
37 | #include <asm/machdep.h> | ||
38 | #include <asm/ppc-pci.h> | ||
39 | #include <asm/firmware.h> | ||
40 | |||
41 | #ifdef DEBUG | ||
42 | #include <asm/udbg.h> | ||
43 | #define DBG(fmt...) printk(fmt) | ||
44 | #else | ||
45 | #define DBG(fmt...) | ||
46 | #endif | ||
47 | |||
48 | static DEFINE_SPINLOCK(hose_spinlock); | ||
49 | |||
50 | /* XXX kill that some day ... */ | ||
51 | int global_phb_number; /* Global phb counter */ | ||
52 | |||
53 | extern struct list_head hose_list; | ||
54 | |||
55 | /* | ||
56 | * pci_controller(phb) initialized common variables. | ||
57 | */ | ||
58 | static void __devinit pci_setup_pci_controller(struct pci_controller *hose) | ||
59 | { | ||
60 | memset(hose, 0, sizeof(struct pci_controller)); | ||
61 | |||
62 | spin_lock(&hose_spinlock); | ||
63 | hose->global_number = global_phb_number++; | ||
64 | list_add_tail(&hose->list_node, &hose_list); | ||
65 | spin_unlock(&hose_spinlock); | ||
66 | } | ||
67 | |||
68 | struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | ||
69 | { | ||
70 | struct pci_controller *phb; | ||
71 | |||
72 | if (mem_init_done) | ||
73 | phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | ||
74 | else | ||
75 | phb = alloc_bootmem(sizeof (struct pci_controller)); | ||
76 | if (phb == NULL) | ||
77 | return NULL; | ||
78 | pci_setup_pci_controller(phb); | ||
79 | phb->arch_data = dev; | ||
80 | phb->is_dynamic = mem_init_done; | ||
81 | #ifdef CONFIG_PPC64 | ||
82 | if (dev) { | ||
83 | int nid = of_node_to_nid(dev); | ||
84 | |||
85 | if (nid < 0 || !node_online(nid)) | ||
86 | nid = -1; | ||
87 | |||
88 | PHB_SET_NODE(phb, nid); | ||
89 | } | ||
90 | #endif | ||
91 | return phb; | ||
92 | } | ||
93 | |||
94 | void pcibios_free_controller(struct pci_controller *phb) | ||
95 | { | ||
96 | spin_lock(&hose_spinlock); | ||
97 | list_del(&phb->list_node); | ||
98 | spin_unlock(&hose_spinlock); | ||
99 | |||
100 | if (phb->is_dynamic) | ||
101 | kfree(phb); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Return the domain number for this bus. | ||
106 | */ | ||
107 | int pci_domain_nr(struct pci_bus *bus) | ||
108 | { | ||
109 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
110 | return 0; | ||
111 | else { | ||
112 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
113 | |||
114 | return hose->global_number; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | EXPORT_SYMBOL(pci_domain_nr); | ||
119 | |||
120 | #ifdef CONFIG_PPC_OF | ||
121 | |||
122 | /* This routine is meant to be used early during boot, when the | ||
123 | * PCI bus numbers have not yet been assigned, and you need to | ||
124 | * issue PCI config cycles to an OF device. | ||
125 | * It could also be used to "fix" RTAS config cycles if you want | ||
126 | * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||
127 | * config cycles. | ||
128 | */ | ||
129 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
130 | { | ||
131 | if (!have_of) | ||
132 | return NULL; | ||
133 | while(node) { | ||
134 | struct pci_controller *hose, *tmp; | ||
135 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||
136 | if (hose->arch_data == node) | ||
137 | return hose; | ||
138 | node = node->parent; | ||
139 | } | ||
140 | return NULL; | ||
141 | } | ||
142 | |||
143 | static ssize_t pci_show_devspec(struct device *dev, | ||
144 | struct device_attribute *attr, char *buf) | ||
145 | { | ||
146 | struct pci_dev *pdev; | ||
147 | struct device_node *np; | ||
148 | |||
149 | pdev = to_pci_dev (dev); | ||
150 | np = pci_device_to_OF_node(pdev); | ||
151 | if (np == NULL || np->full_name == NULL) | ||
152 | return 0; | ||
153 | return sprintf(buf, "%s", np->full_name); | ||
154 | } | ||
155 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
156 | #endif /* CONFIG_PPC_OF */ | ||
157 | |||
158 | /* Add sysfs properties */ | ||
159 | int pcibios_add_platform_entries(struct pci_dev *pdev) | ||
160 | { | ||
161 | #ifdef CONFIG_PPC_OF | ||
162 | return device_create_file(&pdev->dev, &dev_attr_devspec); | ||
163 | #else | ||
164 | return 0; | ||
165 | #endif /* CONFIG_PPC_OF */ | ||
166 | |||
167 | } | ||
168 | |||
169 | char __init *pcibios_setup(char *str) | ||
170 | { | ||
171 | return str; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
176 | * If the interrupt is used, then gets the interrupt line from the | ||
177 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
178 | */ | ||
179 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
180 | { | ||
181 | struct of_irq oirq; | ||
182 | unsigned int virq; | ||
183 | |||
184 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
185 | |||
186 | #ifdef DEBUG | ||
187 | memset(&oirq, 0xff, sizeof(oirq)); | ||
188 | #endif | ||
189 | /* Try to get a mapping from the device-tree */ | ||
190 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
191 | u8 line, pin; | ||
192 | |||
193 | /* If that fails, lets fallback to what is in the config | ||
194 | * space and map that through the default controller. We | ||
195 | * also set the type to level low since that's what PCI | ||
196 | * interrupts are. If your platform does differently, then | ||
197 | * either provide a proper interrupt tree or don't use this | ||
198 | * function. | ||
199 | */ | ||
200 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
201 | return -1; | ||
202 | if (pin == 0) | ||
203 | return -1; | ||
204 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
205 | line == 0xff) { | ||
206 | return -1; | ||
207 | } | ||
208 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
209 | |||
210 | virq = irq_create_mapping(NULL, line); | ||
211 | if (virq != NO_IRQ) | ||
212 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
213 | } else { | ||
214 | DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||
215 | oirq.size, oirq.specifier[0], oirq.specifier[1], | ||
216 | oirq.controller->full_name); | ||
217 | |||
218 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
219 | oirq.size); | ||
220 | } | ||
221 | if(virq == NO_IRQ) { | ||
222 | DBG(" -> failed to map !\n"); | ||
223 | return -1; | ||
224 | } | ||
225 | |||
226 | DBG(" -> mapped to linux irq %d\n", virq); | ||
227 | |||
228 | pci_dev->irq = virq; | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | EXPORT_SYMBOL(pci_read_irq_line); | ||
233 | |||
234 | /* | ||
235 | * Platform support for /proc/bus/pci/X/Y mmap()s, | ||
236 | * modelled on the sparc64 implementation by Dave Miller. | ||
237 | * -- paulus. | ||
238 | */ | ||
239 | |||
240 | /* | ||
241 | * Adjust vm_pgoff of VMA such that it is the physical page offset | ||
242 | * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||
243 | * | ||
244 | * Basically, the user finds the base address for his device which he wishes | ||
245 | * to mmap. They read the 32-bit value from the config space base register, | ||
246 | * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||
247 | * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||
248 | * | ||
249 | * Returns negative error code on failure, zero on success. | ||
250 | */ | ||
251 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
252 | resource_size_t *offset, | ||
253 | enum pci_mmap_state mmap_state) | ||
254 | { | ||
255 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
256 | unsigned long io_offset = 0; | ||
257 | int i, res_bit; | ||
258 | |||
259 | if (hose == 0) | ||
260 | return NULL; /* should never happen */ | ||
261 | |||
262 | /* If memory, add on the PCI bridge address offset */ | ||
263 | if (mmap_state == pci_mmap_mem) { | ||
264 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
265 | *offset += hose->pci_mem_offset; | ||
266 | #endif | ||
267 | res_bit = IORESOURCE_MEM; | ||
268 | } else { | ||
269 | io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
270 | *offset += io_offset; | ||
271 | res_bit = IORESOURCE_IO; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Check that the offset requested corresponds to one of the | ||
276 | * resources of the device. | ||
277 | */ | ||
278 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
279 | struct resource *rp = &dev->resource[i]; | ||
280 | int flags = rp->flags; | ||
281 | |||
282 | /* treat ROM as memory (should be already) */ | ||
283 | if (i == PCI_ROM_RESOURCE) | ||
284 | flags |= IORESOURCE_MEM; | ||
285 | |||
286 | /* Active and same type? */ | ||
287 | if ((flags & res_bit) == 0) | ||
288 | continue; | ||
289 | |||
290 | /* In the range of this resource? */ | ||
291 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
292 | continue; | ||
293 | |||
294 | /* found it! construct the final physical address */ | ||
295 | if (mmap_state == pci_mmap_io) | ||
296 | *offset += hose->io_base_phys - io_offset; | ||
297 | return rp; | ||
298 | } | ||
299 | |||
300 | return NULL; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
305 | * device mapping. | ||
306 | */ | ||
307 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
308 | pgprot_t protection, | ||
309 | enum pci_mmap_state mmap_state, | ||
310 | int write_combine) | ||
311 | { | ||
312 | unsigned long prot = pgprot_val(protection); | ||
313 | |||
314 | /* Write combine is always 0 on non-memory space mappings. On | ||
315 | * memory space, if the user didn't pass 1, we check for a | ||
316 | * "prefetchable" resource. This is a bit hackish, but we use | ||
317 | * this to workaround the inability of /sysfs to provide a write | ||
318 | * combine bit | ||
319 | */ | ||
320 | if (mmap_state != pci_mmap_mem) | ||
321 | write_combine = 0; | ||
322 | else if (write_combine == 0) { | ||
323 | if (rp->flags & IORESOURCE_PREFETCH) | ||
324 | write_combine = 1; | ||
325 | } | ||
326 | |||
327 | /* XXX would be nice to have a way to ask for write-through */ | ||
328 | prot |= _PAGE_NO_CACHE; | ||
329 | if (write_combine) | ||
330 | prot &= ~_PAGE_GUARDED; | ||
331 | else | ||
332 | prot |= _PAGE_GUARDED; | ||
333 | |||
334 | return __pgprot(prot); | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
339 | * PCI device, it tries to find the PCI device first and calls the | ||
340 | * above routine | ||
341 | */ | ||
342 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
343 | unsigned long pfn, | ||
344 | unsigned long size, | ||
345 | pgprot_t protection) | ||
346 | { | ||
347 | struct pci_dev *pdev = NULL; | ||
348 | struct resource *found = NULL; | ||
349 | unsigned long prot = pgprot_val(protection); | ||
350 | unsigned long offset = pfn << PAGE_SHIFT; | ||
351 | int i; | ||
352 | |||
353 | if (page_is_ram(pfn)) | ||
354 | return __pgprot(prot); | ||
355 | |||
356 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
357 | |||
358 | for_each_pci_dev(pdev) { | ||
359 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
360 | struct resource *rp = &pdev->resource[i]; | ||
361 | int flags = rp->flags; | ||
362 | |||
363 | /* Active and same type? */ | ||
364 | if ((flags & IORESOURCE_MEM) == 0) | ||
365 | continue; | ||
366 | /* In the range of this resource? */ | ||
367 | if (offset < (rp->start & PAGE_MASK) || | ||
368 | offset > rp->end) | ||
369 | continue; | ||
370 | found = rp; | ||
371 | break; | ||
372 | } | ||
373 | if (found) | ||
374 | break; | ||
375 | } | ||
376 | if (found) { | ||
377 | if (found->flags & IORESOURCE_PREFETCH) | ||
378 | prot &= ~_PAGE_GUARDED; | ||
379 | pci_dev_put(pdev); | ||
380 | } | ||
381 | |||
382 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
383 | |||
384 | return __pgprot(prot); | ||
385 | } | ||
386 | |||
387 | |||
388 | /* | ||
389 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
390 | * appropriate for this architecture. The region in the process to map | ||
391 | * is described by vm_start and vm_end members of VMA, the base physical | ||
392 | * address is found in vm_pgoff. | ||
393 | * The pci device structure is provided so that architectures may make mapping | ||
394 | * decisions on a per-device or per-bus basis. | ||
395 | * | ||
396 | * Returns a negative error code on failure, zero on success. | ||
397 | */ | ||
398 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
399 | enum pci_mmap_state mmap_state, int write_combine) | ||
400 | { | ||
401 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
402 | struct resource *rp; | ||
403 | int ret; | ||
404 | |||
405 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
406 | if (rp == NULL) | ||
407 | return -EINVAL; | ||
408 | |||
409 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
410 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
411 | vma->vm_page_prot, | ||
412 | mmap_state, write_combine); | ||
413 | |||
414 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
415 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
416 | |||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
421 | const struct resource *rsrc, | ||
422 | resource_size_t *start, resource_size_t *end) | ||
423 | { | ||
424 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
425 | resource_size_t offset = 0; | ||
426 | |||
427 | if (hose == NULL) | ||
428 | return; | ||
429 | |||
430 | if (rsrc->flags & IORESOURCE_IO) | ||
431 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
432 | |||
433 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
434 | * a BAR value because X is lame and expects to be able to use that | ||
435 | * to pass to /dev/mem ! | ||
436 | * | ||
437 | * That means that we'll have potentially 64 bits values where some | ||
438 | * userland apps only expect 32 (like X itself since it thinks only | ||
439 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
440 | * 32 bits CHRPs :-( | ||
441 | * | ||
442 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
443 | * has been fixed (and the fix spread enough), we can re-enable the | ||
444 | * 2 lines below and pass down a BAR value to userland. In that case | ||
445 | * we'll also have to re-enable the matching code in | ||
446 | * __pci_mmap_make_offset(). | ||
447 | * | ||
448 | * BenH. | ||
449 | */ | ||
450 | #if 0 | ||
451 | else if (rsrc->flags & IORESOURCE_MEM) | ||
452 | offset = hose->pci_mem_offset; | ||
453 | #endif | ||
454 | |||
455 | *start = rsrc->start - offset; | ||
456 | *end = rsrc->end - offset; | ||
457 | } | ||
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 86982112b0dd..0adf077f3f3a 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -55,8 +55,7 @@ static u8* pci_to_OF_bus_map; | |||
55 | */ | 55 | */ |
56 | int pci_assign_all_buses; | 56 | int pci_assign_all_buses; |
57 | 57 | ||
58 | struct pci_controller* hose_head; | 58 | LIST_HEAD(hose_list); |
59 | struct pci_controller** hose_tail = &hose_head; | ||
60 | 59 | ||
61 | static int pci_bus_count; | 60 | static int pci_bus_count; |
62 | 61 | ||
@@ -573,58 +572,6 @@ pcibios_assign_resources(void) | |||
573 | } | 572 | } |
574 | } | 573 | } |
575 | 574 | ||
576 | |||
577 | int | ||
578 | pcibios_enable_resources(struct pci_dev *dev, int mask) | ||
579 | { | ||
580 | u16 cmd, old_cmd; | ||
581 | int idx; | ||
582 | struct resource *r; | ||
583 | |||
584 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
585 | old_cmd = cmd; | ||
586 | for (idx=0; idx<6; idx++) { | ||
587 | /* Only set up the requested stuff */ | ||
588 | if (!(mask & (1<<idx))) | ||
589 | continue; | ||
590 | |||
591 | r = &dev->resource[idx]; | ||
592 | if (r->flags & IORESOURCE_UNSET) { | ||
593 | printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); | ||
594 | return -EINVAL; | ||
595 | } | ||
596 | if (r->flags & IORESOURCE_IO) | ||
597 | cmd |= PCI_COMMAND_IO; | ||
598 | if (r->flags & IORESOURCE_MEM) | ||
599 | cmd |= PCI_COMMAND_MEMORY; | ||
600 | } | ||
601 | if (dev->resource[PCI_ROM_RESOURCE].start) | ||
602 | cmd |= PCI_COMMAND_MEMORY; | ||
603 | if (cmd != old_cmd) { | ||
604 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); | ||
605 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
606 | } | ||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static int next_controller_index; | ||
611 | |||
612 | struct pci_controller * __init | ||
613 | pcibios_alloc_controller(void) | ||
614 | { | ||
615 | struct pci_controller *hose; | ||
616 | |||
617 | hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); | ||
618 | memset(hose, 0, sizeof(struct pci_controller)); | ||
619 | |||
620 | *hose_tail = hose; | ||
621 | hose_tail = &hose->next; | ||
622 | |||
623 | hose->index = next_controller_index++; | ||
624 | |||
625 | return hose; | ||
626 | } | ||
627 | |||
628 | #ifdef CONFIG_PPC_OF | 575 | #ifdef CONFIG_PPC_OF |
629 | /* | 576 | /* |
630 | * Functions below are used on OpenFirmware machines. | 577 | * Functions below are used on OpenFirmware machines. |
@@ -670,7 +617,7 @@ void | |||
670 | pcibios_make_OF_bus_map(void) | 617 | pcibios_make_OF_bus_map(void) |
671 | { | 618 | { |
672 | int i; | 619 | int i; |
673 | struct pci_controller* hose; | 620 | struct pci_controller *hose, *tmp; |
674 | struct property *map_prop; | 621 | struct property *map_prop; |
675 | struct device_node *dn; | 622 | struct device_node *dn; |
676 | 623 | ||
@@ -687,7 +634,7 @@ pcibios_make_OF_bus_map(void) | |||
687 | pci_to_OF_bus_map[i] = 0xff; | 634 | pci_to_OF_bus_map[i] = 0xff; |
688 | 635 | ||
689 | /* For each hose, we begin searching bridges */ | 636 | /* For each hose, we begin searching bridges */ |
690 | for(hose=hose_head; hose; hose=hose->next) { | 637 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
691 | struct device_node* node; | 638 | struct device_node* node; |
692 | node = (struct device_node *)hose->arch_data; | 639 | node = (struct device_node *)hose->arch_data; |
693 | if (!node) | 640 | if (!node) |
@@ -765,7 +712,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus) | |||
765 | 712 | ||
766 | /* Are we a root bus ? */ | 713 | /* Are we a root bus ? */ |
767 | if (bus->self == NULL || bus->parent == NULL) { | 714 | if (bus->self == NULL || bus->parent == NULL) { |
768 | struct pci_controller *hose = pci_bus_to_hose(bus->number); | 715 | struct pci_controller *hose = pci_bus_to_host(bus); |
769 | if (hose == NULL) | 716 | if (hose == NULL) |
770 | return NULL; | 717 | return NULL; |
771 | return of_node_get(hose->arch_data); | 718 | return of_node_get(hose->arch_data); |
@@ -818,27 +765,6 @@ pci_device_to_OF_node(struct pci_dev *dev) | |||
818 | } | 765 | } |
819 | EXPORT_SYMBOL(pci_device_to_OF_node); | 766 | EXPORT_SYMBOL(pci_device_to_OF_node); |
820 | 767 | ||
821 | /* This routine is meant to be used early during boot, when the | ||
822 | * PCI bus numbers have not yet been assigned, and you need to | ||
823 | * issue PCI config cycles to an OF device. | ||
824 | * It could also be used to "fix" RTAS config cycles if you want | ||
825 | * to set pci_assign_all_buses to 1 and still use RTAS for PCI | ||
826 | * config cycles. | ||
827 | */ | ||
828 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
829 | { | ||
830 | if (!have_of) | ||
831 | return NULL; | ||
832 | while(node) { | ||
833 | struct pci_controller* hose; | ||
834 | for (hose=hose_head;hose;hose=hose->next) | ||
835 | if (hose->arch_data == node) | ||
836 | return hose; | ||
837 | node=node->parent; | ||
838 | } | ||
839 | return NULL; | ||
840 | } | ||
841 | |||
842 | static int | 768 | static int |
843 | find_OF_pci_device_filter(struct device_node* node, void* data) | 769 | find_OF_pci_device_filter(struct device_node* node, void* data) |
844 | { | 770 | { |
@@ -1027,34 +953,12 @@ pci_create_OF_bus_map(void) | |||
1027 | } | 953 | } |
1028 | } | 954 | } |
1029 | 955 | ||
1030 | static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | ||
1031 | { | ||
1032 | struct pci_dev *pdev; | ||
1033 | struct device_node *np; | ||
1034 | |||
1035 | pdev = to_pci_dev (dev); | ||
1036 | np = pci_device_to_OF_node(pdev); | ||
1037 | if (np == NULL || np->full_name == NULL) | ||
1038 | return 0; | ||
1039 | return sprintf(buf, "%s", np->full_name); | ||
1040 | } | ||
1041 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
1042 | |||
1043 | #else /* CONFIG_PPC_OF */ | 956 | #else /* CONFIG_PPC_OF */ |
1044 | void pcibios_make_OF_bus_map(void) | 957 | void pcibios_make_OF_bus_map(void) |
1045 | { | 958 | { |
1046 | } | 959 | } |
1047 | #endif /* CONFIG_PPC_OF */ | 960 | #endif /* CONFIG_PPC_OF */ |
1048 | 961 | ||
1049 | /* Add sysfs properties */ | ||
1050 | int pcibios_add_platform_entries(struct pci_dev *pdev) | ||
1051 | { | ||
1052 | #ifdef CONFIG_PPC_OF | ||
1053 | return device_create_file(&pdev->dev, &dev_attr_devspec); | ||
1054 | #endif /* CONFIG_PPC_OF */ | ||
1055 | } | ||
1056 | |||
1057 | |||
1058 | #ifdef CONFIG_PPC_PMAC | 962 | #ifdef CONFIG_PPC_PMAC |
1059 | /* | 963 | /* |
1060 | * This set of routines checks for PCI<->PCI bridges that have closed | 964 | * This set of routines checks for PCI<->PCI bridges that have closed |
@@ -1269,14 +1173,14 @@ pcibios_fixup_p2p_bridges(void) | |||
1269 | static int __init | 1173 | static int __init |
1270 | pcibios_init(void) | 1174 | pcibios_init(void) |
1271 | { | 1175 | { |
1272 | struct pci_controller *hose; | 1176 | struct pci_controller *hose, *tmp; |
1273 | struct pci_bus *bus; | 1177 | struct pci_bus *bus; |
1274 | int next_busno; | 1178 | int next_busno = 0; |
1275 | 1179 | ||
1276 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); | 1180 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); |
1277 | 1181 | ||
1278 | /* Scan all of the recorded PCI controllers. */ | 1182 | /* Scan all of the recorded PCI controllers. */ |
1279 | for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { | 1183 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
1280 | if (pci_assign_all_buses) | 1184 | if (pci_assign_all_buses) |
1281 | hose->first_busno = next_busno; | 1185 | hose->first_busno = next_busno; |
1282 | hose->last_busno = 0xff; | 1186 | hose->last_busno = 0xff; |
@@ -1319,12 +1223,6 @@ pcibios_init(void) | |||
1319 | 1223 | ||
1320 | subsys_initcall(pcibios_init); | 1224 | subsys_initcall(pcibios_init); |
1321 | 1225 | ||
1322 | unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, | ||
1323 | unsigned long start, unsigned long size) | ||
1324 | { | ||
1325 | return start; | ||
1326 | } | ||
1327 | |||
1328 | void __init pcibios_fixup_bus(struct pci_bus *bus) | 1226 | void __init pcibios_fixup_bus(struct pci_bus *bus) |
1329 | { | 1227 | { |
1330 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; | 1228 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; |
@@ -1342,7 +1240,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
1342 | if (!res->flags) { | 1240 | if (!res->flags) { |
1343 | if (io_offset) | 1241 | if (io_offset) |
1344 | printk(KERN_ERR "I/O resource not set for host" | 1242 | printk(KERN_ERR "I/O resource not set for host" |
1345 | " bridge %d\n", hose->index); | 1243 | " bridge %d\n", hose->global_number); |
1346 | res->start = 0; | 1244 | res->start = 0; |
1347 | res->end = IO_SPACE_LIMIT; | 1245 | res->end = IO_SPACE_LIMIT; |
1348 | res->flags = IORESOURCE_IO; | 1246 | res->flags = IORESOURCE_IO; |
@@ -1356,7 +1254,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
1356 | if (i > 0) | 1254 | if (i > 0) |
1357 | continue; | 1255 | continue; |
1358 | printk(KERN_ERR "Memory resource not set for " | 1256 | printk(KERN_ERR "Memory resource not set for " |
1359 | "host bridge %d\n", hose->index); | 1257 | "host bridge %d\n", hose->global_number); |
1360 | res->start = hose->pci_mem_offset; | 1258 | res->start = hose->pci_mem_offset; |
1361 | res->end = ~0U; | 1259 | res->end = ~0U; |
1362 | res->flags = IORESOURCE_MEM; | 1260 | res->flags = IORESOURCE_MEM; |
@@ -1370,7 +1268,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
1370 | for (i = 0; i < 4; ++i) { | 1268 | for (i = 0; i < 4; ++i) { |
1371 | if ((res = bus->resource[i]) == NULL) | 1269 | if ((res = bus->resource[i]) == NULL) |
1372 | continue; | 1270 | continue; |
1373 | if (!res->flags) | 1271 | if (!res->flags || bus->self->transparent) |
1374 | continue; | 1272 | continue; |
1375 | if (io_offset && (res->flags & IORESOURCE_IO)) { | 1273 | if (io_offset && (res->flags & IORESOURCE_IO)) { |
1376 | res->start += io_offset; | 1274 | res->start += io_offset; |
@@ -1395,11 +1293,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) | |||
1395 | } | 1293 | } |
1396 | } | 1294 | } |
1397 | 1295 | ||
1398 | char __init *pcibios_setup(char *str) | ||
1399 | { | ||
1400 | return str; | ||
1401 | } | ||
1402 | |||
1403 | /* the next one is stolen from the alpha port... */ | 1296 | /* the next one is stolen from the alpha port... */ |
1404 | void __init | 1297 | void __init |
1405 | pcibios_update_irq(struct pci_dev *dev, int irq) | 1298 | pcibios_update_irq(struct pci_dev *dev, int irq) |
@@ -1408,64 +1301,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq) | |||
1408 | /* XXX FIXME - update OF device tree node interrupt property */ | 1301 | /* XXX FIXME - update OF device tree node interrupt property */ |
1409 | } | 1302 | } |
1410 | 1303 | ||
1411 | #ifdef CONFIG_PPC_MERGE | ||
1412 | /* XXX This is a copy of the ppc64 version. This is temporary until we start | ||
1413 | * merging the 2 PCI layers | ||
1414 | */ | ||
1415 | /* | ||
1416 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
1417 | * If the interrupt is used, then gets the interrupt line from the | ||
1418 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
1419 | */ | ||
1420 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
1421 | { | ||
1422 | struct of_irq oirq; | ||
1423 | unsigned int virq; | ||
1424 | |||
1425 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
1426 | |||
1427 | /* Try to get a mapping from the device-tree */ | ||
1428 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
1429 | u8 line, pin; | ||
1430 | |||
1431 | /* If that fails, lets fallback to what is in the config | ||
1432 | * space and map that through the default controller. We | ||
1433 | * also set the type to level low since that's what PCI | ||
1434 | * interrupts are. If your platform does differently, then | ||
1435 | * either provide a proper interrupt tree or don't use this | ||
1436 | * function. | ||
1437 | */ | ||
1438 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
1439 | return -1; | ||
1440 | if (pin == 0) | ||
1441 | return -1; | ||
1442 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
1443 | line == 0xff) { | ||
1444 | return -1; | ||
1445 | } | ||
1446 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
1447 | |||
1448 | virq = irq_create_mapping(NULL, line); | ||
1449 | if (virq != NO_IRQ) | ||
1450 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
1451 | } else { | ||
1452 | DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", | ||
1453 | oirq.size, oirq.specifier[0], oirq.controller->full_name); | ||
1454 | |||
1455 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
1456 | oirq.size); | ||
1457 | } | ||
1458 | if(virq == NO_IRQ) { | ||
1459 | DBG(" -> failed to map !\n"); | ||
1460 | return -1; | ||
1461 | } | ||
1462 | pci_dev->irq = virq; | ||
1463 | |||
1464 | return 0; | ||
1465 | } | ||
1466 | EXPORT_SYMBOL(pci_read_irq_line); | ||
1467 | #endif /* CONFIG_PPC_MERGE */ | ||
1468 | |||
1469 | int pcibios_enable_device(struct pci_dev *dev, int mask) | 1304 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
1470 | { | 1305 | { |
1471 | u16 cmd, old_cmd; | 1306 | u16 cmd, old_cmd; |
@@ -1497,281 +1332,17 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
1497 | return 0; | 1332 | return 0; |
1498 | } | 1333 | } |
1499 | 1334 | ||
1500 | struct pci_controller* | 1335 | static struct pci_controller* |
1501 | pci_bus_to_hose(int bus) | 1336 | pci_bus_to_hose(int bus) |
1502 | { | 1337 | { |
1503 | struct pci_controller* hose = hose_head; | 1338 | struct pci_controller *hose, *tmp; |
1504 | 1339 | ||
1505 | for (; hose; hose = hose->next) | 1340 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) |
1506 | if (bus >= hose->first_busno && bus <= hose->last_busno) | 1341 | if (bus >= hose->first_busno && bus <= hose->last_busno) |
1507 | return hose; | 1342 | return hose; |
1508 | return NULL; | 1343 | return NULL; |
1509 | } | 1344 | } |
1510 | 1345 | ||
1511 | void __iomem * | ||
1512 | pci_bus_io_base(unsigned int bus) | ||
1513 | { | ||
1514 | struct pci_controller *hose; | ||
1515 | |||
1516 | hose = pci_bus_to_hose(bus); | ||
1517 | if (!hose) | ||
1518 | return NULL; | ||
1519 | return hose->io_base_virt; | ||
1520 | } | ||
1521 | |||
1522 | unsigned long | ||
1523 | pci_bus_io_base_phys(unsigned int bus) | ||
1524 | { | ||
1525 | struct pci_controller *hose; | ||
1526 | |||
1527 | hose = pci_bus_to_hose(bus); | ||
1528 | if (!hose) | ||
1529 | return 0; | ||
1530 | return hose->io_base_phys; | ||
1531 | } | ||
1532 | |||
1533 | unsigned long | ||
1534 | pci_bus_mem_base_phys(unsigned int bus) | ||
1535 | { | ||
1536 | struct pci_controller *hose; | ||
1537 | |||
1538 | hose = pci_bus_to_hose(bus); | ||
1539 | if (!hose) | ||
1540 | return 0; | ||
1541 | return hose->pci_mem_offset; | ||
1542 | } | ||
1543 | |||
1544 | unsigned long | ||
1545 | pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) | ||
1546 | { | ||
1547 | /* Hack alert again ! See comments in chrp_pci.c | ||
1548 | */ | ||
1549 | struct pci_controller* hose = | ||
1550 | (struct pci_controller *)pdev->sysdata; | ||
1551 | if (hose && res->flags & IORESOURCE_MEM) | ||
1552 | return res->start - hose->pci_mem_offset; | ||
1553 | /* We may want to do something with IOs here... */ | ||
1554 | return res->start; | ||
1555 | } | ||
1556 | |||
1557 | |||
1558 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
1559 | resource_size_t *offset, | ||
1560 | enum pci_mmap_state mmap_state) | ||
1561 | { | ||
1562 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
1563 | unsigned long io_offset = 0; | ||
1564 | int i, res_bit; | ||
1565 | |||
1566 | if (hose == 0) | ||
1567 | return NULL; /* should never happen */ | ||
1568 | |||
1569 | /* If memory, add on the PCI bridge address offset */ | ||
1570 | if (mmap_state == pci_mmap_mem) { | ||
1571 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
1572 | *offset += hose->pci_mem_offset; | ||
1573 | #endif | ||
1574 | res_bit = IORESOURCE_MEM; | ||
1575 | } else { | ||
1576 | io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; | ||
1577 | *offset += io_offset; | ||
1578 | res_bit = IORESOURCE_IO; | ||
1579 | } | ||
1580 | |||
1581 | /* | ||
1582 | * Check that the offset requested corresponds to one of the | ||
1583 | * resources of the device. | ||
1584 | */ | ||
1585 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
1586 | struct resource *rp = &dev->resource[i]; | ||
1587 | int flags = rp->flags; | ||
1588 | |||
1589 | /* treat ROM as memory (should be already) */ | ||
1590 | if (i == PCI_ROM_RESOURCE) | ||
1591 | flags |= IORESOURCE_MEM; | ||
1592 | |||
1593 | /* Active and same type? */ | ||
1594 | if ((flags & res_bit) == 0) | ||
1595 | continue; | ||
1596 | |||
1597 | /* In the range of this resource? */ | ||
1598 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
1599 | continue; | ||
1600 | |||
1601 | /* found it! construct the final physical address */ | ||
1602 | if (mmap_state == pci_mmap_io) | ||
1603 | *offset += hose->io_base_phys - io_offset; | ||
1604 | return rp; | ||
1605 | } | ||
1606 | |||
1607 | return NULL; | ||
1608 | } | ||
1609 | |||
1610 | /* | ||
1611 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
1612 | * device mapping. | ||
1613 | */ | ||
1614 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
1615 | pgprot_t protection, | ||
1616 | enum pci_mmap_state mmap_state, | ||
1617 | int write_combine) | ||
1618 | { | ||
1619 | unsigned long prot = pgprot_val(protection); | ||
1620 | |||
1621 | /* Write combine is always 0 on non-memory space mappings. On | ||
1622 | * memory space, if the user didn't pass 1, we check for a | ||
1623 | * "prefetchable" resource. This is a bit hackish, but we use | ||
1624 | * this to workaround the inability of /sysfs to provide a write | ||
1625 | * combine bit | ||
1626 | */ | ||
1627 | if (mmap_state != pci_mmap_mem) | ||
1628 | write_combine = 0; | ||
1629 | else if (write_combine == 0) { | ||
1630 | if (rp->flags & IORESOURCE_PREFETCH) | ||
1631 | write_combine = 1; | ||
1632 | } | ||
1633 | |||
1634 | /* XXX would be nice to have a way to ask for write-through */ | ||
1635 | prot |= _PAGE_NO_CACHE; | ||
1636 | if (write_combine) | ||
1637 | prot &= ~_PAGE_GUARDED; | ||
1638 | else | ||
1639 | prot |= _PAGE_GUARDED; | ||
1640 | |||
1641 | return __pgprot(prot); | ||
1642 | } | ||
1643 | |||
1644 | /* | ||
1645 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
1646 | * PCI device, it tries to find the PCI device first and calls the | ||
1647 | * above routine | ||
1648 | */ | ||
1649 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
1650 | unsigned long pfn, | ||
1651 | unsigned long size, | ||
1652 | pgprot_t protection) | ||
1653 | { | ||
1654 | struct pci_dev *pdev = NULL; | ||
1655 | struct resource *found = NULL; | ||
1656 | unsigned long prot = pgprot_val(protection); | ||
1657 | unsigned long offset = pfn << PAGE_SHIFT; | ||
1658 | int i; | ||
1659 | |||
1660 | if (page_is_ram(pfn)) | ||
1661 | return __pgprot(prot); | ||
1662 | |||
1663 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
1664 | |||
1665 | for_each_pci_dev(pdev) { | ||
1666 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
1667 | struct resource *rp = &pdev->resource[i]; | ||
1668 | int flags = rp->flags; | ||
1669 | |||
1670 | /* Active and same type? */ | ||
1671 | if ((flags & IORESOURCE_MEM) == 0) | ||
1672 | continue; | ||
1673 | /* In the range of this resource? */ | ||
1674 | if (offset < (rp->start & PAGE_MASK) || | ||
1675 | offset > rp->end) | ||
1676 | continue; | ||
1677 | found = rp; | ||
1678 | break; | ||
1679 | } | ||
1680 | if (found) | ||
1681 | break; | ||
1682 | } | ||
1683 | if (found) { | ||
1684 | if (found->flags & IORESOURCE_PREFETCH) | ||
1685 | prot &= ~_PAGE_GUARDED; | ||
1686 | pci_dev_put(pdev); | ||
1687 | } | ||
1688 | |||
1689 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
1690 | |||
1691 | return __pgprot(prot); | ||
1692 | } | ||
1693 | |||
1694 | |||
1695 | /* | ||
1696 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
1697 | * appropriate for this architecture. The region in the process to map | ||
1698 | * is described by vm_start and vm_end members of VMA, the base physical | ||
1699 | * address is found in vm_pgoff. | ||
1700 | * The pci device structure is provided so that architectures may make mapping | ||
1701 | * decisions on a per-device or per-bus basis. | ||
1702 | * | ||
1703 | * Returns a negative error code on failure, zero on success. | ||
1704 | */ | ||
1705 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
1706 | enum pci_mmap_state mmap_state, | ||
1707 | int write_combine) | ||
1708 | { | ||
1709 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
1710 | struct resource *rp; | ||
1711 | int ret; | ||
1712 | |||
1713 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
1714 | if (rp == NULL) | ||
1715 | return -EINVAL; | ||
1716 | |||
1717 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
1718 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
1719 | vma->vm_page_prot, | ||
1720 | mmap_state, write_combine); | ||
1721 | |||
1722 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
1723 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
1724 | |||
1725 | return ret; | ||
1726 | } | ||
1727 | |||
1728 | /* Obsolete functions. Should be removed once the symbios driver | ||
1729 | * is fixed | ||
1730 | */ | ||
1731 | unsigned long | ||
1732 | phys_to_bus(unsigned long pa) | ||
1733 | { | ||
1734 | struct pci_controller *hose; | ||
1735 | int i; | ||
1736 | |||
1737 | for (hose = hose_head; hose; hose = hose->next) { | ||
1738 | for (i = 0; i < 3; ++i) { | ||
1739 | if (pa >= hose->mem_resources[i].start | ||
1740 | && pa <= hose->mem_resources[i].end) { | ||
1741 | /* | ||
1742 | * XXX the hose->pci_mem_offset really | ||
1743 | * only applies to mem_resources[0]. | ||
1744 | * We need a way to store an offset for | ||
1745 | * the others. -- paulus | ||
1746 | */ | ||
1747 | if (i == 0) | ||
1748 | pa -= hose->pci_mem_offset; | ||
1749 | return pa; | ||
1750 | } | ||
1751 | } | ||
1752 | } | ||
1753 | /* hmmm, didn't find it */ | ||
1754 | return 0; | ||
1755 | } | ||
1756 | |||
1757 | unsigned long | ||
1758 | pci_phys_to_bus(unsigned long pa, int busnr) | ||
1759 | { | ||
1760 | struct pci_controller* hose = pci_bus_to_hose(busnr); | ||
1761 | if (!hose) | ||
1762 | return pa; | ||
1763 | return pa - hose->pci_mem_offset; | ||
1764 | } | ||
1765 | |||
1766 | unsigned long | ||
1767 | pci_bus_to_phys(unsigned int ba, int busnr) | ||
1768 | { | ||
1769 | struct pci_controller* hose = pci_bus_to_hose(busnr); | ||
1770 | if (!hose) | ||
1771 | return ba; | ||
1772 | return ba + hose->pci_mem_offset; | ||
1773 | } | ||
1774 | |||
1775 | /* Provide information on locations of various I/O regions in physical | 1346 | /* Provide information on locations of various I/O regions in physical |
1776 | * memory. Do this on a per-card basis so that we choose the right | 1347 | * memory. Do this on a per-card basis so that we choose the right |
1777 | * root bridge. | 1348 | * root bridge. |
@@ -1814,62 +1385,11 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
1814 | return result; | 1385 | return result; |
1815 | } | 1386 | } |
1816 | 1387 | ||
1817 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
1818 | const struct resource *rsrc, | ||
1819 | resource_size_t *start, resource_size_t *end) | ||
1820 | { | ||
1821 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
1822 | resource_size_t offset = 0; | ||
1823 | |||
1824 | if (hose == NULL) | ||
1825 | return; | ||
1826 | |||
1827 | if (rsrc->flags & IORESOURCE_IO) | ||
1828 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
1829 | |||
1830 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
1831 | * a BAR value because X is lame and expects to be able to use that | ||
1832 | * to pass to /dev/mem ! | ||
1833 | * | ||
1834 | * That means that we'll have potentially 64 bits values where some | ||
1835 | * userland apps only expect 32 (like X itself since it thinks only | ||
1836 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
1837 | * 32 bits CHRPs :-( | ||
1838 | * | ||
1839 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
1840 | * has been fixed (and the fix spread enough), we can re-enable the | ||
1841 | * 2 lines below and pass down a BAR value to userland. In that case | ||
1842 | * we'll also have to re-enable the matching code in | ||
1843 | * __pci_mmap_make_offset(). | ||
1844 | * | ||
1845 | * BenH. | ||
1846 | */ | ||
1847 | #if 0 | ||
1848 | else if (rsrc->flags & IORESOURCE_MEM) | ||
1849 | offset = hose->pci_mem_offset; | ||
1850 | #endif | ||
1851 | |||
1852 | *start = rsrc->start - offset; | ||
1853 | *end = rsrc->end - offset; | ||
1854 | } | ||
1855 | |||
1856 | void __init pci_init_resource(struct resource *res, resource_size_t start, | ||
1857 | resource_size_t end, int flags, char *name) | ||
1858 | { | ||
1859 | res->start = start; | ||
1860 | res->end = end; | ||
1861 | res->flags = flags; | ||
1862 | res->name = name; | ||
1863 | res->parent = NULL; | ||
1864 | res->sibling = NULL; | ||
1865 | res->child = NULL; | ||
1866 | } | ||
1867 | |||
1868 | unsigned long pci_address_to_pio(phys_addr_t address) | 1388 | unsigned long pci_address_to_pio(phys_addr_t address) |
1869 | { | 1389 | { |
1870 | struct pci_controller* hose = hose_head; | 1390 | struct pci_controller *hose, *tmp; |
1871 | 1391 | ||
1872 | for (; hose; hose = hose->next) { | 1392 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
1873 | unsigned int size = hose->io_resource.end - | 1393 | unsigned int size = hose->io_resource.end - |
1874 | hose->io_resource.start + 1; | 1394 | hose->io_resource.start + 1; |
1875 | if (address >= hose->io_base_phys && | 1395 | if (address >= hose->io_base_phys && |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index e3009a43ac56..a97e23ac1976 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | #include <linux/syscalls.h> | 23 | #include <linux/syscalls.h> |
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/vmalloc.h> | ||
25 | 26 | ||
26 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
@@ -41,35 +42,23 @@ | |||
41 | 42 | ||
42 | unsigned long pci_probe_only = 1; | 43 | unsigned long pci_probe_only = 1; |
43 | int pci_assign_all_buses = 0; | 44 | int pci_assign_all_buses = 0; |
44 | static int pci_initial_scan_done; | ||
45 | 45 | ||
46 | static void fixup_resource(struct resource *res, struct pci_dev *dev); | 46 | static void fixup_resource(struct resource *res, struct pci_dev *dev); |
47 | static void do_bus_setup(struct pci_bus *bus); | 47 | static void do_bus_setup(struct pci_bus *bus); |
48 | static void phbs_remap_io(void); | ||
49 | 48 | ||
50 | /* pci_io_base -- the base address from which io bars are offsets. | 49 | /* pci_io_base -- the base address from which io bars are offsets. |
51 | * This is the lowest I/O base address (so bar values are always positive), | 50 | * This is the lowest I/O base address (so bar values are always positive), |
52 | * and it *must* be the start of ISA space if an ISA bus exists because | 51 | * and it *must* be the start of ISA space if an ISA bus exists because |
53 | * ISA drivers use hard coded offsets. If no ISA bus exists a dummy | 52 | * ISA drivers use hard coded offsets. If no ISA bus exists nothing |
54 | * page is mapped and isa_io_limit prevents access to it. | 53 | * is mapped on the first 64K of IO space |
55 | */ | 54 | */ |
56 | unsigned long isa_io_base; /* NULL if no ISA bus */ | 55 | unsigned long pci_io_base = ISA_IO_BASE; |
57 | EXPORT_SYMBOL(isa_io_base); | ||
58 | unsigned long pci_io_base; | ||
59 | EXPORT_SYMBOL(pci_io_base); | 56 | EXPORT_SYMBOL(pci_io_base); |
60 | 57 | ||
61 | void iSeries_pcibios_init(void); | ||
62 | |||
63 | LIST_HEAD(hose_list); | 58 | LIST_HEAD(hose_list); |
64 | 59 | ||
65 | static struct dma_mapping_ops *pci_dma_ops; | 60 | static struct dma_mapping_ops *pci_dma_ops; |
66 | 61 | ||
67 | int global_phb_number; /* Global phb counter */ | ||
68 | |||
69 | /* Cached ISA bridge dev. */ | ||
70 | struct pci_dev *ppc64_isabridge_dev = NULL; | ||
71 | EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); | ||
72 | |||
73 | void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) | 62 | void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) |
74 | { | 63 | { |
75 | pci_dma_ops = dma_ops; | 64 | pci_dma_ops = dma_ops; |
@@ -100,7 +89,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region | |||
100 | return; | 89 | return; |
101 | 90 | ||
102 | if (res->flags & IORESOURCE_IO) | 91 | if (res->flags & IORESOURCE_IO) |
103 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 92 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; |
104 | 93 | ||
105 | if (res->flags & IORESOURCE_MEM) | 94 | if (res->flags & IORESOURCE_MEM) |
106 | offset = hose->pci_mem_offset; | 95 | offset = hose->pci_mem_offset; |
@@ -119,7 +108,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | |||
119 | return; | 108 | return; |
120 | 109 | ||
121 | if (res->flags & IORESOURCE_IO) | 110 | if (res->flags & IORESOURCE_IO) |
122 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 111 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; |
123 | 112 | ||
124 | if (res->flags & IORESOURCE_MEM) | 113 | if (res->flags & IORESOURCE_MEM) |
125 | offset = hose->pci_mem_offset; | 114 | offset = hose->pci_mem_offset; |
@@ -156,7 +145,7 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
156 | 145 | ||
157 | if (res->flags & IORESOURCE_IO) { | 146 | if (res->flags & IORESOURCE_IO) { |
158 | unsigned long offset = (unsigned long)hose->io_base_virt - | 147 | unsigned long offset = (unsigned long)hose->io_base_virt - |
159 | pci_io_base; | 148 | _IO_BASE; |
160 | /* Make sure we start at our min on all hoses */ | 149 | /* Make sure we start at our min on all hoses */ |
161 | if (start - offset < PCIBIOS_MIN_IO) | 150 | if (start - offset < PCIBIOS_MIN_IO) |
162 | start = PCIBIOS_MIN_IO + offset; | 151 | start = PCIBIOS_MIN_IO + offset; |
@@ -180,55 +169,6 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
180 | res->start = start; | 169 | res->start = start; |
181 | } | 170 | } |
182 | 171 | ||
183 | static DEFINE_SPINLOCK(hose_spinlock); | ||
184 | |||
185 | /* | ||
186 | * pci_controller(phb) initialized common variables. | ||
187 | */ | ||
188 | static void __devinit pci_setup_pci_controller(struct pci_controller *hose) | ||
189 | { | ||
190 | memset(hose, 0, sizeof(struct pci_controller)); | ||
191 | |||
192 | spin_lock(&hose_spinlock); | ||
193 | hose->global_number = global_phb_number++; | ||
194 | list_add_tail(&hose->list_node, &hose_list); | ||
195 | spin_unlock(&hose_spinlock); | ||
196 | } | ||
197 | |||
198 | struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | ||
199 | { | ||
200 | struct pci_controller *phb; | ||
201 | |||
202 | if (mem_init_done) | ||
203 | phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | ||
204 | else | ||
205 | phb = alloc_bootmem(sizeof (struct pci_controller)); | ||
206 | if (phb == NULL) | ||
207 | return NULL; | ||
208 | pci_setup_pci_controller(phb); | ||
209 | phb->arch_data = dev; | ||
210 | phb->is_dynamic = mem_init_done; | ||
211 | if (dev) { | ||
212 | int nid = of_node_to_nid(dev); | ||
213 | |||
214 | if (nid < 0 || !node_online(nid)) | ||
215 | nid = -1; | ||
216 | |||
217 | PHB_SET_NODE(phb, nid); | ||
218 | } | ||
219 | return phb; | ||
220 | } | ||
221 | |||
222 | void pcibios_free_controller(struct pci_controller *phb) | ||
223 | { | ||
224 | spin_lock(&hose_spinlock); | ||
225 | list_del(&phb->list_node); | ||
226 | spin_unlock(&hose_spinlock); | ||
227 | |||
228 | if (phb->is_dynamic) | ||
229 | kfree(phb); | ||
230 | } | ||
231 | |||
232 | void __devinit pcibios_claim_one_bus(struct pci_bus *b) | 172 | void __devinit pcibios_claim_one_bus(struct pci_bus *b) |
233 | { | 173 | { |
234 | struct pci_dev *dev; | 174 | struct pci_dev *dev; |
@@ -291,7 +231,6 @@ static unsigned int pci_parse_of_flags(u32 addr0) | |||
291 | return flags; | 231 | return flags; |
292 | } | 232 | } |
293 | 233 | ||
294 | #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) | ||
295 | 234 | ||
296 | static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | 235 | static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) |
297 | { | 236 | { |
@@ -310,8 +249,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | |||
310 | flags = pci_parse_of_flags(addrs[0]); | 249 | flags = pci_parse_of_flags(addrs[0]); |
311 | if (!flags) | 250 | if (!flags) |
312 | continue; | 251 | continue; |
313 | base = GET_64BIT(addrs, 1); | 252 | base = of_read_number(&addrs[1], 2); |
314 | size = GET_64BIT(addrs, 3); | 253 | size = of_read_number(&addrs[3], 2); |
315 | if (!size) | 254 | if (!size) |
316 | continue; | 255 | continue; |
317 | i = addrs[0] & 0xff; | 256 | i = addrs[0] & 0xff; |
@@ -479,7 +418,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
479 | i = 1; | 418 | i = 1; |
480 | for (; len >= 32; len -= 32, ranges += 8) { | 419 | for (; len >= 32; len -= 32, ranges += 8) { |
481 | flags = pci_parse_of_flags(ranges[0]); | 420 | flags = pci_parse_of_flags(ranges[0]); |
482 | size = GET_64BIT(ranges, 6); | 421 | size = of_read_number(&ranges[6], 2); |
483 | if (flags == 0 || size == 0) | 422 | if (flags == 0 || size == 0) |
484 | continue; | 423 | continue; |
485 | if (flags & IORESOURCE_IO) { | 424 | if (flags & IORESOURCE_IO) { |
@@ -498,7 +437,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
498 | res = bus->resource[i]; | 437 | res = bus->resource[i]; |
499 | ++i; | 438 | ++i; |
500 | } | 439 | } |
501 | res->start = GET_64BIT(ranges, 1); | 440 | res->start = of_read_number(&ranges[1], 2); |
502 | res->end = res->start + size - 1; | 441 | res->end = res->start + size - 1; |
503 | res->flags = flags; | 442 | res->flags = flags; |
504 | fixup_resource(res, dev); | 443 | fixup_resource(res, dev); |
@@ -537,10 +476,16 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
537 | bus->secondary = hose->first_busno; | 476 | bus->secondary = hose->first_busno; |
538 | hose->bus = bus; | 477 | hose->bus = bus; |
539 | 478 | ||
479 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
480 | pcibios_map_io_space(bus); | ||
481 | |||
540 | bus->resource[0] = res = &hose->io_resource; | 482 | bus->resource[0] = res = &hose->io_resource; |
541 | if (res->flags && request_resource(&ioport_resource, res)) | 483 | if (res->flags && request_resource(&ioport_resource, res)) { |
542 | printk(KERN_ERR "Failed to request PCI IO region " | 484 | printk(KERN_ERR "Failed to request PCI IO region " |
543 | "on PCI domain %04x\n", hose->global_number); | 485 | "on PCI domain %04x\n", hose->global_number); |
486 | DBG("res->start = 0x%016lx, res->end = 0x%016lx\n", | ||
487 | res->start, res->end); | ||
488 | } | ||
544 | 489 | ||
545 | for (i = 0; i < 3; ++i) { | 490 | for (i = 0; i < 3; ++i) { |
546 | res = &hose->mem_resources[i]; | 491 | res = &hose->mem_resources[i]; |
@@ -598,17 +543,6 @@ static int __init pcibios_init(void) | |||
598 | if (ppc_md.pcibios_fixup) | 543 | if (ppc_md.pcibios_fixup) |
599 | ppc_md.pcibios_fixup(); | 544 | ppc_md.pcibios_fixup(); |
600 | 545 | ||
601 | /* Cache the location of the ISA bridge (if we have one) */ | ||
602 | ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); | ||
603 | if (ppc64_isabridge_dev != NULL) | ||
604 | printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | ||
605 | |||
606 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
607 | /* map in PCI I/O space */ | ||
608 | phbs_remap_io(); | ||
609 | |||
610 | pci_initial_scan_done = 1; | ||
611 | |||
612 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); | 546 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); |
613 | 547 | ||
614 | return 0; | 548 | return 0; |
@@ -616,11 +550,6 @@ static int __init pcibios_init(void) | |||
616 | 550 | ||
617 | subsys_initcall(pcibios_init); | 551 | subsys_initcall(pcibios_init); |
618 | 552 | ||
619 | char __init *pcibios_setup(char *str) | ||
620 | { | ||
621 | return str; | ||
622 | } | ||
623 | |||
624 | int pcibios_enable_device(struct pci_dev *dev, int mask) | 553 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
625 | { | 554 | { |
626 | u16 cmd, oldcmd; | 555 | u16 cmd, oldcmd; |
@@ -651,22 +580,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
651 | return 0; | 580 | return 0; |
652 | } | 581 | } |
653 | 582 | ||
654 | /* | ||
655 | * Return the domain number for this bus. | ||
656 | */ | ||
657 | int pci_domain_nr(struct pci_bus *bus) | ||
658 | { | ||
659 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
660 | return 0; | ||
661 | else { | ||
662 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
663 | |||
664 | return hose->global_number; | ||
665 | } | ||
666 | } | ||
667 | |||
668 | EXPORT_SYMBOL(pci_domain_nr); | ||
669 | |||
670 | /* Decide whether to display the domain number in /proc */ | 583 | /* Decide whether to display the domain number in /proc */ |
671 | int pci_proc_domain(struct pci_bus *bus) | 584 | int pci_proc_domain(struct pci_bus *bus) |
672 | { | 585 | { |
@@ -678,281 +591,6 @@ int pci_proc_domain(struct pci_bus *bus) | |||
678 | } | 591 | } |
679 | } | 592 | } |
680 | 593 | ||
681 | /* | ||
682 | * Platform support for /proc/bus/pci/X/Y mmap()s, | ||
683 | * modelled on the sparc64 implementation by Dave Miller. | ||
684 | * -- paulus. | ||
685 | */ | ||
686 | |||
687 | /* | ||
688 | * Adjust vm_pgoff of VMA such that it is the physical page offset | ||
689 | * corresponding to the 32-bit pci bus offset for DEV requested by the user. | ||
690 | * | ||
691 | * Basically, the user finds the base address for his device which he wishes | ||
692 | * to mmap. They read the 32-bit value from the config space base register, | ||
693 | * add whatever PAGE_SIZE multiple offset they wish, and feed this into the | ||
694 | * offset parameter of mmap on /proc/bus/pci/XXX for that device. | ||
695 | * | ||
696 | * Returns negative error code on failure, zero on success. | ||
697 | */ | ||
698 | static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | ||
699 | resource_size_t *offset, | ||
700 | enum pci_mmap_state mmap_state) | ||
701 | { | ||
702 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
703 | unsigned long io_offset = 0; | ||
704 | int i, res_bit; | ||
705 | |||
706 | if (hose == 0) | ||
707 | return NULL; /* should never happen */ | ||
708 | |||
709 | /* If memory, add on the PCI bridge address offset */ | ||
710 | if (mmap_state == pci_mmap_mem) { | ||
711 | #if 0 /* See comment in pci_resource_to_user() for why this is disabled */ | ||
712 | *offset += hose->pci_mem_offset; | ||
713 | #endif | ||
714 | res_bit = IORESOURCE_MEM; | ||
715 | } else { | ||
716 | io_offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
717 | *offset += io_offset; | ||
718 | res_bit = IORESOURCE_IO; | ||
719 | } | ||
720 | |||
721 | /* | ||
722 | * Check that the offset requested corresponds to one of the | ||
723 | * resources of the device. | ||
724 | */ | ||
725 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
726 | struct resource *rp = &dev->resource[i]; | ||
727 | int flags = rp->flags; | ||
728 | |||
729 | /* treat ROM as memory (should be already) */ | ||
730 | if (i == PCI_ROM_RESOURCE) | ||
731 | flags |= IORESOURCE_MEM; | ||
732 | |||
733 | /* Active and same type? */ | ||
734 | if ((flags & res_bit) == 0) | ||
735 | continue; | ||
736 | |||
737 | /* In the range of this resource? */ | ||
738 | if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) | ||
739 | continue; | ||
740 | |||
741 | /* found it! construct the final physical address */ | ||
742 | if (mmap_state == pci_mmap_io) | ||
743 | *offset += hose->io_base_phys - io_offset; | ||
744 | return rp; | ||
745 | } | ||
746 | |||
747 | return NULL; | ||
748 | } | ||
749 | |||
750 | /* | ||
751 | * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci | ||
752 | * device mapping. | ||
753 | */ | ||
754 | static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | ||
755 | pgprot_t protection, | ||
756 | enum pci_mmap_state mmap_state, | ||
757 | int write_combine) | ||
758 | { | ||
759 | unsigned long prot = pgprot_val(protection); | ||
760 | |||
761 | /* Write combine is always 0 on non-memory space mappings. On | ||
762 | * memory space, if the user didn't pass 1, we check for a | ||
763 | * "prefetchable" resource. This is a bit hackish, but we use | ||
764 | * this to workaround the inability of /sysfs to provide a write | ||
765 | * combine bit | ||
766 | */ | ||
767 | if (mmap_state != pci_mmap_mem) | ||
768 | write_combine = 0; | ||
769 | else if (write_combine == 0) { | ||
770 | if (rp->flags & IORESOURCE_PREFETCH) | ||
771 | write_combine = 1; | ||
772 | } | ||
773 | |||
774 | /* XXX would be nice to have a way to ask for write-through */ | ||
775 | prot |= _PAGE_NO_CACHE; | ||
776 | if (write_combine) | ||
777 | prot &= ~_PAGE_GUARDED; | ||
778 | else | ||
779 | prot |= _PAGE_GUARDED; | ||
780 | |||
781 | return __pgprot(prot); | ||
782 | } | ||
783 | |||
784 | /* | ||
785 | * This one is used by /dev/mem and fbdev who have no clue about the | ||
786 | * PCI device, it tries to find the PCI device first and calls the | ||
787 | * above routine | ||
788 | */ | ||
789 | pgprot_t pci_phys_mem_access_prot(struct file *file, | ||
790 | unsigned long pfn, | ||
791 | unsigned long size, | ||
792 | pgprot_t protection) | ||
793 | { | ||
794 | struct pci_dev *pdev = NULL; | ||
795 | struct resource *found = NULL; | ||
796 | unsigned long prot = pgprot_val(protection); | ||
797 | unsigned long offset = pfn << PAGE_SHIFT; | ||
798 | int i; | ||
799 | |||
800 | if (page_is_ram(pfn)) | ||
801 | return __pgprot(prot); | ||
802 | |||
803 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | ||
804 | |||
805 | for_each_pci_dev(pdev) { | ||
806 | for (i = 0; i <= PCI_ROM_RESOURCE; i++) { | ||
807 | struct resource *rp = &pdev->resource[i]; | ||
808 | int flags = rp->flags; | ||
809 | |||
810 | /* Active and same type? */ | ||
811 | if ((flags & IORESOURCE_MEM) == 0) | ||
812 | continue; | ||
813 | /* In the range of this resource? */ | ||
814 | if (offset < (rp->start & PAGE_MASK) || | ||
815 | offset > rp->end) | ||
816 | continue; | ||
817 | found = rp; | ||
818 | break; | ||
819 | } | ||
820 | if (found) | ||
821 | break; | ||
822 | } | ||
823 | if (found) { | ||
824 | if (found->flags & IORESOURCE_PREFETCH) | ||
825 | prot &= ~_PAGE_GUARDED; | ||
826 | pci_dev_put(pdev); | ||
827 | } | ||
828 | |||
829 | DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); | ||
830 | |||
831 | return __pgprot(prot); | ||
832 | } | ||
833 | |||
834 | |||
835 | /* | ||
836 | * Perform the actual remap of the pages for a PCI device mapping, as | ||
837 | * appropriate for this architecture. The region in the process to map | ||
838 | * is described by vm_start and vm_end members of VMA, the base physical | ||
839 | * address is found in vm_pgoff. | ||
840 | * The pci device structure is provided so that architectures may make mapping | ||
841 | * decisions on a per-device or per-bus basis. | ||
842 | * | ||
843 | * Returns a negative error code on failure, zero on success. | ||
844 | */ | ||
845 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | ||
846 | enum pci_mmap_state mmap_state, int write_combine) | ||
847 | { | ||
848 | resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; | ||
849 | struct resource *rp; | ||
850 | int ret; | ||
851 | |||
852 | rp = __pci_mmap_make_offset(dev, &offset, mmap_state); | ||
853 | if (rp == NULL) | ||
854 | return -EINVAL; | ||
855 | |||
856 | vma->vm_pgoff = offset >> PAGE_SHIFT; | ||
857 | vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, | ||
858 | vma->vm_page_prot, | ||
859 | mmap_state, write_combine); | ||
860 | |||
861 | ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | ||
862 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
863 | |||
864 | return ret; | ||
865 | } | ||
866 | |||
867 | static ssize_t pci_show_devspec(struct device *dev, | ||
868 | struct device_attribute *attr, char *buf) | ||
869 | { | ||
870 | struct pci_dev *pdev; | ||
871 | struct device_node *np; | ||
872 | |||
873 | pdev = to_pci_dev (dev); | ||
874 | np = pci_device_to_OF_node(pdev); | ||
875 | if (np == NULL || np->full_name == NULL) | ||
876 | return 0; | ||
877 | return sprintf(buf, "%s", np->full_name); | ||
878 | } | ||
879 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | ||
880 | |||
881 | int pcibios_add_platform_entries(struct pci_dev *pdev) | ||
882 | { | ||
883 | return device_create_file(&pdev->dev, &dev_attr_devspec); | ||
884 | } | ||
885 | |||
886 | #define ISA_SPACE_MASK 0x1 | ||
887 | #define ISA_SPACE_IO 0x1 | ||
888 | |||
889 | static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, | ||
890 | unsigned long phb_io_base_phys, | ||
891 | void __iomem * phb_io_base_virt) | ||
892 | { | ||
893 | /* Remove these asap */ | ||
894 | |||
895 | struct pci_address { | ||
896 | u32 a_hi; | ||
897 | u32 a_mid; | ||
898 | u32 a_lo; | ||
899 | }; | ||
900 | |||
901 | struct isa_address { | ||
902 | u32 a_hi; | ||
903 | u32 a_lo; | ||
904 | }; | ||
905 | |||
906 | struct isa_range { | ||
907 | struct isa_address isa_addr; | ||
908 | struct pci_address pci_addr; | ||
909 | unsigned int size; | ||
910 | }; | ||
911 | |||
912 | const struct isa_range *range; | ||
913 | unsigned long pci_addr; | ||
914 | unsigned int isa_addr; | ||
915 | unsigned int size; | ||
916 | int rlen = 0; | ||
917 | |||
918 | range = of_get_property(isa_node, "ranges", &rlen); | ||
919 | if (range == NULL || (rlen < sizeof(struct isa_range))) { | ||
920 | printk(KERN_ERR "no ISA ranges or unexpected isa range size," | ||
921 | "mapping 64k\n"); | ||
922 | __ioremap_explicit(phb_io_base_phys, | ||
923 | (unsigned long)phb_io_base_virt, | ||
924 | 0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
925 | return; | ||
926 | } | ||
927 | |||
928 | /* From "ISA Binding to 1275" | ||
929 | * The ranges property is laid out as an array of elements, | ||
930 | * each of which comprises: | ||
931 | * cells 0 - 1: an ISA address | ||
932 | * cells 2 - 4: a PCI address | ||
933 | * (size depending on dev->n_addr_cells) | ||
934 | * cell 5: the size of the range | ||
935 | */ | ||
936 | if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) { | ||
937 | isa_addr = range->isa_addr.a_lo; | ||
938 | pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | | ||
939 | range->pci_addr.a_lo; | ||
940 | |||
941 | /* Assume these are both zero */ | ||
942 | if ((pci_addr != 0) || (isa_addr != 0)) { | ||
943 | printk(KERN_ERR "unexpected isa to pci mapping: %s\n", | ||
944 | __FUNCTION__); | ||
945 | return; | ||
946 | } | ||
947 | |||
948 | size = PAGE_ALIGN(range->size); | ||
949 | |||
950 | __ioremap_explicit(phb_io_base_phys, | ||
951 | (unsigned long) phb_io_base_virt, | ||
952 | size, _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
953 | } | ||
954 | } | ||
955 | |||
956 | void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | 594 | void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, |
957 | struct device_node *dev, int prim) | 595 | struct device_node *dev, int prim) |
958 | { | 596 | { |
@@ -1047,155 +685,122 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
1047 | } | 685 | } |
1048 | } | 686 | } |
1049 | 687 | ||
1050 | void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary) | 688 | #ifdef CONFIG_HOTPLUG |
689 | |||
690 | int pcibios_unmap_io_space(struct pci_bus *bus) | ||
1051 | { | 691 | { |
1052 | unsigned long size = hose->pci_io_size; | 692 | struct pci_controller *hose; |
1053 | unsigned long io_virt_offset; | ||
1054 | struct resource *res; | ||
1055 | struct device_node *isa_dn; | ||
1056 | 693 | ||
1057 | if (size == 0) | 694 | WARN_ON(bus == NULL); |
1058 | return; | ||
1059 | 695 | ||
1060 | hose->io_base_virt = reserve_phb_iospace(size); | 696 | /* If this is not a PHB, we only flush the hash table over |
1061 | DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", | 697 | * the area mapped by this bridge. We don't play with the PTE |
1062 | hose->global_number, hose->io_base_phys, | 698 | * mappings since we might have to deal with sub-page alignemnts |
1063 | (unsigned long) hose->io_base_virt); | 699 | * so flushing the hash table is the only sane way to make sure |
1064 | 700 | * that no hash entries are covering that removed bridge area | |
1065 | if (primary) { | 701 | * while still allowing other busses overlapping those pages |
1066 | pci_io_base = (unsigned long)hose->io_base_virt; | 702 | */ |
1067 | isa_dn = of_find_node_by_type(NULL, "isa"); | 703 | if (bus->self) { |
1068 | if (isa_dn) { | 704 | struct resource *res = bus->resource[0]; |
1069 | isa_io_base = pci_io_base; | ||
1070 | pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, | ||
1071 | hose->io_base_virt); | ||
1072 | of_node_put(isa_dn); | ||
1073 | } | ||
1074 | } | ||
1075 | 705 | ||
1076 | io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; | 706 | DBG("IO unmapping for PCI-PCI bridge %s\n", |
1077 | res = &hose->io_resource; | 707 | pci_name(bus->self)); |
1078 | res->start += io_virt_offset; | ||
1079 | res->end += io_virt_offset; | ||
1080 | 708 | ||
1081 | /* If this is called after the initial PCI scan, then we need to | 709 | __flush_hash_table_range(&init_mm, res->start + _IO_BASE, |
1082 | * proceed to IO mappings now | 710 | res->end - res->start + 1); |
1083 | */ | 711 | return 0; |
1084 | if (pci_initial_scan_done) | 712 | } |
1085 | __ioremap_explicit(hose->io_base_phys, | ||
1086 | (unsigned long)hose->io_base_virt, | ||
1087 | hose->pci_io_size, | ||
1088 | _PAGE_NO_CACHE | _PAGE_GUARDED); | ||
1089 | } | ||
1090 | 713 | ||
1091 | void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose, | 714 | /* Get the host bridge */ |
1092 | int primary) | 715 | hose = pci_bus_to_host(bus); |
1093 | { | ||
1094 | unsigned long size = hose->pci_io_size; | ||
1095 | unsigned long io_virt_offset; | ||
1096 | struct resource *res; | ||
1097 | 716 | ||
1098 | if (size == 0) | 717 | /* Check if we have IOs allocated */ |
1099 | return; | 718 | if (hose->io_base_alloc == 0) |
719 | return 0; | ||
1100 | 720 | ||
1101 | hose->io_base_virt = __ioremap(hose->io_base_phys, size, | 721 | DBG("IO unmapping for PHB %s\n", |
1102 | _PAGE_NO_CACHE | _PAGE_GUARDED); | 722 | ((struct device_node *)hose->arch_data)->full_name); |
1103 | DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", | 723 | DBG(" alloc=0x%p\n", hose->io_base_alloc); |
1104 | hose->global_number, hose->io_base_phys, | ||
1105 | (unsigned long) hose->io_base_virt); | ||
1106 | 724 | ||
1107 | if (primary) | 725 | /* This is a PHB, we fully unmap the IO area */ |
1108 | pci_io_base = (unsigned long)hose->io_base_virt; | 726 | vunmap(hose->io_base_alloc); |
1109 | 727 | ||
1110 | io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; | 728 | return 0; |
1111 | res = &hose->io_resource; | ||
1112 | res->start += io_virt_offset; | ||
1113 | res->end += io_virt_offset; | ||
1114 | } | 729 | } |
730 | EXPORT_SYMBOL_GPL(pcibios_unmap_io_space); | ||
1115 | 731 | ||
732 | #endif /* CONFIG_HOTPLUG */ | ||
1116 | 733 | ||
1117 | static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, | 734 | int __devinit pcibios_map_io_space(struct pci_bus *bus) |
1118 | unsigned long *start_virt, unsigned long *size) | ||
1119 | { | 735 | { |
1120 | struct pci_controller *hose = pci_bus_to_host(bus); | 736 | struct vm_struct *area; |
1121 | struct resource *res; | 737 | unsigned long phys_page; |
1122 | 738 | unsigned long size_page; | |
1123 | if (bus->self) | 739 | unsigned long io_virt_offset; |
1124 | res = bus->resource[0]; | 740 | struct pci_controller *hose; |
1125 | else | ||
1126 | /* Root Bus */ | ||
1127 | res = &hose->io_resource; | ||
1128 | |||
1129 | if (res->end == 0 && res->start == 0) | ||
1130 | return 1; | ||
1131 | 741 | ||
1132 | *start_virt = pci_io_base + res->start; | 742 | WARN_ON(bus == NULL); |
1133 | *start_phys = *start_virt + hose->io_base_phys | ||
1134 | - (unsigned long) hose->io_base_virt; | ||
1135 | 743 | ||
1136 | if (res->end > res->start) | 744 | /* If this not a PHB, nothing to do, page tables still exist and |
1137 | *size = res->end - res->start + 1; | 745 | * thus HPTEs will be faulted in when needed |
1138 | else { | 746 | */ |
1139 | printk("%s(): unexpected region 0x%lx->0x%lx\n", | 747 | if (bus->self) { |
1140 | __FUNCTION__, res->start, res->end); | 748 | DBG("IO mapping for PCI-PCI bridge %s\n", |
1141 | return 1; | 749 | pci_name(bus->self)); |
750 | DBG(" virt=0x%016lx...0x%016lx\n", | ||
751 | bus->resource[0]->start + _IO_BASE, | ||
752 | bus->resource[0]->end + _IO_BASE); | ||
753 | return 0; | ||
1142 | } | 754 | } |
1143 | 755 | ||
1144 | return 0; | 756 | /* Get the host bridge */ |
1145 | } | 757 | hose = pci_bus_to_host(bus); |
1146 | 758 | phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE); | |
1147 | int unmap_bus_range(struct pci_bus *bus) | 759 | size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE); |
1148 | { | ||
1149 | unsigned long start_phys; | ||
1150 | unsigned long start_virt; | ||
1151 | unsigned long size; | ||
1152 | 760 | ||
1153 | if (!bus) { | 761 | /* Make sure IO area address is clear */ |
1154 | printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); | 762 | hose->io_base_alloc = NULL; |
1155 | return 1; | ||
1156 | } | ||
1157 | |||
1158 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | ||
1159 | return 1; | ||
1160 | if (__iounmap_explicit((void __iomem *) start_virt, size)) | ||
1161 | return 1; | ||
1162 | |||
1163 | return 0; | ||
1164 | } | ||
1165 | EXPORT_SYMBOL(unmap_bus_range); | ||
1166 | 763 | ||
1167 | int remap_bus_range(struct pci_bus *bus) | 764 | /* If there's no IO to map on that bus, get away too */ |
1168 | { | 765 | if (hose->pci_io_size == 0 || hose->io_base_phys == 0) |
1169 | unsigned long start_phys; | 766 | return 0; |
1170 | unsigned long start_virt; | ||
1171 | unsigned long size; | ||
1172 | 767 | ||
1173 | if (!bus) { | 768 | /* Let's allocate some IO space for that guy. We don't pass |
1174 | printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); | 769 | * VM_IOREMAP because we don't care about alignment tricks that |
1175 | return 1; | 770 | * the core does in that case. Maybe we should due to stupid card |
1176 | } | 771 | * with incomplete address decoding but I'd rather not deal with |
1177 | 772 | * those outside of the reserved 64K legacy region. | |
1178 | 773 | */ | |
1179 | if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) | 774 | area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END); |
1180 | return 1; | 775 | if (area == NULL) |
1181 | if (start_phys == 0) | 776 | return -ENOMEM; |
1182 | return 1; | 777 | hose->io_base_alloc = area->addr; |
1183 | printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); | 778 | hose->io_base_virt = (void __iomem *)(area->addr + |
1184 | if (__ioremap_explicit(start_phys, start_virt, size, | 779 | hose->io_base_phys - phys_page); |
1185 | _PAGE_NO_CACHE | _PAGE_GUARDED)) | 780 | |
1186 | return 1; | 781 | DBG("IO mapping for PHB %s\n", |
782 | ((struct device_node *)hose->arch_data)->full_name); | ||
783 | DBG(" phys=0x%016lx, virt=0x%p (alloc=0x%p)\n", | ||
784 | hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc); | ||
785 | DBG(" size=0x%016lx (alloc=0x%016lx)\n", | ||
786 | hose->pci_io_size, size_page); | ||
787 | |||
788 | /* Establish the mapping */ | ||
789 | if (__ioremap_at(phys_page, area->addr, size_page, | ||
790 | _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL) | ||
791 | return -ENOMEM; | ||
792 | |||
793 | /* Fixup hose IO resource */ | ||
794 | io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
795 | hose->io_resource.start += io_virt_offset; | ||
796 | hose->io_resource.end += io_virt_offset; | ||
797 | |||
798 | DBG(" hose->io_resource=0x%016lx...0x%016lx\n", | ||
799 | hose->io_resource.start, hose->io_resource.end); | ||
1187 | 800 | ||
1188 | return 0; | 801 | return 0; |
1189 | } | 802 | } |
1190 | EXPORT_SYMBOL(remap_bus_range); | 803 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); |
1191 | |||
1192 | static void phbs_remap_io(void) | ||
1193 | { | ||
1194 | struct pci_controller *hose, *tmp; | ||
1195 | |||
1196 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||
1197 | remap_bus_range(hose->bus); | ||
1198 | } | ||
1199 | 804 | ||
1200 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | 805 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) |
1201 | { | 806 | { |
@@ -1203,8 +808,7 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | |||
1203 | unsigned long offset; | 808 | unsigned long offset; |
1204 | 809 | ||
1205 | if (res->flags & IORESOURCE_IO) { | 810 | if (res->flags & IORESOURCE_IO) { |
1206 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 811 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; |
1207 | |||
1208 | res->start += offset; | 812 | res->start += offset; |
1209 | res->end += offset; | 813 | res->end += offset; |
1210 | } else if (res->flags & IORESOURCE_MEM) { | 814 | } else if (res->flags & IORESOURCE_MEM) { |
@@ -1219,9 +823,20 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | |||
1219 | /* Update device resources. */ | 823 | /* Update device resources. */ |
1220 | int i; | 824 | int i; |
1221 | 825 | ||
1222 | for (i = 0; i < PCI_NUM_RESOURCES; i++) | 826 | DBG("%s: Fixup resources:\n", pci_name(dev)); |
1223 | if (dev->resource[i].flags) | 827 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { |
1224 | fixup_resource(&dev->resource[i], dev); | 828 | struct resource *res = &dev->resource[i]; |
829 | if (!res->flags) | ||
830 | continue; | ||
831 | |||
832 | DBG(" 0x%02x < %08lx:0x%016lx...0x%016lx\n", | ||
833 | i, res->flags, res->start, res->end); | ||
834 | |||
835 | fixup_resource(res, dev); | ||
836 | |||
837 | DBG(" > %08lx:0x%016lx...0x%016lx\n", | ||
838 | res->flags, res->start, res->end); | ||
839 | } | ||
1225 | } | 840 | } |
1226 | EXPORT_SYMBOL(pcibios_fixup_device_resources); | 841 | EXPORT_SYMBOL(pcibios_fixup_device_resources); |
1227 | 842 | ||
@@ -1291,119 +906,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
1291 | } | 906 | } |
1292 | EXPORT_SYMBOL(pcibios_fixup_bus); | 907 | EXPORT_SYMBOL(pcibios_fixup_bus); |
1293 | 908 | ||
1294 | /* | ||
1295 | * Reads the interrupt pin to determine if interrupt is use by card. | ||
1296 | * If the interrupt is used, then gets the interrupt line from the | ||
1297 | * openfirmware and sets it in the pci_dev and pci_config line. | ||
1298 | */ | ||
1299 | int pci_read_irq_line(struct pci_dev *pci_dev) | ||
1300 | { | ||
1301 | struct of_irq oirq; | ||
1302 | unsigned int virq; | ||
1303 | |||
1304 | DBG("Try to map irq for %s...\n", pci_name(pci_dev)); | ||
1305 | |||
1306 | #ifdef DEBUG | ||
1307 | memset(&oirq, 0xff, sizeof(oirq)); | ||
1308 | #endif | ||
1309 | /* Try to get a mapping from the device-tree */ | ||
1310 | if (of_irq_map_pci(pci_dev, &oirq)) { | ||
1311 | u8 line, pin; | ||
1312 | |||
1313 | /* If that fails, lets fallback to what is in the config | ||
1314 | * space and map that through the default controller. We | ||
1315 | * also set the type to level low since that's what PCI | ||
1316 | * interrupts are. If your platform does differently, then | ||
1317 | * either provide a proper interrupt tree or don't use this | ||
1318 | * function. | ||
1319 | */ | ||
1320 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) | ||
1321 | return -1; | ||
1322 | if (pin == 0) | ||
1323 | return -1; | ||
1324 | if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || | ||
1325 | line == 0xff) { | ||
1326 | return -1; | ||
1327 | } | ||
1328 | DBG(" -> no map ! Using irq line %d from PCI config\n", line); | ||
1329 | |||
1330 | virq = irq_create_mapping(NULL, line); | ||
1331 | if (virq != NO_IRQ) | ||
1332 | set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | ||
1333 | } else { | ||
1334 | DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | ||
1335 | oirq.size, oirq.specifier[0], oirq.specifier[1], | ||
1336 | oirq.controller->full_name); | ||
1337 | |||
1338 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
1339 | oirq.size); | ||
1340 | } | ||
1341 | if(virq == NO_IRQ) { | ||
1342 | DBG(" -> failed to map !\n"); | ||
1343 | return -1; | ||
1344 | } | ||
1345 | |||
1346 | DBG(" -> mapped to linux irq %d\n", virq); | ||
1347 | |||
1348 | pci_dev->irq = virq; | ||
1349 | |||
1350 | return 0; | ||
1351 | } | ||
1352 | EXPORT_SYMBOL(pci_read_irq_line); | ||
1353 | |||
1354 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
1355 | const struct resource *rsrc, | ||
1356 | resource_size_t *start, resource_size_t *end) | ||
1357 | { | ||
1358 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
1359 | resource_size_t offset = 0; | ||
1360 | |||
1361 | if (hose == NULL) | ||
1362 | return; | ||
1363 | |||
1364 | if (rsrc->flags & IORESOURCE_IO) | ||
1365 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
1366 | |||
1367 | /* We pass a fully fixed up address to userland for MMIO instead of | ||
1368 | * a BAR value because X is lame and expects to be able to use that | ||
1369 | * to pass to /dev/mem ! | ||
1370 | * | ||
1371 | * That means that we'll have potentially 64 bits values where some | ||
1372 | * userland apps only expect 32 (like X itself since it thinks only | ||
1373 | * Sparc has 64 bits MMIO) but if we don't do that, we break it on | ||
1374 | * 32 bits CHRPs :-( | ||
1375 | * | ||
1376 | * Hopefully, the sysfs insterface is immune to that gunk. Once X | ||
1377 | * has been fixed (and the fix spread enough), we can re-enable the | ||
1378 | * 2 lines below and pass down a BAR value to userland. In that case | ||
1379 | * we'll also have to re-enable the matching code in | ||
1380 | * __pci_mmap_make_offset(). | ||
1381 | * | ||
1382 | * BenH. | ||
1383 | */ | ||
1384 | #if 0 | ||
1385 | else if (rsrc->flags & IORESOURCE_MEM) | ||
1386 | offset = hose->pci_mem_offset; | ||
1387 | #endif | ||
1388 | |||
1389 | *start = rsrc->start - offset; | ||
1390 | *end = rsrc->end - offset; | ||
1391 | } | ||
1392 | |||
1393 | struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) | ||
1394 | { | ||
1395 | if (!have_of) | ||
1396 | return NULL; | ||
1397 | while(node) { | ||
1398 | struct pci_controller *hose, *tmp; | ||
1399 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | ||
1400 | if (hose->arch_data == node) | ||
1401 | return hose; | ||
1402 | node = node->parent; | ||
1403 | } | ||
1404 | return NULL; | ||
1405 | } | ||
1406 | |||
1407 | unsigned long pci_address_to_pio(phys_addr_t address) | 909 | unsigned long pci_address_to_pio(phys_addr_t address) |
1408 | { | 910 | { |
1409 | struct pci_controller *hose, *tmp; | 911 | struct pci_controller *hose, *tmp; |
@@ -1412,7 +914,7 @@ unsigned long pci_address_to_pio(phys_addr_t address) | |||
1412 | if (address >= hose->io_base_phys && | 914 | if (address >= hose->io_base_phys && |
1413 | address < (hose->io_base_phys + hose->pci_io_size)) { | 915 | address < (hose->io_base_phys + hose->pci_io_size)) { |
1414 | unsigned long base = | 916 | unsigned long base = |
1415 | (unsigned long)hose->io_base_virt - pci_io_base; | 917 | (unsigned long)hose->io_base_virt - _IO_BASE; |
1416 | return base + (address - hose->io_base_phys); | 918 | return base + (address - hose->io_base_phys); |
1417 | } | 919 | } |
1418 | } | 920 | } |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index c96fa9bd35a4..a20f1951a5ce 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -67,7 +67,6 @@ EXPORT_SYMBOL(ISA_DMA_THRESHOLD); | |||
67 | EXPORT_SYMBOL(DMA_MODE_READ); | 67 | EXPORT_SYMBOL(DMA_MODE_READ); |
68 | EXPORT_SYMBOL(DMA_MODE_WRITE); | 68 | EXPORT_SYMBOL(DMA_MODE_WRITE); |
69 | 69 | ||
70 | EXPORT_SYMBOL(do_signal); | ||
71 | EXPORT_SYMBOL(transfer_to_handler); | 70 | EXPORT_SYMBOL(transfer_to_handler); |
72 | EXPORT_SYMBOL(do_IRQ); | 71 | EXPORT_SYMBOL(do_IRQ); |
73 | EXPORT_SYMBOL(machine_check_exception); | 72 | EXPORT_SYMBOL(machine_check_exception); |
@@ -106,10 +105,6 @@ EXPORT_SYMBOL(isa_mem_base); | |||
106 | EXPORT_SYMBOL(pci_dram_offset); | 105 | EXPORT_SYMBOL(pci_dram_offset); |
107 | EXPORT_SYMBOL(pci_alloc_consistent); | 106 | EXPORT_SYMBOL(pci_alloc_consistent); |
108 | EXPORT_SYMBOL(pci_free_consistent); | 107 | EXPORT_SYMBOL(pci_free_consistent); |
109 | EXPORT_SYMBOL(pci_bus_io_base); | ||
110 | EXPORT_SYMBOL(pci_bus_io_base_phys); | ||
111 | EXPORT_SYMBOL(pci_bus_mem_base_phys); | ||
112 | EXPORT_SYMBOL(pci_bus_to_hose); | ||
113 | #endif /* CONFIG_PCI */ | 108 | #endif /* CONFIG_PCI */ |
114 | 109 | ||
115 | EXPORT_SYMBOL(start_thread); | 110 | EXPORT_SYMBOL(start_thread); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 6e2f03566b0d..84f000a45e36 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -219,22 +219,26 @@ void discard_lazy_cpu_state(void) | |||
219 | } | 219 | } |
220 | #endif /* CONFIG_SMP */ | 220 | #endif /* CONFIG_SMP */ |
221 | 221 | ||
222 | #ifdef CONFIG_PPC_MERGE /* XXX for now */ | ||
223 | int set_dabr(unsigned long dabr) | 222 | int set_dabr(unsigned long dabr) |
224 | { | 223 | { |
224 | #ifdef CONFIG_PPC_MERGE /* XXX for now */ | ||
225 | if (ppc_md.set_dabr) | 225 | if (ppc_md.set_dabr) |
226 | return ppc_md.set_dabr(dabr); | 226 | return ppc_md.set_dabr(dabr); |
227 | #endif | ||
227 | 228 | ||
229 | /* XXX should we have a CPU_FTR_HAS_DABR ? */ | ||
230 | #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) | ||
228 | mtspr(SPRN_DABR, dabr); | 231 | mtspr(SPRN_DABR, dabr); |
232 | #endif | ||
229 | return 0; | 233 | return 0; |
230 | } | 234 | } |
231 | #endif | ||
232 | 235 | ||
233 | #ifdef CONFIG_PPC64 | 236 | #ifdef CONFIG_PPC64 |
234 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); | 237 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); |
235 | static DEFINE_PER_CPU(unsigned long, current_dabr); | ||
236 | #endif | 238 | #endif |
237 | 239 | ||
240 | static DEFINE_PER_CPU(unsigned long, current_dabr); | ||
241 | |||
238 | struct task_struct *__switch_to(struct task_struct *prev, | 242 | struct task_struct *__switch_to(struct task_struct *prev, |
239 | struct task_struct *new) | 243 | struct task_struct *new) |
240 | { | 244 | { |
@@ -299,12 +303,10 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
299 | 303 | ||
300 | #endif /* CONFIG_SMP */ | 304 | #endif /* CONFIG_SMP */ |
301 | 305 | ||
302 | #ifdef CONFIG_PPC64 /* for now */ | ||
303 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { | 306 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { |
304 | set_dabr(new->thread.dabr); | 307 | set_dabr(new->thread.dabr); |
305 | __get_cpu_var(current_dabr) = new->thread.dabr; | 308 | __get_cpu_var(current_dabr) = new->thread.dabr; |
306 | } | 309 | } |
307 | #endif /* CONFIG_PPC64 */ | ||
308 | 310 | ||
309 | new_thread = &new->thread; | 311 | new_thread = &new->thread; |
310 | old_thread = ¤t->thread; | 312 | old_thread = ¤t->thread; |
@@ -473,12 +475,10 @@ void flush_thread(void) | |||
473 | 475 | ||
474 | discard_lazy_cpu_state(); | 476 | discard_lazy_cpu_state(); |
475 | 477 | ||
476 | #ifdef CONFIG_PPC64 /* for now */ | ||
477 | if (current->thread.dabr) { | 478 | if (current->thread.dabr) { |
478 | current->thread.dabr = 0; | 479 | current->thread.dabr = 0; |
479 | set_dabr(0); | 480 | set_dabr(0); |
480 | } | 481 | } |
481 | #endif | ||
482 | } | 482 | } |
483 | 483 | ||
484 | void | 484 | void |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index af42ddab3ab4..37ff99bd98b4 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <asm/pSeries_reconfig.h> | 52 | #include <asm/pSeries_reconfig.h> |
53 | #include <asm/pci-bridge.h> | 53 | #include <asm/pci-bridge.h> |
54 | #include <asm/kexec.h> | 54 | #include <asm/kexec.h> |
55 | #include <asm/system.h> | ||
55 | 56 | ||
56 | #ifdef DEBUG | 57 | #ifdef DEBUG |
57 | #define DBG(fmt...) printk(KERN_ERR fmt) | 58 | #define DBG(fmt...) printk(KERN_ERR fmt) |
@@ -1005,7 +1006,7 @@ static void __init early_reserve_mem(void) | |||
1005 | 1006 | ||
1006 | void __init early_init_devtree(void *params) | 1007 | void __init early_init_devtree(void *params) |
1007 | { | 1008 | { |
1008 | DBG(" -> early_init_devtree()\n"); | 1009 | DBG(" -> early_init_devtree(%p)\n", params); |
1009 | 1010 | ||
1010 | /* Setup flat device-tree pointer */ | 1011 | /* Setup flat device-tree pointer */ |
1011 | initial_boot_params = params; | 1012 | initial_boot_params = params; |
@@ -1055,8 +1056,6 @@ void __init early_init_devtree(void *params) | |||
1055 | DBG(" <- early_init_devtree()\n"); | 1056 | DBG(" <- early_init_devtree()\n"); |
1056 | } | 1057 | } |
1057 | 1058 | ||
1058 | #undef printk | ||
1059 | |||
1060 | int of_n_addr_cells(struct device_node* np) | 1059 | int of_n_addr_cells(struct device_node* np) |
1061 | { | 1060 | { |
1062 | const int *ip; | 1061 | const int *ip; |
@@ -1375,8 +1374,17 @@ static void of_node_release(struct kref *kref) | |||
1375 | struct device_node *node = kref_to_device_node(kref); | 1374 | struct device_node *node = kref_to_device_node(kref); |
1376 | struct property *prop = node->properties; | 1375 | struct property *prop = node->properties; |
1377 | 1376 | ||
1378 | if (!OF_IS_DYNAMIC(node)) | 1377 | /* We should never be releasing nodes that haven't been detached. */ |
1378 | if (!of_node_check_flag(node, OF_DETACHED)) { | ||
1379 | printk("WARNING: Bad of_node_put() on %s\n", node->full_name); | ||
1380 | dump_stack(); | ||
1381 | kref_init(&node->kref); | ||
1382 | return; | ||
1383 | } | ||
1384 | |||
1385 | if (!of_node_check_flag(node, OF_DYNAMIC)) | ||
1379 | return; | 1386 | return; |
1387 | |||
1380 | while (prop) { | 1388 | while (prop) { |
1381 | struct property *next = prop->next; | 1389 | struct property *next = prop->next; |
1382 | kfree(prop->name); | 1390 | kfree(prop->name); |
@@ -1432,6 +1440,8 @@ void of_detach_node(const struct device_node *np) | |||
1432 | write_lock(&devtree_lock); | 1440 | write_lock(&devtree_lock); |
1433 | 1441 | ||
1434 | parent = np->parent; | 1442 | parent = np->parent; |
1443 | if (!parent) | ||
1444 | goto out_unlock; | ||
1435 | 1445 | ||
1436 | if (allnodes == np) | 1446 | if (allnodes == np) |
1437 | allnodes = np->allnext; | 1447 | allnodes = np->allnext; |
@@ -1455,6 +1465,9 @@ void of_detach_node(const struct device_node *np) | |||
1455 | prevsib->sibling = np->sibling; | 1465 | prevsib->sibling = np->sibling; |
1456 | } | 1466 | } |
1457 | 1467 | ||
1468 | of_node_set_flag(np, OF_DETACHED); | ||
1469 | |||
1470 | out_unlock: | ||
1458 | write_unlock(&devtree_lock); | 1471 | write_unlock(&devtree_lock); |
1459 | } | 1472 | } |
1460 | 1473 | ||
@@ -1716,22 +1729,18 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | |||
1716 | } | 1729 | } |
1717 | EXPORT_SYMBOL(of_get_cpu_node); | 1730 | EXPORT_SYMBOL(of_get_cpu_node); |
1718 | 1731 | ||
1719 | #ifdef DEBUG | 1732 | #if defined(CONFIG_DEBUG_FS) && defined(DEBUG) |
1720 | static struct debugfs_blob_wrapper flat_dt_blob; | 1733 | static struct debugfs_blob_wrapper flat_dt_blob; |
1721 | 1734 | ||
1722 | static int __init export_flat_device_tree(void) | 1735 | static int __init export_flat_device_tree(void) |
1723 | { | 1736 | { |
1724 | struct dentry *d; | 1737 | struct dentry *d; |
1725 | 1738 | ||
1726 | d = debugfs_create_dir("powerpc", NULL); | ||
1727 | if (!d) | ||
1728 | return 1; | ||
1729 | |||
1730 | flat_dt_blob.data = initial_boot_params; | 1739 | flat_dt_blob.data = initial_boot_params; |
1731 | flat_dt_blob.size = initial_boot_params->totalsize; | 1740 | flat_dt_blob.size = initial_boot_params->totalsize; |
1732 | 1741 | ||
1733 | d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, | 1742 | d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, |
1734 | d, &flat_dt_blob); | 1743 | powerpc_debugfs_root, &flat_dt_blob); |
1735 | if (!d) | 1744 | if (!d) |
1736 | return 1; | 1745 | return 1; |
1737 | 1746 | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index d6047c441034..a1d582e38627 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -635,6 +635,7 @@ static void __init early_cmdline_parse(void) | |||
635 | /* ibm,dynamic-reconfiguration-memory property supported */ | 635 | /* ibm,dynamic-reconfiguration-memory property supported */ |
636 | #define OV5_DRCONF_MEMORY 0x20 | 636 | #define OV5_DRCONF_MEMORY 0x20 |
637 | #define OV5_LARGE_PAGES 0x10 /* large pages supported */ | 637 | #define OV5_LARGE_PAGES 0x10 /* large pages supported */ |
638 | #define OV5_DONATE_DEDICATE_CPU 0x02 /* donate dedicated CPU support */ | ||
638 | /* PCIe/MSI support. Without MSI full PCIe is not supported */ | 639 | /* PCIe/MSI support. Without MSI full PCIe is not supported */ |
639 | #ifdef CONFIG_PCI_MSI | 640 | #ifdef CONFIG_PCI_MSI |
640 | #define OV5_MSI 0x01 /* PCIe/MSI support */ | 641 | #define OV5_MSI 0x01 /* PCIe/MSI support */ |
@@ -685,7 +686,8 @@ static unsigned char ibm_architecture_vec[] = { | |||
685 | /* option vector 5: PAPR/OF options */ | 686 | /* option vector 5: PAPR/OF options */ |
686 | 3 - 2, /* length */ | 687 | 3 - 2, /* length */ |
687 | 0, /* don't ignore, don't halt */ | 688 | 0, /* don't ignore, don't halt */ |
688 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI, | 689 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | |
690 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, | ||
689 | }; | 691 | }; |
690 | 692 | ||
691 | /* Old method - ELF header with PT_NOTE sections */ | 693 | /* Old method - ELF header with PT_NOTE sections */ |
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h deleted file mode 100644 index 8797ae737a7b..000000000000 --- a/arch/powerpc/kernel/ptrace-common.h +++ /dev/null | |||
@@ -1,161 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2002 Stephen Rothwell, IBM Coproration | ||
3 | * Extracted from ptrace.c and ptrace32.c | ||
4 | * | ||
5 | * This file is subject to the terms and conditions of the GNU General | ||
6 | * Public License. See the file README.legal in the main directory of | ||
7 | * this archive for more details. | ||
8 | */ | ||
9 | |||
10 | #ifndef _PPC64_PTRACE_COMMON_H | ||
11 | #define _PPC64_PTRACE_COMMON_H | ||
12 | |||
13 | #include <asm/system.h> | ||
14 | |||
15 | /* | ||
16 | * Set of msr bits that gdb can change on behalf of a process. | ||
17 | */ | ||
18 | #define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) | ||
19 | |||
20 | /* | ||
21 | * Get contents of register REGNO in task TASK. | ||
22 | */ | ||
23 | static inline unsigned long get_reg(struct task_struct *task, int regno) | ||
24 | { | ||
25 | unsigned long tmp = 0; | ||
26 | |||
27 | /* | ||
28 | * Put the correct FP bits in, they might be wrong as a result | ||
29 | * of our lazy FP restore. | ||
30 | */ | ||
31 | if (regno == PT_MSR) { | ||
32 | tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | ||
33 | tmp |= task->thread.fpexc_mode; | ||
34 | } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { | ||
35 | tmp = ((unsigned long *)task->thread.regs)[regno]; | ||
36 | } | ||
37 | |||
38 | return tmp; | ||
39 | } | ||
40 | |||
41 | /* | ||
42 | * Write contents of register REGNO in task TASK. | ||
43 | */ | ||
44 | static inline int put_reg(struct task_struct *task, int regno, | ||
45 | unsigned long data) | ||
46 | { | ||
47 | if (regno < PT_SOFTE) { | ||
48 | if (regno == PT_MSR) | ||
49 | data = (data & MSR_DEBUGCHANGE) | ||
50 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||
51 | ((unsigned long *)task->thread.regs)[regno] = data; | ||
52 | return 0; | ||
53 | } | ||
54 | return -EIO; | ||
55 | } | ||
56 | |||
57 | static inline void set_single_step(struct task_struct *task) | ||
58 | { | ||
59 | struct pt_regs *regs = task->thread.regs; | ||
60 | if (regs != NULL) | ||
61 | regs->msr |= MSR_SE; | ||
62 | set_tsk_thread_flag(task, TIF_SINGLESTEP); | ||
63 | } | ||
64 | |||
65 | static inline void clear_single_step(struct task_struct *task) | ||
66 | { | ||
67 | struct pt_regs *regs = task->thread.regs; | ||
68 | if (regs != NULL) | ||
69 | regs->msr &= ~MSR_SE; | ||
70 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | ||
71 | } | ||
72 | |||
73 | #ifdef CONFIG_ALTIVEC | ||
74 | /* | ||
75 | * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. | ||
76 | * The transfer totals 34 quadword. Quadwords 0-31 contain the | ||
77 | * corresponding vector registers. Quadword 32 contains the vscr as the | ||
78 | * last word (offset 12) within that quadword. Quadword 33 contains the | ||
79 | * vrsave as the first word (offset 0) within the quadword. | ||
80 | * | ||
81 | * This definition of the VMX state is compatible with the current PPC32 | ||
82 | * ptrace interface. This allows signal handling and ptrace to use the | ||
83 | * same structures. This also simplifies the implementation of a bi-arch | ||
84 | * (combined (32- and 64-bit) gdb. | ||
85 | */ | ||
86 | |||
87 | /* | ||
88 | * Get contents of AltiVec register state in task TASK | ||
89 | */ | ||
90 | static inline int get_vrregs(unsigned long __user *data, | ||
91 | struct task_struct *task) | ||
92 | { | ||
93 | unsigned long regsize; | ||
94 | |||
95 | /* copy AltiVec registers VR[0] .. VR[31] */ | ||
96 | regsize = 32 * sizeof(vector128); | ||
97 | if (copy_to_user(data, task->thread.vr, regsize)) | ||
98 | return -EFAULT; | ||
99 | data += (regsize / sizeof(unsigned long)); | ||
100 | |||
101 | /* copy VSCR */ | ||
102 | regsize = 1 * sizeof(vector128); | ||
103 | if (copy_to_user(data, &task->thread.vscr, regsize)) | ||
104 | return -EFAULT; | ||
105 | data += (regsize / sizeof(unsigned long)); | ||
106 | |||
107 | /* copy VRSAVE */ | ||
108 | if (put_user(task->thread.vrsave, (u32 __user *)data)) | ||
109 | return -EFAULT; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Write contents of AltiVec register state into task TASK. | ||
116 | */ | ||
117 | static inline int set_vrregs(struct task_struct *task, | ||
118 | unsigned long __user *data) | ||
119 | { | ||
120 | unsigned long regsize; | ||
121 | |||
122 | /* copy AltiVec registers VR[0] .. VR[31] */ | ||
123 | regsize = 32 * sizeof(vector128); | ||
124 | if (copy_from_user(task->thread.vr, data, regsize)) | ||
125 | return -EFAULT; | ||
126 | data += (regsize / sizeof(unsigned long)); | ||
127 | |||
128 | /* copy VSCR */ | ||
129 | regsize = 1 * sizeof(vector128); | ||
130 | if (copy_from_user(&task->thread.vscr, data, regsize)) | ||
131 | return -EFAULT; | ||
132 | data += (regsize / sizeof(unsigned long)); | ||
133 | |||
134 | /* copy VRSAVE */ | ||
135 | if (get_user(task->thread.vrsave, (u32 __user *)data)) | ||
136 | return -EFAULT; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | #endif | ||
141 | |||
142 | static inline int ptrace_set_debugreg(struct task_struct *task, | ||
143 | unsigned long addr, unsigned long data) | ||
144 | { | ||
145 | /* We only support one DABR and no IABRS at the moment */ | ||
146 | if (addr > 0) | ||
147 | return -EINVAL; | ||
148 | |||
149 | /* The bottom 3 bits are flags */ | ||
150 | if ((data & ~0x7UL) >= TASK_SIZE) | ||
151 | return -EIO; | ||
152 | |||
153 | /* Ensure translation is on */ | ||
154 | if (data && !(data & DABR_TRANSLATION)) | ||
155 | return -EIO; | ||
156 | |||
157 | task->thread.dabr = data; | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | #endif /* _PPC64_PTRACE_COMMON_H */ | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index bf76562167c3..8a177bd9eab4 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -35,11 +35,11 @@ | |||
35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | 37 | ||
38 | #ifdef CONFIG_PPC64 | 38 | /* |
39 | #include "ptrace-common.h" | 39 | * does not yet catch signals sent when the child dies. |
40 | #endif | 40 | * in exit.c or in signal.c. |
41 | */ | ||
41 | 42 | ||
42 | #ifdef CONFIG_PPC32 | ||
43 | /* | 43 | /* |
44 | * Set of msr bits that gdb can change on behalf of a process. | 44 | * Set of msr bits that gdb can change on behalf of a process. |
45 | */ | 45 | */ |
@@ -48,65 +48,117 @@ | |||
48 | #else | 48 | #else |
49 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) | 49 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) |
50 | #endif | 50 | #endif |
51 | #endif /* CONFIG_PPC32 */ | ||
52 | 51 | ||
53 | /* | 52 | /* |
54 | * does not yet catch signals sent when the child dies. | 53 | * Max register writeable via put_reg |
55 | * in exit.c or in signal.c. | ||
56 | */ | 54 | */ |
57 | |||
58 | #ifdef CONFIG_PPC32 | 55 | #ifdef CONFIG_PPC32 |
56 | #define PT_MAX_PUT_REG PT_MQ | ||
57 | #else | ||
58 | #define PT_MAX_PUT_REG PT_CCR | ||
59 | #endif | ||
60 | |||
59 | /* | 61 | /* |
60 | * Get contents of register REGNO in task TASK. | 62 | * Get contents of register REGNO in task TASK. |
61 | */ | 63 | */ |
62 | static inline unsigned long get_reg(struct task_struct *task, int regno) | 64 | unsigned long ptrace_get_reg(struct task_struct *task, int regno) |
63 | { | 65 | { |
64 | if (regno < sizeof(struct pt_regs) / sizeof(unsigned long) | 66 | unsigned long tmp = 0; |
65 | && task->thread.regs != NULL) | 67 | |
68 | if (task->thread.regs == NULL) | ||
69 | return -EIO; | ||
70 | |||
71 | if (regno == PT_MSR) { | ||
72 | tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; | ||
73 | return tmp | task->thread.fpexc_mode; | ||
74 | } | ||
75 | |||
76 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) | ||
66 | return ((unsigned long *)task->thread.regs)[regno]; | 77 | return ((unsigned long *)task->thread.regs)[regno]; |
67 | return (0); | 78 | |
79 | return -EIO; | ||
68 | } | 80 | } |
69 | 81 | ||
70 | /* | 82 | /* |
71 | * Write contents of register REGNO in task TASK. | 83 | * Write contents of register REGNO in task TASK. |
72 | */ | 84 | */ |
73 | static inline int put_reg(struct task_struct *task, int regno, | 85 | int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) |
74 | unsigned long data) | ||
75 | { | 86 | { |
76 | if (regno <= PT_MQ && task->thread.regs != NULL) { | 87 | if (task->thread.regs == NULL) |
88 | return -EIO; | ||
89 | |||
90 | if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) { | ||
77 | if (regno == PT_MSR) | 91 | if (regno == PT_MSR) |
78 | data = (data & MSR_DEBUGCHANGE) | 92 | data = (data & MSR_DEBUGCHANGE) |
79 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); | 93 | | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); |
94 | /* We prevent mucking around with the reserved area of trap | ||
95 | * which are used internally by the kernel | ||
96 | */ | ||
97 | if (regno == PT_TRAP) | ||
98 | data &= 0xfff0; | ||
80 | ((unsigned long *)task->thread.regs)[regno] = data; | 99 | ((unsigned long *)task->thread.regs)[regno] = data; |
81 | return 0; | 100 | return 0; |
82 | } | 101 | } |
83 | return -EIO; | 102 | return -EIO; |
84 | } | 103 | } |
85 | 104 | ||
105 | |||
106 | static int get_fpregs(void __user *data, struct task_struct *task, | ||
107 | int has_fpscr) | ||
108 | { | ||
109 | unsigned int count = has_fpscr ? 33 : 32; | ||
110 | |||
111 | if (copy_to_user(data, task->thread.fpr, count * sizeof(double))) | ||
112 | return -EFAULT; | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int set_fpregs(void __user *data, struct task_struct *task, | ||
117 | int has_fpscr) | ||
118 | { | ||
119 | unsigned int count = has_fpscr ? 33 : 32; | ||
120 | |||
121 | if (copy_from_user(task->thread.fpr, data, count * sizeof(double))) | ||
122 | return -EFAULT; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | |||
86 | #ifdef CONFIG_ALTIVEC | 127 | #ifdef CONFIG_ALTIVEC |
87 | /* | 128 | /* |
129 | * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. | ||
130 | * The transfer totals 34 quadword. Quadwords 0-31 contain the | ||
131 | * corresponding vector registers. Quadword 32 contains the vscr as the | ||
132 | * last word (offset 12) within that quadword. Quadword 33 contains the | ||
133 | * vrsave as the first word (offset 0) within the quadword. | ||
134 | * | ||
135 | * This definition of the VMX state is compatible with the current PPC32 | ||
136 | * ptrace interface. This allows signal handling and ptrace to use the | ||
137 | * same structures. This also simplifies the implementation of a bi-arch | ||
138 | * (combined (32- and 64-bit) gdb. | ||
139 | */ | ||
140 | |||
141 | /* | ||
88 | * Get contents of AltiVec register state in task TASK | 142 | * Get contents of AltiVec register state in task TASK |
89 | */ | 143 | */ |
90 | static inline int get_vrregs(unsigned long __user *data, struct task_struct *task) | 144 | static int get_vrregs(unsigned long __user *data, struct task_struct *task) |
91 | { | 145 | { |
92 | int i, j; | 146 | unsigned long regsize; |
93 | |||
94 | if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long))) | ||
95 | return -EFAULT; | ||
96 | 147 | ||
97 | /* copy AltiVec registers VR[0] .. VR[31] */ | 148 | /* copy AltiVec registers VR[0] .. VR[31] */ |
98 | for (i = 0; i < 32; i++) | 149 | regsize = 32 * sizeof(vector128); |
99 | for (j = 0; j < 4; j++, data++) | 150 | if (copy_to_user(data, task->thread.vr, regsize)) |
100 | if (__put_user(task->thread.vr[i].u[j], data)) | 151 | return -EFAULT; |
101 | return -EFAULT; | 152 | data += (regsize / sizeof(unsigned long)); |
102 | 153 | ||
103 | /* copy VSCR */ | 154 | /* copy VSCR */ |
104 | for (i = 0; i < 4; i++, data++) | 155 | regsize = 1 * sizeof(vector128); |
105 | if (__put_user(task->thread.vscr.u[i], data)) | 156 | if (copy_to_user(data, &task->thread.vscr, regsize)) |
106 | return -EFAULT; | 157 | return -EFAULT; |
158 | data += (regsize / sizeof(unsigned long)); | ||
107 | 159 | ||
108 | /* copy VRSAVE */ | 160 | /* copy VRSAVE */ |
109 | if (__put_user(task->thread.vrsave, data)) | 161 | if (put_user(task->thread.vrsave, (u32 __user *)data)) |
110 | return -EFAULT; | 162 | return -EFAULT; |
111 | 163 | ||
112 | return 0; | 164 | return 0; |
@@ -115,31 +167,29 @@ static inline int get_vrregs(unsigned long __user *data, struct task_struct *tas | |||
115 | /* | 167 | /* |
116 | * Write contents of AltiVec register state into task TASK. | 168 | * Write contents of AltiVec register state into task TASK. |
117 | */ | 169 | */ |
118 | static inline int set_vrregs(struct task_struct *task, unsigned long __user *data) | 170 | static int set_vrregs(struct task_struct *task, unsigned long __user *data) |
119 | { | 171 | { |
120 | int i, j; | 172 | unsigned long regsize; |
121 | |||
122 | if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long))) | ||
123 | return -EFAULT; | ||
124 | 173 | ||
125 | /* copy AltiVec registers VR[0] .. VR[31] */ | 174 | /* copy AltiVec registers VR[0] .. VR[31] */ |
126 | for (i = 0; i < 32; i++) | 175 | regsize = 32 * sizeof(vector128); |
127 | for (j = 0; j < 4; j++, data++) | 176 | if (copy_from_user(task->thread.vr, data, regsize)) |
128 | if (__get_user(task->thread.vr[i].u[j], data)) | 177 | return -EFAULT; |
129 | return -EFAULT; | 178 | data += (regsize / sizeof(unsigned long)); |
130 | 179 | ||
131 | /* copy VSCR */ | 180 | /* copy VSCR */ |
132 | for (i = 0; i < 4; i++, data++) | 181 | regsize = 1 * sizeof(vector128); |
133 | if (__get_user(task->thread.vscr.u[i], data)) | 182 | if (copy_from_user(&task->thread.vscr, data, regsize)) |
134 | return -EFAULT; | 183 | return -EFAULT; |
184 | data += (regsize / sizeof(unsigned long)); | ||
135 | 185 | ||
136 | /* copy VRSAVE */ | 186 | /* copy VRSAVE */ |
137 | if (__get_user(task->thread.vrsave, data)) | 187 | if (get_user(task->thread.vrsave, (u32 __user *)data)) |
138 | return -EFAULT; | 188 | return -EFAULT; |
139 | 189 | ||
140 | return 0; | 190 | return 0; |
141 | } | 191 | } |
142 | #endif | 192 | #endif /* CONFIG_ALTIVEC */ |
143 | 193 | ||
144 | #ifdef CONFIG_SPE | 194 | #ifdef CONFIG_SPE |
145 | 195 | ||
@@ -156,7 +206,7 @@ static inline int set_vrregs(struct task_struct *task, unsigned long __user *dat | |||
156 | /* | 206 | /* |
157 | * Get contents of SPE register state in task TASK. | 207 | * Get contents of SPE register state in task TASK. |
158 | */ | 208 | */ |
159 | static inline int get_evrregs(unsigned long *data, struct task_struct *task) | 209 | static int get_evrregs(unsigned long *data, struct task_struct *task) |
160 | { | 210 | { |
161 | int i; | 211 | int i; |
162 | 212 | ||
@@ -182,7 +232,7 @@ static inline int get_evrregs(unsigned long *data, struct task_struct *task) | |||
182 | /* | 232 | /* |
183 | * Write contents of SPE register state into task TASK. | 233 | * Write contents of SPE register state into task TASK. |
184 | */ | 234 | */ |
185 | static inline int set_evrregs(struct task_struct *task, unsigned long *data) | 235 | static int set_evrregs(struct task_struct *task, unsigned long *data) |
186 | { | 236 | { |
187 | int i; | 237 | int i; |
188 | 238 | ||
@@ -205,8 +255,8 @@ static inline int set_evrregs(struct task_struct *task, unsigned long *data) | |||
205 | } | 255 | } |
206 | #endif /* CONFIG_SPE */ | 256 | #endif /* CONFIG_SPE */ |
207 | 257 | ||
208 | static inline void | 258 | |
209 | set_single_step(struct task_struct *task) | 259 | static void set_single_step(struct task_struct *task) |
210 | { | 260 | { |
211 | struct pt_regs *regs = task->thread.regs; | 261 | struct pt_regs *regs = task->thread.regs; |
212 | 262 | ||
@@ -221,8 +271,7 @@ set_single_step(struct task_struct *task) | |||
221 | set_tsk_thread_flag(task, TIF_SINGLESTEP); | 271 | set_tsk_thread_flag(task, TIF_SINGLESTEP); |
222 | } | 272 | } |
223 | 273 | ||
224 | static inline void | 274 | static void clear_single_step(struct task_struct *task) |
225 | clear_single_step(struct task_struct *task) | ||
226 | { | 275 | { |
227 | struct pt_regs *regs = task->thread.regs; | 276 | struct pt_regs *regs = task->thread.regs; |
228 | 277 | ||
@@ -236,7 +285,25 @@ clear_single_step(struct task_struct *task) | |||
236 | } | 285 | } |
237 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | 286 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); |
238 | } | 287 | } |
239 | #endif /* CONFIG_PPC32 */ | 288 | |
289 | static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | ||
290 | unsigned long data) | ||
291 | { | ||
292 | /* We only support one DABR and no IABRS at the moment */ | ||
293 | if (addr > 0) | ||
294 | return -EINVAL; | ||
295 | |||
296 | /* The bottom 3 bits are flags */ | ||
297 | if ((data & ~0x7UL) >= TASK_SIZE) | ||
298 | return -EIO; | ||
299 | |||
300 | /* Ensure translation is on */ | ||
301 | if (data && !(data & DABR_TRANSLATION)) | ||
302 | return -EIO; | ||
303 | |||
304 | task->thread.dabr = data; | ||
305 | return 0; | ||
306 | } | ||
240 | 307 | ||
241 | /* | 308 | /* |
242 | * Called by kernel/ptrace.c when detaching.. | 309 | * Called by kernel/ptrace.c when detaching.. |
@@ -249,6 +316,62 @@ void ptrace_disable(struct task_struct *child) | |||
249 | clear_single_step(child); | 316 | clear_single_step(child); |
250 | } | 317 | } |
251 | 318 | ||
319 | /* | ||
320 | * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, | ||
321 | * we mark them as obsolete now, they will be removed in a future version | ||
322 | */ | ||
323 | static long arch_ptrace_old(struct task_struct *child, long request, long addr, | ||
324 | long data) | ||
325 | { | ||
326 | int ret = -EPERM; | ||
327 | |||
328 | switch(request) { | ||
329 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||
330 | int i; | ||
331 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
332 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
333 | |||
334 | for (i = 0; i < 32; i++) { | ||
335 | ret = put_user(*reg, tmp); | ||
336 | if (ret) | ||
337 | break; | ||
338 | reg++; | ||
339 | tmp++; | ||
340 | } | ||
341 | break; | ||
342 | } | ||
343 | |||
344 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||
345 | int i; | ||
346 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
347 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
348 | |||
349 | for (i = 0; i < 32; i++) { | ||
350 | ret = get_user(*reg, tmp); | ||
351 | if (ret) | ||
352 | break; | ||
353 | reg++; | ||
354 | tmp++; | ||
355 | } | ||
356 | break; | ||
357 | } | ||
358 | |||
359 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | ||
360 | flush_fp_to_thread(child); | ||
361 | ret = get_fpregs((void __user *)addr, child, 0); | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||
366 | flush_fp_to_thread(child); | ||
367 | ret = set_fpregs((void __user *)addr, child, 0); | ||
368 | break; | ||
369 | } | ||
370 | |||
371 | } | ||
372 | return ret; | ||
373 | } | ||
374 | |||
252 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 375 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
253 | { | 376 | { |
254 | int ret = -EPERM; | 377 | int ret = -EPERM; |
@@ -256,17 +379,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
256 | switch (request) { | 379 | switch (request) { |
257 | /* when I and D space are separate, these will need to be fixed. */ | 380 | /* when I and D space are separate, these will need to be fixed. */ |
258 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 381 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
259 | case PTRACE_PEEKDATA: { | 382 | case PTRACE_PEEKDATA: |
260 | unsigned long tmp; | 383 | ret = generic_ptrace_peekdata(child, addr, data); |
261 | int copied; | ||
262 | |||
263 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
264 | ret = -EIO; | ||
265 | if (copied != sizeof(tmp)) | ||
266 | break; | ||
267 | ret = put_user(tmp,(unsigned long __user *) data); | ||
268 | break; | 384 | break; |
269 | } | ||
270 | 385 | ||
271 | /* read the word at location addr in the USER area. */ | 386 | /* read the word at location addr in the USER area. */ |
272 | case PTRACE_PEEKUSR: { | 387 | case PTRACE_PEEKUSR: { |
@@ -284,11 +399,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
284 | #endif | 399 | #endif |
285 | break; | 400 | break; |
286 | 401 | ||
287 | #ifdef CONFIG_PPC32 | ||
288 | CHECK_FULL_REGS(child->thread.regs); | 402 | CHECK_FULL_REGS(child->thread.regs); |
289 | #endif | ||
290 | if (index < PT_FPR0) { | 403 | if (index < PT_FPR0) { |
291 | tmp = get_reg(child, (int) index); | 404 | tmp = ptrace_get_reg(child, (int) index); |
292 | } else { | 405 | } else { |
293 | flush_fp_to_thread(child); | 406 | flush_fp_to_thread(child); |
294 | tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; | 407 | tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; |
@@ -300,11 +413,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
300 | /* If I and D space are separate, this will have to be fixed. */ | 413 | /* If I and D space are separate, this will have to be fixed. */ |
301 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 414 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
302 | case PTRACE_POKEDATA: | 415 | case PTRACE_POKEDATA: |
303 | ret = 0; | 416 | ret = generic_ptrace_pokedata(child, addr, data); |
304 | if (access_process_vm(child, addr, &data, sizeof(data), 1) | ||
305 | == sizeof(data)) | ||
306 | break; | ||
307 | ret = -EIO; | ||
308 | break; | 417 | break; |
309 | 418 | ||
310 | /* write the word at location addr in the USER area */ | 419 | /* write the word at location addr in the USER area */ |
@@ -323,13 +432,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
323 | #endif | 432 | #endif |
324 | break; | 433 | break; |
325 | 434 | ||
326 | #ifdef CONFIG_PPC32 | ||
327 | CHECK_FULL_REGS(child->thread.regs); | 435 | CHECK_FULL_REGS(child->thread.regs); |
328 | #endif | ||
329 | if (index == PT_ORIG_R3) | ||
330 | break; | ||
331 | if (index < PT_FPR0) { | 436 | if (index < PT_FPR0) { |
332 | ret = put_reg(child, index, data); | 437 | ret = ptrace_put_reg(child, index, data); |
333 | } else { | 438 | } else { |
334 | flush_fp_to_thread(child); | 439 | flush_fp_to_thread(child); |
335 | ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; | 440 | ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; |
@@ -384,7 +489,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
384 | break; | 489 | break; |
385 | } | 490 | } |
386 | 491 | ||
387 | #ifdef CONFIG_PPC64 | ||
388 | case PTRACE_GET_DEBUGREG: { | 492 | case PTRACE_GET_DEBUGREG: { |
389 | ret = -EINVAL; | 493 | ret = -EINVAL; |
390 | /* We only support one DABR and no IABRS at the moment */ | 494 | /* We only support one DABR and no IABRS at the moment */ |
@@ -398,73 +502,61 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
398 | case PTRACE_SET_DEBUGREG: | 502 | case PTRACE_SET_DEBUGREG: |
399 | ret = ptrace_set_debugreg(child, addr, data); | 503 | ret = ptrace_set_debugreg(child, addr, data); |
400 | break; | 504 | break; |
401 | #endif | ||
402 | 505 | ||
403 | case PTRACE_DETACH: | 506 | case PTRACE_DETACH: |
404 | ret = ptrace_detach(child, data); | 507 | ret = ptrace_detach(child, data); |
405 | break; | 508 | break; |
406 | 509 | ||
407 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 510 | #ifdef CONFIG_PPC64 |
408 | int i; | 511 | case PTRACE_GETREGS64: |
409 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 512 | #endif |
410 | unsigned long __user *tmp = (unsigned long __user *)addr; | 513 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ |
411 | 514 | int ui; | |
412 | for (i = 0; i < 32; i++) { | 515 | if (!access_ok(VERIFY_WRITE, (void __user *)data, |
413 | ret = put_user(*reg, tmp); | 516 | sizeof(struct pt_regs))) { |
414 | if (ret) | 517 | ret = -EIO; |
415 | break; | 518 | break; |
416 | reg++; | 519 | } |
417 | tmp++; | 520 | ret = 0; |
521 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
522 | ret |= __put_user(ptrace_get_reg(child, ui), | ||
523 | (unsigned long __user *) data); | ||
524 | data += sizeof(long); | ||
418 | } | 525 | } |
419 | break; | 526 | break; |
420 | } | 527 | } |
421 | 528 | ||
422 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | 529 | #ifdef CONFIG_PPC64 |
423 | int i; | 530 | case PTRACE_SETREGS64: |
424 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 531 | #endif |
425 | unsigned long __user *tmp = (unsigned long __user *)addr; | 532 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ |
426 | 533 | unsigned long tmp; | |
427 | for (i = 0; i < 32; i++) { | 534 | int ui; |
428 | ret = get_user(*reg, tmp); | 535 | if (!access_ok(VERIFY_READ, (void __user *)data, |
536 | sizeof(struct pt_regs))) { | ||
537 | ret = -EIO; | ||
538 | break; | ||
539 | } | ||
540 | ret = 0; | ||
541 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
542 | ret = __get_user(tmp, (unsigned long __user *) data); | ||
429 | if (ret) | 543 | if (ret) |
430 | break; | 544 | break; |
431 | reg++; | 545 | ptrace_put_reg(child, ui, tmp); |
432 | tmp++; | 546 | data += sizeof(long); |
433 | } | 547 | } |
434 | break; | 548 | break; |
435 | } | 549 | } |
436 | 550 | ||
437 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | 551 | case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */ |
438 | int i; | ||
439 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||
440 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
441 | |||
442 | flush_fp_to_thread(child); | 552 | flush_fp_to_thread(child); |
443 | 553 | ret = get_fpregs((void __user *)data, child, 1); | |
444 | for (i = 0; i < 32; i++) { | ||
445 | ret = put_user(*reg, tmp); | ||
446 | if (ret) | ||
447 | break; | ||
448 | reg++; | ||
449 | tmp++; | ||
450 | } | ||
451 | break; | 554 | break; |
452 | } | 555 | } |
453 | 556 | ||
454 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | 557 | case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */ |
455 | int i; | ||
456 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||
457 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
458 | |||
459 | flush_fp_to_thread(child); | 558 | flush_fp_to_thread(child); |
460 | 559 | ret = set_fpregs((void __user *)data, child, 1); | |
461 | for (i = 0; i < 32; i++) { | ||
462 | ret = get_user(*reg, tmp); | ||
463 | if (ret) | ||
464 | break; | ||
465 | reg++; | ||
466 | tmp++; | ||
467 | } | ||
468 | break; | 560 | break; |
469 | } | 561 | } |
470 | 562 | ||
@@ -499,11 +591,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
499 | break; | 591 | break; |
500 | #endif | 592 | #endif |
501 | 593 | ||
594 | /* Old reverse args ptrace callss */ | ||
595 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | ||
596 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ | ||
597 | case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ | ||
598 | case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */ | ||
599 | ret = arch_ptrace_old(child, request, addr, data); | ||
600 | break; | ||
601 | |||
502 | default: | 602 | default: |
503 | ret = ptrace_request(child, request, addr, data); | 603 | ret = ptrace_request(child, request, addr, data); |
504 | break; | 604 | break; |
505 | } | 605 | } |
506 | |||
507 | return ret; | 606 | return ret; |
508 | } | 607 | } |
509 | 608 | ||
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 9b9a230349bc..9e6baeac0fb1 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -33,13 +33,55 @@ | |||
33 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
34 | #include <asm/system.h> | 34 | #include <asm/system.h> |
35 | 35 | ||
36 | #include "ptrace-common.h" | ||
37 | |||
38 | /* | 36 | /* |
39 | * does not yet catch signals sent when the child dies. | 37 | * does not yet catch signals sent when the child dies. |
40 | * in exit.c or in signal.c. | 38 | * in exit.c or in signal.c. |
41 | */ | 39 | */ |
42 | 40 | ||
41 | /* | ||
42 | * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, | ||
43 | * we mark them as obsolete now, they will be removed in a future version | ||
44 | */ | ||
45 | static long compat_ptrace_old(struct task_struct *child, long request, | ||
46 | long addr, long data) | ||
47 | { | ||
48 | int ret = -EPERM; | ||
49 | |||
50 | switch(request) { | ||
51 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | ||
52 | int i; | ||
53 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
54 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
55 | |||
56 | for (i = 0; i < 32; i++) { | ||
57 | ret = put_user(*reg, tmp); | ||
58 | if (ret) | ||
59 | break; | ||
60 | reg++; | ||
61 | tmp++; | ||
62 | } | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||
67 | int i; | ||
68 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
69 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
70 | |||
71 | for (i = 0; i < 32; i++) { | ||
72 | ret = get_user(*reg, tmp); | ||
73 | if (ret) | ||
74 | break; | ||
75 | reg++; | ||
76 | tmp++; | ||
77 | } | ||
78 | break; | ||
79 | } | ||
80 | |||
81 | } | ||
82 | return ret; | ||
83 | } | ||
84 | |||
43 | long compat_sys_ptrace(int request, int pid, unsigned long addr, | 85 | long compat_sys_ptrace(int request, int pid, unsigned long addr, |
44 | unsigned long data) | 86 | unsigned long data) |
45 | { | 87 | { |
@@ -123,7 +165,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
123 | break; | 165 | break; |
124 | 166 | ||
125 | if (index < PT_FPR0) { | 167 | if (index < PT_FPR0) { |
126 | tmp = get_reg(child, index); | 168 | tmp = ptrace_get_reg(child, index); |
127 | } else { | 169 | } else { |
128 | flush_fp_to_thread(child); | 170 | flush_fp_to_thread(child); |
129 | /* | 171 | /* |
@@ -162,7 +204,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
162 | else | 204 | else |
163 | part = 0; /* want the 1st half of the register (left-most). */ | 205 | part = 0; /* want the 1st half of the register (left-most). */ |
164 | 206 | ||
165 | /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ | 207 | /* Validate the input - check to see if address is on the wrong boundary |
208 | * or beyond the end of the user area | ||
209 | */ | ||
166 | if ((addr & 3) || numReg > PT_FPSCR) | 210 | if ((addr & 3) || numReg > PT_FPSCR) |
167 | break; | 211 | break; |
168 | 212 | ||
@@ -170,7 +214,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
170 | flush_fp_to_thread(child); | 214 | flush_fp_to_thread(child); |
171 | tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; | 215 | tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; |
172 | } else { /* register within PT_REGS struct */ | 216 | } else { /* register within PT_REGS struct */ |
173 | tmp = get_reg(child, numReg); | 217 | tmp = ptrace_get_reg(child, numReg); |
174 | } | 218 | } |
175 | reg32bits = ((u32*)&tmp)[part]; | 219 | reg32bits = ((u32*)&tmp)[part]; |
176 | ret = put_user(reg32bits, (u32 __user *)data); | 220 | ret = put_user(reg32bits, (u32 __user *)data); |
@@ -226,10 +270,8 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
226 | if ((addr & 3) || (index > PT_FPSCR32)) | 270 | if ((addr & 3) || (index > PT_FPSCR32)) |
227 | break; | 271 | break; |
228 | 272 | ||
229 | if (index == PT_ORIG_R3) | ||
230 | break; | ||
231 | if (index < PT_FPR0) { | 273 | if (index < PT_FPR0) { |
232 | ret = put_reg(child, index, data); | 274 | ret = ptrace_put_reg(child, index, data); |
233 | } else { | 275 | } else { |
234 | flush_fp_to_thread(child); | 276 | flush_fp_to_thread(child); |
235 | /* | 277 | /* |
@@ -258,70 +300,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
258 | /* Determine which register the user wants */ | 300 | /* Determine which register the user wants */ |
259 | index = (u64)addr >> 2; | 301 | index = (u64)addr >> 2; |
260 | numReg = index / 2; | 302 | numReg = index / 2; |
303 | |||
261 | /* | 304 | /* |
262 | * Validate the input - check to see if address is on the | 305 | * Validate the input - check to see if address is on the |
263 | * wrong boundary or beyond the end of the user area | 306 | * wrong boundary or beyond the end of the user area |
264 | */ | 307 | */ |
265 | if ((addr & 3) || (numReg > PT_FPSCR)) | 308 | if ((addr & 3) || (numReg > PT_FPSCR)) |
266 | break; | 309 | break; |
267 | /* Insure it is a register we let them change */ | 310 | if (numReg < PT_FPR0) { |
268 | if ((numReg == PT_ORIG_R3) | 311 | unsigned long freg = ptrace_get_reg(child, numReg); |
269 | || ((numReg > PT_CCR) && (numReg < PT_FPR0))) | 312 | if (index % 2) |
270 | break; | 313 | freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); |
271 | if (numReg >= PT_FPR0) { | 314 | else |
315 | freg = (freg & 0xfffffffful) | (data << 32); | ||
316 | ret = ptrace_put_reg(child, numReg, freg); | ||
317 | } else { | ||
272 | flush_fp_to_thread(child); | 318 | flush_fp_to_thread(child); |
319 | ((unsigned int *)child->thread.regs)[index] = data; | ||
320 | ret = 0; | ||
273 | } | 321 | } |
274 | if (numReg == PT_MSR) | ||
275 | data = (data & MSR_DEBUGCHANGE) | ||
276 | | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); | ||
277 | ((u32*)child->thread.regs)[index] = data; | ||
278 | ret = 0; | ||
279 | break; | ||
280 | } | ||
281 | |||
282 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
283 | case PTRACE_CONT: { /* restart after signal. */ | ||
284 | ret = -EIO; | ||
285 | if (!valid_signal(data)) | ||
286 | break; | ||
287 | if (request == PTRACE_SYSCALL) | ||
288 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
289 | else | ||
290 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
291 | child->exit_code = data; | ||
292 | /* make sure the single step bit is not set. */ | ||
293 | clear_single_step(child); | ||
294 | wake_up_process(child); | ||
295 | ret = 0; | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * make the child exit. Best I can do is send it a sigkill. | ||
301 | * perhaps it should be put in the status that it wants to | ||
302 | * exit. | ||
303 | */ | ||
304 | case PTRACE_KILL: { | ||
305 | ret = 0; | ||
306 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
307 | break; | ||
308 | child->exit_code = SIGKILL; | ||
309 | /* make sure the single step bit is not set. */ | ||
310 | clear_single_step(child); | ||
311 | wake_up_process(child); | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
316 | ret = -EIO; | ||
317 | if (!valid_signal(data)) | ||
318 | break; | ||
319 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
320 | set_single_step(child); | ||
321 | child->exit_code = data; | ||
322 | /* give it a chance to run. */ | ||
323 | wake_up_process(child); | ||
324 | ret = 0; | ||
325 | break; | 322 | break; |
326 | } | 323 | } |
327 | 324 | ||
@@ -334,95 +331,67 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, | |||
334 | break; | 331 | break; |
335 | } | 332 | } |
336 | 333 | ||
337 | case PTRACE_SET_DEBUGREG: | 334 | case PTRACE_GETEVENTMSG: |
338 | ret = ptrace_set_debugreg(child, addr, data); | 335 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); |
339 | break; | ||
340 | |||
341 | case PTRACE_DETACH: | ||
342 | ret = ptrace_detach(child, data); | ||
343 | break; | 336 | break; |
344 | 337 | ||
345 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 338 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ |
346 | int i; | 339 | int ui; |
347 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 340 | if (!access_ok(VERIFY_WRITE, (void __user *)data, |
348 | unsigned int __user *tmp = (unsigned int __user *)addr; | 341 | PT_REGS_COUNT * sizeof(int))) { |
349 | 342 | ret = -EIO; | |
350 | for (i = 0; i < 32; i++) { | 343 | break; |
351 | ret = put_user(*reg, tmp); | ||
352 | if (ret) | ||
353 | break; | ||
354 | reg++; | ||
355 | tmp++; | ||
356 | } | 344 | } |
357 | break; | 345 | ret = 0; |
358 | } | 346 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { |
359 | 347 | ret |= __put_user(ptrace_get_reg(child, ui), | |
360 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | 348 | (unsigned int __user *) data); |
361 | int i; | 349 | data += sizeof(int); |
362 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
363 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
364 | |||
365 | for (i = 0; i < 32; i++) { | ||
366 | ret = get_user(*reg, tmp); | ||
367 | if (ret) | ||
368 | break; | ||
369 | reg++; | ||
370 | tmp++; | ||
371 | } | 350 | } |
372 | break; | 351 | break; |
373 | } | 352 | } |
374 | 353 | ||
375 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | 354 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ |
376 | int i; | 355 | unsigned long tmp; |
377 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | 356 | int ui; |
378 | unsigned int __user *tmp = (unsigned int __user *)addr; | 357 | if (!access_ok(VERIFY_READ, (void __user *)data, |
379 | 358 | PT_REGS_COUNT * sizeof(int))) { | |
380 | flush_fp_to_thread(child); | 359 | ret = -EIO; |
381 | 360 | break; | |
382 | for (i = 0; i < 32; i++) { | ||
383 | ret = put_user(*reg, tmp); | ||
384 | if (ret) | ||
385 | break; | ||
386 | reg++; | ||
387 | tmp++; | ||
388 | } | 361 | } |
389 | break; | 362 | ret = 0; |
390 | } | 363 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { |
391 | 364 | ret = __get_user(tmp, (unsigned int __user *) data); | |
392 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||
393 | int i; | ||
394 | unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; | ||
395 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
396 | |||
397 | flush_fp_to_thread(child); | ||
398 | |||
399 | for (i = 0; i < 32; i++) { | ||
400 | ret = get_user(*reg, tmp); | ||
401 | if (ret) | 365 | if (ret) |
402 | break; | 366 | break; |
403 | reg++; | 367 | ptrace_put_reg(child, ui, tmp); |
404 | tmp++; | 368 | data += sizeof(int); |
405 | } | 369 | } |
406 | break; | 370 | break; |
407 | } | 371 | } |
408 | 372 | ||
409 | case PTRACE_GETEVENTMSG: | 373 | case PTRACE_GETFPREGS: |
410 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); | 374 | case PTRACE_SETFPREGS: |
411 | break; | ||
412 | |||
413 | #ifdef CONFIG_ALTIVEC | ||
414 | case PTRACE_GETVRREGS: | 375 | case PTRACE_GETVRREGS: |
415 | /* Get the child altivec register state. */ | 376 | case PTRACE_SETVRREGS: |
416 | flush_altivec_to_thread(child); | 377 | case PTRACE_GETREGS64: |
417 | ret = get_vrregs((unsigned long __user *)data, child); | 378 | case PTRACE_SETREGS64: |
379 | case PPC_PTRACE_GETFPREGS: | ||
380 | case PPC_PTRACE_SETFPREGS: | ||
381 | case PTRACE_KILL: | ||
382 | case PTRACE_SINGLESTEP: | ||
383 | case PTRACE_DETACH: | ||
384 | case PTRACE_SET_DEBUGREG: | ||
385 | case PTRACE_SYSCALL: | ||
386 | case PTRACE_CONT: | ||
387 | ret = arch_ptrace(child, request, addr, data); | ||
418 | break; | 388 | break; |
419 | 389 | ||
420 | case PTRACE_SETVRREGS: | 390 | /* Old reverse args ptrace callss */ |
421 | /* Set the child altivec register state. */ | 391 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ |
422 | flush_altivec_to_thread(child); | 392 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ |
423 | ret = set_vrregs(child, (unsigned long __user *)data); | 393 | ret = compat_ptrace_old(child, request, addr, data); |
424 | break; | 394 | break; |
425 | #endif | ||
426 | 395 | ||
427 | default: | 396 | default: |
428 | ret = ptrace_request(child, request, addr, data); | 397 | ret = ptrace_request(child, request, addr, data); |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index f2286822be09..a5de6211b97a 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -278,10 +278,8 @@ void __init find_and_init_phbs(void) | |||
278 | { | 278 | { |
279 | struct device_node *node; | 279 | struct device_node *node; |
280 | struct pci_controller *phb; | 280 | struct pci_controller *phb; |
281 | unsigned int index; | ||
282 | struct device_node *root = of_find_node_by_path("/"); | 281 | struct device_node *root = of_find_node_by_path("/"); |
283 | 282 | ||
284 | index = 0; | ||
285 | for (node = of_get_next_child(root, NULL); | 283 | for (node = of_get_next_child(root, NULL); |
286 | node != NULL; | 284 | node != NULL; |
287 | node = of_get_next_child(root, node)) { | 285 | node = of_get_next_child(root, node)) { |
@@ -295,8 +293,7 @@ void __init find_and_init_phbs(void) | |||
295 | continue; | 293 | continue; |
296 | rtas_setup_phb(phb); | 294 | rtas_setup_phb(phb); |
297 | pci_process_bridge_OF_ranges(phb, node, 0); | 295 | pci_process_bridge_OF_ranges(phb, node, 0); |
298 | pci_setup_phb_io(phb, index == 0); | 296 | isa_bridge_find_early(phb); |
299 | index++; | ||
300 | } | 297 | } |
301 | 298 | ||
302 | of_node_put(root); | 299 | of_node_put(root); |
@@ -335,7 +332,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb) | |||
335 | return 1; | 332 | return 1; |
336 | } | 333 | } |
337 | 334 | ||
338 | rc = unmap_bus_range(b); | 335 | rc = pcibios_unmap_io_space(b); |
339 | if (rc) { | 336 | if (rc) { |
340 | printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", | 337 | printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", |
341 | __FUNCTION__, b->name); | 338 | __FUNCTION__, b->name); |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index ed07a198f8d6..4924c48cb1ff 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/unistd.h> | 32 | #include <linux/unistd.h> |
33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
34 | #include <linux/serial_8250.h> | 34 | #include <linux/serial_8250.h> |
35 | #include <linux/debugfs.h> | ||
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | #include <asm/prom.h> | 37 | #include <asm/prom.h> |
37 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
@@ -486,6 +487,14 @@ int check_legacy_ioport(unsigned long base_port) | |||
486 | 487 | ||
487 | switch(base_port) { | 488 | switch(base_port) { |
488 | case I8042_DATA_REG: | 489 | case I8042_DATA_REG: |
490 | if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303"))) | ||
491 | np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03"); | ||
492 | if (np) { | ||
493 | parent = of_get_parent(np); | ||
494 | of_node_put(np); | ||
495 | np = parent; | ||
496 | break; | ||
497 | } | ||
489 | np = of_find_node_by_type(NULL, "8042"); | 498 | np = of_find_node_by_type(NULL, "8042"); |
490 | break; | 499 | break; |
491 | case FDC_BASE: /* FDC1 */ | 500 | case FDC_BASE: /* FDC1 */ |
@@ -571,3 +580,15 @@ static int __init check_cache_coherency(void) | |||
571 | 580 | ||
572 | late_initcall(check_cache_coherency); | 581 | late_initcall(check_cache_coherency); |
573 | #endif /* CONFIG_CHECK_CACHE_COHERENCY */ | 582 | #endif /* CONFIG_CHECK_CACHE_COHERENCY */ |
583 | |||
584 | #ifdef CONFIG_DEBUG_FS | ||
585 | struct dentry *powerpc_debugfs_root; | ||
586 | |||
587 | static int powerpc_debugfs_init(void) | ||
588 | { | ||
589 | powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL); | ||
590 | |||
591 | return powerpc_debugfs_root == NULL; | ||
592 | } | ||
593 | arch_initcall(powerpc_debugfs_init); | ||
594 | #endif | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 35f8f443c14f..7ec6ba56d83d 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -262,13 +262,11 @@ void __init setup_arch(char **cmdline_p) | |||
262 | * Systems with OF can look in the properties on the cpu node(s) | 262 | * Systems with OF can look in the properties on the cpu node(s) |
263 | * for a possibly more accurate value. | 263 | * for a possibly more accurate value. |
264 | */ | 264 | */ |
265 | if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { | 265 | dcache_bsize = cur_cpu_spec->dcache_bsize; |
266 | dcache_bsize = cur_cpu_spec->dcache_bsize; | 266 | icache_bsize = cur_cpu_spec->icache_bsize; |
267 | icache_bsize = cur_cpu_spec->icache_bsize; | 267 | ucache_bsize = 0; |
268 | ucache_bsize = 0; | 268 | if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) |
269 | } else | 269 | ucache_bsize = icache_bsize = dcache_bsize; |
270 | ucache_bsize = dcache_bsize = icache_bsize | ||
271 | = cur_cpu_spec->dcache_bsize; | ||
272 | 270 | ||
273 | /* reboot on panic */ | 271 | /* reboot on panic */ |
274 | panic_timeout = 180; | 272 | panic_timeout = 180; |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c new file mode 100644 index 000000000000..c434d6c4e4e6 --- /dev/null +++ b/arch/powerpc/kernel/signal.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Common signal handling code for both 32 and 64 bits | ||
3 | * | ||
4 | * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration | ||
5 | * Extracted from signal_32.c and signal_64.c | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General | ||
8 | * Public License. See the file README.legal in the main directory of | ||
9 | * this archive for more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/ptrace.h> | ||
13 | #include <linux/signal.h> | ||
14 | #include <asm/uaccess.h> | ||
15 | #include <asm/unistd.h> | ||
16 | |||
17 | #include "signal.h" | ||
18 | |||
19 | /* | ||
20 | * Allocate space for the signal frame | ||
21 | */ | ||
22 | void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
23 | size_t frame_size) | ||
24 | { | ||
25 | unsigned long oldsp, newsp; | ||
26 | |||
27 | /* Default to using normal stack */ | ||
28 | oldsp = regs->gpr[1]; | ||
29 | |||
30 | /* Check for alt stack */ | ||
31 | if ((ka->sa.sa_flags & SA_ONSTACK) && | ||
32 | current->sas_ss_size && !on_sig_stack(oldsp)) | ||
33 | oldsp = (current->sas_ss_sp + current->sas_ss_size); | ||
34 | |||
35 | /* Get aligned frame */ | ||
36 | newsp = (oldsp - frame_size) & ~0xFUL; | ||
37 | |||
38 | /* Check access */ | ||
39 | if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp)) | ||
40 | return NULL; | ||
41 | |||
42 | return (void __user *)newsp; | ||
43 | } | ||
44 | |||
45 | |||
46 | /* | ||
47 | * Restore the user process's signal mask | ||
48 | */ | ||
49 | void restore_sigmask(sigset_t *set) | ||
50 | { | ||
51 | sigdelsetmask(set, ~_BLOCKABLE); | ||
52 | spin_lock_irq(¤t->sighand->siglock); | ||
53 | current->blocked = *set; | ||
54 | recalc_sigpending(); | ||
55 | spin_unlock_irq(¤t->sighand->siglock); | ||
56 | } | ||
57 | |||
58 | static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | ||
59 | int has_handler) | ||
60 | { | ||
61 | unsigned long ret = regs->gpr[3]; | ||
62 | int restart = 1; | ||
63 | |||
64 | /* syscall ? */ | ||
65 | if (TRAP(regs) != 0x0C00) | ||
66 | return; | ||
67 | |||
68 | /* error signalled ? */ | ||
69 | if (!(regs->ccr & 0x10000000)) | ||
70 | return; | ||
71 | |||
72 | switch (ret) { | ||
73 | case ERESTART_RESTARTBLOCK: | ||
74 | case ERESTARTNOHAND: | ||
75 | /* ERESTARTNOHAND means that the syscall should only be | ||
76 | * restarted if there was no handler for the signal, and since | ||
77 | * we only get here if there is a handler, we dont restart. | ||
78 | */ | ||
79 | restart = !has_handler; | ||
80 | break; | ||
81 | case ERESTARTSYS: | ||
82 | /* ERESTARTSYS means to restart the syscall if there is no | ||
83 | * handler or the handler was registered with SA_RESTART | ||
84 | */ | ||
85 | restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0; | ||
86 | break; | ||
87 | case ERESTARTNOINTR: | ||
88 | /* ERESTARTNOINTR means that the syscall should be | ||
89 | * called again after the signal handler returns. | ||
90 | */ | ||
91 | break; | ||
92 | default: | ||
93 | return; | ||
94 | } | ||
95 | if (restart) { | ||
96 | if (ret == ERESTART_RESTARTBLOCK) | ||
97 | regs->gpr[0] = __NR_restart_syscall; | ||
98 | else | ||
99 | regs->gpr[3] = regs->orig_gpr3; | ||
100 | regs->nip -= 4; | ||
101 | regs->result = 0; | ||
102 | } else { | ||
103 | regs->result = -EINTR; | ||
104 | regs->gpr[3] = EINTR; | ||
105 | regs->ccr |= 0x10000000; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||
110 | { | ||
111 | siginfo_t info; | ||
112 | int signr; | ||
113 | struct k_sigaction ka; | ||
114 | int ret; | ||
115 | int is32 = is_32bit_task(); | ||
116 | |||
117 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
118 | oldset = ¤t->saved_sigmask; | ||
119 | else if (!oldset) | ||
120 | oldset = ¤t->blocked; | ||
121 | |||
122 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
123 | |||
124 | /* Is there any syscall restart business here ? */ | ||
125 | check_syscall_restart(regs, &ka, signr > 0); | ||
126 | |||
127 | if (signr <= 0) { | ||
128 | /* No signal to deliver -- put the saved sigmask back */ | ||
129 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
130 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
131 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
132 | } | ||
133 | return 0; /* no signals delivered */ | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Reenable the DABR before delivering the signal to | ||
138 | * user space. The DABR will have been cleared if it | ||
139 | * triggered inside the kernel. | ||
140 | */ | ||
141 | if (current->thread.dabr) | ||
142 | set_dabr(current->thread.dabr); | ||
143 | |||
144 | if (is32) { | ||
145 | if (ka.sa.sa_flags & SA_SIGINFO) | ||
146 | ret = handle_rt_signal32(signr, &ka, &info, oldset, | ||
147 | regs); | ||
148 | else | ||
149 | ret = handle_signal32(signr, &ka, &info, oldset, | ||
150 | regs); | ||
151 | } else { | ||
152 | ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); | ||
153 | } | ||
154 | |||
155 | if (ret) { | ||
156 | spin_lock_irq(¤t->sighand->siglock); | ||
157 | sigorsets(¤t->blocked, ¤t->blocked, | ||
158 | &ka.sa.sa_mask); | ||
159 | if (!(ka.sa.sa_flags & SA_NODEFER)) | ||
160 | sigaddset(¤t->blocked, signr); | ||
161 | recalc_sigpending(); | ||
162 | spin_unlock_irq(¤t->sighand->siglock); | ||
163 | |||
164 | /* | ||
165 | * A signal was successfully delivered; the saved sigmask is in | ||
166 | * its frame, and we can clear the TIF_RESTORE_SIGMASK flag. | ||
167 | */ | ||
168 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
169 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
170 | } | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | ||
176 | unsigned long r5, unsigned long r6, unsigned long r7, | ||
177 | unsigned long r8, struct pt_regs *regs) | ||
178 | { | ||
179 | return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||
180 | } | ||
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h new file mode 100644 index 000000000000..77efb3d5465a --- /dev/null +++ b/arch/powerpc/kernel/signal.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration | ||
3 | * Extracted from signal_32.c and signal_64.c | ||
4 | * | ||
5 | * This file is subject to the terms and conditions of the GNU General | ||
6 | * Public License. See the file README.legal in the main directory of | ||
7 | * this archive for more details. | ||
8 | */ | ||
9 | |||
10 | #ifndef _POWERPC_ARCH_SIGNAL_H | ||
11 | #define _POWERPC_ARCH_SIGNAL_H | ||
12 | |||
13 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | ||
14 | |||
15 | extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
16 | size_t frame_size); | ||
17 | extern void restore_sigmask(sigset_t *set); | ||
18 | |||
19 | extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, | ||
20 | siginfo_t *info, sigset_t *oldset, | ||
21 | struct pt_regs *regs); | ||
22 | |||
23 | extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | ||
24 | siginfo_t *info, sigset_t *oldset, | ||
25 | struct pt_regs *regs); | ||
26 | |||
27 | |||
28 | #ifdef CONFIG_PPC64 | ||
29 | |||
30 | static inline int is_32bit_task(void) | ||
31 | { | ||
32 | return test_thread_flag(TIF_32BIT); | ||
33 | } | ||
34 | |||
35 | extern int handle_rt_signal64(int signr, struct k_sigaction *ka, | ||
36 | siginfo_t *info, sigset_t *set, | ||
37 | struct pt_regs *regs); | ||
38 | |||
39 | #else /* CONFIG_PPC64 */ | ||
40 | |||
41 | static inline int is_32bit_task(void) | ||
42 | { | ||
43 | return 1; | ||
44 | } | ||
45 | |||
46 | static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, | ||
47 | siginfo_t *info, sigset_t *set, | ||
48 | struct pt_regs *regs) | ||
49 | { | ||
50 | return -EFAULT; | ||
51 | } | ||
52 | |||
53 | #endif /* !defined(CONFIG_PPC64) */ | ||
54 | |||
55 | #endif /* _POWERPC_ARCH_SIGNAL_H */ | ||
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index dd1dca5bfa81..590057e9e987 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -51,12 +51,11 @@ | |||
51 | #include <asm/pgtable.h> | 51 | #include <asm/pgtable.h> |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | #undef DEBUG_SIG | 54 | #include "signal.h" |
55 | 55 | ||
56 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 56 | #undef DEBUG_SIG |
57 | 57 | ||
58 | #ifdef CONFIG_PPC64 | 58 | #ifdef CONFIG_PPC64 |
59 | #define do_signal do_signal32 | ||
60 | #define sys_sigsuspend compat_sys_sigsuspend | 59 | #define sys_sigsuspend compat_sys_sigsuspend |
61 | #define sys_rt_sigsuspend compat_sys_rt_sigsuspend | 60 | #define sys_rt_sigsuspend compat_sys_rt_sigsuspend |
62 | #define sys_rt_sigreturn compat_sys_rt_sigreturn | 61 | #define sys_rt_sigreturn compat_sys_rt_sigreturn |
@@ -231,8 +230,6 @@ static inline int restore_general_regs(struct pt_regs *regs, | |||
231 | 230 | ||
232 | #endif /* CONFIG_PPC64 */ | 231 | #endif /* CONFIG_PPC64 */ |
233 | 232 | ||
234 | int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
235 | |||
236 | /* | 233 | /* |
237 | * Atomically swap in the new signal mask, and wait for a signal. | 234 | * Atomically swap in the new signal mask, and wait for a signal. |
238 | */ | 235 | */ |
@@ -251,14 +248,6 @@ long sys_sigsuspend(old_sigset_t mask) | |||
251 | return -ERESTARTNOHAND; | 248 | return -ERESTARTNOHAND; |
252 | } | 249 | } |
253 | 250 | ||
254 | #ifdef CONFIG_PPC32 | ||
255 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5, | ||
256 | int r6, int r7, int r8, struct pt_regs *regs) | ||
257 | { | ||
258 | return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||
259 | } | ||
260 | #endif | ||
261 | |||
262 | long sys_sigaction(int sig, struct old_sigaction __user *act, | 251 | long sys_sigaction(int sig, struct old_sigaction __user *act, |
263 | struct old_sigaction __user *oact) | 252 | struct old_sigaction __user *oact) |
264 | { | 253 | { |
@@ -293,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act, | |||
293 | /* | 282 | /* |
294 | * When we have signals to deliver, we set up on the | 283 | * When we have signals to deliver, we set up on the |
295 | * user stack, going down from the original stack pointer: | 284 | * user stack, going down from the original stack pointer: |
296 | * a sigregs struct | 285 | * an ABI gap of 56 words |
286 | * an mcontext struct | ||
297 | * a sigcontext struct | 287 | * a sigcontext struct |
298 | * a gap of __SIGNAL_FRAMESIZE bytes | 288 | * a gap of __SIGNAL_FRAMESIZE bytes |
299 | * | 289 | * |
300 | * Each of these things must be a multiple of 16 bytes in size. | 290 | * Each of these things must be a multiple of 16 bytes in size. The following |
291 | * structure represent all of this except the __SIGNAL_FRAMESIZE gap | ||
301 | * | 292 | * |
302 | */ | 293 | */ |
303 | struct sigregs { | 294 | struct sigframe { |
295 | struct sigcontext sctx; /* the sigcontext */ | ||
304 | struct mcontext mctx; /* all the register values */ | 296 | struct mcontext mctx; /* all the register values */ |
305 | /* | 297 | /* |
306 | * Programs using the rs6000/xcoff abi can save up to 19 gp | 298 | * Programs using the rs6000/xcoff abi can save up to 19 gp |
@@ -703,44 +695,22 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, | |||
703 | } | 695 | } |
704 | #endif /* CONFIG_PPC64 */ | 696 | #endif /* CONFIG_PPC64 */ |
705 | 697 | ||
706 | |||
707 | /* | ||
708 | * Restore the user process's signal mask | ||
709 | */ | ||
710 | #ifdef CONFIG_PPC64 | ||
711 | extern void restore_sigmask(sigset_t *set); | ||
712 | #else /* CONFIG_PPC64 */ | ||
713 | static void restore_sigmask(sigset_t *set) | ||
714 | { | ||
715 | sigdelsetmask(set, ~_BLOCKABLE); | ||
716 | spin_lock_irq(¤t->sighand->siglock); | ||
717 | current->blocked = *set; | ||
718 | recalc_sigpending(); | ||
719 | spin_unlock_irq(¤t->sighand->siglock); | ||
720 | } | ||
721 | #endif | ||
722 | |||
723 | /* | 698 | /* |
724 | * Set up a signal frame for a "real-time" signal handler | 699 | * Set up a signal frame for a "real-time" signal handler |
725 | * (one which gets siginfo). | 700 | * (one which gets siginfo). |
726 | */ | 701 | */ |
727 | static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | 702 | int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, |
728 | siginfo_t *info, sigset_t *oldset, | 703 | siginfo_t *info, sigset_t *oldset, |
729 | struct pt_regs *regs, unsigned long newsp) | 704 | struct pt_regs *regs) |
730 | { | 705 | { |
731 | struct rt_sigframe __user *rt_sf; | 706 | struct rt_sigframe __user *rt_sf; |
732 | struct mcontext __user *frame; | 707 | struct mcontext __user *frame; |
733 | unsigned long origsp = newsp; | 708 | unsigned long newsp = 0; |
734 | 709 | ||
735 | /* Set up Signal Frame */ | 710 | /* Set up Signal Frame */ |
736 | /* Put a Real Time Context onto stack */ | 711 | /* Put a Real Time Context onto stack */ |
737 | newsp -= sizeof(*rt_sf); | 712 | rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); |
738 | rt_sf = (struct rt_sigframe __user *)newsp; | 713 | if (unlikely(rt_sf == NULL)) |
739 | |||
740 | /* create a stack frame for the caller of the handler */ | ||
741 | newsp -= __SIGNAL_FRAMESIZE + 16; | ||
742 | |||
743 | if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) | ||
744 | goto badframe; | 714 | goto badframe; |
745 | 715 | ||
746 | /* Put the siginfo & fill in most of the ucontext */ | 716 | /* Put the siginfo & fill in most of the ucontext */ |
@@ -770,8 +740,12 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | |||
770 | 740 | ||
771 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 741 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
772 | 742 | ||
743 | /* create a stack frame for the caller of the handler */ | ||
744 | newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); | ||
773 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 745 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
774 | goto badframe; | 746 | goto badframe; |
747 | |||
748 | /* Fill registers for signal handler */ | ||
775 | regs->gpr[1] = newsp; | 749 | regs->gpr[1] = newsp; |
776 | regs->gpr[3] = sig; | 750 | regs->gpr[3] = sig; |
777 | regs->gpr[4] = (unsigned long) &rt_sf->info; | 751 | regs->gpr[4] = (unsigned long) &rt_sf->info; |
@@ -1015,27 +989,18 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1015 | /* | 989 | /* |
1016 | * OK, we're invoking a handler | 990 | * OK, we're invoking a handler |
1017 | */ | 991 | */ |
1018 | static int handle_signal(unsigned long sig, struct k_sigaction *ka, | 992 | int handle_signal32(unsigned long sig, struct k_sigaction *ka, |
1019 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, | 993 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
1020 | unsigned long newsp) | ||
1021 | { | 994 | { |
1022 | struct sigcontext __user *sc; | 995 | struct sigcontext __user *sc; |
1023 | struct sigregs __user *frame; | 996 | struct sigframe __user *frame; |
1024 | unsigned long origsp = newsp; | 997 | unsigned long newsp = 0; |
1025 | 998 | ||
1026 | /* Set up Signal Frame */ | 999 | /* Set up Signal Frame */ |
1027 | newsp -= sizeof(struct sigregs); | 1000 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
1028 | frame = (struct sigregs __user *) newsp; | 1001 | if (unlikely(frame == NULL)) |
1029 | |||
1030 | /* Put a sigcontext on the stack */ | ||
1031 | newsp -= sizeof(*sc); | ||
1032 | sc = (struct sigcontext __user *) newsp; | ||
1033 | |||
1034 | /* create a stack frame for the caller of the handler */ | ||
1035 | newsp -= __SIGNAL_FRAMESIZE; | ||
1036 | |||
1037 | if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) | ||
1038 | goto badframe; | 1002 | goto badframe; |
1003 | sc = (struct sigcontext __user *) &frame->sctx; | ||
1039 | 1004 | ||
1040 | #if _NSIG != 64 | 1005 | #if _NSIG != 64 |
1041 | #error "Please adjust handle_signal()" | 1006 | #error "Please adjust handle_signal()" |
@@ -1047,7 +1012,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
1047 | #else | 1012 | #else |
1048 | || __put_user(oldset->sig[1], &sc->_unused[3]) | 1013 | || __put_user(oldset->sig[1], &sc->_unused[3]) |
1049 | #endif | 1014 | #endif |
1050 | || __put_user(to_user_ptr(frame), &sc->regs) | 1015 | || __put_user(to_user_ptr(&frame->mctx), &sc->regs) |
1051 | || __put_user(sig, &sc->signal)) | 1016 | || __put_user(sig, &sc->signal)) |
1052 | goto badframe; | 1017 | goto badframe; |
1053 | 1018 | ||
@@ -1063,8 +1028,11 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
1063 | 1028 | ||
1064 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1029 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
1065 | 1030 | ||
1031 | /* create a stack frame for the caller of the handler */ | ||
1032 | newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; | ||
1066 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 1033 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
1067 | goto badframe; | 1034 | goto badframe; |
1035 | |||
1068 | regs->gpr[1] = newsp; | 1036 | regs->gpr[1] = newsp; |
1069 | regs->gpr[3] = sig; | 1037 | regs->gpr[3] = sig; |
1070 | regs->gpr[4] = (unsigned long) sc; | 1038 | regs->gpr[4] = (unsigned long) sc; |
@@ -1126,106 +1094,3 @@ badframe: | |||
1126 | force_sig(SIGSEGV, current); | 1094 | force_sig(SIGSEGV, current); |
1127 | return 0; | 1095 | return 0; |
1128 | } | 1096 | } |
1129 | |||
1130 | /* | ||
1131 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
1132 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
1133 | * mistake. | ||
1134 | */ | ||
1135 | int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||
1136 | { | ||
1137 | siginfo_t info; | ||
1138 | struct k_sigaction ka; | ||
1139 | unsigned int newsp; | ||
1140 | int signr, ret; | ||
1141 | |||
1142 | #ifdef CONFIG_PPC32 | ||
1143 | if (try_to_freeze()) { | ||
1144 | signr = 0; | ||
1145 | if (!signal_pending(current)) | ||
1146 | goto no_signal; | ||
1147 | } | ||
1148 | #endif | ||
1149 | |||
1150 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
1151 | oldset = ¤t->saved_sigmask; | ||
1152 | else if (!oldset) | ||
1153 | oldset = ¤t->blocked; | ||
1154 | |||
1155 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
1156 | #ifdef CONFIG_PPC32 | ||
1157 | no_signal: | ||
1158 | #endif | ||
1159 | if (TRAP(regs) == 0x0C00 /* System Call! */ | ||
1160 | && regs->ccr & 0x10000000 /* error signalled */ | ||
1161 | && ((ret = regs->gpr[3]) == ERESTARTSYS | ||
1162 | || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR | ||
1163 | || ret == ERESTART_RESTARTBLOCK)) { | ||
1164 | |||
1165 | if (signr > 0 | ||
1166 | && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK | ||
1167 | || (ret == ERESTARTSYS | ||
1168 | && !(ka.sa.sa_flags & SA_RESTART)))) { | ||
1169 | /* make the system call return an EINTR error */ | ||
1170 | regs->result = -EINTR; | ||
1171 | regs->gpr[3] = EINTR; | ||
1172 | /* note that the cr0.SO bit is already set */ | ||
1173 | } else { | ||
1174 | regs->nip -= 4; /* Back up & retry system call */ | ||
1175 | regs->result = 0; | ||
1176 | regs->trap = 0; | ||
1177 | if (ret == ERESTART_RESTARTBLOCK) | ||
1178 | regs->gpr[0] = __NR_restart_syscall; | ||
1179 | else | ||
1180 | regs->gpr[3] = regs->orig_gpr3; | ||
1181 | } | ||
1182 | } | ||
1183 | |||
1184 | if (signr == 0) { | ||
1185 | /* No signal to deliver -- put the saved sigmask back */ | ||
1186 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
1187 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1188 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
1189 | } | ||
1190 | return 0; /* no signals delivered */ | ||
1191 | } | ||
1192 | |||
1193 | if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size | ||
1194 | && !on_sig_stack(regs->gpr[1])) | ||
1195 | newsp = current->sas_ss_sp + current->sas_ss_size; | ||
1196 | else | ||
1197 | newsp = regs->gpr[1]; | ||
1198 | newsp &= ~0xfUL; | ||
1199 | |||
1200 | #ifdef CONFIG_PPC64 | ||
1201 | /* | ||
1202 | * Reenable the DABR before delivering the signal to | ||
1203 | * user space. The DABR will have been cleared if it | ||
1204 | * triggered inside the kernel. | ||
1205 | */ | ||
1206 | if (current->thread.dabr) | ||
1207 | set_dabr(current->thread.dabr); | ||
1208 | #endif | ||
1209 | |||
1210 | /* Whee! Actually deliver the signal. */ | ||
1211 | if (ka.sa.sa_flags & SA_SIGINFO) | ||
1212 | ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp); | ||
1213 | else | ||
1214 | ret = handle_signal(signr, &ka, &info, oldset, regs, newsp); | ||
1215 | |||
1216 | if (ret) { | ||
1217 | spin_lock_irq(¤t->sighand->siglock); | ||
1218 | sigorsets(¤t->blocked, ¤t->blocked, | ||
1219 | &ka.sa.sa_mask); | ||
1220 | if (!(ka.sa.sa_flags & SA_NODEFER)) | ||
1221 | sigaddset(¤t->blocked, signr); | ||
1222 | recalc_sigpending(); | ||
1223 | spin_unlock_irq(¤t->sighand->siglock); | ||
1224 | /* A signal was successfully delivered; the saved sigmask is in | ||
1225 | its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||
1226 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
1227 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1228 | } | ||
1229 | |||
1230 | return ret; | ||
1231 | } | ||
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index b27e26852fdb..de895e6d8c62 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -34,9 +34,9 @@ | |||
34 | #include <asm/syscalls.h> | 34 | #include <asm/syscalls.h> |
35 | #include <asm/vdso.h> | 35 | #include <asm/vdso.h> |
36 | 36 | ||
37 | #define DEBUG_SIG 0 | 37 | #include "signal.h" |
38 | 38 | ||
39 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 39 | #define DEBUG_SIG 0 |
40 | 40 | ||
41 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) | 41 | #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) |
42 | #define FP_REGS_SIZE sizeof(elf_fpregset_t) | 42 | #define FP_REGS_SIZE sizeof(elf_fpregset_t) |
@@ -64,14 +64,6 @@ struct rt_sigframe { | |||
64 | char abigap[288]; | 64 | char abigap[288]; |
65 | } __attribute__ ((aligned (16))); | 65 | } __attribute__ ((aligned (16))); |
66 | 66 | ||
67 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, | ||
68 | unsigned long r6, unsigned long r7, unsigned long r8, | ||
69 | struct pt_regs *regs) | ||
70 | { | ||
71 | return do_sigaltstack(uss, uoss, regs->gpr[1]); | ||
72 | } | ||
73 | |||
74 | |||
75 | /* | 67 | /* |
76 | * Set up the sigcontext for the signal frame. | 68 | * Set up the sigcontext for the signal frame. |
77 | */ | 69 | */ |
@@ -208,25 +200,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
208 | } | 200 | } |
209 | 201 | ||
210 | /* | 202 | /* |
211 | * Allocate space for the signal frame | ||
212 | */ | ||
213 | static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | ||
214 | size_t frame_size) | ||
215 | { | ||
216 | unsigned long newsp; | ||
217 | |||
218 | /* Default to using normal stack */ | ||
219 | newsp = regs->gpr[1]; | ||
220 | |||
221 | if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) { | ||
222 | if (! on_sig_stack(regs->gpr[1])) | ||
223 | newsp = (current->sas_ss_sp + current->sas_ss_size); | ||
224 | } | ||
225 | |||
226 | return (void __user *)((newsp - frame_size) & -16ul); | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Setup the trampoline code on the stack | 203 | * Setup the trampoline code on the stack |
231 | */ | 204 | */ |
232 | static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) | 205 | static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) |
@@ -253,19 +226,6 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) | |||
253 | } | 226 | } |
254 | 227 | ||
255 | /* | 228 | /* |
256 | * Restore the user process's signal mask (also used by signal32.c) | ||
257 | */ | ||
258 | void restore_sigmask(sigset_t *set) | ||
259 | { | ||
260 | sigdelsetmask(set, ~_BLOCKABLE); | ||
261 | spin_lock_irq(¤t->sighand->siglock); | ||
262 | current->blocked = *set; | ||
263 | recalc_sigpending(); | ||
264 | spin_unlock_irq(¤t->sighand->siglock); | ||
265 | } | ||
266 | |||
267 | |||
268 | /* | ||
269 | * Handle {get,set,swap}_context operations | 229 | * Handle {get,set,swap}_context operations |
270 | */ | 230 | */ |
271 | int sys_swapcontext(struct ucontext __user *old_ctx, | 231 | int sys_swapcontext(struct ucontext __user *old_ctx, |
@@ -359,7 +319,7 @@ badframe: | |||
359 | return 0; | 319 | return 0; |
360 | } | 320 | } |
361 | 321 | ||
362 | static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | 322 | int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, |
363 | sigset_t *set, struct pt_regs *regs) | 323 | sigset_t *set, struct pt_regs *regs) |
364 | { | 324 | { |
365 | /* Handler is *really* a pointer to the function descriptor for | 325 | /* Handler is *really* a pointer to the function descriptor for |
@@ -373,8 +333,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
373 | long err = 0; | 333 | long err = 0; |
374 | 334 | ||
375 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 335 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
376 | 336 | if (unlikely(frame == NULL)) | |
377 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | ||
378 | goto badframe; | 337 | goto badframe; |
379 | 338 | ||
380 | err |= __put_user(&frame->info, &frame->pinfo); | 339 | err |= __put_user(&frame->info, &frame->pinfo); |
@@ -411,7 +370,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
411 | funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; | 370 | funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; |
412 | 371 | ||
413 | /* Allocate a dummy caller frame for the signal handler. */ | 372 | /* Allocate a dummy caller frame for the signal handler. */ |
414 | newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; | 373 | newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; |
415 | err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); | 374 | err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); |
416 | 375 | ||
417 | /* Set up "regs" so we "return" to the signal handler. */ | 376 | /* Set up "regs" so we "return" to the signal handler. */ |
@@ -442,134 +401,3 @@ badframe: | |||
442 | force_sigsegv(signr, current); | 401 | force_sigsegv(signr, current); |
443 | return 0; | 402 | return 0; |
444 | } | 403 | } |
445 | |||
446 | |||
447 | /* | ||
448 | * OK, we're invoking a handler | ||
449 | */ | ||
450 | static int handle_signal(unsigned long sig, struct k_sigaction *ka, | ||
451 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | ||
452 | { | ||
453 | int ret; | ||
454 | |||
455 | /* Set up Signal Frame */ | ||
456 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | ||
457 | |||
458 | if (ret) { | ||
459 | spin_lock_irq(¤t->sighand->siglock); | ||
460 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
461 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
462 | sigaddset(¤t->blocked,sig); | ||
463 | recalc_sigpending(); | ||
464 | spin_unlock_irq(¤t->sighand->siglock); | ||
465 | } | ||
466 | |||
467 | return ret; | ||
468 | } | ||
469 | |||
470 | static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | ||
471 | { | ||
472 | switch ((int)regs->result) { | ||
473 | case -ERESTART_RESTARTBLOCK: | ||
474 | case -ERESTARTNOHAND: | ||
475 | /* ERESTARTNOHAND means that the syscall should only be | ||
476 | * restarted if there was no handler for the signal, and since | ||
477 | * we only get here if there is a handler, we dont restart. | ||
478 | */ | ||
479 | regs->result = -EINTR; | ||
480 | regs->gpr[3] = EINTR; | ||
481 | regs->ccr |= 0x10000000; | ||
482 | break; | ||
483 | case -ERESTARTSYS: | ||
484 | /* ERESTARTSYS means to restart the syscall if there is no | ||
485 | * handler or the handler was registered with SA_RESTART | ||
486 | */ | ||
487 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
488 | regs->result = -EINTR; | ||
489 | regs->gpr[3] = EINTR; | ||
490 | regs->ccr |= 0x10000000; | ||
491 | break; | ||
492 | } | ||
493 | /* fallthrough */ | ||
494 | case -ERESTARTNOINTR: | ||
495 | /* ERESTARTNOINTR means that the syscall should be | ||
496 | * called again after the signal handler returns. | ||
497 | */ | ||
498 | regs->gpr[3] = regs->orig_gpr3; | ||
499 | regs->nip -= 4; | ||
500 | regs->result = 0; | ||
501 | break; | ||
502 | } | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
507 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
508 | * mistake. | ||
509 | */ | ||
510 | int do_signal(sigset_t *oldset, struct pt_regs *regs) | ||
511 | { | ||
512 | siginfo_t info; | ||
513 | int signr; | ||
514 | struct k_sigaction ka; | ||
515 | |||
516 | /* | ||
517 | * If the current thread is 32 bit - invoke the | ||
518 | * 32 bit signal handling code | ||
519 | */ | ||
520 | if (test_thread_flag(TIF_32BIT)) | ||
521 | return do_signal32(oldset, regs); | ||
522 | |||
523 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
524 | oldset = ¤t->saved_sigmask; | ||
525 | else if (!oldset) | ||
526 | oldset = ¤t->blocked; | ||
527 | |||
528 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
529 | if (signr > 0) { | ||
530 | int ret; | ||
531 | |||
532 | /* Whee! Actually deliver the signal. */ | ||
533 | if (TRAP(regs) == 0x0C00) | ||
534 | syscall_restart(regs, &ka); | ||
535 | |||
536 | /* | ||
537 | * Reenable the DABR before delivering the signal to | ||
538 | * user space. The DABR will have been cleared if it | ||
539 | * triggered inside the kernel. | ||
540 | */ | ||
541 | if (current->thread.dabr) | ||
542 | set_dabr(current->thread.dabr); | ||
543 | |||
544 | ret = handle_signal(signr, &ka, &info, oldset, regs); | ||
545 | |||
546 | /* If a signal was successfully delivered, the saved sigmask is in | ||
547 | its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ | ||
548 | if (ret && test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
549 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
550 | |||
551 | return ret; | ||
552 | } | ||
553 | |||
554 | if (TRAP(regs) == 0x0C00) { /* System Call! */ | ||
555 | if ((int)regs->result == -ERESTARTNOHAND || | ||
556 | (int)regs->result == -ERESTARTSYS || | ||
557 | (int)regs->result == -ERESTARTNOINTR) { | ||
558 | regs->gpr[3] = regs->orig_gpr3; | ||
559 | regs->nip -= 4; /* Back up & retry system call */ | ||
560 | regs->result = 0; | ||
561 | } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) { | ||
562 | regs->gpr[0] = __NR_restart_syscall; | ||
563 | regs->nip -= 4; | ||
564 | regs->result = 0; | ||
565 | } | ||
566 | } | ||
567 | /* No signal to deliver -- put the saved sigmask back */ | ||
568 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
569 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
570 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
571 | } | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | EXPORT_SYMBOL(do_signal); | ||
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index b42cbf1e2d7d..bd85b5fd08c8 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -773,6 +773,13 @@ asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4, | |||
773 | return sys_truncate(path, (high << 32) | low); | 773 | return sys_truncate(path, (high << 32) | low); |
774 | } | 774 | } |
775 | 775 | ||
776 | asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo, | ||
777 | u32 lenhi, u32 lenlo) | ||
778 | { | ||
779 | return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo, | ||
780 | ((loff_t)lenhi << 32) | lenlo); | ||
781 | } | ||
782 | |||
776 | asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, | 783 | asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, |
777 | unsigned long low) | 784 | unsigned long low) |
778 | { | 785 | { |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 68991c2d4a1b..55d29ed4b7a0 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -442,12 +442,14 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid) | |||
442 | return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, | 442 | return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, |
443 | kobject_name(&dev->kobj)); | 443 | kobject_name(&dev->kobj)); |
444 | } | 444 | } |
445 | EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); | ||
445 | 446 | ||
446 | void sysfs_remove_device_from_node(struct sys_device *dev, int nid) | 447 | void sysfs_remove_device_from_node(struct sys_device *dev, int nid) |
447 | { | 448 | { |
448 | struct node *node = &node_devices[nid]; | 449 | struct node *node = &node_devices[nid]; |
449 | sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); | 450 | sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); |
450 | } | 451 | } |
452 | EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); | ||
451 | 453 | ||
452 | #else | 454 | #else |
453 | static void register_nodes(void) | 455 | static void register_nodes(void) |
@@ -457,9 +459,6 @@ static void register_nodes(void) | |||
457 | 459 | ||
458 | #endif | 460 | #endif |
459 | 461 | ||
460 | EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); | ||
461 | EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); | ||
462 | |||
463 | /* Only valid if CPU is present. */ | 462 | /* Only valid if CPU is present. */ |
464 | static ssize_t show_physical_id(struct sys_device *dev, char *buf) | 463 | static ssize_t show_physical_id(struct sys_device *dev, char *buf) |
465 | { | 464 | { |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2c8564d54e4d..e5df167f7824 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -77,9 +77,8 @@ | |||
77 | /* keep track of when we need to update the rtc */ | 77 | /* keep track of when we need to update the rtc */ |
78 | time_t last_rtc_update; | 78 | time_t last_rtc_update; |
79 | #ifdef CONFIG_PPC_ISERIES | 79 | #ifdef CONFIG_PPC_ISERIES |
80 | unsigned long iSeries_recal_titan = 0; | 80 | static unsigned long __initdata iSeries_recal_titan; |
81 | unsigned long iSeries_recal_tb = 0; | 81 | static signed long __initdata iSeries_recal_tb; |
82 | static unsigned long first_settimeofday = 1; | ||
83 | #endif | 82 | #endif |
84 | 83 | ||
85 | /* The decrementer counts down by 128 every 128ns on a 601. */ | 84 | /* The decrementer counts down by 128 every 128ns on a 601. */ |
@@ -113,8 +112,9 @@ u64 ticklen_to_xs; /* 0.64 fraction */ | |||
113 | DEFINE_SPINLOCK(rtc_lock); | 112 | DEFINE_SPINLOCK(rtc_lock); |
114 | EXPORT_SYMBOL_GPL(rtc_lock); | 113 | EXPORT_SYMBOL_GPL(rtc_lock); |
115 | 114 | ||
116 | u64 tb_to_ns_scale; | 115 | static u64 tb_to_ns_scale __read_mostly; |
117 | unsigned tb_to_ns_shift; | 116 | static unsigned tb_to_ns_shift __read_mostly; |
117 | static unsigned long boot_tb __read_mostly; | ||
118 | 118 | ||
119 | struct gettimeofday_struct do_gtod; | 119 | struct gettimeofday_struct do_gtod; |
120 | 120 | ||
@@ -214,7 +214,6 @@ static void account_process_time(struct pt_regs *regs) | |||
214 | run_posix_cpu_timers(current); | 214 | run_posix_cpu_timers(current); |
215 | } | 215 | } |
216 | 216 | ||
217 | #ifdef CONFIG_PPC_SPLPAR | ||
218 | /* | 217 | /* |
219 | * Stuff for accounting stolen time. | 218 | * Stuff for accounting stolen time. |
220 | */ | 219 | */ |
@@ -222,19 +221,28 @@ struct cpu_purr_data { | |||
222 | int initialized; /* thread is running */ | 221 | int initialized; /* thread is running */ |
223 | u64 tb; /* last TB value read */ | 222 | u64 tb; /* last TB value read */ |
224 | u64 purr; /* last PURR value read */ | 223 | u64 purr; /* last PURR value read */ |
225 | spinlock_t lock; | ||
226 | }; | 224 | }; |
227 | 225 | ||
226 | /* | ||
227 | * Each entry in the cpu_purr_data array is manipulated only by its | ||
228 | * "owner" cpu -- usually in the timer interrupt but also occasionally | ||
229 | * in process context for cpu online. As long as cpus do not touch | ||
230 | * each others' cpu_purr_data, disabling local interrupts is | ||
231 | * sufficient to serialize accesses. | ||
232 | */ | ||
228 | static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); | 233 | static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); |
229 | 234 | ||
230 | static void snapshot_tb_and_purr(void *data) | 235 | static void snapshot_tb_and_purr(void *data) |
231 | { | 236 | { |
237 | unsigned long flags; | ||
232 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | 238 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); |
233 | 239 | ||
240 | local_irq_save(flags); | ||
234 | p->tb = mftb(); | 241 | p->tb = mftb(); |
235 | p->purr = mfspr(SPRN_PURR); | 242 | p->purr = mfspr(SPRN_PURR); |
236 | wmb(); | 243 | wmb(); |
237 | p->initialized = 1; | 244 | p->initialized = 1; |
245 | local_irq_restore(flags); | ||
238 | } | 246 | } |
239 | 247 | ||
240 | /* | 248 | /* |
@@ -242,15 +250,14 @@ static void snapshot_tb_and_purr(void *data) | |||
242 | */ | 250 | */ |
243 | void snapshot_timebases(void) | 251 | void snapshot_timebases(void) |
244 | { | 252 | { |
245 | int cpu; | ||
246 | |||
247 | if (!cpu_has_feature(CPU_FTR_PURR)) | 253 | if (!cpu_has_feature(CPU_FTR_PURR)) |
248 | return; | 254 | return; |
249 | for_each_possible_cpu(cpu) | ||
250 | spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); | ||
251 | on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); | 255 | on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); |
252 | } | 256 | } |
253 | 257 | ||
258 | /* | ||
259 | * Must be called with interrupts disabled. | ||
260 | */ | ||
254 | void calculate_steal_time(void) | 261 | void calculate_steal_time(void) |
255 | { | 262 | { |
256 | u64 tb, purr; | 263 | u64 tb, purr; |
@@ -262,7 +269,6 @@ void calculate_steal_time(void) | |||
262 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); | 269 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
263 | if (!pme->initialized) | 270 | if (!pme->initialized) |
264 | return; /* this can happen in early boot */ | 271 | return; /* this can happen in early boot */ |
265 | spin_lock(&pme->lock); | ||
266 | tb = mftb(); | 272 | tb = mftb(); |
267 | purr = mfspr(SPRN_PURR); | 273 | purr = mfspr(SPRN_PURR); |
268 | stolen = (tb - pme->tb) - (purr - pme->purr); | 274 | stolen = (tb - pme->tb) - (purr - pme->purr); |
@@ -270,9 +276,9 @@ void calculate_steal_time(void) | |||
270 | account_steal_time(current, stolen); | 276 | account_steal_time(current, stolen); |
271 | pme->tb = tb; | 277 | pme->tb = tb; |
272 | pme->purr = purr; | 278 | pme->purr = purr; |
273 | spin_unlock(&pme->lock); | ||
274 | } | 279 | } |
275 | 280 | ||
281 | #ifdef CONFIG_PPC_SPLPAR | ||
276 | /* | 282 | /* |
277 | * Must be called before the cpu is added to the online map when | 283 | * Must be called before the cpu is added to the online map when |
278 | * a cpu is being brought up at runtime. | 284 | * a cpu is being brought up at runtime. |
@@ -284,12 +290,12 @@ static void snapshot_purr(void) | |||
284 | 290 | ||
285 | if (!cpu_has_feature(CPU_FTR_PURR)) | 291 | if (!cpu_has_feature(CPU_FTR_PURR)) |
286 | return; | 292 | return; |
293 | local_irq_save(flags); | ||
287 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); | 294 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
288 | spin_lock_irqsave(&pme->lock, flags); | ||
289 | pme->tb = mftb(); | 295 | pme->tb = mftb(); |
290 | pme->purr = mfspr(SPRN_PURR); | 296 | pme->purr = mfspr(SPRN_PURR); |
291 | pme->initialized = 1; | 297 | pme->initialized = 1; |
292 | spin_unlock_irqrestore(&pme->lock, flags); | 298 | local_irq_restore(flags); |
293 | } | 299 | } |
294 | 300 | ||
295 | #endif /* CONFIG_PPC_SPLPAR */ | 301 | #endif /* CONFIG_PPC_SPLPAR */ |
@@ -550,10 +556,15 @@ EXPORT_SYMBOL(profile_pc); | |||
550 | * returned by the service processor for the timebase frequency. | 556 | * returned by the service processor for the timebase frequency. |
551 | */ | 557 | */ |
552 | 558 | ||
553 | static void iSeries_tb_recal(void) | 559 | static int __init iSeries_tb_recal(void) |
554 | { | 560 | { |
555 | struct div_result divres; | 561 | struct div_result divres; |
556 | unsigned long titan, tb; | 562 | unsigned long titan, tb; |
563 | |||
564 | /* Make sure we only run on iSeries */ | ||
565 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
566 | return -ENODEV; | ||
567 | |||
557 | tb = get_tb(); | 568 | tb = get_tb(); |
558 | titan = HvCallXm_loadTod(); | 569 | titan = HvCallXm_loadTod(); |
559 | if ( iSeries_recal_titan ) { | 570 | if ( iSeries_recal_titan ) { |
@@ -594,8 +605,18 @@ static void iSeries_tb_recal(void) | |||
594 | } | 605 | } |
595 | iSeries_recal_titan = titan; | 606 | iSeries_recal_titan = titan; |
596 | iSeries_recal_tb = tb; | 607 | iSeries_recal_tb = tb; |
608 | |||
609 | return 0; | ||
597 | } | 610 | } |
598 | #endif | 611 | late_initcall(iSeries_tb_recal); |
612 | |||
613 | /* Called from platform early init */ | ||
614 | void __init iSeries_time_init_early(void) | ||
615 | { | ||
616 | iSeries_recal_tb = get_tb(); | ||
617 | iSeries_recal_titan = HvCallXm_loadTod(); | ||
618 | } | ||
619 | #endif /* CONFIG_PPC_ISERIES */ | ||
599 | 620 | ||
600 | /* | 621 | /* |
601 | * For iSeries shared processors, we have to let the hypervisor | 622 | * For iSeries shared processors, we have to let the hypervisor |
@@ -735,7 +756,7 @@ unsigned long long sched_clock(void) | |||
735 | { | 756 | { |
736 | if (__USE_RTC()) | 757 | if (__USE_RTC()) |
737 | return get_rtc(); | 758 | return get_rtc(); |
738 | return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; | 759 | return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift; |
739 | } | 760 | } |
740 | 761 | ||
741 | int do_settimeofday(struct timespec *tv) | 762 | int do_settimeofday(struct timespec *tv) |
@@ -759,12 +780,6 @@ int do_settimeofday(struct timespec *tv) | |||
759 | * to the RTC again, or write to the RTC but then they don't call | 780 | * to the RTC again, or write to the RTC but then they don't call |
760 | * settimeofday to perform this operation. | 781 | * settimeofday to perform this operation. |
761 | */ | 782 | */ |
762 | #ifdef CONFIG_PPC_ISERIES | ||
763 | if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) { | ||
764 | iSeries_tb_recal(); | ||
765 | first_settimeofday = 0; | ||
766 | } | ||
767 | #endif | ||
768 | 783 | ||
769 | /* Make userspace gettimeofday spin until we're done. */ | 784 | /* Make userspace gettimeofday spin until we're done. */ |
770 | ++vdso_data->tb_update_count; | 785 | ++vdso_data->tb_update_count; |
@@ -960,6 +975,8 @@ void __init time_init(void) | |||
960 | } | 975 | } |
961 | tb_to_ns_scale = scale; | 976 | tb_to_ns_scale = scale; |
962 | tb_to_ns_shift = shift; | 977 | tb_to_ns_shift = shift; |
978 | /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ | ||
979 | boot_tb = get_tb(); | ||
963 | 980 | ||
964 | tm = get_boot_time(); | 981 | tm = get_boot_time(); |
965 | 982 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 3b8427e6283d..2bb1cb911783 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -149,6 +149,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
149 | 149 | ||
150 | bust_spinlocks(0); | 150 | bust_spinlocks(0); |
151 | die.lock_owner = -1; | 151 | die.lock_owner = -1; |
152 | add_taint(TAINT_DIE); | ||
152 | spin_unlock_irqrestore(&die.lock, flags); | 153 | spin_unlock_irqrestore(&die.lock, flags); |
153 | 154 | ||
154 | if (kexec_should_crash(current) || | 155 | if (kexec_should_crash(current) || |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 4245579edb4e..cef01e4e8989 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -670,7 +670,7 @@ static int __init vdso_init(void) | |||
670 | /* | 670 | /* |
671 | * Fill up the "systemcfg" stuff for backward compatiblity | 671 | * Fill up the "systemcfg" stuff for backward compatiblity |
672 | */ | 672 | */ |
673 | strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); | 673 | strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); |
674 | vdso_data->version.major = SYSTEMCFG_MAJOR; | 674 | vdso_data->version.major = SYSTEMCFG_MAJOR; |
675 | vdso_data->version.minor = SYSTEMCFG_MINOR; | 675 | vdso_data->version.minor = SYSTEMCFG_MINOR; |
676 | vdso_data->processor = mfspr(SPRN_PVR); | 676 | vdso_data->processor = mfspr(SPRN_PVR); |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 24ff7d983114..0c458556399f 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -7,6 +7,7 @@ | |||
7 | #define PROVIDE32(x) PROVIDE(x) | 7 | #define PROVIDE32(x) PROVIDE(x) |
8 | #endif | 8 | #endif |
9 | #include <asm-generic/vmlinux.lds.h> | 9 | #include <asm-generic/vmlinux.lds.h> |
10 | #include <asm/cache.h> | ||
10 | 11 | ||
11 | ENTRY(_stext) | 12 | ENTRY(_stext) |
12 | 13 | ||
@@ -62,6 +63,8 @@ SECTIONS | |||
62 | __stop___ex_table = .; | 63 | __stop___ex_table = .; |
63 | } | 64 | } |
64 | 65 | ||
66 | NOTES | ||
67 | |||
65 | BUG_TABLE | 68 | BUG_TABLE |
66 | 69 | ||
67 | /* | 70 | /* |
@@ -143,6 +146,7 @@ SECTIONS | |||
143 | .data.percpu : { | 146 | .data.percpu : { |
144 | __per_cpu_start = .; | 147 | __per_cpu_start = .; |
145 | *(.data.percpu) | 148 | *(.data.percpu) |
149 | *(.data.percpu.shared_aligned) | ||
146 | __per_cpu_end = .; | 150 | __per_cpu_end = .; |
147 | } | 151 | } |
148 | 152 | ||
@@ -213,6 +217,11 @@ SECTIONS | |||
213 | *(.data.cacheline_aligned) | 217 | *(.data.cacheline_aligned) |
214 | } | 218 | } |
215 | 219 | ||
220 | . = ALIGN(L1_CACHE_BYTES); | ||
221 | .data.read_mostly : { | ||
222 | *(.data.read_mostly) | ||
223 | } | ||
224 | |||
216 | . = ALIGN(PAGE_SIZE); | 225 | . = ALIGN(PAGE_SIZE); |
217 | __data_nosave : { | 226 | __data_nosave : { |
218 | __nosave_begin = .; | 227 | __nosave_begin = .; |
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index ca4dcb07a939..c3df50476539 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 12 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
13 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 13 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
14 | * Copyright (C) 1996 Paul Mackerras | 14 | * Copyright (C) 1996 Paul Mackerras |
15 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
16 | * | 15 | * |
17 | * Derived from "arch/i386/mm/init.c" | 16 | * Derived from "arch/i386/mm/init.c" |
18 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c index 838e09db71d9..7ff2609b64d1 100644 --- a/arch/powerpc/mm/4xx_mmu.c +++ b/arch/powerpc/mm/4xx_mmu.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 9 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
10 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 10 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
11 | * Copyright (C) 1996 Paul Mackerras | 11 | * Copyright (C) 1996 Paul Mackerras |
12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
13 | * | 12 | * |
14 | * Derived from "arch/i386/mm/init.c" | 13 | * Derived from "arch/i386/mm/init.c" |
15 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 4f839c6a9768..7e4d27ad3dee 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
@@ -11,8 +11,7 @@ obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o | |||
11 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 11 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ | 12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ |
13 | hash_utils_64.o hash_low_64.o tlb_64.o \ | 13 | hash_utils_64.o hash_low_64.o tlb_64.o \ |
14 | slb_low.o slb.o stab.o mmap.o imalloc.o \ | 14 | slb_low.o slb.o stab.o mmap.o $(hash-y) |
15 | $(hash-y) | ||
16 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o | 15 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o |
17 | obj-$(CONFIG_40x) += 4xx_mmu.o | 16 | obj-$(CONFIG_40x) += 4xx_mmu.o |
18 | obj-$(CONFIG_44x) += 44x_mmu.o | 17 | obj-$(CONFIG_44x) += 44x_mmu.o |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 115b25f50bf8..3767211b3d0f 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -145,7 +145,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
145 | struct mm_struct *mm = current->mm; | 145 | struct mm_struct *mm = current->mm; |
146 | siginfo_t info; | 146 | siginfo_t info; |
147 | int code = SEGV_MAPERR; | 147 | int code = SEGV_MAPERR; |
148 | int is_write = 0; | 148 | int is_write = 0, ret; |
149 | int trap = TRAP(regs); | 149 | int trap = TRAP(regs); |
150 | int is_exec = trap == 0x400; | 150 | int is_exec = trap == 0x400; |
151 | 151 | ||
@@ -330,22 +330,18 @@ good_area: | |||
330 | * the fault. | 330 | * the fault. |
331 | */ | 331 | */ |
332 | survive: | 332 | survive: |
333 | switch (handle_mm_fault(mm, vma, address, is_write)) { | 333 | ret = handle_mm_fault(mm, vma, address, is_write); |
334 | 334 | if (unlikely(ret & VM_FAULT_ERROR)) { | |
335 | case VM_FAULT_MINOR: | 335 | if (ret & VM_FAULT_OOM) |
336 | current->min_flt++; | 336 | goto out_of_memory; |
337 | break; | 337 | else if (ret & VM_FAULT_SIGBUS) |
338 | case VM_FAULT_MAJOR: | 338 | goto do_sigbus; |
339 | current->maj_flt++; | ||
340 | break; | ||
341 | case VM_FAULT_SIGBUS: | ||
342 | goto do_sigbus; | ||
343 | case VM_FAULT_OOM: | ||
344 | goto out_of_memory; | ||
345 | default: | ||
346 | BUG(); | 339 | BUG(); |
347 | } | 340 | } |
348 | 341 | if (ret & VM_FAULT_MAJOR) | |
342 | current->maj_flt++; | ||
343 | else | ||
344 | current->min_flt++; | ||
349 | up_read(&mm->mmap_sem); | 345 | up_read(&mm->mmap_sem); |
350 | return 0; | 346 | return 0; |
351 | 347 | ||
@@ -380,7 +376,7 @@ out_of_memory: | |||
380 | } | 376 | } |
381 | printk("VM: killing process %s\n", current->comm); | 377 | printk("VM: killing process %s\n", current->comm); |
382 | if (user_mode(regs)) | 378 | if (user_mode(regs)) |
383 | do_exit(SIGKILL); | 379 | do_group_exit(SIGKILL); |
384 | return SIGKILL; | 380 | return SIGKILL; |
385 | 381 | ||
386 | do_sigbus: | 382 | do_sigbus: |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index 123da03ab118..afab247d472f 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
@@ -14,7 +14,6 @@ | |||
14 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 14 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
15 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 15 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
16 | * Copyright (C) 1996 Paul Mackerras | 16 | * Copyright (C) 1996 Paul Mackerras |
17 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
18 | * | 17 | * |
19 | * Derived from "arch/i386/mm/init.c" | 18 | * Derived from "arch/i386/mm/init.c" |
20 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 19 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 4a20d890e2f4..6ba9b47e55af 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local) | |||
104 | spin_unlock(&native_tlbie_lock); | 104 | spin_unlock(&native_tlbie_lock); |
105 | } | 105 | } |
106 | 106 | ||
107 | static inline void native_lock_hpte(hpte_t *hptep) | 107 | static inline void native_lock_hpte(struct hash_pte *hptep) |
108 | { | 108 | { |
109 | unsigned long *word = &hptep->v; | 109 | unsigned long *word = &hptep->v; |
110 | 110 | ||
@@ -116,7 +116,7 @@ static inline void native_lock_hpte(hpte_t *hptep) | |||
116 | } | 116 | } |
117 | } | 117 | } |
118 | 118 | ||
119 | static inline void native_unlock_hpte(hpte_t *hptep) | 119 | static inline void native_unlock_hpte(struct hash_pte *hptep) |
120 | { | 120 | { |
121 | unsigned long *word = &hptep->v; | 121 | unsigned long *word = &hptep->v; |
122 | 122 | ||
@@ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
128 | unsigned long pa, unsigned long rflags, | 128 | unsigned long pa, unsigned long rflags, |
129 | unsigned long vflags, int psize) | 129 | unsigned long vflags, int psize) |
130 | { | 130 | { |
131 | hpte_t *hptep = htab_address + hpte_group; | 131 | struct hash_pte *hptep = htab_address + hpte_group; |
132 | unsigned long hpte_v, hpte_r; | 132 | unsigned long hpte_v, hpte_r; |
133 | int i; | 133 | int i; |
134 | 134 | ||
@@ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
163 | 163 | ||
164 | hptep->r = hpte_r; | 164 | hptep->r = hpte_r; |
165 | /* Guarantee the second dword is visible before the valid bit */ | 165 | /* Guarantee the second dword is visible before the valid bit */ |
166 | __asm__ __volatile__ ("eieio" : : : "memory"); | 166 | eieio(); |
167 | /* | 167 | /* |
168 | * Now set the first dword including the valid bit | 168 | * Now set the first dword including the valid bit |
169 | * NOTE: this also unlocks the hpte | 169 | * NOTE: this also unlocks the hpte |
@@ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
177 | 177 | ||
178 | static long native_hpte_remove(unsigned long hpte_group) | 178 | static long native_hpte_remove(unsigned long hpte_group) |
179 | { | 179 | { |
180 | hpte_t *hptep; | 180 | struct hash_pte *hptep; |
181 | int i; | 181 | int i; |
182 | int slot_offset; | 182 | int slot_offset; |
183 | unsigned long hpte_v; | 183 | unsigned long hpte_v; |
@@ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group) | |||
217 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | 217 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, |
218 | unsigned long va, int psize, int local) | 218 | unsigned long va, int psize, int local) |
219 | { | 219 | { |
220 | hpte_t *hptep = htab_address + slot; | 220 | struct hash_pte *hptep = htab_address + slot; |
221 | unsigned long hpte_v, want_v; | 221 | unsigned long hpte_v, want_v; |
222 | int ret = 0; | 222 | int ret = 0; |
223 | 223 | ||
@@ -233,15 +233,14 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
233 | /* Even if we miss, we need to invalidate the TLB */ | 233 | /* Even if we miss, we need to invalidate the TLB */ |
234 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { | 234 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { |
235 | DBG_LOW(" -> miss\n"); | 235 | DBG_LOW(" -> miss\n"); |
236 | native_unlock_hpte(hptep); | ||
237 | ret = -1; | 236 | ret = -1; |
238 | } else { | 237 | } else { |
239 | DBG_LOW(" -> hit\n"); | 238 | DBG_LOW(" -> hit\n"); |
240 | /* Update the HPTE */ | 239 | /* Update the HPTE */ |
241 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | | 240 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | |
242 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); | 241 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); |
243 | native_unlock_hpte(hptep); | ||
244 | } | 242 | } |
243 | native_unlock_hpte(hptep); | ||
245 | 244 | ||
246 | /* Ensure it is out of the tlb too. */ | 245 | /* Ensure it is out of the tlb too. */ |
247 | tlbie(va, psize, local); | 246 | tlbie(va, psize, local); |
@@ -251,7 +250,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
251 | 250 | ||
252 | static long native_hpte_find(unsigned long va, int psize) | 251 | static long native_hpte_find(unsigned long va, int psize) |
253 | { | 252 | { |
254 | hpte_t *hptep; | 253 | struct hash_pte *hptep; |
255 | unsigned long hash; | 254 | unsigned long hash; |
256 | unsigned long i, j; | 255 | unsigned long i, j; |
257 | long slot; | 256 | long slot; |
@@ -294,7 +293,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
294 | { | 293 | { |
295 | unsigned long vsid, va; | 294 | unsigned long vsid, va; |
296 | long slot; | 295 | long slot; |
297 | hpte_t *hptep; | 296 | struct hash_pte *hptep; |
298 | 297 | ||
299 | vsid = get_kernel_vsid(ea); | 298 | vsid = get_kernel_vsid(ea); |
300 | va = (vsid << 28) | (ea & 0x0fffffff); | 299 | va = (vsid << 28) | (ea & 0x0fffffff); |
@@ -315,7 +314,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
315 | static void native_hpte_invalidate(unsigned long slot, unsigned long va, | 314 | static void native_hpte_invalidate(unsigned long slot, unsigned long va, |
316 | int psize, int local) | 315 | int psize, int local) |
317 | { | 316 | { |
318 | hpte_t *hptep = htab_address + slot; | 317 | struct hash_pte *hptep = htab_address + slot; |
319 | unsigned long hpte_v; | 318 | unsigned long hpte_v; |
320 | unsigned long want_v; | 319 | unsigned long want_v; |
321 | unsigned long flags; | 320 | unsigned long flags; |
@@ -345,7 +344,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, | |||
345 | #define LP_BITS 8 | 344 | #define LP_BITS 8 |
346 | #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) | 345 | #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) |
347 | 346 | ||
348 | static void hpte_decode(hpte_t *hpte, unsigned long slot, | 347 | static void hpte_decode(struct hash_pte *hpte, unsigned long slot, |
349 | int *psize, unsigned long *va) | 348 | int *psize, unsigned long *va) |
350 | { | 349 | { |
351 | unsigned long hpte_r = hpte->r; | 350 | unsigned long hpte_r = hpte->r; |
@@ -415,7 +414,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot, | |||
415 | static void native_hpte_clear(void) | 414 | static void native_hpte_clear(void) |
416 | { | 415 | { |
417 | unsigned long slot, slots, flags; | 416 | unsigned long slot, slots, flags; |
418 | hpte_t *hptep = htab_address; | 417 | struct hash_pte *hptep = htab_address; |
419 | unsigned long hpte_v, va; | 418 | unsigned long hpte_v, va; |
420 | unsigned long pteg_count; | 419 | unsigned long pteg_count; |
421 | int psize; | 420 | int psize; |
@@ -462,7 +461,7 @@ static void native_hpte_clear(void) | |||
462 | static void native_flush_hash_range(unsigned long number, int local) | 461 | static void native_flush_hash_range(unsigned long number, int local) |
463 | { | 462 | { |
464 | unsigned long va, hash, index, hidx, shift, slot; | 463 | unsigned long va, hash, index, hidx, shift, slot; |
465 | hpte_t *hptep; | 464 | struct hash_pte *hptep; |
466 | unsigned long hpte_v; | 465 | unsigned long hpte_v; |
467 | unsigned long want_v; | 466 | unsigned long want_v; |
468 | unsigned long flags; | 467 | unsigned long flags; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 4f2f4534a9d8..2ce9491b48d4 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -87,7 +87,7 @@ extern unsigned long dart_tablebase; | |||
87 | static unsigned long _SDR1; | 87 | static unsigned long _SDR1; |
88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | 88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; |
89 | 89 | ||
90 | hpte_t *htab_address; | 90 | struct hash_pte *htab_address; |
91 | unsigned long htab_size_bytes; | 91 | unsigned long htab_size_bytes; |
92 | unsigned long htab_hash_mask; | 92 | unsigned long htab_hash_mask; |
93 | int mmu_linear_psize = MMU_PAGE_4K; | 93 | int mmu_linear_psize = MMU_PAGE_4K; |
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c deleted file mode 100644 index c831815c31f0..000000000000 --- a/arch/powerpc/mm/imalloc.c +++ /dev/null | |||
@@ -1,313 +0,0 @@ | |||
1 | /* | ||
2 | * c 2001 PPC 64 Team, IBM Corp | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/slab.h> | ||
11 | #include <linux/vmalloc.h> | ||
12 | |||
13 | #include <asm/uaccess.h> | ||
14 | #include <asm/pgalloc.h> | ||
15 | #include <asm/pgtable.h> | ||
16 | #include <linux/mutex.h> | ||
17 | #include <asm/cacheflush.h> | ||
18 | |||
19 | #include "mmu_decl.h" | ||
20 | |||
21 | static DEFINE_MUTEX(imlist_mutex); | ||
22 | struct vm_struct * imlist = NULL; | ||
23 | |||
24 | static int get_free_im_addr(unsigned long size, unsigned long *im_addr) | ||
25 | { | ||
26 | unsigned long addr; | ||
27 | struct vm_struct **p, *tmp; | ||
28 | |||
29 | addr = ioremap_bot; | ||
30 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||
31 | if (size + addr < (unsigned long) tmp->addr) | ||
32 | break; | ||
33 | if ((unsigned long)tmp->addr >= ioremap_bot) | ||
34 | addr = tmp->size + (unsigned long) tmp->addr; | ||
35 | if (addr >= IMALLOC_END-size) | ||
36 | return 1; | ||
37 | } | ||
38 | *im_addr = addr; | ||
39 | |||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | /* Return whether the region described by v_addr and size is a subset | ||
44 | * of the region described by parent | ||
45 | */ | ||
46 | static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, | ||
47 | struct vm_struct *parent) | ||
48 | { | ||
49 | return (int) (v_addr >= (unsigned long) parent->addr && | ||
50 | v_addr < (unsigned long) parent->addr + parent->size && | ||
51 | size < parent->size); | ||
52 | } | ||
53 | |||
54 | /* Return whether the region described by v_addr and size is a superset | ||
55 | * of the region described by child | ||
56 | */ | ||
57 | static int im_region_is_superset(unsigned long v_addr, unsigned long size, | ||
58 | struct vm_struct *child) | ||
59 | { | ||
60 | struct vm_struct parent; | ||
61 | |||
62 | parent.addr = (void *) v_addr; | ||
63 | parent.size = size; | ||
64 | |||
65 | return im_region_is_subset((unsigned long) child->addr, child->size, | ||
66 | &parent); | ||
67 | } | ||
68 | |||
69 | /* Return whether the region described by v_addr and size overlaps | ||
70 | * the region described by vm. Overlapping regions meet the | ||
71 | * following conditions: | ||
72 | * 1) The regions share some part of the address space | ||
73 | * 2) The regions aren't identical | ||
74 | * 3) Neither region is a subset of the other | ||
75 | */ | ||
76 | static int im_region_overlaps(unsigned long v_addr, unsigned long size, | ||
77 | struct vm_struct *vm) | ||
78 | { | ||
79 | if (im_region_is_superset(v_addr, size, vm)) | ||
80 | return 0; | ||
81 | |||
82 | return (v_addr + size > (unsigned long) vm->addr + vm->size && | ||
83 | v_addr < (unsigned long) vm->addr + vm->size) || | ||
84 | (v_addr < (unsigned long) vm->addr && | ||
85 | v_addr + size > (unsigned long) vm->addr); | ||
86 | } | ||
87 | |||
88 | /* Determine imalloc status of region described by v_addr and size. | ||
89 | * Can return one of the following: | ||
90 | * IM_REGION_UNUSED - Entire region is unallocated in imalloc space. | ||
91 | * IM_REGION_SUBSET - Region is a subset of a region that is already | ||
92 | * allocated in imalloc space. | ||
93 | * vm will be assigned to a ptr to the parent region. | ||
94 | * IM_REGION_EXISTS - Exact region already allocated in imalloc space. | ||
95 | * vm will be assigned to a ptr to the existing imlist | ||
96 | * member. | ||
97 | * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space. | ||
98 | * IM_REGION_SUPERSET - Region is a superset of a region that is already | ||
99 | * allocated in imalloc space. | ||
100 | */ | ||
101 | static int im_region_status(unsigned long v_addr, unsigned long size, | ||
102 | struct vm_struct **vm) | ||
103 | { | ||
104 | struct vm_struct *tmp; | ||
105 | |||
106 | for (tmp = imlist; tmp; tmp = tmp->next) | ||
107 | if (v_addr < (unsigned long) tmp->addr + tmp->size) | ||
108 | break; | ||
109 | |||
110 | *vm = NULL; | ||
111 | if (tmp) { | ||
112 | if (im_region_overlaps(v_addr, size, tmp)) | ||
113 | return IM_REGION_OVERLAP; | ||
114 | |||
115 | *vm = tmp; | ||
116 | if (im_region_is_subset(v_addr, size, tmp)) { | ||
117 | /* Return with tmp pointing to superset */ | ||
118 | return IM_REGION_SUBSET; | ||
119 | } | ||
120 | if (im_region_is_superset(v_addr, size, tmp)) { | ||
121 | /* Return with tmp pointing to first subset */ | ||
122 | return IM_REGION_SUPERSET; | ||
123 | } | ||
124 | else if (v_addr == (unsigned long) tmp->addr && | ||
125 | size == tmp->size) { | ||
126 | /* Return with tmp pointing to exact region */ | ||
127 | return IM_REGION_EXISTS; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return IM_REGION_UNUSED; | ||
132 | } | ||
133 | |||
134 | static struct vm_struct * split_im_region(unsigned long v_addr, | ||
135 | unsigned long size, struct vm_struct *parent) | ||
136 | { | ||
137 | struct vm_struct *vm1 = NULL; | ||
138 | struct vm_struct *vm2 = NULL; | ||
139 | struct vm_struct *new_vm = NULL; | ||
140 | |||
141 | vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL); | ||
142 | if (vm1 == NULL) { | ||
143 | printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||
144 | return NULL; | ||
145 | } | ||
146 | |||
147 | if (v_addr == (unsigned long) parent->addr) { | ||
148 | /* Use existing parent vm_struct to represent child, allocate | ||
149 | * new one for the remainder of parent range | ||
150 | */ | ||
151 | vm1->size = parent->size - size; | ||
152 | vm1->addr = (void *) (v_addr + size); | ||
153 | vm1->next = parent->next; | ||
154 | |||
155 | parent->size = size; | ||
156 | parent->next = vm1; | ||
157 | new_vm = parent; | ||
158 | } else if (v_addr + size == (unsigned long) parent->addr + | ||
159 | parent->size) { | ||
160 | /* Allocate new vm_struct to represent child, use existing | ||
161 | * parent one for remainder of parent range | ||
162 | */ | ||
163 | vm1->size = size; | ||
164 | vm1->addr = (void *) v_addr; | ||
165 | vm1->next = parent->next; | ||
166 | new_vm = vm1; | ||
167 | |||
168 | parent->size -= size; | ||
169 | parent->next = vm1; | ||
170 | } else { | ||
171 | /* Allocate two new vm_structs for the new child and | ||
172 | * uppermost remainder, and use existing parent one for the | ||
173 | * lower remainder of parent range | ||
174 | */ | ||
175 | vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL); | ||
176 | if (vm2 == NULL) { | ||
177 | printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||
178 | kfree(vm1); | ||
179 | return NULL; | ||
180 | } | ||
181 | |||
182 | vm1->size = size; | ||
183 | vm1->addr = (void *) v_addr; | ||
184 | vm1->next = vm2; | ||
185 | new_vm = vm1; | ||
186 | |||
187 | vm2->size = ((unsigned long) parent->addr + parent->size) - | ||
188 | (v_addr + size); | ||
189 | vm2->addr = (void *) v_addr + size; | ||
190 | vm2->next = parent->next; | ||
191 | |||
192 | parent->size = v_addr - (unsigned long) parent->addr; | ||
193 | parent->next = vm1; | ||
194 | } | ||
195 | |||
196 | return new_vm; | ||
197 | } | ||
198 | |||
199 | static struct vm_struct * __add_new_im_area(unsigned long req_addr, | ||
200 | unsigned long size) | ||
201 | { | ||
202 | struct vm_struct **p, *tmp, *area; | ||
203 | |||
204 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||
205 | if (req_addr + size <= (unsigned long)tmp->addr) | ||
206 | break; | ||
207 | } | ||
208 | |||
209 | area = kmalloc(sizeof(*area), GFP_KERNEL); | ||
210 | if (!area) | ||
211 | return NULL; | ||
212 | area->flags = 0; | ||
213 | area->addr = (void *)req_addr; | ||
214 | area->size = size; | ||
215 | area->next = *p; | ||
216 | *p = area; | ||
217 | |||
218 | return area; | ||
219 | } | ||
220 | |||
221 | static struct vm_struct * __im_get_area(unsigned long req_addr, | ||
222 | unsigned long size, | ||
223 | int criteria) | ||
224 | { | ||
225 | struct vm_struct *tmp; | ||
226 | int status; | ||
227 | |||
228 | status = im_region_status(req_addr, size, &tmp); | ||
229 | if ((criteria & status) == 0) { | ||
230 | return NULL; | ||
231 | } | ||
232 | |||
233 | switch (status) { | ||
234 | case IM_REGION_UNUSED: | ||
235 | tmp = __add_new_im_area(req_addr, size); | ||
236 | break; | ||
237 | case IM_REGION_SUBSET: | ||
238 | tmp = split_im_region(req_addr, size, tmp); | ||
239 | break; | ||
240 | case IM_REGION_EXISTS: | ||
241 | /* Return requested region */ | ||
242 | break; | ||
243 | case IM_REGION_SUPERSET: | ||
244 | /* Return first existing subset of requested region */ | ||
245 | break; | ||
246 | default: | ||
247 | printk(KERN_ERR "%s() unexpected imalloc region status\n", | ||
248 | __FUNCTION__); | ||
249 | tmp = NULL; | ||
250 | } | ||
251 | |||
252 | return tmp; | ||
253 | } | ||
254 | |||
255 | struct vm_struct * im_get_free_area(unsigned long size) | ||
256 | { | ||
257 | struct vm_struct *area; | ||
258 | unsigned long addr; | ||
259 | |||
260 | mutex_lock(&imlist_mutex); | ||
261 | if (get_free_im_addr(size, &addr)) { | ||
262 | printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", | ||
263 | __FUNCTION__, size); | ||
264 | area = NULL; | ||
265 | goto next_im_done; | ||
266 | } | ||
267 | |||
268 | area = __im_get_area(addr, size, IM_REGION_UNUSED); | ||
269 | if (area == NULL) { | ||
270 | printk(KERN_ERR | ||
271 | "%s() cannot obtain area for addr 0x%lx size 0x%lx\n", | ||
272 | __FUNCTION__, addr, size); | ||
273 | } | ||
274 | next_im_done: | ||
275 | mutex_unlock(&imlist_mutex); | ||
276 | return area; | ||
277 | } | ||
278 | |||
279 | struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
280 | int criteria) | ||
281 | { | ||
282 | struct vm_struct *area; | ||
283 | |||
284 | mutex_lock(&imlist_mutex); | ||
285 | area = __im_get_area(v_addr, size, criteria); | ||
286 | mutex_unlock(&imlist_mutex); | ||
287 | return area; | ||
288 | } | ||
289 | |||
290 | void im_free(void * addr) | ||
291 | { | ||
292 | struct vm_struct **p, *tmp; | ||
293 | |||
294 | if (!addr) | ||
295 | return; | ||
296 | if ((unsigned long) addr & ~PAGE_MASK) { | ||
297 | printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); | ||
298 | return; | ||
299 | } | ||
300 | mutex_lock(&imlist_mutex); | ||
301 | for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { | ||
302 | if (tmp->addr == addr) { | ||
303 | *p = tmp->next; | ||
304 | unmap_vm_area(tmp); | ||
305 | kfree(tmp); | ||
306 | mutex_unlock(&imlist_mutex); | ||
307 | return; | ||
308 | } | ||
309 | } | ||
310 | mutex_unlock(&imlist_mutex); | ||
311 | printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, | ||
312 | addr); | ||
313 | } | ||
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 5fce6ccecb8d..e1f5ded851f6 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -5,7 +5,6 @@ | |||
5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
7 | * Copyright (C) 1996 Paul Mackerras | 7 | * Copyright (C) 1996 Paul Mackerras |
8 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
9 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) | 8 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) |
10 | * | 9 | * |
11 | * Derived from "arch/i386/mm/init.c" | 10 | * Derived from "arch/i386/mm/init.c" |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 7312a265545f..1d6edf724c85 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -5,7 +5,6 @@ | |||
5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
7 | * Copyright (C) 1996 Paul Mackerras | 7 | * Copyright (C) 1996 Paul Mackerras |
8 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
9 | * | 8 | * |
10 | * Derived from "arch/i386/mm/init.c" | 9 | * Derived from "arch/i386/mm/init.c" |
11 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 10 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 0266a94d83b6..f0e7eedb1ba3 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -5,7 +5,6 @@ | |||
5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
7 | * Copyright (C) 1996 Paul Mackerras | 7 | * Copyright (C) 1996 Paul Mackerras |
8 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
9 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) | 8 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) |
10 | * | 9 | * |
11 | * Derived from "arch/i386/mm/init.c" | 10 | * Derived from "arch/i386/mm/init.c" |
@@ -129,8 +128,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) | |||
129 | zone = pgdata->node_zones; | 128 | zone = pgdata->node_zones; |
130 | 129 | ||
131 | return __add_pages(zone, start_pfn, nr_pages); | 130 | return __add_pages(zone, start_pfn, nr_pages); |
132 | |||
133 | return 0; | ||
134 | } | 131 | } |
135 | 132 | ||
136 | /* | 133 | /* |
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c index 792086b01000..cc32ba41d900 100644 --- a/arch/powerpc/mm/mmu_context_32.c +++ b/arch/powerpc/mm/mmu_context_32.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
15 | * | 14 | * |
16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 2558c34eedaa..c94a64fd3c01 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
@@ -8,7 +8,6 @@ | |||
8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
12 | * | 11 | * |
13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
@@ -40,8 +39,8 @@ extern int __map_without_bats; | |||
40 | extern unsigned long ioremap_base; | 39 | extern unsigned long ioremap_base; |
41 | extern unsigned int rtas_data, rtas_size; | 40 | extern unsigned int rtas_data, rtas_size; |
42 | 41 | ||
43 | struct _PTE; | 42 | struct hash_pte; |
44 | extern struct _PTE *Hash, *Hash_end; | 43 | extern struct hash_pte *Hash, *Hash_end; |
45 | extern unsigned long Hash_size, Hash_mask; | 44 | extern unsigned long Hash_size, Hash_mask; |
46 | 45 | ||
47 | extern unsigned int num_tlbcam_entries; | 46 | extern unsigned int num_tlbcam_entries; |
@@ -90,16 +89,4 @@ static inline void flush_HPTE(unsigned context, unsigned long va, | |||
90 | else | 89 | else |
91 | _tlbie(va); | 90 | _tlbie(va); |
92 | } | 91 | } |
93 | #else /* CONFIG_PPC64 */ | ||
94 | /* imalloc region types */ | ||
95 | #define IM_REGION_UNUSED 0x1 | ||
96 | #define IM_REGION_SUBSET 0x2 | ||
97 | #define IM_REGION_EXISTS 0x4 | ||
98 | #define IM_REGION_OVERLAP 0x8 | ||
99 | #define IM_REGION_SUPERSET 0x10 | ||
100 | |||
101 | extern struct vm_struct * im_get_free_area(unsigned long size); | ||
102 | extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
103 | int region_type); | ||
104 | extern void im_free(void *addr); | ||
105 | #endif | 92 | #endif |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f6ae1a57d652..64488723162a 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -8,7 +8,6 @@ | |||
8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
12 | * | 11 | * |
13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
@@ -37,7 +36,6 @@ | |||
37 | unsigned long ioremap_base; | 36 | unsigned long ioremap_base; |
38 | unsigned long ioremap_bot; | 37 | unsigned long ioremap_bot; |
39 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ | 38 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ |
40 | int io_bat_index; | ||
41 | 39 | ||
42 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) | 40 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) |
43 | #define HAVE_BATS 1 | 41 | #define HAVE_BATS 1 |
@@ -300,51 +298,6 @@ void __init mapin_ram(void) | |||
300 | } | 298 | } |
301 | } | 299 | } |
302 | 300 | ||
303 | /* is x a power of 4? */ | ||
304 | #define is_power_of_4(x) is_power_of_2(x) && (ffs(x) & 1) | ||
305 | |||
306 | /* | ||
307 | * Set up a mapping for a block of I/O. | ||
308 | * virt, phys, size must all be page-aligned. | ||
309 | * This should only be called before ioremap is called. | ||
310 | */ | ||
311 | void __init io_block_mapping(unsigned long virt, phys_addr_t phys, | ||
312 | unsigned int size, int flags) | ||
313 | { | ||
314 | int i; | ||
315 | |||
316 | if (virt > KERNELBASE && virt < ioremap_bot) | ||
317 | ioremap_bot = ioremap_base = virt; | ||
318 | |||
319 | #ifdef HAVE_BATS | ||
320 | /* | ||
321 | * Use a BAT for this if possible... | ||
322 | */ | ||
323 | if (io_bat_index < 2 && is_power_of_2(size) | ||
324 | && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { | ||
325 | setbat(io_bat_index, virt, phys, size, flags); | ||
326 | ++io_bat_index; | ||
327 | return; | ||
328 | } | ||
329 | #endif /* HAVE_BATS */ | ||
330 | |||
331 | #ifdef HAVE_TLBCAM | ||
332 | /* | ||
333 | * Use a CAM for this if possible... | ||
334 | */ | ||
335 | if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size) | ||
336 | && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { | ||
337 | settlbcam(tlbcam_index, virt, phys, size, flags, 0); | ||
338 | ++tlbcam_index; | ||
339 | return; | ||
340 | } | ||
341 | #endif /* HAVE_TLBCAM */ | ||
342 | |||
343 | /* No BATs available, put it in the page tables. */ | ||
344 | for (i = 0; i < size; i += PAGE_SIZE) | ||
345 | map_page(virt + i, phys + i, flags); | ||
346 | } | ||
347 | |||
348 | /* Scan the real Linux page tables and return a PTE pointer for | 301 | /* Scan the real Linux page tables and return a PTE pointer for |
349 | * a virtual address in a context. | 302 | * a virtual address in a context. |
350 | * Returns true (1) if PTE was found, zero otherwise. The pointer to | 303 | * Returns true (1) if PTE was found, zero otherwise. The pointer to |
@@ -379,82 +332,6 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) | |||
379 | return(retval); | 332 | return(retval); |
380 | } | 333 | } |
381 | 334 | ||
382 | /* Find physical address for this virtual address. Normally used by | ||
383 | * I/O functions, but anyone can call it. | ||
384 | */ | ||
385 | unsigned long iopa(unsigned long addr) | ||
386 | { | ||
387 | unsigned long pa; | ||
388 | |||
389 | /* I don't know why this won't work on PMacs or CHRP. It | ||
390 | * appears there is some bug, or there is some implicit | ||
391 | * mapping done not properly represented by BATs or in page | ||
392 | * tables.......I am actively working on resolving this, but | ||
393 | * can't hold up other stuff. -- Dan | ||
394 | */ | ||
395 | pte_t *pte; | ||
396 | struct mm_struct *mm; | ||
397 | |||
398 | /* Check the BATs */ | ||
399 | pa = v_mapped_by_bats(addr); | ||
400 | if (pa) | ||
401 | return pa; | ||
402 | |||
403 | /* Allow mapping of user addresses (within the thread) | ||
404 | * for DMA if necessary. | ||
405 | */ | ||
406 | if (addr < TASK_SIZE) | ||
407 | mm = current->mm; | ||
408 | else | ||
409 | mm = &init_mm; | ||
410 | |||
411 | pa = 0; | ||
412 | if (get_pteptr(mm, addr, &pte, NULL)) { | ||
413 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); | ||
414 | pte_unmap(pte); | ||
415 | } | ||
416 | |||
417 | return(pa); | ||
418 | } | ||
419 | |||
420 | /* This is will find the virtual address for a physical one.... | ||
421 | * Swiped from APUS, could be dangerous :-). | ||
422 | * This is only a placeholder until I really find a way to make this | ||
423 | * work. -- Dan | ||
424 | */ | ||
425 | unsigned long | ||
426 | mm_ptov (unsigned long paddr) | ||
427 | { | ||
428 | unsigned long ret; | ||
429 | #if 0 | ||
430 | if (paddr < 16*1024*1024) | ||
431 | ret = ZTWO_VADDR(paddr); | ||
432 | else { | ||
433 | int i; | ||
434 | |||
435 | for (i = 0; i < kmap_chunk_count;){ | ||
436 | unsigned long phys = kmap_chunks[i++]; | ||
437 | unsigned long size = kmap_chunks[i++]; | ||
438 | unsigned long virt = kmap_chunks[i++]; | ||
439 | if (paddr >= phys | ||
440 | && paddr < (phys + size)){ | ||
441 | ret = virt + paddr - phys; | ||
442 | goto exit; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | ret = (unsigned long) __va(paddr); | ||
447 | } | ||
448 | exit: | ||
449 | #ifdef DEBUGPV | ||
450 | printk ("PTOV(%lx)=%lx\n", paddr, ret); | ||
451 | #endif | ||
452 | #else | ||
453 | ret = (unsigned long)paddr + KERNELBASE; | ||
454 | #endif | ||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | #ifdef CONFIG_DEBUG_PAGEALLOC | 335 | #ifdef CONFIG_DEBUG_PAGEALLOC |
459 | 336 | ||
460 | static int __change_page_attr(struct page *page, pgprot_t prot) | 337 | static int __change_page_attr(struct page *page, pgprot_t prot) |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index ad6e135bf212..3dfd10db931a 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) | 7 | * Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) |
8 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 8 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
9 | * Copyright (C) 1996 Paul Mackerras | 9 | * Copyright (C) 1996 Paul Mackerras |
10 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
11 | * | 10 | * |
12 | * Derived from "arch/i386/mm/init.c" | 11 | * Derived from "arch/i386/mm/init.c" |
13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 12 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
@@ -34,41 +33,27 @@ | |||
34 | #include <linux/stddef.h> | 33 | #include <linux/stddef.h> |
35 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
37 | #include <linux/delay.h> | ||
38 | #include <linux/bootmem.h> | ||
39 | #include <linux/highmem.h> | ||
40 | #include <linux/idr.h> | ||
41 | #include <linux/nodemask.h> | ||
42 | #include <linux/module.h> | ||
43 | 36 | ||
44 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
45 | #include <asm/page.h> | 38 | #include <asm/page.h> |
46 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
47 | #include <asm/lmb.h> | ||
48 | #include <asm/rtas.h> | ||
49 | #include <asm/io.h> | 40 | #include <asm/io.h> |
50 | #include <asm/mmu_context.h> | 41 | #include <asm/mmu_context.h> |
51 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
52 | #include <asm/mmu.h> | 43 | #include <asm/mmu.h> |
53 | #include <asm/uaccess.h> | ||
54 | #include <asm/smp.h> | 44 | #include <asm/smp.h> |
55 | #include <asm/machdep.h> | 45 | #include <asm/machdep.h> |
56 | #include <asm/tlb.h> | 46 | #include <asm/tlb.h> |
57 | #include <asm/eeh.h> | ||
58 | #include <asm/processor.h> | 47 | #include <asm/processor.h> |
59 | #include <asm/mmzone.h> | ||
60 | #include <asm/cputable.h> | 48 | #include <asm/cputable.h> |
61 | #include <asm/sections.h> | 49 | #include <asm/sections.h> |
62 | #include <asm/system.h> | 50 | #include <asm/system.h> |
63 | #include <asm/iommu.h> | ||
64 | #include <asm/abs_addr.h> | 51 | #include <asm/abs_addr.h> |
65 | #include <asm/vdso.h> | ||
66 | #include <asm/firmware.h> | 52 | #include <asm/firmware.h> |
67 | 53 | ||
68 | #include "mmu_decl.h" | 54 | #include "mmu_decl.h" |
69 | 55 | ||
70 | unsigned long ioremap_bot = IMALLOC_BASE; | 56 | unsigned long ioremap_bot = IOREMAP_BASE; |
71 | static unsigned long phbs_io_bot = PHBS_IO_BASE; | ||
72 | 57 | ||
73 | /* | 58 | /* |
74 | * map_io_page currently only called by __ioremap | 59 | * map_io_page currently only called by __ioremap |
@@ -102,8 +87,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
102 | * entry in the hardware page table. | 87 | * entry in the hardware page table. |
103 | * | 88 | * |
104 | */ | 89 | */ |
105 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | 90 | if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE, |
106 | mmu_io_psize)) { | 91 | pa, flags, mmu_io_psize)) { |
107 | printk(KERN_ERR "Failed to do bolted mapping IO " | 92 | printk(KERN_ERR "Failed to do bolted mapping IO " |
108 | "memory at %016lx !\n", pa); | 93 | "memory at %016lx !\n", pa); |
109 | return -ENOMEM; | 94 | return -ENOMEM; |
@@ -113,8 +98,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
113 | } | 98 | } |
114 | 99 | ||
115 | 100 | ||
116 | static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | 101 | /** |
117 | unsigned long ea, unsigned long size, | 102 | * __ioremap_at - Low level function to establish the page tables |
103 | * for an IO mapping | ||
104 | */ | ||
105 | void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, | ||
118 | unsigned long flags) | 106 | unsigned long flags) |
119 | { | 107 | { |
120 | unsigned long i; | 108 | unsigned long i; |
@@ -122,17 +110,35 @@ static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | |||
122 | if ((flags & _PAGE_PRESENT) == 0) | 110 | if ((flags & _PAGE_PRESENT) == 0) |
123 | flags |= pgprot_val(PAGE_KERNEL); | 111 | flags |= pgprot_val(PAGE_KERNEL); |
124 | 112 | ||
113 | WARN_ON(pa & ~PAGE_MASK); | ||
114 | WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||
115 | WARN_ON(size & ~PAGE_MASK); | ||
116 | |||
125 | for (i = 0; i < size; i += PAGE_SIZE) | 117 | for (i = 0; i < size; i += PAGE_SIZE) |
126 | if (map_io_page(ea+i, pa+i, flags)) | 118 | if (map_io_page((unsigned long)ea+i, pa+i, flags)) |
127 | return NULL; | 119 | return NULL; |
128 | 120 | ||
129 | return (void __iomem *) (ea + (addr & ~PAGE_MASK)); | 121 | return (void __iomem *)ea; |
122 | } | ||
123 | |||
124 | /** | ||
125 | * __iounmap_from - Low level function to tear down the page tables | ||
126 | * for an IO mapping. This is used for mappings that | ||
127 | * are manipulated manually, like partial unmapping of | ||
128 | * PCI IOs or ISA space. | ||
129 | */ | ||
130 | void __iounmap_at(void *ea, unsigned long size) | ||
131 | { | ||
132 | WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||
133 | WARN_ON(size & ~PAGE_MASK); | ||
134 | |||
135 | unmap_kernel_range((unsigned long)ea, size); | ||
130 | } | 136 | } |
131 | 137 | ||
132 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | 138 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, |
133 | unsigned long flags) | 139 | unsigned long flags) |
134 | { | 140 | { |
135 | unsigned long pa, ea; | 141 | phys_addr_t paligned; |
136 | void __iomem *ret; | 142 | void __iomem *ret; |
137 | 143 | ||
138 | /* | 144 | /* |
@@ -144,27 +150,30 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | |||
144 | * IMALLOC_END | 150 | * IMALLOC_END |
145 | * | 151 | * |
146 | */ | 152 | */ |
147 | pa = addr & PAGE_MASK; | 153 | paligned = addr & PAGE_MASK; |
148 | size = PAGE_ALIGN(addr + size) - pa; | 154 | size = PAGE_ALIGN(addr + size) - paligned; |
149 | 155 | ||
150 | if ((size == 0) || (pa == 0)) | 156 | if ((size == 0) || (paligned == 0)) |
151 | return NULL; | 157 | return NULL; |
152 | 158 | ||
153 | if (mem_init_done) { | 159 | if (mem_init_done) { |
154 | struct vm_struct *area; | 160 | struct vm_struct *area; |
155 | area = im_get_free_area(size); | 161 | |
162 | area = __get_vm_area(size, VM_IOREMAP, | ||
163 | ioremap_bot, IOREMAP_END); | ||
156 | if (area == NULL) | 164 | if (area == NULL) |
157 | return NULL; | 165 | return NULL; |
158 | ea = (unsigned long)(area->addr); | 166 | ret = __ioremap_at(paligned, area->addr, size, flags); |
159 | ret = __ioremap_com(addr, pa, ea, size, flags); | ||
160 | if (!ret) | 167 | if (!ret) |
161 | im_free(area->addr); | 168 | vunmap(area->addr); |
162 | } else { | 169 | } else { |
163 | ea = ioremap_bot; | 170 | ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); |
164 | ret = __ioremap_com(addr, pa, ea, size, flags); | ||
165 | if (ret) | 171 | if (ret) |
166 | ioremap_bot += size; | 172 | ioremap_bot += size; |
167 | } | 173 | } |
174 | |||
175 | if (ret) | ||
176 | ret += addr & ~PAGE_MASK; | ||
168 | return ret; | 177 | return ret; |
169 | } | 178 | } |
170 | 179 | ||
@@ -187,62 +196,9 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size, | |||
187 | } | 196 | } |
188 | 197 | ||
189 | 198 | ||
190 | #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) | ||
191 | |||
192 | int __ioremap_explicit(phys_addr_t pa, unsigned long ea, | ||
193 | unsigned long size, unsigned long flags) | ||
194 | { | ||
195 | struct vm_struct *area; | ||
196 | void __iomem *ret; | ||
197 | |||
198 | /* For now, require page-aligned values for pa, ea, and size */ | ||
199 | if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || | ||
200 | !IS_PAGE_ALIGNED(size)) { | ||
201 | printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__); | ||
202 | return 1; | ||
203 | } | ||
204 | |||
205 | if (!mem_init_done) { | ||
206 | /* Two things to consider in this case: | ||
207 | * 1) No records will be kept (imalloc, etc) that the region | ||
208 | * has been remapped | ||
209 | * 2) It won't be easy to iounmap() the region later (because | ||
210 | * of 1) | ||
211 | */ | ||
212 | ; | ||
213 | } else { | ||
214 | area = im_get_area(ea, size, | ||
215 | IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS); | ||
216 | if (area == NULL) { | ||
217 | /* Expected when PHB-dlpar is in play */ | ||
218 | return 1; | ||
219 | } | ||
220 | if (ea != (unsigned long) area->addr) { | ||
221 | printk(KERN_ERR "unexpected addr return from " | ||
222 | "im_get_area\n"); | ||
223 | return 1; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | ret = __ioremap_com(pa, pa, ea, size, flags); | ||
228 | if (ret == NULL) { | ||
229 | printk(KERN_ERR "ioremap_explicit() allocation failure !\n"); | ||
230 | return 1; | ||
231 | } | ||
232 | if (ret != (void *) ea) { | ||
233 | printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); | ||
234 | return 1; | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | /* | 199 | /* |
241 | * Unmap an IO region and remove it from imalloc'd list. | 200 | * Unmap an IO region and remove it from imalloc'd list. |
242 | * Access to IO memory should be serialized by driver. | 201 | * Access to IO memory should be serialized by driver. |
243 | * This code is modeled after vmalloc code - unmap_vm_area() | ||
244 | * | ||
245 | * XXX what about calls before mem_init_done (ie python_countermeasures()) | ||
246 | */ | 202 | */ |
247 | void __iounmap(volatile void __iomem *token) | 203 | void __iounmap(volatile void __iomem *token) |
248 | { | 204 | { |
@@ -251,9 +207,14 @@ void __iounmap(volatile void __iomem *token) | |||
251 | if (!mem_init_done) | 207 | if (!mem_init_done) |
252 | return; | 208 | return; |
253 | 209 | ||
254 | addr = (void *) ((unsigned long __force) token & PAGE_MASK); | 210 | addr = (void *) ((unsigned long __force) |
255 | 211 | PCI_FIX_ADDR(token) & PAGE_MASK); | |
256 | im_free(addr); | 212 | if ((unsigned long)addr < ioremap_bot) { |
213 | printk(KERN_WARNING "Attempt to iounmap early bolted mapping" | ||
214 | " at 0x%p\n", addr); | ||
215 | return; | ||
216 | } | ||
217 | vunmap(addr); | ||
257 | } | 218 | } |
258 | 219 | ||
259 | void iounmap(volatile void __iomem *token) | 220 | void iounmap(volatile void __iomem *token) |
@@ -264,77 +225,8 @@ void iounmap(volatile void __iomem *token) | |||
264 | __iounmap(token); | 225 | __iounmap(token); |
265 | } | 226 | } |
266 | 227 | ||
267 | static int iounmap_subset_regions(unsigned long addr, unsigned long size) | ||
268 | { | ||
269 | struct vm_struct *area; | ||
270 | |||
271 | /* Check whether subsets of this region exist */ | ||
272 | area = im_get_area(addr, size, IM_REGION_SUPERSET); | ||
273 | if (area == NULL) | ||
274 | return 1; | ||
275 | |||
276 | while (area) { | ||
277 | iounmap((void __iomem *) area->addr); | ||
278 | area = im_get_area(addr, size, | ||
279 | IM_REGION_SUPERSET); | ||
280 | } | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | int __iounmap_explicit(volatile void __iomem *start, unsigned long size) | ||
286 | { | ||
287 | struct vm_struct *area; | ||
288 | unsigned long addr; | ||
289 | int rc; | ||
290 | |||
291 | addr = (unsigned long __force) start & PAGE_MASK; | ||
292 | |||
293 | /* Verify that the region either exists or is a subset of an existing | ||
294 | * region. In the latter case, split the parent region to create | ||
295 | * the exact region | ||
296 | */ | ||
297 | area = im_get_area(addr, size, | ||
298 | IM_REGION_EXISTS | IM_REGION_SUBSET); | ||
299 | if (area == NULL) { | ||
300 | /* Determine whether subset regions exist. If so, unmap */ | ||
301 | rc = iounmap_subset_regions(addr, size); | ||
302 | if (rc) { | ||
303 | printk(KERN_ERR | ||
304 | "%s() cannot unmap nonexistent range 0x%lx\n", | ||
305 | __FUNCTION__, addr); | ||
306 | return 1; | ||
307 | } | ||
308 | } else { | ||
309 | iounmap((void __iomem *) area->addr); | ||
310 | } | ||
311 | /* | ||
312 | * FIXME! This can't be right: | ||
313 | iounmap(area->addr); | ||
314 | * Maybe it should be "iounmap(area);" | ||
315 | */ | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | EXPORT_SYMBOL(ioremap); | 228 | EXPORT_SYMBOL(ioremap); |
320 | EXPORT_SYMBOL(ioremap_flags); | 229 | EXPORT_SYMBOL(ioremap_flags); |
321 | EXPORT_SYMBOL(__ioremap); | 230 | EXPORT_SYMBOL(__ioremap); |
322 | EXPORT_SYMBOL(iounmap); | 231 | EXPORT_SYMBOL(iounmap); |
323 | EXPORT_SYMBOL(__iounmap); | 232 | EXPORT_SYMBOL(__iounmap); |
324 | |||
325 | static DEFINE_SPINLOCK(phb_io_lock); | ||
326 | |||
327 | void __iomem * reserve_phb_iospace(unsigned long size) | ||
328 | { | ||
329 | void __iomem *virt_addr; | ||
330 | |||
331 | if (phbs_io_bot >= IMALLOC_BASE) | ||
332 | panic("reserve_phb_iospace(): phb io space overflow\n"); | ||
333 | |||
334 | spin_lock(&phb_io_lock); | ||
335 | virt_addr = (void __iomem *) phbs_io_bot; | ||
336 | phbs_io_bot += size; | ||
337 | spin_unlock(&phb_io_lock); | ||
338 | |||
339 | return virt_addr; | ||
340 | } | ||
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index ec1421a20aaa..5c45d474cfcc 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
15 | * | 14 | * |
16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
@@ -35,12 +34,12 @@ | |||
35 | 34 | ||
36 | #include "mmu_decl.h" | 35 | #include "mmu_decl.h" |
37 | 36 | ||
38 | PTE *Hash, *Hash_end; | 37 | struct hash_pte *Hash, *Hash_end; |
39 | unsigned long Hash_size, Hash_mask; | 38 | unsigned long Hash_size, Hash_mask; |
40 | unsigned long _SDR1; | 39 | unsigned long _SDR1; |
41 | 40 | ||
42 | union ubat { /* BAT register values to be loaded */ | 41 | union ubat { /* BAT register values to be loaded */ |
43 | BAT bat; | 42 | struct ppc_bat bat; |
44 | u32 word[2]; | 43 | u32 word[2]; |
45 | } BATS[8][2]; /* 8 pairs of IBAT, DBAT */ | 44 | } BATS[8][2]; /* 8 pairs of IBAT, DBAT */ |
46 | 45 | ||
@@ -245,7 +244,7 @@ void __init MMU_init_hw(void) | |||
245 | cacheable_memzero(Hash, Hash_size); | 244 | cacheable_memzero(Hash, Hash_size); |
246 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; | 245 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; |
247 | 246 | ||
248 | Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); | 247 | Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size); |
249 | 248 | ||
250 | printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", | 249 | printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", |
251 | total_memory >> 20, Hash_size >> 10, Hash); | 250 | total_memory >> 20, Hash_size >> 10, Hash); |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 132c6bc66ce1..28492bbdee8e 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
@@ -55,7 +55,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | |||
55 | for (entry = 0; entry < 8; entry++, ste++) { | 55 | for (entry = 0; entry < 8; entry++, ste++) { |
56 | if (!(ste->esid_data & STE_ESID_V)) { | 56 | if (!(ste->esid_data & STE_ESID_V)) { |
57 | ste->vsid_data = vsid_data; | 57 | ste->vsid_data = vsid_data; |
58 | asm volatile("eieio":::"memory"); | 58 | eieio(); |
59 | ste->esid_data = esid_data; | 59 | ste->esid_data = esid_data; |
60 | return (global_entry | entry); | 60 | return (global_entry | entry); |
61 | } | 61 | } |
@@ -101,7 +101,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | |||
101 | asm volatile("sync" : : : "memory"); /* Order update */ | 101 | asm volatile("sync" : : : "memory"); /* Order update */ |
102 | 102 | ||
103 | castout_ste->vsid_data = vsid_data; | 103 | castout_ste->vsid_data = vsid_data; |
104 | asm volatile("eieio" : : : "memory"); /* Order update */ | 104 | eieio(); /* Order update */ |
105 | castout_ste->esid_data = esid_data; | 105 | castout_ste->esid_data = esid_data; |
106 | 106 | ||
107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); | 107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); |
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c index 6a69417cbc0e..06c7e77e097a 100644 --- a/arch/powerpc/mm/tlb_32.c +++ b/arch/powerpc/mm/tlb_32.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
15 | * | 14 | * |
16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index 2bfc4d7e1aa2..cbd34fc813ee 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c | |||
@@ -8,7 +8,6 @@ | |||
8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
12 | * | 11 | * |
13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
@@ -239,3 +238,59 @@ void pte_free_finish(void) | |||
239 | pte_free_submit(*batchp); | 238 | pte_free_submit(*batchp); |
240 | *batchp = NULL; | 239 | *batchp = NULL; |
241 | } | 240 | } |
241 | |||
242 | /** | ||
243 | * __flush_hash_table_range - Flush all HPTEs for a given address range | ||
244 | * from the hash table (and the TLB). But keeps | ||
245 | * the linux PTEs intact. | ||
246 | * | ||
247 | * @mm : mm_struct of the target address space (generally init_mm) | ||
248 | * @start : starting address | ||
249 | * @end : ending address (not included in the flush) | ||
250 | * | ||
251 | * This function is mostly to be used by some IO hotplug code in order | ||
252 | * to remove all hash entries from a given address range used to map IO | ||
253 | * space on a removed PCI-PCI bidge without tearing down the full mapping | ||
254 | * since 64K pages may overlap with other bridges when using 64K pages | ||
255 | * with 4K HW pages on IO space. | ||
256 | * | ||
257 | * Because of that usage pattern, it's only available with CONFIG_HOTPLUG | ||
258 | * and is implemented for small size rather than speed. | ||
259 | */ | ||
260 | #ifdef CONFIG_HOTPLUG | ||
261 | |||
262 | void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | ||
263 | unsigned long end) | ||
264 | { | ||
265 | unsigned long flags; | ||
266 | |||
267 | start = _ALIGN_DOWN(start, PAGE_SIZE); | ||
268 | end = _ALIGN_UP(end, PAGE_SIZE); | ||
269 | |||
270 | BUG_ON(!mm->pgd); | ||
271 | |||
272 | /* Note: Normally, we should only ever use a batch within a | ||
273 | * PTE locked section. This violates the rule, but will work | ||
274 | * since we don't actually modify the PTEs, we just flush the | ||
275 | * hash while leaving the PTEs intact (including their reference | ||
276 | * to being hashed). This is not the most performance oriented | ||
277 | * way to do things but is fine for our needs here. | ||
278 | */ | ||
279 | local_irq_save(flags); | ||
280 | arch_enter_lazy_mmu_mode(); | ||
281 | for (; start < end; start += PAGE_SIZE) { | ||
282 | pte_t *ptep = find_linux_pte(mm->pgd, start); | ||
283 | unsigned long pte; | ||
284 | |||
285 | if (ptep == NULL) | ||
286 | continue; | ||
287 | pte = pte_val(*ptep); | ||
288 | if (!(pte & _PAGE_HASHPTE)) | ||
289 | continue; | ||
290 | hpte_need_flush(mm, start, ptep, pte, 0); | ||
291 | } | ||
292 | arch_leave_lazy_mmu_mode(); | ||
293 | local_irq_restore(flags); | ||
294 | } | ||
295 | |||
296 | #endif /* CONFIG_HOTPLUG */ | ||
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index fe597a154d4f..a7c206b665af 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM | 2 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM |
3 | * Added mmcra[slot] support: | ||
4 | * Copyright (C) 2006-2007 Will Schmidt <willschm@us.ibm.com>, IBM | ||
3 | * | 5 | * |
4 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
@@ -181,11 +183,17 @@ static void __attribute_used__ kernel_unknown_bucket(void) | |||
181 | * On GQ and newer the MMCRA stores the HV and PR bits at the time | 183 | * On GQ and newer the MMCRA stores the HV and PR bits at the time |
182 | * the SIAR was sampled. We use that to work out if the SIAR was sampled in | 184 | * the SIAR was sampled. We use that to work out if the SIAR was sampled in |
183 | * the hypervisor, our exception vectors or RTAS. | 185 | * the hypervisor, our exception vectors or RTAS. |
186 | * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits | ||
187 | * to more accurately identify the address of the sampled instruction. The | ||
188 | * mmcra[slot] bits represent the slot number of a sampled instruction | ||
189 | * within an instruction group. The slot will contain a value between 1 | ||
190 | * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0. | ||
184 | */ | 191 | */ |
185 | static unsigned long get_pc(struct pt_regs *regs) | 192 | static unsigned long get_pc(struct pt_regs *regs) |
186 | { | 193 | { |
187 | unsigned long pc = mfspr(SPRN_SIAR); | 194 | unsigned long pc = mfspr(SPRN_SIAR); |
188 | unsigned long mmcra; | 195 | unsigned long mmcra; |
196 | unsigned long slot; | ||
189 | 197 | ||
190 | /* Cant do much about it */ | 198 | /* Cant do much about it */ |
191 | if (!cur_cpu_spec->oprofile_mmcra_sihv) | 199 | if (!cur_cpu_spec->oprofile_mmcra_sihv) |
@@ -193,6 +201,12 @@ static unsigned long get_pc(struct pt_regs *regs) | |||
193 | 201 | ||
194 | mmcra = mfspr(SPRN_MMCRA); | 202 | mmcra = mfspr(SPRN_MMCRA); |
195 | 203 | ||
204 | if (mmcra & MMCRA_SAMPLE_ENABLE) { | ||
205 | slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT); | ||
206 | if (slot > 1) | ||
207 | pc += 4 * (slot - 1); | ||
208 | } | ||
209 | |||
196 | /* Were we in the hypervisor? */ | 210 | /* Were we in the hypervisor? */ |
197 | if (firmware_has_feature(FW_FEATURE_LPAR) && | 211 | if (firmware_has_feature(FW_FEATURE_LPAR) && |
198 | (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) | 212 | (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) |
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index f591a9fc19b9..4be6e7a17b66 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
@@ -54,7 +54,7 @@ static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
54 | struct pci_controller *hose = bus->sysdata; | 54 | struct pci_controller *hose = bus->sysdata; |
55 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 55 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
56 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 56 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
57 | | (hose->index << 24); | 57 | | (hose->global_number << 24); |
58 | int ret = -1; | 58 | int ret = -1; |
59 | int rval; | 59 | int rval; |
60 | 60 | ||
@@ -69,7 +69,7 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, | |||
69 | struct pci_controller *hose = bus->sysdata; | 69 | struct pci_controller *hose = bus->sysdata; |
70 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 70 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
71 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 71 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
72 | | (hose->index << 24); | 72 | | (hose->global_number << 24); |
73 | int rval; | 73 | int rval; |
74 | 74 | ||
75 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, | 75 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, |
@@ -83,7 +83,7 @@ static struct pci_ops rtas_pci_ops = { | |||
83 | }; | 83 | }; |
84 | 84 | ||
85 | 85 | ||
86 | void __init efika_pcisetup(void) | 86 | static void __init efika_pcisetup(void) |
87 | { | 87 | { |
88 | const int *bus_range; | 88 | const int *bus_range; |
89 | int len; | 89 | int len; |
@@ -128,7 +128,7 @@ void __init efika_pcisetup(void) | |||
128 | printk(" controlled by %s\n", pcictrl->full_name); | 128 | printk(" controlled by %s\n", pcictrl->full_name); |
129 | printk("\n"); | 129 | printk("\n"); |
130 | 130 | ||
131 | hose = pcibios_alloc_controller(); | 131 | hose = pcibios_alloc_controller(of_node_get(pcictrl)); |
132 | if (!hose) { | 132 | if (!hose) { |
133 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | 133 | printk(KERN_WARNING EFIKA_PLATFORM_NAME |
134 | ": Can't allocate PCI controller structure for %s\n", | 134 | ": Can't allocate PCI controller structure for %s\n", |
@@ -136,7 +136,6 @@ void __init efika_pcisetup(void) | |||
136 | return; | 136 | return; |
137 | } | 137 | } |
138 | 138 | ||
139 | hose->arch_data = of_node_get(pcictrl); | ||
140 | hose->first_busno = bus_range[0]; | 139 | hose->first_busno = bus_range[0]; |
141 | hose->last_busno = bus_range[1]; | 140 | hose->last_busno = bus_range[1]; |
142 | hose->ops = &rtas_pci_ops; | 141 | hose->ops = &rtas_pci_ops; |
@@ -145,7 +144,7 @@ void __init efika_pcisetup(void) | |||
145 | } | 144 | } |
146 | 145 | ||
147 | #else | 146 | #else |
148 | void __init efika_pcisetup(void) | 147 | static void __init efika_pcisetup(void) |
149 | {} | 148 | {} |
150 | #endif | 149 | #endif |
151 | 150 | ||
@@ -252,6 +251,8 @@ define_machine(efika) | |||
252 | .progress = rtas_progress, | 251 | .progress = rtas_progress, |
253 | .get_boot_time = rtas_get_boot_time, | 252 | .get_boot_time = rtas_get_boot_time, |
254 | .calibrate_decr = generic_calibrate_decr, | 253 | .calibrate_decr = generic_calibrate_decr, |
254 | #ifdef CONFIG_PCI | ||
255 | .phys_mem_access_prot = pci_phys_mem_access_prot, | 255 | .phys_mem_access_prot = pci_phys_mem_access_prot, |
256 | #endif | ||
256 | }; | 257 | }; |
257 | 258 | ||
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c index 1cfc00dfb99a..5c46e898fd45 100644 --- a/arch/powerpc/platforms/52xx/lite5200.c +++ b/arch/powerpc/platforms/52xx/lite5200.c | |||
@@ -156,7 +156,7 @@ static void __init lite5200_setup_arch(void) | |||
156 | 156 | ||
157 | } | 157 | } |
158 | 158 | ||
159 | void lite5200_show_cpuinfo(struct seq_file *m) | 159 | static void lite5200_show_cpuinfo(struct seq_file *m) |
160 | { | 160 | { |
161 | struct device_node* np = of_find_all_nodes(NULL); | 161 | struct device_node* np = of_find_all_nodes(NULL); |
162 | const char *model = NULL; | 162 | const char *model = NULL; |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c index 34d34a26d305..4c6c82a684b1 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c | |||
@@ -112,18 +112,18 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | |||
112 | u32 value; | 112 | u32 value; |
113 | 113 | ||
114 | if (ppc_md.pci_exclude_device) | 114 | if (ppc_md.pci_exclude_device) |
115 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 115 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
116 | return PCIBIOS_DEVICE_NOT_FOUND; | 116 | return PCIBIOS_DEVICE_NOT_FOUND; |
117 | 117 | ||
118 | out_be32(hose->cfg_addr, | 118 | out_be32(hose->cfg_addr, |
119 | (1 << 31) | | 119 | (1 << 31) | |
120 | ((bus->number - hose->bus_offset) << 16) | | 120 | (bus->number << 16) | |
121 | (devfn << 8) | | 121 | (devfn << 8) | |
122 | (offset & 0xfc)); | 122 | (offset & 0xfc)); |
123 | mb(); | 123 | mb(); |
124 | 124 | ||
125 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) | 125 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) |
126 | if (bus->number != hose->bus_offset) { | 126 | if (bus->number) { |
127 | /* workaround for the bug 435 of the MPC5200 (L25R); | 127 | /* workaround for the bug 435 of the MPC5200 (L25R); |
128 | * Don't do 32 bits config access during type-1 cycles */ | 128 | * Don't do 32 bits config access during type-1 cycles */ |
129 | switch (len) { | 129 | switch (len) { |
@@ -169,18 +169,18 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, | |||
169 | u32 value, mask; | 169 | u32 value, mask; |
170 | 170 | ||
171 | if (ppc_md.pci_exclude_device) | 171 | if (ppc_md.pci_exclude_device) |
172 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 172 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
173 | return PCIBIOS_DEVICE_NOT_FOUND; | 173 | return PCIBIOS_DEVICE_NOT_FOUND; |
174 | 174 | ||
175 | out_be32(hose->cfg_addr, | 175 | out_be32(hose->cfg_addr, |
176 | (1 << 31) | | 176 | (1 << 31) | |
177 | ((bus->number - hose->bus_offset) << 16) | | 177 | (bus->number << 16) | |
178 | (devfn << 8) | | 178 | (devfn << 8) | |
179 | (offset & 0xfc)); | 179 | (offset & 0xfc)); |
180 | mb(); | 180 | mb(); |
181 | 181 | ||
182 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) | 182 | #if defined(CONFIG_PPC_MPC5200_BUGFIX) |
183 | if (bus->number != hose->bus_offset) { | 183 | if (bus->number) { |
184 | /* workaround for the bug 435 of the MPC5200 (L25R); | 184 | /* workaround for the bug 435 of the MPC5200 (L25R); |
185 | * Don't do 32 bits config access during type-1 cycles */ | 185 | * Don't do 32 bits config access during type-1 cycles */ |
186 | switch (len) { | 186 | switch (len) { |
@@ -385,17 +385,13 @@ mpc52xx_add_bridge(struct device_node *node) | |||
385 | * tree are needed to configure the 52xx PCI controller. Rather | 385 | * tree are needed to configure the 52xx PCI controller. Rather |
386 | * than parse the tree here, let pci_process_bridge_OF_ranges() | 386 | * than parse the tree here, let pci_process_bridge_OF_ranges() |
387 | * do it for us and extract the values after the fact */ | 387 | * do it for us and extract the values after the fact */ |
388 | hose = pcibios_alloc_controller(); | 388 | hose = pcibios_alloc_controller(node); |
389 | if (!hose) | 389 | if (!hose) |
390 | return -ENOMEM; | 390 | return -ENOMEM; |
391 | 391 | ||
392 | hose->arch_data = node; | ||
393 | hose->set_cfg_type = 1; | ||
394 | |||
395 | hose->first_busno = bus_range ? bus_range[0] : 0; | 392 | hose->first_busno = bus_range ? bus_range[0] : 0; |
396 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 393 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
397 | 394 | ||
398 | hose->bus_offset = 0; | ||
399 | hose->ops = &mpc52xx_pci_ops; | 395 | hose->ops = &mpc52xx_pci_ops; |
400 | 396 | ||
401 | pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1); | 397 | pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1); |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/arch/powerpc/platforms/52xx/mpc52xx_pm.c index fd40044d16cd..ee2e7639c63e 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pm.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pm.c | |||
@@ -9,8 +9,8 @@ | |||
9 | 9 | ||
10 | 10 | ||
11 | /* these are defined in mpc52xx_sleep.S, and only used here */ | 11 | /* these are defined in mpc52xx_sleep.S, and only used here */ |
12 | extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs, | 12 | extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs, |
13 | struct mpc52xx_cdm *, struct mpc52xx_intr *); | 13 | struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*); |
14 | extern void mpc52xx_ds_sram(void); | 14 | extern void mpc52xx_ds_sram(void); |
15 | extern const long mpc52xx_ds_sram_size; | 15 | extern const long mpc52xx_ds_sram_size; |
16 | extern void mpc52xx_ds_cached(void); | 16 | extern void mpc52xx_ds_cached(void); |
@@ -21,7 +21,7 @@ static void __iomem *sdram; | |||
21 | static struct mpc52xx_cdm __iomem *cdm; | 21 | static struct mpc52xx_cdm __iomem *cdm; |
22 | static struct mpc52xx_intr __iomem *intr; | 22 | static struct mpc52xx_intr __iomem *intr; |
23 | static struct mpc52xx_gpio_wkup __iomem *gpiow; | 23 | static struct mpc52xx_gpio_wkup __iomem *gpiow; |
24 | static void *sram; | 24 | static void __iomem *sram; |
25 | static int sram_size; | 25 | static int sram_size; |
26 | 26 | ||
27 | struct mpc52xx_suspend mpc52xx_suspend; | 27 | struct mpc52xx_suspend mpc52xx_suspend; |
@@ -100,7 +100,7 @@ int mpc52xx_pm_enter(suspend_state_t state) | |||
100 | u32 clk_enables; | 100 | u32 clk_enables; |
101 | u32 msr, hid0; | 101 | u32 msr, hid0; |
102 | u32 intr_main_mask; | 102 | u32 intr_main_mask; |
103 | void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500; | 103 | void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500; |
104 | unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size; | 104 | unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size; |
105 | char saved_0x500[mpc52xx_ds_cached_size]; | 105 | char saved_0x500[mpc52xx_ds_cached_size]; |
106 | 106 | ||
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index de7fce9cb6eb..89fde43895c5 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | choice | 1 | choice |
2 | prompt "Machine Type" | 2 | prompt "82xx Board Type" |
3 | depends on PPC_82xx | 3 | depends on PPC_82xx |
4 | default MPC82xx_ADS | 4 | default MPC82xx_ADS |
5 | 5 | ||
diff --git a/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/arch/powerpc/platforms/82xx/mpc82xx_ads.c index 47cb09f08052..da20832b27f1 100644 --- a/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/arch/powerpc/platforms/82xx/mpc82xx_ads.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include <linux/fs_enet_pd.h> | 49 | #include <linux/fs_enet_pd.h> |
50 | 50 | ||
51 | #include <sysdev/fsl_soc.h> | 51 | #include <sysdev/fsl_soc.h> |
52 | #include <../sysdev/cpm2_pic.h> | 52 | #include <sysdev/cpm2_pic.h> |
53 | 53 | ||
54 | #include "pq2ads.h" | 54 | #include "pq2ads.h" |
55 | 55 | ||
@@ -507,7 +507,8 @@ void m82xx_pci_init_irq(void) | |||
507 | return; | 507 | return; |
508 | } | 508 | } |
509 | 509 | ||
510 | static int m82xx_pci_exclude_device(u_char bus, u_char devfn) | 510 | static int m82xx_pci_exclude_device(struct pci_controller *hose, |
511 | u_char bus, u_char devfn) | ||
511 | { | 512 | { |
512 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 513 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
513 | return PCIBIOS_DEVICE_NOT_FOUND; | 514 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -515,7 +516,7 @@ static int m82xx_pci_exclude_device(u_char bus, u_char devfn) | |||
515 | return PCIBIOS_SUCCESSFUL; | 516 | return PCIBIOS_SUCCESSFUL; |
516 | } | 517 | } |
517 | 518 | ||
518 | void __init add_bridge(struct device_node *np) | 519 | static void __init mpc82xx_add_bridge(struct device_node *np) |
519 | { | 520 | { |
520 | int len; | 521 | int len; |
521 | struct pci_controller *hose; | 522 | struct pci_controller *hose; |
@@ -542,19 +543,13 @@ void __init add_bridge(struct device_node *np) | |||
542 | 543 | ||
543 | pci_assign_all_buses = 1; | 544 | pci_assign_all_buses = 1; |
544 | 545 | ||
545 | hose = pcibios_alloc_controller(); | 546 | hose = pcibios_alloc_controller(np); |
546 | 547 | ||
547 | if (!hose) | 548 | if (!hose) |
548 | return; | 549 | return; |
549 | 550 | ||
550 | hose->arch_data = np; | ||
551 | hose->set_cfg_type = 1; | ||
552 | |||
553 | hose->first_busno = bus_range ? bus_range[0] : 0; | 551 | hose->first_busno = bus_range ? bus_range[0] : 0; |
554 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 552 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
555 | hose->bus_offset = 0; | ||
556 | |||
557 | hose->set_cfg_type = 1; | ||
558 | 553 | ||
559 | setup_indirect_pci(hose, | 554 | setup_indirect_pci(hose, |
560 | r.start + offsetof(pci_cpm2_t, pci_cfg_addr), | 555 | r.start + offsetof(pci_cpm2_t, pci_cfg_addr), |
@@ -584,7 +579,7 @@ static void __init mpc82xx_ads_setup_arch(void) | |||
584 | #ifdef CONFIG_PCI | 579 | #ifdef CONFIG_PCI |
585 | ppc_md.pci_exclude_device = m82xx_pci_exclude_device; | 580 | ppc_md.pci_exclude_device = m82xx_pci_exclude_device; |
586 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 581 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
587 | add_bridge(np); | 582 | mpc82xx_add_bridge(np); |
588 | 583 | ||
589 | of_node_put(np); | 584 | of_node_put(np); |
590 | #endif | 585 | #endif |
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 19cafdf6df93..ec305f18abd8 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | choice | 1 | choice |
2 | prompt "Machine Type" | 2 | prompt "83xx Board Type" |
3 | depends on PPC_83xx | 3 | depends on PPC_83xx |
4 | default MPC834x_MDS | 4 | default MPC834x_MDS |
5 | 5 | ||
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 31a91b53f528..5a98f885779f 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the PowerPC 83xx linux kernel. | 2 | # Makefile for the PowerPC 83xx linux kernel. |
3 | # | 3 | # |
4 | obj-y := misc.o | 4 | obj-y := misc.o usb.o |
5 | obj-$(CONFIG_PCI) += pci.o | 5 | obj-$(CONFIG_PCI) += pci.o |
6 | obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o | 6 | obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o |
7 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o | 7 | obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o |
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c index 96970ac887ee..3edfe170a03b 100644 --- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c | |||
@@ -28,11 +28,6 @@ | |||
28 | #define DBG(fmt...) | 28 | #define DBG(fmt...) |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #ifndef CONFIG_PCI | ||
32 | unsigned long isa_io_base = 0; | ||
33 | unsigned long isa_mem_base = 0; | ||
34 | #endif | ||
35 | |||
36 | /* ************************************************************************ | 31 | /* ************************************************************************ |
37 | * | 32 | * |
38 | * Setup the architecture | 33 | * Setup the architecture |
@@ -49,10 +44,11 @@ static void __init mpc8313_rdb_setup_arch(void) | |||
49 | 44 | ||
50 | #ifdef CONFIG_PCI | 45 | #ifdef CONFIG_PCI |
51 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 46 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
52 | add_bridge(np); | 47 | mpc83xx_add_bridge(np); |
53 | 48 | ||
54 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 49 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
55 | #endif | 50 | #endif |
51 | mpc831x_usb_cfg(); | ||
56 | } | 52 | } |
57 | 53 | ||
58 | void __init mpc8313_rdb_init_IRQ(void) | 54 | void __init mpc8313_rdb_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index 94843ed52a93..b39cb52c6fb9 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c | |||
@@ -49,11 +49,6 @@ | |||
49 | #define DBG(fmt...) | 49 | #define DBG(fmt...) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifndef CONFIG_PCI | ||
53 | unsigned long isa_io_base = 0; | ||
54 | unsigned long isa_mem_base = 0; | ||
55 | #endif | ||
56 | |||
57 | static u8 *bcsr_regs = NULL; | 52 | static u8 *bcsr_regs = NULL; |
58 | 53 | ||
59 | /* ************************************************************************ | 54 | /* ************************************************************************ |
@@ -80,7 +75,7 @@ static void __init mpc832x_sys_setup_arch(void) | |||
80 | 75 | ||
81 | #ifdef CONFIG_PCI | 76 | #ifdef CONFIG_PCI |
82 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 77 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
83 | add_bridge(np); | 78 | mpc83xx_add_bridge(np); |
84 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 79 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
85 | #endif | 80 | #endif |
86 | 81 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 3db68b73fc32..b2b28a44738c 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
@@ -32,11 +32,6 @@ | |||
32 | #define DBG(fmt...) | 32 | #define DBG(fmt...) |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #ifndef CONFIG_PCI | ||
36 | unsigned long isa_io_base = 0; | ||
37 | unsigned long isa_mem_base = 0; | ||
38 | #endif | ||
39 | |||
40 | /* ************************************************************************ | 35 | /* ************************************************************************ |
41 | * | 36 | * |
42 | * Setup the architecture | 37 | * Setup the architecture |
@@ -53,7 +48,7 @@ static void __init mpc832x_rdb_setup_arch(void) | |||
53 | 48 | ||
54 | #ifdef CONFIG_PCI | 49 | #ifdef CONFIG_PCI |
55 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 50 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
56 | add_bridge(np); | 51 | mpc83xx_add_bridge(np); |
57 | 52 | ||
58 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 53 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
59 | #endif | 54 | #endif |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index 40a01947d684..47ba5446f63c 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c | |||
@@ -38,11 +38,6 @@ | |||
38 | 38 | ||
39 | #include "mpc83xx.h" | 39 | #include "mpc83xx.h" |
40 | 40 | ||
41 | #ifndef CONFIG_PCI | ||
42 | unsigned long isa_io_base = 0; | ||
43 | unsigned long isa_mem_base = 0; | ||
44 | #endif | ||
45 | |||
46 | /* ************************************************************************ | 41 | /* ************************************************************************ |
47 | * | 42 | * |
48 | * Setup the architecture | 43 | * Setup the architecture |
@@ -59,10 +54,12 @@ static void __init mpc834x_itx_setup_arch(void) | |||
59 | 54 | ||
60 | #ifdef CONFIG_PCI | 55 | #ifdef CONFIG_PCI |
61 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 56 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
62 | add_bridge(np); | 57 | mpc83xx_add_bridge(np); |
63 | 58 | ||
64 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 59 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
65 | #endif | 60 | #endif |
61 | |||
62 | mpc834x_usb_cfg(); | ||
66 | } | 63 | } |
67 | 64 | ||
68 | static void __init mpc834x_itx_init_IRQ(void) | 65 | static void __init mpc834x_itx_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 10394b2d7e7a..4c9ff9cadfe4 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c | |||
@@ -38,61 +38,17 @@ | |||
38 | 38 | ||
39 | #include "mpc83xx.h" | 39 | #include "mpc83xx.h" |
40 | 40 | ||
41 | #ifndef CONFIG_PCI | ||
42 | unsigned long isa_io_base = 0; | ||
43 | unsigned long isa_mem_base = 0; | ||
44 | #endif | ||
45 | |||
46 | #define BCSR5_INT_USB 0x02 | 41 | #define BCSR5_INT_USB 0x02 |
47 | /* Note: This is only for PB, not for PB+PIB | 42 | static int mpc834xemds_usb_cfg(void) |
48 | * On PB only port0 is connected using ULPI */ | ||
49 | static int mpc834x_usb_cfg(void) | ||
50 | { | 43 | { |
51 | unsigned long sccr, sicrl; | 44 | struct device_node *np; |
52 | void __iomem *immap; | ||
53 | void __iomem *bcsr_regs = NULL; | 45 | void __iomem *bcsr_regs = NULL; |
54 | u8 bcsr5; | 46 | u8 bcsr5; |
55 | struct device_node *np = NULL; | ||
56 | int port0_is_dr = 0; | ||
57 | |||
58 | if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL) | ||
59 | port0_is_dr = 1; | ||
60 | if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){ | ||
61 | if (port0_is_dr) { | ||
62 | printk(KERN_WARNING | ||
63 | "There is only one USB port on PB board! \n"); | ||
64 | return -1; | ||
65 | } else if (!port0_is_dr) | ||
66 | /* No usb port enabled */ | ||
67 | return -1; | ||
68 | } | ||
69 | |||
70 | immap = ioremap(get_immrbase(), 0x1000); | ||
71 | if (!immap) | ||
72 | return -1; | ||
73 | |||
74 | /* Configure clock */ | ||
75 | sccr = in_be32(immap + MPC83XX_SCCR_OFFS); | ||
76 | if (port0_is_dr) | ||
77 | sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
78 | else | ||
79 | sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ | ||
80 | out_be32(immap + MPC83XX_SCCR_OFFS, sccr); | ||
81 | |||
82 | /* Configure Pin */ | ||
83 | sicrl = in_be32(immap + MPC83XX_SICRL_OFFS); | ||
84 | /* set port0 only */ | ||
85 | if (port0_is_dr) | ||
86 | sicrl |= MPC83XX_SICRL_USB0; | ||
87 | else | ||
88 | sicrl &= ~(MPC83XX_SICRL_USB0); | ||
89 | out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); | ||
90 | |||
91 | iounmap(immap); | ||
92 | 47 | ||
48 | mpc834x_usb_cfg(); | ||
93 | /* Map BCSR area */ | 49 | /* Map BCSR area */ |
94 | np = of_find_node_by_name(NULL, "bcsr"); | 50 | np = of_find_node_by_name(NULL, "bcsr"); |
95 | if (np != 0) { | 51 | if (np) { |
96 | struct resource res; | 52 | struct resource res; |
97 | 53 | ||
98 | of_address_to_resource(np, 0, &res); | 54 | of_address_to_resource(np, 0, &res); |
@@ -129,12 +85,12 @@ static void __init mpc834x_mds_setup_arch(void) | |||
129 | 85 | ||
130 | #ifdef CONFIG_PCI | 86 | #ifdef CONFIG_PCI |
131 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 87 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
132 | add_bridge(np); | 88 | mpc83xx_add_bridge(np); |
133 | 89 | ||
134 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 90 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
135 | #endif | 91 | #endif |
136 | 92 | ||
137 | mpc834x_usb_cfg(); | 93 | mpc834xemds_usb_cfg(); |
138 | } | 94 | } |
139 | 95 | ||
140 | static void __init mpc834x_mds_init_IRQ(void) | 96 | static void __init mpc834x_mds_init_IRQ(void) |
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index bceeff8bbfd2..0e615fd65c1f 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c | |||
@@ -55,11 +55,6 @@ | |||
55 | #define DBG(fmt...) | 55 | #define DBG(fmt...) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #ifndef CONFIG_PCI | ||
59 | unsigned long isa_io_base = 0; | ||
60 | unsigned long isa_mem_base = 0; | ||
61 | #endif | ||
62 | |||
63 | static u8 *bcsr_regs = NULL; | 58 | static u8 *bcsr_regs = NULL; |
64 | 59 | ||
65 | /* ************************************************************************ | 60 | /* ************************************************************************ |
@@ -86,7 +81,7 @@ static void __init mpc836x_mds_setup_arch(void) | |||
86 | 81 | ||
87 | #ifdef CONFIG_PCI | 82 | #ifdef CONFIG_PCI |
88 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 83 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
89 | add_bridge(np); | 84 | mpc83xx_add_bridge(np); |
90 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; | 85 | ppc_md.pci_exclude_device = mpc83xx_exclude_device; |
91 | #endif | 86 | #endif |
92 | 87 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 9cd03b59c8f4..589ee55730f3 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -3,9 +3,11 @@ | |||
3 | 3 | ||
4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
5 | #include <linux/device.h> | 5 | #include <linux/device.h> |
6 | #include <asm/pci-bridge.h> | ||
6 | 7 | ||
7 | /* System Clock Control Register */ | 8 | /* System Clock Control Register */ |
8 | #define MPC83XX_SCCR_OFFS 0xA08 | 9 | #define MPC83XX_SCCR_OFFS 0xA08 |
10 | #define MPC83XX_SCCR_USB_MASK 0x00f00000 | ||
9 | #define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000 | 11 | #define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000 |
10 | #define MPC83XX_SCCR_USB_MPHCM_01 0x00400000 | 12 | #define MPC83XX_SCCR_USB_MPHCM_01 0x00400000 |
11 | #define MPC83XX_SCCR_USB_MPHCM_10 0x00800000 | 13 | #define MPC83XX_SCCR_USB_MPHCM_10 0x00800000 |
@@ -15,21 +17,43 @@ | |||
15 | 17 | ||
16 | /* system i/o configuration register low */ | 18 | /* system i/o configuration register low */ |
17 | #define MPC83XX_SICRL_OFFS 0x114 | 19 | #define MPC83XX_SICRL_OFFS 0x114 |
18 | #define MPC83XX_SICRL_USB0 0x40000000 | 20 | #define MPC834X_SICRL_USB_MASK 0x60000000 |
19 | #define MPC83XX_SICRL_USB1 0x20000000 | 21 | #define MPC834X_SICRL_USB0 0x40000000 |
22 | #define MPC834X_SICRL_USB1 0x20000000 | ||
23 | #define MPC831X_SICRL_USB_MASK 0x00000c00 | ||
24 | #define MPC831X_SICRL_USB_ULPI 0x00000800 | ||
20 | 25 | ||
21 | /* system i/o configuration register high */ | 26 | /* system i/o configuration register high */ |
22 | #define MPC83XX_SICRH_OFFS 0x118 | 27 | #define MPC83XX_SICRH_OFFS 0x118 |
23 | #define MPC83XX_SICRH_USB_UTMI 0x00020000 | 28 | #define MPC834X_SICRH_USB_UTMI 0x00020000 |
29 | #define MPC831X_SICRH_USB_MASK 0x000000e0 | ||
30 | #define MPC831X_SICRH_USB_ULPI 0x000000a0 | ||
31 | |||
32 | /* USB Control Register */ | ||
33 | #define FSL_USB2_CONTROL_OFFS 0x500 | ||
34 | #define CONTROL_UTMI_PHY_EN 0x00000200 | ||
35 | #define CONTROL_REFSEL_48MHZ 0x00000080 | ||
36 | #define CONTROL_PHY_CLK_SEL_ULPI 0x00000400 | ||
37 | #define CONTROL_OTG_PORT 0x00000020 | ||
38 | |||
39 | /* USB PORTSC Registers */ | ||
40 | #define FSL_USB2_PORTSC1_OFFS 0x184 | ||
41 | #define FSL_USB2_PORTSC2_OFFS 0x188 | ||
42 | #define PORTSCX_PTW_16BIT 0x10000000 | ||
43 | #define PORTSCX_PTS_UTMI 0x00000000 | ||
44 | #define PORTSCX_PTS_ULPI 0x80000000 | ||
24 | 45 | ||
25 | /* | 46 | /* |
26 | * Declaration for the various functions exported by the | 47 | * Declaration for the various functions exported by the |
27 | * mpc83xx_* files. Mostly for use by mpc83xx_setup | 48 | * mpc83xx_* files. Mostly for use by mpc83xx_setup |
28 | */ | 49 | */ |
29 | 50 | ||
30 | extern int add_bridge(struct device_node *dev); | 51 | extern int mpc83xx_add_bridge(struct device_node *dev); |
31 | extern int mpc83xx_exclude_device(u_char bus, u_char devfn); | 52 | extern int mpc83xx_exclude_device(struct pci_controller *hose, |
53 | u_char bus, u_char devfn); | ||
32 | extern void mpc83xx_restart(char *cmd); | 54 | extern void mpc83xx_restart(char *cmd); |
33 | extern long mpc83xx_time_init(void); | 55 | extern long mpc83xx_time_init(void); |
56 | extern int mpc834x_usb_cfg(void); | ||
57 | extern int mpc831x_usb_cfg(void); | ||
34 | 58 | ||
35 | #endif /* __MPC83XX_H__ */ | 59 | #endif /* __MPC83XX_H__ */ |
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 774457d09e94..c0e2b89154e5 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c | |||
@@ -33,19 +33,14 @@ | |||
33 | #define DBG(x...) | 33 | #define DBG(x...) |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | int mpc83xx_pci2_busno; | 36 | int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) |
37 | |||
38 | int mpc83xx_exclude_device(u_char bus, u_char devfn) | ||
39 | { | 37 | { |
40 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 38 | if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) |
41 | return PCIBIOS_DEVICE_NOT_FOUND; | 39 | return PCIBIOS_DEVICE_NOT_FOUND; |
42 | if (mpc83xx_pci2_busno) | ||
43 | if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) | ||
44 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
45 | return PCIBIOS_SUCCESSFUL; | 40 | return PCIBIOS_SUCCESSFUL; |
46 | } | 41 | } |
47 | 42 | ||
48 | int __init add_bridge(struct device_node *dev) | 43 | int __init mpc83xx_add_bridge(struct device_node *dev) |
49 | { | 44 | { |
50 | int len; | 45 | int len; |
51 | struct pci_controller *hose; | 46 | struct pci_controller *hose; |
@@ -66,11 +61,10 @@ int __init add_bridge(struct device_node *dev) | |||
66 | " bus 0\n", dev->full_name); | 61 | " bus 0\n", dev->full_name); |
67 | } | 62 | } |
68 | 63 | ||
69 | hose = pcibios_alloc_controller(); | 64 | pci_assign_all_buses = 1; |
65 | hose = pcibios_alloc_controller(dev); | ||
70 | if (!hose) | 66 | if (!hose) |
71 | return -ENOMEM; | 67 | return -ENOMEM; |
72 | hose->arch_data = dev; | ||
73 | hose->set_cfg_type = 1; | ||
74 | 68 | ||
75 | hose->first_busno = bus_range ? bus_range[0] : 0; | 69 | hose->first_busno = bus_range ? bus_range[0] : 0; |
76 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 70 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
@@ -86,8 +80,6 @@ int __init add_bridge(struct device_node *dev) | |||
86 | if ((rsrc.start & 0xfffff) == 0x8600) { | 80 | if ((rsrc.start & 0xfffff) == 0x8600) { |
87 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); | 81 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); |
88 | primary = 0; | 82 | primary = 0; |
89 | hose->bus_offset = hose->first_busno; | ||
90 | mpc83xx_pci2_busno = hose->first_busno; | ||
91 | } | 83 | } |
92 | 84 | ||
93 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " | 85 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " |
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c new file mode 100644 index 000000000000..e7fdf013cd39 --- /dev/null +++ b/arch/powerpc/platforms/83xx/usb.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * Freescale 83xx USB SOC setup code | ||
3 | * | ||
4 | * Copyright (C) 2007 Freescale Semiconductor, Inc. | ||
5 | * Author: Li Yang | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | |||
14 | #include <linux/stddef.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/errno.h> | ||
17 | |||
18 | #include <asm/io.h> | ||
19 | #include <asm/prom.h> | ||
20 | #include <sysdev/fsl_soc.h> | ||
21 | |||
22 | #include "mpc83xx.h" | ||
23 | |||
24 | |||
25 | #ifdef CONFIG_MPC834x | ||
26 | int mpc834x_usb_cfg(void) | ||
27 | { | ||
28 | unsigned long sccr, sicrl, sicrh; | ||
29 | void __iomem *immap; | ||
30 | struct device_node *np = NULL; | ||
31 | int port0_is_dr = 0, port1_is_dr = 0; | ||
32 | const void *prop, *dr_mode; | ||
33 | |||
34 | immap = ioremap(get_immrbase(), 0x1000); | ||
35 | if (!immap) | ||
36 | return -ENOMEM; | ||
37 | |||
38 | /* Read registers */ | ||
39 | /* Note: DR and MPH must use the same clock setting in SCCR */ | ||
40 | sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK; | ||
41 | sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK; | ||
42 | sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI; | ||
43 | |||
44 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); | ||
45 | if (np) { | ||
46 | sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
47 | |||
48 | prop = of_get_property(np, "phy_type", NULL); | ||
49 | if (prop && (!strcmp(prop, "utmi") || | ||
50 | !strcmp(prop, "utmi_wide"))) { | ||
51 | sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; | ||
52 | sicrh |= MPC834X_SICRH_USB_UTMI; | ||
53 | port1_is_dr = 1; | ||
54 | } else if (prop && !strcmp(prop, "serial")) { | ||
55 | dr_mode = of_get_property(np, "dr_mode", NULL); | ||
56 | if (dr_mode && !strcmp(dr_mode, "otg")) { | ||
57 | sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; | ||
58 | port1_is_dr = 1; | ||
59 | } else { | ||
60 | sicrl |= MPC834X_SICRL_USB0; | ||
61 | } | ||
62 | } else if (prop && !strcmp(prop, "ulpi")) { | ||
63 | sicrl |= MPC834X_SICRL_USB0; | ||
64 | } else { | ||
65 | printk(KERN_WARNING "834x USB PHY type not supported\n"); | ||
66 | } | ||
67 | port0_is_dr = 1; | ||
68 | of_node_put(np); | ||
69 | } | ||
70 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph"); | ||
71 | if (np) { | ||
72 | sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ | ||
73 | |||
74 | prop = of_get_property(np, "port0", NULL); | ||
75 | if (prop) { | ||
76 | if (port0_is_dr) | ||
77 | printk(KERN_WARNING | ||
78 | "834x USB port0 can't be used by both DR and MPH!\n"); | ||
79 | sicrl |= MPC834X_SICRL_USB0; | ||
80 | } | ||
81 | prop = of_get_property(np, "port1", NULL); | ||
82 | if (prop) { | ||
83 | if (port1_is_dr) | ||
84 | printk(KERN_WARNING | ||
85 | "834x USB port1 can't be used by both DR and MPH!\n"); | ||
86 | sicrl |= MPC834X_SICRL_USB1; | ||
87 | } | ||
88 | of_node_put(np); | ||
89 | } | ||
90 | |||
91 | /* Write back */ | ||
92 | out_be32(immap + MPC83XX_SCCR_OFFS, sccr); | ||
93 | out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); | ||
94 | out_be32(immap + MPC83XX_SICRH_OFFS, sicrh); | ||
95 | |||
96 | iounmap(immap); | ||
97 | return 0; | ||
98 | } | ||
99 | #endif /* CONFIG_MPC834x */ | ||
100 | |||
101 | #ifdef CONFIG_PPC_MPC831x | ||
102 | int mpc831x_usb_cfg(void) | ||
103 | { | ||
104 | u32 temp; | ||
105 | void __iomem *immap, *usb_regs; | ||
106 | struct device_node *np = NULL; | ||
107 | const void *prop; | ||
108 | struct resource res; | ||
109 | int ret = 0; | ||
110 | #ifdef CONFIG_USB_OTG | ||
111 | const void *dr_mode; | ||
112 | #endif | ||
113 | |||
114 | np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); | ||
115 | if (!np) | ||
116 | return -ENODEV; | ||
117 | prop = of_get_property(np, "phy_type", NULL); | ||
118 | |||
119 | /* Map IMMR space for pin and clock settings */ | ||
120 | immap = ioremap(get_immrbase(), 0x1000); | ||
121 | if (!immap) { | ||
122 | of_node_put(np); | ||
123 | return -ENOMEM; | ||
124 | } | ||
125 | |||
126 | /* Configure clock */ | ||
127 | temp = in_be32(immap + MPC83XX_SCCR_OFFS); | ||
128 | temp &= ~MPC83XX_SCCR_USB_MASK; | ||
129 | temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | ||
130 | out_be32(immap + MPC83XX_SCCR_OFFS, temp); | ||
131 | |||
132 | /* Configure pin mux for ULPI. There is no pin mux for UTMI */ | ||
133 | if (!strcmp(prop, "ulpi")) { | ||
134 | temp = in_be32(immap + MPC83XX_SICRL_OFFS); | ||
135 | temp &= ~MPC831X_SICRL_USB_MASK; | ||
136 | temp |= MPC831X_SICRL_USB_ULPI; | ||
137 | out_be32(immap + MPC83XX_SICRL_OFFS, temp); | ||
138 | |||
139 | temp = in_be32(immap + MPC83XX_SICRH_OFFS); | ||
140 | temp &= ~MPC831X_SICRH_USB_MASK; | ||
141 | temp |= MPC831X_SICRH_USB_ULPI; | ||
142 | out_be32(immap + MPC83XX_SICRH_OFFS, temp); | ||
143 | } | ||
144 | |||
145 | iounmap(immap); | ||
146 | |||
147 | /* Map USB SOC space */ | ||
148 | ret = of_address_to_resource(np, 0, &res); | ||
149 | if (ret) { | ||
150 | of_node_put(np); | ||
151 | return ret; | ||
152 | } | ||
153 | usb_regs = ioremap(res.start, res.end - res.start + 1); | ||
154 | |||
155 | /* Using on-chip PHY */ | ||
156 | if (!strcmp(prop, "utmi_wide") || | ||
157 | !strcmp(prop, "utmi")) { | ||
158 | /* Set UTMI_PHY_EN, REFSEL to 48MHZ */ | ||
159 | out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, | ||
160 | CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ); | ||
161 | /* Using external UPLI PHY */ | ||
162 | } else if (!strcmp(prop, "ulpi")) { | ||
163 | /* Set PHY_CLK_SEL to ULPI */ | ||
164 | temp = CONTROL_PHY_CLK_SEL_ULPI; | ||
165 | #ifdef CONFIG_USB_OTG | ||
166 | /* Set OTG_PORT */ | ||
167 | dr_mode = of_get_property(np, "dr_mode", NULL); | ||
168 | if (dr_mode && !strcmp(dr_mode, "otg")) | ||
169 | temp |= CONTROL_OTG_PORT; | ||
170 | #endif /* CONFIG_USB_OTG */ | ||
171 | out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp); | ||
172 | } else { | ||
173 | printk(KERN_WARNING "831x USB PHY type not supported\n"); | ||
174 | ret = -EINVAL; | ||
175 | } | ||
176 | |||
177 | iounmap(usb_regs); | ||
178 | of_node_put(np); | ||
179 | return ret; | ||
180 | } | ||
181 | #endif /* CONFIG_PPC_MPC831x */ | ||
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c index 3e62fcb04c1c..4fe376e9c3b6 100644 --- a/arch/powerpc/platforms/85xx/misc.c +++ b/arch/powerpc/platforms/85xx/misc.c | |||
@@ -13,11 +13,43 @@ | |||
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
16 | #include <asm/io.h> | ||
17 | #include <asm/prom.h> | ||
18 | #include <sysdev/fsl_soc.h> | ||
19 | |||
20 | static __be32 __iomem *rstcr; | ||
16 | 21 | ||
17 | extern void abort(void); | 22 | extern void abort(void); |
18 | 23 | ||
24 | static int __init mpc85xx_rstcr(void) | ||
25 | { | ||
26 | struct device_node *np; | ||
27 | np = of_find_node_by_name(NULL, "global-utilities"); | ||
28 | if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) { | ||
29 | const u32 *prop = of_get_property(np, "reg", NULL); | ||
30 | if (prop) { | ||
31 | /* map reset control register | ||
32 | * 0xE00B0 is offset of reset control register | ||
33 | */ | ||
34 | rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff); | ||
35 | if (!rstcr) | ||
36 | printk (KERN_EMERG "Error: reset control " | ||
37 | "register not mapped!\n"); | ||
38 | } | ||
39 | } else | ||
40 | printk (KERN_INFO "rstcr compatible register does not exist!\n"); | ||
41 | if (np) | ||
42 | of_node_put(np); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | arch_initcall(mpc85xx_rstcr); | ||
47 | |||
19 | void mpc85xx_restart(char *cmd) | 48 | void mpc85xx_restart(char *cmd) |
20 | { | 49 | { |
21 | local_irq_disable(); | 50 | local_irq_disable(); |
51 | if (rstcr) | ||
52 | /* set reset control register */ | ||
53 | out_be32(rstcr, 0x2); /* HRESET_REQ */ | ||
22 | abort(); | 54 | abort(); |
23 | } | 55 | } |
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c index bec84ffe708e..6fb90aab879f 100644 --- a/arch/powerpc/platforms/85xx/mpc8544_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c | |||
@@ -61,24 +61,11 @@ void __init mpc8544_ds_pic_init(void) | |||
61 | return; | 61 | return; |
62 | } | 62 | } |
63 | 63 | ||
64 | /* Alloc mpic structure and per isu has 16 INT entries. */ | ||
65 | mpic = mpic_alloc(np, r.start, | 64 | mpic = mpic_alloc(np, r.start, |
66 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 65 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
67 | 16, 64, " OPENPIC "); | 66 | 0, 256, " OpenPIC "); |
68 | BUG_ON(mpic == NULL); | 67 | BUG_ON(mpic == NULL); |
69 | 68 | ||
70 | /* | ||
71 | * 48 Internal Interrupts | ||
72 | */ | ||
73 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
74 | mpic_assign_isu(mpic, 1, r.start + 0x10400); | ||
75 | mpic_assign_isu(mpic, 2, r.start + 0x10600); | ||
76 | |||
77 | /* | ||
78 | * 16 External interrupts | ||
79 | */ | ||
80 | mpic_assign_isu(mpic, 3, r.start + 0x10000); | ||
81 | |||
82 | mpic_init(mpic); | 69 | mpic_init(mpic); |
83 | 70 | ||
84 | #ifdef CONFIG_PPC_I8259 | 71 | #ifdef CONFIG_PPC_I8259 |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h index 83415db33378..7286ffac2c1d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx.h +++ b/arch/powerpc/platforms/85xx/mpc85xx.h | |||
@@ -15,4 +15,4 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | extern void mpc85xx_restart(char *); | 17 | extern void mpc85xx_restart(char *); |
18 | extern int add_bridge(struct device_node *dev); | 18 | extern int mpc85xx_add_bridge(struct device_node *dev); |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 5d27621f0927..7235f702394c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
@@ -38,13 +38,9 @@ | |||
38 | #include <asm/fs_pd.h> | 38 | #include <asm/fs_pd.h> |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #ifndef CONFIG_PCI | ||
42 | unsigned long isa_io_base = 0; | ||
43 | unsigned long isa_mem_base = 0; | ||
44 | #endif | ||
45 | |||
46 | #ifdef CONFIG_PCI | 41 | #ifdef CONFIG_PCI |
47 | static int mpc85xx_exclude_device(u_char bus, u_char devfn) | 42 | static int mpc85xx_exclude_device(struct pci_controller *hose, |
43 | u_char bus, u_char devfn) | ||
48 | { | 44 | { |
49 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 45 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
50 | return PCIBIOS_DEVICE_NOT_FOUND; | 46 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -91,30 +87,10 @@ static void __init mpc85xx_ads_pic_init(void) | |||
91 | 87 | ||
92 | mpic = mpic_alloc(np, r.start, | 88 | mpic = mpic_alloc(np, r.start, |
93 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 89 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
94 | 4, 0, " OpenPIC "); | 90 | 0, 256, " OpenPIC "); |
95 | BUG_ON(mpic == NULL); | 91 | BUG_ON(mpic == NULL); |
96 | of_node_put(np); | 92 | of_node_put(np); |
97 | 93 | ||
98 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
99 | mpic_assign_isu(mpic, 1, r.start + 0x10280); | ||
100 | mpic_assign_isu(mpic, 2, r.start + 0x10300); | ||
101 | mpic_assign_isu(mpic, 3, r.start + 0x10380); | ||
102 | mpic_assign_isu(mpic, 4, r.start + 0x10400); | ||
103 | mpic_assign_isu(mpic, 5, r.start + 0x10480); | ||
104 | mpic_assign_isu(mpic, 6, r.start + 0x10500); | ||
105 | mpic_assign_isu(mpic, 7, r.start + 0x10580); | ||
106 | |||
107 | /* Unused on this platform (leave room for 8548) */ | ||
108 | mpic_assign_isu(mpic, 8, r.start + 0x10600); | ||
109 | mpic_assign_isu(mpic, 9, r.start + 0x10680); | ||
110 | mpic_assign_isu(mpic, 10, r.start + 0x10700); | ||
111 | mpic_assign_isu(mpic, 11, r.start + 0x10780); | ||
112 | |||
113 | /* External Interrupts */ | ||
114 | mpic_assign_isu(mpic, 12, r.start + 0x10000); | ||
115 | mpic_assign_isu(mpic, 13, r.start + 0x10080); | ||
116 | mpic_assign_isu(mpic, 14, r.start + 0x10100); | ||
117 | |||
118 | mpic_init(mpic); | 94 | mpic_init(mpic); |
119 | 95 | ||
120 | #ifdef CONFIG_CPM2 | 96 | #ifdef CONFIG_CPM2 |
@@ -241,7 +217,7 @@ static void __init mpc85xx_ads_setup_arch(void) | |||
241 | 217 | ||
242 | #ifdef CONFIG_PCI | 218 | #ifdef CONFIG_PCI |
243 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 219 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
244 | add_bridge(np); | 220 | mpc85xx_add_bridge(np); |
245 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 221 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
246 | #endif | 222 | #endif |
247 | } | 223 | } |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 1490eb3ce0d3..50c8d6458362 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c | |||
@@ -47,11 +47,6 @@ | |||
47 | #include <sysdev/fsl_soc.h> | 47 | #include <sysdev/fsl_soc.h> |
48 | #include "mpc85xx.h" | 48 | #include "mpc85xx.h" |
49 | 49 | ||
50 | #ifndef CONFIG_PCI | ||
51 | unsigned long isa_io_base = 0; | ||
52 | unsigned long isa_mem_base = 0; | ||
53 | #endif | ||
54 | |||
55 | static int cds_pci_slot = 2; | 50 | static int cds_pci_slot = 2; |
56 | static volatile u8 *cadmus; | 51 | static volatile u8 *cadmus; |
57 | 52 | ||
@@ -60,15 +55,11 @@ static volatile u8 *cadmus; | |||
60 | #define ARCADIA_HOST_BRIDGE_IDSEL 17 | 55 | #define ARCADIA_HOST_BRIDGE_IDSEL 17 |
61 | #define ARCADIA_2ND_BRIDGE_IDSEL 3 | 56 | #define ARCADIA_2ND_BRIDGE_IDSEL 3 |
62 | 57 | ||
63 | extern int mpc85xx_pci2_busno; | 58 | static int mpc85xx_exclude_device(struct pci_controller *hose, |
64 | 59 | u_char bus, u_char devfn) | |
65 | static int mpc85xx_exclude_device(u_char bus, u_char devfn) | ||
66 | { | 60 | { |
67 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 61 | if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) |
68 | return PCIBIOS_DEVICE_NOT_FOUND; | 62 | return PCIBIOS_DEVICE_NOT_FOUND; |
69 | if (mpc85xx_pci2_busno) | ||
70 | if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0) | ||
71 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
72 | /* We explicitly do not go past the Tundra 320 Bridge */ | 63 | /* We explicitly do not go past the Tundra 320 Bridge */ |
73 | if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) | 64 | if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) |
74 | return PCIBIOS_DEVICE_NOT_FOUND; | 65 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -78,52 +69,44 @@ static int mpc85xx_exclude_device(u_char bus, u_char devfn) | |||
78 | return PCIBIOS_SUCCESSFUL; | 69 | return PCIBIOS_SUCCESSFUL; |
79 | } | 70 | } |
80 | 71 | ||
81 | static void __init mpc85xx_cds_pcibios_fixup(void) | 72 | static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) |
82 | { | 73 | { |
83 | struct pci_dev *dev; | 74 | u_char c; |
84 | u_char c; | 75 | if (dev->vendor == PCI_VENDOR_ID_VIA) { |
85 | 76 | switch (dev->device) { | |
86 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | 77 | case PCI_DEVICE_ID_VIA_82C586_1: |
87 | PCI_DEVICE_ID_VIA_82C586_1, NULL))) { | 78 | /* |
79 | * U-Boot does not set the enable bits | ||
80 | * for the IDE device. Force them on here. | ||
81 | */ | ||
82 | pci_read_config_byte(dev, 0x40, &c); | ||
83 | c |= 0x03; /* IDE: Chip Enable Bits */ | ||
84 | pci_write_config_byte(dev, 0x40, c); | ||
85 | |||
86 | /* | ||
87 | * Since only primary interface works, force the | ||
88 | * IDE function to standard primary IDE interrupt | ||
89 | * w/ 8259 offset | ||
90 | */ | ||
91 | dev->irq = 14; | ||
92 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
93 | break; | ||
88 | /* | 94 | /* |
89 | * U-Boot does not set the enable bits | 95 | * Force legacy USB interrupt routing |
90 | * for the IDE device. Force them on here. | ||
91 | */ | 96 | */ |
92 | pci_read_config_byte(dev, 0x40, &c); | 97 | case PCI_DEVICE_ID_VIA_82C586_2: |
93 | c |= 0x03; /* IDE: Chip Enable Bits */ | 98 | /* There are two USB controllers. |
94 | pci_write_config_byte(dev, 0x40, c); | 99 | * Identify them by functon number |
95 | |||
96 | /* | ||
97 | * Since only primary interface works, force the | ||
98 | * IDE function to standard primary IDE interrupt | ||
99 | * w/ 8259 offset | ||
100 | */ | 100 | */ |
101 | dev->irq = 14; | 101 | if (PCI_FUNC(dev->devfn)) |
102 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | 102 | dev->irq = 11; |
103 | pci_dev_put(dev); | 103 | else |
104 | } | 104 | dev->irq = 10; |
105 | 105 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | |
106 | /* | 106 | default: |
107 | * Force legacy USB interrupt routing | 107 | break; |
108 | */ | 108 | } |
109 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
110 | PCI_DEVICE_ID_VIA_82C586_2, NULL))) { | ||
111 | dev->irq = 10; | ||
112 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); | ||
113 | pci_dev_put(dev); | ||
114 | } | ||
115 | |||
116 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
117 | PCI_DEVICE_ID_VIA_82C586_2, dev))) { | ||
118 | dev->irq = 11; | ||
119 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); | ||
120 | pci_dev_put(dev); | ||
121 | } | 109 | } |
122 | |||
123 | /* Now map all the PCI irqs */ | ||
124 | dev = NULL; | ||
125 | for_each_pci_dev(dev) | ||
126 | pci_read_irq_line(dev); | ||
127 | } | 110 | } |
128 | 111 | ||
129 | #ifdef CONFIG_PPC_I8259 | 112 | #ifdef CONFIG_PPC_I8259 |
@@ -165,33 +148,12 @@ static void __init mpc85xx_cds_pic_init(void) | |||
165 | 148 | ||
166 | mpic = mpic_alloc(np, r.start, | 149 | mpic = mpic_alloc(np, r.start, |
167 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 150 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
168 | 4, 0, " OpenPIC "); | 151 | 0, 256, " OpenPIC "); |
169 | BUG_ON(mpic == NULL); | 152 | BUG_ON(mpic == NULL); |
170 | 153 | ||
171 | /* Return the mpic node */ | 154 | /* Return the mpic node */ |
172 | of_node_put(np); | 155 | of_node_put(np); |
173 | 156 | ||
174 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
175 | mpic_assign_isu(mpic, 1, r.start + 0x10280); | ||
176 | mpic_assign_isu(mpic, 2, r.start + 0x10300); | ||
177 | mpic_assign_isu(mpic, 3, r.start + 0x10380); | ||
178 | mpic_assign_isu(mpic, 4, r.start + 0x10400); | ||
179 | mpic_assign_isu(mpic, 5, r.start + 0x10480); | ||
180 | mpic_assign_isu(mpic, 6, r.start + 0x10500); | ||
181 | mpic_assign_isu(mpic, 7, r.start + 0x10580); | ||
182 | |||
183 | /* Used only for 8548 so far, but no harm in | ||
184 | * allocating them for everyone */ | ||
185 | mpic_assign_isu(mpic, 8, r.start + 0x10600); | ||
186 | mpic_assign_isu(mpic, 9, r.start + 0x10680); | ||
187 | mpic_assign_isu(mpic, 10, r.start + 0x10700); | ||
188 | mpic_assign_isu(mpic, 11, r.start + 0x10780); | ||
189 | |||
190 | /* External Interrupts */ | ||
191 | mpic_assign_isu(mpic, 12, r.start + 0x10000); | ||
192 | mpic_assign_isu(mpic, 13, r.start + 0x10080); | ||
193 | mpic_assign_isu(mpic, 14, r.start + 0x10100); | ||
194 | |||
195 | mpic_init(mpic); | 157 | mpic_init(mpic); |
196 | 158 | ||
197 | #ifdef CONFIG_PPC_I8259 | 159 | #ifdef CONFIG_PPC_I8259 |
@@ -257,9 +219,9 @@ static void __init mpc85xx_cds_setup_arch(void) | |||
257 | 219 | ||
258 | #ifdef CONFIG_PCI | 220 | #ifdef CONFIG_PCI |
259 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 221 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
260 | add_bridge(np); | 222 | mpc85xx_add_bridge(np); |
261 | 223 | ||
262 | ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; | 224 | ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; |
263 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | 225 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
264 | #endif | 226 | #endif |
265 | } | 227 | } |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index e3dddbfe66ff..004b80bd0b84 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
@@ -59,11 +59,6 @@ | |||
59 | #define DBG(fmt...) | 59 | #define DBG(fmt...) |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | #ifndef CONFIG_PCI | ||
63 | unsigned long isa_io_base = 0; | ||
64 | unsigned long isa_mem_base = 0; | ||
65 | #endif | ||
66 | |||
67 | /* ************************************************************************ | 62 | /* ************************************************************************ |
68 | * | 63 | * |
69 | * Setup the architecture | 64 | * Setup the architecture |
@@ -100,7 +95,7 @@ static void __init mpc85xx_mds_setup_arch(void) | |||
100 | 95 | ||
101 | #ifdef CONFIG_PCI | 96 | #ifdef CONFIG_PCI |
102 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | 97 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { |
103 | add_bridge(np); | 98 | mpc85xx_add_bridge(np); |
104 | } | 99 | } |
105 | of_node_put(np); | 100 | of_node_put(np); |
106 | #endif | 101 | #endif |
@@ -181,29 +176,10 @@ static void __init mpc85xx_mds_pic_init(void) | |||
181 | 176 | ||
182 | mpic = mpic_alloc(np, r.start, | 177 | mpic = mpic_alloc(np, r.start, |
183 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 178 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
184 | 4, 0, " OpenPIC "); | 179 | 0, 256, " OpenPIC "); |
185 | BUG_ON(mpic == NULL); | 180 | BUG_ON(mpic == NULL); |
186 | of_node_put(np); | 181 | of_node_put(np); |
187 | 182 | ||
188 | /* Internal Interrupts */ | ||
189 | mpic_assign_isu(mpic, 0, r.start + 0x10200); | ||
190 | mpic_assign_isu(mpic, 1, r.start + 0x10280); | ||
191 | mpic_assign_isu(mpic, 2, r.start + 0x10300); | ||
192 | mpic_assign_isu(mpic, 3, r.start + 0x10380); | ||
193 | mpic_assign_isu(mpic, 4, r.start + 0x10400); | ||
194 | mpic_assign_isu(mpic, 5, r.start + 0x10480); | ||
195 | mpic_assign_isu(mpic, 6, r.start + 0x10500); | ||
196 | mpic_assign_isu(mpic, 7, r.start + 0x10580); | ||
197 | mpic_assign_isu(mpic, 8, r.start + 0x10600); | ||
198 | mpic_assign_isu(mpic, 9, r.start + 0x10680); | ||
199 | mpic_assign_isu(mpic, 10, r.start + 0x10700); | ||
200 | mpic_assign_isu(mpic, 11, r.start + 0x10780); | ||
201 | |||
202 | /* External Interrupts */ | ||
203 | mpic_assign_isu(mpic, 12, r.start + 0x10000); | ||
204 | mpic_assign_isu(mpic, 13, r.start + 0x10080); | ||
205 | mpic_assign_isu(mpic, 14, r.start + 0x10100); | ||
206 | |||
207 | mpic_init(mpic); | 183 | mpic_init(mpic); |
208 | 184 | ||
209 | #ifdef CONFIG_QUICC_ENGINE | 185 | #ifdef CONFIG_QUICC_ENGINE |
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c index 48f17e23d771..8118417b7364 100644 --- a/arch/powerpc/platforms/85xx/pci.c +++ b/arch/powerpc/platforms/85xx/pci.c | |||
@@ -33,10 +33,8 @@ | |||
33 | #define DBG(x...) | 33 | #define DBG(x...) |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | int mpc85xx_pci2_busno = 0; | ||
37 | |||
38 | #ifdef CONFIG_PCI | 36 | #ifdef CONFIG_PCI |
39 | int __init add_bridge(struct device_node *dev) | 37 | int __init mpc85xx_add_bridge(struct device_node *dev) |
40 | { | 38 | { |
41 | int len; | 39 | int len; |
42 | struct pci_controller *hose; | 40 | struct pci_controller *hose; |
@@ -57,11 +55,10 @@ int __init add_bridge(struct device_node *dev) | |||
57 | " bus 0\n", dev->full_name); | 55 | " bus 0\n", dev->full_name); |
58 | } | 56 | } |
59 | 57 | ||
60 | hose = pcibios_alloc_controller(); | 58 | pci_assign_all_buses = 1; |
59 | hose = pcibios_alloc_controller(dev); | ||
61 | if (!hose) | 60 | if (!hose) |
62 | return -ENOMEM; | 61 | return -ENOMEM; |
63 | hose->arch_data = dev; | ||
64 | hose->set_cfg_type = 1; | ||
65 | 62 | ||
66 | hose->first_busno = bus_range ? bus_range[0] : 0; | 63 | hose->first_busno = bus_range ? bus_range[0] : 0; |
67 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 64 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
@@ -74,8 +71,6 @@ int __init add_bridge(struct device_node *dev) | |||
74 | if ((rsrc.start & 0xfffff) == 0x9000) { | 71 | if ((rsrc.start & 0xfffff) == 0x9000) { |
75 | setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); | 72 | setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); |
76 | primary = 0; | 73 | primary = 0; |
77 | hose->bus_offset = hose->first_busno; | ||
78 | mpc85xx_pci2_busno = hose->first_busno; | ||
79 | } | 74 | } |
80 | 75 | ||
81 | printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. " | 76 | printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. " |
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index d1bcff500464..0faebfdc1596 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | choice | 1 | choice |
2 | prompt "Machine Type" | 2 | prompt "86xx Board Type" |
3 | depends on PPC_86xx | 3 | depends on PPC_86xx |
4 | default MPC8641_HPCN | 4 | default MPC8641_HPCN |
5 | 5 | ||
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h index 2834462590b8..23f7ed2a7f88 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx.h +++ b/arch/powerpc/platforms/86xx/mpc86xx.h | |||
@@ -15,15 +15,10 @@ | |||
15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). | 15 | * mpc86xx_* files. Mostly for use by mpc86xx_setup(). |
16 | */ | 16 | */ |
17 | 17 | ||
18 | extern int add_bridge(struct device_node *dev); | 18 | extern int mpc86xx_add_bridge(struct device_node *dev); |
19 | 19 | ||
20 | extern int mpc86xx_exclude_device(u_char bus, u_char devfn); | 20 | extern int mpc86xx_exclude_device(struct pci_controller *hose, |
21 | 21 | u_char bus, u_char devfn); | |
22 | extern void setup_indirect_pcie(struct pci_controller *hose, | ||
23 | u32 cfg_addr, u32 cfg_data); | ||
24 | extern void setup_indirect_pcie_nomap(struct pci_controller *hose, | ||
25 | void __iomem *cfg_addr, | ||
26 | void __iomem *cfg_data); | ||
27 | 22 | ||
28 | extern void __init mpc86xx_smp_init(void); | 23 | extern void __init mpc86xx_smp_init(void); |
29 | 24 | ||
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 1051702c8d4f..5b01ec7c13dc 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | |||
@@ -44,13 +44,6 @@ | |||
44 | #define DBG(fmt...) do { } while(0) | 44 | #define DBG(fmt...) do { } while(0) |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #ifndef CONFIG_PCI | ||
48 | unsigned long isa_io_base = 0; | ||
49 | unsigned long isa_mem_base = 0; | ||
50 | unsigned long pci_dram_offset = 0; | ||
51 | #endif | ||
52 | |||
53 | |||
54 | #ifdef CONFIG_PCI | 47 | #ifdef CONFIG_PCI |
55 | static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc) | 48 | static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc) |
56 | { | 49 | { |
@@ -81,22 +74,9 @@ mpc86xx_hpcn_init_irq(void) | |||
81 | /* Alloc mpic structure and per isu has 16 INT entries. */ | 74 | /* Alloc mpic structure and per isu has 16 INT entries. */ |
82 | mpic1 = mpic_alloc(np, res.start, | 75 | mpic1 = mpic_alloc(np, res.start, |
83 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | 76 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, |
84 | 16, NR_IRQS - 4, | 77 | 0, 256, " MPIC "); |
85 | " MPIC "); | ||
86 | BUG_ON(mpic1 == NULL); | 78 | BUG_ON(mpic1 == NULL); |
87 | 79 | ||
88 | mpic_assign_isu(mpic1, 0, res.start + 0x10000); | ||
89 | |||
90 | /* 48 Internal Interrupts */ | ||
91 | mpic_assign_isu(mpic1, 1, res.start + 0x10200); | ||
92 | mpic_assign_isu(mpic1, 2, res.start + 0x10400); | ||
93 | mpic_assign_isu(mpic1, 3, res.start + 0x10600); | ||
94 | |||
95 | /* 16 External interrupts | ||
96 | * Moving them from [0 - 15] to [64 - 79] | ||
97 | */ | ||
98 | mpic_assign_isu(mpic1, 4, res.start + 0x10000); | ||
99 | |||
100 | mpic_init(mpic1); | 80 | mpic_init(mpic1); |
101 | 81 | ||
102 | #ifdef CONFIG_PCI | 82 | #ifdef CONFIG_PCI |
@@ -319,6 +299,7 @@ static void __devinit quirk_uli5229(struct pci_dev *dev) | |||
319 | { | 299 | { |
320 | unsigned short temp; | 300 | unsigned short temp; |
321 | pci_write_config_word(dev, 0x04, 0x0405); | 301 | pci_write_config_word(dev, 0x04, 0x0405); |
302 | dev->class &= ~0x5; | ||
322 | pci_read_config_word(dev, 0x4a, &temp); | 303 | pci_read_config_word(dev, 0x4a, &temp); |
323 | temp |= 0x1000; | 304 | temp |= 0x1000; |
324 | pci_write_config_word(dev, 0x4a, temp); | 305 | pci_write_config_word(dev, 0x4a, temp); |
@@ -364,9 +345,7 @@ mpc86xx_hpcn_setup_arch(void) | |||
364 | 345 | ||
365 | #ifdef CONFIG_PCI | 346 | #ifdef CONFIG_PCI |
366 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 347 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
367 | add_bridge(np); | 348 | mpc86xx_add_bridge(np); |
368 | |||
369 | ppc_md.pci_exclude_device = mpc86xx_exclude_device; | ||
370 | #endif | 349 | #endif |
371 | 350 | ||
372 | printk("MPC86xx HPCN board from Freescale Semiconductor\n"); | 351 | printk("MPC86xx HPCN board from Freescale Semiconductor\n"); |
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c index 8235c562661f..73cd5b05a84e 100644 --- a/arch/powerpc/platforms/86xx/pci.c +++ b/arch/powerpc/platforms/86xx/pci.c | |||
@@ -122,7 +122,6 @@ static void __init | |||
122 | mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) | 122 | mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) |
123 | { | 123 | { |
124 | u16 cmd; | 124 | u16 cmd; |
125 | unsigned int temps; | ||
126 | 125 | ||
127 | DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", | 126 | DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", |
128 | pcie_offset, pcie_size); | 127 | pcie_offset, pcie_size); |
@@ -133,22 +132,49 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) | |||
133 | early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); | 132 | early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); |
134 | 133 | ||
135 | early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); | 134 | early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); |
136 | |||
137 | /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ | ||
138 | early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); | ||
139 | temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); | ||
140 | early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); | ||
141 | } | 135 | } |
142 | 136 | ||
143 | int mpc86xx_exclude_device(u_char bus, u_char devfn) | 137 | static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev) |
144 | { | 138 | { |
145 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 139 | struct resource *res; |
146 | return PCIBIOS_DEVICE_NOT_FOUND; | 140 | int i, res_idx = PCI_BRIDGE_RESOURCES; |
141 | struct pci_controller *hose; | ||
147 | 142 | ||
148 | return PCIBIOS_SUCCESSFUL; | 143 | /* |
144 | * Make the bridge be transparent. | ||
145 | */ | ||
146 | dev->transparent = 1; | ||
147 | |||
148 | hose = pci_bus_to_host(dev->bus); | ||
149 | if (!hose) { | ||
150 | printk(KERN_ERR "Can't find hose for bus %d\n", | ||
151 | dev->bus->number); | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | if (hose->io_resource.flags) { | ||
156 | res = &dev->resource[res_idx++]; | ||
157 | res->start = hose->io_resource.start; | ||
158 | res->end = hose->io_resource.end; | ||
159 | res->flags = hose->io_resource.flags; | ||
160 | } | ||
161 | |||
162 | for (i = 0; i < 3; i++) { | ||
163 | res = &dev->resource[res_idx + i]; | ||
164 | res->start = hose->mem_resources[i].start; | ||
165 | res->end = hose->mem_resources[i].end; | ||
166 | res->flags = hose->mem_resources[i].flags; | ||
167 | } | ||
149 | } | 168 | } |
150 | 169 | ||
151 | int __init add_bridge(struct device_node *dev) | 170 | |
171 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent); | ||
172 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent); | ||
173 | |||
174 | #define PCIE_LTSSM 0x404 /* PCIe Link Training and Status */ | ||
175 | #define PCIE_LTSSM_L0 0x16 /* L0 state */ | ||
176 | |||
177 | int __init mpc86xx_add_bridge(struct device_node *dev) | ||
152 | { | 178 | { |
153 | int len; | 179 | int len; |
154 | struct pci_controller *hose; | 180 | struct pci_controller *hose; |
@@ -156,6 +182,7 @@ int __init add_bridge(struct device_node *dev) | |||
156 | const int *bus_range; | 182 | const int *bus_range; |
157 | int has_address = 0; | 183 | int has_address = 0; |
158 | int primary = 0; | 184 | int primary = 0; |
185 | u16 val; | ||
159 | 186 | ||
160 | DBG("Adding PCIE host bridge %s\n", dev->full_name); | 187 | DBG("Adding PCIE host bridge %s\n", dev->full_name); |
161 | 188 | ||
@@ -168,17 +195,23 @@ int __init add_bridge(struct device_node *dev) | |||
168 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 195 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
169 | " bus 0\n", dev->full_name); | 196 | " bus 0\n", dev->full_name); |
170 | 197 | ||
171 | hose = pcibios_alloc_controller(); | 198 | pci_assign_all_buses = 1; |
199 | hose = pcibios_alloc_controller(dev); | ||
172 | if (!hose) | 200 | if (!hose) |
173 | return -ENOMEM; | 201 | return -ENOMEM; |
174 | hose->arch_data = dev; | ||
175 | hose->set_cfg_type = 1; | ||
176 | 202 | ||
177 | /* last_busno = 0xfe cause by MPC8641 PCIE bug */ | 203 | hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG | |
204 | PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; | ||
205 | |||
178 | hose->first_busno = bus_range ? bus_range[0] : 0x0; | 206 | hose->first_busno = bus_range ? bus_range[0] : 0x0; |
179 | hose->last_busno = bus_range ? bus_range[1] : 0xfe; | 207 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
208 | |||
209 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4); | ||
180 | 210 | ||
181 | setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); | 211 | /* Probe the hose link training status */ |
212 | early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val); | ||
213 | if (val < PCIE_LTSSM_L0) | ||
214 | return -ENXIO; | ||
182 | 215 | ||
183 | /* Setup the PCIE host controller. */ | 216 | /* Setup the PCIE host controller. */ |
184 | mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); | 217 | mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); |
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 0901dbada350..f1693550c70c 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/root_dev.h> | 32 | #include <linux/root_dev.h> |
33 | #include <linux/time.h> | 33 | #include <linux/time.h> |
34 | #include <linux/rtc.h> | 34 | #include <linux/rtc.h> |
35 | #include <linux/fsl_devices.h> | ||
35 | 36 | ||
36 | #include <asm/mmu.h> | 37 | #include <asm/mmu.h> |
37 | #include <asm/reg.h> | 38 | #include <asm/reg.h> |
@@ -49,6 +50,10 @@ | |||
49 | 50 | ||
50 | #include "sysdev/mpc8xx_pic.h" | 51 | #include "sysdev/mpc8xx_pic.h" |
51 | 52 | ||
53 | #ifdef CONFIG_PCMCIA_M8XX | ||
54 | struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | ||
55 | #endif | ||
56 | |||
52 | void m8xx_calibrate_decr(void); | 57 | void m8xx_calibrate_decr(void); |
53 | extern void m8xx_wdt_handler_install(bd_t *bp); | 58 | extern void m8xx_wdt_handler_install(bd_t *bp); |
54 | extern int cpm_pic_init(void); | 59 | extern int cpm_pic_init(void); |
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c36e475d93dc..5a808d611ae3 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/fs_enet_pd.h> | 23 | #include <linux/fs_enet_pd.h> |
24 | #include <linux/fs_uart_pd.h> | 24 | #include <linux/fs_uart_pd.h> |
25 | #include <linux/fsl_devices.h> | ||
25 | #include <linux/mii.h> | 26 | #include <linux/mii.h> |
26 | 27 | ||
27 | #include <asm/delay.h> | 28 | #include <asm/delay.h> |
@@ -39,7 +40,7 @@ | |||
39 | #include <asm/prom.h> | 40 | #include <asm/prom.h> |
40 | 41 | ||
41 | extern void cpm_reset(void); | 42 | extern void cpm_reset(void); |
42 | extern void mpc8xx_show_cpuinfo(struct seq_file*); | 43 | extern void mpc8xx_show_cpuinfo(struct seq_file *); |
43 | extern void mpc8xx_restart(char *cmd); | 44 | extern void mpc8xx_restart(char *cmd); |
44 | extern void mpc8xx_calibrate_decr(void); | 45 | extern void mpc8xx_calibrate_decr(void); |
45 | extern int mpc8xx_set_rtc_time(struct rtc_time *tm); | 46 | extern int mpc8xx_set_rtc_time(struct rtc_time *tm); |
@@ -47,9 +48,73 @@ extern void mpc8xx_get_rtc_time(struct rtc_time *tm); | |||
47 | extern void m8xx_pic_init(void); | 48 | extern void m8xx_pic_init(void); |
48 | extern unsigned int mpc8xx_get_irq(void); | 49 | extern unsigned int mpc8xx_get_irq(void); |
49 | 50 | ||
50 | static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); | 51 | static void init_smc1_uart_ioports(struct fs_uart_platform_info *fpi); |
51 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); | 52 | static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi); |
52 | static void init_scc3_ioports(struct fs_platform_info* ptr); | 53 | static void init_scc3_ioports(struct fs_platform_info *ptr); |
54 | |||
55 | #ifdef CONFIG_PCMCIA_M8XX | ||
56 | static void pcmcia_hw_setup(int slot, int enable) | ||
57 | { | ||
58 | unsigned *bcsr_io; | ||
59 | |||
60 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
61 | if (enable) | ||
62 | clrbits32(bcsr_io, BCSR1_PCCEN); | ||
63 | else | ||
64 | setbits32(bcsr_io, BCSR1_PCCEN); | ||
65 | |||
66 | iounmap(bcsr_io); | ||
67 | } | ||
68 | |||
69 | static int pcmcia_set_voltage(int slot, int vcc, int vpp) | ||
70 | { | ||
71 | u32 reg = 0; | ||
72 | unsigned *bcsr_io; | ||
73 | |||
74 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
75 | |||
76 | switch (vcc) { | ||
77 | case 0: | ||
78 | break; | ||
79 | case 33: | ||
80 | reg |= BCSR1_PCCVCC0; | ||
81 | break; | ||
82 | case 50: | ||
83 | reg |= BCSR1_PCCVCC1; | ||
84 | break; | ||
85 | default: | ||
86 | return 1; | ||
87 | } | ||
88 | |||
89 | switch (vpp) { | ||
90 | case 0: | ||
91 | break; | ||
92 | case 33: | ||
93 | case 50: | ||
94 | if (vcc == vpp) | ||
95 | reg |= BCSR1_PCCVPP1; | ||
96 | else | ||
97 | return 1; | ||
98 | break; | ||
99 | case 120: | ||
100 | if ((vcc == 33) || (vcc == 50)) | ||
101 | reg |= BCSR1_PCCVPP0; | ||
102 | else | ||
103 | return 1; | ||
104 | default: | ||
105 | return 1; | ||
106 | } | ||
107 | |||
108 | /* first, turn off all power */ | ||
109 | clrbits32(bcsr_io, 0x00610000); | ||
110 | |||
111 | /* enable new powersettings */ | ||
112 | setbits32(bcsr_io, reg); | ||
113 | |||
114 | iounmap(bcsr_io); | ||
115 | return 0; | ||
116 | } | ||
117 | #endif | ||
53 | 118 | ||
54 | void __init mpc885ads_board_setup(void) | 119 | void __init mpc885ads_board_setup(void) |
55 | { | 120 | { |
@@ -62,7 +127,7 @@ void __init mpc885ads_board_setup(void) | |||
62 | #endif | 127 | #endif |
63 | 128 | ||
64 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | 129 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); |
65 | cp = (cpm8xx_t *)immr_map(im_cpm); | 130 | cp = (cpm8xx_t *) immr_map(im_cpm); |
66 | 131 | ||
67 | if (bcsr_io == NULL) { | 132 | if (bcsr_io == NULL) { |
68 | printk(KERN_CRIT "Could not remap BCSR\n"); | 133 | printk(KERN_CRIT "Could not remap BCSR\n"); |
@@ -75,13 +140,13 @@ void __init mpc885ads_board_setup(void) | |||
75 | out_8(&(cp->cp_smc[0].smc_smcm), tmpval8); | 140 | out_8(&(cp->cp_smc[0].smc_smcm), tmpval8); |
76 | clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN); /* brg1 */ | 141 | clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN); /* brg1 */ |
77 | #else | 142 | #else |
78 | setbits32(bcsr_io,BCSR1_RS232EN_1); | 143 | setbits32(bcsr_io, BCSR1_RS232EN_1); |
79 | out_be16(&cp->cp_smc[0].smc_smcmr, 0); | 144 | out_be16(&cp->cp_smc[0].smc_smcmr, 0); |
80 | out_8(&cp->cp_smc[0].smc_smce, 0); | 145 | out_8(&cp->cp_smc[0].smc_smce, 0); |
81 | #endif | 146 | #endif |
82 | 147 | ||
83 | #ifdef CONFIG_SERIAL_CPM_SMC2 | 148 | #ifdef CONFIG_SERIAL_CPM_SMC2 |
84 | clrbits32(bcsr_io,BCSR1_RS232EN_2); | 149 | clrbits32(bcsr_io, BCSR1_RS232EN_2); |
85 | clrbits32(&cp->cp_simode, 0xe0000000 >> 1); | 150 | clrbits32(&cp->cp_simode, 0xe0000000 >> 1); |
86 | setbits32(&cp->cp_simode, 0x20000000 >> 1); /* brg2 */ | 151 | setbits32(&cp->cp_simode, 0x20000000 >> 1); /* brg2 */ |
87 | tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX); | 152 | tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX); |
@@ -90,7 +155,7 @@ void __init mpc885ads_board_setup(void) | |||
90 | 155 | ||
91 | init_smc2_uart_ioports(0); | 156 | init_smc2_uart_ioports(0); |
92 | #else | 157 | #else |
93 | setbits32(bcsr_io,BCSR1_RS232EN_2); | 158 | setbits32(bcsr_io, BCSR1_RS232EN_2); |
94 | out_be16(&cp->cp_smc[1].smc_smcmr, 0); | 159 | out_be16(&cp->cp_smc[1].smc_smcmr, 0); |
95 | out_8(&cp->cp_smc[1].smc_smce, 0); | 160 | out_8(&cp->cp_smc[1].smc_smce, 0); |
96 | #endif | 161 | #endif |
@@ -99,29 +164,34 @@ void __init mpc885ads_board_setup(void) | |||
99 | 164 | ||
100 | #ifdef CONFIG_FS_ENET | 165 | #ifdef CONFIG_FS_ENET |
101 | /* use MDC for MII (common) */ | 166 | /* use MDC for MII (common) */ |
102 | io_port = (iop8xx_t*)immr_map(im_ioport); | 167 | io_port = (iop8xx_t *) immr_map(im_ioport); |
103 | setbits16(&io_port->iop_pdpar, 0x0080); | 168 | setbits16(&io_port->iop_pdpar, 0x0080); |
104 | clrbits16(&io_port->iop_pddir, 0x0080); | 169 | clrbits16(&io_port->iop_pddir, 0x0080); |
105 | 170 | ||
106 | bcsr_io = ioremap(BCSR5, sizeof(unsigned long)); | 171 | bcsr_io = ioremap(BCSR5, sizeof(unsigned long)); |
107 | clrbits32(bcsr_io,BCSR5_MII1_EN); | 172 | clrbits32(bcsr_io, BCSR5_MII1_EN); |
108 | clrbits32(bcsr_io,BCSR5_MII1_RST); | 173 | clrbits32(bcsr_io, BCSR5_MII1_RST); |
109 | #ifndef CONFIG_FC_ENET_HAS_SCC | 174 | #ifndef CONFIG_FC_ENET_HAS_SCC |
110 | clrbits32(bcsr_io,BCSR5_MII2_EN); | 175 | clrbits32(bcsr_io, BCSR5_MII2_EN); |
111 | clrbits32(bcsr_io,BCSR5_MII2_RST); | 176 | clrbits32(bcsr_io, BCSR5_MII2_RST); |
112 | 177 | ||
113 | #endif | 178 | #endif |
114 | iounmap(bcsr_io); | 179 | iounmap(bcsr_io); |
115 | immr_unmap(io_port); | 180 | immr_unmap(io_port); |
116 | 181 | ||
117 | #endif | 182 | #endif |
118 | } | ||
119 | 183 | ||
184 | #ifdef CONFIG_PCMCIA_M8XX | ||
185 | /*Set up board specific hook-ups */ | ||
186 | m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; | ||
187 | m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; | ||
188 | #endif | ||
189 | } | ||
120 | 190 | ||
121 | static void init_fec1_ioports(struct fs_platform_info* ptr) | 191 | static void init_fec1_ioports(struct fs_platform_info *ptr) |
122 | { | 192 | { |
123 | cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm); | 193 | cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm); |
124 | iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport); | 194 | iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport); |
125 | 195 | ||
126 | /* configure FEC1 pins */ | 196 | /* configure FEC1 pins */ |
127 | setbits16(&io_port->iop_papar, 0xf830); | 197 | setbits16(&io_port->iop_papar, 0xf830); |
@@ -143,11 +213,10 @@ static void init_fec1_ioports(struct fs_platform_info* ptr) | |||
143 | immr_unmap(cp); | 213 | immr_unmap(cp); |
144 | } | 214 | } |
145 | 215 | ||
146 | 216 | static void init_fec2_ioports(struct fs_platform_info *ptr) | |
147 | static void init_fec2_ioports(struct fs_platform_info* ptr) | ||
148 | { | 217 | { |
149 | cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm); | 218 | cpm8xx_t *cp = (cpm8xx_t *) immr_map(im_cpm); |
150 | iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport); | 219 | iop8xx_t *io_port = (iop8xx_t *) immr_map(im_ioport); |
151 | 220 | ||
152 | /* configure FEC2 pins */ | 221 | /* configure FEC2 pins */ |
153 | setbits32(&cp->cp_pepar, 0x0003fffc); | 222 | setbits32(&cp->cp_pepar, 0x0003fffc); |
@@ -177,15 +246,15 @@ void init_fec_ioports(struct fs_platform_info *fpi) | |||
177 | } | 246 | } |
178 | } | 247 | } |
179 | 248 | ||
180 | static void init_scc3_ioports(struct fs_platform_info* fpi) | 249 | static void init_scc3_ioports(struct fs_platform_info *fpi) |
181 | { | 250 | { |
182 | unsigned *bcsr_io; | 251 | unsigned *bcsr_io; |
183 | iop8xx_t *io_port; | 252 | iop8xx_t *io_port; |
184 | cpm8xx_t *cp; | 253 | cpm8xx_t *cp; |
185 | 254 | ||
186 | bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE); | 255 | bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE); |
187 | io_port = (iop8xx_t *)immr_map(im_ioport); | 256 | io_port = (iop8xx_t *) immr_map(im_ioport); |
188 | cp = (cpm8xx_t *)immr_map(im_cpm); | 257 | cp = (cpm8xx_t *) immr_map(im_cpm); |
189 | 258 | ||
190 | if (bcsr_io == NULL) { | 259 | if (bcsr_io == NULL) { |
191 | printk(KERN_CRIT "Could not remap BCSR\n"); | 260 | printk(KERN_CRIT "Could not remap BCSR\n"); |
@@ -194,9 +263,9 @@ static void init_scc3_ioports(struct fs_platform_info* fpi) | |||
194 | 263 | ||
195 | /* Enable the PHY. | 264 | /* Enable the PHY. |
196 | */ | 265 | */ |
197 | clrbits32(bcsr_io+4, BCSR4_ETH10_RST); | 266 | clrbits32(bcsr_io + 4, BCSR4_ETH10_RST); |
198 | udelay(1000); | 267 | udelay(1000); |
199 | setbits32(bcsr_io+4, BCSR4_ETH10_RST); | 268 | setbits32(bcsr_io + 4, BCSR4_ETH10_RST); |
200 | /* Configure port A pins for Txd and Rxd. | 269 | /* Configure port A pins for Txd and Rxd. |
201 | */ | 270 | */ |
202 | setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD); | 271 | setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD); |
@@ -212,8 +281,7 @@ static void init_scc3_ioports(struct fs_platform_info* fpi) | |||
212 | */ | 281 | */ |
213 | setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK); | 282 | setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK); |
214 | clrbits32(&cp->cp_pepar, PE_ENET_TENA); | 283 | clrbits32(&cp->cp_pepar, PE_ENET_TENA); |
215 | clrbits32(&cp->cp_pedir, | 284 | clrbits32(&cp->cp_pedir, PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA); |
216 | PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA); | ||
217 | clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK); | 285 | clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK); |
218 | setbits32(&cp->cp_peso, PE_ENET_TENA); | 286 | setbits32(&cp->cp_peso, PE_ENET_TENA); |
219 | 287 | ||
@@ -237,7 +305,7 @@ static void init_scc3_ioports(struct fs_platform_info* fpi) | |||
237 | clrbits32(&cp->cp_pedir, PE_ENET_TENA); | 305 | clrbits32(&cp->cp_pedir, PE_ENET_TENA); |
238 | setbits32(&cp->cp_peso, PE_ENET_TENA); | 306 | setbits32(&cp->cp_peso, PE_ENET_TENA); |
239 | 307 | ||
240 | setbits32(bcsr_io+4, BCSR1_ETHEN); | 308 | setbits32(bcsr_io + 4, BCSR1_ETHEN); |
241 | iounmap(bcsr_io); | 309 | iounmap(bcsr_io); |
242 | immr_unmap(io_port); | 310 | immr_unmap(io_port); |
243 | immr_unmap(cp); | 311 | immr_unmap(cp); |
@@ -257,50 +325,48 @@ void init_scc_ioports(struct fs_platform_info *fpi) | |||
257 | } | 325 | } |
258 | } | 326 | } |
259 | 327 | ||
260 | 328 | static void init_smc1_uart_ioports(struct fs_uart_platform_info *ptr) | |
261 | |||
262 | static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr) | ||
263 | { | 329 | { |
264 | unsigned *bcsr_io; | 330 | unsigned *bcsr_io; |
265 | cpm8xx_t *cp; | 331 | cpm8xx_t *cp; |
266 | 332 | ||
267 | cp = (cpm8xx_t *)immr_map(im_cpm); | 333 | cp = (cpm8xx_t *) immr_map(im_cpm); |
268 | setbits32(&cp->cp_pepar, 0x000000c0); | 334 | setbits32(&cp->cp_pepar, 0x000000c0); |
269 | clrbits32(&cp->cp_pedir, 0x000000c0); | 335 | clrbits32(&cp->cp_pedir, 0x000000c0); |
270 | clrbits32(&cp->cp_peso, 0x00000040); | 336 | clrbits32(&cp->cp_peso, 0x00000040); |
271 | setbits32(&cp->cp_peso, 0x00000080); | 337 | setbits32(&cp->cp_peso, 0x00000080); |
272 | immr_unmap(cp); | 338 | immr_unmap(cp); |
273 | 339 | ||
274 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | 340 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); |
275 | 341 | ||
276 | if (bcsr_io == NULL) { | 342 | if (bcsr_io == NULL) { |
277 | printk(KERN_CRIT "Could not remap BCSR1\n"); | 343 | printk(KERN_CRIT "Could not remap BCSR1\n"); |
278 | return; | 344 | return; |
279 | } | 345 | } |
280 | clrbits32(bcsr_io,BCSR1_RS232EN_1); | 346 | clrbits32(bcsr_io, BCSR1_RS232EN_1); |
281 | iounmap(bcsr_io); | 347 | iounmap(bcsr_io); |
282 | } | 348 | } |
283 | 349 | ||
284 | static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi) | 350 | static void init_smc2_uart_ioports(struct fs_uart_platform_info *fpi) |
285 | { | 351 | { |
286 | unsigned *bcsr_io; | 352 | unsigned *bcsr_io; |
287 | cpm8xx_t *cp; | 353 | cpm8xx_t *cp; |
288 | 354 | ||
289 | cp = (cpm8xx_t *)immr_map(im_cpm); | 355 | cp = (cpm8xx_t *) immr_map(im_cpm); |
290 | setbits32(&cp->cp_pepar, 0x00000c00); | 356 | setbits32(&cp->cp_pepar, 0x00000c00); |
291 | clrbits32(&cp->cp_pedir, 0x00000c00); | 357 | clrbits32(&cp->cp_pedir, 0x00000c00); |
292 | clrbits32(&cp->cp_peso, 0x00000400); | 358 | clrbits32(&cp->cp_peso, 0x00000400); |
293 | setbits32(&cp->cp_peso, 0x00000800); | 359 | setbits32(&cp->cp_peso, 0x00000800); |
294 | immr_unmap(cp); | 360 | immr_unmap(cp); |
295 | 361 | ||
296 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | 362 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); |
297 | 363 | ||
298 | if (bcsr_io == NULL) { | 364 | if (bcsr_io == NULL) { |
299 | printk(KERN_CRIT "Could not remap BCSR1\n"); | 365 | printk(KERN_CRIT "Could not remap BCSR1\n"); |
300 | return; | 366 | return; |
301 | } | 367 | } |
302 | clrbits32(bcsr_io,BCSR1_RS232EN_2); | 368 | clrbits32(bcsr_io, BCSR1_RS232EN_2); |
303 | iounmap(bcsr_io); | 369 | iounmap(bcsr_io); |
304 | } | 370 | } |
305 | 371 | ||
306 | void init_smc_ioports(struct fs_uart_platform_info *data) | 372 | void init_smc_ioports(struct fs_uart_platform_info *data) |
@@ -373,15 +439,11 @@ static int __init mpc885ads_probe(void) | |||
373 | return 1; | 439 | return 1; |
374 | } | 440 | } |
375 | 441 | ||
376 | define_machine(mpc885_ads) { | 442 | define_machine(mpc885_ads) |
377 | .name = "MPC885 ADS", | 443 | { |
378 | .probe = mpc885ads_probe, | 444 | .name = "MPC885 ADS",.probe = mpc885ads_probe,.setup_arch = |
379 | .setup_arch = mpc885ads_setup_arch, | 445 | mpc885ads_setup_arch,.init_IRQ = |
380 | .init_IRQ = m8xx_pic_init, | 446 | m8xx_pic_init,.show_cpuinfo = mpc8xx_show_cpuinfo,.get_irq = |
381 | .show_cpuinfo = mpc8xx_show_cpuinfo, | 447 | mpc8xx_get_irq,.restart = mpc8xx_restart,.calibrate_decr = |
382 | .get_irq = mpc8xx_get_irq, | 448 | mpc8xx_calibrate_decr,.set_rtc_time = |
383 | .restart = mpc8xx_restart, | 449 | mpc8xx_set_rtc_time,.get_rtc_time = mpc8xx_get_rtc_time,}; |
384 | .calibrate_decr = mpc8xx_calibrate_decr, | ||
385 | .set_rtc_time = mpc8xx_set_rtc_time, | ||
386 | .get_rtc_time = mpc8xx_get_rtc_time, | ||
387 | }; | ||
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 361acfa2894c..33545d352e92 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -2,7 +2,7 @@ menu "Platform support" | |||
2 | 2 | ||
3 | choice | 3 | choice |
4 | prompt "Machine type" | 4 | prompt "Machine type" |
5 | depends on PPC64 || CLASSIC32 | 5 | depends on PPC64 || 6xx |
6 | default PPC_MULTIPLATFORM | 6 | default PPC_MULTIPLATFORM |
7 | 7 | ||
8 | config PPC_MULTIPLATFORM | 8 | config PPC_MULTIPLATFORM |
@@ -16,15 +16,30 @@ config EMBEDDED6xx | |||
16 | bool "Embedded 6xx/7xx/7xxx-based board" | 16 | bool "Embedded 6xx/7xx/7xxx-based board" |
17 | depends on PPC32 && (BROKEN||BROKEN_ON_SMP) | 17 | depends on PPC32 && (BROKEN||BROKEN_ON_SMP) |
18 | 18 | ||
19 | config APUS | 19 | config PPC_82xx |
20 | bool "Amiga-APUS" | 20 | bool "Freescale 82xx" |
21 | depends on PPC32 && BROKEN | 21 | depends on 6xx |
22 | |||
23 | config PPC_83xx | ||
24 | bool "Freescale 83xx" | ||
25 | depends on 6xx | ||
26 | select FSL_SOC | ||
27 | select 83xx | ||
28 | select WANT_DEVICE_TREE | ||
29 | |||
30 | config PPC_86xx | ||
31 | bool "Freescale 86xx" | ||
32 | depends on 6xx | ||
33 | select FSL_SOC | ||
34 | select ALTIVEC | ||
22 | help | 35 | help |
23 | Select APUS if configuring for a PowerUP Amiga. | 36 | The Freescale E600 SoCs have 74xx cores. |
24 | More information is available at: | ||
25 | <http://linux-apus.sourceforge.net/>. | ||
26 | endchoice | 37 | endchoice |
27 | 38 | ||
39 | config CLASSIC32 | ||
40 | def_bool y | ||
41 | depends on 6xx && PPC_MULTIPLATFORM | ||
42 | |||
28 | source "arch/powerpc/platforms/pseries/Kconfig" | 43 | source "arch/powerpc/platforms/pseries/Kconfig" |
29 | source "arch/powerpc/platforms/iseries/Kconfig" | 44 | source "arch/powerpc/platforms/iseries/Kconfig" |
30 | source "arch/powerpc/platforms/chrp/Kconfig" | 45 | source "arch/powerpc/platforms/chrp/Kconfig" |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype new file mode 100644 index 000000000000..b8b5fde94668 --- /dev/null +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -0,0 +1,221 @@ | |||
1 | config PPC64 | ||
2 | bool "64-bit kernel" | ||
3 | default n | ||
4 | help | ||
5 | This option selects whether a 32-bit or a 64-bit kernel | ||
6 | will be built. | ||
7 | |||
8 | menu "Processor support" | ||
9 | choice | ||
10 | prompt "Processor Type" | ||
11 | depends on PPC32 | ||
12 | default 6xx | ||
13 | help | ||
14 | There are five families of 32 bit PowerPC chips supported. | ||
15 | The most common ones are the desktop and server CPUs (601, 603, | ||
16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their | ||
17 | embedded 52xx/82xx/83xx/86xx counterparts. | ||
18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 | ||
19 | (85xx) each form a family of their own that is not compatible | ||
20 | with the others. | ||
21 | |||
22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. | ||
23 | |||
24 | config 6xx | ||
25 | bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx" | ||
26 | select PPC_FPU | ||
27 | |||
28 | config PPC_85xx | ||
29 | bool "Freescale 85xx" | ||
30 | select E500 | ||
31 | select FSL_SOC | ||
32 | select 85xx | ||
33 | select WANT_DEVICE_TREE | ||
34 | |||
35 | config PPC_8xx | ||
36 | bool "Freescale 8xx" | ||
37 | select FSL_SOC | ||
38 | select 8xx | ||
39 | |||
40 | config 40x | ||
41 | bool "AMCC 40x" | ||
42 | select PPC_DCR_NATIVE | ||
43 | |||
44 | config 44x | ||
45 | bool "AMCC 44x" | ||
46 | select PPC_DCR_NATIVE | ||
47 | select WANT_DEVICE_TREE | ||
48 | |||
49 | config E200 | ||
50 | bool "Freescale e200" | ||
51 | |||
52 | endchoice | ||
53 | |||
54 | config POWER4_ONLY | ||
55 | bool "Optimize for POWER4" | ||
56 | depends on PPC64 | ||
57 | default n | ||
58 | ---help--- | ||
59 | Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. | ||
60 | The resulting binary will not work on POWER3 or RS64 processors | ||
61 | when compiled with binutils 2.15 or later. | ||
62 | |||
63 | config POWER3 | ||
64 | bool | ||
65 | depends on PPC64 | ||
66 | default y if !POWER4_ONLY | ||
67 | |||
68 | config POWER4 | ||
69 | depends on PPC64 | ||
70 | def_bool y | ||
71 | |||
72 | config 6xx | ||
73 | bool | ||
74 | |||
75 | # this is temp to handle compat with arch=ppc | ||
76 | config 8xx | ||
77 | bool | ||
78 | |||
79 | # this is temp to handle compat with arch=ppc | ||
80 | config 83xx | ||
81 | bool | ||
82 | |||
83 | # this is temp to handle compat with arch=ppc | ||
84 | config 85xx | ||
85 | bool | ||
86 | |||
87 | config E500 | ||
88 | bool | ||
89 | |||
90 | config PPC_FPU | ||
91 | bool | ||
92 | default y if PPC64 | ||
93 | |||
94 | config 4xx | ||
95 | bool | ||
96 | depends on 40x || 44x | ||
97 | default y | ||
98 | |||
99 | config BOOKE | ||
100 | bool | ||
101 | depends on E200 || E500 || 44x | ||
102 | default y | ||
103 | |||
104 | config FSL_BOOKE | ||
105 | bool | ||
106 | depends on E200 || E500 | ||
107 | default y | ||
108 | |||
109 | config PTE_64BIT | ||
110 | bool | ||
111 | depends on 44x || E500 | ||
112 | default y if 44x | ||
113 | default y if E500 && PHYS_64BIT | ||
114 | |||
115 | config PHYS_64BIT | ||
116 | bool 'Large physical address support' if E500 | ||
117 | depends on 44x || E500 | ||
118 | select RESOURCES_64BIT | ||
119 | default y if 44x | ||
120 | ---help--- | ||
121 | This option enables kernel support for larger than 32-bit physical | ||
122 | addresses. This features is not be available on all e500 cores. | ||
123 | |||
124 | If in doubt, say N here. | ||
125 | |||
126 | config ALTIVEC | ||
127 | bool "AltiVec Support" | ||
128 | depends on CLASSIC32 || POWER4 | ||
129 | ---help--- | ||
130 | This option enables kernel support for the Altivec extensions to the | ||
131 | PowerPC processor. The kernel currently supports saving and restoring | ||
132 | altivec registers, and turning on the 'altivec enable' bit so user | ||
133 | processes can execute altivec instructions. | ||
134 | |||
135 | This option is only usefully if you have a processor that supports | ||
136 | altivec (G4, otherwise known as 74xx series), but does not have | ||
137 | any affect on a non-altivec cpu (it does, however add code to the | ||
138 | kernel). | ||
139 | |||
140 | If in doubt, say Y here. | ||
141 | |||
142 | config SPE | ||
143 | bool "SPE Support" | ||
144 | depends on E200 || E500 | ||
145 | default y | ||
146 | ---help--- | ||
147 | This option enables kernel support for the Signal Processing | ||
148 | Extensions (SPE) to the PowerPC processor. The kernel currently | ||
149 | supports saving and restoring SPE registers, and turning on the | ||
150 | 'spe enable' bit so user processes can execute SPE instructions. | ||
151 | |||
152 | This option is only useful if you have a processor that supports | ||
153 | SPE (e500, otherwise known as 85xx series), but does not have any | ||
154 | effect on a non-spe cpu (it does, however add code to the kernel). | ||
155 | |||
156 | If in doubt, say Y here. | ||
157 | |||
158 | config PPC_STD_MMU | ||
159 | bool | ||
160 | depends on 6xx || POWER3 || POWER4 || PPC64 | ||
161 | default y | ||
162 | |||
163 | config PPC_STD_MMU_32 | ||
164 | def_bool y | ||
165 | depends on PPC_STD_MMU && PPC32 | ||
166 | |||
167 | config PPC_MM_SLICES | ||
168 | bool | ||
169 | default y if HUGETLB_PAGE | ||
170 | default n | ||
171 | |||
172 | config VIRT_CPU_ACCOUNTING | ||
173 | bool "Deterministic task and CPU time accounting" | ||
174 | depends on PPC64 | ||
175 | default y | ||
176 | help | ||
177 | Select this option to enable more accurate task and CPU time | ||
178 | accounting. This is done by reading a CPU counter on each | ||
179 | kernel entry and exit and on transitions within the kernel | ||
180 | between system, softirq and hardirq state, so there is a | ||
181 | small performance impact. This also enables accounting of | ||
182 | stolen time on logically-partitioned systems running on | ||
183 | IBM POWER5-based machines. | ||
184 | |||
185 | If in doubt, say Y here. | ||
186 | |||
187 | config SMP | ||
188 | depends on PPC_STD_MMU | ||
189 | bool "Symmetric multi-processing support" | ||
190 | ---help--- | ||
191 | This enables support for systems with more than one CPU. If you have | ||
192 | a system with only one CPU, say N. If you have a system with more | ||
193 | than one CPU, say Y. Note that the kernel does not currently | ||
194 | support SMP machines with 603/603e/603ev or PPC750 ("G3") processors | ||
195 | since they have inadequate hardware support for multiprocessor | ||
196 | operation. | ||
197 | |||
198 | If you say N here, the kernel will run on single and multiprocessor | ||
199 | machines, but will use only one CPU of a multiprocessor machine. If | ||
200 | you say Y here, the kernel will run on single-processor machines. | ||
201 | On a single-processor machine, the kernel will run faster if you say | ||
202 | N here. | ||
203 | |||
204 | If you don't know what to do here, say N. | ||
205 | |||
206 | config NR_CPUS | ||
207 | int "Maximum number of CPUs (2-128)" | ||
208 | range 2 128 | ||
209 | depends on SMP | ||
210 | default "32" if PPC64 | ||
211 | default "4" | ||
212 | |||
213 | config NOT_COHERENT_CACHE | ||
214 | bool | ||
215 | depends on 4xx || 8xx || E200 | ||
216 | default y | ||
217 | |||
218 | config CONFIG_CHECK_CACHE_COHERENCY | ||
219 | bool | ||
220 | |||
221 | endmenu | ||
diff --git a/arch/powerpc/platforms/apus/Kconfig b/arch/powerpc/platforms/apus/Kconfig deleted file mode 100644 index 6bde3bffed86..000000000000 --- a/arch/powerpc/platforms/apus/Kconfig +++ /dev/null | |||
@@ -1,130 +0,0 @@ | |||
1 | |||
2 | config AMIGA | ||
3 | bool | ||
4 | depends on APUS | ||
5 | default y | ||
6 | help | ||
7 | This option enables support for the Amiga series of computers. | ||
8 | |||
9 | config ZORRO | ||
10 | bool | ||
11 | depends on APUS | ||
12 | default y | ||
13 | help | ||
14 | This enables support for the Zorro bus in the Amiga. If you have | ||
15 | expansion cards in your Amiga that conform to the Amiga | ||
16 | AutoConfig(tm) specification, say Y, otherwise N. Note that even | ||
17 | expansion cards that do not fit in the Zorro slots but fit in e.g. | ||
18 | the CPU slot may fall in this category, so you have to say Y to let | ||
19 | Linux use these. | ||
20 | |||
21 | config ABSTRACT_CONSOLE | ||
22 | bool | ||
23 | depends on APUS | ||
24 | default y | ||
25 | |||
26 | config APUS_FAST_EXCEPT | ||
27 | bool | ||
28 | depends on APUS | ||
29 | default y | ||
30 | |||
31 | config AMIGA_PCMCIA | ||
32 | bool "Amiga 1200/600 PCMCIA support" | ||
33 | depends on APUS && EXPERIMENTAL | ||
34 | help | ||
35 | Include support in the kernel for pcmcia on Amiga 1200 and Amiga | ||
36 | 600. If you intend to use pcmcia cards say Y; otherwise say N. | ||
37 | |||
38 | config AMIGA_BUILTIN_SERIAL | ||
39 | tristate "Amiga builtin serial support" | ||
40 | depends on APUS | ||
41 | help | ||
42 | If you want to use your Amiga's built-in serial port in Linux, | ||
43 | answer Y. | ||
44 | |||
45 | To compile this driver as a module, choose M here. | ||
46 | |||
47 | config GVPIOEXT | ||
48 | tristate "GVP IO-Extender support" | ||
49 | depends on APUS | ||
50 | help | ||
51 | If you want to use a GVP IO-Extender serial card in Linux, say Y. | ||
52 | Otherwise, say N. | ||
53 | |||
54 | config GVPIOEXT_LP | ||
55 | tristate "GVP IO-Extender parallel printer support" | ||
56 | depends on GVPIOEXT | ||
57 | help | ||
58 | Say Y to enable driving a printer from the parallel port on your | ||
59 | GVP IO-Extender card, N otherwise. | ||
60 | |||
61 | config GVPIOEXT_PLIP | ||
62 | tristate "GVP IO-Extender PLIP support" | ||
63 | depends on GVPIOEXT | ||
64 | help | ||
65 | Say Y to enable doing IP over the parallel port on your GVP | ||
66 | IO-Extender card, N otherwise. | ||
67 | |||
68 | config MULTIFACE_III_TTY | ||
69 | tristate "Multiface Card III serial support" | ||
70 | depends on APUS | ||
71 | help | ||
72 | If you want to use a Multiface III card's serial port in Linux, | ||
73 | answer Y. | ||
74 | |||
75 | To compile this driver as a module, choose M here. | ||
76 | |||
77 | config A2232 | ||
78 | tristate "Commodore A2232 serial support (EXPERIMENTAL)" | ||
79 | depends on EXPERIMENTAL && APUS | ||
80 | ---help--- | ||
81 | This option supports the 2232 7-port serial card shipped with the | ||
82 | Amiga 2000 and other Zorro-bus machines, dating from 1989. At | ||
83 | a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip | ||
84 | each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The | ||
85 | ports were connected with 8 pin DIN connectors on the card bracket, | ||
86 | for which 8 pin to DB25 adapters were supplied. The card also had | ||
87 | jumpers internally to toggle various pinning configurations. | ||
88 | |||
89 | This driver can be built as a module; but then "generic_serial" | ||
90 | will also be built as a module. This has to be loaded before | ||
91 | "ser_a2232". If you want to do this, answer M here. | ||
92 | |||
93 | config WHIPPET_SERIAL | ||
94 | tristate "Hisoft Whippet PCMCIA serial support" | ||
95 | depends on AMIGA_PCMCIA | ||
96 | help | ||
97 | HiSoft has a web page at <http://www.hisoft.co.uk/>, but there | ||
98 | is no listing for the Whippet in their Amiga section. | ||
99 | |||
100 | config APNE | ||
101 | tristate "PCMCIA NE2000 support" | ||
102 | depends on AMIGA_PCMCIA | ||
103 | help | ||
104 | If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, | ||
105 | say N. | ||
106 | |||
107 | To compile this driver as a module, choose M here: the | ||
108 | module will be called apne. | ||
109 | |||
110 | config SERIAL_CONSOLE | ||
111 | bool "Support for serial port console" | ||
112 | depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y) | ||
113 | |||
114 | config HEARTBEAT | ||
115 | bool "Use power LED as a heartbeat" | ||
116 | depends on APUS | ||
117 | help | ||
118 | Use the power-on LED on your machine as a load meter. The exact | ||
119 | behavior is platform-dependent, but normally the flash frequency is | ||
120 | a hyperbolic function of the 5-minute load average. | ||
121 | |||
122 | config PROC_HARDWARE | ||
123 | bool "/proc/hardware support" | ||
124 | depends on APUS | ||
125 | |||
126 | source "drivers/zorro/Kconfig" | ||
127 | |||
128 | config PCI_PERMEDIA | ||
129 | bool "PCI for Permedia2" | ||
130 | depends on !4xx && !8xx && APUS | ||
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c index 7fb92f23f380..9d7c2ef940a8 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.c +++ b/arch/powerpc/platforms/cell/io-workarounds.c | |||
@@ -102,7 +102,7 @@ static void spider_io_flush(const volatile void __iomem *addr) | |||
102 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); | 102 | vaddr = (unsigned long)PCI_FIX_ADDR(addr); |
103 | 103 | ||
104 | /* Check if it's in allowed range for PIO */ | 104 | /* Check if it's in allowed range for PIO */ |
105 | if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE) | 105 | if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END) |
106 | return; | 106 | return; |
107 | 107 | ||
108 | /* Try to find a PTE. If not, clear the paddr, we'll do | 108 | /* Try to find a PTE. If not, clear the paddr, we'll do |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index a7f5a7653c62..96a8f609690c 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/linux_logo.h> | ||
34 | #include <asm/spu.h> | 35 | #include <asm/spu.h> |
35 | #include <asm/spu_priv1.h> | 36 | #include <asm/spu_priv1.h> |
36 | #include <asm/xmon.h> | 37 | #include <asm/xmon.h> |
@@ -183,7 +184,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
183 | spu->slb_replace = 0; | 184 | spu->slb_replace = 0; |
184 | 185 | ||
185 | spu_restart_dma(spu); | 186 | spu_restart_dma(spu); |
186 | 187 | spu->stats.slb_flt++; | |
187 | return 0; | 188 | return 0; |
188 | } | 189 | } |
189 | 190 | ||
@@ -332,6 +333,7 @@ spu_irq_class_2(int irq, void *data) | |||
332 | if (stat & 0x10) /* SPU mailbox threshold */ | 333 | if (stat & 0x10) /* SPU mailbox threshold */ |
333 | spu->wbox_callback(spu); | 334 | spu->wbox_callback(spu); |
334 | 335 | ||
336 | spu->stats.class2_intr++; | ||
335 | return stat ? IRQ_HANDLED : IRQ_NONE; | 337 | return stat ? IRQ_HANDLED : IRQ_NONE; |
336 | } | 338 | } |
337 | 339 | ||
@@ -462,8 +464,18 @@ void spu_free(struct spu *spu) | |||
462 | } | 464 | } |
463 | EXPORT_SYMBOL_GPL(spu_free); | 465 | EXPORT_SYMBOL_GPL(spu_free); |
464 | 466 | ||
467 | static int spu_shutdown(struct sys_device *sysdev) | ||
468 | { | ||
469 | struct spu *spu = container_of(sysdev, struct spu, sysdev); | ||
470 | |||
471 | spu_free_irqs(spu); | ||
472 | spu_destroy_spu(spu); | ||
473 | return 0; | ||
474 | } | ||
475 | |||
465 | struct sysdev_class spu_sysdev_class = { | 476 | struct sysdev_class spu_sysdev_class = { |
466 | set_kset_name("spu") | 477 | set_kset_name("spu"), |
478 | .shutdown = spu_shutdown, | ||
467 | }; | 479 | }; |
468 | 480 | ||
469 | int spu_add_sysdev_attr(struct sysdev_attribute *attr) | 481 | int spu_add_sysdev_attr(struct sysdev_attribute *attr) |
@@ -574,6 +586,9 @@ static int __init create_spu(void *data) | |||
574 | spin_unlock_irqrestore(&spu_list_lock, flags); | 586 | spin_unlock_irqrestore(&spu_list_lock, flags); |
575 | mutex_unlock(&spu_mutex); | 587 | mutex_unlock(&spu_mutex); |
576 | 588 | ||
589 | spu->stats.utilization_state = SPU_UTIL_IDLE; | ||
590 | spu->stats.tstamp = jiffies; | ||
591 | |||
577 | goto out; | 592 | goto out; |
578 | 593 | ||
579 | out_free_irqs: | 594 | out_free_irqs: |
@@ -586,6 +601,45 @@ out: | |||
586 | return ret; | 601 | return ret; |
587 | } | 602 | } |
588 | 603 | ||
604 | static const char *spu_state_names[] = { | ||
605 | "user", "system", "iowait", "idle" | ||
606 | }; | ||
607 | |||
608 | static unsigned long long spu_acct_time(struct spu *spu, | ||
609 | enum spu_utilization_state state) | ||
610 | { | ||
611 | unsigned long long time = spu->stats.times[state]; | ||
612 | |||
613 | if (spu->stats.utilization_state == state) | ||
614 | time += jiffies - spu->stats.tstamp; | ||
615 | |||
616 | return jiffies_to_msecs(time); | ||
617 | } | ||
618 | |||
619 | |||
620 | static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf) | ||
621 | { | ||
622 | struct spu *spu = container_of(sysdev, struct spu, sysdev); | ||
623 | |||
624 | return sprintf(buf, "%s %llu %llu %llu %llu " | ||
625 | "%llu %llu %llu %llu %llu %llu %llu %llu\n", | ||
626 | spu_state_names[spu->stats.utilization_state], | ||
627 | spu_acct_time(spu, SPU_UTIL_USER), | ||
628 | spu_acct_time(spu, SPU_UTIL_SYSTEM), | ||
629 | spu_acct_time(spu, SPU_UTIL_IOWAIT), | ||
630 | spu_acct_time(spu, SPU_UTIL_IDLE), | ||
631 | spu->stats.vol_ctx_switch, | ||
632 | spu->stats.invol_ctx_switch, | ||
633 | spu->stats.slb_flt, | ||
634 | spu->stats.hash_flt, | ||
635 | spu->stats.min_flt, | ||
636 | spu->stats.maj_flt, | ||
637 | spu->stats.class2_intr, | ||
638 | spu->stats.libassist); | ||
639 | } | ||
640 | |||
641 | static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL); | ||
642 | |||
589 | static int __init init_spu_base(void) | 643 | static int __init init_spu_base(void) |
590 | { | 644 | { |
591 | int i, ret = 0; | 645 | int i, ret = 0; |
@@ -603,14 +657,28 @@ static int __init init_spu_base(void) | |||
603 | 657 | ||
604 | ret = spu_enumerate_spus(create_spu); | 658 | ret = spu_enumerate_spus(create_spu); |
605 | 659 | ||
606 | if (ret) { | 660 | if (ret < 0) { |
607 | printk(KERN_WARNING "%s: Error initializing spus\n", | 661 | printk(KERN_WARNING "%s: Error initializing spus\n", |
608 | __FUNCTION__); | 662 | __FUNCTION__); |
609 | goto out_unregister_sysdev_class; | 663 | goto out_unregister_sysdev_class; |
610 | } | 664 | } |
611 | 665 | ||
666 | if (ret > 0) { | ||
667 | /* | ||
668 | * We cannot put the forward declaration in | ||
669 | * <linux/linux_logo.h> because of conflicting session type | ||
670 | * conflicts for const and __initdata with different compiler | ||
671 | * versions | ||
672 | */ | ||
673 | extern const struct linux_logo logo_spe_clut224; | ||
674 | |||
675 | fb_append_extra_logo(&logo_spe_clut224, ret); | ||
676 | } | ||
677 | |||
612 | xmon_register_spus(&spu_full_list); | 678 | xmon_register_spus(&spu_full_list); |
613 | 679 | ||
680 | spu_add_sysdev_attr(&attr_stat); | ||
681 | |||
614 | return 0; | 682 | return 0; |
615 | 683 | ||
616 | out_unregister_sysdev_class: | 684 | out_unregister_sysdev_class: |
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index 1d4562ae463d..75ed50fcc3db 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c | |||
@@ -279,6 +279,7 @@ static int __init of_enumerate_spus(int (*fn)(void *data)) | |||
279 | { | 279 | { |
280 | int ret; | 280 | int ret; |
281 | struct device_node *node; | 281 | struct device_node *node; |
282 | unsigned int n = 0; | ||
282 | 283 | ||
283 | ret = -ENODEV; | 284 | ret = -ENODEV; |
284 | for (node = of_find_node_by_type(NULL, "spe"); | 285 | for (node = of_find_node_by_type(NULL, "spe"); |
@@ -289,8 +290,9 @@ static int __init of_enumerate_spus(int (*fn)(void *data)) | |||
289 | __FUNCTION__, node->name); | 290 | __FUNCTION__, node->name); |
290 | break; | 291 | break; |
291 | } | 292 | } |
293 | n++; | ||
292 | } | 294 | } |
293 | return ret; | 295 | return ret ? ret : n; |
294 | } | 296 | } |
295 | 297 | ||
296 | static int __init of_create_spu(struct spu *spu, void *data) | 298 | static int __init of_create_spu(struct spu *spu, void *data) |
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index d32db9ffc6eb..07a0e815abf5 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c | |||
@@ -320,6 +320,12 @@ static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, | |||
320 | /* FIXME: what are the side-effects of this? */ | 320 | /* FIXME: what are the side-effects of this? */ |
321 | prob->dma_querymask_RW = mask; | 321 | prob->dma_querymask_RW = mask; |
322 | prob->dma_querytype_RW = mode; | 322 | prob->dma_querytype_RW = mode; |
323 | /* In the current implementation, the SPU context is always | ||
324 | * acquired in runnable state when new bits are added to the | ||
325 | * mask (tagwait), so it's sufficient just to mask | ||
326 | * dma_tagstatus_R with the 'mask' parameter here. | ||
327 | */ | ||
328 | ctx->csa.prob.dma_tagstatus_R &= mask; | ||
323 | out: | 329 | out: |
324 | spin_unlock(&ctx->csa.register_lock); | 330 | spin_unlock(&ctx->csa.register_lock); |
325 | 331 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 7c51cb54bca1..6d7bd60f5380 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -23,10 +23,14 @@ | |||
23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <asm/atomic.h> | ||
26 | #include <asm/spu.h> | 27 | #include <asm/spu.h> |
27 | #include <asm/spu_csa.h> | 28 | #include <asm/spu_csa.h> |
28 | #include "spufs.h" | 29 | #include "spufs.h" |
29 | 30 | ||
31 | |||
32 | atomic_t nr_spu_contexts = ATOMIC_INIT(0); | ||
33 | |||
30 | struct spu_context *alloc_spu_context(struct spu_gang *gang) | 34 | struct spu_context *alloc_spu_context(struct spu_gang *gang) |
31 | { | 35 | { |
32 | struct spu_context *ctx; | 36 | struct spu_context *ctx; |
@@ -53,10 +57,12 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) | |||
53 | INIT_LIST_HEAD(&ctx->rq); | 57 | INIT_LIST_HEAD(&ctx->rq); |
54 | if (gang) | 58 | if (gang) |
55 | spu_gang_add_ctx(gang, ctx); | 59 | spu_gang_add_ctx(gang, ctx); |
56 | ctx->rt_priority = current->rt_priority; | 60 | ctx->cpus_allowed = current->cpus_allowed; |
57 | ctx->policy = current->policy; | 61 | spu_set_timeslice(ctx); |
58 | ctx->prio = current->prio; | 62 | ctx->stats.execution_state = SPUCTX_UTIL_USER; |
59 | INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick); | 63 | ctx->stats.tstamp = jiffies; |
64 | |||
65 | atomic_inc(&nr_spu_contexts); | ||
60 | goto out; | 66 | goto out; |
61 | out_free: | 67 | out_free: |
62 | kfree(ctx); | 68 | kfree(ctx); |
@@ -76,6 +82,7 @@ void destroy_spu_context(struct kref *kref) | |||
76 | if (ctx->gang) | 82 | if (ctx->gang) |
77 | spu_gang_remove_ctx(ctx->gang, ctx); | 83 | spu_gang_remove_ctx(ctx->gang, ctx); |
78 | BUG_ON(!list_empty(&ctx->rq)); | 84 | BUG_ON(!list_empty(&ctx->rq)); |
85 | atomic_dec(&nr_spu_contexts); | ||
79 | kfree(ctx); | 86 | kfree(ctx); |
80 | } | 87 | } |
81 | 88 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c index 0f75c07e29d8..07f88de0544d 100644 --- a/arch/powerpc/platforms/cell/spufs/fault.c +++ b/arch/powerpc/platforms/cell/spufs/fault.c | |||
@@ -33,7 +33,8 @@ | |||
33 | * function. Currently, there are a few corner cases that we haven't had | 33 | * function. Currently, there are a few corner cases that we haven't had |
34 | * to handle fortunately. | 34 | * to handle fortunately. |
35 | */ | 35 | */ |
36 | static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr) | 36 | static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, |
37 | unsigned long dsisr, unsigned *flt) | ||
37 | { | 38 | { |
38 | struct vm_area_struct *vma; | 39 | struct vm_area_struct *vma; |
39 | unsigned long is_write; | 40 | unsigned long is_write; |
@@ -73,22 +74,21 @@ good_area: | |||
73 | goto bad_area; | 74 | goto bad_area; |
74 | } | 75 | } |
75 | ret = 0; | 76 | ret = 0; |
76 | switch (handle_mm_fault(mm, vma, ea, is_write)) { | 77 | fault = handle_mm_fault(mm, vma, ea, is_write); |
77 | case VM_FAULT_MINOR: | 78 | if (unlikely(fault & VM_FAULT_ERROR)) { |
78 | current->min_flt++; | 79 | if (fault & VM_FAULT_OOM) { |
79 | break; | 80 | ret = -ENOMEM; |
80 | case VM_FAULT_MAJOR: | 81 | goto bad_area; |
81 | current->maj_flt++; | 82 | } else if (fault & VM_FAULT_SIGBUS) { |
82 | break; | 83 | ret = -EFAULT; |
83 | case VM_FAULT_SIGBUS: | 84 | goto bad_area; |
84 | ret = -EFAULT; | 85 | } |
85 | goto bad_area; | ||
86 | case VM_FAULT_OOM: | ||
87 | ret = -ENOMEM; | ||
88 | goto bad_area; | ||
89 | default: | ||
90 | BUG(); | 86 | BUG(); |
91 | } | 87 | } |
88 | if (fault & VM_FAULT_MAJOR) | ||
89 | current->maj_flt++; | ||
90 | else | ||
91 | current->min_flt++; | ||
92 | up_read(&mm->mmap_sem); | 92 | up_read(&mm->mmap_sem); |
93 | return ret; | 93 | return ret; |
94 | 94 | ||
@@ -153,6 +153,7 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
153 | { | 153 | { |
154 | u64 ea, dsisr, access; | 154 | u64 ea, dsisr, access; |
155 | unsigned long flags; | 155 | unsigned long flags; |
156 | unsigned flt = 0; | ||
156 | int ret; | 157 | int ret; |
157 | 158 | ||
158 | /* | 159 | /* |
@@ -178,9 +179,17 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
178 | if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) | 179 | if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) |
179 | return 0; | 180 | return 0; |
180 | 181 | ||
182 | spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT); | ||
183 | |||
181 | pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, | 184 | pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, |
182 | dsisr, ctx->state); | 185 | dsisr, ctx->state); |
183 | 186 | ||
187 | ctx->stats.hash_flt++; | ||
188 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
189 | ctx->spu->stats.hash_flt++; | ||
190 | spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT); | ||
191 | } | ||
192 | |||
184 | /* we must not hold the lock when entering spu_handle_mm_fault */ | 193 | /* we must not hold the lock when entering spu_handle_mm_fault */ |
185 | spu_release(ctx); | 194 | spu_release(ctx); |
186 | 195 | ||
@@ -192,7 +201,7 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
192 | 201 | ||
193 | /* hashing failed, so try the actual fault handler */ | 202 | /* hashing failed, so try the actual fault handler */ |
194 | if (ret) | 203 | if (ret) |
195 | ret = spu_handle_mm_fault(current->mm, ea, dsisr); | 204 | ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt); |
196 | 205 | ||
197 | spu_acquire(ctx); | 206 | spu_acquire(ctx); |
198 | /* | 207 | /* |
@@ -201,11 +210,23 @@ int spufs_handle_class1(struct spu_context *ctx) | |||
201 | * In case of unhandled error report the problem to user space. | 210 | * In case of unhandled error report the problem to user space. |
202 | */ | 211 | */ |
203 | if (!ret) { | 212 | if (!ret) { |
213 | if (flt == VM_FAULT_MINOR) | ||
214 | ctx->stats.min_flt++; | ||
215 | else | ||
216 | ctx->stats.maj_flt++; | ||
217 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
218 | if (flt == VM_FAULT_MINOR) | ||
219 | ctx->spu->stats.min_flt++; | ||
220 | else | ||
221 | ctx->spu->stats.maj_flt++; | ||
222 | } | ||
223 | |||
204 | if (ctx->spu) | 224 | if (ctx->spu) |
205 | ctx->ops->restart_dma(ctx); | 225 | ctx->ops->restart_dma(ctx); |
206 | } else | 226 | } else |
207 | spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); | 227 | spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); |
208 | 228 | ||
229 | spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM); | ||
209 | return ret; | 230 | return ret; |
210 | } | 231 | } |
211 | EXPORT_SYMBOL_GPL(spufs_handle_class1); | 232 | EXPORT_SYMBOL_GPL(spufs_handle_class1); |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index b1e7e2f8a2e9..c2814ea96af2 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/pagemap.h> | 28 | #include <linux/pagemap.h> |
29 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
30 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
31 | #include <linux/seq_file.h> | ||
31 | 32 | ||
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
33 | #include <asm/semaphore.h> | 34 | #include <asm/semaphore.h> |
@@ -39,6 +40,7 @@ | |||
39 | 40 | ||
40 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) | 41 | #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) |
41 | 42 | ||
43 | |||
42 | static int | 44 | static int |
43 | spufs_mem_open(struct inode *inode, struct file *file) | 45 | spufs_mem_open(struct inode *inode, struct file *file) |
44 | { | 46 | { |
@@ -216,12 +218,12 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, | |||
216 | #endif /* CONFIG_SPU_FS_64K_LS */ | 218 | #endif /* CONFIG_SPU_FS_64K_LS */ |
217 | 219 | ||
218 | static const struct file_operations spufs_mem_fops = { | 220 | static const struct file_operations spufs_mem_fops = { |
219 | .open = spufs_mem_open, | 221 | .open = spufs_mem_open, |
220 | .release = spufs_mem_release, | 222 | .release = spufs_mem_release, |
221 | .read = spufs_mem_read, | 223 | .read = spufs_mem_read, |
222 | .write = spufs_mem_write, | 224 | .write = spufs_mem_write, |
223 | .llseek = generic_file_llseek, | 225 | .llseek = generic_file_llseek, |
224 | .mmap = spufs_mem_mmap, | 226 | .mmap = spufs_mem_mmap, |
225 | #ifdef CONFIG_SPU_FS_64K_LS | 227 | #ifdef CONFIG_SPU_FS_64K_LS |
226 | .get_unmapped_area = spufs_get_unmapped_area, | 228 | .get_unmapped_area = spufs_get_unmapped_area, |
227 | #endif | 229 | #endif |
@@ -1497,14 +1499,15 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, | |||
1497 | if (status) | 1499 | if (status) |
1498 | ret = status; | 1500 | ret = status; |
1499 | } | 1501 | } |
1500 | spu_release(ctx); | ||
1501 | 1502 | ||
1502 | if (ret) | 1503 | if (ret) |
1503 | goto out; | 1504 | goto out_unlock; |
1504 | 1505 | ||
1505 | ctx->tagwait |= 1 << cmd.tag; | 1506 | ctx->tagwait |= 1 << cmd.tag; |
1506 | ret = size; | 1507 | ret = size; |
1507 | 1508 | ||
1509 | out_unlock: | ||
1510 | spu_release(ctx); | ||
1508 | out: | 1511 | out: |
1509 | return ret; | 1512 | return ret; |
1510 | } | 1513 | } |
@@ -1515,14 +1518,14 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait) | |||
1515 | u32 free_elements, tagstatus; | 1518 | u32 free_elements, tagstatus; |
1516 | unsigned int mask; | 1519 | unsigned int mask; |
1517 | 1520 | ||
1521 | poll_wait(file, &ctx->mfc_wq, wait); | ||
1522 | |||
1518 | spu_acquire(ctx); | 1523 | spu_acquire(ctx); |
1519 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); | 1524 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); |
1520 | free_elements = ctx->ops->get_mfc_free_elements(ctx); | 1525 | free_elements = ctx->ops->get_mfc_free_elements(ctx); |
1521 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); | 1526 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); |
1522 | spu_release(ctx); | 1527 | spu_release(ctx); |
1523 | 1528 | ||
1524 | poll_wait(file, &ctx->mfc_wq, wait); | ||
1525 | |||
1526 | mask = 0; | 1529 | mask = 0; |
1527 | if (free_elements & 0xffff) | 1530 | if (free_elements & 0xffff) |
1528 | mask |= POLLOUT | POLLWRNORM; | 1531 | mask |= POLLOUT | POLLWRNORM; |
@@ -1797,6 +1800,29 @@ static int spufs_info_open(struct inode *inode, struct file *file) | |||
1797 | return 0; | 1800 | return 0; |
1798 | } | 1801 | } |
1799 | 1802 | ||
1803 | static int spufs_caps_show(struct seq_file *s, void *private) | ||
1804 | { | ||
1805 | struct spu_context *ctx = s->private; | ||
1806 | |||
1807 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) | ||
1808 | seq_puts(s, "sched\n"); | ||
1809 | if (!(ctx->flags & SPU_CREATE_ISOLATE)) | ||
1810 | seq_puts(s, "step\n"); | ||
1811 | return 0; | ||
1812 | } | ||
1813 | |||
1814 | static int spufs_caps_open(struct inode *inode, struct file *file) | ||
1815 | { | ||
1816 | return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx); | ||
1817 | } | ||
1818 | |||
1819 | static const struct file_operations spufs_caps_fops = { | ||
1820 | .open = spufs_caps_open, | ||
1821 | .read = seq_read, | ||
1822 | .llseek = seq_lseek, | ||
1823 | .release = single_release, | ||
1824 | }; | ||
1825 | |||
1800 | static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, | 1826 | static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, |
1801 | char __user *buf, size_t len, loff_t *pos) | 1827 | char __user *buf, size_t len, loff_t *pos) |
1802 | { | 1828 | { |
@@ -2014,7 +2040,105 @@ static const struct file_operations spufs_proxydma_info_fops = { | |||
2014 | .read = spufs_proxydma_info_read, | 2040 | .read = spufs_proxydma_info_read, |
2015 | }; | 2041 | }; |
2016 | 2042 | ||
2043 | static int spufs_show_tid(struct seq_file *s, void *private) | ||
2044 | { | ||
2045 | struct spu_context *ctx = s->private; | ||
2046 | |||
2047 | seq_printf(s, "%d\n", ctx->tid); | ||
2048 | return 0; | ||
2049 | } | ||
2050 | |||
2051 | static int spufs_tid_open(struct inode *inode, struct file *file) | ||
2052 | { | ||
2053 | return single_open(file, spufs_show_tid, SPUFS_I(inode)->i_ctx); | ||
2054 | } | ||
2055 | |||
2056 | static const struct file_operations spufs_tid_fops = { | ||
2057 | .open = spufs_tid_open, | ||
2058 | .read = seq_read, | ||
2059 | .llseek = seq_lseek, | ||
2060 | .release = single_release, | ||
2061 | }; | ||
2062 | |||
2063 | static const char *ctx_state_names[] = { | ||
2064 | "user", "system", "iowait", "loaded" | ||
2065 | }; | ||
2066 | |||
2067 | static unsigned long long spufs_acct_time(struct spu_context *ctx, | ||
2068 | enum spuctx_execution_state state) | ||
2069 | { | ||
2070 | unsigned long time = ctx->stats.times[state]; | ||
2071 | |||
2072 | if (ctx->stats.execution_state == state) | ||
2073 | time += jiffies - ctx->stats.tstamp; | ||
2074 | |||
2075 | return jiffies_to_msecs(time); | ||
2076 | } | ||
2077 | |||
2078 | static unsigned long long spufs_slb_flts(struct spu_context *ctx) | ||
2079 | { | ||
2080 | unsigned long long slb_flts = ctx->stats.slb_flt; | ||
2081 | |||
2082 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
2083 | slb_flts += (ctx->spu->stats.slb_flt - | ||
2084 | ctx->stats.slb_flt_base); | ||
2085 | } | ||
2086 | |||
2087 | return slb_flts; | ||
2088 | } | ||
2089 | |||
2090 | static unsigned long long spufs_class2_intrs(struct spu_context *ctx) | ||
2091 | { | ||
2092 | unsigned long long class2_intrs = ctx->stats.class2_intr; | ||
2093 | |||
2094 | if (ctx->state == SPU_STATE_RUNNABLE) { | ||
2095 | class2_intrs += (ctx->spu->stats.class2_intr - | ||
2096 | ctx->stats.class2_intr_base); | ||
2097 | } | ||
2098 | |||
2099 | return class2_intrs; | ||
2100 | } | ||
2101 | |||
2102 | |||
2103 | static int spufs_show_stat(struct seq_file *s, void *private) | ||
2104 | { | ||
2105 | struct spu_context *ctx = s->private; | ||
2106 | |||
2107 | spu_acquire(ctx); | ||
2108 | seq_printf(s, "%s %llu %llu %llu %llu " | ||
2109 | "%llu %llu %llu %llu %llu %llu %llu %llu\n", | ||
2110 | ctx_state_names[ctx->stats.execution_state], | ||
2111 | spufs_acct_time(ctx, SPUCTX_UTIL_USER), | ||
2112 | spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM), | ||
2113 | spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT), | ||
2114 | spufs_acct_time(ctx, SPUCTX_UTIL_LOADED), | ||
2115 | ctx->stats.vol_ctx_switch, | ||
2116 | ctx->stats.invol_ctx_switch, | ||
2117 | spufs_slb_flts(ctx), | ||
2118 | ctx->stats.hash_flt, | ||
2119 | ctx->stats.min_flt, | ||
2120 | ctx->stats.maj_flt, | ||
2121 | spufs_class2_intrs(ctx), | ||
2122 | ctx->stats.libassist); | ||
2123 | spu_release(ctx); | ||
2124 | return 0; | ||
2125 | } | ||
2126 | |||
2127 | static int spufs_stat_open(struct inode *inode, struct file *file) | ||
2128 | { | ||
2129 | return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx); | ||
2130 | } | ||
2131 | |||
2132 | static const struct file_operations spufs_stat_fops = { | ||
2133 | .open = spufs_stat_open, | ||
2134 | .read = seq_read, | ||
2135 | .llseek = seq_lseek, | ||
2136 | .release = single_release, | ||
2137 | }; | ||
2138 | |||
2139 | |||
2017 | struct tree_descr spufs_dir_contents[] = { | 2140 | struct tree_descr spufs_dir_contents[] = { |
2141 | { "capabilities", &spufs_caps_fops, 0444, }, | ||
2018 | { "mem", &spufs_mem_fops, 0666, }, | 2142 | { "mem", &spufs_mem_fops, 0666, }, |
2019 | { "regs", &spufs_regs_fops, 0666, }, | 2143 | { "regs", &spufs_regs_fops, 0666, }, |
2020 | { "mbox", &spufs_mbox_fops, 0444, }, | 2144 | { "mbox", &spufs_mbox_fops, 0444, }, |
@@ -2046,10 +2170,13 @@ struct tree_descr spufs_dir_contents[] = { | |||
2046 | { "wbox_info", &spufs_wbox_info_fops, 0444, }, | 2170 | { "wbox_info", &spufs_wbox_info_fops, 0444, }, |
2047 | { "dma_info", &spufs_dma_info_fops, 0444, }, | 2171 | { "dma_info", &spufs_dma_info_fops, 0444, }, |
2048 | { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, | 2172 | { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, |
2173 | { "tid", &spufs_tid_fops, 0444, }, | ||
2174 | { "stat", &spufs_stat_fops, 0444, }, | ||
2049 | {}, | 2175 | {}, |
2050 | }; | 2176 | }; |
2051 | 2177 | ||
2052 | struct tree_descr spufs_dir_nosched_contents[] = { | 2178 | struct tree_descr spufs_dir_nosched_contents[] = { |
2179 | { "capabilities", &spufs_caps_fops, 0444, }, | ||
2053 | { "mem", &spufs_mem_fops, 0666, }, | 2180 | { "mem", &spufs_mem_fops, 0666, }, |
2054 | { "mbox", &spufs_mbox_fops, 0444, }, | 2181 | { "mbox", &spufs_mbox_fops, 0444, }, |
2055 | { "ibox", &spufs_ibox_fops, 0444, }, | 2182 | { "ibox", &spufs_ibox_fops, 0444, }, |
@@ -2068,6 +2195,8 @@ struct tree_descr spufs_dir_nosched_contents[] = { | |||
2068 | { "psmap", &spufs_psmap_fops, 0666, }, | 2195 | { "psmap", &spufs_psmap_fops, 0666, }, |
2069 | { "phys-id", &spufs_id_ops, 0666, }, | 2196 | { "phys-id", &spufs_id_ops, 0666, }, |
2070 | { "object-id", &spufs_object_id_ops, 0666, }, | 2197 | { "object-id", &spufs_object_id_ops, 0666, }, |
2198 | { "tid", &spufs_tid_fops, 0444, }, | ||
2199 | { "stat", &spufs_stat_fops, 0444, }, | ||
2071 | {}, | 2200 | {}, |
2072 | }; | 2201 | }; |
2073 | 2202 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 9807206e0219..f37460e5bfd2 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -232,10 +232,6 @@ static int spufs_dir_close(struct inode *inode, struct file *file) | |||
232 | return dcache_dir_close(inode, file); | 232 | return dcache_dir_close(inode, file); |
233 | } | 233 | } |
234 | 234 | ||
235 | const struct inode_operations spufs_dir_inode_operations = { | ||
236 | .lookup = simple_lookup, | ||
237 | }; | ||
238 | |||
239 | const struct file_operations spufs_context_fops = { | 235 | const struct file_operations spufs_context_fops = { |
240 | .open = dcache_dir_open, | 236 | .open = dcache_dir_open, |
241 | .release = spufs_dir_close, | 237 | .release = spufs_dir_close, |
@@ -269,7 +265,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | |||
269 | goto out_iput; | 265 | goto out_iput; |
270 | 266 | ||
271 | ctx->flags = flags; | 267 | ctx->flags = flags; |
272 | inode->i_op = &spufs_dir_inode_operations; | 268 | inode->i_op = &simple_dir_inode_operations; |
273 | inode->i_fop = &simple_dir_operations; | 269 | inode->i_fop = &simple_dir_operations; |
274 | if (flags & SPU_CREATE_NOSCHED) | 270 | if (flags & SPU_CREATE_NOSCHED) |
275 | ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, | 271 | ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, |
@@ -386,7 +382,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode) | |||
386 | if (!gang) | 382 | if (!gang) |
387 | goto out_iput; | 383 | goto out_iput; |
388 | 384 | ||
389 | inode->i_op = &spufs_dir_inode_operations; | 385 | inode->i_op = &simple_dir_inode_operations; |
390 | inode->i_fop = &simple_dir_operations; | 386 | inode->i_fop = &simple_dir_operations; |
391 | 387 | ||
392 | d_instantiate(dentry, inode); | 388 | d_instantiate(dentry, inode); |
@@ -593,7 +589,7 @@ spufs_create_root(struct super_block *sb, void *data) | |||
593 | if (!inode) | 589 | if (!inode) |
594 | goto out; | 590 | goto out; |
595 | 591 | ||
596 | inode->i_op = &spufs_dir_inode_operations; | 592 | inode->i_op = &simple_dir_inode_operations; |
597 | inode->i_fop = &simple_dir_operations; | 593 | inode->i_fop = &simple_dir_operations; |
598 | SPUFS_I(inode)->i_ctx = NULL; | 594 | SPUFS_I(inode)->i_ctx = NULL; |
599 | 595 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 57626600b1a4..58ae13b7de84 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -29,7 +29,8 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) | |||
29 | spu = ctx->spu; | 29 | spu = ctx->spu; |
30 | pte_fault = spu->dsisr & | 30 | pte_fault = spu->dsisr & |
31 | (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED); | 31 | (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED); |
32 | return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; | 32 | return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ? |
33 | 1 : 0; | ||
33 | } | 34 | } |
34 | 35 | ||
35 | static int spu_setup_isolated(struct spu_context *ctx) | 36 | static int spu_setup_isolated(struct spu_context *ctx) |
@@ -142,8 +143,11 @@ static int spu_run_init(struct spu_context *ctx, u32 * npc) | |||
142 | runcntl = SPU_RUNCNTL_RUNNABLE; | 143 | runcntl = SPU_RUNCNTL_RUNNABLE; |
143 | ctx->ops->runcntl_write(ctx, runcntl); | 144 | ctx->ops->runcntl_write(ctx, runcntl); |
144 | } else { | 145 | } else { |
145 | spu_start_tick(ctx); | 146 | unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL; |
146 | ctx->ops->npc_write(ctx, *npc); | 147 | ctx->ops->npc_write(ctx, *npc); |
148 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
149 | mode = SPU_PRIVCNTL_MODE_SINGLE_STEP; | ||
150 | out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode); | ||
147 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); | 151 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); |
148 | } | 152 | } |
149 | 153 | ||
@@ -155,7 +159,6 @@ static int spu_run_fini(struct spu_context *ctx, u32 * npc, | |||
155 | { | 159 | { |
156 | int ret = 0; | 160 | int ret = 0; |
157 | 161 | ||
158 | spu_stop_tick(ctx); | ||
159 | *status = ctx->ops->status_read(ctx); | 162 | *status = ctx->ops->status_read(ctx); |
160 | *npc = ctx->ops->npc_read(ctx); | 163 | *npc = ctx->ops->npc_read(ctx); |
161 | spu_release(ctx); | 164 | spu_release(ctx); |
@@ -298,9 +301,22 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
298 | ctx->ops->master_start(ctx); | 301 | ctx->ops->master_start(ctx); |
299 | ctx->event_return = 0; | 302 | ctx->event_return = 0; |
300 | 303 | ||
301 | ret = spu_acquire_runnable(ctx, 0); | 304 | spu_acquire(ctx); |
302 | if (ret) | 305 | if (ctx->state == SPU_STATE_SAVED) { |
303 | return ret; | 306 | __spu_update_sched_info(ctx); |
307 | |||
308 | ret = spu_activate(ctx, 0); | ||
309 | if (ret) { | ||
310 | spu_release(ctx); | ||
311 | goto out; | ||
312 | } | ||
313 | } else { | ||
314 | /* | ||
315 | * We have to update the scheduling priority under active_mutex | ||
316 | * to protect against find_victim(). | ||
317 | */ | ||
318 | spu_update_sched_info(ctx); | ||
319 | } | ||
304 | 320 | ||
305 | ret = spu_run_init(ctx, npc); | 321 | ret = spu_run_init(ctx, npc); |
306 | if (ret) { | 322 | if (ret) { |
@@ -325,16 +341,20 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
325 | 341 | ||
326 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { | 342 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { |
327 | ret = spu_reacquire_runnable(ctx, npc, &status); | 343 | ret = spu_reacquire_runnable(ctx, npc, &status); |
328 | if (ret) { | 344 | if (ret) |
329 | spu_stop_tick(ctx); | ||
330 | goto out2; | 345 | goto out2; |
331 | } | ||
332 | continue; | 346 | continue; |
333 | } | 347 | } |
334 | ret = spu_process_events(ctx); | 348 | ret = spu_process_events(ctx); |
335 | 349 | ||
336 | } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | | 350 | } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | |
337 | SPU_STATUS_STOPPED_BY_HALT))); | 351 | SPU_STATUS_STOPPED_BY_HALT | |
352 | SPU_STATUS_SINGLE_STEP))); | ||
353 | |||
354 | if ((status & SPU_STATUS_STOPPED_BY_STOP) && | ||
355 | (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) && | ||
356 | (ctx->state == SPU_STATE_RUNNABLE)) | ||
357 | ctx->stats.libassist++; | ||
338 | 358 | ||
339 | ctx->ops->master_stop(ctx); | 359 | ctx->ops->master_stop(ctx); |
340 | ret = spu_run_fini(ctx, npc, &status); | 360 | ret = spu_run_fini(ctx, npc, &status); |
@@ -344,10 +364,15 @@ out2: | |||
344 | if ((ret == 0) || | 364 | if ((ret == 0) || |
345 | ((ret == -ERESTARTSYS) && | 365 | ((ret == -ERESTARTSYS) && |
346 | ((status & SPU_STATUS_STOPPED_BY_HALT) || | 366 | ((status & SPU_STATUS_STOPPED_BY_HALT) || |
367 | (status & SPU_STATUS_SINGLE_STEP) || | ||
347 | ((status & SPU_STATUS_STOPPED_BY_STOP) && | 368 | ((status & SPU_STATUS_STOPPED_BY_STOP) && |
348 | (status >> SPU_STOP_STATUS_SHIFT != 0x2104))))) | 369 | (status >> SPU_STOP_STATUS_SHIFT != 0x2104))))) |
349 | ret = status; | 370 | ret = status; |
350 | 371 | ||
372 | /* Note: we don't need to force_sig SIGTRAP on single-step | ||
373 | * since we have TIF_SINGLESTEP set, thus the kernel will do | ||
374 | * it upon return from the syscall anyawy | ||
375 | */ | ||
351 | if ((status & SPU_STATUS_STOPPED_BY_STOP) | 376 | if ((status & SPU_STATUS_STOPPED_BY_STOP) |
352 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { | 377 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { |
353 | force_sig(SIGTRAP, current); | 378 | force_sig(SIGTRAP, current); |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 3b831e07f1ed..e5b4dd1db286 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -35,6 +35,10 @@ | |||
35 | #include <linux/numa.h> | 35 | #include <linux/numa.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/notifier.h> | 37 | #include <linux/notifier.h> |
38 | #include <linux/kthread.h> | ||
39 | #include <linux/pid_namespace.h> | ||
40 | #include <linux/proc_fs.h> | ||
41 | #include <linux/seq_file.h> | ||
38 | 42 | ||
39 | #include <asm/io.h> | 43 | #include <asm/io.h> |
40 | #include <asm/mmu_context.h> | 44 | #include <asm/mmu_context.h> |
@@ -43,54 +47,126 @@ | |||
43 | #include <asm/spu_priv1.h> | 47 | #include <asm/spu_priv1.h> |
44 | #include "spufs.h" | 48 | #include "spufs.h" |
45 | 49 | ||
46 | #define SPU_TIMESLICE (HZ) | ||
47 | |||
48 | struct spu_prio_array { | 50 | struct spu_prio_array { |
49 | DECLARE_BITMAP(bitmap, MAX_PRIO); | 51 | DECLARE_BITMAP(bitmap, MAX_PRIO); |
50 | struct list_head runq[MAX_PRIO]; | 52 | struct list_head runq[MAX_PRIO]; |
51 | spinlock_t runq_lock; | 53 | spinlock_t runq_lock; |
52 | struct list_head active_list[MAX_NUMNODES]; | 54 | struct list_head active_list[MAX_NUMNODES]; |
53 | struct mutex active_mutex[MAX_NUMNODES]; | 55 | struct mutex active_mutex[MAX_NUMNODES]; |
56 | int nr_active[MAX_NUMNODES]; | ||
57 | int nr_waiting; | ||
54 | }; | 58 | }; |
55 | 59 | ||
60 | static unsigned long spu_avenrun[3]; | ||
56 | static struct spu_prio_array *spu_prio; | 61 | static struct spu_prio_array *spu_prio; |
57 | static struct workqueue_struct *spu_sched_wq; | 62 | static struct task_struct *spusched_task; |
63 | static struct timer_list spusched_timer; | ||
64 | |||
65 | /* | ||
66 | * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). | ||
67 | */ | ||
68 | #define NORMAL_PRIO 120 | ||
69 | |||
70 | /* | ||
71 | * Frequency of the spu scheduler tick. By default we do one SPU scheduler | ||
72 | * tick for every 10 CPU scheduler ticks. | ||
73 | */ | ||
74 | #define SPUSCHED_TICK (10) | ||
58 | 75 | ||
59 | static inline int node_allowed(int node) | 76 | /* |
77 | * These are the 'tuning knobs' of the scheduler: | ||
78 | * | ||
79 | * Minimum timeslice is 5 msecs (or 1 spu scheduler tick, whichever is | ||
80 | * larger), default timeslice is 100 msecs, maximum timeslice is 800 msecs. | ||
81 | */ | ||
82 | #define MIN_SPU_TIMESLICE max(5 * HZ / (1000 * SPUSCHED_TICK), 1) | ||
83 | #define DEF_SPU_TIMESLICE (100 * HZ / (1000 * SPUSCHED_TICK)) | ||
84 | |||
85 | #define MAX_USER_PRIO (MAX_PRIO - MAX_RT_PRIO) | ||
86 | #define SCALE_PRIO(x, prio) \ | ||
87 | max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE) | ||
88 | |||
89 | /* | ||
90 | * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values: | ||
91 | * [800ms ... 100ms ... 5ms] | ||
92 | * | ||
93 | * The higher a thread's priority, the bigger timeslices | ||
94 | * it gets during one round of execution. But even the lowest | ||
95 | * priority thread gets MIN_TIMESLICE worth of execution time. | ||
96 | */ | ||
97 | void spu_set_timeslice(struct spu_context *ctx) | ||
60 | { | 98 | { |
61 | cpumask_t mask; | 99 | if (ctx->prio < NORMAL_PRIO) |
100 | ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio); | ||
101 | else | ||
102 | ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio); | ||
103 | } | ||
62 | 104 | ||
63 | if (!nr_cpus_node(node)) | 105 | /* |
64 | return 0; | 106 | * Update scheduling information from the owning thread. |
65 | mask = node_to_cpumask(node); | 107 | */ |
66 | if (!cpus_intersects(mask, current->cpus_allowed)) | 108 | void __spu_update_sched_info(struct spu_context *ctx) |
67 | return 0; | 109 | { |
68 | return 1; | 110 | /* |
111 | * 32-Bit assignment are atomic on powerpc, and we don't care about | ||
112 | * memory ordering here because retriving the controlling thread is | ||
113 | * per defintion racy. | ||
114 | */ | ||
115 | ctx->tid = current->pid; | ||
116 | |||
117 | /* | ||
118 | * We do our own priority calculations, so we normally want | ||
119 | * ->static_prio to start with. Unfortunately thies field | ||
120 | * contains junk for threads with a realtime scheduling | ||
121 | * policy so we have to look at ->prio in this case. | ||
122 | */ | ||
123 | if (rt_prio(current->prio)) | ||
124 | ctx->prio = current->prio; | ||
125 | else | ||
126 | ctx->prio = current->static_prio; | ||
127 | ctx->policy = current->policy; | ||
128 | |||
129 | /* | ||
130 | * A lot of places that don't hold active_mutex poke into | ||
131 | * cpus_allowed, including grab_runnable_context which | ||
132 | * already holds the runq_lock. So abuse runq_lock | ||
133 | * to protect this field aswell. | ||
134 | */ | ||
135 | spin_lock(&spu_prio->runq_lock); | ||
136 | ctx->cpus_allowed = current->cpus_allowed; | ||
137 | spin_unlock(&spu_prio->runq_lock); | ||
69 | } | 138 | } |
70 | 139 | ||
71 | void spu_start_tick(struct spu_context *ctx) | 140 | void spu_update_sched_info(struct spu_context *ctx) |
72 | { | 141 | { |
73 | if (ctx->policy == SCHED_RR) { | 142 | int node = ctx->spu->node; |
74 | /* | 143 | |
75 | * Make sure the exiting bit is cleared. | 144 | mutex_lock(&spu_prio->active_mutex[node]); |
76 | */ | 145 | __spu_update_sched_info(ctx); |
77 | clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags); | 146 | mutex_unlock(&spu_prio->active_mutex[node]); |
78 | mb(); | ||
79 | queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); | ||
80 | } | ||
81 | } | 147 | } |
82 | 148 | ||
83 | void spu_stop_tick(struct spu_context *ctx) | 149 | static int __node_allowed(struct spu_context *ctx, int node) |
84 | { | 150 | { |
85 | if (ctx->policy == SCHED_RR) { | 151 | if (nr_cpus_node(node)) { |
86 | /* | 152 | cpumask_t mask = node_to_cpumask(node); |
87 | * While the work can be rearming normally setting this flag | 153 | |
88 | * makes sure it does not rearm itself anymore. | 154 | if (cpus_intersects(mask, ctx->cpus_allowed)) |
89 | */ | 155 | return 1; |
90 | set_bit(SPU_SCHED_EXITING, &ctx->sched_flags); | ||
91 | mb(); | ||
92 | cancel_delayed_work(&ctx->sched_work); | ||
93 | } | 156 | } |
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int node_allowed(struct spu_context *ctx, int node) | ||
162 | { | ||
163 | int rval; | ||
164 | |||
165 | spin_lock(&spu_prio->runq_lock); | ||
166 | rval = __node_allowed(ctx, node); | ||
167 | spin_unlock(&spu_prio->runq_lock); | ||
168 | |||
169 | return rval; | ||
94 | } | 170 | } |
95 | 171 | ||
96 | /** | 172 | /** |
@@ -99,9 +175,18 @@ void spu_stop_tick(struct spu_context *ctx) | |||
99 | */ | 175 | */ |
100 | static void spu_add_to_active_list(struct spu *spu) | 176 | static void spu_add_to_active_list(struct spu *spu) |
101 | { | 177 | { |
102 | mutex_lock(&spu_prio->active_mutex[spu->node]); | 178 | int node = spu->node; |
103 | list_add_tail(&spu->list, &spu_prio->active_list[spu->node]); | 179 | |
104 | mutex_unlock(&spu_prio->active_mutex[spu->node]); | 180 | mutex_lock(&spu_prio->active_mutex[node]); |
181 | spu_prio->nr_active[node]++; | ||
182 | list_add_tail(&spu->list, &spu_prio->active_list[node]); | ||
183 | mutex_unlock(&spu_prio->active_mutex[node]); | ||
184 | } | ||
185 | |||
186 | static void __spu_remove_from_active_list(struct spu *spu) | ||
187 | { | ||
188 | list_del_init(&spu->list); | ||
189 | spu_prio->nr_active[spu->node]--; | ||
105 | } | 190 | } |
106 | 191 | ||
107 | /** | 192 | /** |
@@ -113,7 +198,7 @@ static void spu_remove_from_active_list(struct spu *spu) | |||
113 | int node = spu->node; | 198 | int node = spu->node; |
114 | 199 | ||
115 | mutex_lock(&spu_prio->active_mutex[node]); | 200 | mutex_lock(&spu_prio->active_mutex[node]); |
116 | list_del_init(&spu->list); | 201 | __spu_remove_from_active_list(spu); |
117 | mutex_unlock(&spu_prio->active_mutex[node]); | 202 | mutex_unlock(&spu_prio->active_mutex[node]); |
118 | } | 203 | } |
119 | 204 | ||
@@ -144,6 +229,10 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | |||
144 | { | 229 | { |
145 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, | 230 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, |
146 | spu->number, spu->node); | 231 | spu->number, spu->node); |
232 | |||
233 | ctx->stats.slb_flt_base = spu->stats.slb_flt; | ||
234 | ctx->stats.class2_intr_base = spu->stats.class2_intr; | ||
235 | |||
147 | spu->ctx = ctx; | 236 | spu->ctx = ctx; |
148 | spu->flags = 0; | 237 | spu->flags = 0; |
149 | ctx->spu = spu; | 238 | ctx->spu = spu; |
@@ -161,8 +250,8 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | |||
161 | spu->timestamp = jiffies; | 250 | spu->timestamp = jiffies; |
162 | spu_cpu_affinity_set(spu, raw_smp_processor_id()); | 251 | spu_cpu_affinity_set(spu, raw_smp_processor_id()); |
163 | spu_switch_notify(spu, ctx); | 252 | spu_switch_notify(spu, ctx); |
164 | spu_add_to_active_list(spu); | ||
165 | ctx->state = SPU_STATE_RUNNABLE; | 253 | ctx->state = SPU_STATE_RUNNABLE; |
254 | spu_switch_state(spu, SPU_UTIL_SYSTEM); | ||
166 | } | 255 | } |
167 | 256 | ||
168 | /** | 257 | /** |
@@ -175,7 +264,8 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
175 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, | 264 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, |
176 | spu->pid, spu->number, spu->node); | 265 | spu->pid, spu->number, spu->node); |
177 | 266 | ||
178 | spu_remove_from_active_list(spu); | 267 | spu_switch_state(spu, SPU_UTIL_IDLE); |
268 | |||
179 | spu_switch_notify(spu, NULL); | 269 | spu_switch_notify(spu, NULL); |
180 | spu_unmap_mappings(ctx); | 270 | spu_unmap_mappings(ctx); |
181 | spu_save(&ctx->csa, spu); | 271 | spu_save(&ctx->csa, spu); |
@@ -192,6 +282,11 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
192 | ctx->spu = NULL; | 282 | ctx->spu = NULL; |
193 | spu->flags = 0; | 283 | spu->flags = 0; |
194 | spu->ctx = NULL; | 284 | spu->ctx = NULL; |
285 | |||
286 | ctx->stats.slb_flt += | ||
287 | (spu->stats.slb_flt - ctx->stats.slb_flt_base); | ||
288 | ctx->stats.class2_intr += | ||
289 | (spu->stats.class2_intr - ctx->stats.class2_intr_base); | ||
195 | } | 290 | } |
196 | 291 | ||
197 | /** | 292 | /** |
@@ -200,20 +295,39 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | |||
200 | */ | 295 | */ |
201 | static void __spu_add_to_rq(struct spu_context *ctx) | 296 | static void __spu_add_to_rq(struct spu_context *ctx) |
202 | { | 297 | { |
203 | int prio = ctx->prio; | 298 | /* |
204 | 299 | * Unfortunately this code path can be called from multiple threads | |
205 | list_add_tail(&ctx->rq, &spu_prio->runq[prio]); | 300 | * on behalf of a single context due to the way the problem state |
206 | set_bit(prio, spu_prio->bitmap); | 301 | * mmap support works. |
302 | * | ||
303 | * Fortunately we need to wake up all these threads at the same time | ||
304 | * and can simply skip the runqueue addition for every but the first | ||
305 | * thread getting into this codepath. | ||
306 | * | ||
307 | * It's still quite hacky, and long-term we should proxy all other | ||
308 | * threads through the owner thread so that spu_run is in control | ||
309 | * of all the scheduling activity for a given context. | ||
310 | */ | ||
311 | if (list_empty(&ctx->rq)) { | ||
312 | list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]); | ||
313 | set_bit(ctx->prio, spu_prio->bitmap); | ||
314 | if (!spu_prio->nr_waiting++) | ||
315 | __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); | ||
316 | } | ||
207 | } | 317 | } |
208 | 318 | ||
209 | static void __spu_del_from_rq(struct spu_context *ctx) | 319 | static void __spu_del_from_rq(struct spu_context *ctx) |
210 | { | 320 | { |
211 | int prio = ctx->prio; | 321 | int prio = ctx->prio; |
212 | 322 | ||
213 | if (!list_empty(&ctx->rq)) | 323 | if (!list_empty(&ctx->rq)) { |
324 | if (!--spu_prio->nr_waiting) | ||
325 | del_timer(&spusched_timer); | ||
214 | list_del_init(&ctx->rq); | 326 | list_del_init(&ctx->rq); |
215 | if (list_empty(&spu_prio->runq[prio])) | 327 | |
216 | clear_bit(prio, spu_prio->bitmap); | 328 | if (list_empty(&spu_prio->runq[prio])) |
329 | clear_bit(prio, spu_prio->bitmap); | ||
330 | } | ||
217 | } | 331 | } |
218 | 332 | ||
219 | static void spu_prio_wait(struct spu_context *ctx) | 333 | static void spu_prio_wait(struct spu_context *ctx) |
@@ -244,7 +358,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
244 | 358 | ||
245 | for (n = 0; n < MAX_NUMNODES; n++, node++) { | 359 | for (n = 0; n < MAX_NUMNODES; n++, node++) { |
246 | node = (node < MAX_NUMNODES) ? node : 0; | 360 | node = (node < MAX_NUMNODES) ? node : 0; |
247 | if (!node_allowed(node)) | 361 | if (!node_allowed(ctx, node)) |
248 | continue; | 362 | continue; |
249 | spu = spu_alloc_node(node); | 363 | spu = spu_alloc_node(node); |
250 | if (spu) | 364 | if (spu) |
@@ -276,15 +390,15 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
276 | node = cpu_to_node(raw_smp_processor_id()); | 390 | node = cpu_to_node(raw_smp_processor_id()); |
277 | for (n = 0; n < MAX_NUMNODES; n++, node++) { | 391 | for (n = 0; n < MAX_NUMNODES; n++, node++) { |
278 | node = (node < MAX_NUMNODES) ? node : 0; | 392 | node = (node < MAX_NUMNODES) ? node : 0; |
279 | if (!node_allowed(node)) | 393 | if (!node_allowed(ctx, node)) |
280 | continue; | 394 | continue; |
281 | 395 | ||
282 | mutex_lock(&spu_prio->active_mutex[node]); | 396 | mutex_lock(&spu_prio->active_mutex[node]); |
283 | list_for_each_entry(spu, &spu_prio->active_list[node], list) { | 397 | list_for_each_entry(spu, &spu_prio->active_list[node], list) { |
284 | struct spu_context *tmp = spu->ctx; | 398 | struct spu_context *tmp = spu->ctx; |
285 | 399 | ||
286 | if (tmp->rt_priority < ctx->rt_priority && | 400 | if (tmp->prio > ctx->prio && |
287 | (!victim || tmp->rt_priority < victim->rt_priority)) | 401 | (!victim || tmp->prio > victim->prio)) |
288 | victim = spu->ctx; | 402 | victim = spu->ctx; |
289 | } | 403 | } |
290 | mutex_unlock(&spu_prio->active_mutex[node]); | 404 | mutex_unlock(&spu_prio->active_mutex[node]); |
@@ -312,7 +426,10 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
312 | victim = NULL; | 426 | victim = NULL; |
313 | goto restart; | 427 | goto restart; |
314 | } | 428 | } |
429 | spu_remove_from_active_list(spu); | ||
315 | spu_unbind_context(spu, victim); | 430 | spu_unbind_context(spu, victim); |
431 | victim->stats.invol_ctx_switch++; | ||
432 | spu->stats.invol_ctx_switch++; | ||
316 | mutex_unlock(&victim->state_mutex); | 433 | mutex_unlock(&victim->state_mutex); |
317 | /* | 434 | /* |
318 | * We need to break out of the wait loop in spu_run | 435 | * We need to break out of the wait loop in spu_run |
@@ -338,22 +455,30 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
338 | */ | 455 | */ |
339 | int spu_activate(struct spu_context *ctx, unsigned long flags) | 456 | int spu_activate(struct spu_context *ctx, unsigned long flags) |
340 | { | 457 | { |
341 | 458 | spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM); | |
342 | if (ctx->spu) | ||
343 | return 0; | ||
344 | 459 | ||
345 | do { | 460 | do { |
346 | struct spu *spu; | 461 | struct spu *spu; |
347 | 462 | ||
463 | /* | ||
464 | * If there are multiple threads waiting for a single context | ||
465 | * only one actually binds the context while the others will | ||
466 | * only be able to acquire the state_mutex once the context | ||
467 | * already is in runnable state. | ||
468 | */ | ||
469 | if (ctx->spu) | ||
470 | return 0; | ||
471 | |||
348 | spu = spu_get_idle(ctx); | 472 | spu = spu_get_idle(ctx); |
349 | /* | 473 | /* |
350 | * If this is a realtime thread we try to get it running by | 474 | * If this is a realtime thread we try to get it running by |
351 | * preempting a lower priority thread. | 475 | * preempting a lower priority thread. |
352 | */ | 476 | */ |
353 | if (!spu && ctx->rt_priority) | 477 | if (!spu && rt_prio(ctx->prio)) |
354 | spu = find_victim(ctx); | 478 | spu = find_victim(ctx); |
355 | if (spu) { | 479 | if (spu) { |
356 | spu_bind_context(spu, ctx); | 480 | spu_bind_context(spu, ctx); |
481 | spu_add_to_active_list(spu); | ||
357 | return 0; | 482 | return 0; |
358 | } | 483 | } |
359 | 484 | ||
@@ -369,23 +494,28 @@ int spu_activate(struct spu_context *ctx, unsigned long flags) | |||
369 | * Remove the highest priority context on the runqueue and return it | 494 | * Remove the highest priority context on the runqueue and return it |
370 | * to the caller. Returns %NULL if no runnable context was found. | 495 | * to the caller. Returns %NULL if no runnable context was found. |
371 | */ | 496 | */ |
372 | static struct spu_context *grab_runnable_context(int prio) | 497 | static struct spu_context *grab_runnable_context(int prio, int node) |
373 | { | 498 | { |
374 | struct spu_context *ctx = NULL; | 499 | struct spu_context *ctx; |
375 | int best; | 500 | int best; |
376 | 501 | ||
377 | spin_lock(&spu_prio->runq_lock); | 502 | spin_lock(&spu_prio->runq_lock); |
378 | best = sched_find_first_bit(spu_prio->bitmap); | 503 | best = sched_find_first_bit(spu_prio->bitmap); |
379 | if (best < prio) { | 504 | while (best < prio) { |
380 | struct list_head *rq = &spu_prio->runq[best]; | 505 | struct list_head *rq = &spu_prio->runq[best]; |
381 | 506 | ||
382 | BUG_ON(list_empty(rq)); | 507 | list_for_each_entry(ctx, rq, rq) { |
383 | 508 | /* XXX(hch): check for affinity here aswell */ | |
384 | ctx = list_entry(rq->next, struct spu_context, rq); | 509 | if (__node_allowed(ctx, node)) { |
385 | __spu_del_from_rq(ctx); | 510 | __spu_del_from_rq(ctx); |
511 | goto found; | ||
512 | } | ||
513 | } | ||
514 | best++; | ||
386 | } | 515 | } |
516 | ctx = NULL; | ||
517 | found: | ||
387 | spin_unlock(&spu_prio->runq_lock); | 518 | spin_unlock(&spu_prio->runq_lock); |
388 | |||
389 | return ctx; | 519 | return ctx; |
390 | } | 520 | } |
391 | 521 | ||
@@ -395,9 +525,12 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) | |||
395 | struct spu_context *new = NULL; | 525 | struct spu_context *new = NULL; |
396 | 526 | ||
397 | if (spu) { | 527 | if (spu) { |
398 | new = grab_runnable_context(max_prio); | 528 | new = grab_runnable_context(max_prio, spu->node); |
399 | if (new || force) { | 529 | if (new || force) { |
530 | spu_remove_from_active_list(spu); | ||
400 | spu_unbind_context(spu, ctx); | 531 | spu_unbind_context(spu, ctx); |
532 | ctx->stats.vol_ctx_switch++; | ||
533 | spu->stats.vol_ctx_switch++; | ||
401 | spu_free(spu); | 534 | spu_free(spu); |
402 | if (new) | 535 | if (new) |
403 | wake_up(&new->stop_wq); | 536 | wake_up(&new->stop_wq); |
@@ -417,7 +550,17 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) | |||
417 | */ | 550 | */ |
418 | void spu_deactivate(struct spu_context *ctx) | 551 | void spu_deactivate(struct spu_context *ctx) |
419 | { | 552 | { |
553 | /* | ||
554 | * We must never reach this for a nosched context, | ||
555 | * but handle the case gracefull instead of panicing. | ||
556 | */ | ||
557 | if (ctx->flags & SPU_CREATE_NOSCHED) { | ||
558 | WARN_ON(1); | ||
559 | return; | ||
560 | } | ||
561 | |||
420 | __spu_deactivate(ctx, 1, MAX_PRIO); | 562 | __spu_deactivate(ctx, 1, MAX_PRIO); |
563 | spuctx_switch_state(ctx, SPUCTX_UTIL_USER); | ||
421 | } | 564 | } |
422 | 565 | ||
423 | /** | 566 | /** |
@@ -432,56 +575,178 @@ void spu_yield(struct spu_context *ctx) | |||
432 | { | 575 | { |
433 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { | 576 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { |
434 | mutex_lock(&ctx->state_mutex); | 577 | mutex_lock(&ctx->state_mutex); |
435 | __spu_deactivate(ctx, 0, MAX_PRIO); | 578 | if (__spu_deactivate(ctx, 0, MAX_PRIO)) |
579 | spuctx_switch_state(ctx, SPUCTX_UTIL_USER); | ||
580 | else { | ||
581 | spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED); | ||
582 | spu_switch_state(ctx->spu, SPU_UTIL_USER); | ||
583 | } | ||
436 | mutex_unlock(&ctx->state_mutex); | 584 | mutex_unlock(&ctx->state_mutex); |
437 | } | 585 | } |
438 | } | 586 | } |
439 | 587 | ||
440 | void spu_sched_tick(struct work_struct *work) | 588 | static void spusched_tick(struct spu_context *ctx) |
441 | { | 589 | { |
442 | struct spu_context *ctx = | 590 | if (ctx->flags & SPU_CREATE_NOSCHED) |
443 | container_of(work, struct spu_context, sched_work.work); | 591 | return; |
444 | int preempted; | 592 | if (ctx->policy == SCHED_FIFO) |
593 | return; | ||
594 | |||
595 | if (--ctx->time_slice) | ||
596 | return; | ||
445 | 597 | ||
446 | /* | 598 | /* |
447 | * If this context is being stopped avoid rescheduling from the | 599 | * Unfortunately active_mutex ranks outside of state_mutex, so |
448 | * scheduler tick because we would block on the state_mutex. | 600 | * we have to trylock here. If we fail give the context another |
449 | * The caller will yield the spu later on anyway. | 601 | * tick and try again. |
450 | */ | 602 | */ |
451 | if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) | 603 | if (mutex_trylock(&ctx->state_mutex)) { |
452 | return; | 604 | struct spu *spu = ctx->spu; |
605 | struct spu_context *new; | ||
453 | 606 | ||
454 | mutex_lock(&ctx->state_mutex); | 607 | new = grab_runnable_context(ctx->prio + 1, spu->node); |
455 | preempted = __spu_deactivate(ctx, 0, ctx->prio + 1); | 608 | if (new) { |
456 | mutex_unlock(&ctx->state_mutex); | ||
457 | 609 | ||
458 | if (preempted) { | 610 | __spu_remove_from_active_list(spu); |
459 | /* | 611 | spu_unbind_context(spu, ctx); |
460 | * We need to break out of the wait loop in spu_run manually | 612 | ctx->stats.invol_ctx_switch++; |
461 | * to ensure this context gets put on the runqueue again | 613 | spu->stats.invol_ctx_switch++; |
462 | * ASAP. | 614 | spu_free(spu); |
463 | */ | 615 | wake_up(&new->stop_wq); |
464 | wake_up(&ctx->stop_wq); | 616 | /* |
617 | * We need to break out of the wait loop in | ||
618 | * spu_run manually to ensure this context | ||
619 | * gets put on the runqueue again ASAP. | ||
620 | */ | ||
621 | wake_up(&ctx->stop_wq); | ||
622 | } | ||
623 | spu_set_timeslice(ctx); | ||
624 | mutex_unlock(&ctx->state_mutex); | ||
465 | } else { | 625 | } else { |
466 | spu_start_tick(ctx); | 626 | ctx->time_slice++; |
467 | } | 627 | } |
468 | } | 628 | } |
469 | 629 | ||
470 | int __init spu_sched_init(void) | 630 | /** |
631 | * count_active_contexts - count nr of active tasks | ||
632 | * | ||
633 | * Return the number of tasks currently running or waiting to run. | ||
634 | * | ||
635 | * Note that we don't take runq_lock / active_mutex here. Reading | ||
636 | * a single 32bit value is atomic on powerpc, and we don't care | ||
637 | * about memory ordering issues here. | ||
638 | */ | ||
639 | static unsigned long count_active_contexts(void) | ||
471 | { | 640 | { |
472 | int i; | 641 | int nr_active = 0, node; |
473 | 642 | ||
474 | spu_sched_wq = create_singlethread_workqueue("spusched"); | 643 | for (node = 0; node < MAX_NUMNODES; node++) |
475 | if (!spu_sched_wq) | 644 | nr_active += spu_prio->nr_active[node]; |
476 | return 1; | 645 | nr_active += spu_prio->nr_waiting; |
477 | 646 | ||
478 | spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); | 647 | return nr_active; |
479 | if (!spu_prio) { | 648 | } |
480 | printk(KERN_WARNING "%s: Unable to allocate priority queue.\n", | 649 | |
481 | __FUNCTION__); | 650 | /** |
482 | destroy_workqueue(spu_sched_wq); | 651 | * spu_calc_load - given tick count, update the avenrun load estimates. |
483 | return 1; | 652 | * @tick: tick count |
653 | * | ||
654 | * No locking against reading these values from userspace, as for | ||
655 | * the CPU loadavg code. | ||
656 | */ | ||
657 | static void spu_calc_load(unsigned long ticks) | ||
658 | { | ||
659 | unsigned long active_tasks; /* fixed-point */ | ||
660 | static int count = LOAD_FREQ; | ||
661 | |||
662 | count -= ticks; | ||
663 | |||
664 | if (unlikely(count < 0)) { | ||
665 | active_tasks = count_active_contexts() * FIXED_1; | ||
666 | do { | ||
667 | CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks); | ||
668 | CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks); | ||
669 | CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks); | ||
670 | count += LOAD_FREQ; | ||
671 | } while (count < 0); | ||
484 | } | 672 | } |
673 | } | ||
674 | |||
675 | static void spusched_wake(unsigned long data) | ||
676 | { | ||
677 | mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); | ||
678 | wake_up_process(spusched_task); | ||
679 | spu_calc_load(SPUSCHED_TICK); | ||
680 | } | ||
681 | |||
682 | static int spusched_thread(void *unused) | ||
683 | { | ||
684 | struct spu *spu, *next; | ||
685 | int node; | ||
686 | |||
687 | while (!kthread_should_stop()) { | ||
688 | set_current_state(TASK_INTERRUPTIBLE); | ||
689 | schedule(); | ||
690 | for (node = 0; node < MAX_NUMNODES; node++) { | ||
691 | mutex_lock(&spu_prio->active_mutex[node]); | ||
692 | list_for_each_entry_safe(spu, next, | ||
693 | &spu_prio->active_list[node], | ||
694 | list) | ||
695 | spusched_tick(spu->ctx); | ||
696 | mutex_unlock(&spu_prio->active_mutex[node]); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | #define LOAD_INT(x) ((x) >> FSHIFT) | ||
704 | #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) | ||
705 | |||
706 | static int show_spu_loadavg(struct seq_file *s, void *private) | ||
707 | { | ||
708 | int a, b, c; | ||
709 | |||
710 | a = spu_avenrun[0] + (FIXED_1/200); | ||
711 | b = spu_avenrun[1] + (FIXED_1/200); | ||
712 | c = spu_avenrun[2] + (FIXED_1/200); | ||
713 | |||
714 | /* | ||
715 | * Note that last_pid doesn't really make much sense for the | ||
716 | * SPU loadavg (it even seems very odd on the CPU side..), | ||
717 | * but we include it here to have a 100% compatible interface. | ||
718 | */ | ||
719 | seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n", | ||
720 | LOAD_INT(a), LOAD_FRAC(a), | ||
721 | LOAD_INT(b), LOAD_FRAC(b), | ||
722 | LOAD_INT(c), LOAD_FRAC(c), | ||
723 | count_active_contexts(), | ||
724 | atomic_read(&nr_spu_contexts), | ||
725 | current->nsproxy->pid_ns->last_pid); | ||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | static int spu_loadavg_open(struct inode *inode, struct file *file) | ||
730 | { | ||
731 | return single_open(file, show_spu_loadavg, NULL); | ||
732 | } | ||
733 | |||
734 | static const struct file_operations spu_loadavg_fops = { | ||
735 | .open = spu_loadavg_open, | ||
736 | .read = seq_read, | ||
737 | .llseek = seq_lseek, | ||
738 | .release = single_release, | ||
739 | }; | ||
740 | |||
741 | int __init spu_sched_init(void) | ||
742 | { | ||
743 | struct proc_dir_entry *entry; | ||
744 | int err = -ENOMEM, i; | ||
745 | |||
746 | spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); | ||
747 | if (!spu_prio) | ||
748 | goto out; | ||
749 | |||
485 | for (i = 0; i < MAX_PRIO; i++) { | 750 | for (i = 0; i < MAX_PRIO; i++) { |
486 | INIT_LIST_HEAD(&spu_prio->runq[i]); | 751 | INIT_LIST_HEAD(&spu_prio->runq[i]); |
487 | __clear_bit(i, spu_prio->bitmap); | 752 | __clear_bit(i, spu_prio->bitmap); |
@@ -492,7 +757,30 @@ int __init spu_sched_init(void) | |||
492 | INIT_LIST_HEAD(&spu_prio->active_list[i]); | 757 | INIT_LIST_HEAD(&spu_prio->active_list[i]); |
493 | } | 758 | } |
494 | spin_lock_init(&spu_prio->runq_lock); | 759 | spin_lock_init(&spu_prio->runq_lock); |
760 | |||
761 | setup_timer(&spusched_timer, spusched_wake, 0); | ||
762 | |||
763 | spusched_task = kthread_run(spusched_thread, NULL, "spusched"); | ||
764 | if (IS_ERR(spusched_task)) { | ||
765 | err = PTR_ERR(spusched_task); | ||
766 | goto out_free_spu_prio; | ||
767 | } | ||
768 | |||
769 | entry = create_proc_entry("spu_loadavg", 0, NULL); | ||
770 | if (!entry) | ||
771 | goto out_stop_kthread; | ||
772 | entry->proc_fops = &spu_loadavg_fops; | ||
773 | |||
774 | pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n", | ||
775 | SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE); | ||
495 | return 0; | 776 | return 0; |
777 | |||
778 | out_stop_kthread: | ||
779 | kthread_stop(spusched_task); | ||
780 | out_free_spu_prio: | ||
781 | kfree(spu_prio); | ||
782 | out: | ||
783 | return err; | ||
496 | } | 784 | } |
497 | 785 | ||
498 | void __exit spu_sched_exit(void) | 786 | void __exit spu_sched_exit(void) |
@@ -500,6 +788,11 @@ void __exit spu_sched_exit(void) | |||
500 | struct spu *spu, *tmp; | 788 | struct spu *spu, *tmp; |
501 | int node; | 789 | int node; |
502 | 790 | ||
791 | remove_proc_entry("spu_loadavg", NULL); | ||
792 | |||
793 | del_timer_sync(&spusched_timer); | ||
794 | kthread_stop(spusched_task); | ||
795 | |||
503 | for (node = 0; node < MAX_NUMNODES; node++) { | 796 | for (node = 0; node < MAX_NUMNODES; node++) { |
504 | mutex_lock(&spu_prio->active_mutex[node]); | 797 | mutex_lock(&spu_prio->active_mutex[node]); |
505 | list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node], | 798 | list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node], |
@@ -510,5 +803,4 @@ void __exit spu_sched_exit(void) | |||
510 | mutex_unlock(&spu_prio->active_mutex[node]); | 803 | mutex_unlock(&spu_prio->active_mutex[node]); |
511 | } | 804 | } |
512 | kfree(spu_prio); | 805 | kfree(spu_prio); |
513 | destroy_workqueue(spu_sched_wq); | ||
514 | } | 806 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore.c b/arch/powerpc/platforms/cell/spufs/spu_restore.c index 0bf723dcd677..4e19ed7a0756 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_restore.c +++ b/arch/powerpc/platforms/cell/spufs/spu_restore.c | |||
@@ -296,7 +296,7 @@ static inline void restore_complete(void) | |||
296 | * This code deviates from the documented sequence in the | 296 | * This code deviates from the documented sequence in the |
297 | * following aspects: | 297 | * following aspects: |
298 | * | 298 | * |
299 | * 1. The EA for LSCSA is passed from PPE in the | 299 | * 1. The EA for LSCSA is passed from PPE in the |
300 | * signal notification channels. | 300 | * signal notification channels. |
301 | * 2. The register spill area is pulled by SPU | 301 | * 2. The register spill area is pulled by SPU |
302 | * into LS, rather than pushed by PPE. | 302 | * into LS, rather than pushed by PPE. |
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save.c b/arch/powerpc/platforms/cell/spufs/spu_save.c index 196033b8a579..ae95cc1701e9 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_save.c +++ b/arch/powerpc/platforms/cell/spufs/spu_save.c | |||
@@ -44,7 +44,7 @@ static inline void save_event_mask(void) | |||
44 | * Read the SPU_RdEventMsk channel and save to the LSCSA. | 44 | * Read the SPU_RdEventMsk channel and save to the LSCSA. |
45 | */ | 45 | */ |
46 | offset = LSCSA_QW_OFFSET(event_mask); | 46 | offset = LSCSA_QW_OFFSET(event_mask); |
47 | regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask); | 47 | regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask); |
48 | } | 48 | } |
49 | 49 | ||
50 | static inline void save_tag_mask(void) | 50 | static inline void save_tag_mask(void) |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 47617e8014a5..08b3530288ac 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/cpumask.h> | ||
29 | 30 | ||
30 | #include <asm/spu.h> | 31 | #include <asm/spu.h> |
31 | #include <asm/spu_csa.h> | 32 | #include <asm/spu_csa.h> |
@@ -39,9 +40,17 @@ enum { | |||
39 | struct spu_context_ops; | 40 | struct spu_context_ops; |
40 | struct spu_gang; | 41 | struct spu_gang; |
41 | 42 | ||
42 | /* ctx->sched_flags */ | 43 | /* |
43 | enum { | 44 | * This is the state for spu utilization reporting to userspace. |
44 | SPU_SCHED_EXITING = 0, | 45 | * Because this state is visible to userspace it must never change and needs |
46 | * to be kept strictly separate from any internal state kept by the kernel. | ||
47 | */ | ||
48 | enum spuctx_execution_state { | ||
49 | SPUCTX_UTIL_USER = 0, | ||
50 | SPUCTX_UTIL_SYSTEM, | ||
51 | SPUCTX_UTIL_IOWAIT, | ||
52 | SPUCTX_UTIL_LOADED, | ||
53 | SPUCTX_UTIL_MAX | ||
45 | }; | 54 | }; |
46 | 55 | ||
47 | struct spu_context { | 56 | struct spu_context { |
@@ -81,13 +90,34 @@ struct spu_context { | |||
81 | struct list_head gang_list; | 90 | struct list_head gang_list; |
82 | struct spu_gang *gang; | 91 | struct spu_gang *gang; |
83 | 92 | ||
93 | /* owner thread */ | ||
94 | pid_t tid; | ||
95 | |||
84 | /* scheduler fields */ | 96 | /* scheduler fields */ |
85 | struct list_head rq; | 97 | struct list_head rq; |
86 | struct delayed_work sched_work; | 98 | unsigned int time_slice; |
87 | unsigned long sched_flags; | 99 | unsigned long sched_flags; |
88 | unsigned long rt_priority; | 100 | cpumask_t cpus_allowed; |
89 | int policy; | 101 | int policy; |
90 | int prio; | 102 | int prio; |
103 | |||
104 | /* statistics */ | ||
105 | struct { | ||
106 | /* updates protected by ctx->state_mutex */ | ||
107 | enum spuctx_execution_state execution_state; | ||
108 | unsigned long tstamp; /* time of last ctx switch */ | ||
109 | unsigned long times[SPUCTX_UTIL_MAX]; | ||
110 | unsigned long long vol_ctx_switch; | ||
111 | unsigned long long invol_ctx_switch; | ||
112 | unsigned long long min_flt; | ||
113 | unsigned long long maj_flt; | ||
114 | unsigned long long hash_flt; | ||
115 | unsigned long long slb_flt; | ||
116 | unsigned long long slb_flt_base; /* # at last ctx switch */ | ||
117 | unsigned long long class2_intr; | ||
118 | unsigned long long class2_intr_base; /* # at last ctx switch */ | ||
119 | unsigned long long libassist; | ||
120 | } stats; | ||
91 | }; | 121 | }; |
92 | 122 | ||
93 | struct spu_gang { | 123 | struct spu_gang { |
@@ -177,6 +207,7 @@ void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx); | |||
177 | int spufs_handle_class1(struct spu_context *ctx); | 207 | int spufs_handle_class1(struct spu_context *ctx); |
178 | 208 | ||
179 | /* context management */ | 209 | /* context management */ |
210 | extern atomic_t nr_spu_contexts; | ||
180 | static inline void spu_acquire(struct spu_context *ctx) | 211 | static inline void spu_acquire(struct spu_context *ctx) |
181 | { | 212 | { |
182 | mutex_lock(&ctx->state_mutex); | 213 | mutex_lock(&ctx->state_mutex); |
@@ -200,9 +231,9 @@ void spu_acquire_saved(struct spu_context *ctx); | |||
200 | int spu_activate(struct spu_context *ctx, unsigned long flags); | 231 | int spu_activate(struct spu_context *ctx, unsigned long flags); |
201 | void spu_deactivate(struct spu_context *ctx); | 232 | void spu_deactivate(struct spu_context *ctx); |
202 | void spu_yield(struct spu_context *ctx); | 233 | void spu_yield(struct spu_context *ctx); |
203 | void spu_start_tick(struct spu_context *ctx); | 234 | void spu_set_timeslice(struct spu_context *ctx); |
204 | void spu_stop_tick(struct spu_context *ctx); | 235 | void spu_update_sched_info(struct spu_context *ctx); |
205 | void spu_sched_tick(struct work_struct *work); | 236 | void __spu_update_sched_info(struct spu_context *ctx); |
206 | int __init spu_sched_init(void); | 237 | int __init spu_sched_init(void); |
207 | void __exit spu_sched_exit(void); | 238 | void __exit spu_sched_exit(void); |
208 | 239 | ||
@@ -210,7 +241,7 @@ extern char *isolated_loader; | |||
210 | 241 | ||
211 | /* | 242 | /* |
212 | * spufs_wait | 243 | * spufs_wait |
213 | * Same as wait_event_interruptible(), except that here | 244 | * Same as wait_event_interruptible(), except that here |
214 | * we need to call spu_release(ctx) before sleeping, and | 245 | * we need to call spu_release(ctx) before sleeping, and |
215 | * then spu_acquire(ctx) when awoken. | 246 | * then spu_acquire(ctx) when awoken. |
216 | */ | 247 | */ |
@@ -256,4 +287,37 @@ struct spufs_coredump_reader { | |||
256 | extern struct spufs_coredump_reader spufs_coredump_read[]; | 287 | extern struct spufs_coredump_reader spufs_coredump_read[]; |
257 | extern int spufs_coredump_num_notes; | 288 | extern int spufs_coredump_num_notes; |
258 | 289 | ||
290 | /* | ||
291 | * This function is a little bit too large for an inline, but | ||
292 | * as fault.c is built into the kernel we can't move it out of | ||
293 | * line. | ||
294 | */ | ||
295 | static inline void spuctx_switch_state(struct spu_context *ctx, | ||
296 | enum spuctx_execution_state new_state) | ||
297 | { | ||
298 | WARN_ON(!mutex_is_locked(&ctx->state_mutex)); | ||
299 | |||
300 | if (ctx->stats.execution_state != new_state) { | ||
301 | unsigned long curtime = jiffies; | ||
302 | |||
303 | ctx->stats.times[ctx->stats.execution_state] += | ||
304 | curtime - ctx->stats.tstamp; | ||
305 | ctx->stats.tstamp = curtime; | ||
306 | ctx->stats.execution_state = new_state; | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static inline void spu_switch_state(struct spu *spu, | ||
311 | enum spuctx_execution_state new_state) | ||
312 | { | ||
313 | if (spu->stats.utilization_state != new_state) { | ||
314 | unsigned long curtime = jiffies; | ||
315 | |||
316 | spu->stats.times[spu->stats.utilization_state] += | ||
317 | curtime - spu->stats.tstamp; | ||
318 | spu->stats.tstamp = curtime; | ||
319 | spu->stats.utilization_state = new_state; | ||
320 | } | ||
321 | } | ||
322 | |||
259 | #endif | 323 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 71a0b41adb8c..9c506ba08cdc 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
@@ -70,7 +70,7 @@ | |||
70 | } | 70 | } |
71 | #endif /* debug */ | 71 | #endif /* debug */ |
72 | 72 | ||
73 | #define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c)) | 73 | #define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c)) |
74 | 74 | ||
75 | static inline void acquire_spu_lock(struct spu *spu) | 75 | static inline void acquire_spu_lock(struct spu *spu) |
76 | { | 76 | { |
@@ -387,6 +387,19 @@ static inline void save_ppu_querytype(struct spu_state *csa, struct spu *spu) | |||
387 | csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW); | 387 | csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW); |
388 | } | 388 | } |
389 | 389 | ||
390 | static inline void save_ppu_tagstatus(struct spu_state *csa, struct spu *spu) | ||
391 | { | ||
392 | struct spu_problem __iomem *prob = spu->problem; | ||
393 | |||
394 | /* Save the Prxy_TagStatus register in the CSA. | ||
395 | * | ||
396 | * It is unnecessary to restore dma_tagstatus_R, however, | ||
397 | * dma_tagstatus_R in the CSA is accessed via backing_ops, so | ||
398 | * we must save it. | ||
399 | */ | ||
400 | csa->prob.dma_tagstatus_R = in_be32(&prob->dma_tagstatus_R); | ||
401 | } | ||
402 | |||
390 | static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu) | 403 | static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu) |
391 | { | 404 | { |
392 | struct spu_priv2 __iomem *priv2 = spu->priv2; | 405 | struct spu_priv2 __iomem *priv2 = spu->priv2; |
@@ -1812,6 +1825,7 @@ static void save_csa(struct spu_state *prev, struct spu *spu) | |||
1812 | save_mfc_queues(prev, spu); /* Step 19. */ | 1825 | save_mfc_queues(prev, spu); /* Step 19. */ |
1813 | save_ppu_querymask(prev, spu); /* Step 20. */ | 1826 | save_ppu_querymask(prev, spu); /* Step 20. */ |
1814 | save_ppu_querytype(prev, spu); /* Step 21. */ | 1827 | save_ppu_querytype(prev, spu); /* Step 21. */ |
1828 | save_ppu_tagstatus(prev, spu); /* NEW. */ | ||
1815 | save_mfc_csr_tsq(prev, spu); /* Step 22. */ | 1829 | save_mfc_csr_tsq(prev, spu); /* Step 22. */ |
1816 | save_mfc_csr_cmd(prev, spu); /* Step 23. */ | 1830 | save_mfc_csr_cmd(prev, spu); /* Step 23. */ |
1817 | save_mfc_csr_ato(prev, spu); /* Step 24. */ | 1831 | save_mfc_csr_ato(prev, spu); /* Step 24. */ |
@@ -1930,7 +1944,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) | |||
1930 | reset_spu_privcntl(prev, spu); /* Step 16. */ | 1944 | reset_spu_privcntl(prev, spu); /* Step 16. */ |
1931 | reset_spu_lslr(prev, spu); /* Step 17. */ | 1945 | reset_spu_lslr(prev, spu); /* Step 17. */ |
1932 | setup_mfc_sr1(prev, spu); /* Step 18. */ | 1946 | setup_mfc_sr1(prev, spu); /* Step 18. */ |
1933 | spu_invalidate_slbs(spu); /* Step 19. */ | 1947 | spu_invalidate_slbs(spu); /* Step 19. */ |
1934 | reset_ch_part1(prev, spu); /* Step 20. */ | 1948 | reset_ch_part1(prev, spu); /* Step 20. */ |
1935 | reset_ch_part2(prev, spu); /* Step 21. */ | 1949 | reset_ch_part2(prev, spu); /* Step 21. */ |
1936 | enable_interrupts(prev, spu); /* Step 22. */ | 1950 | enable_interrupts(prev, spu); /* Step 22. */ |
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig index d2c690531963..22b4b4e3b6f0 100644 --- a/arch/powerpc/platforms/chrp/Kconfig +++ b/arch/powerpc/platforms/chrp/Kconfig | |||
@@ -8,4 +8,5 @@ config PPC_CHRP | |||
8 | select PPC_MPC106 | 8 | select PPC_MPC106 |
9 | select PPC_UDBG_16550 | 9 | select PPC_UDBG_16550 |
10 | select PPC_NATIVE | 10 | select PPC_NATIVE |
11 | select PCI | ||
11 | default y | 12 | default y |
diff --git a/arch/powerpc/platforms/chrp/Makefile b/arch/powerpc/platforms/chrp/Makefile index 902feb1ac431..4b3bfadc70fa 100644 --- a/arch/powerpc/platforms/chrp/Makefile +++ b/arch/powerpc/platforms/chrp/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | obj-y += setup.o time.o pegasos_eth.o | 1 | obj-y += setup.o time.o pegasos_eth.o pci.o |
2 | obj-$(CONFIG_PCI) += pci.o | ||
3 | obj-$(CONFIG_SMP) += smp.o | 2 | obj-$(CONFIG_SMP) += smp.o |
4 | obj-$(CONFIG_NVRAM) += nvram.o | 3 | obj-$(CONFIG_NVRAM) += nvram.o |
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index d32fedc991d3..3690624e49d4 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
@@ -99,7 +99,7 @@ int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
99 | struct pci_controller *hose = bus->sysdata; | 99 | struct pci_controller *hose = bus->sysdata; |
100 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 100 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
101 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 101 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
102 | | (hose->index << 24); | 102 | | (hose->global_number << 24); |
103 | int ret = -1; | 103 | int ret = -1; |
104 | int rval; | 104 | int rval; |
105 | 105 | ||
@@ -114,7 +114,7 @@ int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
114 | struct pci_controller *hose = bus->sysdata; | 114 | struct pci_controller *hose = bus->sysdata; |
115 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 115 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
116 | | (((bus->number - hose->first_busno) & 0xff) << 16) | 116 | | (((bus->number - hose->first_busno) & 0xff) << 16) |
117 | | (hose->index << 24); | 117 | | (hose->global_number << 24); |
118 | int rval; | 118 | int rval; |
119 | 119 | ||
120 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, | 120 | rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, |
@@ -254,13 +254,12 @@ chrp_find_bridges(void) | |||
254 | printk(" at %llx", (unsigned long long)r.start); | 254 | printk(" at %llx", (unsigned long long)r.start); |
255 | printk("\n"); | 255 | printk("\n"); |
256 | 256 | ||
257 | hose = pcibios_alloc_controller(); | 257 | hose = pcibios_alloc_controller(dev); |
258 | if (!hose) { | 258 | if (!hose) { |
259 | printk("Can't allocate PCI controller structure for %s\n", | 259 | printk("Can't allocate PCI controller structure for %s\n", |
260 | dev->full_name); | 260 | dev->full_name); |
261 | continue; | 261 | continue; |
262 | } | 262 | } |
263 | hose->arch_data = dev; | ||
264 | hose->first_busno = bus_range[0]; | 263 | hose->first_busno = bus_range[0]; |
265 | hose->last_busno = bus_range[1]; | 264 | hose->last_busno = bus_range[1]; |
266 | 265 | ||
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index f2d26268ca6f..bec772674e40 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
@@ -28,6 +28,7 @@ config PPC_HOLLY | |||
28 | bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" | 28 | bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" |
29 | select TSI108_BRIDGE | 29 | select TSI108_BRIDGE |
30 | select PPC_UDBG_16550 | 30 | select PPC_UDBG_16550 |
31 | select WANT_DEVICE_TREE | ||
31 | help | 32 | help |
32 | Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval | 33 | Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval |
33 | Board with TSI108/9 bridge (Hickory/Holly) | 34 | Board with TSI108/9 bridge (Hickory/Holly) |
@@ -44,6 +45,7 @@ endchoice | |||
44 | config TSI108_BRIDGE | 45 | config TSI108_BRIDGE |
45 | bool | 46 | bool |
46 | depends on MPC7448HPC2 || PPC_HOLLY | 47 | depends on MPC7448HPC2 || PPC_HOLLY |
48 | select PCI | ||
47 | select MPIC | 49 | select MPIC |
48 | select MPIC_WEIRD | 50 | select MPIC_WEIRD |
49 | default y | 51 | default y |
diff --git a/arch/powerpc/platforms/embedded6xx/holly.c b/arch/powerpc/platforms/embedded6xx/holly.c index 3a0b4a01401c..6292e36dc577 100644 --- a/arch/powerpc/platforms/embedded6xx/holly.c +++ b/arch/powerpc/platforms/embedded6xx/holly.c | |||
@@ -45,7 +45,7 @@ | |||
45 | 45 | ||
46 | #define HOLLY_PCI_CFG_PHYS 0x7c000000 | 46 | #define HOLLY_PCI_CFG_PHYS 0x7c000000 |
47 | 47 | ||
48 | int holly_exclude_device(u_char bus, u_char devfn) | 48 | int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) |
49 | { | 49 | { |
50 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 50 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
51 | return PCIBIOS_DEVICE_NOT_FOUND; | 51 | return PCIBIOS_DEVICE_NOT_FOUND; |
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c index b412f006a9c5..f4d0a7a603f5 100644 --- a/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/arch/powerpc/platforms/embedded6xx/linkstation.c | |||
@@ -54,8 +54,9 @@ static struct mtd_partition linkstation_physmap_partitions[] = { | |||
54 | }, | 54 | }, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static int __init add_bridge(struct device_node *dev) | 57 | static int __init linkstation_add_bridge(struct device_node *dev) |
58 | { | 58 | { |
59 | #ifdef CONFIG_PCI | ||
59 | int len; | 60 | int len; |
60 | struct pci_controller *hose; | 61 | struct pci_controller *hose; |
61 | const int *bus_range; | 62 | const int *bus_range; |
@@ -67,18 +68,17 @@ static int __init add_bridge(struct device_node *dev) | |||
67 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 68 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
68 | " bus 0\n", dev->full_name); | 69 | " bus 0\n", dev->full_name); |
69 | 70 | ||
70 | hose = pcibios_alloc_controller(); | 71 | hose = pcibios_alloc_controller(dev); |
71 | if (hose == NULL) | 72 | if (hose == NULL) |
72 | return -ENOMEM; | 73 | return -ENOMEM; |
73 | hose->first_busno = bus_range ? bus_range[0] : 0; | 74 | hose->first_busno = bus_range ? bus_range[0] : 0; |
74 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 75 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
75 | hose->arch_data = dev; | ||
76 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | 76 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); |
77 | 77 | ||
78 | /* Interpret the "ranges" property */ | 78 | /* Interpret the "ranges" property */ |
79 | /* This also maps the I/O region and sets isa_io/mem_base */ | 79 | /* This also maps the I/O region and sets isa_io/mem_base */ |
80 | pci_process_bridge_OF_ranges(hose, dev, 1); | 80 | pci_process_bridge_OF_ranges(hose, dev, 1); |
81 | 81 | #endif | |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
@@ -92,7 +92,7 @@ static void __init linkstation_setup_arch(void) | |||
92 | 92 | ||
93 | /* Lookup PCI host bridges */ | 93 | /* Lookup PCI host bridges */ |
94 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 94 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
95 | add_bridge(np); | 95 | linkstation_add_bridge(np); |
96 | 96 | ||
97 | printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); | 97 | printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); |
98 | printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n"); | 98 | printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n"); |
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 4542e0c837c0..1e3cc69487b5 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c | |||
@@ -54,15 +54,10 @@ | |||
54 | 54 | ||
55 | #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000 | 55 | #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000 |
56 | 56 | ||
57 | #ifndef CONFIG_PCI | ||
58 | isa_io_base = MPC7448_HPC2_ISA_IO_BASE; | ||
59 | isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; | ||
60 | pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; | ||
61 | #endif | ||
62 | |||
63 | extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); | 57 | extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); |
64 | 58 | ||
65 | int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) | 59 | int mpc7448_hpc2_exclude_device(struct pci_controller *hose, |
60 | u_char bus, u_char devfn) | ||
66 | { | 61 | { |
67 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 62 | if (bus == 0 && PCI_SLOT(devfn) == 0) |
68 | return PCIBIOS_DEVICE_NOT_FOUND; | 63 | return PCIBIOS_DEVICE_NOT_FOUND; |
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h index a543a5242e34..f7e0e0c7f8d8 100644 --- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h | |||
@@ -18,9 +18,4 @@ | |||
18 | 18 | ||
19 | #include <asm/ppcboot.h> | 19 | #include <asm/ppcboot.h> |
20 | 20 | ||
21 | /* Base Addresses for the PCI bus | ||
22 | */ | ||
23 | #define MPC7448_HPC2_PCI_MEM_OFFSET (0x00000000) | ||
24 | #define MPC7448_HPC2_ISA_IO_BASE (0x00000000) | ||
25 | #define MPC7448_HPC2_ISA_MEM_BASE (0x00000000) | ||
26 | #endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ | 21 | #endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ |
diff --git a/arch/powerpc/platforms/iseries/call_hpt.h b/arch/powerpc/platforms/iseries/call_hpt.h index a843b0f87b72..8d95fe4b554e 100644 --- a/arch/powerpc/platforms/iseries/call_hpt.h +++ b/arch/powerpc/platforms/iseries/call_hpt.h | |||
@@ -76,24 +76,25 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, | |||
76 | return compressedStatus; | 76 | return compressedStatus; |
77 | } | 77 | } |
78 | 78 | ||
79 | static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn) | 79 | static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn) |
80 | { | 80 | { |
81 | return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0); | 81 | return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0); |
82 | } | 82 | } |
83 | 83 | ||
84 | static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex, | 84 | static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex, |
85 | u8 bitson, u8 bitsoff) | 85 | u8 bitson, u8 bitsoff) |
86 | { | 86 | { |
87 | return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex, | 87 | return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex, |
88 | bitson, bitsoff); | 88 | bitson, bitsoff); |
89 | } | 89 | } |
90 | 90 | ||
91 | static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex) | 91 | static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex) |
92 | { | 92 | { |
93 | HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0); | 93 | HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0); |
94 | } | 94 | } |
95 | 95 | ||
96 | static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte) | 96 | static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, |
97 | struct hash_pte *hpte) | ||
97 | { | 98 | { |
98 | HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r); | 99 | HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r); |
99 | } | 100 | } |
diff --git a/arch/powerpc/platforms/iseries/htab.c b/arch/powerpc/platforms/iseries/htab.c index ed44dfceaa45..b4e2c7a038e1 100644 --- a/arch/powerpc/platforms/iseries/htab.c +++ b/arch/powerpc/platforms/iseries/htab.c | |||
@@ -44,7 +44,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
44 | unsigned long vflags, int psize) | 44 | unsigned long vflags, int psize) |
45 | { | 45 | { |
46 | long slot; | 46 | long slot; |
47 | hpte_t lhpte; | 47 | struct hash_pte lhpte; |
48 | int secondary = 0; | 48 | int secondary = 0; |
49 | 49 | ||
50 | BUG_ON(psize != MMU_PAGE_4K); | 50 | BUG_ON(psize != MMU_PAGE_4K); |
@@ -99,7 +99,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
99 | 99 | ||
100 | static unsigned long iSeries_hpte_getword0(unsigned long slot) | 100 | static unsigned long iSeries_hpte_getword0(unsigned long slot) |
101 | { | 101 | { |
102 | hpte_t hpte; | 102 | struct hash_pte hpte; |
103 | 103 | ||
104 | HvCallHpt_get(&hpte, slot); | 104 | HvCallHpt_get(&hpte, slot); |
105 | return hpte.v; | 105 | return hpte.v; |
@@ -144,7 +144,7 @@ static long iSeries_hpte_remove(unsigned long hpte_group) | |||
144 | static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, | 144 | static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, |
145 | unsigned long va, int psize, int local) | 145 | unsigned long va, int psize, int local) |
146 | { | 146 | { |
147 | hpte_t hpte; | 147 | struct hash_pte hpte; |
148 | unsigned long want_v; | 148 | unsigned long want_v; |
149 | 149 | ||
150 | iSeries_hlock(slot); | 150 | iSeries_hlock(slot); |
@@ -176,7 +176,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
176 | */ | 176 | */ |
177 | static long iSeries_hpte_find(unsigned long vpn) | 177 | static long iSeries_hpte_find(unsigned long vpn) |
178 | { | 178 | { |
179 | hpte_t hpte; | 179 | struct hash_pte hpte; |
180 | long slot; | 180 | long slot; |
181 | 181 | ||
182 | /* | 182 | /* |
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 9c974227155e..da87162000f0 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
@@ -742,6 +742,11 @@ void __init iSeries_pcibios_init(void) | |||
742 | /* Install IO hooks */ | 742 | /* Install IO hooks */ |
743 | ppc_pci_io = iseries_pci_io; | 743 | ppc_pci_io = iseries_pci_io; |
744 | 744 | ||
745 | /* iSeries has no IO space in the common sense, it needs to set | ||
746 | * the IO base to 0 | ||
747 | */ | ||
748 | pci_io_base = 0; | ||
749 | |||
745 | if (root == NULL) { | 750 | if (root == NULL) { |
746 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " | 751 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " |
747 | "of device tree\n"); | 752 | "of device tree\n"); |
@@ -763,7 +768,7 @@ void __init iSeries_pcibios_init(void) | |||
763 | if (phb == NULL) | 768 | if (phb == NULL) |
764 | continue; | 769 | continue; |
765 | 770 | ||
766 | phb->pci_mem_offset = phb->local_number = bus; | 771 | phb->pci_mem_offset = bus; |
767 | phb->first_busno = bus; | 772 | phb->first_busno = bus; |
768 | phb->last_busno = bus; | 773 | phb->last_busno = bus; |
769 | phb->ops = &iSeries_pci_ops; | 774 | phb->ops = &iSeries_pci_ops; |
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 7f5dcee814d4..13a8b1908ded 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -79,8 +79,6 @@ extern void iSeries_pci_final_fixup(void); | |||
79 | static void iSeries_pci_final_fixup(void) { } | 79 | static void iSeries_pci_final_fixup(void) { } |
80 | #endif | 80 | #endif |
81 | 81 | ||
82 | extern unsigned long iSeries_recal_tb; | ||
83 | extern unsigned long iSeries_recal_titan; | ||
84 | 82 | ||
85 | struct MemoryBlock { | 83 | struct MemoryBlock { |
86 | unsigned long absStart; | 84 | unsigned long absStart; |
@@ -292,8 +290,8 @@ static void __init iSeries_init_early(void) | |||
292 | { | 290 | { |
293 | DBG(" -> iSeries_init_early()\n"); | 291 | DBG(" -> iSeries_init_early()\n"); |
294 | 292 | ||
295 | iSeries_recal_tb = get_tb(); | 293 | /* Snapshot the timebase, for use in later recalibration */ |
296 | iSeries_recal_titan = HvCallXm_loadTod(); | 294 | iSeries_time_init_early(); |
297 | 295 | ||
298 | /* | 296 | /* |
299 | * Initialize the DMA/TCE management | 297 | * Initialize the DMA/TCE management |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 7aaa5bbc9363..fceaae40fe70 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -444,7 +444,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
444 | u3_ht = hose; | 444 | u3_ht = hose; |
445 | } | 445 | } |
446 | 446 | ||
447 | static int __init add_bridge(struct device_node *dev) | 447 | static int __init maple_add_bridge(struct device_node *dev) |
448 | { | 448 | { |
449 | int len; | 449 | int len; |
450 | struct pci_controller *hose; | 450 | struct pci_controller *hose; |
@@ -519,23 +519,6 @@ void __devinit maple_pci_irq_fixup(struct pci_dev *dev) | |||
519 | DBG(" <- maple_pci_irq_fixup\n"); | 519 | DBG(" <- maple_pci_irq_fixup\n"); |
520 | } | 520 | } |
521 | 521 | ||
522 | static void __init maple_fixup_phb_resources(void) | ||
523 | { | ||
524 | struct pci_controller *hose, *tmp; | ||
525 | |||
526 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
527 | unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
528 | |||
529 | hose->io_resource.start += offset; | ||
530 | hose->io_resource.end += offset; | ||
531 | |||
532 | printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n", | ||
533 | hose->global_number, | ||
534 | (unsigned long long)hose->io_resource.start, | ||
535 | (unsigned long long)hose->io_resource.end); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | void __init maple_pci_init(void) | 522 | void __init maple_pci_init(void) |
540 | { | 523 | { |
541 | struct device_node *np, *root; | 524 | struct device_node *np, *root; |
@@ -558,7 +541,7 @@ void __init maple_pci_init(void) | |||
558 | continue; | 541 | continue; |
559 | if ((of_device_is_compatible(np, "u4-pcie") || | 542 | if ((of_device_is_compatible(np, "u4-pcie") || |
560 | of_device_is_compatible(np, "u3-agp")) && | 543 | of_device_is_compatible(np, "u3-agp")) && |
561 | add_bridge(np) == 0) | 544 | maple_add_bridge(np) == 0) |
562 | of_node_get(np); | 545 | of_node_get(np); |
563 | 546 | ||
564 | if (of_device_is_compatible(np, "u3-ht")) { | 547 | if (of_device_is_compatible(np, "u3-ht")) { |
@@ -570,27 +553,9 @@ void __init maple_pci_init(void) | |||
570 | 553 | ||
571 | /* Now setup the HyperTransport host if we found any | 554 | /* Now setup the HyperTransport host if we found any |
572 | */ | 555 | */ |
573 | if (ht && add_bridge(ht) != 0) | 556 | if (ht && maple_add_bridge(ht) != 0) |
574 | of_node_put(ht); | 557 | of_node_put(ht); |
575 | 558 | ||
576 | /* | ||
577 | * We need to call pci_setup_phb_io for the HT bridge first | ||
578 | * so it gets the I/O port numbers starting at 0, and we | ||
579 | * need to call it for the AGP bridge after that so it gets | ||
580 | * small positive I/O port numbers. | ||
581 | */ | ||
582 | if (u3_ht) | ||
583 | pci_setup_phb_io(u3_ht, 1); | ||
584 | if (u3_agp) | ||
585 | pci_setup_phb_io(u3_agp, 0); | ||
586 | if (u4_pcie) | ||
587 | pci_setup_phb_io(u4_pcie, 0); | ||
588 | |||
589 | /* Fixup the IO resources on our host bridges as the common code | ||
590 | * does it only for childs of the host bridges | ||
591 | */ | ||
592 | maple_fixup_phb_resources(); | ||
593 | |||
594 | /* Setup the linkage between OF nodes and PHBs */ | 559 | /* Setup the linkage between OF nodes and PHBs */ |
595 | pci_devs_phb_init(); | 560 | pci_devs_phb_init(); |
596 | 561 | ||
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index 7c5076e38ea1..95cd90fd81c7 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig | |||
@@ -25,4 +25,13 @@ config PPC_PASEMI_MDIO | |||
25 | help | 25 | help |
26 | Driver for MDIO via GPIO on PWRficient platforms | 26 | Driver for MDIO via GPIO on PWRficient platforms |
27 | 27 | ||
28 | config ELECTRA_IDE | ||
29 | tristate "Electra IDE driver" | ||
30 | default y | ||
31 | depends on PPC_PASEMI && ATA | ||
32 | select PATA_PLATFORM | ||
33 | help | ||
34 | This includes driver support for the Electra on-board IDE | ||
35 | interface. | ||
36 | |||
28 | endmenu | 37 | endmenu |
diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile index 2cd2a4f26a48..f47fcac7e581 100644 --- a/arch/powerpc/platforms/pasemi/Makefile +++ b/arch/powerpc/platforms/pasemi/Makefile | |||
@@ -1,3 +1,4 @@ | |||
1 | obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o | 1 | obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o |
2 | obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o | 2 | obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o |
3 | obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o | ||
3 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o | 4 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o |
diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c new file mode 100644 index 000000000000..12fb0c949263 --- /dev/null +++ b/arch/powerpc/platforms/pasemi/electra_ide.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 PA Semi, Inc | ||
3 | * | ||
4 | * Maintained by: Olof Johansson <olof@lixom.net> | ||
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 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/platform_device.h> | ||
21 | |||
22 | #include <asm/prom.h> | ||
23 | #include <asm/system.h> | ||
24 | |||
25 | /* The electra IDE interface is incredibly simple: Just a device on the localbus | ||
26 | * with interrupts hooked up to one of the GPIOs. The device tree contains the | ||
27 | * address window and interrupt mappings already, and the pata_platform driver handles | ||
28 | * the rest. We just need to hook the two up. | ||
29 | */ | ||
30 | |||
31 | #define MAX_IFS 4 /* really, we have only one */ | ||
32 | |||
33 | static struct platform_device *pdevs[MAX_IFS]; | ||
34 | |||
35 | static int __devinit electra_ide_init(void) | ||
36 | { | ||
37 | struct device_node *np; | ||
38 | struct resource r[3]; | ||
39 | int ret = 0; | ||
40 | int i; | ||
41 | |||
42 | np = of_find_compatible_node(NULL, "ide", "electra-ide"); | ||
43 | i = 0; | ||
44 | |||
45 | while (np && i < MAX_IFS) { | ||
46 | memset(r, 0, sizeof(r)); | ||
47 | |||
48 | /* pata_platform wants two address ranges: one for the base registers, | ||
49 | * another for the control (altstatus). It's located at offset 0x3f6 in | ||
50 | * the window, but the device tree only has one large register window | ||
51 | * that covers both ranges. So we need to split it up by hand here: | ||
52 | */ | ||
53 | |||
54 | ret = of_address_to_resource(np, 0, &r[0]); | ||
55 | if (ret) | ||
56 | goto out; | ||
57 | ret = of_address_to_resource(np, 0, &r[1]); | ||
58 | if (ret) | ||
59 | goto out; | ||
60 | |||
61 | r[1].start += 0x3f6; | ||
62 | r[0].end = r[1].start-1; | ||
63 | |||
64 | r[2].start = irq_of_parse_and_map(np, 0); | ||
65 | r[2].end = irq_of_parse_and_map(np, 0); | ||
66 | r[2].flags = IORESOURCE_IRQ; | ||
67 | |||
68 | pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n", | ||
69 | r[0].start, r[1].start, r[2].start); | ||
70 | pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3); | ||
71 | if (IS_ERR(pdevs[i])) { | ||
72 | ret = PTR_ERR(pdevs[i]); | ||
73 | pdevs[i] = NULL; | ||
74 | goto out; | ||
75 | } | ||
76 | np = of_find_compatible_node(np, "ide", "electra-ide"); | ||
77 | } | ||
78 | out: | ||
79 | return ret; | ||
80 | } | ||
81 | module_init(electra_ide_init); | ||
82 | |||
83 | static void __devexit electra_ide_exit(void) | ||
84 | { | ||
85 | int i; | ||
86 | |||
87 | for (i = 0; i < MAX_IFS; i++) | ||
88 | if (pdevs[i]) | ||
89 | platform_device_unregister(pdevs[i]); | ||
90 | } | ||
91 | module_exit(electra_ide_exit); | ||
92 | |||
93 | |||
94 | MODULE_LICENSE("GPL"); | ||
95 | MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); | ||
96 | MODULE_DESCRIPTION("PA Semi Electra IDE driver"); | ||
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index bbc6dfcfaa91..ab1f5f62bcd8 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c | |||
@@ -132,7 +132,7 @@ static void __init setup_pa_pxp(struct pci_controller *hose) | |||
132 | hose->cfg_data = ioremap(0xe0000000, 0x10000000); | 132 | hose->cfg_data = ioremap(0xe0000000, 0x10000000); |
133 | } | 133 | } |
134 | 134 | ||
135 | static int __init add_bridge(struct device_node *dev) | 135 | static int __init pas_add_bridge(struct device_node *dev) |
136 | { | 136 | { |
137 | struct pci_controller *hose; | 137 | struct pci_controller *hose; |
138 | 138 | ||
@@ -150,29 +150,11 @@ static int __init add_bridge(struct device_node *dev) | |||
150 | printk(KERN_INFO "Found PA-PXP PCI host bridge.\n"); | 150 | printk(KERN_INFO "Found PA-PXP PCI host bridge.\n"); |
151 | 151 | ||
152 | /* Interpret the "ranges" property */ | 152 | /* Interpret the "ranges" property */ |
153 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
154 | pci_process_bridge_OF_ranges(hose, dev, 1); | 153 | pci_process_bridge_OF_ranges(hose, dev, 1); |
155 | pci_setup_phb_io(hose, 1); | ||
156 | 154 | ||
157 | return 0; | 155 | return 0; |
158 | } | 156 | } |
159 | 157 | ||
160 | |||
161 | static void __init pas_fixup_phb_resources(void) | ||
162 | { | ||
163 | struct pci_controller *hose, *tmp; | ||
164 | |||
165 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
166 | unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; | ||
167 | hose->io_resource.start += offset; | ||
168 | hose->io_resource.end += offset; | ||
169 | printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", | ||
170 | hose->global_number, | ||
171 | hose->io_resource.start, hose->io_resource.end); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | |||
176 | void __init pas_pci_init(void) | 158 | void __init pas_pci_init(void) |
177 | { | 159 | { |
178 | struct device_node *np, *root; | 160 | struct device_node *np, *root; |
@@ -185,13 +167,11 @@ void __init pas_pci_init(void) | |||
185 | } | 167 | } |
186 | 168 | ||
187 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) | 169 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) |
188 | if (np->name && !strcmp(np->name, "pxp") && !add_bridge(np)) | 170 | if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np)) |
189 | of_node_get(np); | 171 | of_node_get(np); |
190 | 172 | ||
191 | of_node_put(root); | 173 | of_node_put(root); |
192 | 174 | ||
193 | pas_fixup_phb_resources(); | ||
194 | |||
195 | /* Setup the linkage between OF nodes and PHBs */ | 175 | /* Setup the linkage between OF nodes and PHBs */ |
196 | pci_devs_phb_init(); | 176 | pci_devs_phb_init(); |
197 | 177 | ||
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index c5a3f61f8d85..ffe6528048b5 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
@@ -239,7 +239,7 @@ static int __init pas_probe(void) | |||
239 | return 1; | 239 | return 1; |
240 | } | 240 | } |
241 | 241 | ||
242 | define_machine(pas) { | 242 | define_machine(pasemi) { |
243 | .name = "PA Semi PA6T-1682M", | 243 | .name = "PA Semi PA6T-1682M", |
244 | .probe = pas_probe, | 244 | .probe = pas_probe, |
245 | .setup_arch = pas_setup_arch, | 245 | .setup_arch = pas_setup_arch, |
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig index 5b7afe50039a..055990ca8ce6 100644 --- a/arch/powerpc/platforms/powermac/Kconfig +++ b/arch/powerpc/platforms/powermac/Kconfig | |||
@@ -2,6 +2,7 @@ config PPC_PMAC | |||
2 | bool "Apple PowerMac based machines" | 2 | bool "Apple PowerMac based machines" |
3 | depends on PPC_MULTIPLATFORM | 3 | depends on PPC_MULTIPLATFORM |
4 | select MPIC | 4 | select MPIC |
5 | select PCI | ||
5 | select PPC_INDIRECT_PCI if PPC32 | 6 | select PPC_INDIRECT_PCI if PPC32 |
6 | select PPC_MPC106 if PPC32 | 7 | select PPC_MPC106 if PPC32 |
7 | select PPC_NATIVE | 8 | select PPC_NATIVE |
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 3f507ab9c5e5..efdf5eb81ecc 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/completion.h> | 43 | #include <linux/completion.h> |
44 | #include <linux/timer.h> | 44 | #include <linux/timer.h> |
45 | #include <linux/mutex.h> | ||
45 | #include <asm/keylargo.h> | 46 | #include <asm/keylargo.h> |
46 | #include <asm/uninorth.h> | 47 | #include <asm/uninorth.h> |
47 | #include <asm/io.h> | 48 | #include <asm/io.h> |
@@ -84,7 +85,7 @@ struct pmac_i2c_bus | |||
84 | void *hostdata; | 85 | void *hostdata; |
85 | int channel; /* some hosts have multiple */ | 86 | int channel; /* some hosts have multiple */ |
86 | int mode; /* current mode */ | 87 | int mode; /* current mode */ |
87 | struct semaphore sem; | 88 | struct mutex mutex; |
88 | int opened; | 89 | int opened; |
89 | int polled; /* open mode */ | 90 | int polled; /* open mode */ |
90 | struct platform_device *platform_dev; | 91 | struct platform_device *platform_dev; |
@@ -104,7 +105,7 @@ static LIST_HEAD(pmac_i2c_busses); | |||
104 | 105 | ||
105 | struct pmac_i2c_host_kw | 106 | struct pmac_i2c_host_kw |
106 | { | 107 | { |
107 | struct semaphore mutex; /* Access mutex for use by | 108 | struct mutex mutex; /* Access mutex for use by |
108 | * i2c-keywest */ | 109 | * i2c-keywest */ |
109 | void __iomem *base; /* register base address */ | 110 | void __iomem *base; /* register base address */ |
110 | int bsteps; /* register stepping */ | 111 | int bsteps; /* register stepping */ |
@@ -375,14 +376,14 @@ static void kw_i2c_timeout(unsigned long data) | |||
375 | static int kw_i2c_open(struct pmac_i2c_bus *bus) | 376 | static int kw_i2c_open(struct pmac_i2c_bus *bus) |
376 | { | 377 | { |
377 | struct pmac_i2c_host_kw *host = bus->hostdata; | 378 | struct pmac_i2c_host_kw *host = bus->hostdata; |
378 | down(&host->mutex); | 379 | mutex_lock(&host->mutex); |
379 | return 0; | 380 | return 0; |
380 | } | 381 | } |
381 | 382 | ||
382 | static void kw_i2c_close(struct pmac_i2c_bus *bus) | 383 | static void kw_i2c_close(struct pmac_i2c_bus *bus) |
383 | { | 384 | { |
384 | struct pmac_i2c_host_kw *host = bus->hostdata; | 385 | struct pmac_i2c_host_kw *host = bus->hostdata; |
385 | up(&host->mutex); | 386 | mutex_unlock(&host->mutex); |
386 | } | 387 | } |
387 | 388 | ||
388 | static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, | 389 | static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, |
@@ -498,7 +499,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) | |||
498 | kfree(host); | 499 | kfree(host); |
499 | return NULL; | 500 | return NULL; |
500 | } | 501 | } |
501 | init_MUTEX(&host->mutex); | 502 | mutex_init(&host->mutex); |
502 | init_completion(&host->complete); | 503 | init_completion(&host->complete); |
503 | spin_lock_init(&host->lock); | 504 | spin_lock_init(&host->lock); |
504 | init_timer(&host->timeout_timer); | 505 | init_timer(&host->timeout_timer); |
@@ -571,7 +572,7 @@ static void __init kw_i2c_add(struct pmac_i2c_host_kw *host, | |||
571 | bus->open = kw_i2c_open; | 572 | bus->open = kw_i2c_open; |
572 | bus->close = kw_i2c_close; | 573 | bus->close = kw_i2c_close; |
573 | bus->xfer = kw_i2c_xfer; | 574 | bus->xfer = kw_i2c_xfer; |
574 | init_MUTEX(&bus->sem); | 575 | mutex_init(&bus->mutex); |
575 | if (controller == busnode) | 576 | if (controller == busnode) |
576 | bus->flags = pmac_i2c_multibus; | 577 | bus->flags = pmac_i2c_multibus; |
577 | list_add(&bus->link, &pmac_i2c_busses); | 578 | list_add(&bus->link, &pmac_i2c_busses); |
@@ -798,7 +799,7 @@ static void __init pmu_i2c_probe(void) | |||
798 | bus->mode = pmac_i2c_mode_std; | 799 | bus->mode = pmac_i2c_mode_std; |
799 | bus->hostdata = bus + 1; | 800 | bus->hostdata = bus + 1; |
800 | bus->xfer = pmu_i2c_xfer; | 801 | bus->xfer = pmu_i2c_xfer; |
801 | init_MUTEX(&bus->sem); | 802 | mutex_init(&bus->mutex); |
802 | bus->flags = pmac_i2c_multibus; | 803 | bus->flags = pmac_i2c_multibus; |
803 | list_add(&bus->link, &pmac_i2c_busses); | 804 | list_add(&bus->link, &pmac_i2c_busses); |
804 | 805 | ||
@@ -921,7 +922,7 @@ static void __init smu_i2c_probe(void) | |||
921 | bus->mode = pmac_i2c_mode_std; | 922 | bus->mode = pmac_i2c_mode_std; |
922 | bus->hostdata = bus + 1; | 923 | bus->hostdata = bus + 1; |
923 | bus->xfer = smu_i2c_xfer; | 924 | bus->xfer = smu_i2c_xfer; |
924 | init_MUTEX(&bus->sem); | 925 | mutex_init(&bus->mutex); |
925 | bus->flags = 0; | 926 | bus->flags = 0; |
926 | list_add(&bus->link, &pmac_i2c_busses); | 927 | list_add(&bus->link, &pmac_i2c_busses); |
927 | 928 | ||
@@ -1093,13 +1094,13 @@ int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled) | |||
1093 | { | 1094 | { |
1094 | int rc; | 1095 | int rc; |
1095 | 1096 | ||
1096 | down(&bus->sem); | 1097 | mutex_lock(&bus->mutex); |
1097 | bus->polled = polled || pmac_i2c_force_poll; | 1098 | bus->polled = polled || pmac_i2c_force_poll; |
1098 | bus->opened = 1; | 1099 | bus->opened = 1; |
1099 | bus->mode = pmac_i2c_mode_std; | 1100 | bus->mode = pmac_i2c_mode_std; |
1100 | if (bus->open && (rc = bus->open(bus)) != 0) { | 1101 | if (bus->open && (rc = bus->open(bus)) != 0) { |
1101 | bus->opened = 0; | 1102 | bus->opened = 0; |
1102 | up(&bus->sem); | 1103 | mutex_unlock(&bus->mutex); |
1103 | return rc; | 1104 | return rc; |
1104 | } | 1105 | } |
1105 | return 0; | 1106 | return 0; |
@@ -1112,7 +1113,7 @@ void pmac_i2c_close(struct pmac_i2c_bus *bus) | |||
1112 | if (bus->close) | 1113 | if (bus->close) |
1113 | bus->close(bus); | 1114 | bus->close(bus); |
1114 | bus->opened = 0; | 1115 | bus->opened = 0; |
1115 | up(&bus->sem); | 1116 | mutex_unlock(&bus->mutex); |
1116 | } | 1117 | } |
1117 | EXPORT_SYMBOL_GPL(pmac_i2c_close); | 1118 | EXPORT_SYMBOL_GPL(pmac_i2c_close); |
1118 | 1119 | ||
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index c4af9e21ac93..92586db19754 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -35,8 +35,6 @@ | |||
35 | #define DBG(x...) | 35 | #define DBG(x...) |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | static int add_bridge(struct device_node *dev); | ||
39 | |||
40 | /* XXX Could be per-controller, but I don't think we risk anything by | 38 | /* XXX Could be per-controller, but I don't think we risk anything by |
41 | * assuming we won't have both UniNorth and Bandit */ | 39 | * assuming we won't have both UniNorth and Bandit */ |
42 | static int has_uninorth; | 40 | static int has_uninorth; |
@@ -897,7 +895,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
897 | * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, | 895 | * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, |
898 | * if we have one or more bandit or chaos bridges, we don't have a MPC106. | 896 | * if we have one or more bandit or chaos bridges, we don't have a MPC106. |
899 | */ | 897 | */ |
900 | static int __init add_bridge(struct device_node *dev) | 898 | static int __init pmac_add_bridge(struct device_node *dev) |
901 | { | 899 | { |
902 | int len; | 900 | int len; |
903 | struct pci_controller *hose; | 901 | struct pci_controller *hose; |
@@ -918,15 +916,9 @@ static int __init add_bridge(struct device_node *dev) | |||
918 | " bus 0\n", dev->full_name); | 916 | " bus 0\n", dev->full_name); |
919 | } | 917 | } |
920 | 918 | ||
921 | /* XXX Different prototypes, to be merged */ | ||
922 | #ifdef CONFIG_PPC64 | ||
923 | hose = pcibios_alloc_controller(dev); | 919 | hose = pcibios_alloc_controller(dev); |
924 | #else | ||
925 | hose = pcibios_alloc_controller(); | ||
926 | #endif | ||
927 | if (!hose) | 920 | if (!hose) |
928 | return -ENOMEM; | 921 | return -ENOMEM; |
929 | hose->arch_data = dev; | ||
930 | hose->first_busno = bus_range ? bus_range[0] : 0; | 922 | hose->first_busno = bus_range ? bus_range[0] : 0; |
931 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 923 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
932 | 924 | ||
@@ -1006,19 +998,6 @@ void __devinit pmac_pci_irq_fixup(struct pci_dev *dev) | |||
1006 | #endif /* CONFIG_PPC32 */ | 998 | #endif /* CONFIG_PPC32 */ |
1007 | } | 999 | } |
1008 | 1000 | ||
1009 | #ifdef CONFIG_PPC64 | ||
1010 | static void __init pmac_fixup_phb_resources(void) | ||
1011 | { | ||
1012 | struct pci_controller *hose, *tmp; | ||
1013 | |||
1014 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
1015 | printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", | ||
1016 | hose->global_number, | ||
1017 | hose->io_resource.start, hose->io_resource.end); | ||
1018 | } | ||
1019 | } | ||
1020 | #endif | ||
1021 | |||
1022 | void __init pmac_pci_init(void) | 1001 | void __init pmac_pci_init(void) |
1023 | { | 1002 | { |
1024 | struct device_node *np, *root; | 1003 | struct device_node *np, *root; |
@@ -1036,7 +1015,7 @@ void __init pmac_pci_init(void) | |||
1036 | if (strcmp(np->name, "bandit") == 0 | 1015 | if (strcmp(np->name, "bandit") == 0 |
1037 | || strcmp(np->name, "chaos") == 0 | 1016 | || strcmp(np->name, "chaos") == 0 |
1038 | || strcmp(np->name, "pci") == 0) { | 1017 | || strcmp(np->name, "pci") == 0) { |
1039 | if (add_bridge(np) == 0) | 1018 | if (pmac_add_bridge(np) == 0) |
1040 | of_node_get(np); | 1019 | of_node_get(np); |
1041 | } | 1020 | } |
1042 | if (strcmp(np->name, "ht") == 0) { | 1021 | if (strcmp(np->name, "ht") == 0) { |
@@ -1050,28 +1029,9 @@ void __init pmac_pci_init(void) | |||
1050 | /* Probe HT last as it relies on the agp resources to be already | 1029 | /* Probe HT last as it relies on the agp resources to be already |
1051 | * setup | 1030 | * setup |
1052 | */ | 1031 | */ |
1053 | if (ht && add_bridge(ht) != 0) | 1032 | if (ht && pmac_add_bridge(ht) != 0) |
1054 | of_node_put(ht); | 1033 | of_node_put(ht); |
1055 | 1034 | ||
1056 | /* | ||
1057 | * We need to call pci_setup_phb_io for the HT bridge first | ||
1058 | * so it gets the I/O port numbers starting at 0, and we | ||
1059 | * need to call it for the AGP bridge after that so it gets | ||
1060 | * small positive I/O port numbers. | ||
1061 | */ | ||
1062 | if (u3_ht) | ||
1063 | pci_setup_phb_io(u3_ht, 1); | ||
1064 | if (u3_agp) | ||
1065 | pci_setup_phb_io(u3_agp, 0); | ||
1066 | if (u4_pcie) | ||
1067 | pci_setup_phb_io(u4_pcie, 0); | ||
1068 | |||
1069 | /* | ||
1070 | * On ppc64, fixup the IO resources on our host bridges as | ||
1071 | * the common code does it only for children of the host bridges | ||
1072 | */ | ||
1073 | pmac_fixup_phb_resources(); | ||
1074 | |||
1075 | /* Setup the linkage between OF nodes and PHBs */ | 1035 | /* Setup the linkage between OF nodes and PHBs */ |
1076 | pci_devs_phb_init(); | 1036 | pci_devs_phb_init(); |
1077 | 1037 | ||
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 40f0008af4d1..a05079b07696 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig | |||
@@ -7,6 +7,7 @@ config PPC_PS3 | |||
7 | select USB_OHCI_BIG_ENDIAN_MMIO | 7 | select USB_OHCI_BIG_ENDIAN_MMIO |
8 | select USB_ARCH_HAS_EHCI | 8 | select USB_ARCH_HAS_EHCI |
9 | select USB_EHCI_BIG_ENDIAN_MMIO | 9 | select USB_EHCI_BIG_ENDIAN_MMIO |
10 | select MEMORY_HOTPLUG | ||
10 | help | 11 | help |
11 | This option enables support for the Sony PS3 game console | 12 | This option enables support for the Sony PS3 game console |
12 | and other platforms using the PS3 hypervisor. | 13 | and other platforms using the PS3 hypervisor. |
@@ -73,18 +74,12 @@ config PS3_USE_LPAR_ADDR | |||
73 | 74 | ||
74 | config PS3_VUART | 75 | config PS3_VUART |
75 | depends on PPC_PS3 | 76 | depends on PPC_PS3 |
76 | bool "PS3 Virtual UART support" if PS3_ADVANCED | 77 | tristate |
77 | default y | ||
78 | help | ||
79 | Include support for the PS3 Virtual UART. | ||
80 | |||
81 | This support is required for several system services | ||
82 | including the System Manager and AV Settings. In | ||
83 | general, all users will say Y. | ||
84 | 78 | ||
85 | config PS3_PS3AV | 79 | config PS3_PS3AV |
80 | depends on PPC_PS3 | ||
86 | tristate "PS3 AV settings driver" if PS3_ADVANCED | 81 | tristate "PS3 AV settings driver" if PS3_ADVANCED |
87 | depends on PS3_VUART | 82 | select PS3_VUART |
88 | default y | 83 | default y |
89 | help | 84 | help |
90 | Include support for the PS3 AV Settings driver. | 85 | Include support for the PS3 AV Settings driver. |
@@ -93,13 +88,18 @@ config PS3_PS3AV | |||
93 | general, all users will say Y or M. | 88 | general, all users will say Y or M. |
94 | 89 | ||
95 | config PS3_SYS_MANAGER | 90 | config PS3_SYS_MANAGER |
96 | bool "PS3 System Manager driver" if PS3_ADVANCED | 91 | depends on PPC_PS3 |
97 | depends on PS3_VUART | 92 | tristate "PS3 System Manager driver" if PS3_ADVANCED |
98 | default y | 93 | select PS3_VUART |
94 | default m | ||
99 | help | 95 | help |
100 | Include support for the PS3 System Manager. | 96 | Include support for the PS3 System Manager. |
101 | 97 | ||
102 | This support is required for system control. In | 98 | This support is required for system control. In |
103 | general, all users will say Y. | 99 | general, all users will say Y or M. |
100 | |||
101 | config PS3_STORAGE | ||
102 | depends on PPC_PS3 | ||
103 | tristate | ||
104 | 104 | ||
105 | endmenu | 105 | endmenu |
diff --git a/arch/powerpc/platforms/ps3/Makefile b/arch/powerpc/platforms/ps3/Makefile index a0048fcf0866..ac1bdf844eca 100644 --- a/arch/powerpc/platforms/ps3/Makefile +++ b/arch/powerpc/platforms/ps3/Makefile | |||
@@ -4,3 +4,4 @@ obj-y += system-bus.o | |||
4 | 4 | ||
5 | obj-$(CONFIG_SMP) += smp.o | 5 | obj-$(CONFIG_SMP) += smp.o |
6 | obj-$(CONFIG_SPU_BASE) += spu.o | 6 | obj-$(CONFIG_SPU_BASE) += spu.o |
7 | obj-y += device-init.o | ||
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c new file mode 100644 index 000000000000..825ebb2cbc2a --- /dev/null +++ b/arch/powerpc/platforms/ps3/device-init.c | |||
@@ -0,0 +1,785 @@ | |||
1 | /* | ||
2 | * PS3 device registration routines. | ||
3 | * | ||
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2007 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/delay.h> | ||
22 | #include <linux/freezer.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/kthread.h> | ||
25 | #include <linux/init.h> | ||
26 | |||
27 | #include <asm/firmware.h> | ||
28 | #include <asm/lv1call.h> | ||
29 | #include <asm/ps3stor.h> | ||
30 | |||
31 | #include "platform.h" | ||
32 | |||
33 | /** | ||
34 | * ps3_setup_gelic_device - Setup and register a gelic device instance. | ||
35 | * | ||
36 | * Allocates memory for a struct ps3_system_bus_device instance, initialises the | ||
37 | * structure members, and registers the device instance with the system bus. | ||
38 | */ | ||
39 | |||
40 | static int __init ps3_setup_gelic_device( | ||
41 | const struct ps3_repository_device *repo) | ||
42 | { | ||
43 | int result; | ||
44 | struct layout { | ||
45 | struct ps3_system_bus_device dev; | ||
46 | struct ps3_dma_region d_region; | ||
47 | } *p; | ||
48 | |||
49 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
50 | |||
51 | BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB); | ||
52 | BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC); | ||
53 | |||
54 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
55 | |||
56 | if (!p) { | ||
57 | result = -ENOMEM; | ||
58 | goto fail_malloc; | ||
59 | } | ||
60 | |||
61 | p->dev.match_id = PS3_MATCH_ID_GELIC; | ||
62 | p->dev.dev_type = PS3_DEVICE_TYPE_SB; | ||
63 | p->dev.bus_id = repo->bus_id; | ||
64 | p->dev.dev_id = repo->dev_id; | ||
65 | p->dev.d_region = &p->d_region; | ||
66 | |||
67 | result = ps3_repository_find_interrupt(repo, | ||
68 | PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id); | ||
69 | |||
70 | if (result) { | ||
71 | pr_debug("%s:%d ps3_repository_find_interrupt failed\n", | ||
72 | __func__, __LINE__); | ||
73 | goto fail_find_interrupt; | ||
74 | } | ||
75 | |||
76 | BUG_ON(p->dev.interrupt_id != 0); | ||
77 | |||
78 | result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K, | ||
79 | PS3_DMA_OTHER, NULL, 0); | ||
80 | |||
81 | if (result) { | ||
82 | pr_debug("%s:%d ps3_dma_region_init failed\n", | ||
83 | __func__, __LINE__); | ||
84 | goto fail_dma_init; | ||
85 | } | ||
86 | |||
87 | result = ps3_system_bus_device_register(&p->dev); | ||
88 | |||
89 | if (result) { | ||
90 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
91 | __func__, __LINE__); | ||
92 | goto fail_device_register; | ||
93 | } | ||
94 | |||
95 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
96 | return result; | ||
97 | |||
98 | fail_device_register: | ||
99 | fail_dma_init: | ||
100 | fail_find_interrupt: | ||
101 | kfree(p); | ||
102 | fail_malloc: | ||
103 | pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__); | ||
104 | return result; | ||
105 | } | ||
106 | |||
107 | static int __init_refok ps3_setup_uhc_device( | ||
108 | const struct ps3_repository_device *repo, enum ps3_match_id match_id, | ||
109 | enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type) | ||
110 | { | ||
111 | int result; | ||
112 | struct layout { | ||
113 | struct ps3_system_bus_device dev; | ||
114 | struct ps3_dma_region d_region; | ||
115 | struct ps3_mmio_region m_region; | ||
116 | } *p; | ||
117 | u64 bus_addr; | ||
118 | u64 len; | ||
119 | |||
120 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
121 | |||
122 | BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB); | ||
123 | BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB); | ||
124 | |||
125 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
126 | |||
127 | if (!p) { | ||
128 | result = -ENOMEM; | ||
129 | goto fail_malloc; | ||
130 | } | ||
131 | |||
132 | p->dev.match_id = match_id; | ||
133 | p->dev.dev_type = PS3_DEVICE_TYPE_SB; | ||
134 | p->dev.bus_id = repo->bus_id; | ||
135 | p->dev.dev_id = repo->dev_id; | ||
136 | p->dev.d_region = &p->d_region; | ||
137 | p->dev.m_region = &p->m_region; | ||
138 | |||
139 | result = ps3_repository_find_interrupt(repo, | ||
140 | interrupt_type, &p->dev.interrupt_id); | ||
141 | |||
142 | if (result) { | ||
143 | pr_debug("%s:%d ps3_repository_find_interrupt failed\n", | ||
144 | __func__, __LINE__); | ||
145 | goto fail_find_interrupt; | ||
146 | } | ||
147 | |||
148 | result = ps3_repository_find_reg(repo, reg_type, | ||
149 | &bus_addr, &len); | ||
150 | |||
151 | if (result) { | ||
152 | pr_debug("%s:%d ps3_repository_find_reg failed\n", | ||
153 | __func__, __LINE__); | ||
154 | goto fail_find_reg; | ||
155 | } | ||
156 | |||
157 | result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K, | ||
158 | PS3_DMA_INTERNAL, NULL, 0); | ||
159 | |||
160 | if (result) { | ||
161 | pr_debug("%s:%d ps3_dma_region_init failed\n", | ||
162 | __func__, __LINE__); | ||
163 | goto fail_dma_init; | ||
164 | } | ||
165 | |||
166 | result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len, | ||
167 | PS3_MMIO_4K); | ||
168 | |||
169 | if (result) { | ||
170 | pr_debug("%s:%d ps3_mmio_region_init failed\n", | ||
171 | __func__, __LINE__); | ||
172 | goto fail_mmio_init; | ||
173 | } | ||
174 | |||
175 | result = ps3_system_bus_device_register(&p->dev); | ||
176 | |||
177 | if (result) { | ||
178 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
179 | __func__, __LINE__); | ||
180 | goto fail_device_register; | ||
181 | } | ||
182 | |||
183 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
184 | return result; | ||
185 | |||
186 | fail_device_register: | ||
187 | fail_mmio_init: | ||
188 | fail_dma_init: | ||
189 | fail_find_reg: | ||
190 | fail_find_interrupt: | ||
191 | kfree(p); | ||
192 | fail_malloc: | ||
193 | pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__); | ||
194 | return result; | ||
195 | } | ||
196 | |||
197 | static int __init ps3_setup_ehci_device( | ||
198 | const struct ps3_repository_device *repo) | ||
199 | { | ||
200 | return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI, | ||
201 | PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI); | ||
202 | } | ||
203 | |||
204 | static int __init ps3_setup_ohci_device( | ||
205 | const struct ps3_repository_device *repo) | ||
206 | { | ||
207 | return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI, | ||
208 | PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI); | ||
209 | } | ||
210 | |||
211 | static int __init ps3_setup_vuart_device(enum ps3_match_id match_id, | ||
212 | unsigned int port_number) | ||
213 | { | ||
214 | int result; | ||
215 | struct layout { | ||
216 | struct ps3_system_bus_device dev; | ||
217 | } *p; | ||
218 | |||
219 | pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__, | ||
220 | match_id, port_number); | ||
221 | |||
222 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
223 | |||
224 | if (!p) | ||
225 | return -ENOMEM; | ||
226 | |||
227 | p->dev.match_id = match_id; | ||
228 | p->dev.dev_type = PS3_DEVICE_TYPE_VUART; | ||
229 | p->dev.port_number = port_number; | ||
230 | |||
231 | result = ps3_system_bus_device_register(&p->dev); | ||
232 | |||
233 | if (result) | ||
234 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
235 | __func__, __LINE__); | ||
236 | |||
237 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
238 | return result; | ||
239 | } | ||
240 | |||
241 | static int ps3stor_wait_for_completion(u64 dev_id, u64 tag, | ||
242 | unsigned int timeout) | ||
243 | { | ||
244 | int result = -1; | ||
245 | unsigned int retries = 0; | ||
246 | u64 status; | ||
247 | |||
248 | for (retries = 0; retries < timeout; retries++) { | ||
249 | result = lv1_storage_check_async_status(dev_id, tag, &status); | ||
250 | if (!result) | ||
251 | break; | ||
252 | |||
253 | msleep(1); | ||
254 | } | ||
255 | |||
256 | if (result) | ||
257 | pr_debug("%s:%u: check_async_status: %s, status %lx\n", | ||
258 | __func__, __LINE__, ps3_result(result), status); | ||
259 | |||
260 | return result; | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * ps3_storage_wait_for_device - Wait for a storage device to become ready. | ||
265 | * @repo: The repository device to wait for. | ||
266 | * | ||
267 | * Uses the hypervisor's storage device notification mechanism to wait until | ||
268 | * a storage device is ready. The device notification mechanism uses a | ||
269 | * psuedo device (id = -1) to asynchronously notify the guest when storage | ||
270 | * devices become ready. The notification device has a block size of 512 | ||
271 | * bytes. | ||
272 | */ | ||
273 | |||
274 | static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) | ||
275 | { | ||
276 | int result; | ||
277 | const u64 notification_dev_id = (u64)-1LL; | ||
278 | const unsigned int timeout = HZ; | ||
279 | u64 lpar; | ||
280 | u64 tag; | ||
281 | struct { | ||
282 | u64 operation_code; /* must be zero */ | ||
283 | u64 event_mask; /* 1 = device ready */ | ||
284 | } *notify_cmd; | ||
285 | struct { | ||
286 | u64 event_type; /* notify_device_ready */ | ||
287 | u64 bus_id; | ||
288 | u64 dev_id; | ||
289 | u64 dev_type; | ||
290 | u64 dev_port; | ||
291 | } *notify_event; | ||
292 | enum { | ||
293 | notify_device_ready = 1 | ||
294 | }; | ||
295 | |||
296 | pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__, | ||
297 | __LINE__, repo->bus_id, repo->dev_id, repo->dev_type); | ||
298 | |||
299 | notify_cmd = kzalloc(512, GFP_KERNEL); | ||
300 | notify_event = (void *)notify_cmd; | ||
301 | if (!notify_cmd) | ||
302 | return -ENOMEM; | ||
303 | |||
304 | lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd)); | ||
305 | |||
306 | result = lv1_open_device(repo->bus_id, notification_dev_id, 0); | ||
307 | if (result) { | ||
308 | printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__, | ||
309 | __LINE__, ps3_result(result)); | ||
310 | result = -ENODEV; | ||
311 | goto fail_free; | ||
312 | } | ||
313 | |||
314 | /* Setup and write the request for device notification. */ | ||
315 | |||
316 | notify_cmd->operation_code = 0; /* must be zero */ | ||
317 | notify_cmd->event_mask = 0x01; /* device ready */ | ||
318 | |||
319 | result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar, | ||
320 | &tag); | ||
321 | if (result) { | ||
322 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, | ||
323 | ps3_result(result)); | ||
324 | result = -ENODEV; | ||
325 | goto fail_close; | ||
326 | } | ||
327 | |||
328 | /* Wait for the write completion */ | ||
329 | |||
330 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
331 | timeout); | ||
332 | if (result) { | ||
333 | printk(KERN_ERR "%s:%u: write not completed %s\n", __func__, | ||
334 | __LINE__, ps3_result(result)); | ||
335 | result = -ENODEV; | ||
336 | goto fail_close; | ||
337 | } | ||
338 | |||
339 | /* Loop here processing the requested notification events. */ | ||
340 | |||
341 | result = -ENODEV; | ||
342 | while (1) { | ||
343 | memset(notify_event, 0, sizeof(*notify_event)); | ||
344 | |||
345 | result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0, | ||
346 | lpar, &tag); | ||
347 | if (result) { | ||
348 | printk(KERN_ERR "%s:%u: write failed %s\n", __func__, | ||
349 | __LINE__, ps3_result(result)); | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | result = ps3stor_wait_for_completion(notification_dev_id, tag, | ||
354 | timeout); | ||
355 | if (result) { | ||
356 | printk(KERN_ERR "%s:%u: read not completed %s\n", | ||
357 | __func__, __LINE__, ps3_result(result)); | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | if (notify_event->event_type != notify_device_ready || | ||
362 | notify_event->bus_id != repo->bus_id) { | ||
363 | pr_debug("%s:%u: bad notify_event: event %lu, " | ||
364 | "dev_id %lu, dev_type %lu\n", | ||
365 | __func__, __LINE__, notify_event->event_type, | ||
366 | notify_event->dev_id, notify_event->dev_type); | ||
367 | break; | ||
368 | } | ||
369 | |||
370 | if (notify_event->dev_id == repo->dev_id && | ||
371 | notify_event->dev_type == repo->dev_type) { | ||
372 | pr_debug("%s:%u: device ready: dev_id %u\n", __func__, | ||
373 | __LINE__, repo->dev_id); | ||
374 | result = 0; | ||
375 | break; | ||
376 | } | ||
377 | |||
378 | if (notify_event->dev_id == repo->dev_id && | ||
379 | notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) { | ||
380 | pr_debug("%s:%u: no access: dev_id %u\n", __func__, | ||
381 | __LINE__, repo->dev_id); | ||
382 | break; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | fail_close: | ||
387 | lv1_close_device(repo->bus_id, notification_dev_id); | ||
388 | fail_free: | ||
389 | kfree(notify_cmd); | ||
390 | pr_debug(" <- %s:%u\n", __func__, __LINE__); | ||
391 | return result; | ||
392 | } | ||
393 | |||
394 | static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, | ||
395 | enum ps3_match_id match_id) | ||
396 | { | ||
397 | int result; | ||
398 | struct ps3_storage_device *p; | ||
399 | u64 port, blk_size, num_blocks; | ||
400 | unsigned int num_regions, i; | ||
401 | |||
402 | pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id); | ||
403 | |||
404 | result = ps3_repository_read_stor_dev_info(repo->bus_index, | ||
405 | repo->dev_index, &port, | ||
406 | &blk_size, &num_blocks, | ||
407 | &num_regions); | ||
408 | if (result) { | ||
409 | printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n", | ||
410 | __func__, __LINE__, result); | ||
411 | return -ENODEV; | ||
412 | } | ||
413 | |||
414 | pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu " | ||
415 | "num_regions %u\n", __func__, __LINE__, repo->bus_index, | ||
416 | repo->dev_index, port, blk_size, num_blocks, num_regions); | ||
417 | |||
418 | p = kzalloc(sizeof(struct ps3_storage_device) + | ||
419 | num_regions * sizeof(struct ps3_storage_region), | ||
420 | GFP_KERNEL); | ||
421 | if (!p) { | ||
422 | result = -ENOMEM; | ||
423 | goto fail_malloc; | ||
424 | } | ||
425 | |||
426 | p->sbd.match_id = match_id; | ||
427 | p->sbd.dev_type = PS3_DEVICE_TYPE_SB; | ||
428 | p->sbd.bus_id = repo->bus_id; | ||
429 | p->sbd.dev_id = repo->dev_id; | ||
430 | p->sbd.d_region = &p->dma_region; | ||
431 | p->blk_size = blk_size; | ||
432 | p->num_regions = num_regions; | ||
433 | |||
434 | result = ps3_repository_find_interrupt(repo, | ||
435 | PS3_INTERRUPT_TYPE_EVENT_PORT, | ||
436 | &p->sbd.interrupt_id); | ||
437 | if (result) { | ||
438 | printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__, | ||
439 | __LINE__, result); | ||
440 | result = -ENODEV; | ||
441 | goto fail_find_interrupt; | ||
442 | } | ||
443 | |||
444 | /* FIXME: Arrange to only do this on a 'cold' boot */ | ||
445 | |||
446 | result = ps3_storage_wait_for_device(repo); | ||
447 | if (result) { | ||
448 | printk(KERN_ERR "%s:%u: storage_notification failed %d\n", | ||
449 | __func__, __LINE__, result); | ||
450 | result = -ENODEV; | ||
451 | goto fail_probe_notification; | ||
452 | } | ||
453 | |||
454 | for (i = 0; i < num_regions; i++) { | ||
455 | unsigned int id; | ||
456 | u64 start, size; | ||
457 | |||
458 | result = ps3_repository_read_stor_dev_region(repo->bus_index, | ||
459 | repo->dev_index, | ||
460 | i, &id, &start, | ||
461 | &size); | ||
462 | if (result) { | ||
463 | printk(KERN_ERR | ||
464 | "%s:%u: read_stor_dev_region failed %d\n", | ||
465 | __func__, __LINE__, result); | ||
466 | result = -ENODEV; | ||
467 | goto fail_read_region; | ||
468 | } | ||
469 | pr_debug("%s:%u: region %u: id %u start %lu size %lu\n", | ||
470 | __func__, __LINE__, i, id, start, size); | ||
471 | |||
472 | p->regions[i].id = id; | ||
473 | p->regions[i].start = start; | ||
474 | p->regions[i].size = size; | ||
475 | } | ||
476 | |||
477 | result = ps3_system_bus_device_register(&p->sbd); | ||
478 | if (result) { | ||
479 | pr_debug("%s:%u ps3_system_bus_device_register failed\n", | ||
480 | __func__, __LINE__); | ||
481 | goto fail_device_register; | ||
482 | } | ||
483 | |||
484 | pr_debug(" <- %s:%u\n", __func__, __LINE__); | ||
485 | return 0; | ||
486 | |||
487 | fail_device_register: | ||
488 | fail_read_region: | ||
489 | fail_probe_notification: | ||
490 | fail_find_interrupt: | ||
491 | kfree(p); | ||
492 | fail_malloc: | ||
493 | pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__); | ||
494 | return result; | ||
495 | } | ||
496 | |||
497 | static int __init ps3_register_vuart_devices(void) | ||
498 | { | ||
499 | int result; | ||
500 | unsigned int port_number; | ||
501 | |||
502 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
503 | |||
504 | result = ps3_repository_read_vuart_av_port(&port_number); | ||
505 | if (result) | ||
506 | port_number = 0; /* av default */ | ||
507 | |||
508 | result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number); | ||
509 | WARN_ON(result); | ||
510 | |||
511 | result = ps3_repository_read_vuart_sysmgr_port(&port_number); | ||
512 | if (result) | ||
513 | port_number = 2; /* sysmgr default */ | ||
514 | |||
515 | result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER, | ||
516 | port_number); | ||
517 | WARN_ON(result); | ||
518 | |||
519 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
520 | return result; | ||
521 | } | ||
522 | |||
523 | static int __init ps3_register_sound_devices(void) | ||
524 | { | ||
525 | int result; | ||
526 | struct layout { | ||
527 | struct ps3_system_bus_device dev; | ||
528 | struct ps3_dma_region d_region; | ||
529 | struct ps3_mmio_region m_region; | ||
530 | } *p; | ||
531 | |||
532 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
533 | |||
534 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
535 | if (!p) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | p->dev.match_id = PS3_MATCH_ID_SOUND; | ||
539 | p->dev.dev_type = PS3_DEVICE_TYPE_IOC0; | ||
540 | p->dev.d_region = &p->d_region; | ||
541 | p->dev.m_region = &p->m_region; | ||
542 | |||
543 | result = ps3_system_bus_device_register(&p->dev); | ||
544 | |||
545 | if (result) | ||
546 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
547 | __func__, __LINE__); | ||
548 | |||
549 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
550 | return result; | ||
551 | } | ||
552 | |||
553 | static int __init ps3_register_graphics_devices(void) | ||
554 | { | ||
555 | int result; | ||
556 | struct layout { | ||
557 | struct ps3_system_bus_device dev; | ||
558 | } *p; | ||
559 | |||
560 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
561 | |||
562 | p = kzalloc(sizeof(struct layout), GFP_KERNEL); | ||
563 | |||
564 | if (!p) | ||
565 | return -ENOMEM; | ||
566 | |||
567 | p->dev.match_id = PS3_MATCH_ID_GRAPHICS; | ||
568 | p->dev.dev_type = PS3_DEVICE_TYPE_IOC0; | ||
569 | |||
570 | result = ps3_system_bus_device_register(&p->dev); | ||
571 | |||
572 | if (result) | ||
573 | pr_debug("%s:%d ps3_system_bus_device_register failed\n", | ||
574 | __func__, __LINE__); | ||
575 | |||
576 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
577 | return result; | ||
578 | } | ||
579 | |||
580 | /** | ||
581 | * ps3_register_repository_device - Register a device from the repositiory info. | ||
582 | * | ||
583 | */ | ||
584 | |||
585 | static int ps3_register_repository_device( | ||
586 | const struct ps3_repository_device *repo) | ||
587 | { | ||
588 | int result; | ||
589 | |||
590 | switch (repo->dev_type) { | ||
591 | case PS3_DEV_TYPE_SB_GELIC: | ||
592 | result = ps3_setup_gelic_device(repo); | ||
593 | if (result) { | ||
594 | pr_debug("%s:%d ps3_setup_gelic_device failed\n", | ||
595 | __func__, __LINE__); | ||
596 | } | ||
597 | break; | ||
598 | case PS3_DEV_TYPE_SB_USB: | ||
599 | |||
600 | /* Each USB device has both an EHCI and an OHCI HC */ | ||
601 | |||
602 | result = ps3_setup_ehci_device(repo); | ||
603 | |||
604 | if (result) { | ||
605 | pr_debug("%s:%d ps3_setup_ehci_device failed\n", | ||
606 | __func__, __LINE__); | ||
607 | } | ||
608 | |||
609 | result = ps3_setup_ohci_device(repo); | ||
610 | |||
611 | if (result) { | ||
612 | pr_debug("%s:%d ps3_setup_ohci_device failed\n", | ||
613 | __func__, __LINE__); | ||
614 | } | ||
615 | break; | ||
616 | case PS3_DEV_TYPE_STOR_DISK: | ||
617 | result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK); | ||
618 | |||
619 | /* Some devices are not accessable from the Other OS lpar. */ | ||
620 | if (result == -ENODEV) { | ||
621 | result = 0; | ||
622 | pr_debug("%s:%u: not accessable\n", __func__, | ||
623 | __LINE__); | ||
624 | } | ||
625 | |||
626 | if (result) | ||
627 | pr_debug("%s:%u ps3_setup_storage_dev failed\n", | ||
628 | __func__, __LINE__); | ||
629 | break; | ||
630 | |||
631 | case PS3_DEV_TYPE_STOR_ROM: | ||
632 | result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM); | ||
633 | if (result) | ||
634 | pr_debug("%s:%u ps3_setup_storage_dev failed\n", | ||
635 | __func__, __LINE__); | ||
636 | break; | ||
637 | |||
638 | case PS3_DEV_TYPE_STOR_FLASH: | ||
639 | result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH); | ||
640 | if (result) | ||
641 | pr_debug("%s:%u ps3_setup_storage_dev failed\n", | ||
642 | __func__, __LINE__); | ||
643 | break; | ||
644 | |||
645 | default: | ||
646 | result = 0; | ||
647 | pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__, | ||
648 | repo->dev_type); | ||
649 | } | ||
650 | |||
651 | return result; | ||
652 | } | ||
653 | |||
654 | /** | ||
655 | * ps3_probe_thread - Background repository probing at system startup. | ||
656 | * | ||
657 | * This implementation only supports background probing on a single bus. | ||
658 | */ | ||
659 | |||
660 | static int ps3_probe_thread(void *data) | ||
661 | { | ||
662 | struct ps3_repository_device *repo = data; | ||
663 | int result; | ||
664 | unsigned int ms = 250; | ||
665 | |||
666 | pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); | ||
667 | |||
668 | do { | ||
669 | try_to_freeze(); | ||
670 | |||
671 | pr_debug("%s:%u: probing...\n", __func__, __LINE__); | ||
672 | |||
673 | do { | ||
674 | result = ps3_repository_find_device(repo); | ||
675 | |||
676 | if (result == -ENODEV) | ||
677 | pr_debug("%s:%u: nothing new\n", __func__, | ||
678 | __LINE__); | ||
679 | else if (result) | ||
680 | pr_debug("%s:%u: find device error.\n", | ||
681 | __func__, __LINE__); | ||
682 | else { | ||
683 | pr_debug("%s:%u: found device\n", __func__, | ||
684 | __LINE__); | ||
685 | ps3_register_repository_device(repo); | ||
686 | ps3_repository_bump_device(repo); | ||
687 | ms = 250; | ||
688 | } | ||
689 | } while (!result); | ||
690 | |||
691 | pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms); | ||
692 | |||
693 | if ( ms > 60000) | ||
694 | break; | ||
695 | |||
696 | msleep_interruptible(ms); | ||
697 | |||
698 | /* An exponential backoff. */ | ||
699 | ms <<= 1; | ||
700 | |||
701 | } while (!kthread_should_stop()); | ||
702 | |||
703 | pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * ps3_start_probe_thread - Starts the background probe thread. | ||
710 | * | ||
711 | */ | ||
712 | |||
713 | static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) | ||
714 | { | ||
715 | int result; | ||
716 | struct task_struct *task; | ||
717 | static struct ps3_repository_device repo; /* must be static */ | ||
718 | |||
719 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
720 | |||
721 | memset(&repo, 0, sizeof(repo)); | ||
722 | |||
723 | repo.bus_type = bus_type; | ||
724 | |||
725 | result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index); | ||
726 | |||
727 | if (result) { | ||
728 | printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result); | ||
729 | return -ENODEV; | ||
730 | } | ||
731 | |||
732 | result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id); | ||
733 | |||
734 | if (result) { | ||
735 | printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__, | ||
736 | result); | ||
737 | return -ENODEV; | ||
738 | } | ||
739 | |||
740 | task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type); | ||
741 | |||
742 | if (IS_ERR(task)) { | ||
743 | result = PTR_ERR(task); | ||
744 | printk(KERN_ERR "%s: kthread_run failed %d\n", __func__, | ||
745 | result); | ||
746 | return result; | ||
747 | } | ||
748 | |||
749 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | /** | ||
754 | * ps3_register_devices - Probe the system and register devices found. | ||
755 | * | ||
756 | * A device_initcall() routine. | ||
757 | */ | ||
758 | |||
759 | static int __init ps3_register_devices(void) | ||
760 | { | ||
761 | int result; | ||
762 | |||
763 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
764 | return -ENODEV; | ||
765 | |||
766 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
767 | |||
768 | /* ps3_repository_dump_bus_info(); */ | ||
769 | |||
770 | result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE); | ||
771 | |||
772 | ps3_register_vuart_devices(); | ||
773 | |||
774 | ps3_register_graphics_devices(); | ||
775 | |||
776 | ps3_repository_find_devices(PS3_BUS_TYPE_SB, | ||
777 | ps3_register_repository_device); | ||
778 | |||
779 | ps3_register_sound_devices(); | ||
780 | |||
781 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | device_initcall(ps3_register_devices); | ||
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index a1409e450c70..5d2e176a1b18 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c | |||
@@ -29,12 +29,12 @@ | |||
29 | #include "platform.h" | 29 | #include "platform.h" |
30 | 30 | ||
31 | #if defined(DEBUG) | 31 | #if defined(DEBUG) |
32 | #define DBG(fmt...) udbg_printf(fmt) | 32 | #define DBG udbg_printf |
33 | #else | 33 | #else |
34 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 34 | #define DBG pr_debug |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | static hpte_t *htab; | 37 | static struct hash_pte *htab; |
38 | static unsigned long htab_addr; | 38 | static unsigned long htab_addr; |
39 | static unsigned char *bolttab; | 39 | static unsigned char *bolttab; |
40 | static unsigned char *inusetab; | 40 | static unsigned char *inusetab; |
@@ -44,8 +44,8 @@ static DEFINE_SPINLOCK(ps3_bolttab_lock); | |||
44 | #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ | 44 | #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ |
45 | _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) | 45 | _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) |
46 | static void _debug_dump_hpte(unsigned long pa, unsigned long va, | 46 | static void _debug_dump_hpte(unsigned long pa, unsigned long va, |
47 | unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize, | 47 | unsigned long group, unsigned long bitmap, struct hash_pte lhpte, |
48 | unsigned long slot, const char* func, int line) | 48 | int psize, unsigned long slot, const char* func, int line) |
49 | { | 49 | { |
50 | DBG("%s:%d: pa = %lxh\n", func, line, pa); | 50 | DBG("%s:%d: pa = %lxh\n", func, line, pa); |
51 | DBG("%s:%d: lpar = %lxh\n", func, line, | 51 | DBG("%s:%d: lpar = %lxh\n", func, line, |
@@ -63,7 +63,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
63 | unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) | 63 | unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) |
64 | { | 64 | { |
65 | unsigned long slot; | 65 | unsigned long slot; |
66 | hpte_t lhpte; | 66 | struct hash_pte lhpte; |
67 | int secondary = 0; | 67 | int secondary = 0; |
68 | unsigned long result; | 68 | unsigned long result; |
69 | unsigned long bitmap; | 69 | unsigned long bitmap; |
@@ -234,10 +234,17 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, | |||
234 | 234 | ||
235 | static void ps3_hpte_clear(void) | 235 | static void ps3_hpte_clear(void) |
236 | { | 236 | { |
237 | /* Make sure to clean up the frame buffer device first */ | 237 | int result; |
238 | ps3fb_cleanup(); | ||
239 | 238 | ||
240 | lv1_unmap_htab(htab_addr); | 239 | DBG(" -> %s:%d\n", __func__, __LINE__); |
240 | |||
241 | result = lv1_unmap_htab(htab_addr); | ||
242 | BUG_ON(result); | ||
243 | |||
244 | ps3_mm_shutdown(); | ||
245 | ps3_mm_vas_destroy(); | ||
246 | |||
247 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
241 | } | 248 | } |
242 | 249 | ||
243 | void __init ps3_hpte_init(unsigned long htab_size) | 250 | void __init ps3_hpte_init(unsigned long htab_size) |
@@ -255,7 +262,7 @@ void __init ps3_hpte_init(unsigned long htab_size) | |||
255 | 262 | ||
256 | ppc64_pft_size = __ilog2(htab_size); | 263 | ppc64_pft_size = __ilog2(htab_size); |
257 | 264 | ||
258 | bitmap_size = htab_size / sizeof(hpte_t) / 8; | 265 | bitmap_size = htab_size / sizeof(struct hash_pte) / 8; |
259 | 266 | ||
260 | bolttab = __va(lmb_alloc(bitmap_size, 1)); | 267 | bolttab = __va(lmb_alloc(bitmap_size, 1)); |
261 | inusetab = __va(lmb_alloc(bitmap_size, 1)); | 268 | inusetab = __va(lmb_alloc(bitmap_size, 1)); |
@@ -273,8 +280,8 @@ void __init ps3_map_htab(void) | |||
273 | 280 | ||
274 | result = lv1_map_htab(0, &htab_addr); | 281 | result = lv1_map_htab(0, &htab_addr); |
275 | 282 | ||
276 | htab = (hpte_t *)__ioremap(htab_addr, htab_size, | 283 | htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size, |
277 | pgprot_val(PAGE_READONLY_X)); | 284 | pgprot_val(PAGE_READONLY_X)); |
278 | 285 | ||
279 | DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, | 286 | DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, |
280 | htab_addr, (unsigned long)htab); | 287 | htab_addr, (unsigned long)htab); |
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index ec9030dbb5f1..67e32ec9b37e 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include "platform.h" | 30 | #include "platform.h" |
31 | 31 | ||
32 | #if defined(DEBUG) | 32 | #if defined(DEBUG) |
33 | #define DBG(fmt...) udbg_printf(fmt) | 33 | #define DBG udbg_printf |
34 | #else | 34 | #else |
35 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 35 | #define DBG pr_debug |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | /** | 38 | /** |
@@ -78,19 +78,85 @@ struct ps3_bmp { | |||
78 | /** | 78 | /** |
79 | * struct ps3_private - a per cpu data structure | 79 | * struct ps3_private - a per cpu data structure |
80 | * @bmp: ps3_bmp structure | 80 | * @bmp: ps3_bmp structure |
81 | * @node: HV logical_ppe_id | 81 | * @ppe_id: HV logical_ppe_id |
82 | * @cpu: HV thread_id | 82 | * @thread_id: HV thread_id |
83 | */ | 83 | */ |
84 | 84 | ||
85 | struct ps3_private { | 85 | struct ps3_private { |
86 | struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); | 86 | struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); |
87 | u64 node; | 87 | u64 ppe_id; |
88 | unsigned int cpu; | 88 | u64 thread_id; |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static DEFINE_PER_CPU(struct ps3_private, ps3_private); | 91 | static DEFINE_PER_CPU(struct ps3_private, ps3_private); |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp. | ||
95 | * @virq: The assigned Linux virq. | ||
96 | * | ||
97 | * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). | ||
98 | */ | ||
99 | |||
100 | static void ps3_chip_mask(unsigned int virq) | ||
101 | { | ||
102 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
103 | unsigned long flags; | ||
104 | |||
105 | pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__, | ||
106 | pd->thread_id, virq); | ||
107 | |||
108 | local_irq_save(flags); | ||
109 | clear_bit(63 - virq, &pd->bmp.mask); | ||
110 | lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); | ||
111 | local_irq_restore(flags); | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp. | ||
116 | * @virq: The assigned Linux virq. | ||
117 | * | ||
118 | * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). | ||
119 | */ | ||
120 | |||
121 | static void ps3_chip_unmask(unsigned int virq) | ||
122 | { | ||
123 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
124 | unsigned long flags; | ||
125 | |||
126 | pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__, | ||
127 | pd->thread_id, virq); | ||
128 | |||
129 | local_irq_save(flags); | ||
130 | set_bit(63 - virq, &pd->bmp.mask); | ||
131 | lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); | ||
132 | local_irq_restore(flags); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * ps3_chip_eoi - HV end-of-interrupt. | ||
137 | * @virq: The assigned Linux virq. | ||
138 | * | ||
139 | * Calls lv1_end_of_interrupt_ext(). | ||
140 | */ | ||
141 | |||
142 | static void ps3_chip_eoi(unsigned int virq) | ||
143 | { | ||
144 | const struct ps3_private *pd = get_irq_chip_data(virq); | ||
145 | lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip. | ||
150 | */ | ||
151 | |||
152 | static struct irq_chip ps3_irq_chip = { | ||
153 | .typename = "ps3", | ||
154 | .mask = ps3_chip_mask, | ||
155 | .unmask = ps3_chip_unmask, | ||
156 | .eoi = ps3_chip_eoi, | ||
157 | }; | ||
158 | |||
159 | /** | ||
94 | * ps3_virq_setup - virq related setup. | 160 | * ps3_virq_setup - virq related setup. |
95 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be | 161 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be |
96 | * serviced on. | 162 | * serviced on. |
@@ -134,6 +200,8 @@ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet, | |||
134 | goto fail_set; | 200 | goto fail_set; |
135 | } | 201 | } |
136 | 202 | ||
203 | ps3_chip_mask(*virq); | ||
204 | |||
137 | return result; | 205 | return result; |
138 | 206 | ||
139 | fail_set: | 207 | fail_set: |
@@ -153,8 +221,8 @@ int ps3_virq_destroy(unsigned int virq) | |||
153 | { | 221 | { |
154 | const struct ps3_private *pd = get_irq_chip_data(virq); | 222 | const struct ps3_private *pd = get_irq_chip_data(virq); |
155 | 223 | ||
156 | pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, | 224 | pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__, |
157 | pd->node, pd->cpu, virq); | 225 | __LINE__, pd->ppe_id, pd->thread_id, virq); |
158 | 226 | ||
159 | set_irq_chip_data(virq, NULL); | 227 | set_irq_chip_data(virq, NULL); |
160 | irq_dispose_mapping(virq); | 228 | irq_dispose_mapping(virq); |
@@ -190,7 +258,8 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, | |||
190 | 258 | ||
191 | /* Binds outlet to cpu + virq. */ | 259 | /* Binds outlet to cpu + virq. */ |
192 | 260 | ||
193 | result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); | 261 | result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq, |
262 | outlet, 0); | ||
194 | 263 | ||
195 | if (result) { | 264 | if (result) { |
196 | pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", | 265 | pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", |
@@ -222,10 +291,12 @@ int ps3_irq_plug_destroy(unsigned int virq) | |||
222 | int result; | 291 | int result; |
223 | const struct ps3_private *pd = get_irq_chip_data(virq); | 292 | const struct ps3_private *pd = get_irq_chip_data(virq); |
224 | 293 | ||
225 | pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, | 294 | pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__, |
226 | pd->node, pd->cpu, virq); | 295 | __LINE__, pd->ppe_id, pd->thread_id, virq); |
296 | |||
297 | ps3_chip_mask(virq); | ||
227 | 298 | ||
228 | result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); | 299 | result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq); |
229 | 300 | ||
230 | if (result) | 301 | if (result) |
231 | pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", | 302 | pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", |
@@ -282,7 +353,9 @@ int ps3_event_receive_port_destroy(unsigned int virq) | |||
282 | { | 353 | { |
283 | int result; | 354 | int result; |
284 | 355 | ||
285 | pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq); | 356 | pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq); |
357 | |||
358 | ps3_chip_mask(virq); | ||
286 | 359 | ||
287 | result = lv1_destruct_event_receive_port(virq_to_hw(virq)); | 360 | result = lv1_destruct_event_receive_port(virq_to_hw(virq)); |
288 | 361 | ||
@@ -290,17 +363,14 @@ int ps3_event_receive_port_destroy(unsigned int virq) | |||
290 | pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", | 363 | pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", |
291 | __func__, __LINE__, ps3_result(result)); | 364 | __func__, __LINE__, ps3_result(result)); |
292 | 365 | ||
293 | /* lv1_destruct_event_receive_port() destroys the IRQ plug, | 366 | /* |
294 | * so don't call ps3_irq_plug_destroy() here. | 367 | * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu() |
368 | * calls from interrupt context (smp_call_function) when kexecing. | ||
295 | */ | 369 | */ |
296 | 370 | ||
297 | result = ps3_virq_destroy(virq); | ||
298 | BUG_ON(result); | ||
299 | |||
300 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 371 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
301 | return result; | 372 | return result; |
302 | } | 373 | } |
303 | EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy); | ||
304 | 374 | ||
305 | int ps3_send_event_locally(unsigned int virq) | 375 | int ps3_send_event_locally(unsigned int virq) |
306 | { | 376 | { |
@@ -311,17 +381,15 @@ int ps3_send_event_locally(unsigned int virq) | |||
311 | * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. | 381 | * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. |
312 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be | 382 | * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be |
313 | * serviced on. | 383 | * serviced on. |
314 | * @did: The HV device identifier read from the system repository. | 384 | * @dev: The system bus device instance. |
315 | * @interrupt_id: The device interrupt id read from the system repository. | ||
316 | * @virq: The assigned Linux virq. | 385 | * @virq: The assigned Linux virq. |
317 | * | 386 | * |
318 | * An event irq represents a virtual device interrupt. The interrupt_id | 387 | * An event irq represents a virtual device interrupt. The interrupt_id |
319 | * coresponds to the software interrupt number. | 388 | * coresponds to the software interrupt number. |
320 | */ | 389 | */ |
321 | 390 | ||
322 | int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | 391 | int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, |
323 | const struct ps3_device_id *did, unsigned int interrupt_id, | 392 | enum ps3_cpu_binding cpu, unsigned int *virq) |
324 | unsigned int *virq) | ||
325 | { | 393 | { |
326 | /* this should go in system-bus.c */ | 394 | /* this should go in system-bus.c */ |
327 | 395 | ||
@@ -332,8 +400,8 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | |||
332 | if (result) | 400 | if (result) |
333 | return result; | 401 | return result; |
334 | 402 | ||
335 | result = lv1_connect_interrupt_event_receive_port(did->bus_id, | 403 | result = lv1_connect_interrupt_event_receive_port(dev->bus_id, |
336 | did->dev_id, virq_to_hw(*virq), interrupt_id); | 404 | dev->dev_id, virq_to_hw(*virq), dev->interrupt_id); |
337 | 405 | ||
338 | if (result) { | 406 | if (result) { |
339 | pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" | 407 | pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" |
@@ -345,24 +413,24 @@ int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, | |||
345 | } | 413 | } |
346 | 414 | ||
347 | pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, | 415 | pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, |
348 | interrupt_id, *virq); | 416 | dev->interrupt_id, *virq); |
349 | 417 | ||
350 | return 0; | 418 | return 0; |
351 | } | 419 | } |
352 | EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); | 420 | EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); |
353 | 421 | ||
354 | int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, | 422 | int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, |
355 | unsigned int interrupt_id, unsigned int virq) | 423 | unsigned int virq) |
356 | { | 424 | { |
357 | /* this should go in system-bus.c */ | 425 | /* this should go in system-bus.c */ |
358 | 426 | ||
359 | int result; | 427 | int result; |
360 | 428 | ||
361 | pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, | 429 | pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, |
362 | interrupt_id, virq); | 430 | dev->interrupt_id, virq); |
363 | 431 | ||
364 | result = lv1_disconnect_interrupt_event_receive_port(did->bus_id, | 432 | result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id, |
365 | did->dev_id, virq_to_hw(virq), interrupt_id); | 433 | dev->dev_id, virq_to_hw(virq), dev->interrupt_id); |
366 | 434 | ||
367 | if (result) | 435 | if (result) |
368 | pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" | 436 | pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" |
@@ -372,6 +440,14 @@ int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, | |||
372 | result = ps3_event_receive_port_destroy(virq); | 440 | result = ps3_event_receive_port_destroy(virq); |
373 | BUG_ON(result); | 441 | BUG_ON(result); |
374 | 442 | ||
443 | /* | ||
444 | * ps3_event_receive_port_destroy() destroys the IRQ plug, | ||
445 | * so don't call ps3_irq_plug_destroy() here. | ||
446 | */ | ||
447 | |||
448 | result = ps3_virq_destroy(virq); | ||
449 | BUG_ON(result); | ||
450 | |||
375 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 451 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
376 | return result; | 452 | return result; |
377 | } | 453 | } |
@@ -412,16 +488,24 @@ EXPORT_SYMBOL_GPL(ps3_io_irq_setup); | |||
412 | int ps3_io_irq_destroy(unsigned int virq) | 488 | int ps3_io_irq_destroy(unsigned int virq) |
413 | { | 489 | { |
414 | int result; | 490 | int result; |
491 | unsigned long outlet = virq_to_hw(virq); | ||
415 | 492 | ||
416 | result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); | 493 | ps3_chip_mask(virq); |
417 | 494 | ||
418 | if (result) | 495 | /* |
419 | pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", | 496 | * lv1_destruct_io_irq_outlet() will destroy the IRQ plug, |
420 | __func__, __LINE__, ps3_result(result)); | 497 | * so call ps3_irq_plug_destroy() first. |
498 | */ | ||
421 | 499 | ||
422 | result = ps3_irq_plug_destroy(virq); | 500 | result = ps3_irq_plug_destroy(virq); |
423 | BUG_ON(result); | 501 | BUG_ON(result); |
424 | 502 | ||
503 | result = lv1_destruct_io_irq_outlet(outlet); | ||
504 | |||
505 | if (result) | ||
506 | pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", | ||
507 | __func__, __LINE__, ps3_result(result)); | ||
508 | |||
425 | return result; | 509 | return result; |
426 | } | 510 | } |
427 | EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); | 511 | EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); |
@@ -461,11 +545,13 @@ int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, | |||
461 | 545 | ||
462 | return result; | 546 | return result; |
463 | } | 547 | } |
548 | EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup); | ||
464 | 549 | ||
465 | int ps3_vuart_irq_destroy(unsigned int virq) | 550 | int ps3_vuart_irq_destroy(unsigned int virq) |
466 | { | 551 | { |
467 | int result; | 552 | int result; |
468 | 553 | ||
554 | ps3_chip_mask(virq); | ||
469 | result = lv1_deconfigure_virtual_uart_irq(); | 555 | result = lv1_deconfigure_virtual_uart_irq(); |
470 | 556 | ||
471 | if (result) { | 557 | if (result) { |
@@ -479,6 +565,7 @@ int ps3_vuart_irq_destroy(unsigned int virq) | |||
479 | 565 | ||
480 | return result; | 566 | return result; |
481 | } | 567 | } |
568 | EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy); | ||
482 | 569 | ||
483 | /** | 570 | /** |
484 | * ps3_spe_irq_setup - Setup an spe virq. | 571 | * ps3_spe_irq_setup - Setup an spe virq. |
@@ -514,9 +601,14 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, | |||
514 | 601 | ||
515 | int ps3_spe_irq_destroy(unsigned int virq) | 602 | int ps3_spe_irq_destroy(unsigned int virq) |
516 | { | 603 | { |
517 | int result = ps3_irq_plug_destroy(virq); | 604 | int result; |
605 | |||
606 | ps3_chip_mask(virq); | ||
607 | |||
608 | result = ps3_irq_plug_destroy(virq); | ||
518 | BUG_ON(result); | 609 | BUG_ON(result); |
519 | return 0; | 610 | |
611 | return result; | ||
520 | } | 612 | } |
521 | 613 | ||
522 | 614 | ||
@@ -533,7 +625,7 @@ static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu, | |||
533 | *p & 0xffff); | 625 | *p & 0xffff); |
534 | } | 626 | } |
535 | 627 | ||
536 | static void __attribute__ ((unused)) _dump_256_bmp(const char *header, | 628 | static void __maybe_unused _dump_256_bmp(const char *header, |
537 | const u64 *p, unsigned cpu, const char* func, int line) | 629 | const u64 *p, unsigned cpu, const char* func, int line) |
538 | { | 630 | { |
539 | pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", | 631 | pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", |
@@ -546,86 +638,25 @@ static void _dump_bmp(struct ps3_private* pd, const char* func, int line) | |||
546 | unsigned long flags; | 638 | unsigned long flags; |
547 | 639 | ||
548 | spin_lock_irqsave(&pd->bmp.lock, flags); | 640 | spin_lock_irqsave(&pd->bmp.lock, flags); |
549 | _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line); | 641 | _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line); |
550 | _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); | 642 | _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); |
551 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | 643 | spin_unlock_irqrestore(&pd->bmp.lock, flags); |
552 | } | 644 | } |
553 | 645 | ||
554 | #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) | 646 | #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) |
555 | static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd, | 647 | static void __maybe_unused _dump_mask(struct ps3_private *pd, |
556 | const char* func, int line) | 648 | const char* func, int line) |
557 | { | 649 | { |
558 | unsigned long flags; | 650 | unsigned long flags; |
559 | 651 | ||
560 | spin_lock_irqsave(&pd->bmp.lock, flags); | 652 | spin_lock_irqsave(&pd->bmp.lock, flags); |
561 | _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); | 653 | _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); |
562 | spin_unlock_irqrestore(&pd->bmp.lock, flags); | 654 | spin_unlock_irqrestore(&pd->bmp.lock, flags); |
563 | } | 655 | } |
564 | #else | 656 | #else |
565 | static void dump_bmp(struct ps3_private* pd) {}; | 657 | static void dump_bmp(struct ps3_private* pd) {}; |
566 | #endif /* defined(DEBUG) */ | 658 | #endif /* defined(DEBUG) */ |
567 | 659 | ||
568 | static void ps3_chip_mask(unsigned int virq) | ||
569 | { | ||
570 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
571 | u64 bit = 0x8000000000000000UL >> virq; | ||
572 | u64 *p = &pd->bmp.mask; | ||
573 | u64 old; | ||
574 | unsigned long flags; | ||
575 | |||
576 | pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); | ||
577 | |||
578 | local_irq_save(flags); | ||
579 | asm volatile( | ||
580 | "1: ldarx %0,0,%3\n" | ||
581 | "andc %0,%0,%2\n" | ||
582 | "stdcx. %0,0,%3\n" | ||
583 | "bne- 1b" | ||
584 | : "=&r" (old), "+m" (*p) | ||
585 | : "r" (bit), "r" (p) | ||
586 | : "cc" ); | ||
587 | |||
588 | lv1_did_update_interrupt_mask(pd->node, pd->cpu); | ||
589 | local_irq_restore(flags); | ||
590 | } | ||
591 | |||
592 | static void ps3_chip_unmask(unsigned int virq) | ||
593 | { | ||
594 | struct ps3_private *pd = get_irq_chip_data(virq); | ||
595 | u64 bit = 0x8000000000000000UL >> virq; | ||
596 | u64 *p = &pd->bmp.mask; | ||
597 | u64 old; | ||
598 | unsigned long flags; | ||
599 | |||
600 | pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); | ||
601 | |||
602 | local_irq_save(flags); | ||
603 | asm volatile( | ||
604 | "1: ldarx %0,0,%3\n" | ||
605 | "or %0,%0,%2\n" | ||
606 | "stdcx. %0,0,%3\n" | ||
607 | "bne- 1b" | ||
608 | : "=&r" (old), "+m" (*p) | ||
609 | : "r" (bit), "r" (p) | ||
610 | : "cc" ); | ||
611 | |||
612 | lv1_did_update_interrupt_mask(pd->node, pd->cpu); | ||
613 | local_irq_restore(flags); | ||
614 | } | ||
615 | |||
616 | static void ps3_chip_eoi(unsigned int virq) | ||
617 | { | ||
618 | const struct ps3_private *pd = get_irq_chip_data(virq); | ||
619 | lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq); | ||
620 | } | ||
621 | |||
622 | static struct irq_chip irq_chip = { | ||
623 | .typename = "ps3", | ||
624 | .mask = ps3_chip_mask, | ||
625 | .unmask = ps3_chip_unmask, | ||
626 | .eoi = ps3_chip_eoi, | ||
627 | }; | ||
628 | |||
629 | static void ps3_host_unmap(struct irq_host *h, unsigned int virq) | 660 | static void ps3_host_unmap(struct irq_host *h, unsigned int virq) |
630 | { | 661 | { |
631 | set_irq_chip_data(virq, NULL); | 662 | set_irq_chip_data(virq, NULL); |
@@ -637,7 +668,7 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq, | |||
637 | pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, | 668 | pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, |
638 | virq); | 669 | virq); |
639 | 670 | ||
640 | set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); | 671 | set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq); |
641 | 672 | ||
642 | return 0; | 673 | return 0; |
643 | } | 674 | } |
@@ -657,7 +688,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) | |||
657 | cpu, virq, pd->bmp.ipi_debug_brk_mask); | 688 | cpu, virq, pd->bmp.ipi_debug_brk_mask); |
658 | } | 689 | } |
659 | 690 | ||
660 | unsigned int ps3_get_irq(void) | 691 | static unsigned int ps3_get_irq(void) |
661 | { | 692 | { |
662 | struct ps3_private *pd = &__get_cpu_var(ps3_private); | 693 | struct ps3_private *pd = &__get_cpu_var(ps3_private); |
663 | u64 x = (pd->bmp.status & pd->bmp.mask); | 694 | u64 x = (pd->bmp.status & pd->bmp.mask); |
@@ -672,8 +703,8 @@ unsigned int ps3_get_irq(void) | |||
672 | plug &= 0x3f; | 703 | plug &= 0x3f; |
673 | 704 | ||
674 | if (unlikely(plug) == NO_IRQ) { | 705 | if (unlikely(plug) == NO_IRQ) { |
675 | pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__, | 706 | pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__, |
676 | pd->cpu); | 707 | __LINE__, pd->thread_id); |
677 | dump_bmp(&per_cpu(ps3_private, 0)); | 708 | dump_bmp(&per_cpu(ps3_private, 0)); |
678 | dump_bmp(&per_cpu(ps3_private, 1)); | 709 | dump_bmp(&per_cpu(ps3_private, 1)); |
679 | return NO_IRQ; | 710 | return NO_IRQ; |
@@ -703,16 +734,16 @@ void __init ps3_init_IRQ(void) | |||
703 | for_each_possible_cpu(cpu) { | 734 | for_each_possible_cpu(cpu) { |
704 | struct ps3_private *pd = &per_cpu(ps3_private, cpu); | 735 | struct ps3_private *pd = &per_cpu(ps3_private, cpu); |
705 | 736 | ||
706 | lv1_get_logical_ppe_id(&pd->node); | 737 | lv1_get_logical_ppe_id(&pd->ppe_id); |
707 | pd->cpu = get_hard_smp_processor_id(cpu); | 738 | pd->thread_id = get_hard_smp_processor_id(cpu); |
708 | spin_lock_init(&pd->bmp.lock); | 739 | spin_lock_init(&pd->bmp.lock); |
709 | 740 | ||
710 | pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__, | 741 | pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n", |
711 | __LINE__, pd->node, pd->cpu, | 742 | __func__, __LINE__, pd->ppe_id, pd->thread_id, |
712 | ps3_mm_phys_to_lpar(__pa(&pd->bmp))); | 743 | ps3_mm_phys_to_lpar(__pa(&pd->bmp))); |
713 | 744 | ||
714 | result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu, | 745 | result = lv1_configure_irq_state_bitmap(pd->ppe_id, |
715 | ps3_mm_phys_to_lpar(__pa(&pd->bmp))); | 746 | pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp))); |
716 | 747 | ||
717 | if (result) | 748 | if (result) |
718 | pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" | 749 | pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" |
@@ -722,3 +753,16 @@ void __init ps3_init_IRQ(void) | |||
722 | 753 | ||
723 | ppc_md.get_irq = ps3_get_irq; | 754 | ppc_md.get_irq = ps3_get_irq; |
724 | } | 755 | } |
756 | |||
757 | void ps3_shutdown_IRQ(int cpu) | ||
758 | { | ||
759 | int result; | ||
760 | u64 ppe_id; | ||
761 | u64 thread_id = get_hard_smp_processor_id(cpu); | ||
762 | |||
763 | lv1_get_logical_ppe_id(&ppe_id); | ||
764 | result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0); | ||
765 | |||
766 | DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__, | ||
767 | __LINE__, ppe_id, thread_id, cpu, ps3_result(result)); | ||
768 | } | ||
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index f8a3e206c584..7bb3e1620974 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include "platform.h" | 30 | #include "platform.h" |
31 | 31 | ||
32 | #if defined(DEBUG) | 32 | #if defined(DEBUG) |
33 | #define DBG(fmt...) udbg_printf(fmt) | 33 | #define DBG udbg_printf |
34 | #else | 34 | #else |
35 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 35 | #define DBG pr_debug |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | enum { | 38 | enum { |
@@ -115,7 +115,8 @@ struct map { | |||
115 | }; | 115 | }; |
116 | 116 | ||
117 | #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__) | 117 | #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__) |
118 | static void _debug_dump_map(const struct map* m, const char* func, int line) | 118 | static void __maybe_unused _debug_dump_map(const struct map *m, |
119 | const char *func, int line) | ||
119 | { | 120 | { |
120 | DBG("%s:%d: map.total = %lxh\n", func, line, m->total); | 121 | DBG("%s:%d: map.total = %lxh\n", func, line, m->total); |
121 | DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size); | 122 | DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size); |
@@ -212,9 +213,15 @@ fail: | |||
212 | 213 | ||
213 | void ps3_mm_vas_destroy(void) | 214 | void ps3_mm_vas_destroy(void) |
214 | { | 215 | { |
216 | int result; | ||
217 | |||
218 | DBG("%s:%d: map.vas_id = %lu\n", __func__, __LINE__, map.vas_id); | ||
219 | |||
215 | if (map.vas_id) { | 220 | if (map.vas_id) { |
216 | lv1_select_virtual_address_space(0); | 221 | result = lv1_select_virtual_address_space(0); |
217 | lv1_destruct_virtual_address_space(map.vas_id); | 222 | BUG_ON(result); |
223 | result = lv1_destruct_virtual_address_space(map.vas_id); | ||
224 | BUG_ON(result); | ||
218 | map.vas_id = 0; | 225 | map.vas_id = 0; |
219 | } | 226 | } |
220 | } | 227 | } |
@@ -232,7 +239,7 @@ void ps3_mm_vas_destroy(void) | |||
232 | * @size is rounded down to a multiple of the vas large page size. | 239 | * @size is rounded down to a multiple of the vas large page size. |
233 | */ | 240 | */ |
234 | 241 | ||
235 | int ps3_mm_region_create(struct mem_region *r, unsigned long size) | 242 | static int ps3_mm_region_create(struct mem_region *r, unsigned long size) |
236 | { | 243 | { |
237 | int result; | 244 | int result; |
238 | unsigned long muid; | 245 | unsigned long muid; |
@@ -273,10 +280,14 @@ zero_region: | |||
273 | * @r: pointer to struct mem_region | 280 | * @r: pointer to struct mem_region |
274 | */ | 281 | */ |
275 | 282 | ||
276 | void ps3_mm_region_destroy(struct mem_region *r) | 283 | static void ps3_mm_region_destroy(struct mem_region *r) |
277 | { | 284 | { |
285 | int result; | ||
286 | |||
287 | DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base); | ||
278 | if (r->base) { | 288 | if (r->base) { |
279 | lv1_release_memory(r->base); | 289 | result = lv1_release_memory(r->base); |
290 | BUG_ON(result); | ||
280 | r->size = r->base = r->offset = 0; | 291 | r->size = r->base = r->offset = 0; |
281 | map.total = map.rm.size; | 292 | map.total = map.rm.size; |
282 | } | 293 | } |
@@ -329,31 +340,34 @@ core_initcall(ps3_mm_add_memory); | |||
329 | /*============================================================================*/ | 340 | /*============================================================================*/ |
330 | 341 | ||
331 | /** | 342 | /** |
332 | * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address. | 343 | * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address. |
333 | * @r: pointer to dma region structure | 344 | * @r: pointer to dma region structure |
334 | * @lpar_addr: HV lpar address | 345 | * @lpar_addr: HV lpar address |
335 | */ | 346 | */ |
336 | 347 | ||
337 | static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r, | 348 | static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r, |
338 | unsigned long lpar_addr) | 349 | unsigned long lpar_addr) |
339 | { | 350 | { |
340 | BUG_ON(lpar_addr >= map.r1.base + map.r1.size); | 351 | if (lpar_addr >= map.rm.size) |
341 | return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr | 352 | lpar_addr -= map.r1.offset; |
342 | : lpar_addr - map.r1.offset); | 353 | BUG_ON(lpar_addr < r->offset); |
354 | BUG_ON(lpar_addr >= r->offset + r->len); | ||
355 | return r->bus_addr + lpar_addr - r->offset; | ||
343 | } | 356 | } |
344 | 357 | ||
345 | #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__) | 358 | #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__) |
346 | static void _dma_dump_region(const struct ps3_dma_region *r, const char* func, | 359 | static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r, |
347 | int line) | 360 | const char *func, int line) |
348 | { | 361 | { |
349 | DBG("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, | 362 | DBG("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, |
350 | r->did.dev_id); | 363 | r->dev->dev_id); |
351 | DBG("%s:%d: page_size %u\n", func, line, r->page_size); | 364 | DBG("%s:%d: page_size %u\n", func, line, r->page_size); |
352 | DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | 365 | DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); |
353 | DBG("%s:%d: len %lxh\n", func, line, r->len); | 366 | DBG("%s:%d: len %lxh\n", func, line, r->len); |
367 | DBG("%s:%d: offset %lxh\n", func, line, r->offset); | ||
354 | } | 368 | } |
355 | 369 | ||
356 | /** | 370 | /** |
357 | * dma_chunk - A chunk of dma pages mapped by the io controller. | 371 | * dma_chunk - A chunk of dma pages mapped by the io controller. |
358 | * @region - The dma region that owns this chunk. | 372 | * @region - The dma region that owns this chunk. |
359 | * @lpar_addr: Starting lpar address of the area to map. | 373 | * @lpar_addr: Starting lpar address of the area to map. |
@@ -381,10 +395,11 @@ static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, | |||
381 | int line) | 395 | int line) |
382 | { | 396 | { |
383 | DBG("%s:%d: r.dev %u:%u\n", func, line, | 397 | DBG("%s:%d: r.dev %u:%u\n", func, line, |
384 | c->region->did.bus_id, c->region->did.dev_id); | 398 | c->region->dev->bus_id, c->region->dev->dev_id); |
385 | DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); | 399 | DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); |
386 | DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); | 400 | DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); |
387 | DBG("%s:%d: r.len %lxh\n", func, line, c->region->len); | 401 | DBG("%s:%d: r.len %lxh\n", func, line, c->region->len); |
402 | DBG("%s:%d: r.offset %lxh\n", func, line, c->region->offset); | ||
388 | DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr); | 403 | DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr); |
389 | DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr); | 404 | DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr); |
390 | DBG("%s:%d: c.len %lxh\n", func, line, c->len); | 405 | DBG("%s:%d: c.len %lxh\n", func, line, c->len); |
@@ -395,39 +410,68 @@ static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r, | |||
395 | { | 410 | { |
396 | struct dma_chunk *c; | 411 | struct dma_chunk *c; |
397 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); | 412 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); |
398 | unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); | 413 | unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus, |
414 | 1 << r->page_size); | ||
399 | 415 | ||
400 | list_for_each_entry(c, &r->chunk_list.head, link) { | 416 | list_for_each_entry(c, &r->chunk_list.head, link) { |
401 | /* intersection */ | 417 | /* intersection */ |
402 | if (aligned_bus >= c->bus_addr | 418 | if (aligned_bus >= c->bus_addr && |
403 | && aligned_bus < c->bus_addr + c->len | 419 | aligned_bus + aligned_len <= c->bus_addr + c->len) |
404 | && aligned_bus + aligned_len <= c->bus_addr + c->len) { | ||
405 | return c; | 420 | return c; |
406 | } | 421 | |
407 | /* below */ | 422 | /* below */ |
408 | if (aligned_bus + aligned_len <= c->bus_addr) { | 423 | if (aligned_bus + aligned_len <= c->bus_addr) |
409 | continue; | 424 | continue; |
410 | } | 425 | |
411 | /* above */ | 426 | /* above */ |
412 | if (aligned_bus >= c->bus_addr + c->len) { | 427 | if (aligned_bus >= c->bus_addr + c->len) |
413 | continue; | 428 | continue; |
414 | } | ||
415 | 429 | ||
416 | /* we don't handle the multi-chunk case for now */ | 430 | /* we don't handle the multi-chunk case for now */ |
417 | |||
418 | dma_dump_chunk(c); | 431 | dma_dump_chunk(c); |
419 | BUG(); | 432 | BUG(); |
420 | } | 433 | } |
421 | return NULL; | 434 | return NULL; |
422 | } | 435 | } |
423 | 436 | ||
424 | static int dma_free_chunk(struct dma_chunk *c) | 437 | static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r, |
438 | unsigned long lpar_addr, unsigned long len) | ||
439 | { | ||
440 | struct dma_chunk *c; | ||
441 | unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size); | ||
442 | unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar, | ||
443 | 1 << r->page_size); | ||
444 | |||
445 | list_for_each_entry(c, &r->chunk_list.head, link) { | ||
446 | /* intersection */ | ||
447 | if (c->lpar_addr <= aligned_lpar && | ||
448 | aligned_lpar < c->lpar_addr + c->len) { | ||
449 | if (aligned_lpar + aligned_len <= c->lpar_addr + c->len) | ||
450 | return c; | ||
451 | else { | ||
452 | dma_dump_chunk(c); | ||
453 | BUG(); | ||
454 | } | ||
455 | } | ||
456 | /* below */ | ||
457 | if (aligned_lpar + aligned_len <= c->lpar_addr) { | ||
458 | continue; | ||
459 | } | ||
460 | /* above */ | ||
461 | if (c->lpar_addr + c->len <= aligned_lpar) { | ||
462 | continue; | ||
463 | } | ||
464 | } | ||
465 | return NULL; | ||
466 | } | ||
467 | |||
468 | static int dma_sb_free_chunk(struct dma_chunk *c) | ||
425 | { | 469 | { |
426 | int result = 0; | 470 | int result = 0; |
427 | 471 | ||
428 | if (c->bus_addr) { | 472 | if (c->bus_addr) { |
429 | result = lv1_unmap_device_dma_region(c->region->did.bus_id, | 473 | result = lv1_unmap_device_dma_region(c->region->dev->bus_id, |
430 | c->region->did.dev_id, c->bus_addr, c->len); | 474 | c->region->dev->dev_id, c->bus_addr, c->len); |
431 | BUG_ON(result); | 475 | BUG_ON(result); |
432 | } | 476 | } |
433 | 477 | ||
@@ -435,8 +479,39 @@ static int dma_free_chunk(struct dma_chunk *c) | |||
435 | return result; | 479 | return result; |
436 | } | 480 | } |
437 | 481 | ||
482 | static int dma_ioc0_free_chunk(struct dma_chunk *c) | ||
483 | { | ||
484 | int result = 0; | ||
485 | int iopage; | ||
486 | unsigned long offset; | ||
487 | struct ps3_dma_region *r = c->region; | ||
488 | |||
489 | DBG("%s:start\n", __func__); | ||
490 | for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) { | ||
491 | offset = (1 << r->page_size) * iopage; | ||
492 | /* put INVALID entry */ | ||
493 | result = lv1_put_iopte(0, | ||
494 | c->bus_addr + offset, | ||
495 | c->lpar_addr + offset, | ||
496 | r->ioid, | ||
497 | 0); | ||
498 | DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__, | ||
499 | c->bus_addr + offset, | ||
500 | c->lpar_addr + offset, | ||
501 | r->ioid); | ||
502 | |||
503 | if (result) { | ||
504 | DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__, | ||
505 | __LINE__, ps3_result(result)); | ||
506 | } | ||
507 | } | ||
508 | kfree(c); | ||
509 | DBG("%s:end\n", __func__); | ||
510 | return result; | ||
511 | } | ||
512 | |||
438 | /** | 513 | /** |
439 | * dma_map_pages - Maps dma pages into the io controller bus address space. | 514 | * dma_sb_map_pages - Maps dma pages into the io controller bus address space. |
440 | * @r: Pointer to a struct ps3_dma_region. | 515 | * @r: Pointer to a struct ps3_dma_region. |
441 | * @phys_addr: Starting physical address of the area to map. | 516 | * @phys_addr: Starting physical address of the area to map. |
442 | * @len: Length in bytes of the area to map. | 517 | * @len: Length in bytes of the area to map. |
@@ -446,8 +521,8 @@ static int dma_free_chunk(struct dma_chunk *c) | |||
446 | * make the HV call to add the pages into the io controller address space. | 521 | * make the HV call to add the pages into the io controller address space. |
447 | */ | 522 | */ |
448 | 523 | ||
449 | static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, | 524 | static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, |
450 | unsigned long len, struct dma_chunk **c_out) | 525 | unsigned long len, struct dma_chunk **c_out, u64 iopte_flag) |
451 | { | 526 | { |
452 | int result; | 527 | int result; |
453 | struct dma_chunk *c; | 528 | struct dma_chunk *c; |
@@ -461,13 +536,13 @@ static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, | |||
461 | 536 | ||
462 | c->region = r; | 537 | c->region = r; |
463 | c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | 538 | c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); |
464 | c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr); | 539 | c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr); |
465 | c->len = len; | 540 | c->len = len; |
466 | 541 | ||
467 | result = lv1_map_device_dma_region(c->region->did.bus_id, | 542 | BUG_ON(iopte_flag != 0xf800000000000000UL); |
468 | c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len, | 543 | result = lv1_map_device_dma_region(c->region->dev->bus_id, |
469 | 0xf800000000000000UL); | 544 | c->region->dev->dev_id, c->lpar_addr, |
470 | 545 | c->bus_addr, c->len, iopte_flag); | |
471 | if (result) { | 546 | if (result) { |
472 | DBG("%s:%d: lv1_map_device_dma_region failed: %s\n", | 547 | DBG("%s:%d: lv1_map_device_dma_region failed: %s\n", |
473 | __func__, __LINE__, ps3_result(result)); | 548 | __func__, __LINE__, ps3_result(result)); |
@@ -487,26 +562,120 @@ fail_alloc: | |||
487 | return result; | 562 | return result; |
488 | } | 563 | } |
489 | 564 | ||
565 | static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, | ||
566 | unsigned long len, struct dma_chunk **c_out, | ||
567 | u64 iopte_flag) | ||
568 | { | ||
569 | int result; | ||
570 | struct dma_chunk *c, *last; | ||
571 | int iopage, pages; | ||
572 | unsigned long offset; | ||
573 | |||
574 | DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__, | ||
575 | phys_addr, ps3_mm_phys_to_lpar(phys_addr), len); | ||
576 | c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC); | ||
577 | |||
578 | if (!c) { | ||
579 | result = -ENOMEM; | ||
580 | goto fail_alloc; | ||
581 | } | ||
582 | |||
583 | c->region = r; | ||
584 | c->len = len; | ||
585 | c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | ||
586 | /* allocate IO address */ | ||
587 | if (list_empty(&r->chunk_list.head)) { | ||
588 | /* first one */ | ||
589 | c->bus_addr = r->bus_addr; | ||
590 | } else { | ||
591 | /* derive from last bus addr*/ | ||
592 | last = list_entry(r->chunk_list.head.next, | ||
593 | struct dma_chunk, link); | ||
594 | c->bus_addr = last->bus_addr + last->len; | ||
595 | DBG("%s: last bus=%#lx, len=%#lx\n", __func__, | ||
596 | last->bus_addr, last->len); | ||
597 | } | ||
598 | |||
599 | /* FIXME: check whether length exceeds region size */ | ||
600 | |||
601 | /* build ioptes for the area */ | ||
602 | pages = len >> r->page_size; | ||
603 | DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__, | ||
604 | r->page_size, r->len, pages, iopte_flag); | ||
605 | for (iopage = 0; iopage < pages; iopage++) { | ||
606 | offset = (1 << r->page_size) * iopage; | ||
607 | result = lv1_put_iopte(0, | ||
608 | c->bus_addr + offset, | ||
609 | c->lpar_addr + offset, | ||
610 | r->ioid, | ||
611 | iopte_flag); | ||
612 | if (result) { | ||
613 | printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region " | ||
614 | "failed: %s\n", __func__, __LINE__, | ||
615 | ps3_result(result)); | ||
616 | goto fail_map; | ||
617 | } | ||
618 | DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__, | ||
619 | iopage, c->bus_addr + offset, c->lpar_addr + offset, | ||
620 | r->ioid); | ||
621 | } | ||
622 | |||
623 | /* be sure that last allocated one is inserted at head */ | ||
624 | list_add(&c->link, &r->chunk_list.head); | ||
625 | |||
626 | *c_out = c; | ||
627 | DBG("%s: end\n", __func__); | ||
628 | return 0; | ||
629 | |||
630 | fail_map: | ||
631 | for (iopage--; 0 <= iopage; iopage--) { | ||
632 | lv1_put_iopte(0, | ||
633 | c->bus_addr + offset, | ||
634 | c->lpar_addr + offset, | ||
635 | r->ioid, | ||
636 | 0); | ||
637 | } | ||
638 | kfree(c); | ||
639 | fail_alloc: | ||
640 | *c_out = NULL; | ||
641 | return result; | ||
642 | } | ||
643 | |||
490 | /** | 644 | /** |
491 | * dma_region_create - Create a device dma region. | 645 | * dma_sb_region_create - Create a device dma region. |
492 | * @r: Pointer to a struct ps3_dma_region. | 646 | * @r: Pointer to a struct ps3_dma_region. |
493 | * | 647 | * |
494 | * This is the lowest level dma region create routine, and is the one that | 648 | * This is the lowest level dma region create routine, and is the one that |
495 | * will make the HV call to create the region. | 649 | * will make the HV call to create the region. |
496 | */ | 650 | */ |
497 | 651 | ||
498 | static int dma_region_create(struct ps3_dma_region* r) | 652 | static int dma_sb_region_create(struct ps3_dma_region *r) |
499 | { | 653 | { |
500 | int result; | 654 | int result; |
501 | 655 | ||
502 | r->len = _ALIGN_UP(map.total, 1 << r->page_size); | 656 | pr_info(" -> %s:%d:\n", __func__, __LINE__); |
657 | |||
658 | BUG_ON(!r); | ||
659 | |||
660 | if (!r->dev->bus_id) { | ||
661 | pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, | ||
662 | r->dev->bus_id, r->dev->dev_id); | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__, | ||
667 | __LINE__, r->len, r->page_size, r->offset); | ||
668 | |||
669 | BUG_ON(!r->len); | ||
670 | BUG_ON(!r->page_size); | ||
671 | BUG_ON(!r->region_ops); | ||
672 | |||
503 | INIT_LIST_HEAD(&r->chunk_list.head); | 673 | INIT_LIST_HEAD(&r->chunk_list.head); |
504 | spin_lock_init(&r->chunk_list.lock); | 674 | spin_lock_init(&r->chunk_list.lock); |
505 | 675 | ||
506 | result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id, | 676 | result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id, |
507 | r->len, r->page_size, r->region_type, &r->bus_addr); | 677 | roundup_pow_of_two(r->len), r->page_size, r->region_type, |
508 | 678 | &r->bus_addr); | |
509 | dma_dump_region(r); | ||
510 | 679 | ||
511 | if (result) { | 680 | if (result) { |
512 | DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n", | 681 | DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n", |
@@ -517,6 +686,27 @@ static int dma_region_create(struct ps3_dma_region* r) | |||
517 | return result; | 686 | return result; |
518 | } | 687 | } |
519 | 688 | ||
689 | static int dma_ioc0_region_create(struct ps3_dma_region *r) | ||
690 | { | ||
691 | int result; | ||
692 | |||
693 | INIT_LIST_HEAD(&r->chunk_list.head); | ||
694 | spin_lock_init(&r->chunk_list.lock); | ||
695 | |||
696 | result = lv1_allocate_io_segment(0, | ||
697 | r->len, | ||
698 | r->page_size, | ||
699 | &r->bus_addr); | ||
700 | if (result) { | ||
701 | DBG("%s:%d: lv1_allocate_io_segment failed: %s\n", | ||
702 | __func__, __LINE__, ps3_result(result)); | ||
703 | r->len = r->bus_addr = 0; | ||
704 | } | ||
705 | DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__, | ||
706 | r->len, r->page_size, r->bus_addr); | ||
707 | return result; | ||
708 | } | ||
709 | |||
520 | /** | 710 | /** |
521 | * dma_region_free - Free a device dma region. | 711 | * dma_region_free - Free a device dma region. |
522 | * @r: Pointer to a struct ps3_dma_region. | 712 | * @r: Pointer to a struct ps3_dma_region. |
@@ -525,31 +715,62 @@ static int dma_region_create(struct ps3_dma_region* r) | |||
525 | * will make the HV call to free the region. | 715 | * will make the HV call to free the region. |
526 | */ | 716 | */ |
527 | 717 | ||
528 | static int dma_region_free(struct ps3_dma_region* r) | 718 | static int dma_sb_region_free(struct ps3_dma_region *r) |
529 | { | 719 | { |
530 | int result; | 720 | int result; |
531 | struct dma_chunk *c; | 721 | struct dma_chunk *c; |
532 | struct dma_chunk *tmp; | 722 | struct dma_chunk *tmp; |
533 | 723 | ||
724 | BUG_ON(!r); | ||
725 | |||
726 | if (!r->dev->bus_id) { | ||
727 | pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, | ||
728 | r->dev->bus_id, r->dev->dev_id); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
534 | list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) { | 732 | list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) { |
535 | list_del(&c->link); | 733 | list_del(&c->link); |
536 | dma_free_chunk(c); | 734 | dma_sb_free_chunk(c); |
537 | } | 735 | } |
538 | 736 | ||
539 | result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id, | 737 | result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id, |
540 | r->bus_addr); | 738 | r->bus_addr); |
541 | 739 | ||
542 | if (result) | 740 | if (result) |
543 | DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", | 741 | DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", |
544 | __func__, __LINE__, ps3_result(result)); | 742 | __func__, __LINE__, ps3_result(result)); |
545 | 743 | ||
546 | r->len = r->bus_addr = 0; | 744 | r->bus_addr = 0; |
745 | |||
746 | return result; | ||
747 | } | ||
748 | |||
749 | static int dma_ioc0_region_free(struct ps3_dma_region *r) | ||
750 | { | ||
751 | int result; | ||
752 | struct dma_chunk *c, *n; | ||
753 | |||
754 | DBG("%s: start\n", __func__); | ||
755 | list_for_each_entry_safe(c, n, &r->chunk_list.head, link) { | ||
756 | list_del(&c->link); | ||
757 | dma_ioc0_free_chunk(c); | ||
758 | } | ||
759 | |||
760 | result = lv1_release_io_segment(0, r->bus_addr); | ||
761 | |||
762 | if (result) | ||
763 | DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", | ||
764 | __func__, __LINE__, ps3_result(result)); | ||
765 | |||
766 | r->bus_addr = 0; | ||
767 | DBG("%s: end\n", __func__); | ||
547 | 768 | ||
548 | return result; | 769 | return result; |
549 | } | 770 | } |
550 | 771 | ||
551 | /** | 772 | /** |
552 | * dma_map_area - Map an area of memory into a device dma region. | 773 | * dma_sb_map_area - Map an area of memory into a device dma region. |
553 | * @r: Pointer to a struct ps3_dma_region. | 774 | * @r: Pointer to a struct ps3_dma_region. |
554 | * @virt_addr: Starting virtual address of the area to map. | 775 | * @virt_addr: Starting virtual address of the area to map. |
555 | * @len: Length in bytes of the area to map. | 776 | * @len: Length in bytes of the area to map. |
@@ -559,16 +780,19 @@ static int dma_region_free(struct ps3_dma_region* r) | |||
559 | * This is the common dma mapping routine. | 780 | * This is the common dma mapping routine. |
560 | */ | 781 | */ |
561 | 782 | ||
562 | static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | 783 | static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr, |
563 | unsigned long len, unsigned long *bus_addr) | 784 | unsigned long len, unsigned long *bus_addr, |
785 | u64 iopte_flag) | ||
564 | { | 786 | { |
565 | int result; | 787 | int result; |
566 | unsigned long flags; | 788 | unsigned long flags; |
567 | struct dma_chunk *c; | 789 | struct dma_chunk *c; |
568 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | 790 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) |
569 | : virt_addr; | 791 | : virt_addr; |
570 | 792 | unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size); | |
571 | *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | 793 | unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys, |
794 | 1 << r->page_size); | ||
795 | *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | ||
572 | 796 | ||
573 | if (!USE_DYNAMIC_DMA) { | 797 | if (!USE_DYNAMIC_DMA) { |
574 | unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr); | 798 | unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr); |
@@ -588,17 +812,18 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | |||
588 | c = dma_find_chunk(r, *bus_addr, len); | 812 | c = dma_find_chunk(r, *bus_addr, len); |
589 | 813 | ||
590 | if (c) { | 814 | if (c) { |
815 | DBG("%s:%d: reusing mapped chunk", __func__, __LINE__); | ||
816 | dma_dump_chunk(c); | ||
591 | c->usage_count++; | 817 | c->usage_count++; |
592 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | 818 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); |
593 | return 0; | 819 | return 0; |
594 | } | 820 | } |
595 | 821 | ||
596 | result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size), | 822 | result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag); |
597 | _ALIGN_UP(len, 1 << r->page_size), &c); | ||
598 | 823 | ||
599 | if (result) { | 824 | if (result) { |
600 | *bus_addr = 0; | 825 | *bus_addr = 0; |
601 | DBG("%s:%d: dma_map_pages failed (%d)\n", | 826 | DBG("%s:%d: dma_sb_map_pages failed (%d)\n", |
602 | __func__, __LINE__, result); | 827 | __func__, __LINE__, result); |
603 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | 828 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); |
604 | return result; | 829 | return result; |
@@ -610,8 +835,57 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | |||
610 | return result; | 835 | return result; |
611 | } | 836 | } |
612 | 837 | ||
838 | static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | ||
839 | unsigned long len, unsigned long *bus_addr, | ||
840 | u64 iopte_flag) | ||
841 | { | ||
842 | int result; | ||
843 | unsigned long flags; | ||
844 | struct dma_chunk *c; | ||
845 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | ||
846 | : virt_addr; | ||
847 | unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size); | ||
848 | unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys, | ||
849 | 1 << r->page_size); | ||
850 | |||
851 | DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__, | ||
852 | virt_addr, len); | ||
853 | DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__, | ||
854 | phys_addr, aligned_phys, aligned_len); | ||
855 | |||
856 | spin_lock_irqsave(&r->chunk_list.lock, flags); | ||
857 | c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len); | ||
858 | |||
859 | if (c) { | ||
860 | /* FIXME */ | ||
861 | BUG(); | ||
862 | *bus_addr = c->bus_addr + phys_addr - aligned_phys; | ||
863 | c->usage_count++; | ||
864 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c, | ||
869 | iopte_flag); | ||
870 | |||
871 | if (result) { | ||
872 | *bus_addr = 0; | ||
873 | DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n", | ||
874 | __func__, __LINE__, result); | ||
875 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
876 | return result; | ||
877 | } | ||
878 | *bus_addr = c->bus_addr + phys_addr - aligned_phys; | ||
879 | DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__, | ||
880 | virt_addr, phys_addr, aligned_phys, *bus_addr); | ||
881 | c->usage_count = 1; | ||
882 | |||
883 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
884 | return result; | ||
885 | } | ||
886 | |||
613 | /** | 887 | /** |
614 | * dma_unmap_area - Unmap an area of memory from a device dma region. | 888 | * dma_sb_unmap_area - Unmap an area of memory from a device dma region. |
615 | * @r: Pointer to a struct ps3_dma_region. | 889 | * @r: Pointer to a struct ps3_dma_region. |
616 | * @bus_addr: The starting ioc bus address of the area to unmap. | 890 | * @bus_addr: The starting ioc bus address of the area to unmap. |
617 | * @len: Length in bytes of the area to unmap. | 891 | * @len: Length in bytes of the area to unmap. |
@@ -619,7 +893,7 @@ static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, | |||
619 | * This is the common dma unmap routine. | 893 | * This is the common dma unmap routine. |
620 | */ | 894 | */ |
621 | 895 | ||
622 | int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, | 896 | static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, |
623 | unsigned long len) | 897 | unsigned long len) |
624 | { | 898 | { |
625 | unsigned long flags; | 899 | unsigned long flags; |
@@ -631,7 +905,8 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, | |||
631 | if (!c) { | 905 | if (!c) { |
632 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, | 906 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, |
633 | 1 << r->page_size); | 907 | 1 << r->page_size); |
634 | unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); | 908 | unsigned long aligned_len = _ALIGN_UP(len + bus_addr |
909 | - aligned_bus, 1 << r->page_size); | ||
635 | DBG("%s:%d: not found: bus_addr %lxh\n", | 910 | DBG("%s:%d: not found: bus_addr %lxh\n", |
636 | __func__, __LINE__, bus_addr); | 911 | __func__, __LINE__, bus_addr); |
637 | DBG("%s:%d: not found: len %lxh\n", | 912 | DBG("%s:%d: not found: len %lxh\n", |
@@ -647,94 +922,166 @@ int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, | |||
647 | 922 | ||
648 | if (!c->usage_count) { | 923 | if (!c->usage_count) { |
649 | list_del(&c->link); | 924 | list_del(&c->link); |
650 | dma_free_chunk(c); | 925 | dma_sb_free_chunk(c); |
651 | } | 926 | } |
652 | 927 | ||
653 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | 928 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); |
654 | return 0; | 929 | return 0; |
655 | } | 930 | } |
656 | 931 | ||
932 | static int dma_ioc0_unmap_area(struct ps3_dma_region *r, | ||
933 | unsigned long bus_addr, unsigned long len) | ||
934 | { | ||
935 | unsigned long flags; | ||
936 | struct dma_chunk *c; | ||
937 | |||
938 | DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len); | ||
939 | spin_lock_irqsave(&r->chunk_list.lock, flags); | ||
940 | c = dma_find_chunk(r, bus_addr, len); | ||
941 | |||
942 | if (!c) { | ||
943 | unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, | ||
944 | 1 << r->page_size); | ||
945 | unsigned long aligned_len = _ALIGN_UP(len + bus_addr | ||
946 | - aligned_bus, | ||
947 | 1 << r->page_size); | ||
948 | DBG("%s:%d: not found: bus_addr %lxh\n", | ||
949 | __func__, __LINE__, bus_addr); | ||
950 | DBG("%s:%d: not found: len %lxh\n", | ||
951 | __func__, __LINE__, len); | ||
952 | DBG("%s:%d: not found: aligned_bus %lxh\n", | ||
953 | __func__, __LINE__, aligned_bus); | ||
954 | DBG("%s:%d: not found: aligned_len %lxh\n", | ||
955 | __func__, __LINE__, aligned_len); | ||
956 | BUG(); | ||
957 | } | ||
958 | |||
959 | c->usage_count--; | ||
960 | |||
961 | if (!c->usage_count) { | ||
962 | list_del(&c->link); | ||
963 | dma_ioc0_free_chunk(c); | ||
964 | } | ||
965 | |||
966 | spin_unlock_irqrestore(&r->chunk_list.lock, flags); | ||
967 | DBG("%s: end\n", __func__); | ||
968 | return 0; | ||
969 | } | ||
970 | |||
657 | /** | 971 | /** |
658 | * dma_region_create_linear - Setup a linear dma maping for a device. | 972 | * dma_sb_region_create_linear - Setup a linear dma mapping for a device. |
659 | * @r: Pointer to a struct ps3_dma_region. | 973 | * @r: Pointer to a struct ps3_dma_region. |
660 | * | 974 | * |
661 | * This routine creates an HV dma region for the device and maps all available | 975 | * This routine creates an HV dma region for the device and maps all available |
662 | * ram into the io controller bus address space. | 976 | * ram into the io controller bus address space. |
663 | */ | 977 | */ |
664 | 978 | ||
665 | static int dma_region_create_linear(struct ps3_dma_region *r) | 979 | static int dma_sb_region_create_linear(struct ps3_dma_region *r) |
666 | { | 980 | { |
667 | int result; | 981 | int result; |
668 | unsigned long tmp; | 982 | unsigned long virt_addr, len, tmp; |
669 | 983 | ||
670 | /* force 16M dma pages for linear mapping */ | 984 | if (r->len > 16*1024*1024) { /* FIXME: need proper fix */ |
671 | 985 | /* force 16M dma pages for linear mapping */ | |
672 | if (r->page_size != PS3_DMA_16M) { | 986 | if (r->page_size != PS3_DMA_16M) { |
673 | pr_info("%s:%d: forcing 16M pages for linear map\n", | 987 | pr_info("%s:%d: forcing 16M pages for linear map\n", |
674 | __func__, __LINE__); | 988 | __func__, __LINE__); |
675 | r->page_size = PS3_DMA_16M; | 989 | r->page_size = PS3_DMA_16M; |
990 | r->len = _ALIGN_UP(r->len, 1 << r->page_size); | ||
991 | } | ||
676 | } | 992 | } |
677 | 993 | ||
678 | result = dma_region_create(r); | 994 | result = dma_sb_region_create(r); |
679 | BUG_ON(result); | 995 | BUG_ON(result); |
680 | 996 | ||
681 | result = dma_map_area(r, map.rm.base, map.rm.size, &tmp); | 997 | if (r->offset < map.rm.size) { |
682 | BUG_ON(result); | 998 | /* Map (part of) 1st RAM chunk */ |
683 | 999 | virt_addr = map.rm.base + r->offset; | |
684 | if (USE_LPAR_ADDR) | 1000 | len = map.rm.size - r->offset; |
685 | result = dma_map_area(r, map.r1.base, map.r1.size, | 1001 | if (len > r->len) |
686 | &tmp); | 1002 | len = r->len; |
687 | else | 1003 | result = dma_sb_map_area(r, virt_addr, len, &tmp, |
688 | result = dma_map_area(r, map.rm.size, map.r1.size, | 1004 | IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); |
689 | &tmp); | 1005 | BUG_ON(result); |
1006 | } | ||
690 | 1007 | ||
691 | BUG_ON(result); | 1008 | if (r->offset + r->len > map.rm.size) { |
1009 | /* Map (part of) 2nd RAM chunk */ | ||
1010 | virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; | ||
1011 | len = r->len; | ||
1012 | if (r->offset >= map.rm.size) | ||
1013 | virt_addr += r->offset - map.rm.size; | ||
1014 | else | ||
1015 | len -= map.rm.size - r->offset; | ||
1016 | result = dma_sb_map_area(r, virt_addr, len, &tmp, | ||
1017 | IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); | ||
1018 | BUG_ON(result); | ||
1019 | } | ||
692 | 1020 | ||
693 | return result; | 1021 | return result; |
694 | } | 1022 | } |
695 | 1023 | ||
696 | /** | 1024 | /** |
697 | * dma_region_free_linear - Free a linear dma mapping for a device. | 1025 | * dma_sb_region_free_linear - Free a linear dma mapping for a device. |
698 | * @r: Pointer to a struct ps3_dma_region. | 1026 | * @r: Pointer to a struct ps3_dma_region. |
699 | * | 1027 | * |
700 | * This routine will unmap all mapped areas and free the HV dma region. | 1028 | * This routine will unmap all mapped areas and free the HV dma region. |
701 | */ | 1029 | */ |
702 | 1030 | ||
703 | static int dma_region_free_linear(struct ps3_dma_region *r) | 1031 | static int dma_sb_region_free_linear(struct ps3_dma_region *r) |
704 | { | 1032 | { |
705 | int result; | 1033 | int result; |
1034 | unsigned long bus_addr, len, lpar_addr; | ||
1035 | |||
1036 | if (r->offset < map.rm.size) { | ||
1037 | /* Unmap (part of) 1st RAM chunk */ | ||
1038 | lpar_addr = map.rm.base + r->offset; | ||
1039 | len = map.rm.size - r->offset; | ||
1040 | if (len > r->len) | ||
1041 | len = r->len; | ||
1042 | bus_addr = dma_sb_lpar_to_bus(r, lpar_addr); | ||
1043 | result = dma_sb_unmap_area(r, bus_addr, len); | ||
1044 | BUG_ON(result); | ||
1045 | } | ||
706 | 1046 | ||
707 | result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size); | 1047 | if (r->offset + r->len > map.rm.size) { |
708 | BUG_ON(result); | 1048 | /* Unmap (part of) 2nd RAM chunk */ |
709 | 1049 | lpar_addr = map.r1.base; | |
710 | result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base), | 1050 | len = r->len; |
711 | map.r1.size); | 1051 | if (r->offset >= map.rm.size) |
712 | BUG_ON(result); | 1052 | lpar_addr += r->offset - map.rm.size; |
1053 | else | ||
1054 | len -= map.rm.size - r->offset; | ||
1055 | bus_addr = dma_sb_lpar_to_bus(r, lpar_addr); | ||
1056 | result = dma_sb_unmap_area(r, bus_addr, len); | ||
1057 | BUG_ON(result); | ||
1058 | } | ||
713 | 1059 | ||
714 | result = dma_region_free(r); | 1060 | result = dma_sb_region_free(r); |
715 | BUG_ON(result); | 1061 | BUG_ON(result); |
716 | 1062 | ||
717 | return result; | 1063 | return result; |
718 | } | 1064 | } |
719 | 1065 | ||
720 | /** | 1066 | /** |
721 | * dma_map_area_linear - Map an area of memory into a device dma region. | 1067 | * dma_sb_map_area_linear - Map an area of memory into a device dma region. |
722 | * @r: Pointer to a struct ps3_dma_region. | 1068 | * @r: Pointer to a struct ps3_dma_region. |
723 | * @virt_addr: Starting virtual address of the area to map. | 1069 | * @virt_addr: Starting virtual address of the area to map. |
724 | * @len: Length in bytes of the area to map. | 1070 | * @len: Length in bytes of the area to map. |
725 | * @bus_addr: A pointer to return the starting ioc bus address of the area to | 1071 | * @bus_addr: A pointer to return the starting ioc bus address of the area to |
726 | * map. | 1072 | * map. |
727 | * | 1073 | * |
728 | * This routine just returns the coresponding bus address. Actual mapping | 1074 | * This routine just returns the corresponding bus address. Actual mapping |
729 | * occurs in dma_region_create_linear(). | 1075 | * occurs in dma_region_create_linear(). |
730 | */ | 1076 | */ |
731 | 1077 | ||
732 | static int dma_map_area_linear(struct ps3_dma_region *r, | 1078 | static int dma_sb_map_area_linear(struct ps3_dma_region *r, |
733 | unsigned long virt_addr, unsigned long len, unsigned long *bus_addr) | 1079 | unsigned long virt_addr, unsigned long len, unsigned long *bus_addr, |
1080 | u64 iopte_flag) | ||
734 | { | 1081 | { |
735 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) | 1082 | unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) |
736 | : virt_addr; | 1083 | : virt_addr; |
737 | *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); | 1084 | *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); |
738 | return 0; | 1085 | return 0; |
739 | } | 1086 | } |
740 | 1087 | ||
@@ -744,42 +1091,98 @@ static int dma_map_area_linear(struct ps3_dma_region *r, | |||
744 | * @bus_addr: The starting ioc bus address of the area to unmap. | 1091 | * @bus_addr: The starting ioc bus address of the area to unmap. |
745 | * @len: Length in bytes of the area to unmap. | 1092 | * @len: Length in bytes of the area to unmap. |
746 | * | 1093 | * |
747 | * This routine does nothing. Unmapping occurs in dma_region_free_linear(). | 1094 | * This routine does nothing. Unmapping occurs in dma_sb_region_free_linear(). |
748 | */ | 1095 | */ |
749 | 1096 | ||
750 | static int dma_unmap_area_linear(struct ps3_dma_region *r, | 1097 | static int dma_sb_unmap_area_linear(struct ps3_dma_region *r, |
751 | unsigned long bus_addr, unsigned long len) | 1098 | unsigned long bus_addr, unsigned long len) |
752 | { | 1099 | { |
753 | return 0; | 1100 | return 0; |
1101 | }; | ||
1102 | |||
1103 | static const struct ps3_dma_region_ops ps3_dma_sb_region_ops = { | ||
1104 | .create = dma_sb_region_create, | ||
1105 | .free = dma_sb_region_free, | ||
1106 | .map = dma_sb_map_area, | ||
1107 | .unmap = dma_sb_unmap_area | ||
1108 | }; | ||
1109 | |||
1110 | static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = { | ||
1111 | .create = dma_sb_region_create_linear, | ||
1112 | .free = dma_sb_region_free_linear, | ||
1113 | .map = dma_sb_map_area_linear, | ||
1114 | .unmap = dma_sb_unmap_area_linear | ||
1115 | }; | ||
1116 | |||
1117 | static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = { | ||
1118 | .create = dma_ioc0_region_create, | ||
1119 | .free = dma_ioc0_region_free, | ||
1120 | .map = dma_ioc0_map_area, | ||
1121 | .unmap = dma_ioc0_unmap_area | ||
1122 | }; | ||
1123 | |||
1124 | int ps3_dma_region_init(struct ps3_system_bus_device *dev, | ||
1125 | struct ps3_dma_region *r, enum ps3_dma_page_size page_size, | ||
1126 | enum ps3_dma_region_type region_type, void *addr, unsigned long len) | ||
1127 | { | ||
1128 | unsigned long lpar_addr; | ||
1129 | |||
1130 | lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0; | ||
1131 | |||
1132 | r->dev = dev; | ||
1133 | r->page_size = page_size; | ||
1134 | r->region_type = region_type; | ||
1135 | r->offset = lpar_addr; | ||
1136 | if (r->offset >= map.rm.size) | ||
1137 | r->offset -= map.r1.offset; | ||
1138 | r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size); | ||
1139 | |||
1140 | switch (dev->dev_type) { | ||
1141 | case PS3_DEVICE_TYPE_SB: | ||
1142 | r->region_ops = (USE_DYNAMIC_DMA) | ||
1143 | ? &ps3_dma_sb_region_ops | ||
1144 | : &ps3_dma_sb_region_linear_ops; | ||
1145 | break; | ||
1146 | case PS3_DEVICE_TYPE_IOC0: | ||
1147 | r->region_ops = &ps3_dma_ioc0_region_ops; | ||
1148 | break; | ||
1149 | default: | ||
1150 | BUG(); | ||
1151 | return -EINVAL; | ||
1152 | } | ||
1153 | return 0; | ||
754 | } | 1154 | } |
1155 | EXPORT_SYMBOL(ps3_dma_region_init); | ||
755 | 1156 | ||
756 | int ps3_dma_region_create(struct ps3_dma_region *r) | 1157 | int ps3_dma_region_create(struct ps3_dma_region *r) |
757 | { | 1158 | { |
758 | return (USE_DYNAMIC_DMA) | 1159 | BUG_ON(!r); |
759 | ? dma_region_create(r) | 1160 | BUG_ON(!r->region_ops); |
760 | : dma_region_create_linear(r); | 1161 | BUG_ON(!r->region_ops->create); |
1162 | return r->region_ops->create(r); | ||
761 | } | 1163 | } |
1164 | EXPORT_SYMBOL(ps3_dma_region_create); | ||
762 | 1165 | ||
763 | int ps3_dma_region_free(struct ps3_dma_region *r) | 1166 | int ps3_dma_region_free(struct ps3_dma_region *r) |
764 | { | 1167 | { |
765 | return (USE_DYNAMIC_DMA) | 1168 | BUG_ON(!r); |
766 | ? dma_region_free(r) | 1169 | BUG_ON(!r->region_ops); |
767 | : dma_region_free_linear(r); | 1170 | BUG_ON(!r->region_ops->free); |
1171 | return r->region_ops->free(r); | ||
768 | } | 1172 | } |
1173 | EXPORT_SYMBOL(ps3_dma_region_free); | ||
769 | 1174 | ||
770 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, | 1175 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, |
771 | unsigned long len, unsigned long *bus_addr) | 1176 | unsigned long len, unsigned long *bus_addr, |
1177 | u64 iopte_flag) | ||
772 | { | 1178 | { |
773 | return (USE_DYNAMIC_DMA) | 1179 | return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag); |
774 | ? dma_map_area(r, virt_addr, len, bus_addr) | ||
775 | : dma_map_area_linear(r, virt_addr, len, bus_addr); | ||
776 | } | 1180 | } |
777 | 1181 | ||
778 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, | 1182 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, |
779 | unsigned long len) | 1183 | unsigned long len) |
780 | { | 1184 | { |
781 | return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len) | 1185 | return r->region_ops->unmap(r, bus_addr, len); |
782 | : dma_unmap_area_linear(r, bus_addr, len); | ||
783 | } | 1186 | } |
784 | 1187 | ||
785 | /*============================================================================*/ | 1188 | /*============================================================================*/ |
@@ -810,12 +1213,13 @@ void __init ps3_mm_init(void) | |||
810 | BUG_ON(map.rm.base); | 1213 | BUG_ON(map.rm.base); |
811 | BUG_ON(!map.rm.size); | 1214 | BUG_ON(!map.rm.size); |
812 | 1215 | ||
813 | lmb_add(map.rm.base, map.rm.size); | ||
814 | lmb_analyze(); | ||
815 | 1216 | ||
816 | /* arrange to do this in ps3_mm_add_memory */ | 1217 | /* arrange to do this in ps3_mm_add_memory */ |
817 | ps3_mm_region_create(&map.r1, map.total - map.rm.size); | 1218 | ps3_mm_region_create(&map.r1, map.total - map.rm.size); |
818 | 1219 | ||
1220 | /* correct map.total for the real total amount of memory we use */ | ||
1221 | map.total = map.rm.size + map.r1.size; | ||
1222 | |||
819 | DBG(" <- %s:%d\n", __func__, __LINE__); | 1223 | DBG(" <- %s:%d\n", __func__, __LINE__); |
820 | } | 1224 | } |
821 | 1225 | ||
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index 5c3da08bc0c4..b70e474014f0 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c | |||
@@ -133,7 +133,7 @@ struct saved_params { | |||
133 | } static saved_params; | 133 | } static saved_params; |
134 | 134 | ||
135 | #define dump_header(_a) _dump_header(_a, __func__, __LINE__) | 135 | #define dump_header(_a) _dump_header(_a, __func__, __LINE__) |
136 | static void _dump_header(const struct os_area_header __iomem *h, const char* func, | 136 | static void _dump_header(const struct os_area_header *h, const char *func, |
137 | int line) | 137 | int line) |
138 | { | 138 | { |
139 | pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, | 139 | pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, |
@@ -151,7 +151,7 @@ static void _dump_header(const struct os_area_header __iomem *h, const char* fun | |||
151 | } | 151 | } |
152 | 152 | ||
153 | #define dump_params(_a) _dump_params(_a, __func__, __LINE__) | 153 | #define dump_params(_a) _dump_params(_a, __func__, __LINE__) |
154 | static void _dump_params(const struct os_area_params __iomem *p, const char* func, | 154 | static void _dump_params(const struct os_area_params *p, const char *func, |
155 | int line) | 155 | int line) |
156 | { | 156 | { |
157 | pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag); | 157 | pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag); |
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index ca04f03305c7..87d52060fec0 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h | |||
@@ -41,6 +41,7 @@ void ps3_mm_shutdown(void); | |||
41 | /* irq */ | 41 | /* irq */ |
42 | 42 | ||
43 | void ps3_init_IRQ(void); | 43 | void ps3_init_IRQ(void); |
44 | void ps3_shutdown_IRQ(int cpu); | ||
44 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); | 45 | void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); |
45 | 46 | ||
46 | /* smp */ | 47 | /* smp */ |
@@ -82,6 +83,7 @@ enum ps3_dev_type { | |||
82 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ | 83 | PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ |
83 | PS3_DEV_TYPE_SB_GPIO = 6, | 84 | PS3_DEV_TYPE_SB_GPIO = 6, |
84 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ | 85 | PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ |
86 | PS3_DEV_TYPE_NOACCESS = 255, | ||
85 | }; | 87 | }; |
86 | 88 | ||
87 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | 89 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, |
@@ -129,24 +131,28 @@ int ps3_repository_read_dev_reg(unsigned int bus_index, | |||
129 | /* repository bus enumerators */ | 131 | /* repository bus enumerators */ |
130 | 132 | ||
131 | struct ps3_repository_device { | 133 | struct ps3_repository_device { |
134 | enum ps3_bus_type bus_type; | ||
132 | unsigned int bus_index; | 135 | unsigned int bus_index; |
136 | unsigned int bus_id; | ||
137 | enum ps3_dev_type dev_type; | ||
133 | unsigned int dev_index; | 138 | unsigned int dev_index; |
134 | struct ps3_device_id did; | 139 | unsigned int dev_id; |
135 | }; | 140 | }; |
136 | 141 | ||
137 | int ps3_repository_find_device(enum ps3_bus_type bus_type, | 142 | static inline struct ps3_repository_device *ps3_repository_bump_device( |
138 | enum ps3_dev_type dev_type, | 143 | struct ps3_repository_device *repo) |
139 | const struct ps3_repository_device *start_dev, | ||
140 | struct ps3_repository_device *dev); | ||
141 | static inline int ps3_repository_find_first_device( | ||
142 | enum ps3_bus_type bus_type, enum ps3_dev_type dev_type, | ||
143 | struct ps3_repository_device *dev) | ||
144 | { | 144 | { |
145 | return ps3_repository_find_device(bus_type, dev_type, NULL, dev); | 145 | repo->dev_index++; |
146 | return repo; | ||
146 | } | 147 | } |
147 | int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | 148 | int ps3_repository_find_device(struct ps3_repository_device *repo); |
149 | int ps3_repository_find_devices(enum ps3_bus_type bus_type, | ||
150 | int (*callback)(const struct ps3_repository_device *repo)); | ||
151 | int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, | ||
152 | unsigned int *bus_index); | ||
153 | int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, | ||
148 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id); | 154 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id); |
149 | int ps3_repository_find_reg(const struct ps3_repository_device *dev, | 155 | int ps3_repository_find_reg(const struct ps3_repository_device *repo, |
150 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len); | 156 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len); |
151 | 157 | ||
152 | /* repository block device info */ | 158 | /* repository block device info */ |
@@ -216,4 +222,19 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id); | |||
216 | int ps3_repository_read_spu_resource_id(unsigned int res_index, | 222 | int ps3_repository_read_spu_resource_id(unsigned int res_index, |
217 | enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); | 223 | enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); |
218 | 224 | ||
225 | /* repository vuart info */ | ||
226 | |||
227 | int ps3_repository_read_vuart_av_port(unsigned int *port); | ||
228 | int ps3_repository_read_vuart_sysmgr_port(unsigned int *port); | ||
229 | |||
230 | /* Page table entries */ | ||
231 | #define IOPTE_PP_W 0x8000000000000000ul /* protection: write */ | ||
232 | #define IOPTE_PP_R 0x4000000000000000ul /* protection: read */ | ||
233 | #define IOPTE_M 0x2000000000000000ul /* coherency required */ | ||
234 | #define IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */ | ||
235 | #define IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */ | ||
236 | #define IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */ | ||
237 | #define IOPTE_H 0x0000000000000800ul /* cache hint */ | ||
238 | #define IOPTE_IOID_Mask 0x00000000000007fful /* ioid */ | ||
239 | |||
219 | #endif | 240 | #endif |
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index ae586a0e5d3f..8cc37cfea0f2 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c | |||
@@ -138,7 +138,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, | |||
138 | pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", | 138 | pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", |
139 | __func__, __LINE__, ps3_result(result)); | 139 | __func__, __LINE__, ps3_result(result)); |
140 | dump_node_name(lpar_id, n1, n2, n3, n4); | 140 | dump_node_name(lpar_id, n1, n2, n3, n4); |
141 | return result; | 141 | return -ENOENT; |
142 | } | 142 | } |
143 | 143 | ||
144 | dump_node(lpar_id, n1, n2, n3, n4, v1, v2); | 144 | dump_node(lpar_id, n1, n2, n3, n4, v1, v2); |
@@ -155,7 +155,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, | |||
155 | pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n", | 155 | pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n", |
156 | __func__, __LINE__, v2); | 156 | __func__, __LINE__, v2); |
157 | 157 | ||
158 | return result; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
161 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, | 161 | int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, |
@@ -314,324 +314,140 @@ int ps3_repository_read_dev_reg(unsigned int bus_index, | |||
314 | reg_index, bus_addr, len); | 314 | reg_index, bus_addr, len); |
315 | } | 315 | } |
316 | 316 | ||
317 | #if defined(DEBUG) | ||
318 | int ps3_repository_dump_resource_info(unsigned int bus_index, | ||
319 | unsigned int dev_index) | ||
320 | { | ||
321 | int result = 0; | ||
322 | unsigned int res_index; | ||
323 | 317 | ||
324 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
325 | bus_index, dev_index); | ||
326 | 318 | ||
327 | for (res_index = 0; res_index < 10; res_index++) { | 319 | int ps3_repository_find_device(struct ps3_repository_device *repo) |
328 | enum ps3_interrupt_type intr_type; | 320 | { |
329 | unsigned int interrupt_id; | 321 | int result; |
322 | struct ps3_repository_device tmp = *repo; | ||
323 | unsigned int num_dev; | ||
330 | 324 | ||
331 | result = ps3_repository_read_dev_intr(bus_index, dev_index, | 325 | BUG_ON(repo->bus_index > 10); |
332 | res_index, &intr_type, &interrupt_id); | 326 | BUG_ON(repo->dev_index > 10); |
333 | 327 | ||
334 | if (result) { | 328 | result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); |
335 | if (result != LV1_NO_ENTRY) | ||
336 | pr_debug("%s:%d ps3_repository_read_dev_intr" | ||
337 | " (%u:%u) failed\n", __func__, __LINE__, | ||
338 | bus_index, dev_index); | ||
339 | break; | ||
340 | } | ||
341 | 329 | ||
342 | pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", | 330 | if (result) { |
343 | __func__, __LINE__, bus_index, dev_index, intr_type, | 331 | pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); |
344 | interrupt_id); | 332 | return result; |
345 | } | 333 | } |
346 | 334 | ||
347 | for (res_index = 0; res_index < 10; res_index++) { | 335 | pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n", |
348 | enum ps3_reg_type reg_type; | 336 | __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, |
349 | u64 bus_addr; | 337 | num_dev); |
350 | u64 len; | ||
351 | |||
352 | result = ps3_repository_read_dev_reg(bus_index, dev_index, | ||
353 | res_index, ®_type, &bus_addr, &len); | ||
354 | 338 | ||
355 | if (result) { | 339 | if (tmp.dev_index >= num_dev) { |
356 | if (result != LV1_NO_ENTRY) | 340 | pr_debug("%s:%d: no device found\n", __func__, __LINE__); |
357 | pr_debug("%s:%d ps3_repository_read_dev_reg" | 341 | return -ENODEV; |
358 | " (%u:%u) failed\n", __func__, __LINE__, | ||
359 | bus_index, dev_index); | ||
360 | break; | ||
361 | } | ||
362 | |||
363 | pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", | ||
364 | __func__, __LINE__, bus_index, dev_index, reg_type, | ||
365 | bus_addr, len); | ||
366 | } | 342 | } |
367 | 343 | ||
368 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 344 | result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, |
369 | return result; | 345 | &tmp.dev_type); |
370 | } | ||
371 | |||
372 | static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index) | ||
373 | { | ||
374 | int result = 0; | ||
375 | unsigned int num_regions, region_index; | ||
376 | u64 port, blk_size, num_blocks; | ||
377 | |||
378 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
379 | bus_index, dev_index); | ||
380 | 346 | ||
381 | result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port, | ||
382 | &blk_size, &num_blocks, &num_regions); | ||
383 | if (result) { | 347 | if (result) { |
384 | pr_debug("%s:%d ps3_repository_read_stor_dev_info" | 348 | pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__); |
385 | " (%u:%u) failed\n", __func__, __LINE__, | 349 | return result; |
386 | bus_index, dev_index); | ||
387 | goto out; | ||
388 | } | 350 | } |
389 | 351 | ||
390 | pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " | 352 | result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, |
391 | "%lu, num_regions %u\n", | 353 | &tmp.dev_id); |
392 | __func__, __LINE__, bus_index, dev_index, port, | ||
393 | blk_size, num_blocks, num_regions); | ||
394 | |||
395 | for (region_index = 0; region_index < num_regions; region_index++) { | ||
396 | unsigned int region_id; | ||
397 | u64 region_start, region_size; | ||
398 | |||
399 | result = ps3_repository_read_stor_dev_region(bus_index, | ||
400 | dev_index, region_index, ®ion_id, ®ion_start, | ||
401 | ®ion_size); | ||
402 | if (result) { | ||
403 | pr_debug("%s:%d ps3_repository_read_stor_dev_region" | ||
404 | " (%u:%u) failed\n", __func__, __LINE__, | ||
405 | bus_index, dev_index); | ||
406 | break; | ||
407 | } | ||
408 | 354 | ||
409 | pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", | 355 | if (result) { |
410 | __func__, __LINE__, bus_index, dev_index, region_id, | 356 | pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, |
411 | region_start, region_size); | 357 | __LINE__); |
358 | return result; | ||
412 | } | 359 | } |
413 | 360 | ||
414 | out: | 361 | pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n", |
415 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 362 | __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); |
416 | return result; | ||
417 | } | ||
418 | |||
419 | static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type, | ||
420 | unsigned int num_dev) | ||
421 | { | ||
422 | int result = 0; | ||
423 | unsigned int dev_index; | ||
424 | |||
425 | pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index); | ||
426 | |||
427 | for (dev_index = 0; dev_index < num_dev; dev_index++) { | ||
428 | enum ps3_dev_type dev_type; | ||
429 | unsigned int dev_id; | ||
430 | |||
431 | result = ps3_repository_read_dev_type(bus_index, dev_index, | ||
432 | &dev_type); | ||
433 | |||
434 | if (result) { | ||
435 | pr_debug("%s:%d ps3_repository_read_dev_type" | ||
436 | " (%u:%u) failed\n", __func__, __LINE__, | ||
437 | bus_index, dev_index); | ||
438 | break; | ||
439 | } | ||
440 | |||
441 | result = ps3_repository_read_dev_id(bus_index, dev_index, | ||
442 | &dev_id); | ||
443 | |||
444 | if (result) { | ||
445 | pr_debug("%s:%d ps3_repository_read_dev_id" | ||
446 | " (%u:%u) failed\n", __func__, __LINE__, | ||
447 | bus_index, dev_index); | ||
448 | continue; | ||
449 | } | ||
450 | 363 | ||
451 | pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, | 364 | *repo = tmp; |
452 | __LINE__, bus_index, dev_index, dev_type, dev_id); | 365 | return 0; |
453 | |||
454 | ps3_repository_dump_resource_info(bus_index, dev_index); | ||
455 | |||
456 | if (bus_type == PS3_BUS_TYPE_STORAGE) | ||
457 | dump_stor_dev_info(bus_index, dev_index); | ||
458 | } | ||
459 | |||
460 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
461 | return result; | ||
462 | } | 366 | } |
463 | 367 | ||
464 | int ps3_repository_dump_bus_info(void) | 368 | int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, |
369 | int (*callback)(const struct ps3_repository_device *repo)) | ||
465 | { | 370 | { |
466 | int result = 0; | 371 | int result = 0; |
467 | unsigned int bus_index; | 372 | struct ps3_repository_device repo; |
468 | 373 | ||
469 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | 374 | pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); |
470 | 375 | ||
471 | for (bus_index = 0; bus_index < 10; bus_index++) { | 376 | for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { |
472 | enum ps3_bus_type bus_type; | ||
473 | unsigned int bus_id; | ||
474 | unsigned int num_dev; | ||
475 | 377 | ||
476 | result = ps3_repository_read_bus_type(bus_index, &bus_type); | 378 | result = ps3_repository_read_bus_type(repo.bus_index, |
379 | &repo.bus_type); | ||
477 | 380 | ||
478 | if (result) { | 381 | if (result) { |
479 | pr_debug("%s:%d read_bus_type(%u) failed\n", | 382 | pr_debug("%s:%d read_bus_type(%u) failed\n", |
480 | __func__, __LINE__, bus_index); | 383 | __func__, __LINE__, repo.bus_index); |
481 | break; | 384 | break; |
482 | } | 385 | } |
483 | 386 | ||
484 | result = ps3_repository_read_bus_id(bus_index, &bus_id); | 387 | if (repo.bus_type != bus_type) { |
485 | 388 | pr_debug("%s:%d: skip, bus_type %u\n", __func__, | |
486 | if (result) { | 389 | __LINE__, repo.bus_type); |
487 | pr_debug("%s:%d read_bus_id(%u) failed\n", | ||
488 | __func__, __LINE__, bus_index); | ||
489 | continue; | 390 | continue; |
490 | } | 391 | } |
491 | 392 | ||
492 | if (bus_index != bus_id) | 393 | result = ps3_repository_read_bus_id(repo.bus_index, |
493 | pr_debug("%s:%d bus_index != bus_id\n", | 394 | &repo.bus_id); |
494 | __func__, __LINE__); | ||
495 | |||
496 | result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); | ||
497 | 395 | ||
498 | if (result) { | 396 | if (result) { |
499 | pr_debug("%s:%d read_bus_num_dev(%u) failed\n", | 397 | pr_debug("%s:%d read_bus_id(%u) failed\n", |
500 | __func__, __LINE__, bus_index); | 398 | __func__, __LINE__, repo.bus_index); |
501 | continue; | 399 | continue; |
502 | } | 400 | } |
503 | 401 | ||
504 | pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", | 402 | for (repo.dev_index = 0; ; repo.dev_index++) { |
505 | __func__, __LINE__, bus_index, bus_type, bus_id, | 403 | result = ps3_repository_find_device(&repo); |
506 | num_dev); | ||
507 | 404 | ||
508 | dump_device_info(bus_index, bus_type, num_dev); | 405 | if (result == -ENODEV) { |
509 | } | 406 | result = 0; |
407 | break; | ||
408 | } else if (result) | ||
409 | break; | ||
510 | 410 | ||
511 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 411 | result = callback(&repo); |
512 | return result; | ||
513 | } | ||
514 | #endif /* defined(DEBUG) */ | ||
515 | |||
516 | static int find_device(unsigned int bus_index, unsigned int num_dev, | ||
517 | unsigned int start_dev_index, enum ps3_dev_type dev_type, | ||
518 | struct ps3_repository_device *dev) | ||
519 | { | ||
520 | int result = 0; | ||
521 | unsigned int dev_index; | ||
522 | 412 | ||
523 | pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type); | 413 | if (result) { |
524 | 414 | pr_debug("%s:%d: abort at callback\n", __func__, | |
525 | dev->dev_index = UINT_MAX; | 415 | __LINE__); |
526 | 416 | break; | |
527 | for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) { | 417 | } |
528 | enum ps3_dev_type x; | ||
529 | |||
530 | result = ps3_repository_read_dev_type(bus_index, dev_index, | ||
531 | &x); | ||
532 | |||
533 | if (result) { | ||
534 | pr_debug("%s:%d read_dev_type failed\n", | ||
535 | __func__, __LINE__); | ||
536 | return result; | ||
537 | } | 418 | } |
538 | 419 | break; | |
539 | if (x == dev_type) | ||
540 | break; | ||
541 | } | ||
542 | |||
543 | if (dev_index == num_dev) | ||
544 | return -1; | ||
545 | |||
546 | pr_debug("%s:%d: found dev_type %u at dev_index %u\n", | ||
547 | __func__, __LINE__, dev_type, dev_index); | ||
548 | |||
549 | result = ps3_repository_read_dev_id(bus_index, dev_index, | ||
550 | &dev->did.dev_id); | ||
551 | |||
552 | if (result) { | ||
553 | pr_debug("%s:%d read_dev_id failed\n", | ||
554 | __func__, __LINE__); | ||
555 | return result; | ||
556 | } | 420 | } |
557 | 421 | ||
558 | dev->dev_index = dev_index; | 422 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
559 | |||
560 | pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__, | ||
561 | dev->did.dev_id); | ||
562 | |||
563 | return result; | 423 | return result; |
564 | } | 424 | } |
565 | 425 | ||
566 | int ps3_repository_find_device (enum ps3_bus_type bus_type, | 426 | int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, |
567 | enum ps3_dev_type dev_type, | 427 | unsigned int *bus_index) |
568 | const struct ps3_repository_device *start_dev, | ||
569 | struct ps3_repository_device *dev) | ||
570 | { | 428 | { |
571 | int result = 0; | 429 | unsigned int i; |
572 | unsigned int bus_index; | 430 | enum ps3_bus_type type; |
573 | unsigned int num_dev; | 431 | int error; |
574 | |||
575 | pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__, | ||
576 | bus_type, dev_type); | ||
577 | |||
578 | BUG_ON(start_dev && start_dev->bus_index > 10); | ||
579 | |||
580 | for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10; | ||
581 | bus_index++) { | ||
582 | enum ps3_bus_type x; | ||
583 | |||
584 | result = ps3_repository_read_bus_type(bus_index, &x); | ||
585 | 432 | ||
586 | if (result) { | 433 | for (i = from; i < 10; i++) { |
434 | error = ps3_repository_read_bus_type(i, &type); | ||
435 | if (error) { | ||
587 | pr_debug("%s:%d read_bus_type failed\n", | 436 | pr_debug("%s:%d read_bus_type failed\n", |
588 | __func__, __LINE__); | 437 | __func__, __LINE__); |
589 | dev->bus_index = UINT_MAX; | 438 | *bus_index = UINT_MAX; |
590 | return result; | 439 | return error; |
440 | } | ||
441 | if (type == bus_type) { | ||
442 | *bus_index = i; | ||
443 | return 0; | ||
591 | } | 444 | } |
592 | if (x == bus_type) | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | if (bus_index >= 10) | ||
597 | return -ENODEV; | ||
598 | |||
599 | pr_debug("%s:%d: found bus_type %u at bus_index %u\n", | ||
600 | __func__, __LINE__, bus_type, bus_index); | ||
601 | |||
602 | result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); | ||
603 | |||
604 | if (result) { | ||
605 | pr_debug("%s:%d read_bus_num_dev failed\n", | ||
606 | __func__, __LINE__); | ||
607 | return result; | ||
608 | } | ||
609 | |||
610 | result = find_device(bus_index, num_dev, start_dev | ||
611 | ? start_dev->dev_index + 1 : 0, dev_type, dev); | ||
612 | |||
613 | if (result) { | ||
614 | pr_debug("%s:%d get_did failed\n", __func__, __LINE__); | ||
615 | return result; | ||
616 | } | ||
617 | |||
618 | result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id); | ||
619 | |||
620 | if (result) { | ||
621 | pr_debug("%s:%d read_bus_id failed\n", | ||
622 | __func__, __LINE__); | ||
623 | return result; | ||
624 | } | 445 | } |
625 | 446 | *bus_index = UINT_MAX; | |
626 | dev->bus_index = bus_index; | 447 | return -ENODEV; |
627 | |||
628 | pr_debug("%s:%d found: bus_id %u, dev_id %u\n", | ||
629 | __func__, __LINE__, dev->did.bus_id, dev->did.dev_id); | ||
630 | |||
631 | return result; | ||
632 | } | 448 | } |
633 | 449 | ||
634 | int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | 450 | int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, |
635 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) | 451 | enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) |
636 | { | 452 | { |
637 | int result = 0; | 453 | int result = 0; |
@@ -645,8 +461,8 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | |||
645 | enum ps3_interrupt_type t; | 461 | enum ps3_interrupt_type t; |
646 | unsigned int id; | 462 | unsigned int id; |
647 | 463 | ||
648 | result = ps3_repository_read_dev_intr(dev->bus_index, | 464 | result = ps3_repository_read_dev_intr(repo->bus_index, |
649 | dev->dev_index, res_index, &t, &id); | 465 | repo->dev_index, res_index, &t, &id); |
650 | 466 | ||
651 | if (result) { | 467 | if (result) { |
652 | pr_debug("%s:%d read_dev_intr failed\n", | 468 | pr_debug("%s:%d read_dev_intr failed\n", |
@@ -669,7 +485,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, | |||
669 | return result; | 485 | return result; |
670 | } | 486 | } |
671 | 487 | ||
672 | int ps3_repository_find_reg(const struct ps3_repository_device *dev, | 488 | int ps3_repository_find_reg(const struct ps3_repository_device *repo, |
673 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) | 489 | enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) |
674 | { | 490 | { |
675 | int result = 0; | 491 | int result = 0; |
@@ -684,8 +500,8 @@ int ps3_repository_find_reg(const struct ps3_repository_device *dev, | |||
684 | u64 a; | 500 | u64 a; |
685 | u64 l; | 501 | u64 l; |
686 | 502 | ||
687 | result = ps3_repository_read_dev_reg(dev->bus_index, | 503 | result = ps3_repository_read_dev_reg(repo->bus_index, |
688 | dev->dev_index, res_index, &t, &a, &l); | 504 | repo->dev_index, res_index, &t, &a, &l); |
689 | 505 | ||
690 | if (result) { | 506 | if (result) { |
691 | pr_debug("%s:%d read_dev_reg failed\n", | 507 | pr_debug("%s:%d read_dev_reg failed\n", |
@@ -965,6 +781,36 @@ int ps3_repository_read_boot_dat_size(unsigned int *size) | |||
965 | return result; | 781 | return result; |
966 | } | 782 | } |
967 | 783 | ||
784 | int ps3_repository_read_vuart_av_port(unsigned int *port) | ||
785 | { | ||
786 | int result; | ||
787 | u64 v1; | ||
788 | |||
789 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
790 | make_first_field("bi", 0), | ||
791 | make_field("vir_uart", 0), | ||
792 | make_field("port", 0), | ||
793 | make_field("avset", 0), | ||
794 | &v1, 0); | ||
795 | *port = v1; | ||
796 | return result; | ||
797 | } | ||
798 | |||
799 | int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) | ||
800 | { | ||
801 | int result; | ||
802 | u64 v1; | ||
803 | |||
804 | result = read_node(PS3_LPAR_ID_CURRENT, | ||
805 | make_first_field("bi", 0), | ||
806 | make_field("vir_uart", 0), | ||
807 | make_field("port", 0), | ||
808 | make_field("sysmgr", 0), | ||
809 | &v1, 0); | ||
810 | *port = v1; | ||
811 | return result; | ||
812 | } | ||
813 | |||
968 | /** | 814 | /** |
969 | * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. | 815 | * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. |
970 | * address: lpar address of cell_ext_os_area | 816 | * address: lpar address of cell_ext_os_area |
@@ -1026,3 +872,205 @@ int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) | |||
1026 | return result ? result | 872 | return result ? result |
1027 | : ps3_repository_read_tb_freq(node_id, tb_freq); | 873 | : ps3_repository_read_tb_freq(node_id, tb_freq); |
1028 | } | 874 | } |
875 | |||
876 | #if defined(DEBUG) | ||
877 | |||
878 | int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) | ||
879 | { | ||
880 | int result = 0; | ||
881 | unsigned int res_index; | ||
882 | |||
883 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
884 | repo->bus_index, repo->dev_index); | ||
885 | |||
886 | for (res_index = 0; res_index < 10; res_index++) { | ||
887 | enum ps3_interrupt_type intr_type; | ||
888 | unsigned int interrupt_id; | ||
889 | |||
890 | result = ps3_repository_read_dev_intr(repo->bus_index, | ||
891 | repo->dev_index, res_index, &intr_type, &interrupt_id); | ||
892 | |||
893 | if (result) { | ||
894 | if (result != LV1_NO_ENTRY) | ||
895 | pr_debug("%s:%d ps3_repository_read_dev_intr" | ||
896 | " (%u:%u) failed\n", __func__, __LINE__, | ||
897 | repo->bus_index, repo->dev_index); | ||
898 | break; | ||
899 | } | ||
900 | |||
901 | pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", | ||
902 | __func__, __LINE__, repo->bus_index, repo->dev_index, | ||
903 | intr_type, interrupt_id); | ||
904 | } | ||
905 | |||
906 | for (res_index = 0; res_index < 10; res_index++) { | ||
907 | enum ps3_reg_type reg_type; | ||
908 | u64 bus_addr; | ||
909 | u64 len; | ||
910 | |||
911 | result = ps3_repository_read_dev_reg(repo->bus_index, | ||
912 | repo->dev_index, res_index, ®_type, &bus_addr, &len); | ||
913 | |||
914 | if (result) { | ||
915 | if (result != LV1_NO_ENTRY) | ||
916 | pr_debug("%s:%d ps3_repository_read_dev_reg" | ||
917 | " (%u:%u) failed\n", __func__, __LINE__, | ||
918 | repo->bus_index, repo->dev_index); | ||
919 | break; | ||
920 | } | ||
921 | |||
922 | pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", | ||
923 | __func__, __LINE__, repo->bus_index, repo->dev_index, | ||
924 | reg_type, bus_addr, len); | ||
925 | } | ||
926 | |||
927 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
928 | return result; | ||
929 | } | ||
930 | |||
931 | static int dump_stor_dev_info(struct ps3_repository_device *repo) | ||
932 | { | ||
933 | int result = 0; | ||
934 | unsigned int num_regions, region_index; | ||
935 | u64 port, blk_size, num_blocks; | ||
936 | |||
937 | pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, | ||
938 | repo->bus_index, repo->dev_index); | ||
939 | |||
940 | result = ps3_repository_read_stor_dev_info(repo->bus_index, | ||
941 | repo->dev_index, &port, &blk_size, &num_blocks, &num_regions); | ||
942 | if (result) { | ||
943 | pr_debug("%s:%d ps3_repository_read_stor_dev_info" | ||
944 | " (%u:%u) failed\n", __func__, __LINE__, | ||
945 | repo->bus_index, repo->dev_index); | ||
946 | goto out; | ||
947 | } | ||
948 | |||
949 | pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " | ||
950 | "%lu, num_regions %u\n", | ||
951 | __func__, __LINE__, repo->bus_index, repo->dev_index, port, | ||
952 | blk_size, num_blocks, num_regions); | ||
953 | |||
954 | for (region_index = 0; region_index < num_regions; region_index++) { | ||
955 | unsigned int region_id; | ||
956 | u64 region_start, region_size; | ||
957 | |||
958 | result = ps3_repository_read_stor_dev_region(repo->bus_index, | ||
959 | repo->dev_index, region_index, ®ion_id, | ||
960 | ®ion_start, ®ion_size); | ||
961 | if (result) { | ||
962 | pr_debug("%s:%d ps3_repository_read_stor_dev_region" | ||
963 | " (%u:%u) failed\n", __func__, __LINE__, | ||
964 | repo->bus_index, repo->dev_index); | ||
965 | break; | ||
966 | } | ||
967 | |||
968 | pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", | ||
969 | __func__, __LINE__, repo->bus_index, repo->dev_index, | ||
970 | region_id, region_start, region_size); | ||
971 | } | ||
972 | |||
973 | out: | ||
974 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
975 | return result; | ||
976 | } | ||
977 | |||
978 | static int dump_device_info(struct ps3_repository_device *repo, | ||
979 | unsigned int num_dev) | ||
980 | { | ||
981 | int result = 0; | ||
982 | |||
983 | pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); | ||
984 | |||
985 | for (repo->dev_index = 0; repo->dev_index < num_dev; | ||
986 | repo->dev_index++) { | ||
987 | |||
988 | result = ps3_repository_read_dev_type(repo->bus_index, | ||
989 | repo->dev_index, &repo->dev_type); | ||
990 | |||
991 | if (result) { | ||
992 | pr_debug("%s:%d ps3_repository_read_dev_type" | ||
993 | " (%u:%u) failed\n", __func__, __LINE__, | ||
994 | repo->bus_index, repo->dev_index); | ||
995 | break; | ||
996 | } | ||
997 | |||
998 | result = ps3_repository_read_dev_id(repo->bus_index, | ||
999 | repo->dev_index, &repo->dev_id); | ||
1000 | |||
1001 | if (result) { | ||
1002 | pr_debug("%s:%d ps3_repository_read_dev_id" | ||
1003 | " (%u:%u) failed\n", __func__, __LINE__, | ||
1004 | repo->bus_index, repo->dev_index); | ||
1005 | continue; | ||
1006 | } | ||
1007 | |||
1008 | pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, | ||
1009 | __LINE__, repo->bus_index, repo->dev_index, | ||
1010 | repo->dev_type, repo->dev_id); | ||
1011 | |||
1012 | ps3_repository_dump_resource_info(repo); | ||
1013 | |||
1014 | if (repo->bus_type == PS3_BUS_TYPE_STORAGE) | ||
1015 | dump_stor_dev_info(repo); | ||
1016 | } | ||
1017 | |||
1018 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
1019 | return result; | ||
1020 | } | ||
1021 | |||
1022 | int ps3_repository_dump_bus_info(void) | ||
1023 | { | ||
1024 | int result = 0; | ||
1025 | struct ps3_repository_device repo; | ||
1026 | |||
1027 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
1028 | |||
1029 | memset(&repo, 0, sizeof(repo)); | ||
1030 | |||
1031 | for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { | ||
1032 | unsigned int num_dev; | ||
1033 | |||
1034 | result = ps3_repository_read_bus_type(repo.bus_index, | ||
1035 | &repo.bus_type); | ||
1036 | |||
1037 | if (result) { | ||
1038 | pr_debug("%s:%d read_bus_type(%u) failed\n", | ||
1039 | __func__, __LINE__, repo.bus_index); | ||
1040 | break; | ||
1041 | } | ||
1042 | |||
1043 | result = ps3_repository_read_bus_id(repo.bus_index, | ||
1044 | &repo.bus_id); | ||
1045 | |||
1046 | if (result) { | ||
1047 | pr_debug("%s:%d read_bus_id(%u) failed\n", | ||
1048 | __func__, __LINE__, repo.bus_index); | ||
1049 | continue; | ||
1050 | } | ||
1051 | |||
1052 | if (repo.bus_index != repo.bus_id) | ||
1053 | pr_debug("%s:%d bus_index != bus_id\n", | ||
1054 | __func__, __LINE__); | ||
1055 | |||
1056 | result = ps3_repository_read_bus_num_dev(repo.bus_index, | ||
1057 | &num_dev); | ||
1058 | |||
1059 | if (result) { | ||
1060 | pr_debug("%s:%d read_bus_num_dev(%u) failed\n", | ||
1061 | __func__, __LINE__, repo.bus_index); | ||
1062 | continue; | ||
1063 | } | ||
1064 | |||
1065 | pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", | ||
1066 | __func__, __LINE__, repo.bus_index, repo.bus_type, | ||
1067 | repo.bus_id, num_dev); | ||
1068 | |||
1069 | dump_device_info(&repo, num_dev); | ||
1070 | } | ||
1071 | |||
1072 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
1073 | return result; | ||
1074 | } | ||
1075 | |||
1076 | #endif /* defined(DEBUG) */ | ||
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 935396766621..aa05288de64e 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c | |||
@@ -37,27 +37,35 @@ | |||
37 | #include "platform.h" | 37 | #include "platform.h" |
38 | 38 | ||
39 | #if defined(DEBUG) | 39 | #if defined(DEBUG) |
40 | #define DBG(fmt...) udbg_printf(fmt) | 40 | #define DBG udbg_printf |
41 | #else | 41 | #else |
42 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 42 | #define DBG pr_debug |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | #if !defined(CONFIG_SMP) | 45 | #if !defined(CONFIG_SMP) |
46 | static void smp_send_stop(void) {} | 46 | static void smp_send_stop(void) {} |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | int ps3_get_firmware_version(union ps3_firmware_version *v) | 49 | static union ps3_firmware_version ps3_firmware_version; |
50 | |||
51 | void ps3_get_firmware_version(union ps3_firmware_version *v) | ||
50 | { | 52 | { |
51 | int result = lv1_get_version_info(&v->raw); | 53 | *v = ps3_firmware_version; |
54 | } | ||
55 | EXPORT_SYMBOL_GPL(ps3_get_firmware_version); | ||
52 | 56 | ||
53 | if (result) { | 57 | int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev) |
54 | v->raw = 0; | 58 | { |
55 | return -1; | 59 | union ps3_firmware_version x; |
56 | } | 60 | |
61 | x.pad = 0; | ||
62 | x.major = major; | ||
63 | x.minor = minor; | ||
64 | x.rev = rev; | ||
57 | 65 | ||
58 | return result; | 66 | return (ps3_firmware_version.raw - x.raw); |
59 | } | 67 | } |
60 | EXPORT_SYMBOL_GPL(ps3_get_firmware_version); | 68 | EXPORT_SYMBOL_GPL(ps3_compare_firmware_version); |
61 | 69 | ||
62 | static void ps3_power_save(void) | 70 | static void ps3_power_save(void) |
63 | { | 71 | { |
@@ -99,7 +107,8 @@ static void ps3_panic(char *str) | |||
99 | while(1); | 107 | while(1); |
100 | } | 108 | } |
101 | 109 | ||
102 | #ifdef CONFIG_FB_PS3 | 110 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \ |
111 | defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) | ||
103 | static void prealloc(struct ps3_prealloc *p) | 112 | static void prealloc(struct ps3_prealloc *p) |
104 | { | 113 | { |
105 | if (!p->size) | 114 | if (!p->size) |
@@ -115,12 +124,15 @@ static void prealloc(struct ps3_prealloc *p) | |||
115 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, | 124 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, |
116 | p->address); | 125 | p->address); |
117 | } | 126 | } |
127 | #endif | ||
118 | 128 | ||
129 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) | ||
119 | struct ps3_prealloc ps3fb_videomemory = { | 130 | struct ps3_prealloc ps3fb_videomemory = { |
120 | .name = "ps3fb videomemory", | 131 | .name = "ps3fb videomemory", |
121 | .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, | 132 | .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, |
122 | .align = 1024*1024 /* the GPU requires 1 MiB alignment */ | 133 | .align = 1024*1024 /* the GPU requires 1 MiB alignment */ |
123 | }; | 134 | }; |
135 | EXPORT_SYMBOL_GPL(ps3fb_videomemory); | ||
124 | #define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory) | 136 | #define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory) |
125 | 137 | ||
126 | static int __init early_parse_ps3fb(char *p) | 138 | static int __init early_parse_ps3fb(char *p) |
@@ -137,6 +149,30 @@ early_param("ps3fb", early_parse_ps3fb); | |||
137 | #define prealloc_ps3fb_videomemory() do { } while (0) | 149 | #define prealloc_ps3fb_videomemory() do { } while (0) |
138 | #endif | 150 | #endif |
139 | 151 | ||
152 | #if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) | ||
153 | struct ps3_prealloc ps3flash_bounce_buffer = { | ||
154 | .name = "ps3flash bounce buffer", | ||
155 | .size = 256*1024, | ||
156 | .align = 256*1024 | ||
157 | }; | ||
158 | EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer); | ||
159 | #define prealloc_ps3flash_bounce_buffer() prealloc(&ps3flash_bounce_buffer) | ||
160 | |||
161 | static int __init early_parse_ps3flash(char *p) | ||
162 | { | ||
163 | if (!p) | ||
164 | return 1; | ||
165 | |||
166 | if (!strcmp(p, "off")) | ||
167 | ps3flash_bounce_buffer.size = 0; | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | early_param("ps3flash", early_parse_ps3flash); | ||
172 | #else | ||
173 | #define prealloc_ps3flash_bounce_buffer() do { } while (0) | ||
174 | #endif | ||
175 | |||
140 | static int ps3_set_dabr(u64 dabr) | 176 | static int ps3_set_dabr(u64 dabr) |
141 | { | 177 | { |
142 | enum {DABR_USER = 1, DABR_KERNEL = 2,}; | 178 | enum {DABR_USER = 1, DABR_KERNEL = 2,}; |
@@ -146,13 +182,13 @@ static int ps3_set_dabr(u64 dabr) | |||
146 | 182 | ||
147 | static void __init ps3_setup_arch(void) | 183 | static void __init ps3_setup_arch(void) |
148 | { | 184 | { |
149 | union ps3_firmware_version v; | ||
150 | 185 | ||
151 | DBG(" -> %s:%d\n", __func__, __LINE__); | 186 | DBG(" -> %s:%d\n", __func__, __LINE__); |
152 | 187 | ||
153 | ps3_get_firmware_version(&v); | 188 | lv1_get_version_info(&ps3_firmware_version.raw); |
154 | printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor, | 189 | printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", |
155 | v.rev); | 190 | ps3_firmware_version.major, ps3_firmware_version.minor, |
191 | ps3_firmware_version.rev); | ||
156 | 192 | ||
157 | ps3_spu_set_platform(); | 193 | ps3_spu_set_platform(); |
158 | ps3_map_htab(); | 194 | ps3_map_htab(); |
@@ -166,6 +202,8 @@ static void __init ps3_setup_arch(void) | |||
166 | #endif | 202 | #endif |
167 | 203 | ||
168 | prealloc_ps3fb_videomemory(); | 204 | prealloc_ps3fb_videomemory(); |
205 | prealloc_ps3flash_bounce_buffer(); | ||
206 | |||
169 | ppc_md.power_save = ps3_power_save; | 207 | ppc_md.power_save = ps3_power_save; |
170 | 208 | ||
171 | DBG(" <- %s:%d\n", __func__, __LINE__); | 209 | DBG(" <- %s:%d\n", __func__, __LINE__); |
@@ -184,7 +222,7 @@ static int __init ps3_probe(void) | |||
184 | DBG(" -> %s:%d\n", __func__, __LINE__); | 222 | DBG(" -> %s:%d\n", __func__, __LINE__); |
185 | 223 | ||
186 | dt_root = of_get_flat_dt_root(); | 224 | dt_root = of_get_flat_dt_root(); |
187 | if (!of_flat_dt_is_compatible(dt_root, "PS3")) | 225 | if (!of_flat_dt_is_compatible(dt_root, "sony,ps3")) |
188 | return 0; | 226 | return 0; |
189 | 227 | ||
190 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; | 228 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; |
@@ -201,31 +239,12 @@ static int __init ps3_probe(void) | |||
201 | #if defined(CONFIG_KEXEC) | 239 | #if defined(CONFIG_KEXEC) |
202 | static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) | 240 | static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) |
203 | { | 241 | { |
204 | DBG(" -> %s:%d\n", __func__, __LINE__); | 242 | int cpu = smp_processor_id(); |
205 | |||
206 | if (secondary) { | ||
207 | int cpu; | ||
208 | for_each_online_cpu(cpu) | ||
209 | if (cpu) | ||
210 | ps3_smp_cleanup_cpu(cpu); | ||
211 | } else | ||
212 | ps3_smp_cleanup_cpu(0); | ||
213 | |||
214 | DBG(" <- %s:%d\n", __func__, __LINE__); | ||
215 | } | ||
216 | |||
217 | static void ps3_machine_kexec(struct kimage *image) | ||
218 | { | ||
219 | unsigned long ppe_id; | ||
220 | |||
221 | DBG(" -> %s:%d\n", __func__, __LINE__); | ||
222 | 243 | ||
223 | lv1_get_logical_ppe_id(&ppe_id); | 244 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); |
224 | lv1_configure_irq_state_bitmap(ppe_id, 0, 0); | ||
225 | ps3_mm_shutdown(); | ||
226 | ps3_mm_vas_destroy(); | ||
227 | 245 | ||
228 | default_machine_kexec(image); | 246 | ps3_smp_cleanup_cpu(cpu); |
247 | ps3_shutdown_IRQ(cpu); | ||
229 | 248 | ||
230 | DBG(" <- %s:%d\n", __func__, __LINE__); | 249 | DBG(" <- %s:%d\n", __func__, __LINE__); |
231 | } | 250 | } |
@@ -247,7 +266,7 @@ define_machine(ps3) { | |||
247 | .power_off = ps3_power_off, | 266 | .power_off = ps3_power_off, |
248 | #if defined(CONFIG_KEXEC) | 267 | #if defined(CONFIG_KEXEC) |
249 | .kexec_cpu_down = ps3_kexec_cpu_down, | 268 | .kexec_cpu_down = ps3_kexec_cpu_down, |
250 | .machine_kexec = ps3_machine_kexec, | 269 | .machine_kexec = default_machine_kexec, |
251 | .machine_kexec_prepare = default_machine_kexec_prepare, | 270 | .machine_kexec_prepare = default_machine_kexec_prepare, |
252 | .machine_crash_shutdown = default_machine_crash_shutdown, | 271 | .machine_crash_shutdown = default_machine_crash_shutdown, |
253 | #endif | 272 | #endif |
diff --git a/arch/powerpc/platforms/ps3/smp.c b/arch/powerpc/platforms/ps3/smp.c index 53416ec5198b..f0b12f212363 100644 --- a/arch/powerpc/platforms/ps3/smp.c +++ b/arch/powerpc/platforms/ps3/smp.c | |||
@@ -27,9 +27,9 @@ | |||
27 | #include "platform.h" | 27 | #include "platform.h" |
28 | 28 | ||
29 | #if defined(DEBUG) | 29 | #if defined(DEBUG) |
30 | #define DBG(fmt...) udbg_printf(fmt) | 30 | #define DBG udbg_printf |
31 | #else | 31 | #else |
32 | #define DBG(fmt...) do{if(0)printk(fmt);}while(0) | 32 | #define DBG pr_debug |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | static irqreturn_t ipi_function_handler(int irq, void *msg) | 35 | static irqreturn_t ipi_function_handler(int irq, void *msg) |
@@ -39,11 +39,11 @@ static irqreturn_t ipi_function_handler(int irq, void *msg) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | /** | 41 | /** |
42 | * virqs - a per cpu array of virqs for ipi use | 42 | * ps3_ipi_virqs - a per cpu array of virqs for ipi use |
43 | */ | 43 | */ |
44 | 44 | ||
45 | #define MSG_COUNT 4 | 45 | #define MSG_COUNT 4 |
46 | static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]); | 46 | static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]); |
47 | 47 | ||
48 | static const char *names[MSG_COUNT] = { | 48 | static const char *names[MSG_COUNT] = { |
49 | "ipi call", | 49 | "ipi call", |
@@ -62,7 +62,7 @@ static void do_message_pass(int target, int msg) | |||
62 | return; | 62 | return; |
63 | } | 63 | } |
64 | 64 | ||
65 | virq = per_cpu(virqs, target)[msg]; | 65 | virq = per_cpu(ps3_ipi_virqs, target)[msg]; |
66 | result = ps3_send_event_locally(virq); | 66 | result = ps3_send_event_locally(virq); |
67 | 67 | ||
68 | if (result) | 68 | if (result) |
@@ -94,13 +94,13 @@ static int ps3_smp_probe(void) | |||
94 | static void __init ps3_smp_setup_cpu(int cpu) | 94 | static void __init ps3_smp_setup_cpu(int cpu) |
95 | { | 95 | { |
96 | int result; | 96 | int result; |
97 | unsigned int *virqs = per_cpu(virqs, cpu); | 97 | unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); |
98 | int i; | 98 | int i; |
99 | 99 | ||
100 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); | 100 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); |
101 | 101 | ||
102 | /* | 102 | /* |
103 | * Check assumptions on virqs[] indexing. If this | 103 | * Check assumptions on ps3_ipi_virqs[] indexing. If this |
104 | * check fails, then a different mapping of PPC_MSG_ | 104 | * check fails, then a different mapping of PPC_MSG_ |
105 | * to index needs to be setup. | 105 | * to index needs to be setup. |
106 | */ | 106 | */ |
@@ -132,13 +132,13 @@ static void __init ps3_smp_setup_cpu(int cpu) | |||
132 | 132 | ||
133 | void ps3_smp_cleanup_cpu(int cpu) | 133 | void ps3_smp_cleanup_cpu(int cpu) |
134 | { | 134 | { |
135 | unsigned int *virqs = per_cpu(virqs, cpu); | 135 | unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); |
136 | int i; | 136 | int i; |
137 | 137 | ||
138 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); | 138 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); |
139 | 139 | ||
140 | for (i = 0; i < MSG_COUNT; i++) { | 140 | for (i = 0; i < MSG_COUNT; i++) { |
141 | free_irq(virqs[i], (void*)(long)i); | 141 | /* Can't call free_irq from interrupt context. */ |
142 | ps3_event_receive_port_destroy(virqs[i]); | 142 | ps3_event_receive_port_destroy(virqs[i]); |
143 | virqs[i] = NO_IRQ; | 143 | virqs[i] = NO_IRQ; |
144 | } | 144 | } |
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index 651437cb2c18..502d80ed982b 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c | |||
@@ -182,15 +182,18 @@ static int __init setup_areas(struct spu *spu) | |||
182 | { | 182 | { |
183 | struct table {char* name; unsigned long addr; unsigned long size;}; | 183 | struct table {char* name; unsigned long addr; unsigned long size;}; |
184 | 184 | ||
185 | spu_pdata(spu)->shadow = __ioremap( | 185 | spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr, |
186 | spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow), | 186 | sizeof(struct spe_shadow), |
187 | pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED); | 187 | pgprot_val(PAGE_READONLY) | |
188 | _PAGE_NO_CACHE); | ||
188 | if (!spu_pdata(spu)->shadow) { | 189 | if (!spu_pdata(spu)->shadow) { |
189 | pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); | 190 | pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); |
190 | goto fail_ioremap; | 191 | goto fail_ioremap; |
191 | } | 192 | } |
192 | 193 | ||
193 | spu->local_store = ioremap(spu->local_store_phys, LS_SIZE); | 194 | spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys, |
195 | LS_SIZE, _PAGE_NO_CACHE); | ||
196 | |||
194 | if (!spu->local_store) { | 197 | if (!spu->local_store) { |
195 | pr_debug("%s:%d: ioremap local_store failed\n", | 198 | pr_debug("%s:%d: ioremap local_store failed\n", |
196 | __func__, __LINE__); | 199 | __func__, __LINE__); |
@@ -199,6 +202,7 @@ static int __init setup_areas(struct spu *spu) | |||
199 | 202 | ||
200 | spu->problem = ioremap(spu->problem_phys, | 203 | spu->problem = ioremap(spu->problem_phys, |
201 | sizeof(struct spu_problem)); | 204 | sizeof(struct spu_problem)); |
205 | |||
202 | if (!spu->problem) { | 206 | if (!spu->problem) { |
203 | pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); | 207 | pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); |
204 | goto fail_ioremap; | 208 | goto fail_ioremap; |
@@ -206,6 +210,7 @@ static int __init setup_areas(struct spu *spu) | |||
206 | 210 | ||
207 | spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, | 211 | spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, |
208 | sizeof(struct spu_priv2)); | 212 | sizeof(struct spu_priv2)); |
213 | |||
209 | if (!spu->priv2) { | 214 | if (!spu->priv2) { |
210 | pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); | 215 | pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); |
211 | goto fail_ioremap; | 216 | goto fail_ioremap; |
@@ -400,11 +405,13 @@ static int __init ps3_enumerate_spus(int (*fn)(void *data)) | |||
400 | } | 405 | } |
401 | } | 406 | } |
402 | 407 | ||
403 | if (result) | 408 | if (result) { |
404 | printk(KERN_WARNING "%s:%d: Error initializing spus\n", | 409 | printk(KERN_WARNING "%s:%d: Error initializing spus\n", |
405 | __func__, __LINE__); | 410 | __func__, __LINE__); |
411 | return result; | ||
412 | } | ||
406 | 413 | ||
407 | return result; | 414 | return num_resource_id; |
408 | } | 415 | } |
409 | 416 | ||
410 | const struct spu_management_ops spu_management_ps3_ops = { | 417 | const struct spu_management_ops spu_management_ps3_ops = { |
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 6bda51027cc6..4bb634a17e43 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c | |||
@@ -30,22 +30,228 @@ | |||
30 | 30 | ||
31 | #include "platform.h" | 31 | #include "platform.h" |
32 | 32 | ||
33 | static struct device ps3_system_bus = { | ||
34 | .bus_id = "ps3_system", | ||
35 | }; | ||
36 | |||
37 | /* FIXME: need device usage counters! */ | ||
38 | struct { | ||
39 | struct mutex mutex; | ||
40 | int sb_11; /* usb 0 */ | ||
41 | int sb_12; /* usb 0 */ | ||
42 | int gpu; | ||
43 | } static usage_hack; | ||
44 | |||
45 | static int ps3_is_device(struct ps3_system_bus_device *dev, | ||
46 | unsigned int bus_id, unsigned int dev_id) | ||
47 | { | ||
48 | return dev->bus_id == bus_id && dev->dev_id == dev_id; | ||
49 | } | ||
50 | |||
51 | static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev) | ||
52 | { | ||
53 | int result; | ||
54 | |||
55 | BUG_ON(!dev->bus_id); | ||
56 | mutex_lock(&usage_hack.mutex); | ||
57 | |||
58 | if (ps3_is_device(dev, 1, 1)) { | ||
59 | usage_hack.sb_11++; | ||
60 | if (usage_hack.sb_11 > 1) { | ||
61 | result = 0; | ||
62 | goto done; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | if (ps3_is_device(dev, 1, 2)) { | ||
67 | usage_hack.sb_12++; | ||
68 | if (usage_hack.sb_12 > 1) { | ||
69 | result = 0; | ||
70 | goto done; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | result = lv1_open_device(dev->bus_id, dev->dev_id, 0); | ||
75 | |||
76 | if (result) { | ||
77 | pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__, | ||
78 | __LINE__, ps3_result(result)); | ||
79 | result = -EPERM; | ||
80 | } | ||
81 | |||
82 | done: | ||
83 | mutex_unlock(&usage_hack.mutex); | ||
84 | return result; | ||
85 | } | ||
86 | |||
87 | static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev) | ||
88 | { | ||
89 | int result; | ||
90 | |||
91 | BUG_ON(!dev->bus_id); | ||
92 | mutex_lock(&usage_hack.mutex); | ||
93 | |||
94 | if (ps3_is_device(dev, 1, 1)) { | ||
95 | usage_hack.sb_11--; | ||
96 | if (usage_hack.sb_11) { | ||
97 | result = 0; | ||
98 | goto done; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | if (ps3_is_device(dev, 1, 2)) { | ||
103 | usage_hack.sb_12--; | ||
104 | if (usage_hack.sb_12) { | ||
105 | result = 0; | ||
106 | goto done; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | result = lv1_close_device(dev->bus_id, dev->dev_id); | ||
111 | BUG_ON(result); | ||
112 | |||
113 | done: | ||
114 | mutex_unlock(&usage_hack.mutex); | ||
115 | return result; | ||
116 | } | ||
117 | |||
118 | static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev) | ||
119 | { | ||
120 | int result; | ||
121 | |||
122 | mutex_lock(&usage_hack.mutex); | ||
123 | |||
124 | usage_hack.gpu++; | ||
125 | if (usage_hack.gpu > 1) { | ||
126 | result = 0; | ||
127 | goto done; | ||
128 | } | ||
129 | |||
130 | result = lv1_gpu_open(0); | ||
131 | |||
132 | if (result) { | ||
133 | pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__, | ||
134 | __LINE__, ps3_result(result)); | ||
135 | result = -EPERM; | ||
136 | } | ||
137 | |||
138 | done: | ||
139 | mutex_unlock(&usage_hack.mutex); | ||
140 | return result; | ||
141 | } | ||
142 | |||
143 | static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev) | ||
144 | { | ||
145 | int result; | ||
146 | |||
147 | mutex_lock(&usage_hack.mutex); | ||
148 | |||
149 | usage_hack.gpu--; | ||
150 | if (usage_hack.gpu) { | ||
151 | result = 0; | ||
152 | goto done; | ||
153 | } | ||
154 | |||
155 | result = lv1_gpu_close(); | ||
156 | BUG_ON(result); | ||
157 | |||
158 | done: | ||
159 | mutex_unlock(&usage_hack.mutex); | ||
160 | return result; | ||
161 | } | ||
162 | |||
163 | int ps3_open_hv_device(struct ps3_system_bus_device *dev) | ||
164 | { | ||
165 | BUG_ON(!dev); | ||
166 | pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); | ||
167 | |||
168 | switch (dev->match_id) { | ||
169 | case PS3_MATCH_ID_EHCI: | ||
170 | case PS3_MATCH_ID_OHCI: | ||
171 | case PS3_MATCH_ID_GELIC: | ||
172 | case PS3_MATCH_ID_STOR_DISK: | ||
173 | case PS3_MATCH_ID_STOR_ROM: | ||
174 | case PS3_MATCH_ID_STOR_FLASH: | ||
175 | return ps3_open_hv_device_sb(dev); | ||
176 | |||
177 | case PS3_MATCH_ID_SOUND: | ||
178 | case PS3_MATCH_ID_GRAPHICS: | ||
179 | return ps3_open_hv_device_gpu(dev); | ||
180 | |||
181 | case PS3_MATCH_ID_AV_SETTINGS: | ||
182 | case PS3_MATCH_ID_SYSTEM_MANAGER: | ||
183 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, | ||
184 | __LINE__, dev->match_id); | ||
185 | pr_debug("%s:%d: bus_id: %u\n", __func__, | ||
186 | __LINE__, dev->bus_id); | ||
187 | BUG(); | ||
188 | return -EINVAL; | ||
189 | |||
190 | default: | ||
191 | break; | ||
192 | } | ||
193 | |||
194 | pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, | ||
195 | dev->match_id); | ||
196 | BUG(); | ||
197 | return -ENODEV; | ||
198 | } | ||
199 | EXPORT_SYMBOL_GPL(ps3_open_hv_device); | ||
200 | |||
201 | int ps3_close_hv_device(struct ps3_system_bus_device *dev) | ||
202 | { | ||
203 | BUG_ON(!dev); | ||
204 | pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); | ||
205 | |||
206 | switch (dev->match_id) { | ||
207 | case PS3_MATCH_ID_EHCI: | ||
208 | case PS3_MATCH_ID_OHCI: | ||
209 | case PS3_MATCH_ID_GELIC: | ||
210 | case PS3_MATCH_ID_STOR_DISK: | ||
211 | case PS3_MATCH_ID_STOR_ROM: | ||
212 | case PS3_MATCH_ID_STOR_FLASH: | ||
213 | return ps3_close_hv_device_sb(dev); | ||
214 | |||
215 | case PS3_MATCH_ID_SOUND: | ||
216 | case PS3_MATCH_ID_GRAPHICS: | ||
217 | return ps3_close_hv_device_gpu(dev); | ||
218 | |||
219 | case PS3_MATCH_ID_AV_SETTINGS: | ||
220 | case PS3_MATCH_ID_SYSTEM_MANAGER: | ||
221 | pr_debug("%s:%d: unsupported match_id: %u\n", __func__, | ||
222 | __LINE__, dev->match_id); | ||
223 | pr_debug("%s:%d: bus_id: %u\n", __func__, | ||
224 | __LINE__, dev->bus_id); | ||
225 | BUG(); | ||
226 | return -EINVAL; | ||
227 | |||
228 | default: | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, | ||
233 | dev->match_id); | ||
234 | BUG(); | ||
235 | return -ENODEV; | ||
236 | } | ||
237 | EXPORT_SYMBOL_GPL(ps3_close_hv_device); | ||
238 | |||
33 | #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) | 239 | #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) |
34 | static void _dump_mmio_region(const struct ps3_mmio_region* r, | 240 | static void _dump_mmio_region(const struct ps3_mmio_region* r, |
35 | const char* func, int line) | 241 | const char* func, int line) |
36 | { | 242 | { |
37 | pr_debug("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, | 243 | pr_debug("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, |
38 | r->did.dev_id); | 244 | r->dev->dev_id); |
39 | pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); | 245 | pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); |
40 | pr_debug("%s:%d: len %lxh\n", func, line, r->len); | 246 | pr_debug("%s:%d: len %lxh\n", func, line, r->len); |
41 | pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); | 247 | pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); |
42 | } | 248 | } |
43 | 249 | ||
44 | int ps3_mmio_region_create(struct ps3_mmio_region *r) | 250 | static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r) |
45 | { | 251 | { |
46 | int result; | 252 | int result; |
47 | 253 | ||
48 | result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id, | 254 | result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id, |
49 | r->bus_addr, r->len, r->page_size, &r->lpar_addr); | 255 | r->bus_addr, r->len, r->page_size, &r->lpar_addr); |
50 | 256 | ||
51 | if (result) { | 257 | if (result) { |
@@ -57,13 +263,26 @@ int ps3_mmio_region_create(struct ps3_mmio_region *r) | |||
57 | dump_mmio_region(r); | 263 | dump_mmio_region(r); |
58 | return result; | 264 | return result; |
59 | } | 265 | } |
266 | |||
267 | static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r) | ||
268 | { | ||
269 | /* device specific; do nothing currently */ | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | int ps3_mmio_region_create(struct ps3_mmio_region *r) | ||
274 | { | ||
275 | return r->mmio_ops->create(r); | ||
276 | } | ||
60 | EXPORT_SYMBOL_GPL(ps3_mmio_region_create); | 277 | EXPORT_SYMBOL_GPL(ps3_mmio_region_create); |
61 | 278 | ||
62 | int ps3_free_mmio_region(struct ps3_mmio_region *r) | 279 | static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r) |
63 | { | 280 | { |
64 | int result; | 281 | int result; |
65 | 282 | ||
66 | result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id, | 283 | dump_mmio_region(r); |
284 | ; | ||
285 | result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id, | ||
67 | r->lpar_addr); | 286 | r->lpar_addr); |
68 | 287 | ||
69 | if (result) | 288 | if (result) |
@@ -73,14 +292,60 @@ int ps3_free_mmio_region(struct ps3_mmio_region *r) | |||
73 | r->lpar_addr = 0; | 292 | r->lpar_addr = 0; |
74 | return result; | 293 | return result; |
75 | } | 294 | } |
295 | |||
296 | static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r) | ||
297 | { | ||
298 | /* device specific; do nothing currently */ | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | |||
303 | int ps3_free_mmio_region(struct ps3_mmio_region *r) | ||
304 | { | ||
305 | return r->mmio_ops->free(r); | ||
306 | } | ||
307 | |||
76 | EXPORT_SYMBOL_GPL(ps3_free_mmio_region); | 308 | EXPORT_SYMBOL_GPL(ps3_free_mmio_region); |
77 | 309 | ||
310 | static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = { | ||
311 | .create = ps3_sb_mmio_region_create, | ||
312 | .free = ps3_sb_free_mmio_region | ||
313 | }; | ||
314 | |||
315 | static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = { | ||
316 | .create = ps3_ioc0_mmio_region_create, | ||
317 | .free = ps3_ioc0_free_mmio_region | ||
318 | }; | ||
319 | |||
320 | int ps3_mmio_region_init(struct ps3_system_bus_device *dev, | ||
321 | struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, | ||
322 | enum ps3_mmio_page_size page_size) | ||
323 | { | ||
324 | r->dev = dev; | ||
325 | r->bus_addr = bus_addr; | ||
326 | r->len = len; | ||
327 | r->page_size = page_size; | ||
328 | switch (dev->dev_type) { | ||
329 | case PS3_DEVICE_TYPE_SB: | ||
330 | r->mmio_ops = &ps3_mmio_sb_region_ops; | ||
331 | break; | ||
332 | case PS3_DEVICE_TYPE_IOC0: | ||
333 | r->mmio_ops = &ps3_mmio_ioc0_region_ops; | ||
334 | break; | ||
335 | default: | ||
336 | BUG(); | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | return 0; | ||
340 | } | ||
341 | EXPORT_SYMBOL_GPL(ps3_mmio_region_init); | ||
342 | |||
78 | static int ps3_system_bus_match(struct device *_dev, | 343 | static int ps3_system_bus_match(struct device *_dev, |
79 | struct device_driver *_drv) | 344 | struct device_driver *_drv) |
80 | { | 345 | { |
81 | int result; | 346 | int result; |
82 | struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv); | 347 | struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv); |
83 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 348 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
84 | 349 | ||
85 | result = dev->match_id == drv->match_id; | 350 | result = dev->match_id == drv->match_id; |
86 | 351 | ||
@@ -92,32 +357,14 @@ static int ps3_system_bus_match(struct device *_dev, | |||
92 | 357 | ||
93 | static int ps3_system_bus_probe(struct device *_dev) | 358 | static int ps3_system_bus_probe(struct device *_dev) |
94 | { | 359 | { |
95 | int result; | 360 | int result = 0; |
96 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 361 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
97 | struct ps3_system_bus_driver *drv = | 362 | struct ps3_system_bus_driver *drv; |
98 | to_ps3_system_bus_driver(_dev->driver); | ||
99 | |||
100 | result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0); | ||
101 | |||
102 | if (result) { | ||
103 | pr_debug("%s:%d: lv1_open_device failed (%d)\n", | ||
104 | __func__, __LINE__, result); | ||
105 | result = -EACCES; | ||
106 | goto clean_none; | ||
107 | } | ||
108 | |||
109 | if (dev->d_region->did.bus_id) { | ||
110 | result = ps3_dma_region_create(dev->d_region); | ||
111 | 363 | ||
112 | if (result) { | 364 | BUG_ON(!dev); |
113 | pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n", | 365 | pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); |
114 | __func__, __LINE__, result); | ||
115 | BUG_ON("check region type"); | ||
116 | result = -EINVAL; | ||
117 | goto clean_device; | ||
118 | } | ||
119 | } | ||
120 | 366 | ||
367 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | ||
121 | BUG_ON(!drv); | 368 | BUG_ON(!drv); |
122 | 369 | ||
123 | if (drv->probe) | 370 | if (drv->probe) |
@@ -126,56 +373,127 @@ static int ps3_system_bus_probe(struct device *_dev) | |||
126 | pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, | 373 | pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, |
127 | dev->core.bus_id); | 374 | dev->core.bus_id); |
128 | 375 | ||
129 | if (result) { | 376 | pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); |
130 | pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__); | ||
131 | goto clean_dma; | ||
132 | } | ||
133 | |||
134 | return result; | ||
135 | |||
136 | clean_dma: | ||
137 | ps3_dma_region_free(dev->d_region); | ||
138 | clean_device: | ||
139 | lv1_close_device(dev->did.bus_id, dev->did.dev_id); | ||
140 | clean_none: | ||
141 | return result; | 377 | return result; |
142 | } | 378 | } |
143 | 379 | ||
144 | static int ps3_system_bus_remove(struct device *_dev) | 380 | static int ps3_system_bus_remove(struct device *_dev) |
145 | { | 381 | { |
146 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 382 | int result = 0; |
147 | struct ps3_system_bus_driver *drv = | 383 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
148 | to_ps3_system_bus_driver(_dev->driver); | 384 | struct ps3_system_bus_driver *drv; |
385 | |||
386 | BUG_ON(!dev); | ||
387 | pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); | ||
388 | |||
389 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | ||
390 | BUG_ON(!drv); | ||
149 | 391 | ||
150 | if (drv->remove) | 392 | if (drv->remove) |
151 | drv->remove(dev); | 393 | result = drv->remove(dev); |
152 | else | 394 | else |
153 | pr_info("%s:%d: %s no remove method\n", __func__, __LINE__, | 395 | dev_dbg(&dev->core, "%s:%d %s: no remove method\n", |
154 | dev->core.bus_id); | 396 | __func__, __LINE__, drv->core.name); |
397 | |||
398 | pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); | ||
399 | return result; | ||
400 | } | ||
401 | |||
402 | static void ps3_system_bus_shutdown(struct device *_dev) | ||
403 | { | ||
404 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
405 | struct ps3_system_bus_driver *drv; | ||
406 | |||
407 | BUG_ON(!dev); | ||
408 | |||
409 | dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, | ||
410 | dev->match_id); | ||
411 | |||
412 | if (!dev->core.driver) { | ||
413 | dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, | ||
414 | __LINE__); | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | drv = ps3_system_bus_dev_to_system_bus_drv(dev); | ||
419 | |||
420 | BUG_ON(!drv); | ||
421 | |||
422 | dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__, | ||
423 | dev->core.bus_id, drv->core.name); | ||
424 | |||
425 | if (drv->shutdown) | ||
426 | drv->shutdown(dev); | ||
427 | else if (drv->remove) { | ||
428 | dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n", | ||
429 | __func__, __LINE__, drv->core.name); | ||
430 | drv->remove(dev); | ||
431 | } else { | ||
432 | dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n", | ||
433 | __func__, __LINE__, drv->core.name); | ||
434 | BUG(); | ||
435 | } | ||
436 | |||
437 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | ||
438 | } | ||
439 | |||
440 | static int ps3_system_bus_uevent(struct device *_dev, char **envp, | ||
441 | int num_envp, char *buffer, int buffer_size) | ||
442 | { | ||
443 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
444 | int i = 0, length = 0; | ||
155 | 445 | ||
156 | ps3_dma_region_free(dev->d_region); | 446 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, |
157 | ps3_free_mmio_region(dev->m_region); | 447 | &length, "MODALIAS=ps3:%d", |
158 | lv1_close_device(dev->did.bus_id, dev->did.dev_id); | 448 | dev->match_id)) |
449 | return -ENOMEM; | ||
159 | 450 | ||
451 | envp[i] = NULL; | ||
160 | return 0; | 452 | return 0; |
161 | } | 453 | } |
162 | 454 | ||
455 | static ssize_t modalias_show(struct device *_dev, struct device_attribute *a, | ||
456 | char *buf) | ||
457 | { | ||
458 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
459 | int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id); | ||
460 | |||
461 | return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; | ||
462 | } | ||
463 | |||
464 | static struct device_attribute ps3_system_bus_dev_attrs[] = { | ||
465 | __ATTR_RO(modalias), | ||
466 | __ATTR_NULL, | ||
467 | }; | ||
468 | |||
163 | struct bus_type ps3_system_bus_type = { | 469 | struct bus_type ps3_system_bus_type = { |
164 | .name = "ps3_system_bus", | 470 | .name = "ps3_system_bus", |
165 | .match = ps3_system_bus_match, | 471 | .match = ps3_system_bus_match, |
472 | .uevent = ps3_system_bus_uevent, | ||
166 | .probe = ps3_system_bus_probe, | 473 | .probe = ps3_system_bus_probe, |
167 | .remove = ps3_system_bus_remove, | 474 | .remove = ps3_system_bus_remove, |
475 | .shutdown = ps3_system_bus_shutdown, | ||
476 | .dev_attrs = ps3_system_bus_dev_attrs, | ||
168 | }; | 477 | }; |
169 | 478 | ||
170 | int __init ps3_system_bus_init(void) | 479 | static int __init ps3_system_bus_init(void) |
171 | { | 480 | { |
172 | int result; | 481 | int result; |
173 | 482 | ||
174 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | 483 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) |
175 | return -ENODEV; | 484 | return -ENODEV; |
176 | 485 | ||
486 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | ||
487 | |||
488 | mutex_init(&usage_hack.mutex); | ||
489 | |||
490 | result = device_register(&ps3_system_bus); | ||
491 | BUG_ON(result); | ||
492 | |||
177 | result = bus_register(&ps3_system_bus_type); | 493 | result = bus_register(&ps3_system_bus_type); |
178 | BUG_ON(result); | 494 | BUG_ON(result); |
495 | |||
496 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | ||
179 | return result; | 497 | return result; |
180 | } | 498 | } |
181 | 499 | ||
@@ -185,16 +503,13 @@ core_initcall(ps3_system_bus_init); | |||
185 | * Returns the virtual address of the buffer and sets dma_handle | 503 | * Returns the virtual address of the buffer and sets dma_handle |
186 | * to the dma address (mapping) of the first page. | 504 | * to the dma address (mapping) of the first page. |
187 | */ | 505 | */ |
188 | |||
189 | static void * ps3_alloc_coherent(struct device *_dev, size_t size, | 506 | static void * ps3_alloc_coherent(struct device *_dev, size_t size, |
190 | dma_addr_t *dma_handle, gfp_t flag) | 507 | dma_addr_t *dma_handle, gfp_t flag) |
191 | { | 508 | { |
192 | int result; | 509 | int result; |
193 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 510 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
194 | unsigned long virt_addr; | 511 | unsigned long virt_addr; |
195 | 512 | ||
196 | BUG_ON(!dev->d_region->bus_addr); | ||
197 | |||
198 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM); | 513 | flag &= ~(__GFP_DMA | __GFP_HIGHMEM); |
199 | flag |= __GFP_ZERO; | 514 | flag |= __GFP_ZERO; |
200 | 515 | ||
@@ -205,7 +520,8 @@ static void * ps3_alloc_coherent(struct device *_dev, size_t size, | |||
205 | goto clean_none; | 520 | goto clean_none; |
206 | } | 521 | } |
207 | 522 | ||
208 | result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle); | 523 | result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle, |
524 | IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); | ||
209 | 525 | ||
210 | if (result) { | 526 | if (result) { |
211 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | 527 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", |
@@ -226,7 +542,7 @@ clean_none: | |||
226 | static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, | 542 | static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, |
227 | dma_addr_t dma_handle) | 543 | dma_addr_t dma_handle) |
228 | { | 544 | { |
229 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 545 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
230 | 546 | ||
231 | ps3_dma_unmap(dev->d_region, dma_handle, size); | 547 | ps3_dma_unmap(dev->d_region, dma_handle, size); |
232 | free_pages((unsigned long)vaddr, get_order(size)); | 548 | free_pages((unsigned long)vaddr, get_order(size)); |
@@ -239,15 +555,16 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, | |||
239 | * byte within the page as vaddr. | 555 | * byte within the page as vaddr. |
240 | */ | 556 | */ |
241 | 557 | ||
242 | static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size, | 558 | static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size, |
243 | enum dma_data_direction direction) | 559 | enum dma_data_direction direction) |
244 | { | 560 | { |
245 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 561 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
246 | int result; | 562 | int result; |
247 | unsigned long bus_addr; | 563 | unsigned long bus_addr; |
248 | 564 | ||
249 | result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, | 565 | result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, |
250 | &bus_addr); | 566 | &bus_addr, |
567 | IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M); | ||
251 | 568 | ||
252 | if (result) { | 569 | if (result) { |
253 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | 570 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", |
@@ -257,10 +574,44 @@ static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size, | |||
257 | return bus_addr; | 574 | return bus_addr; |
258 | } | 575 | } |
259 | 576 | ||
577 | static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr, | ||
578 | size_t size, | ||
579 | enum dma_data_direction direction) | ||
580 | { | ||
581 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | ||
582 | int result; | ||
583 | unsigned long bus_addr; | ||
584 | u64 iopte_flag; | ||
585 | |||
586 | iopte_flag = IOPTE_M; | ||
587 | switch (direction) { | ||
588 | case DMA_BIDIRECTIONAL: | ||
589 | iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW; | ||
590 | break; | ||
591 | case DMA_TO_DEVICE: | ||
592 | iopte_flag |= IOPTE_PP_R | IOPTE_SO_R; | ||
593 | break; | ||
594 | case DMA_FROM_DEVICE: | ||
595 | iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW; | ||
596 | break; | ||
597 | default: | ||
598 | /* not happned */ | ||
599 | BUG(); | ||
600 | }; | ||
601 | result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, | ||
602 | &bus_addr, iopte_flag); | ||
603 | |||
604 | if (result) { | ||
605 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | ||
606 | __func__, __LINE__, result); | ||
607 | } | ||
608 | return bus_addr; | ||
609 | } | ||
610 | |||
260 | static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, | 611 | static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, |
261 | size_t size, enum dma_data_direction direction) | 612 | size_t size, enum dma_data_direction direction) |
262 | { | 613 | { |
263 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 614 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
264 | int result; | 615 | int result; |
265 | 616 | ||
266 | result = ps3_dma_unmap(dev->d_region, dma_addr, size); | 617 | result = ps3_dma_unmap(dev->d_region, dma_addr, size); |
@@ -271,20 +622,20 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, | |||
271 | } | 622 | } |
272 | } | 623 | } |
273 | 624 | ||
274 | static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, | 625 | static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents, |
275 | enum dma_data_direction direction) | 626 | enum dma_data_direction direction) |
276 | { | 627 | { |
277 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | 628 | #if defined(CONFIG_PS3_DYNAMIC_DMA) |
278 | BUG_ON("do"); | 629 | BUG_ON("do"); |
279 | return -EPERM; | 630 | return -EPERM; |
280 | #else | 631 | #else |
281 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 632 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
282 | int i; | 633 | int i; |
283 | 634 | ||
284 | for (i = 0; i < nents; i++, sg++) { | 635 | for (i = 0; i < nents; i++, sg++) { |
285 | int result = ps3_dma_map(dev->d_region, | 636 | int result = ps3_dma_map(dev->d_region, |
286 | page_to_phys(sg->page) + sg->offset, sg->length, | 637 | page_to_phys(sg->page) + sg->offset, sg->length, |
287 | &sg->dma_address); | 638 | &sg->dma_address, 0); |
288 | 639 | ||
289 | if (result) { | 640 | if (result) { |
290 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", | 641 | pr_debug("%s:%d: ps3_dma_map failed (%d)\n", |
@@ -299,7 +650,15 @@ static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, | |||
299 | #endif | 650 | #endif |
300 | } | 651 | } |
301 | 652 | ||
302 | static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg, | 653 | static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg, |
654 | int nents, | ||
655 | enum dma_data_direction direction) | ||
656 | { | ||
657 | BUG(); | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, | ||
303 | int nents, enum dma_data_direction direction) | 662 | int nents, enum dma_data_direction direction) |
304 | { | 663 | { |
305 | #if defined(CONFIG_PS3_DYNAMIC_DMA) | 664 | #if defined(CONFIG_PS3_DYNAMIC_DMA) |
@@ -307,18 +666,34 @@ static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg, | |||
307 | #endif | 666 | #endif |
308 | } | 667 | } |
309 | 668 | ||
669 | static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg, | ||
670 | int nents, enum dma_data_direction direction) | ||
671 | { | ||
672 | BUG(); | ||
673 | } | ||
674 | |||
310 | static int ps3_dma_supported(struct device *_dev, u64 mask) | 675 | static int ps3_dma_supported(struct device *_dev, u64 mask) |
311 | { | 676 | { |
312 | return mask >= DMA_32BIT_MASK; | 677 | return mask >= DMA_32BIT_MASK; |
313 | } | 678 | } |
314 | 679 | ||
315 | static struct dma_mapping_ops ps3_dma_ops = { | 680 | static struct dma_mapping_ops ps3_sb_dma_ops = { |
316 | .alloc_coherent = ps3_alloc_coherent, | 681 | .alloc_coherent = ps3_alloc_coherent, |
317 | .free_coherent = ps3_free_coherent, | 682 | .free_coherent = ps3_free_coherent, |
318 | .map_single = ps3_map_single, | 683 | .map_single = ps3_sb_map_single, |
319 | .unmap_single = ps3_unmap_single, | 684 | .unmap_single = ps3_unmap_single, |
320 | .map_sg = ps3_map_sg, | 685 | .map_sg = ps3_sb_map_sg, |
321 | .unmap_sg = ps3_unmap_sg, | 686 | .unmap_sg = ps3_sb_unmap_sg, |
687 | .dma_supported = ps3_dma_supported | ||
688 | }; | ||
689 | |||
690 | static struct dma_mapping_ops ps3_ioc0_dma_ops = { | ||
691 | .alloc_coherent = ps3_alloc_coherent, | ||
692 | .free_coherent = ps3_free_coherent, | ||
693 | .map_single = ps3_ioc0_map_single, | ||
694 | .unmap_single = ps3_unmap_single, | ||
695 | .map_sg = ps3_ioc0_map_sg, | ||
696 | .unmap_sg = ps3_ioc0_unmap_sg, | ||
322 | .dma_supported = ps3_dma_supported | 697 | .dma_supported = ps3_dma_supported |
323 | }; | 698 | }; |
324 | 699 | ||
@@ -328,7 +703,7 @@ static struct dma_mapping_ops ps3_dma_ops = { | |||
328 | 703 | ||
329 | static void ps3_system_bus_release_device(struct device *_dev) | 704 | static void ps3_system_bus_release_device(struct device *_dev) |
330 | { | 705 | { |
331 | struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); | 706 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
332 | kfree(dev); | 707 | kfree(dev); |
333 | } | 708 | } |
334 | 709 | ||
@@ -343,19 +718,38 @@ static void ps3_system_bus_release_device(struct device *_dev) | |||
343 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) | 718 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) |
344 | { | 719 | { |
345 | int result; | 720 | int result; |
346 | static unsigned int dev_count = 1; | 721 | static unsigned int dev_ioc0_count; |
722 | static unsigned int dev_sb_count; | ||
723 | static unsigned int dev_vuart_count; | ||
347 | 724 | ||
348 | dev->core.parent = NULL; | 725 | if (!dev->core.parent) |
726 | dev->core.parent = &ps3_system_bus; | ||
349 | dev->core.bus = &ps3_system_bus_type; | 727 | dev->core.bus = &ps3_system_bus_type; |
350 | dev->core.release = ps3_system_bus_release_device; | 728 | dev->core.release = ps3_system_bus_release_device; |
351 | 729 | ||
730 | switch (dev->dev_type) { | ||
731 | case PS3_DEVICE_TYPE_IOC0: | ||
732 | dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops; | ||
733 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | ||
734 | "ioc0_%02x", ++dev_ioc0_count); | ||
735 | break; | ||
736 | case PS3_DEVICE_TYPE_SB: | ||
737 | dev->core.archdata.dma_ops = &ps3_sb_dma_ops; | ||
738 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | ||
739 | "sb_%02x", ++dev_sb_count); | ||
740 | |||
741 | break; | ||
742 | case PS3_DEVICE_TYPE_VUART: | ||
743 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), | ||
744 | "vuart_%02x", ++dev_vuart_count); | ||
745 | break; | ||
746 | default: | ||
747 | BUG(); | ||
748 | }; | ||
749 | |||
352 | dev->core.archdata.of_node = NULL; | 750 | dev->core.archdata.of_node = NULL; |
353 | dev->core.archdata.dma_ops = &ps3_dma_ops; | ||
354 | dev->core.archdata.numa_node = 0; | 751 | dev->core.archdata.numa_node = 0; |
355 | 752 | ||
356 | snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x", | ||
357 | dev_count++); | ||
358 | |||
359 | pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); | 753 | pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); |
360 | 754 | ||
361 | result = device_register(&dev->core); | 755 | result = device_register(&dev->core); |
@@ -368,9 +762,15 @@ int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv) | |||
368 | { | 762 | { |
369 | int result; | 763 | int result; |
370 | 764 | ||
765 | pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
766 | |||
767 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
768 | return -ENODEV; | ||
769 | |||
371 | drv->core.bus = &ps3_system_bus_type; | 770 | drv->core.bus = &ps3_system_bus_type; |
372 | 771 | ||
373 | result = driver_register(&drv->core); | 772 | result = driver_register(&drv->core); |
773 | pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
374 | return result; | 774 | return result; |
375 | } | 775 | } |
376 | 776 | ||
@@ -378,7 +778,9 @@ EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register); | |||
378 | 778 | ||
379 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) | 779 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) |
380 | { | 780 | { |
781 | pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
381 | driver_unregister(&drv->core); | 782 | driver_unregister(&drv->core); |
783 | pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); | ||
382 | } | 784 | } |
383 | 785 | ||
384 | EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); | 786 | EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); |
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c index 1bae8b19b363..802a9ccacb5e 100644 --- a/arch/powerpc/platforms/ps3/time.c +++ b/arch/powerpc/platforms/ps3/time.c | |||
@@ -39,7 +39,7 @@ static void _dump_tm(const struct rtc_time *tm, const char* func, int line) | |||
39 | } | 39 | } |
40 | 40 | ||
41 | #define dump_time(_a) _dump_time(_a, __func__, __LINE__) | 41 | #define dump_time(_a) _dump_time(_a, __func__, __LINE__) |
42 | static void __attribute__ ((unused)) _dump_time(int time, const char* func, | 42 | static void __maybe_unused _dump_time(int time, const char *func, |
43 | int line) | 43 | int line) |
44 | { | 44 | { |
45 | struct rtc_time tm; | 45 | struct rtc_time tm; |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index ae1fc92dc1c9..992ba6753cf2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -8,7 +8,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | |||
8 | obj-$(CONFIG_SMP) += smp.o | 8 | obj-$(CONFIG_SMP) += smp.o |
9 | obj-$(CONFIG_XICS) += xics.o | 9 | obj-$(CONFIG_XICS) += xics.o |
10 | obj-$(CONFIG_SCANLOG) += scanlog.o | 10 | obj-$(CONFIG_SCANLOG) += scanlog.o |
11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o | 11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o |
12 | obj-$(CONFIG_KEXEC) += kexec.o | 12 | obj-$(CONFIG_KEXEC) += kexec.o |
13 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o | 13 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o |
14 | obj-$(CONFIG_PCI_MSI) += msi.o | 14 | obj-$(CONFIG_PCI_MSI) += msi.o |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 5f3e6d8659fe..b8770395013d 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * eeh.c | 2 | * eeh.c |
3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation | 3 | * Copyright IBM Corporation 2001, 2005, 2006 |
4 | * Copyright Dave Engebretsen & Todd Inglett 2001 | ||
5 | * Copyright Linas Vepstas 2005, 2006 | ||
4 | * | 6 | * |
5 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -15,6 +17,8 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | * | ||
21 | * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com> | ||
18 | */ | 22 | */ |
19 | 23 | ||
20 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
@@ -117,7 +121,6 @@ static unsigned long no_cfg_addr; | |||
117 | static unsigned long ignored_check; | 121 | static unsigned long ignored_check; |
118 | static unsigned long total_mmio_ffs; | 122 | static unsigned long total_mmio_ffs; |
119 | static unsigned long false_positives; | 123 | static unsigned long false_positives; |
120 | static unsigned long ignored_failures; | ||
121 | static unsigned long slot_resets; | 124 | static unsigned long slot_resets; |
122 | 125 | ||
123 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) | 126 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) |
@@ -505,6 +508,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
505 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", | 508 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", |
506 | ret, dn->full_name); | 509 | ret, dn->full_name); |
507 | false_positives++; | 510 | false_positives++; |
511 | pdn->eeh_false_positives ++; | ||
508 | rc = 0; | 512 | rc = 0; |
509 | goto dn_unlock; | 513 | goto dn_unlock; |
510 | } | 514 | } |
@@ -513,6 +517,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
513 | * they are empty when they don't have children. */ | 517 | * they are empty when they don't have children. */ |
514 | if ((rets[0] == 5) && (dn->child == NULL)) { | 518 | if ((rets[0] == 5) && (dn->child == NULL)) { |
515 | false_positives++; | 519 | false_positives++; |
520 | pdn->eeh_false_positives ++; | ||
516 | rc = 0; | 521 | rc = 0; |
517 | goto dn_unlock; | 522 | goto dn_unlock; |
518 | } | 523 | } |
@@ -522,6 +527,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
522 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", | 527 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", |
523 | ret, dn->full_name); | 528 | ret, dn->full_name); |
524 | false_positives++; | 529 | false_positives++; |
530 | pdn->eeh_false_positives ++; | ||
525 | rc = 0; | 531 | rc = 0; |
526 | goto dn_unlock; | 532 | goto dn_unlock; |
527 | } | 533 | } |
@@ -529,6 +535,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
529 | /* If not the kind of error we know about, punt. */ | 535 | /* If not the kind of error we know about, punt. */ |
530 | if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { | 536 | if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { |
531 | false_positives++; | 537 | false_positives++; |
538 | pdn->eeh_false_positives ++; | ||
532 | rc = 0; | 539 | rc = 0; |
533 | goto dn_unlock; | 540 | goto dn_unlock; |
534 | } | 541 | } |
@@ -921,6 +928,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
921 | pdn->eeh_mode = 0; | 928 | pdn->eeh_mode = 0; |
922 | pdn->eeh_check_count = 0; | 929 | pdn->eeh_check_count = 0; |
923 | pdn->eeh_freeze_count = 0; | 930 | pdn->eeh_freeze_count = 0; |
931 | pdn->eeh_false_positives = 0; | ||
924 | 932 | ||
925 | if (status && strcmp(status, "ok") != 0) | 933 | if (status && strcmp(status, "ok") != 0) |
926 | return NULL; /* ignore devices with bad status */ | 934 | return NULL; /* ignore devices with bad status */ |
@@ -1139,7 +1147,8 @@ static void eeh_add_device_late(struct pci_dev *dev) | |||
1139 | pdn = PCI_DN(dn); | 1147 | pdn = PCI_DN(dn); |
1140 | pdn->pcidev = dev; | 1148 | pdn->pcidev = dev; |
1141 | 1149 | ||
1142 | pci_addr_cache_insert_device (dev); | 1150 | pci_addr_cache_insert_device(dev); |
1151 | eeh_sysfs_add_device(dev); | ||
1143 | } | 1152 | } |
1144 | 1153 | ||
1145 | void eeh_add_device_tree_late(struct pci_bus *bus) | 1154 | void eeh_add_device_tree_late(struct pci_bus *bus) |
@@ -1178,6 +1187,7 @@ static void eeh_remove_device(struct pci_dev *dev) | |||
1178 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); | 1187 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); |
1179 | #endif | 1188 | #endif |
1180 | pci_addr_cache_remove_device(dev); | 1189 | pci_addr_cache_remove_device(dev); |
1190 | eeh_sysfs_remove_device(dev); | ||
1181 | 1191 | ||
1182 | dn = pci_device_to_OF_node(dev); | 1192 | dn = pci_device_to_OF_node(dev); |
1183 | if (PCI_DN(dn)->pcidev) { | 1193 | if (PCI_DN(dn)->pcidev) { |
@@ -1214,11 +1224,10 @@ static int proc_eeh_show(struct seq_file *m, void *v) | |||
1214 | "check not wanted=%ld\n" | 1224 | "check not wanted=%ld\n" |
1215 | "eeh_total_mmio_ffs=%ld\n" | 1225 | "eeh_total_mmio_ffs=%ld\n" |
1216 | "eeh_false_positives=%ld\n" | 1226 | "eeh_false_positives=%ld\n" |
1217 | "eeh_ignored_failures=%ld\n" | ||
1218 | "eeh_slot_resets=%ld\n", | 1227 | "eeh_slot_resets=%ld\n", |
1219 | no_device, no_dn, no_cfg_addr, | 1228 | no_device, no_dn, no_cfg_addr, |
1220 | ignored_check, total_mmio_ffs, | 1229 | ignored_check, total_mmio_ffs, |
1221 | false_positives, ignored_failures, | 1230 | false_positives, |
1222 | slot_resets); | 1231 | slot_resets); |
1223 | } | 1232 | } |
1224 | 1233 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index f2bae04424f8..e49c815eae23 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c | |||
@@ -2,7 +2,8 @@ | |||
2 | * eeh_cache.c | 2 | * eeh_cache.c |
3 | * PCI address cache; allows the lookup of PCI devices based on I/O address | 3 | * PCI address cache; allows the lookup of PCI devices based on I/O address |
4 | * | 4 | * |
5 | * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation | 5 | * Copyright IBM Corporation 2004 |
6 | * Copyright Linas Vepstas <linas@austin.ibm.com> 2004 | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -295,6 +296,8 @@ void __init pci_addr_cache_build(void) | |||
295 | continue; | 296 | continue; |
296 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ | 297 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ |
297 | PCI_DN(dn)->pcidev = dev; | 298 | PCI_DN(dn)->pcidev = dev; |
299 | |||
300 | eeh_sysfs_add_device(dev); | ||
298 | } | 301 | } |
299 | 302 | ||
300 | #ifdef DEBUG | 303 | #ifdef DEBUG |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 161a5844ab6c..15e015ef6865 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * PCI Error Recovery Driver for RPA-compliant PPC64 platform. | 2 | * PCI Error Recovery Driver for RPA-compliant PPC64 platform. |
3 | * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org> | 3 | * Copyright IBM Corp. 2004 2005 |
4 | * Copyright Linas Vepstas <linas@linas.org> 2004, 2005 | ||
4 | * | 5 | * |
5 | * All rights reserved. | 6 | * All rights reserved. |
6 | * | 7 | * |
@@ -19,8 +20,7 @@ | |||
19 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | * | 22 | * |
22 | * Send feedback to <linas@us.ibm.com> | 23 | * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com> |
23 | * | ||
24 | */ | 24 | */ |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c new file mode 100644 index 000000000000..15e13b568904 --- /dev/null +++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Sysfs entries for PCI Error Recovery for PAPR-compliant platform. | ||
3 | * Copyright IBM Corporation 2007 | ||
4 | * Copyright Linas Vepstas <linas@austin.ibm.com> 2007 | ||
5 | * | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or (at | ||
11 | * your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
16 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
17 | * details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com> | ||
24 | */ | ||
25 | #include <linux/pci.h> | ||
26 | #include <asm/ppc-pci.h> | ||
27 | #include <asm/pci-bridge.h> | ||
28 | #include <linux/kobject.h> | ||
29 | |||
30 | /** | ||
31 | * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic | ||
32 | * @_name: name of file in sysfs directory | ||
33 | * @_memb: name of member in struct pci_dn to access | ||
34 | * @_format: printf format for display | ||
35 | * | ||
36 | * All of the attributes look very similar, so just | ||
37 | * auto-gen a cut-n-paste routine to display them. | ||
38 | */ | ||
39 | #define EEH_SHOW_ATTR(_name,_memb,_format) \ | ||
40 | static ssize_t eeh_show_##_name(struct device *dev, \ | ||
41 | struct device_attribute *attr, char *buf) \ | ||
42 | { \ | ||
43 | struct pci_dev *pdev = to_pci_dev(dev); \ | ||
44 | struct device_node *dn = pci_device_to_OF_node(pdev); \ | ||
45 | struct pci_dn *pdn; \ | ||
46 | \ | ||
47 | if (!dn || PCI_DN(dn) == NULL) \ | ||
48 | return 0; \ | ||
49 | \ | ||
50 | pdn = PCI_DN(dn); \ | ||
51 | return sprintf(buf, _format "\n", pdn->_memb); \ | ||
52 | } \ | ||
53 | static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL); | ||
54 | |||
55 | |||
56 | EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x"); | ||
57 | EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x"); | ||
58 | EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x"); | ||
59 | EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d"); | ||
60 | EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d"); | ||
61 | EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d"); | ||
62 | |||
63 | void eeh_sysfs_add_device(struct pci_dev *pdev) | ||
64 | { | ||
65 | int rc=0; | ||
66 | |||
67 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode); | ||
68 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr); | ||
69 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | ||
70 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count); | ||
71 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives); | ||
72 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count); | ||
73 | |||
74 | if (rc) | ||
75 | printk(KERN_WARNING "EEH: Unable to create sysfs entries\n"); | ||
76 | } | ||
77 | |||
78 | void eeh_sysfs_remove_device(struct pci_dev *pdev) | ||
79 | { | ||
80 | device_remove_file(&pdev->dev, &dev_attr_eeh_mode); | ||
81 | device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr); | ||
82 | device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | ||
83 | device_remove_file(&pdev->dev, &dev_attr_eeh_check_count); | ||
84 | device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives); | ||
85 | device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count); | ||
86 | } | ||
87 | |||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 362dfbc260a6..8cc6eeeaae2f 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -373,12 +373,23 @@ static void pSeries_lpar_hptab_clear(void) | |||
373 | { | 373 | { |
374 | unsigned long size_bytes = 1UL << ppc64_pft_size; | 374 | unsigned long size_bytes = 1UL << ppc64_pft_size; |
375 | unsigned long hpte_count = size_bytes >> 4; | 375 | unsigned long hpte_count = size_bytes >> 4; |
376 | unsigned long dummy1, dummy2; | 376 | unsigned long dummy1, dummy2, dword0; |
377 | long lpar_rc; | ||
377 | int i; | 378 | int i; |
378 | 379 | ||
379 | /* TODO: Use bulk call */ | 380 | /* TODO: Use bulk call */ |
380 | for (i = 0; i < hpte_count; i++) | 381 | for (i = 0; i < hpte_count; i++) { |
381 | plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); | 382 | /* dont remove HPTEs with VRMA mappings */ |
383 | lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG, | ||
384 | &dummy1, &dummy2); | ||
385 | if (lpar_rc == H_NOT_FOUND) { | ||
386 | lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1); | ||
387 | if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK) | ||
388 | != HPTE_V_VRMA_MASK)) | ||
389 | /* Can be hpte for 1TB Seg. So remove it */ | ||
390 | plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); | ||
391 | } | ||
392 | } | ||
382 | } | 393 | } |
383 | 394 | ||
384 | /* | 395 | /* |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index ffaf6c5c517b..47f0e0857f0e 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -110,8 +110,6 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | } | 112 | } |
113 | |||
114 | eeh_add_device_tree_late(bus); | ||
115 | } | 113 | } |
116 | EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); | 114 | EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); |
117 | 115 | ||
@@ -139,6 +137,8 @@ pcibios_pci_config_bridge(struct pci_dev *dev) | |||
139 | 137 | ||
140 | /* Make the discovered devices available */ | 138 | /* Make the discovered devices available */ |
141 | pci_bus_add_devices(child_bus); | 139 | pci_bus_add_devices(child_bus); |
140 | |||
141 | eeh_add_device_tree_late(child_bus); | ||
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | 144 | ||
@@ -171,6 +171,7 @@ pcibios_add_pci_devices(struct pci_bus * bus) | |||
171 | if (!list_empty(&bus->devices)) { | 171 | if (!list_empty(&bus->devices)) { |
172 | pcibios_fixup_new_pci_devices(bus, 0); | 172 | pcibios_fixup_new_pci_devices(bus, 0); |
173 | pci_bus_add_devices(bus); | 173 | pci_bus_add_devices(bus); |
174 | eeh_add_device_tree_late(bus); | ||
174 | } | 175 | } |
175 | } else if (mode == PCI_PROBE_NORMAL) { | 176 | } else if (mode == PCI_PROBE_NORMAL) { |
176 | /* use legacy probe */ | 177 | /* use legacy probe */ |
@@ -179,6 +180,7 @@ pcibios_add_pci_devices(struct pci_bus * bus) | |||
179 | if (num) { | 180 | if (num) { |
180 | pcibios_fixup_new_pci_devices(bus, 1); | 181 | pcibios_fixup_new_pci_devices(bus, 1); |
181 | pci_bus_add_devices(bus); | 182 | pci_bus_add_devices(bus); |
183 | eeh_add_device_tree_late(bus); | ||
182 | } | 184 | } |
183 | 185 | ||
184 | list_for_each_entry(dev, &bus->devices, bus_list) | 186 | list_for_each_entry(dev, &bus->devices, bus_list) |
@@ -200,8 +202,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
200 | rtas_setup_phb(phb); | 202 | rtas_setup_phb(phb); |
201 | pci_process_bridge_OF_ranges(phb, dn, 0); | 203 | pci_process_bridge_OF_ranges(phb, dn, 0); |
202 | 204 | ||
203 | pci_setup_phb_io_dynamic(phb, primary); | ||
204 | |||
205 | pci_devs_phb_init_dynamic(phb); | 205 | pci_devs_phb_init_dynamic(phb); |
206 | 206 | ||
207 | if (dn->child) | 207 | if (dn->child) |
@@ -210,6 +210,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
210 | scan_phb(phb); | 210 | scan_phb(phb); |
211 | pcibios_fixup_new_pci_devices(phb->bus, 0); | 211 | pcibios_fixup_new_pci_devices(phb->bus, 0); |
212 | pci_bus_add_devices(phb->bus); | 212 | pci_bus_add_devices(phb->bus); |
213 | eeh_add_device_tree_late(phb->bus); | ||
213 | 214 | ||
214 | return phb; | 215 | return phb; |
215 | } | 216 | } |
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 2e4d10c9eea8..d003c80fa31d 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h | |||
@@ -108,6 +108,21 @@ static inline long plpar_pte_read(unsigned long flags, unsigned long ptex, | |||
108 | return rc; | 108 | return rc; |
109 | } | 109 | } |
110 | 110 | ||
111 | /* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */ | ||
112 | static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex, | ||
113 | unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) | ||
114 | { | ||
115 | long rc; | ||
116 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
117 | |||
118 | rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex); | ||
119 | |||
120 | *old_pteh_ret = retbuf[0]; | ||
121 | *old_ptel_ret = retbuf[1]; | ||
122 | |||
123 | return rc; | ||
124 | } | ||
125 | |||
111 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, | 126 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, |
112 | unsigned long avpn) | 127 | unsigned long avpn) |
113 | { | 128 | { |
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 2729d559fd91..61e19f78b923 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
@@ -33,6 +33,8 @@ static inline void setup_kexec_cpu_down_xics(void) { } | |||
33 | static inline void setup_kexec_cpu_down_mpic(void) { } | 33 | static inline void setup_kexec_cpu_down_mpic(void) { } |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | extern void pSeries_final_fixup(void); | ||
37 | |||
36 | /* Poweron flag used for enabling auto ups restart */ | 38 | /* Poweron flag used for enabling auto ups restart */ |
37 | extern unsigned long rtas_poweron_auto; | 39 | extern unsigned long rtas_poweron_auto; |
38 | 40 | ||
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 5aa97aff3391..c02f8742c54d 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -123,7 +123,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist | |||
123 | strcpy(np->full_name, path); | 123 | strcpy(np->full_name, path); |
124 | 124 | ||
125 | np->properties = proplist; | 125 | np->properties = proplist; |
126 | OF_MARK_DYNAMIC(np); | 126 | of_node_set_flag(np, OF_DYNAMIC); |
127 | kref_init(&np->kref); | 127 | kref_init(&np->kref); |
128 | 128 | ||
129 | np->parent = derive_parent(path); | 129 | np->parent = derive_parent(path); |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index a031d99becb7..59e69f085cb4 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -399,6 +399,7 @@ static void pseries_dedicated_idle_sleep(void) | |||
399 | * a good time to find other work to dispatch. | 399 | * a good time to find other work to dispatch. |
400 | */ | 400 | */ |
401 | get_lppaca()->idle = 1; | 401 | get_lppaca()->idle = 1; |
402 | get_lppaca()->donate_dedicated_cpu = 1; | ||
402 | 403 | ||
403 | /* | 404 | /* |
404 | * We come in with interrupts disabled, and need_resched() | 405 | * We come in with interrupts disabled, and need_resched() |
@@ -431,6 +432,7 @@ static void pseries_dedicated_idle_sleep(void) | |||
431 | 432 | ||
432 | out: | 433 | out: |
433 | HMT_medium(); | 434 | HMT_medium(); |
435 | get_lppaca()->donate_dedicated_cpu = 0; | ||
434 | get_lppaca()->idle = 0; | 436 | get_lppaca()->idle = 0; |
435 | } | 437 | } |
436 | 438 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index f1df942072bb..5bd90a7eb763 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) | |||
156 | 156 | ||
157 | 157 | ||
158 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
159 | static int get_irq_server(unsigned int virq) | 159 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
160 | { | 160 | { |
161 | unsigned int server; | 161 | int server; |
162 | /* For the moment only implement delivery to all cpus or one cpu */ | 162 | /* For the moment only implement delivery to all cpus or one cpu */ |
163 | cpumask_t cpumask = irq_desc[virq].affinity; | 163 | cpumask_t cpumask = irq_desc[virq].affinity; |
164 | cpumask_t tmp = CPU_MASK_NONE; | 164 | cpumask_t tmp = CPU_MASK_NONE; |
@@ -166,22 +166,25 @@ static int get_irq_server(unsigned int virq) | |||
166 | if (!distribute_irqs) | 166 | if (!distribute_irqs) |
167 | return default_server; | 167 | return default_server; |
168 | 168 | ||
169 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 169 | if (!cpus_equal(cpumask, CPU_MASK_ALL)) { |
170 | server = default_distrib_server; | ||
171 | } else { | ||
172 | cpus_and(tmp, cpu_online_map, cpumask); | 170 | cpus_and(tmp, cpu_online_map, cpumask); |
173 | 171 | ||
174 | if (cpus_empty(tmp)) | 172 | server = first_cpu(tmp); |
175 | server = default_distrib_server; | 173 | |
176 | else | 174 | if (server < NR_CPUS) |
177 | server = get_hard_smp_processor_id(first_cpu(tmp)); | 175 | return get_hard_smp_processor_id(server); |
176 | |||
177 | if (strict_check) | ||
178 | return -1; | ||
178 | } | 179 | } |
179 | 180 | ||
180 | return server; | 181 | if (cpus_equal(cpu_online_map, cpu_present_map)) |
182 | return default_distrib_server; | ||
181 | 183 | ||
184 | return default_server; | ||
182 | } | 185 | } |
183 | #else | 186 | #else |
184 | static int get_irq_server(unsigned int virq) | 187 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
185 | { | 188 | { |
186 | return default_server; | 189 | return default_server; |
187 | } | 190 | } |
@@ -192,7 +195,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
192 | { | 195 | { |
193 | unsigned int irq; | 196 | unsigned int irq; |
194 | int call_status; | 197 | int call_status; |
195 | unsigned int server; | 198 | int server; |
196 | 199 | ||
197 | pr_debug("xics: unmask virq %d\n", virq); | 200 | pr_debug("xics: unmask virq %d\n", virq); |
198 | 201 | ||
@@ -201,7 +204,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
201 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 204 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
202 | return; | 205 | return; |
203 | 206 | ||
204 | server = get_irq_server(virq); | 207 | server = get_irq_server(virq, 0); |
205 | 208 | ||
206 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, | 209 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, |
207 | DEFAULT_PRIORITY); | 210 | DEFAULT_PRIORITY); |
@@ -398,8 +401,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
398 | unsigned int irq; | 401 | unsigned int irq; |
399 | int status; | 402 | int status; |
400 | int xics_status[2]; | 403 | int xics_status[2]; |
401 | unsigned long newmask; | 404 | int irq_server; |
402 | cpumask_t tmp = CPU_MASK_NONE; | ||
403 | 405 | ||
404 | irq = (unsigned int)irq_map[virq].hwirq; | 406 | irq = (unsigned int)irq_map[virq].hwirq; |
405 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 407 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
@@ -413,18 +415,21 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
413 | return; | 415 | return; |
414 | } | 416 | } |
415 | 417 | ||
416 | /* For the moment only implement delivery to all cpus or one cpu */ | 418 | /* |
417 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 419 | * For the moment only implement delivery to all cpus or one cpu. |
418 | newmask = default_distrib_server; | 420 | * Get current irq_server for the given irq |
419 | } else { | 421 | */ |
420 | cpus_and(tmp, cpu_online_map, cpumask); | 422 | irq_server = get_irq_server(irq, 1); |
421 | if (cpus_empty(tmp)) | 423 | if (irq_server == -1) { |
422 | return; | 424 | char cpulist[128]; |
423 | newmask = get_hard_smp_processor_id(first_cpu(tmp)); | 425 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); |
426 | printk(KERN_WARNING "xics_set_affinity: No online cpus in " | ||
427 | "the mask %s for irq %d\n", cpulist, virq); | ||
428 | return; | ||
424 | } | 429 | } |
425 | 430 | ||
426 | status = rtas_call(ibm_set_xive, 3, 1, NULL, | 431 | status = rtas_call(ibm_set_xive, 3, 1, NULL, |
427 | irq, newmask, xics_status[1]); | 432 | irq, irq_server, xics_status[1]); |
428 | 433 | ||
429 | if (status) { | 434 | if (status) { |
430 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " | 435 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index c3ce0bd12c0b..f65078c3d3b3 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -5,7 +5,6 @@ endif | |||
5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o | 5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o |
6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) | 6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) |
7 | 7 | ||
8 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | ||
9 | obj-$(CONFIG_PPC_MPC106) += grackle.o | 8 | obj-$(CONFIG_PPC_MPC106) += grackle.o |
10 | obj-$(CONFIG_PPC_DCR) += dcr.o | 9 | obj-$(CONFIG_PPC_DCR) += dcr.o |
11 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o | 10 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o |
@@ -13,16 +12,19 @@ obj-$(CONFIG_PPC_PMI) += pmi.o | |||
13 | obj-$(CONFIG_U3_DART) += dart_iommu.o | 12 | obj-$(CONFIG_U3_DART) += dart_iommu.o |
14 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 13 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
15 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o | 14 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o |
16 | obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o | ||
17 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 15 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
18 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ | 16 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ |
19 | mv64x60-$(CONFIG_PCI) += mv64x60_pci.o | 17 | mv64x60-$(CONFIG_PCI) += mv64x60_pci.o |
20 | obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o | 18 | obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o |
19 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o | ||
21 | 20 | ||
22 | # contains only the suspend handler for time | 21 | # contains only the suspend handler for time |
22 | ifeq ($(CONFIG_RTC_CLASS),) | ||
23 | obj-$(CONFIG_PM) += timer.o | 23 | obj-$(CONFIG_PM) += timer.o |
24 | endif | ||
24 | 25 | ||
25 | ifeq ($(CONFIG_PPC_MERGE),y) | 26 | ifeq ($(CONFIG_PPC_MERGE),y) |
27 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | ||
26 | obj-$(CONFIG_PPC_I8259) += i8259.o | 28 | obj-$(CONFIG_PPC_I8259) += i8259.o |
27 | obj-$(CONFIG_PPC_83xx) += ipic.o | 29 | obj-$(CONFIG_PPC_83xx) += ipic.o |
28 | obj-$(CONFIG_4xx) += uic.o | 30 | obj-$(CONFIG_4xx) += uic.o |
diff --git a/arch/powerpc/sysdev/fsl_pcie.c b/arch/powerpc/sysdev/fsl_pcie.c deleted file mode 100644 index 041c07e8b665..000000000000 --- a/arch/powerpc/sysdev/fsl_pcie.c +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | /* | ||
2 | * Support for indirect PCI bridges. | ||
3 | * | ||
4 | * Copyright (C) 1998 Gabriel Paubert. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * "Temporary" MPC8548 Errata file - | ||
12 | * The standard indirect_pci code should work with future silicon versions. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/bootmem.h> | ||
21 | |||
22 | #include <asm/io.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/pci-bridge.h> | ||
25 | #include <asm/machdep.h> | ||
26 | |||
27 | #define PCI_CFG_OUT out_be32 | ||
28 | |||
29 | /* ERRATA PCI-Ex 14 PCIE Controller timeout */ | ||
30 | #define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) | ||
31 | |||
32 | |||
33 | static int | ||
34 | indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, | ||
35 | int len, u32 *val) | ||
36 | { | ||
37 | struct pci_controller *hose = bus->sysdata; | ||
38 | volatile void __iomem *cfg_data; | ||
39 | u32 temp; | ||
40 | |||
41 | if (ppc_md.pci_exclude_device) | ||
42 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
43 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
44 | |||
45 | /* Possible artifact of CDCpp50937 needs further investigation */ | ||
46 | if (devfn != 0x0 && bus->number == 0xff) | ||
47 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
48 | |||
49 | PCIE_FIX; | ||
50 | if (bus->number == 0xff) { | ||
51 | PCI_CFG_OUT(hose->cfg_addr, | ||
52 | (0x80000000 | ((offset & 0xf00) << 16) | | ||
53 | ((bus->number - hose->bus_offset) << 16) | ||
54 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
55 | } else { | ||
56 | PCI_CFG_OUT(hose->cfg_addr, | ||
57 | (0x80000001 | ((offset & 0xf00) << 16) | | ||
58 | ((bus->number - hose->bus_offset) << 16) | ||
59 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Note: the caller has already checked that offset is | ||
64 | * suitably aligned and that len is 1, 2 or 4. | ||
65 | */ | ||
66 | /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ | ||
67 | cfg_data = hose->cfg_data; | ||
68 | PCIE_FIX; | ||
69 | temp = in_le32(cfg_data); | ||
70 | switch (len) { | ||
71 | case 1: | ||
72 | *val = (temp >> (((offset & 3))*8)) & 0xff; | ||
73 | break; | ||
74 | case 2: | ||
75 | *val = (temp >> (((offset & 3))*8)) & 0xffff; | ||
76 | break; | ||
77 | default: | ||
78 | *val = temp; | ||
79 | break; | ||
80 | } | ||
81 | return PCIBIOS_SUCCESSFUL; | ||
82 | } | ||
83 | |||
84 | static int | ||
85 | indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, | ||
86 | int len, u32 val) | ||
87 | { | ||
88 | struct pci_controller *hose = bus->sysdata; | ||
89 | volatile void __iomem *cfg_data; | ||
90 | u32 temp; | ||
91 | |||
92 | if (ppc_md.pci_exclude_device) | ||
93 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
94 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
95 | |||
96 | /* Possible artifact of CDCpp50937 needs further investigation */ | ||
97 | if (devfn != 0x0 && bus->number == 0xff) | ||
98 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
99 | |||
100 | PCIE_FIX; | ||
101 | if (bus->number == 0xff) { | ||
102 | PCI_CFG_OUT(hose->cfg_addr, | ||
103 | (0x80000000 | ((offset & 0xf00) << 16) | | ||
104 | ((bus->number - hose->bus_offset) << 16) | ||
105 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
106 | } else { | ||
107 | PCI_CFG_OUT(hose->cfg_addr, | ||
108 | (0x80000001 | ((offset & 0xf00) << 16) | | ||
109 | ((bus->number - hose->bus_offset) << 16) | ||
110 | | (devfn << 8) | ((offset & 0xfc) ))); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Note: the caller has already checked that offset is | ||
115 | * suitably aligned and that len is 1, 2 or 4. | ||
116 | */ | ||
117 | /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ | ||
118 | cfg_data = hose->cfg_data; | ||
119 | switch (len) { | ||
120 | case 1: | ||
121 | PCIE_FIX; | ||
122 | temp = in_le32(cfg_data); | ||
123 | temp = (temp & ~(0xff << ((offset & 3) * 8))) | | ||
124 | (val << ((offset & 3) * 8)); | ||
125 | PCIE_FIX; | ||
126 | out_le32(cfg_data, temp); | ||
127 | break; | ||
128 | case 2: | ||
129 | PCIE_FIX; | ||
130 | temp = in_le32(cfg_data); | ||
131 | temp = (temp & ~(0xffff << ((offset & 3) * 8))); | ||
132 | temp |= (val << ((offset & 3) * 8)) ; | ||
133 | PCIE_FIX; | ||
134 | out_le32(cfg_data, temp); | ||
135 | break; | ||
136 | default: | ||
137 | PCIE_FIX; | ||
138 | out_le32(cfg_data, val); | ||
139 | break; | ||
140 | } | ||
141 | PCIE_FIX; | ||
142 | return PCIBIOS_SUCCESSFUL; | ||
143 | } | ||
144 | |||
145 | static struct pci_ops indirect_pcie_ops = { | ||
146 | indirect_read_config_pcie, | ||
147 | indirect_write_config_pcie | ||
148 | }; | ||
149 | |||
150 | void __init | ||
151 | setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr, | ||
152 | void __iomem * cfg_data) | ||
153 | { | ||
154 | hose->cfg_addr = cfg_addr; | ||
155 | hose->cfg_data = cfg_data; | ||
156 | hose->ops = &indirect_pcie_ops; | ||
157 | } | ||
158 | |||
159 | void __init | ||
160 | setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) | ||
161 | { | ||
162 | unsigned long base = cfg_addr & PAGE_MASK; | ||
163 | void __iomem *mbase, *addr, *data; | ||
164 | |||
165 | mbase = ioremap(base, PAGE_SIZE); | ||
166 | addr = mbase + (cfg_addr & ~PAGE_MASK); | ||
167 | if ((cfg_data & PAGE_MASK) != base) | ||
168 | mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); | ||
169 | data = mbase + (cfg_data & ~PAGE_MASK); | ||
170 | setup_indirect_pcie_nomap(hose, addr, data); | ||
171 | } | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index cad175724359..3289fab01e92 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -197,6 +197,7 @@ static int __init gfar_of_init(void) | |||
197 | struct gianfar_platform_data gfar_data; | 197 | struct gianfar_platform_data gfar_data; |
198 | const unsigned int *id; | 198 | const unsigned int *id; |
199 | const char *model; | 199 | const char *model; |
200 | const char *ctype; | ||
200 | const void *mac_addr; | 201 | const void *mac_addr; |
201 | const phandle *ph; | 202 | const phandle *ph; |
202 | int n_res = 2; | 203 | int n_res = 2; |
@@ -254,6 +255,14 @@ static int __init gfar_of_init(void) | |||
254 | FSL_GIANFAR_DEV_HAS_VLAN | | 255 | FSL_GIANFAR_DEV_HAS_VLAN | |
255 | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; | 256 | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; |
256 | 257 | ||
258 | ctype = of_get_property(np, "phy-connection-type", NULL); | ||
259 | |||
260 | /* We only care about rgmii-id. The rest are autodetected */ | ||
261 | if (ctype && !strcmp(ctype, "rgmii-id")) | ||
262 | gfar_data.interface = PHY_INTERFACE_MODE_RGMII_ID; | ||
263 | else | ||
264 | gfar_data.interface = PHY_INTERFACE_MODE_MII; | ||
265 | |||
257 | ph = of_get_property(np, "phy-handle", NULL); | 266 | ph = of_get_property(np, "phy-handle", NULL); |
258 | phy = of_find_node_by_phandle(*ph); | 267 | phy = of_find_node_by_phandle(*ph); |
259 | 268 | ||
@@ -1028,6 +1037,19 @@ err: | |||
1028 | 1037 | ||
1029 | arch_initcall(fs_enet_of_init); | 1038 | arch_initcall(fs_enet_of_init); |
1030 | 1039 | ||
1040 | static int __init fsl_pcmcia_of_init(void) | ||
1041 | { | ||
1042 | struct device_node *np = NULL; | ||
1043 | /* | ||
1044 | * Register all the devices which type is "pcmcia" | ||
1045 | */ | ||
1046 | while ((np = of_find_compatible_node(np, | ||
1047 | "pcmcia", "fsl,pq-pcmcia")) != NULL) | ||
1048 | of_platform_device_create(np, "m8xx-pcmcia", NULL); | ||
1049 | return 0; | ||
1050 | } | ||
1051 | |||
1052 | arch_initcall(fsl_pcmcia_of_init); | ||
1031 | 1053 | ||
1032 | static const char *smc_regs = "regs"; | 1054 | static const char *smc_regs = "regs"; |
1033 | static const char *smc_pram = "pram"; | 1055 | static const char *smc_pram = "pram"; |
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c index e71488469704..c7e6e859b393 100644 --- a/arch/powerpc/sysdev/indirect_pci.c +++ b/arch/powerpc/sysdev/indirect_pci.c | |||
@@ -33,18 +33,27 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
33 | struct pci_controller *hose = bus->sysdata; | 33 | struct pci_controller *hose = bus->sysdata; |
34 | volatile void __iomem *cfg_data; | 34 | volatile void __iomem *cfg_data; |
35 | u8 cfg_type = 0; | 35 | u8 cfg_type = 0; |
36 | u32 bus_no, reg; | ||
36 | 37 | ||
37 | if (ppc_md.pci_exclude_device) | 38 | if (ppc_md.pci_exclude_device) |
38 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 39 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
39 | return PCIBIOS_DEVICE_NOT_FOUND; | 40 | return PCIBIOS_DEVICE_NOT_FOUND; |
40 | 41 | ||
41 | if (hose->set_cfg_type) | 42 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) |
42 | if (bus->number != hose->first_busno) | 43 | if (bus->number != hose->first_busno) |
43 | cfg_type = 1; | 44 | cfg_type = 1; |
44 | 45 | ||
45 | PCI_CFG_OUT(hose->cfg_addr, | 46 | bus_no = (bus->number == hose->first_busno) ? |
46 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | 47 | hose->self_busno : bus->number; |
47 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | 48 | |
49 | if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG) | ||
50 | reg = ((offset & 0xf00) << 16) | (offset & 0xfc); | ||
51 | else | ||
52 | reg = offset & 0xfc; | ||
53 | |||
54 | PCI_CFG_OUT(hose->cfg_addr, | ||
55 | (0x80000000 | (bus_no << 16) | ||
56 | | (devfn << 8) | reg | cfg_type)); | ||
48 | 57 | ||
49 | /* | 58 | /* |
50 | * Note: the caller has already checked that offset is | 59 | * Note: the caller has already checked that offset is |
@@ -72,18 +81,33 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
72 | struct pci_controller *hose = bus->sysdata; | 81 | struct pci_controller *hose = bus->sysdata; |
73 | volatile void __iomem *cfg_data; | 82 | volatile void __iomem *cfg_data; |
74 | u8 cfg_type = 0; | 83 | u8 cfg_type = 0; |
84 | u32 bus_no, reg; | ||
75 | 85 | ||
76 | if (ppc_md.pci_exclude_device) | 86 | if (ppc_md.pci_exclude_device) |
77 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 87 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
78 | return PCIBIOS_DEVICE_NOT_FOUND; | 88 | return PCIBIOS_DEVICE_NOT_FOUND; |
79 | 89 | ||
80 | if (hose->set_cfg_type) | 90 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) |
81 | if (bus->number != hose->first_busno) | 91 | if (bus->number != hose->first_busno) |
82 | cfg_type = 1; | 92 | cfg_type = 1; |
83 | 93 | ||
84 | PCI_CFG_OUT(hose->cfg_addr, | 94 | bus_no = (bus->number == hose->first_busno) ? |
85 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | 95 | hose->self_busno : bus->number; |
86 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | 96 | |
97 | if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG) | ||
98 | reg = ((offset & 0xf00) << 16) | (offset & 0xfc); | ||
99 | else | ||
100 | reg = offset & 0xfc; | ||
101 | |||
102 | PCI_CFG_OUT(hose->cfg_addr, | ||
103 | (0x80000000 | (bus_no << 16) | ||
104 | | (devfn << 8) | reg | cfg_type)); | ||
105 | |||
106 | /* surpress setting of PCI_PRIMARY_BUS */ | ||
107 | if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) | ||
108 | if ((offset == PCI_PRIMARY_BUS) && | ||
109 | (bus->number == hose->first_busno)) | ||
110 | val &= 0xffffff00; | ||
87 | 111 | ||
88 | /* | 112 | /* |
89 | * Note: the caller has already checked that offset is | 113 | * Note: the caller has already checked that offset is |
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h index afa2ee6717c1..9fe00eebdc8b 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.h +++ b/arch/powerpc/sysdev/mpc8xx_pic.h | |||
@@ -4,9 +4,16 @@ | |||
4 | #include <linux/irq.h> | 4 | #include <linux/irq.h> |
5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | 6 | ||
7 | extern struct hw_interrupt_type mpc8xx_pic; | ||
8 | |||
9 | int mpc8xx_pic_init(void); | 7 | int mpc8xx_pic_init(void); |
10 | unsigned int mpc8xx_get_irq(void); | 8 | unsigned int mpc8xx_get_irq(void); |
11 | 9 | ||
10 | /* | ||
11 | * Some internal interrupt registers use an 8-bit mask for the interrupt | ||
12 | * level instead of a number. | ||
13 | */ | ||
14 | static inline uint mk_int_int_mask(uint mask) | ||
15 | { | ||
16 | return (1 << (7 - (mask/2))); | ||
17 | } | ||
18 | |||
12 | #endif /* _PPC_KERNEL_PPC8xx_H */ | 19 | #endif /* _PPC_KERNEL_PPC8xx_H */ |
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 4b0a9c88eeb3..b618fa60aef3 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/stddef.h> | 12 | #include <linux/stddef.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/console.h> | ||
15 | #include <linux/mv643xx.h> | 16 | #include <linux/mv643xx.h> |
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
17 | 18 | ||
@@ -420,3 +421,30 @@ error: | |||
420 | return err; | 421 | return err; |
421 | } | 422 | } |
422 | arch_initcall(mv64x60_device_setup); | 423 | arch_initcall(mv64x60_device_setup); |
424 | |||
425 | static int __init mv64x60_add_mpsc_console(void) | ||
426 | { | ||
427 | struct device_node *np = NULL; | ||
428 | const char *prop; | ||
429 | |||
430 | prop = of_get_property(of_chosen, "linux,stdout-path", NULL); | ||
431 | if (prop == NULL) | ||
432 | goto not_mpsc; | ||
433 | |||
434 | np = of_find_node_by_path(prop); | ||
435 | if (!np) | ||
436 | goto not_mpsc; | ||
437 | |||
438 | if (!of_device_is_compatible(np, "marvell,mpsc")) | ||
439 | goto not_mpsc; | ||
440 | |||
441 | prop = of_get_property(np, "block-index", NULL); | ||
442 | if (!prop) | ||
443 | goto not_mpsc; | ||
444 | |||
445 | add_preferred_console("ttyMM", *(int *)prop, NULL); | ||
446 | |||
447 | not_mpsc: | ||
448 | return 0; | ||
449 | } | ||
450 | console_initcall(mv64x60_add_mpsc_console); | ||
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index b5aef4cbc8d2..45db86c2363c 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c | |||
@@ -137,18 +137,15 @@ static int __init mv64x60_add_bridge(struct device_node *dev) | |||
137 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 137 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
138 | " bus 0\n", dev->full_name); | 138 | " bus 0\n", dev->full_name); |
139 | 139 | ||
140 | hose = pcibios_alloc_controller(); | 140 | hose = pcibios_alloc_controller(dev); |
141 | if (!hose) | 141 | if (!hose) |
142 | return -ENOMEM; | 142 | return -ENOMEM; |
143 | 143 | ||
144 | hose->arch_data = dev; | ||
145 | hose->set_cfg_type = 1; | ||
146 | |||
147 | hose->first_busno = bus_range ? bus_range[0] : 0; | 144 | hose->first_busno = bus_range ? bus_range[0] : 0; |
148 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 145 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
149 | 146 | ||
150 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 4); | 147 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 4); |
151 | hose->bus_offset = hose->first_busno; | 148 | hose->self_busno = hose->first_busno; |
152 | 149 | ||
153 | printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. " | 150 | printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. " |
154 | "Firmware bus number: %d->%d\n", | 151 | "Firmware bus number: %d->%d\n", |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c index ac12a44d516f..f970e5415ac0 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc.c +++ b/arch/powerpc/sysdev/qe_lib/ucc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
21 | #include <linux/module.h> | ||
21 | 22 | ||
22 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
@@ -40,6 +41,7 @@ int ucc_set_qe_mux_mii_mng(int ucc_num) | |||
40 | 41 | ||
41 | return 0; | 42 | return 0; |
42 | } | 43 | } |
44 | EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng); | ||
43 | 45 | ||
44 | int ucc_set_type(int ucc_num, struct ucc_common *regs, | 46 | int ucc_set_type(int ucc_num, struct ucc_common *regs, |
45 | enum ucc_speed_type speed) | 47 | enum ucc_speed_type speed) |
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c index 9143236853fc..3df202e8d332 100644 --- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/module.h> | ||
22 | 23 | ||
23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
24 | #include <asm/immap_qe.h> | 25 | #include <asm/immap_qe.h> |
@@ -70,6 +71,7 @@ void ucc_fast_dump_regs(struct ucc_fast_private * uccf) | |||
70 | printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x", | 71 | printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x", |
71 | (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr); | 72 | (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr); |
72 | } | 73 | } |
74 | EXPORT_SYMBOL(ucc_fast_dump_regs); | ||
73 | 75 | ||
74 | u32 ucc_fast_get_qe_cr_subblock(int uccf_num) | 76 | u32 ucc_fast_get_qe_cr_subblock(int uccf_num) |
75 | { | 77 | { |
@@ -85,11 +87,13 @@ u32 ucc_fast_get_qe_cr_subblock(int uccf_num) | |||
85 | default: return QE_CR_SUBBLOCK_INVALID; | 87 | default: return QE_CR_SUBBLOCK_INVALID; |
86 | } | 88 | } |
87 | } | 89 | } |
90 | EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock); | ||
88 | 91 | ||
89 | void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf) | 92 | void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf) |
90 | { | 93 | { |
91 | out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD); | 94 | out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD); |
92 | } | 95 | } |
96 | EXPORT_SYMBOL(ucc_fast_transmit_on_demand); | ||
93 | 97 | ||
94 | void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) | 98 | void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) |
95 | { | 99 | { |
@@ -110,6 +114,7 @@ void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) | |||
110 | } | 114 | } |
111 | out_be32(&uf_regs->gumr, gumr); | 115 | out_be32(&uf_regs->gumr, gumr); |
112 | } | 116 | } |
117 | EXPORT_SYMBOL(ucc_fast_enable); | ||
113 | 118 | ||
114 | void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) | 119 | void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) |
115 | { | 120 | { |
@@ -130,6 +135,7 @@ void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) | |||
130 | } | 135 | } |
131 | out_be32(&uf_regs->gumr, gumr); | 136 | out_be32(&uf_regs->gumr, gumr); |
132 | } | 137 | } |
138 | EXPORT_SYMBOL(ucc_fast_disable); | ||
133 | 139 | ||
134 | int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret) | 140 | int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret) |
135 | { | 141 | { |
@@ -341,6 +347,7 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc | |||
341 | *uccf_ret = uccf; | 347 | *uccf_ret = uccf; |
342 | return 0; | 348 | return 0; |
343 | } | 349 | } |
350 | EXPORT_SYMBOL(ucc_fast_init); | ||
344 | 351 | ||
345 | void ucc_fast_free(struct ucc_fast_private * uccf) | 352 | void ucc_fast_free(struct ucc_fast_private * uccf) |
346 | { | 353 | { |
@@ -355,3 +362,4 @@ void ucc_fast_free(struct ucc_fast_private * uccf) | |||
355 | 362 | ||
356 | kfree(uccf); | 363 | kfree(uccf); |
357 | } | 364 | } |
365 | EXPORT_SYMBOL(ucc_fast_free); | ||
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c new file mode 100644 index 000000000000..e276048b8c5f --- /dev/null +++ b/arch/powerpc/sysdev/rtc_cmos_setup.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Setup code for PC-style Real-Time Clock. | ||
3 | * | ||
4 | * Author: Wade Farnsworth <wfarnsworth@mvista.com> | ||
5 | * | ||
6 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/mc146818rtc.h> | ||
16 | |||
17 | #include <asm/prom.h> | ||
18 | |||
19 | static int __init add_rtc(void) | ||
20 | { | ||
21 | struct device_node *np; | ||
22 | struct platform_device *pd; | ||
23 | struct resource res; | ||
24 | int ret; | ||
25 | |||
26 | np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00"); | ||
27 | if (!np) | ||
28 | return -ENODEV; | ||
29 | |||
30 | ret = of_address_to_resource(np, 0, &res); | ||
31 | of_node_put(np); | ||
32 | if (ret) | ||
33 | return ret; | ||
34 | |||
35 | /* | ||
36 | * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h. Verify that the | ||
37 | * address provided by the device node matches. | ||
38 | */ | ||
39 | if (res.start != RTC_PORT(0)) | ||
40 | return -EINVAL; | ||
41 | |||
42 | pd = platform_device_register_simple("rtc_cmos", -1, | ||
43 | &res, 1); | ||
44 | if (IS_ERR(pd)) | ||
45 | return PTR_ERR(pd); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | fs_initcall(add_rtc); | ||
diff --git a/arch/powerpc/sysdev/timer.c b/arch/powerpc/sysdev/timer.c index 4a01748b4217..e81e7ec2e799 100644 --- a/arch/powerpc/sysdev/timer.c +++ b/arch/powerpc/sysdev/timer.c | |||
@@ -24,7 +24,12 @@ static int timer_resume(struct sys_device *dev) | |||
24 | 24 | ||
25 | /* get current RTC time and convert to seconds */ | 25 | /* get current RTC time and convert to seconds */ |
26 | get_rtc_time(&cur_rtc_tm); | 26 | get_rtc_time(&cur_rtc_tm); |
27 | rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time); | 27 | cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900, |
28 | cur_rtc_tm.tm_mon + 1, | ||
29 | cur_rtc_tm.tm_mday, | ||
30 | cur_rtc_tm.tm_hour, | ||
31 | cur_rtc_tm.tm_min, | ||
32 | cur_rtc_tm.tm_sec); | ||
28 | 33 | ||
29 | diff = cur_rtc_time - suspend_rtc_time; | 34 | diff = cur_rtc_time - suspend_rtc_time; |
30 | 35 | ||
@@ -44,7 +49,12 @@ static int timer_suspend(struct sys_device *dev, pm_message_t state) | |||
44 | WARN_ON(!ppc_md.get_rtc_time); | 49 | WARN_ON(!ppc_md.get_rtc_time); |
45 | 50 | ||
46 | get_rtc_time(&suspend_rtc_tm); | 51 | get_rtc_time(&suspend_rtc_tm); |
47 | rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time); | 52 | suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900, |
53 | suspend_rtc_tm.tm_mon + 1, | ||
54 | suspend_rtc_tm.tm_mday, | ||
55 | suspend_rtc_tm.tm_hour, | ||
56 | suspend_rtc_tm.tm_min, | ||
57 | suspend_rtc_tm.tm_sec); | ||
48 | 58 | ||
49 | return 0; | 59 | return 0; |
50 | } | 60 | } |
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c index 7d3b09b7d544..a113d800cbf0 100644 --- a/arch/powerpc/sysdev/tsi108_dev.c +++ b/arch/powerpc/sysdev/tsi108_dev.c | |||
@@ -72,12 +72,11 @@ static int __init tsi108_eth_of_init(void) | |||
72 | int ret; | 72 | int ret; |
73 | 73 | ||
74 | for (np = NULL, i = 0; | 74 | for (np = NULL, i = 0; |
75 | (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL; | 75 | (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL; |
76 | i++) { | 76 | i++) { |
77 | struct resource r[2]; | 77 | struct resource r[2]; |
78 | struct device_node *phy; | 78 | struct device_node *phy, *mdio; |
79 | hw_info tsi_eth_data; | 79 | hw_info tsi_eth_data; |
80 | const unsigned int *id; | ||
81 | const unsigned int *phy_id; | 80 | const unsigned int *phy_id; |
82 | const void *mac_addr; | 81 | const void *mac_addr; |
83 | const phandle *ph; | 82 | const phandle *ph; |
@@ -111,6 +110,13 @@ static int __init tsi108_eth_of_init(void) | |||
111 | if (mac_addr) | 110 | if (mac_addr) |
112 | memcpy(tsi_eth_data.mac_addr, mac_addr, 6); | 111 | memcpy(tsi_eth_data.mac_addr, mac_addr, 6); |
113 | 112 | ||
113 | ph = of_get_property(np, "mdio-handle", NULL); | ||
114 | mdio = of_find_node_by_phandle(*ph); | ||
115 | ret = of_address_to_resource(mdio, 0, &res); | ||
116 | of_node_put(mdio); | ||
117 | if (ret) | ||
118 | goto unreg; | ||
119 | |||
114 | ph = of_get_property(np, "phy-handle", NULL); | 120 | ph = of_get_property(np, "phy-handle", NULL); |
115 | phy = of_find_node_by_phandle(*ph); | 121 | phy = of_find_node_by_phandle(*ph); |
116 | 122 | ||
@@ -119,20 +125,25 @@ static int __init tsi108_eth_of_init(void) | |||
119 | goto unreg; | 125 | goto unreg; |
120 | } | 126 | } |
121 | 127 | ||
122 | id = of_get_property(phy, "reg", NULL); | 128 | phy_id = of_get_property(phy, "reg", NULL); |
123 | phy_id = of_get_property(phy, "phy-id", NULL); | 129 | |
124 | ret = of_address_to_resource(phy, 0, &res); | ||
125 | if (ret) { | ||
126 | of_node_put(phy); | ||
127 | goto unreg; | ||
128 | } | ||
129 | tsi_eth_data.regs = r[0].start; | 130 | tsi_eth_data.regs = r[0].start; |
130 | tsi_eth_data.phyregs = res.start; | 131 | tsi_eth_data.phyregs = res.start; |
131 | tsi_eth_data.phy = *phy_id; | 132 | tsi_eth_data.phy = *phy_id; |
132 | tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); | 133 | tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); |
133 | if (of_device_is_compatible(phy, "bcm54xx")) | 134 | |
135 | /* Some boards with the TSI108 bridge (e.g. Holly) | ||
136 | * have a miswiring of the ethernet PHYs which | ||
137 | * requires a workaround. The special | ||
138 | * "txc-rxc-delay-disable" property enables this | ||
139 | * workaround. FIXME: Need to port the tsi108_eth | ||
140 | * driver itself to phylib and use a non-misleading | ||
141 | * name for the workaround flag - it's not actually to | ||
142 | * do with the model of PHY in use */ | ||
143 | if (of_get_property(phy, "txc-rxc-delay-disable", NULL)) | ||
134 | tsi_eth_data.phy_type = TSI108_PHY_BCM54XX; | 144 | tsi_eth_data.phy_type = TSI108_PHY_BCM54XX; |
135 | of_node_put(phy); | 145 | of_node_put(phy); |
146 | |||
136 | ret = | 147 | ret = |
137 | platform_device_add_data(tsi_eth_dev, &tsi_eth_data, | 148 | platform_device_add_data(tsi_eth_dev, &tsi_eth_data, |
138 | sizeof(hw_info)); | 149 | sizeof(hw_info)); |
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 2153163fa593..90db8a720fed 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c | |||
@@ -64,9 +64,10 @@ tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc, | |||
64 | int offset, int len, u32 val) | 64 | int offset, int len, u32 val) |
65 | { | 65 | { |
66 | volatile unsigned char *cfg_addr; | 66 | volatile unsigned char *cfg_addr; |
67 | struct pci_controller *hose = bus->sysdata; | ||
67 | 68 | ||
68 | if (ppc_md.pci_exclude_device) | 69 | if (ppc_md.pci_exclude_device) |
69 | if (ppc_md.pci_exclude_device(bus->number, devfunc)) | 70 | if (ppc_md.pci_exclude_device(hose, bus->number, devfunc)) |
70 | return PCIBIOS_DEVICE_NOT_FOUND; | 71 | return PCIBIOS_DEVICE_NOT_FOUND; |
71 | 72 | ||
72 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, | 73 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, |
@@ -149,10 +150,11 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
149 | int len, u32 * val) | 150 | int len, u32 * val) |
150 | { | 151 | { |
151 | volatile unsigned char *cfg_addr; | 152 | volatile unsigned char *cfg_addr; |
153 | struct pci_controller *hose = bus->sysdata; | ||
152 | u32 temp; | 154 | u32 temp; |
153 | 155 | ||
154 | if (ppc_md.pci_exclude_device) | 156 | if (ppc_md.pci_exclude_device) |
155 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | 157 | if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) |
156 | return PCIBIOS_DEVICE_NOT_FOUND; | 158 | return PCIBIOS_DEVICE_NOT_FOUND; |
157 | 159 | ||
158 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, | 160 | cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, |
@@ -219,14 +221,12 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary) | |||
219 | " bus 0\n", dev->full_name); | 221 | " bus 0\n", dev->full_name); |
220 | } | 222 | } |
221 | 223 | ||
222 | hose = pcibios_alloc_controller(); | 224 | hose = pcibios_alloc_controller(dev); |
223 | 225 | ||
224 | if (!hose) { | 226 | if (!hose) { |
225 | printk("PCI Host bridge init failed\n"); | 227 | printk("PCI Host bridge init failed\n"); |
226 | return -ENOMEM; | 228 | return -ENOMEM; |
227 | } | 229 | } |
228 | hose->arch_data = dev; | ||
229 | hose->set_cfg_type = 1; | ||
230 | 230 | ||
231 | hose->first_busno = bus_range ? bus_range[0] : 0; | 231 | hose->first_busno = bus_range ? bus_range[0] : 0; |
232 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 232 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 28fdf4f50c27..669e6566ad70 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -2634,7 +2634,7 @@ static int __init setup_xmon_sysrq(void) | |||
2634 | __initcall(setup_xmon_sysrq); | 2634 | __initcall(setup_xmon_sysrq); |
2635 | #endif /* CONFIG_MAGIC_SYSRQ */ | 2635 | #endif /* CONFIG_MAGIC_SYSRQ */ |
2636 | 2636 | ||
2637 | int __initdata xmon_early, xmon_off; | 2637 | static int __initdata xmon_early, xmon_off; |
2638 | 2638 | ||
2639 | static int __init early_parse_xmon(char *p) | 2639 | static int __init early_parse_xmon(char *p) |
2640 | { | 2640 | { |
diff --git a/arch/ppc/configs/ev64260_defconfig b/arch/ppc/configs/ev64260_defconfig index 84cc142a67bb..587e9a3b9491 100644 --- a/arch/ppc/configs/ev64260_defconfig +++ b/arch/ppc/configs/ev64260_defconfig | |||
@@ -531,7 +531,6 @@ CONFIG_I2C_CHARDEV=m | |||
531 | # CONFIG_I2C_AMD8111 is not set | 531 | # CONFIG_I2C_AMD8111 is not set |
532 | # CONFIG_I2C_I801 is not set | 532 | # CONFIG_I2C_I801 is not set |
533 | # CONFIG_I2C_I810 is not set | 533 | # CONFIG_I2C_I810 is not set |
534 | # CONFIG_I2C_ISA is not set | ||
535 | # CONFIG_I2C_NFORCE2 is not set | 534 | # CONFIG_I2C_NFORCE2 is not set |
536 | # CONFIG_I2C_PARPORT_LIGHT is not set | 535 | # CONFIG_I2C_PARPORT_LIGHT is not set |
537 | # CONFIG_I2C_PIIX4 is not set | 536 | # CONFIG_I2C_PIIX4 is not set |
diff --git a/arch/ppc/configs/mpc8540_ads_defconfig b/arch/ppc/configs/mpc8540_ads_defconfig index c5c86025e261..bf676ebd99ab 100644 --- a/arch/ppc/configs/mpc8540_ads_defconfig +++ b/arch/ppc/configs/mpc8540_ads_defconfig | |||
@@ -452,7 +452,6 @@ CONFIG_I2C_CHARDEV=y | |||
452 | # CONFIG_I2C_AMD8111 is not set | 452 | # CONFIG_I2C_AMD8111 is not set |
453 | # CONFIG_I2C_I801 is not set | 453 | # CONFIG_I2C_I801 is not set |
454 | # CONFIG_I2C_I810 is not set | 454 | # CONFIG_I2C_I810 is not set |
455 | # CONFIG_I2C_ISA is not set | ||
456 | CONFIG_I2C_MPC=y | 455 | CONFIG_I2C_MPC=y |
457 | # CONFIG_I2C_NFORCE2 is not set | 456 | # CONFIG_I2C_NFORCE2 is not set |
458 | # CONFIG_I2C_PARPORT_LIGHT is not set | 457 | # CONFIG_I2C_PARPORT_LIGHT is not set |
diff --git a/arch/ppc/configs/mpc8548_cds_defconfig b/arch/ppc/configs/mpc8548_cds_defconfig index abe034f24b83..f36fc5db540b 100644 --- a/arch/ppc/configs/mpc8548_cds_defconfig +++ b/arch/ppc/configs/mpc8548_cds_defconfig | |||
@@ -413,7 +413,6 @@ CONFIG_I2C_CHARDEV=y | |||
413 | # | 413 | # |
414 | # I2C Hardware Bus support | 414 | # I2C Hardware Bus support |
415 | # | 415 | # |
416 | # CONFIG_I2C_ISA is not set | ||
417 | CONFIG_I2C_MPC=y | 416 | CONFIG_I2C_MPC=y |
418 | # CONFIG_I2C_PARPORT_LIGHT is not set | 417 | # CONFIG_I2C_PARPORT_LIGHT is not set |
419 | # CONFIG_I2C_PCA_ISA is not set | 418 | # CONFIG_I2C_PCA_ISA is not set |
diff --git a/arch/ppc/configs/mpc8555_cds_defconfig b/arch/ppc/configs/mpc8555_cds_defconfig index 15abebf46b96..4f1e320acfbe 100644 --- a/arch/ppc/configs/mpc8555_cds_defconfig +++ b/arch/ppc/configs/mpc8555_cds_defconfig | |||
@@ -518,7 +518,6 @@ CONFIG_I2C_CHARDEV=y | |||
518 | # CONFIG_I2C_I801 is not set | 518 | # CONFIG_I2C_I801 is not set |
519 | # CONFIG_I2C_I810 is not set | 519 | # CONFIG_I2C_I810 is not set |
520 | # CONFIG_I2C_PIIX4 is not set | 520 | # CONFIG_I2C_PIIX4 is not set |
521 | # CONFIG_I2C_ISA is not set | ||
522 | CONFIG_I2C_MPC=y | 521 | CONFIG_I2C_MPC=y |
523 | # CONFIG_I2C_NFORCE2 is not set | 522 | # CONFIG_I2C_NFORCE2 is not set |
524 | # CONFIG_I2C_PARPORT_LIGHT is not set | 523 | # CONFIG_I2C_PARPORT_LIGHT is not set |
diff --git a/arch/ppc/configs/mpc8560_ads_defconfig b/arch/ppc/configs/mpc8560_ads_defconfig index f834fb541ad5..f12d48fcbba7 100644 --- a/arch/ppc/configs/mpc8560_ads_defconfig +++ b/arch/ppc/configs/mpc8560_ads_defconfig | |||
@@ -489,7 +489,6 @@ CONFIG_I2C_CHARDEV=y | |||
489 | # CONFIG_I2C_I801 is not set | 489 | # CONFIG_I2C_I801 is not set |
490 | # CONFIG_I2C_I810 is not set | 490 | # CONFIG_I2C_I810 is not set |
491 | # CONFIG_I2C_PIIX4 is not set | 491 | # CONFIG_I2C_PIIX4 is not set |
492 | # CONFIG_I2C_ISA is not set | ||
493 | CONFIG_I2C_MPC=y | 492 | CONFIG_I2C_MPC=y |
494 | # CONFIG_I2C_NFORCE2 is not set | 493 | # CONFIG_I2C_NFORCE2 is not set |
495 | # CONFIG_I2C_PARPORT_LIGHT is not set | 494 | # CONFIG_I2C_PARPORT_LIGHT is not set |
diff --git a/arch/ppc/configs/radstone_ppc7d_defconfig b/arch/ppc/configs/radstone_ppc7d_defconfig index ca4d1fd0ca05..9f64532f2a81 100644 --- a/arch/ppc/configs/radstone_ppc7d_defconfig +++ b/arch/ppc/configs/radstone_ppc7d_defconfig | |||
@@ -710,7 +710,6 @@ CONFIG_I2C_CHARDEV=y | |||
710 | # CONFIG_I2C_I801 is not set | 710 | # CONFIG_I2C_I801 is not set |
711 | # CONFIG_I2C_I810 is not set | 711 | # CONFIG_I2C_I810 is not set |
712 | # CONFIG_I2C_PIIX4 is not set | 712 | # CONFIG_I2C_PIIX4 is not set |
713 | # CONFIG_I2C_ISA is not set | ||
714 | # CONFIG_I2C_MPC is not set | 713 | # CONFIG_I2C_MPC is not set |
715 | # CONFIG_I2C_NFORCE2 is not set | 714 | # CONFIG_I2C_NFORCE2 is not set |
716 | # CONFIG_I2C_PARPORT_LIGHT is not set | 715 | # CONFIG_I2C_PARPORT_LIGHT is not set |
diff --git a/arch/ppc/configs/stx_gp3_defconfig b/arch/ppc/configs/stx_gp3_defconfig index 3fedc43e44ad..70d6f842aa9b 100644 --- a/arch/ppc/configs/stx_gp3_defconfig +++ b/arch/ppc/configs/stx_gp3_defconfig | |||
@@ -661,7 +661,6 @@ CONFIG_I2C_ALGOBIT=m | |||
661 | # CONFIG_I2C_I801 is not set | 661 | # CONFIG_I2C_I801 is not set |
662 | # CONFIG_I2C_I810 is not set | 662 | # CONFIG_I2C_I810 is not set |
663 | # CONFIG_I2C_PIIX4 is not set | 663 | # CONFIG_I2C_PIIX4 is not set |
664 | # CONFIG_I2C_ISA is not set | ||
665 | # CONFIG_I2C_MPC is not set | 664 | # CONFIG_I2C_MPC is not set |
666 | # CONFIG_I2C_NFORCE2 is not set | 665 | # CONFIG_I2C_NFORCE2 is not set |
667 | # CONFIG_I2C_PARPORT is not set | 666 | # CONFIG_I2C_PARPORT is not set |
diff --git a/arch/ppc/configs/sycamore_defconfig b/arch/ppc/configs/sycamore_defconfig index 758114cfea5c..6996cca18f3e 100644 --- a/arch/ppc/configs/sycamore_defconfig +++ b/arch/ppc/configs/sycamore_defconfig | |||
@@ -461,7 +461,6 @@ CONFIG_I2C_CHARDEV=y | |||
461 | # CONFIG_I2C_I801 is not set | 461 | # CONFIG_I2C_I801 is not set |
462 | # CONFIG_I2C_I810 is not set | 462 | # CONFIG_I2C_I810 is not set |
463 | # CONFIG_I2C_IBM_IIC is not set | 463 | # CONFIG_I2C_IBM_IIC is not set |
464 | # CONFIG_I2C_ISA is not set | ||
465 | # CONFIG_I2C_NFORCE2 is not set | 464 | # CONFIG_I2C_NFORCE2 is not set |
466 | # CONFIG_I2C_PARPORT_LIGHT is not set | 465 | # CONFIG_I2C_PARPORT_LIGHT is not set |
467 | # CONFIG_I2C_PIIX4 is not set | 466 | # CONFIG_I2C_PIIX4 is not set |
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index d319f9ba2379..0da55368655c 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S | |||
@@ -328,7 +328,7 @@ BEGIN_FTR_SECTION | |||
328 | mtspr SPRN_L1CSR0,r3 | 328 | mtspr SPRN_L1CSR0,r3 |
329 | isync | 329 | isync |
330 | blr | 330 | blr |
331 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 331 | END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) |
332 | mfspr r3,SPRN_L1CSR1 | 332 | mfspr r3,SPRN_L1CSR1 |
333 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR | 333 | ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR |
334 | mtspr SPRN_L1CSR1,r3 | 334 | mtspr SPRN_L1CSR1,r3 |
@@ -355,7 +355,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
355 | _GLOBAL(__flush_icache_range) | 355 | _GLOBAL(__flush_icache_range) |
356 | BEGIN_FTR_SECTION | 356 | BEGIN_FTR_SECTION |
357 | blr /* for 601, do nothing */ | 357 | blr /* for 601, do nothing */ |
358 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 358 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
359 | li r5,L1_CACHE_BYTES-1 | 359 | li r5,L1_CACHE_BYTES-1 |
360 | andc r3,r3,r5 | 360 | andc r3,r3,r5 |
361 | subf r4,r3,r4 | 361 | subf r4,r3,r4 |
@@ -472,7 +472,7 @@ _GLOBAL(flush_dcache_all) | |||
472 | _GLOBAL(__flush_dcache_icache) | 472 | _GLOBAL(__flush_dcache_icache) |
473 | BEGIN_FTR_SECTION | 473 | BEGIN_FTR_SECTION |
474 | blr /* for 601, do nothing */ | 474 | blr /* for 601, do nothing */ |
475 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 475 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
476 | rlwinm r3,r3,0,0,19 /* Get page base address */ | 476 | rlwinm r3,r3,0,0,19 /* Get page base address */ |
477 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ | 477 | li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ |
478 | mtctr r4 | 478 | mtctr r4 |
@@ -500,7 +500,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | |||
500 | _GLOBAL(__flush_dcache_icache_phys) | 500 | _GLOBAL(__flush_dcache_icache_phys) |
501 | BEGIN_FTR_SECTION | 501 | BEGIN_FTR_SECTION |
502 | blr /* for 601, do nothing */ | 502 | blr /* for 601, do nothing */ |
503 | END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) | 503 | END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) |
504 | mfmsr r10 | 504 | mfmsr r10 |
505 | rlwinm r0,r10,0,28,26 /* clear DR */ | 505 | rlwinm r0,r10,0,28,26 /* clear DR */ |
506 | mtmsr r0 | 506 | mtmsr r0 |
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index a4165209ac7c..63f0a987139b 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c | |||
@@ -64,7 +64,6 @@ extern unsigned long mm_ptov (unsigned long paddr); | |||
64 | 64 | ||
65 | EXPORT_SYMBOL(clear_pages); | 65 | EXPORT_SYMBOL(clear_pages); |
66 | EXPORT_SYMBOL(clear_user_page); | 66 | EXPORT_SYMBOL(clear_user_page); |
67 | EXPORT_SYMBOL(do_signal); | ||
68 | EXPORT_SYMBOL(transfer_to_handler); | 67 | EXPORT_SYMBOL(transfer_to_handler); |
69 | EXPORT_SYMBOL(do_IRQ); | 68 | EXPORT_SYMBOL(do_IRQ); |
70 | EXPORT_SYMBOL(machine_check_exception); | 69 | EXPORT_SYMBOL(machine_check_exception); |
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index c79704f5409c..967c1ef59a6b 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c | |||
@@ -526,7 +526,7 @@ void __init setup_arch(char **cmdline_p) | |||
526 | * Systems with OF can look in the properties on the cpu node(s) | 526 | * Systems with OF can look in the properties on the cpu node(s) |
527 | * for a possibly more accurate value. | 527 | * for a possibly more accurate value. |
528 | */ | 528 | */ |
529 | if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { | 529 | if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) { |
530 | dcache_bsize = cur_cpu_spec->dcache_bsize; | 530 | dcache_bsize = cur_cpu_spec->dcache_bsize; |
531 | icache_bsize = cur_cpu_spec->icache_bsize; | 531 | icache_bsize = cur_cpu_spec->icache_bsize; |
532 | ucache_bsize = 0; | 532 | ucache_bsize = 0; |
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 0eaef7c8378b..3f3b292eb773 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c | |||
@@ -92,6 +92,7 @@ int die(const char * str, struct pt_regs * fp, long err) | |||
92 | if (nl) | 92 | if (nl) |
93 | printk("\n"); | 93 | printk("\n"); |
94 | show_regs(fp); | 94 | show_regs(fp); |
95 | add_taint(TAINT_DIE); | ||
95 | spin_unlock_irq(&die_lock); | 96 | spin_unlock_irq(&die_lock); |
96 | /* do_exit() should take care of panic'ing from an interrupt | 97 | /* do_exit() should take care of panic'ing from an interrupt |
97 | * context so we don't handle it here | 98 | * context so we don't handle it here |
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S index 19db8746ff14..c0aac3ff9e91 100644 --- a/arch/ppc/kernel/vmlinux.lds.S +++ b/arch/ppc/kernel/vmlinux.lds.S | |||
@@ -130,10 +130,7 @@ SECTIONS | |||
130 | __ftr_fixup : { *(__ftr_fixup) } | 130 | __ftr_fixup : { *(__ftr_fixup) } |
131 | __stop___ftr_fixup = .; | 131 | __stop___ftr_fixup = .; |
132 | 132 | ||
133 | . = ALIGN(4096); | 133 | PERCPU(4096) |
134 | __per_cpu_start = .; | ||
135 | .data.percpu : { *(.data.percpu) } | ||
136 | __per_cpu_end = .; | ||
137 | 134 | ||
138 | #ifdef CONFIG_BLK_DEV_INITRD | 135 | #ifdef CONFIG_BLK_DEV_INITRD |
139 | . = ALIGN(4096); | 136 | . = ALIGN(4096); |
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 465f451f3bc3..b98244e277fb 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c | |||
@@ -96,6 +96,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, | |||
96 | struct mm_struct *mm = current->mm; | 96 | struct mm_struct *mm = current->mm; |
97 | siginfo_t info; | 97 | siginfo_t info; |
98 | int code = SEGV_MAPERR; | 98 | int code = SEGV_MAPERR; |
99 | int fault; | ||
99 | #if defined(CONFIG_4xx) || defined (CONFIG_BOOKE) | 100 | #if defined(CONFIG_4xx) || defined (CONFIG_BOOKE) |
100 | int is_write = error_code & ESR_DST; | 101 | int is_write = error_code & ESR_DST; |
101 | #else | 102 | #else |
@@ -249,20 +250,18 @@ good_area: | |||
249 | * the fault. | 250 | * the fault. |
250 | */ | 251 | */ |
251 | survive: | 252 | survive: |
252 | switch (handle_mm_fault(mm, vma, address, is_write)) { | 253 | fault = handle_mm_fault(mm, vma, address, is_write); |
253 | case VM_FAULT_MINOR: | 254 | if (unlikely(fault & VM_FAULT_ERROR)) { |
254 | current->min_flt++; | 255 | if (fault & VM_FAULT_OOM) |
255 | break; | 256 | goto out_of_memory; |
256 | case VM_FAULT_MAJOR: | 257 | else if (fault & VM_FAULT_SIGBUS) |
257 | current->maj_flt++; | 258 | goto do_sigbus; |
258 | break; | ||
259 | case VM_FAULT_SIGBUS: | ||
260 | goto do_sigbus; | ||
261 | case VM_FAULT_OOM: | ||
262 | goto out_of_memory; | ||
263 | default: | ||
264 | BUG(); | 259 | BUG(); |
265 | } | 260 | } |
261 | if (fault & VM_FAULT_MAJOR) | ||
262 | current->maj_flt++; | ||
263 | else | ||
264 | current->min_flt++; | ||
266 | 265 | ||
267 | up_read(&mm->mmap_sem); | 266 | up_read(&mm->mmap_sem); |
268 | /* | 267 | /* |
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c index fa29740a28f5..4ff260bc9dd1 100644 --- a/arch/ppc/mm/tlb.c +++ b/arch/ppc/mm/tlb.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/highmem.h> | 29 | #include <linux/highmem.h> |
30 | #include <linux/pagemap.h> | ||
30 | #include <asm/tlbflush.h> | 31 | #include <asm/tlbflush.h> |
31 | #include <asm/tlb.h> | 32 | #include <asm/tlb.h> |
32 | 33 | ||
diff --git a/arch/ppc/platforms/4xx/bamboo.c b/arch/ppc/platforms/4xx/bamboo.c index 349660b84a02..017623c9bc4b 100644 --- a/arch/ppc/platforms/4xx/bamboo.c +++ b/arch/ppc/platforms/4xx/bamboo.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
30 | #include <linux/serial.h> | 30 | #include <linux/serial.h> |
31 | #include <linux/serial_core.h> | 31 | #include <linux/serial_core.h> |
32 | #include <linux/serial_8250.h> | ||
32 | #include <linux/ethtool.h> | 33 | #include <linux/ethtool.h> |
33 | 34 | ||
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c index 1a7f075b754f..cd696be55aca 100644 --- a/arch/ppc/platforms/4xx/bubinga.c +++ b/arch/ppc/platforms/4xx/bubinga.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/tty.h> | 21 | #include <linux/tty.h> |
22 | #include <linux/serial.h> | 22 | #include <linux/serial.h> |
23 | #include <linux/serial_core.h> | 23 | #include <linux/serial_core.h> |
24 | #include <linux/serial_8250.h> | ||
24 | 25 | ||
25 | #include <asm/system.h> | 26 | #include <asm/system.h> |
26 | #include <asm/pci-bridge.h> | 27 | #include <asm/pci-bridge.h> |
diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c index 8474b05b795a..2e7e25dd84cb 100644 --- a/arch/ppc/platforms/4xx/cpci405.c +++ b/arch/ppc/platforms/4xx/cpci405.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/todc.h> | 23 | #include <asm/todc.h> |
24 | #include <linux/serial.h> | 24 | #include <linux/serial.h> |
25 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
26 | #include <linux/serial_8250.h> | ||
26 | #include <asm/ocp.h> | 27 | #include <asm/ocp.h> |
27 | #include <asm/ibm_ocp_pci.h> | 28 | #include <asm/ibm_ocp_pci.h> |
28 | #include <platforms/4xx/ibm405gp.h> | 29 | #include <platforms/4xx/ibm405gp.h> |
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index f0f9cc8480ca..05d7184d7e14 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/tty.h> | 32 | #include <linux/tty.h> |
33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
34 | #include <linux/serial_core.h> | 34 | #include <linux/serial_core.h> |
35 | #include <linux/serial_8250.h> | ||
35 | 36 | ||
36 | #include <asm/system.h> | 37 | #include <asm/system.h> |
37 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c index 61706ef37112..4b169610f154 100644 --- a/arch/ppc/platforms/4xx/luan.c +++ b/arch/ppc/platforms/4xx/luan.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
31 | #include <linux/serial.h> | 31 | #include <linux/serial.h> |
32 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
33 | #include <linux/serial_8250.h> | ||
33 | 34 | ||
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c index 5e994e146ba8..fd0f971881d6 100644 --- a/arch/ppc/platforms/4xx/ocotea.c +++ b/arch/ppc/platforms/4xx/ocotea.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
31 | #include <linux/serial.h> | 31 | #include <linux/serial.h> |
32 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
33 | #include <linux/serial_8250.h> | ||
33 | 34 | ||
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c index 5d9af8ddb155..888c492b4a45 100644 --- a/arch/ppc/platforms/4xx/taishan.c +++ b/arch/ppc/platforms/4xx/taishan.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
31 | #include <linux/serial.h> | 31 | #include <linux/serial.h> |
32 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
33 | #include <linux/serial_8250.h> | ||
33 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
34 | #include <linux/mtd/partitions.h> | 35 | #include <linux/mtd/partitions.h> |
35 | #include <linux/mtd/nand.h> | 36 | #include <linux/mtd/nand.h> |
diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c index 346787df0ddb..a83b0baea011 100644 --- a/arch/ppc/platforms/4xx/yucca.c +++ b/arch/ppc/platforms/4xx/yucca.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/tty.h> | 31 | #include <linux/tty.h> |
32 | #include <linux/serial.h> | 32 | #include <linux/serial.h> |
33 | #include <linux/serial_core.h> | 33 | #include <linux/serial_core.h> |
34 | #include <linux/serial_8250.h> | ||
34 | 35 | ||
35 | #include <asm/system.h> | 36 | #include <asm/system.h> |
36 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c index 1d10ab98f66d..3d7addbdecfd 100644 --- a/arch/ppc/platforms/85xx/sbc8560.c +++ b/arch/ppc/platforms/85xx/sbc8560.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/serial.h> | 26 | #include <linux/serial.h> |
27 | #include <linux/tty.h> /* for linux/serial_core.h */ | 27 | #include <linux/tty.h> /* for linux/serial_core.h */ |
28 | #include <linux/serial_core.h> | 28 | #include <linux/serial_core.h> |
29 | #include <linux/serial_8250.h> | ||
29 | #include <linux/initrd.h> | 30 | #include <linux/initrd.h> |
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/fsl_devices.h> | 32 | #include <linux/fsl_devices.h> |
diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c index a764ae71cbcb..248684f50dd9 100644 --- a/arch/ppc/platforms/chestnut.c +++ b/arch/ppc/platforms/chestnut.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/ide.h> | 25 | #include <linux/ide.h> |
26 | #include <linux/serial.h> | 26 | #include <linux/serial.h> |
27 | #include <linux/serial_core.h> | 27 | #include <linux/serial_core.h> |
28 | #include <linux/serial_8250.h> | ||
28 | #include <linux/mtd/physmap.h> | 29 | #include <linux/mtd/physmap.h> |
29 | #include <asm/system.h> | 30 | #include <asm/system.h> |
30 | #include <asm/pgtable.h> | 31 | #include <asm/pgtable.h> |
diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c index 4957a7bcde22..976270d537c1 100644 --- a/arch/ppc/platforms/ev64260.c +++ b/arch/ppc/platforms/ev64260.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/serial.h> | 35 | #include <linux/serial.h> |
36 | #include <linux/tty.h> | 36 | #include <linux/tty.h> |
37 | #include <linux/serial_core.h> | 37 | #include <linux/serial_core.h> |
38 | #include <linux/serial_8250.h> | ||
38 | #else | 39 | #else |
39 | #include <linux/mv643xx.h> | 40 | #include <linux/mv643xx.h> |
40 | #endif | 41 | #endif |
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index 6f21110a9747..3c56654bfc6f 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c | |||
@@ -69,9 +69,6 @@ | |||
69 | 69 | ||
70 | TODC_ALLOC(); | 70 | TODC_ALLOC(); |
71 | 71 | ||
72 | unsigned char ucBoardRev; | ||
73 | unsigned char ucBoardRevMaj, ucBoardRevMin; | ||
74 | |||
75 | extern unsigned char prep_nvram_read_val(int addr); | 72 | extern unsigned char prep_nvram_read_val(int addr); |
76 | extern void prep_nvram_write_val(int addr, | 73 | extern void prep_nvram_write_val(int addr, |
77 | unsigned char val); | 74 | unsigned char val); |
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c index b55860734a72..44d4398a36ff 100644 --- a/arch/ppc/platforms/radstone_ppc7d.c +++ b/arch/ppc/platforms/radstone_ppc7d.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/serial.h> | 35 | #include <linux/serial.h> |
36 | #include <linux/tty.h> /* for linux/serial_core.h */ | 36 | #include <linux/tty.h> /* for linux/serial_core.h */ |
37 | #include <linux/serial_core.h> | 37 | #include <linux/serial_core.h> |
38 | #include <linux/serial_8250.h> | ||
38 | #include <linux/mv643xx.h> | 39 | #include <linux/mv643xx.h> |
39 | #include <linux/netdevice.h> | 40 | #include <linux/netdevice.h> |
40 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c index 3c7842784876..f4de50ba292e 100644 --- a/arch/ppc/platforms/spruce.c +++ b/arch/ppc/platforms/spruce.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/serial.h> | 27 | #include <linux/serial.h> |
28 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
29 | #include <linux/serial_core.h> | 29 | #include <linux/serial_core.h> |
30 | #include <linux/serial_8250.h> | ||
30 | 31 | ||
31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
32 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 95694159b226..543795be58c8 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile | |||
@@ -7,6 +7,7 @@ CFLAGS_btext.o += -fPIC | |||
7 | 7 | ||
8 | wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o | 8 | wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o |
9 | 9 | ||
10 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | ||
10 | obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o | 11 | obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o |
11 | obj-$(CONFIG_PPC_OCP) += ocp.o | 12 | obj-$(CONFIG_PPC_OCP) += ocp.o |
12 | obj-$(CONFIG_IBM_OCP) += ibm_ocp.o | 13 | obj-$(CONFIG_IBM_OCP) += ibm_ocp.o |
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c new file mode 100644 index 000000000000..83b323a7d029 --- /dev/null +++ b/arch/ppc/syslib/indirect_pci.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Support for indirect PCI bridges. | ||
3 | * | ||
4 | * Copyright (C) 1998 Gabriel Paubert. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/init.h> | ||
17 | |||
18 | #include <asm/io.h> | ||
19 | #include <asm/prom.h> | ||
20 | #include <asm/pci-bridge.h> | ||
21 | #include <asm/machdep.h> | ||
22 | |||
23 | #ifdef CONFIG_PPC_INDIRECT_PCI_BE | ||
24 | #define PCI_CFG_OUT out_be32 | ||
25 | #else | ||
26 | #define PCI_CFG_OUT out_le32 | ||
27 | #endif | ||
28 | |||
29 | static int | ||
30 | indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
31 | int len, u32 *val) | ||
32 | { | ||
33 | struct pci_controller *hose = bus->sysdata; | ||
34 | volatile void __iomem *cfg_data; | ||
35 | u8 cfg_type = 0; | ||
36 | |||
37 | if (ppc_md.pci_exclude_device) | ||
38 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
39 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
40 | |||
41 | if (hose->set_cfg_type) | ||
42 | if (bus->number != hose->first_busno) | ||
43 | cfg_type = 1; | ||
44 | |||
45 | PCI_CFG_OUT(hose->cfg_addr, | ||
46 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | ||
47 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | ||
48 | |||
49 | /* | ||
50 | * Note: the caller has already checked that offset is | ||
51 | * suitably aligned and that len is 1, 2 or 4. | ||
52 | */ | ||
53 | cfg_data = hose->cfg_data + (offset & 3); | ||
54 | switch (len) { | ||
55 | case 1: | ||
56 | *val = in_8(cfg_data); | ||
57 | break; | ||
58 | case 2: | ||
59 | *val = in_le16(cfg_data); | ||
60 | break; | ||
61 | default: | ||
62 | *val = in_le32(cfg_data); | ||
63 | break; | ||
64 | } | ||
65 | return PCIBIOS_SUCCESSFUL; | ||
66 | } | ||
67 | |||
68 | static int | ||
69 | indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
70 | int len, u32 val) | ||
71 | { | ||
72 | struct pci_controller *hose = bus->sysdata; | ||
73 | volatile void __iomem *cfg_data; | ||
74 | u8 cfg_type = 0; | ||
75 | |||
76 | if (ppc_md.pci_exclude_device) | ||
77 | if (ppc_md.pci_exclude_device(bus->number, devfn)) | ||
78 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
79 | |||
80 | if (hose->set_cfg_type) | ||
81 | if (bus->number != hose->first_busno) | ||
82 | cfg_type = 1; | ||
83 | |||
84 | PCI_CFG_OUT(hose->cfg_addr, | ||
85 | (0x80000000 | ((bus->number - hose->bus_offset) << 16) | ||
86 | | (devfn << 8) | ((offset & 0xfc) | cfg_type))); | ||
87 | |||
88 | /* | ||
89 | * Note: the caller has already checked that offset is | ||
90 | * suitably aligned and that len is 1, 2 or 4. | ||
91 | */ | ||
92 | cfg_data = hose->cfg_data + (offset & 3); | ||
93 | switch (len) { | ||
94 | case 1: | ||
95 | out_8(cfg_data, val); | ||
96 | break; | ||
97 | case 2: | ||
98 | out_le16(cfg_data, val); | ||
99 | break; | ||
100 | default: | ||
101 | out_le32(cfg_data, val); | ||
102 | break; | ||
103 | } | ||
104 | return PCIBIOS_SUCCESSFUL; | ||
105 | } | ||
106 | |||
107 | static struct pci_ops indirect_pci_ops = | ||
108 | { | ||
109 | indirect_read_config, | ||
110 | indirect_write_config | ||
111 | }; | ||
112 | |||
113 | void __init | ||
114 | setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr, | ||
115 | void __iomem * cfg_data) | ||
116 | { | ||
117 | hose->cfg_addr = cfg_addr; | ||
118 | hose->cfg_data = cfg_data; | ||
119 | hose->ops = &indirect_pci_ops; | ||
120 | } | ||
121 | |||
122 | void __init | ||
123 | setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) | ||
124 | { | ||
125 | unsigned long base = cfg_addr & PAGE_MASK; | ||
126 | void __iomem *mbase, *addr, *data; | ||
127 | |||
128 | mbase = ioremap(base, PAGE_SIZE); | ||
129 | addr = mbase + (cfg_addr & ~PAGE_MASK); | ||
130 | if ((cfg_data & PAGE_MASK) != base) | ||
131 | mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); | ||
132 | data = mbase + (cfg_data & ~PAGE_MASK); | ||
133 | setup_indirect_pci_nomap(hose, addr, data); | ||
134 | } | ||
diff --git a/arch/ppc/syslib/virtex_devices.c b/arch/ppc/syslib/virtex_devices.c index 16546788e23b..ace4ec08de51 100644 --- a/arch/ppc/syslib/virtex_devices.c +++ b/arch/ppc/syslib/virtex_devices.c | |||
@@ -71,6 +71,21 @@ | |||
71 | }, \ | 71 | }, \ |
72 | } | 72 | } |
73 | 73 | ||
74 | /* | ||
75 | * ML300/ML403 Video Device: shortcut macro for single instance | ||
76 | */ | ||
77 | #define XPAR_TFT(num) { \ | ||
78 | .name = "xilinxfb", \ | ||
79 | .id = num, \ | ||
80 | .num_resources = 1, \ | ||
81 | .resource = (struct resource[]) { \ | ||
82 | { \ | ||
83 | .start = XPAR_TFT_##num##_BASEADDR, \ | ||
84 | .end = XPAR_TFT_##num##_BASEADDR+7, \ | ||
85 | .flags = IORESOURCE_IO, \ | ||
86 | }, \ | ||
87 | }, \ | ||
88 | } | ||
74 | 89 | ||
75 | /* UART 8250 driver platform data table */ | 90 | /* UART 8250 driver platform data table */ |
76 | struct plat_serial8250_port virtex_serial_platform_data[] = { | 91 | struct plat_serial8250_port virtex_serial_platform_data[] = { |
@@ -146,20 +161,17 @@ struct platform_device virtex_platform_devices[] = { | |||
146 | XPAR_SYSACE(1), | 161 | XPAR_SYSACE(1), |
147 | #endif | 162 | #endif |
148 | 163 | ||
149 | /* ML300/403 reference design framebuffer */ | ||
150 | #if defined(XPAR_TFT_0_BASEADDR) | 164 | #if defined(XPAR_TFT_0_BASEADDR) |
151 | { | 165 | XPAR_TFT(0), |
152 | .name = "xilinxfb", | 166 | #endif |
153 | .id = 0, | 167 | #if defined(XPAR_TFT_1_BASEADDR) |
154 | .num_resources = 1, | 168 | XPAR_TFT(1), |
155 | .resource = (struct resource[]) { | 169 | #endif |
156 | { | 170 | #if defined(XPAR_TFT_2_BASEADDR) |
157 | .start = XPAR_TFT_0_BASEADDR, | 171 | XPAR_TFT(2), |
158 | .end = XPAR_TFT_0_BASEADDR+7, | 172 | #endif |
159 | .flags = IORESOURCE_IO, | 173 | #if defined(XPAR_TFT_3_BASEADDR) |
160 | }, | 174 | XPAR_TFT(3), |
161 | }, | ||
162 | }, | ||
163 | #endif | 175 | #endif |
164 | }; | 176 | }; |
165 | 177 | ||
diff --git a/arch/ppc/syslib/virtex_devices.h b/arch/ppc/syslib/virtex_devices.h index 3d4be1412f60..9f38d92ae536 100644 --- a/arch/ppc/syslib/virtex_devices.h +++ b/arch/ppc/syslib/virtex_devices.h | |||
@@ -31,4 +31,11 @@ void __init virtex_early_serial_map(void); | |||
31 | */ | 31 | */ |
32 | int virtex_device_fixup(struct platform_device *dev); | 32 | int virtex_device_fixup(struct platform_device *dev); |
33 | 33 | ||
34 | /* SPI Controller IP */ | ||
35 | struct xspi_platform_data { | ||
36 | s16 bus_num; | ||
37 | u16 num_chipselect; | ||
38 | u32 speed_hz; | ||
39 | }; | ||
40 | |||
34 | #endif /* __ASM_VIRTEX_DEVICES_H__ */ | 41 | #endif /* __ASM_VIRTEX_DEVICES_H__ */ |
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 485b60c1983c..2aae23dba4bb 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.21 | 3 | # Linux kernel version: 2.6.22 |
4 | # Thu May 10 15:18:19 2007 | 4 | # Tue Jul 17 12:50:23 2007 |
5 | # | 5 | # |
6 | CONFIG_MMU=y | 6 | CONFIG_MMU=y |
7 | CONFIG_ZONE_DMA=y | 7 | CONFIG_ZONE_DMA=y |
@@ -32,12 +32,11 @@ CONFIG_LOCALVERSION="" | |||
32 | CONFIG_LOCALVERSION_AUTO=y | 32 | CONFIG_LOCALVERSION_AUTO=y |
33 | CONFIG_SWAP=y | 33 | CONFIG_SWAP=y |
34 | CONFIG_SYSVIPC=y | 34 | CONFIG_SYSVIPC=y |
35 | # CONFIG_IPC_NS is not set | ||
36 | CONFIG_SYSVIPC_SYSCTL=y | 35 | CONFIG_SYSVIPC_SYSCTL=y |
37 | CONFIG_POSIX_MQUEUE=y | 36 | CONFIG_POSIX_MQUEUE=y |
38 | # CONFIG_BSD_PROCESS_ACCT is not set | 37 | # CONFIG_BSD_PROCESS_ACCT is not set |
39 | # CONFIG_TASKSTATS is not set | 38 | # CONFIG_TASKSTATS is not set |
40 | # CONFIG_UTS_NS is not set | 39 | # CONFIG_USER_NS is not set |
41 | CONFIG_AUDIT=y | 40 | CONFIG_AUDIT=y |
42 | # CONFIG_AUDITSYSCALL is not set | 41 | # CONFIG_AUDITSYSCALL is not set |
43 | CONFIG_IKCONFIG=y | 42 | CONFIG_IKCONFIG=y |
@@ -61,20 +60,19 @@ CONFIG_BUG=y | |||
61 | CONFIG_ELF_CORE=y | 60 | CONFIG_ELF_CORE=y |
62 | CONFIG_BASE_FULL=y | 61 | CONFIG_BASE_FULL=y |
63 | CONFIG_FUTEX=y | 62 | CONFIG_FUTEX=y |
63 | CONFIG_ANON_INODES=y | ||
64 | CONFIG_EPOLL=y | 64 | CONFIG_EPOLL=y |
65 | CONFIG_SIGNALFD=y | ||
66 | CONFIG_TIMERFD=y | ||
67 | CONFIG_EVENTFD=y | ||
65 | CONFIG_SHMEM=y | 68 | CONFIG_SHMEM=y |
66 | CONFIG_VM_EVENT_COUNTERS=y | 69 | CONFIG_VM_EVENT_COUNTERS=y |
67 | CONFIG_SLUB_DEBUG=y | ||
68 | CONFIG_SLAB=y | 70 | CONFIG_SLAB=y |
69 | # CONFIG_SLUB is not set | 71 | # CONFIG_SLUB is not set |
70 | # CONFIG_SLOB is not set | 72 | # CONFIG_SLOB is not set |
71 | CONFIG_RT_MUTEXES=y | 73 | CONFIG_RT_MUTEXES=y |
72 | # CONFIG_TINY_SHMEM is not set | 74 | # CONFIG_TINY_SHMEM is not set |
73 | CONFIG_BASE_SMALL=0 | 75 | CONFIG_BASE_SMALL=0 |
74 | |||
75 | # | ||
76 | # Loadable module support | ||
77 | # | ||
78 | CONFIG_MODULES=y | 76 | CONFIG_MODULES=y |
79 | CONFIG_MODULE_UNLOAD=y | 77 | CONFIG_MODULE_UNLOAD=y |
80 | # CONFIG_MODULE_FORCE_UNLOAD is not set | 78 | # CONFIG_MODULE_FORCE_UNLOAD is not set |
@@ -82,12 +80,9 @@ CONFIG_MODVERSIONS=y | |||
82 | # CONFIG_MODULE_SRCVERSION_ALL is not set | 80 | # CONFIG_MODULE_SRCVERSION_ALL is not set |
83 | CONFIG_KMOD=y | 81 | CONFIG_KMOD=y |
84 | CONFIG_STOP_MACHINE=y | 82 | CONFIG_STOP_MACHINE=y |
85 | |||
86 | # | ||
87 | # Block layer | ||
88 | # | ||
89 | CONFIG_BLOCK=y | 83 | CONFIG_BLOCK=y |
90 | # CONFIG_BLK_DEV_IO_TRACE is not set | 84 | # CONFIG_BLK_DEV_IO_TRACE is not set |
85 | CONFIG_BLK_DEV_BSG=y | ||
91 | 86 | ||
92 | # | 87 | # |
93 | # IO Schedulers | 88 | # IO Schedulers |
@@ -151,6 +146,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y | |||
151 | CONFIG_SPLIT_PTLOCK_CPUS=4 | 146 | CONFIG_SPLIT_PTLOCK_CPUS=4 |
152 | CONFIG_RESOURCES_64BIT=y | 147 | CONFIG_RESOURCES_64BIT=y |
153 | CONFIG_ZONE_DMA_FLAG=1 | 148 | CONFIG_ZONE_DMA_FLAG=1 |
149 | CONFIG_VIRT_TO_BUS=y | ||
154 | CONFIG_HOLES_IN_ZONE=y | 150 | CONFIG_HOLES_IN_ZONE=y |
155 | 151 | ||
156 | # | 152 | # |
@@ -248,25 +244,13 @@ CONFIG_IPV6_SIT=y | |||
248 | # CONFIG_IPV6_MULTIPLE_TABLES is not set | 244 | # CONFIG_IPV6_MULTIPLE_TABLES is not set |
249 | # CONFIG_NETWORK_SECMARK is not set | 245 | # CONFIG_NETWORK_SECMARK is not set |
250 | # CONFIG_NETFILTER is not set | 246 | # CONFIG_NETFILTER is not set |
251 | |||
252 | # | ||
253 | # DCCP Configuration (EXPERIMENTAL) | ||
254 | # | ||
255 | # CONFIG_IP_DCCP is not set | 247 | # CONFIG_IP_DCCP is not set |
256 | |||
257 | # | ||
258 | # SCTP Configuration (EXPERIMENTAL) | ||
259 | # | ||
260 | CONFIG_IP_SCTP=m | 248 | CONFIG_IP_SCTP=m |
261 | # CONFIG_SCTP_DBG_MSG is not set | 249 | # CONFIG_SCTP_DBG_MSG is not set |
262 | # CONFIG_SCTP_DBG_OBJCNT is not set | 250 | # CONFIG_SCTP_DBG_OBJCNT is not set |
263 | # CONFIG_SCTP_HMAC_NONE is not set | 251 | # CONFIG_SCTP_HMAC_NONE is not set |
264 | # CONFIG_SCTP_HMAC_SHA1 is not set | 252 | # CONFIG_SCTP_HMAC_SHA1 is not set |
265 | CONFIG_SCTP_HMAC_MD5=y | 253 | CONFIG_SCTP_HMAC_MD5=y |
266 | |||
267 | # | ||
268 | # TIPC Configuration (EXPERIMENTAL) | ||
269 | # | ||
270 | # CONFIG_TIPC is not set | 254 | # CONFIG_TIPC is not set |
271 | # CONFIG_ATM is not set | 255 | # CONFIG_ATM is not set |
272 | # CONFIG_BRIDGE is not set | 256 | # CONFIG_BRIDGE is not set |
@@ -293,6 +277,7 @@ CONFIG_NET_SCH_CBQ=m | |||
293 | # CONFIG_NET_SCH_HTB is not set | 277 | # CONFIG_NET_SCH_HTB is not set |
294 | # CONFIG_NET_SCH_HFSC is not set | 278 | # CONFIG_NET_SCH_HFSC is not set |
295 | CONFIG_NET_SCH_PRIO=m | 279 | CONFIG_NET_SCH_PRIO=m |
280 | CONFIG_NET_SCH_RR=m | ||
296 | CONFIG_NET_SCH_RED=m | 281 | CONFIG_NET_SCH_RED=m |
297 | CONFIG_NET_SCH_SFQ=m | 282 | CONFIG_NET_SCH_SFQ=m |
298 | CONFIG_NET_SCH_TEQL=m | 283 | CONFIG_NET_SCH_TEQL=m |
@@ -317,10 +302,14 @@ CONFIG_CLS_U32_MARK=y | |||
317 | CONFIG_NET_CLS_RSVP=m | 302 | CONFIG_NET_CLS_RSVP=m |
318 | CONFIG_NET_CLS_RSVP6=m | 303 | CONFIG_NET_CLS_RSVP6=m |
319 | # CONFIG_NET_EMATCH is not set | 304 | # CONFIG_NET_EMATCH is not set |
320 | # CONFIG_NET_CLS_ACT is not set | 305 | CONFIG_NET_CLS_ACT=y |
306 | CONFIG_NET_ACT_POLICE=y | ||
307 | # CONFIG_NET_ACT_GACT is not set | ||
308 | # CONFIG_NET_ACT_MIRRED is not set | ||
309 | # CONFIG_NET_ACT_PEDIT is not set | ||
310 | # CONFIG_NET_ACT_SIMP is not set | ||
321 | CONFIG_NET_CLS_POLICE=y | 311 | CONFIG_NET_CLS_POLICE=y |
322 | # CONFIG_NET_CLS_IND is not set | 312 | # CONFIG_NET_CLS_IND is not set |
323 | CONFIG_NET_ESTIMATOR=y | ||
324 | 313 | ||
325 | # | 314 | # |
326 | # Network testing | 315 | # Network testing |
@@ -329,6 +318,7 @@ CONFIG_NET_ESTIMATOR=y | |||
329 | # CONFIG_NET_TCPPROBE is not set | 318 | # CONFIG_NET_TCPPROBE is not set |
330 | # CONFIG_AF_RXRPC is not set | 319 | # CONFIG_AF_RXRPC is not set |
331 | # CONFIG_RFKILL is not set | 320 | # CONFIG_RFKILL is not set |
321 | # CONFIG_NET_9P is not set | ||
332 | # CONFIG_PCMCIA is not set | 322 | # CONFIG_PCMCIA is not set |
333 | CONFIG_CCW=y | 323 | CONFIG_CCW=y |
334 | 324 | ||
@@ -345,15 +335,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y | |||
345 | # CONFIG_DEBUG_DRIVER is not set | 335 | # CONFIG_DEBUG_DRIVER is not set |
346 | # CONFIG_DEBUG_DEVRES is not set | 336 | # CONFIG_DEBUG_DEVRES is not set |
347 | CONFIG_SYS_HYPERVISOR=y | 337 | CONFIG_SYS_HYPERVISOR=y |
348 | |||
349 | # | ||
350 | # Connector - unified userspace <-> kernelspace linker | ||
351 | # | ||
352 | # CONFIG_CONNECTOR is not set | 338 | # CONFIG_CONNECTOR is not set |
353 | 339 | CONFIG_BLK_DEV=y | |
354 | # | ||
355 | # Block devices | ||
356 | # | ||
357 | # CONFIG_BLK_DEV_COW_COMMON is not set | 340 | # CONFIG_BLK_DEV_COW_COMMON is not set |
358 | CONFIG_BLK_DEV_LOOP=m | 341 | CONFIG_BLK_DEV_LOOP=m |
359 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | 342 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set |
@@ -376,17 +359,15 @@ CONFIG_DASD_ECKD=y | |||
376 | CONFIG_DASD_FBA=y | 359 | CONFIG_DASD_FBA=y |
377 | CONFIG_DASD_DIAG=y | 360 | CONFIG_DASD_DIAG=y |
378 | CONFIG_DASD_EER=y | 361 | CONFIG_DASD_EER=y |
379 | 362 | CONFIG_MISC_DEVICES=y | |
380 | # | 363 | # CONFIG_EEPROM_93CX6 is not set |
381 | # Misc devices | ||
382 | # | ||
383 | # CONFIG_BLINK is not set | ||
384 | 364 | ||
385 | # | 365 | # |
386 | # SCSI device support | 366 | # SCSI device support |
387 | # | 367 | # |
388 | # CONFIG_RAID_ATTRS is not set | 368 | # CONFIG_RAID_ATTRS is not set |
389 | CONFIG_SCSI=y | 369 | CONFIG_SCSI=y |
370 | # CONFIG_SCSI_DMA is not set | ||
390 | # CONFIG_SCSI_TGT is not set | 371 | # CONFIG_SCSI_TGT is not set |
391 | CONFIG_SCSI_NETLINK=y | 372 | CONFIG_SCSI_NETLINK=y |
392 | CONFIG_SCSI_PROC_FS=y | 373 | CONFIG_SCSI_PROC_FS=y |
@@ -447,40 +428,21 @@ CONFIG_DM_MIRROR=y | |||
447 | CONFIG_DM_ZERO=y | 428 | CONFIG_DM_ZERO=y |
448 | CONFIG_DM_MULTIPATH=y | 429 | CONFIG_DM_MULTIPATH=y |
449 | # CONFIG_DM_MULTIPATH_EMC is not set | 430 | # CONFIG_DM_MULTIPATH_EMC is not set |
431 | # CONFIG_DM_MULTIPATH_RDAC is not set | ||
450 | # CONFIG_DM_DELAY is not set | 432 | # CONFIG_DM_DELAY is not set |
451 | |||
452 | # | ||
453 | # Network device support | ||
454 | # | ||
455 | CONFIG_NETDEVICES=y | 433 | CONFIG_NETDEVICES=y |
434 | # CONFIG_NETDEVICES_MULTIQUEUE is not set | ||
435 | # CONFIG_IFB is not set | ||
456 | CONFIG_DUMMY=m | 436 | CONFIG_DUMMY=m |
457 | CONFIG_BONDING=m | 437 | CONFIG_BONDING=m |
438 | # CONFIG_MACVLAN is not set | ||
458 | CONFIG_EQUALIZER=m | 439 | CONFIG_EQUALIZER=m |
459 | CONFIG_TUN=m | 440 | CONFIG_TUN=m |
460 | |||
461 | # | ||
462 | # Ethernet (10 or 100Mbit) | ||
463 | # | ||
464 | CONFIG_NET_ETHERNET=y | 441 | CONFIG_NET_ETHERNET=y |
465 | # CONFIG_MII is not set | 442 | # CONFIG_MII is not set |
466 | 443 | CONFIG_NETDEV_1000=y | |
467 | # | 444 | CONFIG_NETDEV_10000=y |
468 | # Ethernet (1000 Mbit) | ||
469 | # | ||
470 | |||
471 | # | ||
472 | # Ethernet (10000 Mbit) | ||
473 | # | ||
474 | CONFIG_MLX4_DEBUG=y | ||
475 | |||
476 | # | ||
477 | # Token Ring devices | ||
478 | # | ||
479 | # CONFIG_TR is not set | 445 | # CONFIG_TR is not set |
480 | |||
481 | # | ||
482 | # Wan interfaces | ||
483 | # | ||
484 | # CONFIG_WAN is not set | 446 | # CONFIG_WAN is not set |
485 | 447 | ||
486 | # | 448 | # |
@@ -511,10 +473,6 @@ CONFIG_CCWGROUP=y | |||
511 | CONFIG_UNIX98_PTYS=y | 473 | CONFIG_UNIX98_PTYS=y |
512 | CONFIG_LEGACY_PTYS=y | 474 | CONFIG_LEGACY_PTYS=y |
513 | CONFIG_LEGACY_PTY_COUNT=256 | 475 | CONFIG_LEGACY_PTY_COUNT=256 |
514 | |||
515 | # | ||
516 | # Watchdog Cards | ||
517 | # | ||
518 | # CONFIG_WATCHDOG is not set | 476 | # CONFIG_WATCHDOG is not set |
519 | CONFIG_HW_RANDOM=m | 477 | CONFIG_HW_RANDOM=m |
520 | # CONFIG_R3964 is not set | 478 | # CONFIG_R3964 is not set |
@@ -554,6 +512,8 @@ CONFIG_S390_TAPE_34XX=m | |||
554 | # CONFIG_VMCP is not set | 512 | # CONFIG_VMCP is not set |
555 | # CONFIG_MONREADER is not set | 513 | # CONFIG_MONREADER is not set |
556 | CONFIG_MONWRITER=m | 514 | CONFIG_MONWRITER=m |
515 | CONFIG_S390_VMUR=m | ||
516 | # CONFIG_POWER_SUPPLY is not set | ||
557 | 517 | ||
558 | # | 518 | # |
559 | # File systems | 519 | # File systems |
@@ -655,7 +615,6 @@ CONFIG_SUNRPC=y | |||
655 | # CONFIG_NCP_FS is not set | 615 | # CONFIG_NCP_FS is not set |
656 | # CONFIG_CODA_FS is not set | 616 | # CONFIG_CODA_FS is not set |
657 | # CONFIG_AFS_FS is not set | 617 | # CONFIG_AFS_FS is not set |
658 | # CONFIG_9P_FS is not set | ||
659 | 618 | ||
660 | # | 619 | # |
661 | # Partition Types | 620 | # Partition Types |
@@ -712,6 +671,7 @@ CONFIG_MAGIC_SYSRQ=y | |||
712 | CONFIG_DEBUG_FS=y | 671 | CONFIG_DEBUG_FS=y |
713 | CONFIG_HEADERS_CHECK=y | 672 | CONFIG_HEADERS_CHECK=y |
714 | CONFIG_DEBUG_KERNEL=y | 673 | CONFIG_DEBUG_KERNEL=y |
674 | # CONFIG_SCHED_DEBUG is not set | ||
715 | # CONFIG_SCHEDSTATS is not set | 675 | # CONFIG_SCHEDSTATS is not set |
716 | # CONFIG_TIMER_STATS is not set | 676 | # CONFIG_TIMER_STATS is not set |
717 | # CONFIG_DEBUG_SLAB is not set | 677 | # CONFIG_DEBUG_SLAB is not set |
@@ -740,10 +700,6 @@ CONFIG_FORCED_INLINING=y | |||
740 | # | 700 | # |
741 | # CONFIG_KEYS is not set | 701 | # CONFIG_KEYS is not set |
742 | # CONFIG_SECURITY is not set | 702 | # CONFIG_SECURITY is not set |
743 | |||
744 | # | ||
745 | # Cryptographic options | ||
746 | # | ||
747 | CONFIG_CRYPTO=y | 703 | CONFIG_CRYPTO=y |
748 | CONFIG_CRYPTO_ALGAPI=y | 704 | CONFIG_CRYPTO_ALGAPI=y |
749 | CONFIG_CRYPTO_BLKCIPHER=y | 705 | CONFIG_CRYPTO_BLKCIPHER=y |
@@ -782,10 +738,7 @@ CONFIG_CRYPTO_FCRYPT=m | |||
782 | # CONFIG_CRYPTO_CRC32C is not set | 738 | # CONFIG_CRYPTO_CRC32C is not set |
783 | CONFIG_CRYPTO_CAMELLIA=m | 739 | CONFIG_CRYPTO_CAMELLIA=m |
784 | # CONFIG_CRYPTO_TEST is not set | 740 | # CONFIG_CRYPTO_TEST is not set |
785 | 741 | CONFIG_CRYPTO_HW=y | |
786 | # | ||
787 | # Hardware crypto devices | ||
788 | # | ||
789 | # CONFIG_CRYPTO_SHA1_S390 is not set | 742 | # CONFIG_CRYPTO_SHA1_S390 is not set |
790 | # CONFIG_CRYPTO_SHA256_S390 is not set | 743 | # CONFIG_CRYPTO_SHA256_S390 is not set |
791 | # CONFIG_CRYPTO_DES_S390 is not set | 744 | # CONFIG_CRYPTO_DES_S390 is not set |
@@ -800,6 +753,7 @@ CONFIG_ZCRYPT=m | |||
800 | CONFIG_BITREVERSE=m | 753 | CONFIG_BITREVERSE=m |
801 | # CONFIG_CRC_CCITT is not set | 754 | # CONFIG_CRC_CCITT is not set |
802 | # CONFIG_CRC16 is not set | 755 | # CONFIG_CRC16 is not set |
756 | # CONFIG_CRC_ITU_T is not set | ||
803 | CONFIG_CRC32=m | 757 | CONFIG_CRC32=m |
804 | # CONFIG_LIBCRC32C is not set | 758 | # CONFIG_LIBCRC32C is not set |
805 | CONFIG_PLIST=y | 759 | CONFIG_PLIST=y |
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index a057ebf108a7..d3057318f2bf 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c | |||
@@ -240,8 +240,8 @@ static const unsigned char formats[][7] = { | |||
240 | [INSTR_RXY_FRRD] = { 0xff, F_8,D20_20,X_12,B_16,0,0 },/* e.g. ley */ | 240 | [INSTR_RXY_FRRD] = { 0xff, F_8,D20_20,X_12,B_16,0,0 },/* e.g. ley */ |
241 | [INSTR_RX_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. ae */ | 241 | [INSTR_RX_FRRD] = { 0xff, F_8,D_20,X_12,B_16,0,0 }, /* e.g. ae */ |
242 | [INSTR_RX_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. l */ | 242 | [INSTR_RX_RRRD] = { 0xff, R_8,D_20,X_12,B_16,0,0 }, /* e.g. l */ |
243 | [INSTR_RX_URRD] = { 0x00, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */ | 243 | [INSTR_RX_URRD] = { 0xff, U4_8,D_20,X_12,B_16,0,0 }, /* e.g. bc */ |
244 | [INSTR_SI_URD] = { 0x00, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */ | 244 | [INSTR_SI_URD] = { 0xff, D_20,B_16,U8_8,0,0,0 }, /* e.g. cli */ |
245 | [INSTR_SIY_URD] = { 0xff, D20_20,B_16,U8_8,0,0,0 }, /* e.g. tmy */ | 245 | [INSTR_SIY_URD] = { 0xff, D20_20,B_16,U8_8,0,0,0 }, /* e.g. tmy */ |
246 | [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, /* e.g. mvsdk */ | 246 | [INSTR_SSE_RDRD] = { 0xff, D_20,B_16,D_36,B_32,0,0 }, /* e.g. mvsdk */ |
247 | [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 }, | 247 | [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 }, |
@@ -1190,7 +1190,8 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr) | |||
1190 | else if (operand->flags & OPERAND_CR) | 1190 | else if (operand->flags & OPERAND_CR) |
1191 | ptr += sprintf(ptr, "%%c%i", value); | 1191 | ptr += sprintf(ptr, "%%c%i", value); |
1192 | else if (operand->flags & OPERAND_PCREL) | 1192 | else if (operand->flags & OPERAND_PCREL) |
1193 | ptr += sprintf(ptr, "%lx", value + addr); | 1193 | ptr += sprintf(ptr, "%lx", (signed int) value |
1194 | + addr); | ||
1194 | else if (operand->flags & OPERAND_SIGNED) | 1195 | else if (operand->flags & OPERAND_SIGNED) |
1195 | ptr += sprintf(ptr, "%i", value); | 1196 | ptr += sprintf(ptr, "%i", value); |
1196 | else | 1197 | else |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 2a8f0872ea8b..f4503ca27630 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -294,7 +294,6 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) | |||
294 | static int | 294 | static int |
295 | do_ptrace_normal(struct task_struct *child, long request, long addr, long data) | 295 | do_ptrace_normal(struct task_struct *child, long request, long addr, long data) |
296 | { | 296 | { |
297 | unsigned long tmp; | ||
298 | ptrace_area parea; | 297 | ptrace_area parea; |
299 | int copied, ret; | 298 | int copied, ret; |
300 | 299 | ||
@@ -304,10 +303,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) | |||
304 | /* Remove high order bit from address (only for 31 bit). */ | 303 | /* Remove high order bit from address (only for 31 bit). */ |
305 | addr &= PSW_ADDR_INSN; | 304 | addr &= PSW_ADDR_INSN; |
306 | /* read word at location addr. */ | 305 | /* read word at location addr. */ |
307 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | 306 | return generic_ptrace_peekdata(child, addr, data); |
308 | if (copied != sizeof(tmp)) | ||
309 | return -EIO; | ||
310 | return put_user(tmp, (unsigned long __force __user *) data); | ||
311 | 307 | ||
312 | case PTRACE_PEEKUSR: | 308 | case PTRACE_PEEKUSR: |
313 | /* read the word at location addr in the USER area. */ | 309 | /* read the word at location addr in the USER area. */ |
@@ -318,10 +314,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) | |||
318 | /* Remove high order bit from address (only for 31 bit). */ | 314 | /* Remove high order bit from address (only for 31 bit). */ |
319 | addr &= PSW_ADDR_INSN; | 315 | addr &= PSW_ADDR_INSN; |
320 | /* write the word at location addr. */ | 316 | /* write the word at location addr. */ |
321 | copied = access_process_vm(child, addr, &data, sizeof(data),1); | 317 | return generic_ptrace_pokedata(child, addr, data); |
322 | if (copied != sizeof(data)) | ||
323 | return -EIO; | ||
324 | return 0; | ||
325 | 318 | ||
326 | case PTRACE_POKEUSR: | 319 | case PTRACE_POKEUSR: |
327 | /* write the word at location addr in the USER area */ | 320 | /* write the word at location addr in the USER area */ |
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c index 515ff9011dd7..da6924729964 100644 --- a/arch/s390/kernel/stacktrace.c +++ b/arch/s390/kernel/stacktrace.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/kallsyms.h> | 12 | #include <linux/kallsyms.h> |
13 | 13 | ||
14 | static unsigned long save_context_stack(struct stack_trace *trace, | 14 | static unsigned long save_context_stack(struct stack_trace *trace, |
15 | unsigned int *skip, | ||
16 | unsigned long sp, | 15 | unsigned long sp, |
17 | unsigned long low, | 16 | unsigned long low, |
18 | unsigned long high) | 17 | unsigned long high) |
@@ -28,10 +27,10 @@ static unsigned long save_context_stack(struct stack_trace *trace, | |||
28 | sf = (struct stack_frame *)sp; | 27 | sf = (struct stack_frame *)sp; |
29 | while(1) { | 28 | while(1) { |
30 | addr = sf->gprs[8] & PSW_ADDR_INSN; | 29 | addr = sf->gprs[8] & PSW_ADDR_INSN; |
31 | if (!(*skip)) | 30 | if (!trace->skip) |
32 | trace->entries[trace->nr_entries++] = addr; | 31 | trace->entries[trace->nr_entries++] = addr; |
33 | else | 32 | else |
34 | (*skip)--; | 33 | trace->skip--; |
35 | if (trace->nr_entries >= trace->max_entries) | 34 | if (trace->nr_entries >= trace->max_entries) |
36 | return sp; | 35 | return sp; |
37 | low = sp; | 36 | low = sp; |
@@ -48,10 +47,10 @@ static unsigned long save_context_stack(struct stack_trace *trace, | |||
48 | return sp; | 47 | return sp; |
49 | regs = (struct pt_regs *)sp; | 48 | regs = (struct pt_regs *)sp; |
50 | addr = regs->psw.addr & PSW_ADDR_INSN; | 49 | addr = regs->psw.addr & PSW_ADDR_INSN; |
51 | if (!(*skip)) | 50 | if (!trace->skip) |
52 | trace->entries[trace->nr_entries++] = addr; | 51 | trace->entries[trace->nr_entries++] = addr; |
53 | else | 52 | else |
54 | (*skip)--; | 53 | trace->skip--; |
55 | if (trace->nr_entries >= trace->max_entries) | 54 | if (trace->nr_entries >= trace->max_entries) |
56 | return sp; | 55 | return sp; |
57 | low = sp; | 56 | low = sp; |
@@ -65,20 +64,17 @@ void save_stack_trace(struct stack_trace *trace) | |||
65 | unsigned long orig_sp, new_sp; | 64 | unsigned long orig_sp, new_sp; |
66 | 65 | ||
67 | orig_sp = sp & PSW_ADDR_INSN; | 66 | orig_sp = sp & PSW_ADDR_INSN; |
68 | 67 | new_sp = save_context_stack(trace, orig_sp, | |
69 | new_sp = save_context_stack(trace, &trace->skip, orig_sp, | 68 | S390_lowcore.panic_stack - PAGE_SIZE, |
70 | S390_lowcore.panic_stack - PAGE_SIZE, | 69 | S390_lowcore.panic_stack); |
71 | S390_lowcore.panic_stack); | ||
72 | if (new_sp != orig_sp) | 70 | if (new_sp != orig_sp) |
73 | return; | 71 | return; |
74 | new_sp = save_context_stack(trace, &trace->skip, new_sp, | 72 | new_sp = save_context_stack(trace, new_sp, |
75 | S390_lowcore.async_stack - ASYNC_SIZE, | 73 | S390_lowcore.async_stack - ASYNC_SIZE, |
76 | S390_lowcore.async_stack); | 74 | S390_lowcore.async_stack); |
77 | if (new_sp != orig_sp) | 75 | if (new_sp != orig_sp) |
78 | return; | 76 | return; |
79 | 77 | save_context_stack(trace, new_sp, | |
80 | save_context_stack(trace, &trace->skip, new_sp, | ||
81 | S390_lowcore.thread_info, | 78 | S390_lowcore.thread_info, |
82 | S390_lowcore.thread_info + THREAD_SIZE); | 79 | S390_lowcore.thread_info + THREAD_SIZE); |
83 | return; | ||
84 | } | 80 | } |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 81e03b9c3841..8ec9def83ccb 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -262,6 +262,7 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
262 | print_modules(); | 262 | print_modules(); |
263 | show_regs(regs); | 263 | show_regs(regs); |
264 | bust_spinlocks(0); | 264 | bust_spinlocks(0); |
265 | add_taint(TAINT_DIE); | ||
265 | spin_unlock_irq(&die_lock); | 266 | spin_unlock_irq(&die_lock); |
266 | if (in_interrupt()) | 267 | if (in_interrupt()) |
267 | panic("Fatal exception in interrupt"); | 268 | panic("Fatal exception in interrupt"); |
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 7158a804a5e4..6ab7d4ee13a4 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S | |||
@@ -45,6 +45,8 @@ SECTIONS | |||
45 | __ex_table : { *(__ex_table) } | 45 | __ex_table : { *(__ex_table) } |
46 | __stop___ex_table = .; | 46 | __stop___ex_table = .; |
47 | 47 | ||
48 | NOTES | ||
49 | |||
48 | BUG_TABLE | 50 | BUG_TABLE |
49 | 51 | ||
50 | .data : { /* Data */ | 52 | .data : { /* Data */ |
@@ -107,10 +109,7 @@ SECTIONS | |||
107 | . = ALIGN(2); | 109 | . = ALIGN(2); |
108 | __initramfs_end = .; | 110 | __initramfs_end = .; |
109 | #endif | 111 | #endif |
110 | . = ALIGN(4096); | 112 | PERCPU(4096) |
111 | __per_cpu_start = .; | ||
112 | .data.percpu : { *(.data.percpu) } | ||
113 | __per_cpu_end = .; | ||
114 | . = ALIGN(4096); | 113 | . = ALIGN(4096); |
115 | __init_end = .; | 114 | __init_end = .; |
116 | /* freed after init ends here */ | 115 | /* freed after init ends here */ |
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 63181671e3e3..60604b2819b2 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c | |||
@@ -20,6 +20,7 @@ static int __handle_fault(struct mm_struct *mm, unsigned long address, | |||
20 | { | 20 | { |
21 | struct vm_area_struct *vma; | 21 | struct vm_area_struct *vma; |
22 | int ret = -EFAULT; | 22 | int ret = -EFAULT; |
23 | int fault; | ||
23 | 24 | ||
24 | if (in_atomic()) | 25 | if (in_atomic()) |
25 | return ret; | 26 | return ret; |
@@ -44,20 +45,18 @@ static int __handle_fault(struct mm_struct *mm, unsigned long address, | |||
44 | } | 45 | } |
45 | 46 | ||
46 | survive: | 47 | survive: |
47 | switch (handle_mm_fault(mm, vma, address, write_access)) { | 48 | fault = handle_mm_fault(mm, vma, address, write_access); |
48 | case VM_FAULT_MINOR: | 49 | if (unlikely(fault & VM_FAULT_ERROR)) { |
49 | current->min_flt++; | 50 | if (fault & VM_FAULT_OOM) |
50 | break; | 51 | goto out_of_memory; |
51 | case VM_FAULT_MAJOR: | 52 | else if (fault & VM_FAULT_SIGBUS) |
52 | current->maj_flt++; | 53 | goto out_sigbus; |
53 | break; | ||
54 | case VM_FAULT_SIGBUS: | ||
55 | goto out_sigbus; | ||
56 | case VM_FAULT_OOM: | ||
57 | goto out_of_memory; | ||
58 | default: | ||
59 | BUG(); | 54 | BUG(); |
60 | } | 55 | } |
56 | if (fault & VM_FAULT_MAJOR) | ||
57 | current->maj_flt++; | ||
58 | else | ||
59 | current->min_flt++; | ||
61 | ret = 0; | 60 | ret = 0; |
62 | out: | 61 | out: |
63 | up_read(&mm->mmap_sem); | 62 | up_read(&mm->mmap_sem); |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index d855cdbf8fb8..54055194e9af 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -307,6 +307,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write) | |||
307 | unsigned long address; | 307 | unsigned long address; |
308 | int space; | 308 | int space; |
309 | int si_code; | 309 | int si_code; |
310 | int fault; | ||
310 | 311 | ||
311 | if (notify_page_fault(regs, error_code)) | 312 | if (notify_page_fault(regs, error_code)) |
312 | return; | 313 | return; |
@@ -377,23 +378,22 @@ survive: | |||
377 | * make sure we exit gracefully rather than endlessly redo | 378 | * make sure we exit gracefully rather than endlessly redo |
378 | * the fault. | 379 | * the fault. |
379 | */ | 380 | */ |
380 | switch (handle_mm_fault(mm, vma, address, write)) { | 381 | fault = handle_mm_fault(mm, vma, address, write); |
381 | case VM_FAULT_MINOR: | 382 | if (unlikely(fault & VM_FAULT_ERROR)) { |
382 | tsk->min_flt++; | 383 | if (fault & VM_FAULT_OOM) { |
383 | break; | 384 | if (do_out_of_memory(regs, error_code, address)) |
384 | case VM_FAULT_MAJOR: | 385 | goto survive; |
385 | tsk->maj_flt++; | 386 | return; |
386 | break; | 387 | } else if (fault & VM_FAULT_SIGBUS) { |
387 | case VM_FAULT_SIGBUS: | 388 | do_sigbus(regs, error_code, address); |
388 | do_sigbus(regs, error_code, address); | 389 | return; |
389 | return; | 390 | } |
390 | case VM_FAULT_OOM: | ||
391 | if (do_out_of_memory(regs, error_code, address)) | ||
392 | goto survive; | ||
393 | return; | ||
394 | default: | ||
395 | BUG(); | 391 | BUG(); |
396 | } | 392 | } |
393 | if (fault & VM_FAULT_MAJOR) | ||
394 | tsk->maj_flt++; | ||
395 | else | ||
396 | tsk->min_flt++; | ||
397 | 397 | ||
398 | up_read(&mm->mmap_sem); | 398 | up_read(&mm->mmap_sem); |
399 | /* | 399 | /* |
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index f2eaa485d04d..891d1d46c902 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c | |||
@@ -91,17 +91,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
91 | switch (request) { | 91 | switch (request) { |
92 | /* when I and D space are separate, these will need to be fixed. */ | 92 | /* when I and D space are separate, these will need to be fixed. */ |
93 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 93 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
94 | case PTRACE_PEEKDATA: { | 94 | case PTRACE_PEEKDATA: |
95 | unsigned long tmp; | 95 | ret = generic_ptrace_peekdata(child, addr, data); |
96 | int copied; | ||
97 | |||
98 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
99 | ret = -EIO; | ||
100 | if (copied != sizeof(tmp)) | ||
101 | break; | ||
102 | ret = put_user(tmp,(unsigned long __user *) data); | ||
103 | break; | ||
104 | } | ||
105 | 96 | ||
106 | /* read the word at location addr in the USER area. */ | 97 | /* read the word at location addr in the USER area. */ |
107 | case PTRACE_PEEKUSR: { | 98 | case PTRACE_PEEKUSR: { |
@@ -135,10 +126,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
135 | /* when I and D space are separate, this will have to be fixed. */ | 126 | /* when I and D space are separate, this will have to be fixed. */ |
136 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 127 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
137 | case PTRACE_POKEDATA: | 128 | case PTRACE_POKEDATA: |
138 | ret = 0; | 129 | ret = generic_ptrace_pokedata(child, addr, data); |
139 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
140 | break; | ||
141 | ret = -EIO; | ||
142 | break; | 130 | break; |
143 | 131 | ||
144 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 132 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 05a40f3c30bf..502d43e4785c 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -103,6 +103,7 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
103 | (unsigned long)task_stack_page(current)); | 103 | (unsigned long)task_stack_page(current)); |
104 | 104 | ||
105 | bust_spinlocks(0); | 105 | bust_spinlocks(0); |
106 | add_taint(TAINT_DIE); | ||
106 | spin_unlock_irq(&die_lock); | 107 | spin_unlock_irq(&die_lock); |
107 | 108 | ||
108 | if (kexec_should_crash(current)) | 109 | if (kexec_should_crash(current)) |
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 0696402f446a..5ba216180b30 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S | |||
@@ -60,10 +60,7 @@ SECTIONS | |||
60 | . = ALIGN(PAGE_SIZE); | 60 | . = ALIGN(PAGE_SIZE); |
61 | __nosave_end = .; | 61 | __nosave_end = .; |
62 | 62 | ||
63 | . = ALIGN(PAGE_SIZE); | 63 | PERCPU(PAGE_SIZE) |
64 | __per_cpu_start = .; | ||
65 | .data.percpu : { *(.data.percpu) } | ||
66 | __per_cpu_end = .; | ||
67 | .data.cacheline_aligned : { *(.data.cacheline_aligned) } | 64 | .data.cacheline_aligned : { *(.data.cacheline_aligned) } |
68 | 65 | ||
69 | _edata = .; /* End of data section */ | 66 | _edata = .; /* End of data section */ |
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 0b3eaf6fbb28..964c6767dc73 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c | |||
@@ -33,6 +33,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
33 | struct mm_struct *mm; | 33 | struct mm_struct *mm; |
34 | struct vm_area_struct * vma; | 34 | struct vm_area_struct * vma; |
35 | int si_code; | 35 | int si_code; |
36 | int fault; | ||
36 | siginfo_t info; | 37 | siginfo_t info; |
37 | 38 | ||
38 | trace_hardirqs_on(); | 39 | trace_hardirqs_on(); |
@@ -124,20 +125,18 @@ good_area: | |||
124 | * the fault. | 125 | * the fault. |
125 | */ | 126 | */ |
126 | survive: | 127 | survive: |
127 | switch (handle_mm_fault(mm, vma, address, writeaccess)) { | 128 | fault = handle_mm_fault(mm, vma, address, writeaccess); |
128 | case VM_FAULT_MINOR: | 129 | if (unlikely(fault & VM_FAULT_ERROR)) { |
129 | tsk->min_flt++; | 130 | if (fault & VM_FAULT_OOM) |
130 | break; | ||
131 | case VM_FAULT_MAJOR: | ||
132 | tsk->maj_flt++; | ||
133 | break; | ||
134 | case VM_FAULT_SIGBUS: | ||
135 | goto do_sigbus; | ||
136 | case VM_FAULT_OOM: | ||
137 | goto out_of_memory; | 131 | goto out_of_memory; |
138 | default: | 132 | else if (fault & VM_FAULT_SIGBUS) |
139 | BUG(); | 133 | goto do_sigbus; |
134 | BUG(); | ||
140 | } | 135 | } |
136 | if (fault & VM_FAULT_MAJOR) | ||
137 | tsk->maj_flt++; | ||
138 | else | ||
139 | tsk->min_flt++; | ||
141 | 140 | ||
142 | up_read(&mm->mmap_sem); | 141 | up_read(&mm->mmap_sem); |
143 | return; | 142 | return; |
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index 4e95e18b46d9..df06c6477468 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c | |||
@@ -129,17 +129,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
129 | switch (request) { | 129 | switch (request) { |
130 | /* when I and D space are separate, these will need to be fixed. */ | 130 | /* when I and D space are separate, these will need to be fixed. */ |
131 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 131 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
132 | case PTRACE_PEEKDATA: { | 132 | case PTRACE_PEEKDATA: |
133 | unsigned long tmp; | 133 | ret = generic_ptrace_peekdata(child, addr, data); |
134 | int copied; | ||
135 | |||
136 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
137 | ret = -EIO; | ||
138 | if (copied != sizeof(tmp)) | ||
139 | break; | ||
140 | ret = put_user(tmp,(unsigned long *) data); | ||
141 | break; | 134 | break; |
142 | } | ||
143 | 135 | ||
144 | /* read the word at location addr in the USER area. */ | 136 | /* read the word at location addr in the USER area. */ |
145 | case PTRACE_PEEKUSR: { | 137 | case PTRACE_PEEKUSR: { |
@@ -166,10 +158,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
166 | /* when I and D space are separate, this will have to be fixed. */ | 158 | /* when I and D space are separate, this will have to be fixed. */ |
167 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 159 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
168 | case PTRACE_POKEDATA: | 160 | case PTRACE_POKEDATA: |
169 | ret = 0; | 161 | ret = generic_ptrace_pokedata(child, addr, data); |
170 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
171 | break; | ||
172 | ret = -EIO; | ||
173 | break; | 162 | break; |
174 | 163 | ||
175 | case PTRACE_POKEUSR: | 164 | case PTRACE_POKEUSR: |
diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S index 02aea86c5907..8ac9c7c5f848 100644 --- a/arch/sh64/kernel/vmlinux.lds.S +++ b/arch/sh64/kernel/vmlinux.lds.S | |||
@@ -87,7 +87,10 @@ SECTIONS | |||
87 | 87 | ||
88 | . = ALIGN(PAGE_SIZE); | 88 | . = ALIGN(PAGE_SIZE); |
89 | __per_cpu_start = .; | 89 | __per_cpu_start = .; |
90 | .data.percpu : C_PHYS(.data.percpu) { *(.data.percpu) } | 90 | .data.percpu : C_PHYS(.data.percpu) { |
91 | *(.data.percpu) | ||
92 | *(.data.percpu.shared_aligned) | ||
93 | } | ||
91 | __per_cpu_end = . ; | 94 | __per_cpu_end = . ; |
92 | .data.cacheline_aligned : C_PHYS(.data.cacheline_aligned) { *(.data.cacheline_aligned) } | 95 | .data.cacheline_aligned : C_PHYS(.data.cacheline_aligned) { *(.data.cacheline_aligned) } |
93 | 96 | ||
diff --git a/arch/sh64/lib/c-checksum.c b/arch/sh64/lib/c-checksum.c index 4b2676380deb..bd5501760240 100644 --- a/arch/sh64/lib/c-checksum.c +++ b/arch/sh64/lib/c-checksum.c | |||
@@ -213,3 +213,4 @@ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |||
213 | 213 | ||
214 | return (__wsum)result; | 214 | return (__wsum)result; |
215 | } | 215 | } |
216 | EXPORT_SYMBOL(csum_tcpudp_nofold); | ||
diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c index 3cd93ba5d826..0d069d82141f 100644 --- a/arch/sh64/mm/fault.c +++ b/arch/sh64/mm/fault.c | |||
@@ -127,6 +127,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, | |||
127 | struct vm_area_struct * vma; | 127 | struct vm_area_struct * vma; |
128 | const struct exception_table_entry *fixup; | 128 | const struct exception_table_entry *fixup; |
129 | pte_t *pte; | 129 | pte_t *pte; |
130 | int fault; | ||
130 | 131 | ||
131 | #if defined(CONFIG_SH64_PROC_TLB) | 132 | #if defined(CONFIG_SH64_PROC_TLB) |
132 | ++calls_to_do_slow_page_fault; | 133 | ++calls_to_do_slow_page_fault; |
@@ -221,18 +222,19 @@ good_area: | |||
221 | * the fault. | 222 | * the fault. |
222 | */ | 223 | */ |
223 | survive: | 224 | survive: |
224 | switch (handle_mm_fault(mm, vma, address, writeaccess)) { | 225 | fault = handle_mm_fault(mm, vma, address, writeaccess); |
225 | case VM_FAULT_MINOR: | 226 | if (unlikely(fault & VM_FAULT_ERROR)) { |
226 | tsk->min_flt++; | 227 | if (fault & VM_FAULT_OOM) |
227 | break; | 228 | goto out_of_memory; |
228 | case VM_FAULT_MAJOR: | 229 | else if (fault & VM_FAULT_SIGBUS) |
229 | tsk->maj_flt++; | 230 | goto do_sigbus; |
230 | break; | 231 | BUG(); |
231 | case VM_FAULT_SIGBUS: | ||
232 | goto do_sigbus; | ||
233 | default: | ||
234 | goto out_of_memory; | ||
235 | } | 232 | } |
233 | if (fault & VM_FAULT_MAJOR) | ||
234 | tsk->maj_flt++; | ||
235 | else | ||
236 | tsk->min_flt++; | ||
237 | |||
236 | /* If we get here, the page fault has been handled. Do the TLB refill | 238 | /* If we get here, the page fault has been handled. Do the TLB refill |
237 | now from the newly-setup PTE, to avoid having to fault again right | 239 | now from the newly-setup PTE, to avoid having to fault again right |
238 | away on the same instruction. */ | 240 | away on the same instruction. */ |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 8567cc901942..603d83ad65c8 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -21,6 +21,9 @@ config GENERIC_ISA_DMA | |||
21 | bool | 21 | bool |
22 | default y | 22 | default y |
23 | 23 | ||
24 | config ARCH_NO_VIRT_TO_BUS | ||
25 | def_bool y | ||
26 | |||
24 | source "init/Kconfig" | 27 | source "init/Kconfig" |
25 | 28 | ||
26 | menu "General machine setup" | 29 | menu "General machine setup" |
@@ -217,6 +220,9 @@ source "drivers/pci/Kconfig" | |||
217 | 220 | ||
218 | endif | 221 | endif |
219 | 222 | ||
223 | config NO_DMA | ||
224 | def_bool !PCI | ||
225 | |||
220 | config SUN_OPENPROMFS | 226 | config SUN_OPENPROMFS |
221 | tristate "Openprom tree appears in /proc/openprom" | 227 | tristate "Openprom tree appears in /proc/openprom" |
222 | help | 228 | help |
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index dc9ffea2a4f7..3bc3bff51e08 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c | |||
@@ -101,6 +101,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
101 | 101 | ||
102 | printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); | 102 | printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); |
103 | show_regs(regs); | 103 | show_regs(regs); |
104 | add_taint(TAINT_DIE); | ||
104 | 105 | ||
105 | __SAVE; __SAVE; __SAVE; __SAVE; | 106 | __SAVE; __SAVE; __SAVE; __SAVE; |
106 | __SAVE; __SAVE; __SAVE; __SAVE; | 107 | __SAVE; __SAVE; __SAVE; __SAVE; |
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index f75a1b822789..47583887abc6 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S | |||
@@ -65,10 +65,7 @@ SECTIONS | |||
65 | __initramfs_end = .; | 65 | __initramfs_end = .; |
66 | #endif | 66 | #endif |
67 | 67 | ||
68 | . = ALIGN(4096); | 68 | PERCPU(4096) |
69 | __per_cpu_start = .; | ||
70 | .data.percpu : { *(.data.percpu) } | ||
71 | __per_cpu_end = .; | ||
72 | . = ALIGN(4096); | 69 | . = ALIGN(4096); |
73 | __init_end = .; | 70 | __init_end = .; |
74 | . = ALIGN(32); | 71 | . = ALIGN(32); |
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c index c3483365db4b..50747fe44356 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault.c | |||
@@ -226,6 +226,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
226 | unsigned long g2; | 226 | unsigned long g2; |
227 | siginfo_t info; | 227 | siginfo_t info; |
228 | int from_user = !(regs->psr & PSR_PS); | 228 | int from_user = !(regs->psr & PSR_PS); |
229 | int fault; | ||
229 | 230 | ||
230 | if(text_fault) | 231 | if(text_fault) |
231 | address = regs->pc; | 232 | address = regs->pc; |
@@ -289,19 +290,18 @@ good_area: | |||
289 | * make sure we exit gracefully rather than endlessly redo | 290 | * make sure we exit gracefully rather than endlessly redo |
290 | * the fault. | 291 | * the fault. |
291 | */ | 292 | */ |
292 | switch (handle_mm_fault(mm, vma, address, write)) { | 293 | fault = handle_mm_fault(mm, vma, address, write); |
293 | case VM_FAULT_SIGBUS: | 294 | if (unlikely(fault & VM_FAULT_ERROR)) { |
294 | goto do_sigbus; | 295 | if (fault & VM_FAULT_OOM) |
295 | case VM_FAULT_OOM: | 296 | goto out_of_memory; |
296 | goto out_of_memory; | 297 | else if (fault & VM_FAULT_SIGBUS) |
297 | case VM_FAULT_MAJOR: | 298 | goto do_sigbus; |
299 | BUG(); | ||
300 | } | ||
301 | if (fault & VM_FAULT_MAJOR) | ||
298 | current->maj_flt++; | 302 | current->maj_flt++; |
299 | break; | 303 | else |
300 | case VM_FAULT_MINOR: | ||
301 | default: | ||
302 | current->min_flt++; | 304 | current->min_flt++; |
303 | break; | ||
304 | } | ||
305 | up_read(&mm->mmap_sem); | 305 | up_read(&mm->mmap_sem); |
306 | return; | 306 | return; |
307 | 307 | ||
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index b84b6af1241e..df6ee71894d1 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
@@ -62,6 +62,9 @@ config AUDIT_ARCH | |||
62 | bool | 62 | bool |
63 | default y | 63 | default y |
64 | 64 | ||
65 | config ARCH_NO_VIRT_TO_BUS | ||
66 | def_bool y | ||
67 | |||
65 | choice | 68 | choice |
66 | prompt "Kernel page size" | 69 | prompt "Kernel page size" |
67 | default SPARC64_PAGE_SIZE_8KB | 70 | default SPARC64_PAGE_SIZE_8KB |
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 65840a62bb9c..45ebf91a280c 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.22-rc1 | 3 | # Linux kernel version: 2.6.22 |
4 | # Mon May 14 04:17:48 2007 | 4 | # Tue Jul 17 01:19:52 2007 |
5 | # | 5 | # |
6 | CONFIG_SPARC=y | 6 | CONFIG_SPARC=y |
7 | CONFIG_SPARC64=y | 7 | CONFIG_SPARC64=y |
@@ -42,12 +42,11 @@ CONFIG_LOCALVERSION="" | |||
42 | # CONFIG_LOCALVERSION_AUTO is not set | 42 | # CONFIG_LOCALVERSION_AUTO is not set |
43 | CONFIG_SWAP=y | 43 | CONFIG_SWAP=y |
44 | CONFIG_SYSVIPC=y | 44 | CONFIG_SYSVIPC=y |
45 | # CONFIG_IPC_NS is not set | ||
46 | CONFIG_SYSVIPC_SYSCTL=y | 45 | CONFIG_SYSVIPC_SYSCTL=y |
47 | CONFIG_POSIX_MQUEUE=y | 46 | CONFIG_POSIX_MQUEUE=y |
48 | # CONFIG_BSD_PROCESS_ACCT is not set | 47 | # CONFIG_BSD_PROCESS_ACCT is not set |
49 | # CONFIG_TASKSTATS is not set | 48 | # CONFIG_TASKSTATS is not set |
50 | # CONFIG_UTS_NS is not set | 49 | # CONFIG_USER_NS is not set |
51 | # CONFIG_AUDIT is not set | 50 | # CONFIG_AUDIT is not set |
52 | # CONFIG_IKCONFIG is not set | 51 | # CONFIG_IKCONFIG is not set |
53 | CONFIG_LOG_BUF_SHIFT=18 | 52 | CONFIG_LOG_BUF_SHIFT=18 |
@@ -82,22 +81,15 @@ CONFIG_SLUB=y | |||
82 | CONFIG_RT_MUTEXES=y | 81 | CONFIG_RT_MUTEXES=y |
83 | # CONFIG_TINY_SHMEM is not set | 82 | # CONFIG_TINY_SHMEM is not set |
84 | CONFIG_BASE_SMALL=0 | 83 | CONFIG_BASE_SMALL=0 |
85 | |||
86 | # | ||
87 | # Loadable module support | ||
88 | # | ||
89 | CONFIG_MODULES=y | 84 | CONFIG_MODULES=y |
90 | CONFIG_MODULE_UNLOAD=y | 85 | CONFIG_MODULE_UNLOAD=y |
91 | CONFIG_MODULE_FORCE_UNLOAD=y | 86 | CONFIG_MODULE_FORCE_UNLOAD=y |
92 | CONFIG_MODVERSIONS=y | 87 | CONFIG_MODVERSIONS=y |
93 | CONFIG_MODULE_SRCVERSION_ALL=y | 88 | CONFIG_MODULE_SRCVERSION_ALL=y |
94 | CONFIG_KMOD=y | 89 | CONFIG_KMOD=y |
95 | |||
96 | # | ||
97 | # Block layer | ||
98 | # | ||
99 | CONFIG_BLOCK=y | 90 | CONFIG_BLOCK=y |
100 | CONFIG_BLK_DEV_IO_TRACE=y | 91 | CONFIG_BLK_DEV_IO_TRACE=y |
92 | CONFIG_BLK_DEV_BSG=y | ||
101 | 93 | ||
102 | # | 94 | # |
103 | # IO Schedulers | 95 | # IO Schedulers |
@@ -156,12 +148,15 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 | |||
156 | CONFIG_RESOURCES_64BIT=y | 148 | CONFIG_RESOURCES_64BIT=y |
157 | CONFIG_ZONE_DMA_FLAG=0 | 149 | CONFIG_ZONE_DMA_FLAG=0 |
158 | CONFIG_NR_QUICK=1 | 150 | CONFIG_NR_QUICK=1 |
151 | CONFIG_VIRT_TO_BUS=y | ||
159 | CONFIG_SBUS=y | 152 | CONFIG_SBUS=y |
160 | CONFIG_SBUSCHAR=y | 153 | CONFIG_SBUSCHAR=y |
161 | CONFIG_SUN_AUXIO=y | 154 | CONFIG_SUN_AUXIO=y |
162 | CONFIG_SUN_IO=y | 155 | CONFIG_SUN_IO=y |
156 | # CONFIG_SUN_LDOMS is not set | ||
163 | CONFIG_PCI=y | 157 | CONFIG_PCI=y |
164 | CONFIG_PCI_DOMAINS=y | 158 | CONFIG_PCI_DOMAINS=y |
159 | CONFIG_PCI_SYSCALL=y | ||
165 | CONFIG_ARCH_SUPPORTS_MSI=y | 160 | CONFIG_ARCH_SUPPORTS_MSI=y |
166 | CONFIG_PCI_MSI=y | 161 | CONFIG_PCI_MSI=y |
167 | # CONFIG_PCI_DEBUG is not set | 162 | # CONFIG_PCI_DEBUG is not set |
@@ -246,10 +241,6 @@ CONFIG_IPV6_TUNNEL=m | |||
246 | # CONFIG_IPV6_MULTIPLE_TABLES is not set | 241 | # CONFIG_IPV6_MULTIPLE_TABLES is not set |
247 | # CONFIG_NETWORK_SECMARK is not set | 242 | # CONFIG_NETWORK_SECMARK is not set |
248 | # CONFIG_NETFILTER is not set | 243 | # CONFIG_NETFILTER is not set |
249 | |||
250 | # | ||
251 | # DCCP Configuration (EXPERIMENTAL) | ||
252 | # | ||
253 | CONFIG_IP_DCCP=m | 244 | CONFIG_IP_DCCP=m |
254 | CONFIG_INET_DCCP_DIAG=m | 245 | CONFIG_INET_DCCP_DIAG=m |
255 | CONFIG_IP_DCCP_ACKVEC=y | 246 | CONFIG_IP_DCCP_ACKVEC=y |
@@ -269,15 +260,7 @@ CONFIG_IP_DCCP_CCID3_RTO=100 | |||
269 | # | 260 | # |
270 | # CONFIG_IP_DCCP_DEBUG is not set | 261 | # CONFIG_IP_DCCP_DEBUG is not set |
271 | # CONFIG_NET_DCCPPROBE is not set | 262 | # CONFIG_NET_DCCPPROBE is not set |
272 | |||
273 | # | ||
274 | # SCTP Configuration (EXPERIMENTAL) | ||
275 | # | ||
276 | # CONFIG_IP_SCTP is not set | 263 | # CONFIG_IP_SCTP is not set |
277 | |||
278 | # | ||
279 | # TIPC Configuration (EXPERIMENTAL) | ||
280 | # | ||
281 | # CONFIG_TIPC is not set | 264 | # CONFIG_TIPC is not set |
282 | # CONFIG_ATM is not set | 265 | # CONFIG_ATM is not set |
283 | # CONFIG_BRIDGE is not set | 266 | # CONFIG_BRIDGE is not set |
@@ -314,6 +297,7 @@ CONFIG_NET_TCPPROBE=m | |||
314 | # CONFIG_MAC80211 is not set | 297 | # CONFIG_MAC80211 is not set |
315 | # CONFIG_IEEE80211 is not set | 298 | # CONFIG_IEEE80211 is not set |
316 | # CONFIG_RFKILL is not set | 299 | # CONFIG_RFKILL is not set |
300 | # CONFIG_NET_9P is not set | ||
317 | 301 | ||
318 | # | 302 | # |
319 | # Device Drivers | 303 | # Device Drivers |
@@ -328,26 +312,10 @@ CONFIG_FW_LOADER=y | |||
328 | # CONFIG_DEBUG_DRIVER is not set | 312 | # CONFIG_DEBUG_DRIVER is not set |
329 | # CONFIG_DEBUG_DEVRES is not set | 313 | # CONFIG_DEBUG_DEVRES is not set |
330 | # CONFIG_SYS_HYPERVISOR is not set | 314 | # CONFIG_SYS_HYPERVISOR is not set |
331 | |||
332 | # | ||
333 | # Connector - unified userspace <-> kernelspace linker | ||
334 | # | ||
335 | CONFIG_CONNECTOR=m | 315 | CONFIG_CONNECTOR=m |
336 | # CONFIG_MTD is not set | 316 | # CONFIG_MTD is not set |
337 | |||
338 | # | ||
339 | # Parallel port support | ||
340 | # | ||
341 | # CONFIG_PARPORT is not set | 317 | # CONFIG_PARPORT is not set |
342 | 318 | CONFIG_BLK_DEV=y | |
343 | # | ||
344 | # Plug and Play support | ||
345 | # | ||
346 | # CONFIG_PNPACPI is not set | ||
347 | |||
348 | # | ||
349 | # Block devices | ||
350 | # | ||
351 | # CONFIG_BLK_DEV_FD is not set | 319 | # CONFIG_BLK_DEV_FD is not set |
352 | # CONFIG_BLK_CPQ_DA is not set | 320 | # CONFIG_BLK_CPQ_DA is not set |
353 | # CONFIG_BLK_CPQ_CISS_DA is not set | 321 | # CONFIG_BLK_CPQ_CISS_DA is not set |
@@ -364,18 +332,11 @@ CONFIG_CDROM_PKTCDVD=m | |||
364 | CONFIG_CDROM_PKTCDVD_BUFFERS=8 | 332 | CONFIG_CDROM_PKTCDVD_BUFFERS=8 |
365 | CONFIG_CDROM_PKTCDVD_WCACHE=y | 333 | CONFIG_CDROM_PKTCDVD_WCACHE=y |
366 | CONFIG_ATA_OVER_ETH=m | 334 | CONFIG_ATA_OVER_ETH=m |
367 | 335 | CONFIG_MISC_DEVICES=y | |
368 | # | ||
369 | # Misc devices | ||
370 | # | ||
371 | # CONFIG_PHANTOM is not set | 336 | # CONFIG_PHANTOM is not set |
337 | # CONFIG_EEPROM_93CX6 is not set | ||
372 | # CONFIG_SGI_IOC4 is not set | 338 | # CONFIG_SGI_IOC4 is not set |
373 | # CONFIG_TIFM_CORE is not set | 339 | # CONFIG_TIFM_CORE is not set |
374 | # CONFIG_BLINK is not set | ||
375 | |||
376 | # | ||
377 | # ATA/ATAPI/MFM/RLL support | ||
378 | # | ||
379 | CONFIG_IDE=y | 340 | CONFIG_IDE=y |
380 | CONFIG_BLK_DEV_IDE=y | 341 | CONFIG_BLK_DEV_IDE=y |
381 | 342 | ||
@@ -440,6 +401,7 @@ CONFIG_BLK_DEV_IDEDMA=y | |||
440 | # | 401 | # |
441 | CONFIG_RAID_ATTRS=m | 402 | CONFIG_RAID_ATTRS=m |
442 | CONFIG_SCSI=y | 403 | CONFIG_SCSI=y |
404 | CONFIG_SCSI_DMA=y | ||
443 | # CONFIG_SCSI_TGT is not set | 405 | # CONFIG_SCSI_TGT is not set |
444 | CONFIG_SCSI_NETLINK=y | 406 | CONFIG_SCSI_NETLINK=y |
445 | CONFIG_SCSI_PROC_FS=y | 407 | CONFIG_SCSI_PROC_FS=y |
@@ -505,7 +467,6 @@ CONFIG_ISCSI_TCP=m | |||
505 | # CONFIG_SCSI_DC395x is not set | 467 | # CONFIG_SCSI_DC395x is not set |
506 | # CONFIG_SCSI_DC390T is not set | 468 | # CONFIG_SCSI_DC390T is not set |
507 | # CONFIG_SCSI_DEBUG is not set | 469 | # CONFIG_SCSI_DEBUG is not set |
508 | # CONFIG_SCSI_ESP_CORE is not set | ||
509 | # CONFIG_SCSI_SUNESP is not set | 470 | # CONFIG_SCSI_SUNESP is not set |
510 | # CONFIG_SCSI_SRP is not set | 471 | # CONFIG_SCSI_SRP is not set |
511 | # CONFIG_ATA is not set | 472 | # CONFIG_ATA is not set |
@@ -545,30 +506,16 @@ CONFIG_DM_ZERO=m | |||
545 | # | 506 | # |
546 | # CONFIG_FIREWIRE is not set | 507 | # CONFIG_FIREWIRE is not set |
547 | # CONFIG_IEEE1394 is not set | 508 | # CONFIG_IEEE1394 is not set |
548 | |||
549 | # | ||
550 | # I2O device support | ||
551 | # | ||
552 | # CONFIG_I2O is not set | 509 | # CONFIG_I2O is not set |
553 | |||
554 | # | ||
555 | # Network device support | ||
556 | # | ||
557 | CONFIG_NETDEVICES=y | 510 | CONFIG_NETDEVICES=y |
511 | # CONFIG_NETDEVICES_MULTIQUEUE is not set | ||
558 | CONFIG_DUMMY=m | 512 | CONFIG_DUMMY=m |
559 | # CONFIG_BONDING is not set | 513 | # CONFIG_BONDING is not set |
514 | # CONFIG_MACVLAN is not set | ||
560 | # CONFIG_EQUALIZER is not set | 515 | # CONFIG_EQUALIZER is not set |
561 | # CONFIG_TUN is not set | 516 | # CONFIG_TUN is not set |
562 | |||
563 | # | ||
564 | # ARCnet devices | ||
565 | # | ||
566 | # CONFIG_ARCNET is not set | 517 | # CONFIG_ARCNET is not set |
567 | # CONFIG_PHYLIB is not set | 518 | # CONFIG_PHYLIB is not set |
568 | |||
569 | # | ||
570 | # Ethernet (10 or 100Mbit) | ||
571 | # | ||
572 | CONFIG_NET_ETHERNET=y | 519 | CONFIG_NET_ETHERNET=y |
573 | CONFIG_MII=m | 520 | CONFIG_MII=m |
574 | # CONFIG_SUNLANCE is not set | 521 | # CONFIG_SUNLANCE is not set |
@@ -578,10 +525,6 @@ CONFIG_MII=m | |||
578 | # CONFIG_SUNGEM is not set | 525 | # CONFIG_SUNGEM is not set |
579 | CONFIG_CASSINI=m | 526 | CONFIG_CASSINI=m |
580 | # CONFIG_NET_VENDOR_3COM is not set | 527 | # CONFIG_NET_VENDOR_3COM is not set |
581 | |||
582 | # | ||
583 | # Tulip family network device support | ||
584 | # | ||
585 | # CONFIG_NET_TULIP is not set | 528 | # CONFIG_NET_TULIP is not set |
586 | # CONFIG_HP100 is not set | 529 | # CONFIG_HP100 is not set |
587 | CONFIG_NET_PCI=y | 530 | CONFIG_NET_PCI=y |
@@ -617,7 +560,6 @@ CONFIG_E1000_NAPI=y | |||
617 | # CONFIG_SIS190 is not set | 560 | # CONFIG_SIS190 is not set |
618 | # CONFIG_SKGE is not set | 561 | # CONFIG_SKGE is not set |
619 | # CONFIG_SKY2 is not set | 562 | # CONFIG_SKY2 is not set |
620 | # CONFIG_SK98LIN is not set | ||
621 | # CONFIG_VIA_VELOCITY is not set | 563 | # CONFIG_VIA_VELOCITY is not set |
622 | CONFIG_TIGON3=m | 564 | CONFIG_TIGON3=m |
623 | CONFIG_BNX2=m | 565 | CONFIG_BNX2=m |
@@ -631,11 +573,6 @@ CONFIG_NETDEV_10000=y | |||
631 | # CONFIG_MYRI10GE is not set | 573 | # CONFIG_MYRI10GE is not set |
632 | # CONFIG_NETXEN_NIC is not set | 574 | # CONFIG_NETXEN_NIC is not set |
633 | # CONFIG_MLX4_CORE is not set | 575 | # CONFIG_MLX4_CORE is not set |
634 | CONFIG_MLX4_DEBUG=y | ||
635 | |||
636 | # | ||
637 | # Token Ring devices | ||
638 | # | ||
639 | # CONFIG_TR is not set | 576 | # CONFIG_TR is not set |
640 | 577 | ||
641 | # | 578 | # |
@@ -665,6 +602,7 @@ CONFIG_PPP_DEFLATE=m | |||
665 | CONFIG_PPP_BSDCOMP=m | 602 | CONFIG_PPP_BSDCOMP=m |
666 | CONFIG_PPP_MPPE=m | 603 | CONFIG_PPP_MPPE=m |
667 | CONFIG_PPPOE=m | 604 | CONFIG_PPPOE=m |
605 | # CONFIG_PPPOL2TP is not set | ||
668 | # CONFIG_SLIP is not set | 606 | # CONFIG_SLIP is not set |
669 | CONFIG_SLHC=m | 607 | CONFIG_SLHC=m |
670 | # CONFIG_NET_FC is not set | 608 | # CONFIG_NET_FC is not set |
@@ -677,10 +615,6 @@ CONFIG_SLHC=m | |||
677 | # ISDN subsystem | 615 | # ISDN subsystem |
678 | # | 616 | # |
679 | # CONFIG_ISDN is not set | 617 | # CONFIG_ISDN is not set |
680 | |||
681 | # | ||
682 | # Telephony Support | ||
683 | # | ||
684 | # CONFIG_PHONE is not set | 618 | # CONFIG_PHONE is not set |
685 | 619 | ||
686 | # | 620 | # |
@@ -688,6 +622,7 @@ CONFIG_SLHC=m | |||
688 | # | 622 | # |
689 | CONFIG_INPUT=y | 623 | CONFIG_INPUT=y |
690 | # CONFIG_INPUT_FF_MEMLESS is not set | 624 | # CONFIG_INPUT_FF_MEMLESS is not set |
625 | # CONFIG_INPUT_POLLDEV is not set | ||
691 | 626 | ||
692 | # | 627 | # |
693 | # Userland interfaces | 628 | # Userland interfaces |
@@ -733,7 +668,6 @@ CONFIG_INPUT_SPARCSPKR=y | |||
733 | # CONFIG_INPUT_POWERMATE is not set | 668 | # CONFIG_INPUT_POWERMATE is not set |
734 | # CONFIG_INPUT_YEALINK is not set | 669 | # CONFIG_INPUT_YEALINK is not set |
735 | # CONFIG_INPUT_UINPUT is not set | 670 | # CONFIG_INPUT_UINPUT is not set |
736 | # CONFIG_INPUT_POLLDEV is not set | ||
737 | 671 | ||
738 | # | 672 | # |
739 | # Hardware I/O ports | 673 | # Hardware I/O ports |
@@ -773,10 +707,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y | |||
773 | # CONFIG_SERIAL_JSM is not set | 707 | # CONFIG_SERIAL_JSM is not set |
774 | CONFIG_UNIX98_PTYS=y | 708 | CONFIG_UNIX98_PTYS=y |
775 | # CONFIG_LEGACY_PTYS is not set | 709 | # CONFIG_LEGACY_PTYS is not set |
776 | |||
777 | # | ||
778 | # IPMI | ||
779 | # | ||
780 | # CONFIG_IPMI_HANDLER is not set | 710 | # CONFIG_IPMI_HANDLER is not set |
781 | # CONFIG_WATCHDOG is not set | 711 | # CONFIG_WATCHDOG is not set |
782 | # CONFIG_HW_RANDOM is not set | 712 | # CONFIG_HW_RANDOM is not set |
@@ -785,10 +715,6 @@ CONFIG_RTC=y | |||
785 | # CONFIG_APPLICOM is not set | 715 | # CONFIG_APPLICOM is not set |
786 | # CONFIG_DRM is not set | 716 | # CONFIG_DRM is not set |
787 | # CONFIG_RAW_DRIVER is not set | 717 | # CONFIG_RAW_DRIVER is not set |
788 | |||
789 | # | ||
790 | # TPM devices | ||
791 | # | ||
792 | # CONFIG_TCG_TPM is not set | 718 | # CONFIG_TCG_TPM is not set |
793 | CONFIG_DEVPORT=y | 719 | CONFIG_DEVPORT=y |
794 | CONFIG_I2C=y | 720 | CONFIG_I2C=y |
@@ -822,6 +748,7 @@ CONFIG_I2C_ALGOBIT=y | |||
822 | # CONFIG_I2C_SIS5595 is not set | 748 | # CONFIG_I2C_SIS5595 is not set |
823 | # CONFIG_I2C_SIS630 is not set | 749 | # CONFIG_I2C_SIS630 is not set |
824 | # CONFIG_I2C_SIS96X is not set | 750 | # CONFIG_I2C_SIS96X is not set |
751 | # CONFIG_I2C_TAOS_EVM is not set | ||
825 | # CONFIG_I2C_STUB is not set | 752 | # CONFIG_I2C_STUB is not set |
826 | # CONFIG_I2C_TINY_USB is not set | 753 | # CONFIG_I2C_TINY_USB is not set |
827 | # CONFIG_I2C_VIA is not set | 754 | # CONFIG_I2C_VIA is not set |
@@ -833,11 +760,13 @@ CONFIG_I2C_ALGOBIT=y | |||
833 | # | 760 | # |
834 | # CONFIG_SENSORS_DS1337 is not set | 761 | # CONFIG_SENSORS_DS1337 is not set |
835 | # CONFIG_SENSORS_DS1374 is not set | 762 | # CONFIG_SENSORS_DS1374 is not set |
763 | # CONFIG_DS1682 is not set | ||
836 | # CONFIG_SENSORS_EEPROM is not set | 764 | # CONFIG_SENSORS_EEPROM is not set |
837 | # CONFIG_SENSORS_PCF8574 is not set | 765 | # CONFIG_SENSORS_PCF8574 is not set |
838 | # CONFIG_SENSORS_PCA9539 is not set | 766 | # CONFIG_SENSORS_PCA9539 is not set |
839 | # CONFIG_SENSORS_PCF8591 is not set | 767 | # CONFIG_SENSORS_PCF8591 is not set |
840 | # CONFIG_SENSORS_MAX6875 is not set | 768 | # CONFIG_SENSORS_MAX6875 is not set |
769 | # CONFIG_SENSORS_TSL2550 is not set | ||
841 | # CONFIG_I2C_DEBUG_CORE is not set | 770 | # CONFIG_I2C_DEBUG_CORE is not set |
842 | # CONFIG_I2C_DEBUG_ALGO is not set | 771 | # CONFIG_I2C_DEBUG_ALGO is not set |
843 | # CONFIG_I2C_DEBUG_BUS is not set | 772 | # CONFIG_I2C_DEBUG_BUS is not set |
@@ -848,11 +777,8 @@ CONFIG_I2C_ALGOBIT=y | |||
848 | # | 777 | # |
849 | # CONFIG_SPI is not set | 778 | # CONFIG_SPI is not set |
850 | # CONFIG_SPI_MASTER is not set | 779 | # CONFIG_SPI_MASTER is not set |
851 | |||
852 | # | ||
853 | # Dallas's 1-wire bus | ||
854 | # | ||
855 | # CONFIG_W1 is not set | 780 | # CONFIG_W1 is not set |
781 | # CONFIG_POWER_SUPPLY is not set | ||
856 | CONFIG_HWMON=y | 782 | CONFIG_HWMON=y |
857 | # CONFIG_HWMON_VID is not set | 783 | # CONFIG_HWMON_VID is not set |
858 | # CONFIG_SENSORS_ABITUGURU is not set | 784 | # CONFIG_SENSORS_ABITUGURU is not set |
@@ -949,6 +875,8 @@ CONFIG_FB_TILEBLITTING=y | |||
949 | # CONFIG_FB_ASILIANT is not set | 875 | # CONFIG_FB_ASILIANT is not set |
950 | # CONFIG_FB_IMSTT is not set | 876 | # CONFIG_FB_IMSTT is not set |
951 | # CONFIG_FB_SBUS is not set | 877 | # CONFIG_FB_SBUS is not set |
878 | # CONFIG_FB_XVR500 is not set | ||
879 | # CONFIG_FB_XVR2500 is not set | ||
952 | # CONFIG_FB_S1D13XXX is not set | 880 | # CONFIG_FB_S1D13XXX is not set |
953 | # CONFIG_FB_NVIDIA is not set | 881 | # CONFIG_FB_NVIDIA is not set |
954 | # CONFIG_FB_RIVA is not set | 882 | # CONFIG_FB_RIVA is not set |
@@ -970,9 +898,6 @@ CONFIG_FB_RADEON_I2C=y | |||
970 | # CONFIG_FB_TRIDENT is not set | 898 | # CONFIG_FB_TRIDENT is not set |
971 | # CONFIG_FB_ARK is not set | 899 | # CONFIG_FB_ARK is not set |
972 | # CONFIG_FB_PM3 is not set | 900 | # CONFIG_FB_PM3 is not set |
973 | # CONFIG_FB_XVR500 is not set | ||
974 | # CONFIG_FB_XVR2500 is not set | ||
975 | # CONFIG_FB_PCI is not set | ||
976 | # CONFIG_FB_VIRTUAL is not set | 901 | # CONFIG_FB_VIRTUAL is not set |
977 | 902 | ||
978 | # | 903 | # |
@@ -1118,10 +1043,7 @@ CONFIG_SND_SUN_CS4231=m | |||
1118 | # | 1043 | # |
1119 | # CONFIG_SOUND_PRIME is not set | 1044 | # CONFIG_SOUND_PRIME is not set |
1120 | CONFIG_AC97_BUS=m | 1045 | CONFIG_AC97_BUS=m |
1121 | 1046 | CONFIG_HID_SUPPORT=y | |
1122 | # | ||
1123 | # HID Devices | ||
1124 | # | ||
1125 | CONFIG_HID=y | 1047 | CONFIG_HID=y |
1126 | # CONFIG_HID_DEBUG is not set | 1048 | # CONFIG_HID_DEBUG is not set |
1127 | 1049 | ||
@@ -1132,10 +1054,7 @@ CONFIG_USB_HID=y | |||
1132 | # CONFIG_USB_HIDINPUT_POWERBOOK is not set | 1054 | # CONFIG_USB_HIDINPUT_POWERBOOK is not set |
1133 | # CONFIG_HID_FF is not set | 1055 | # CONFIG_HID_FF is not set |
1134 | CONFIG_USB_HIDDEV=y | 1056 | CONFIG_USB_HIDDEV=y |
1135 | 1057 | CONFIG_USB_SUPPORT=y | |
1136 | # | ||
1137 | # USB support | ||
1138 | # | ||
1139 | CONFIG_USB_ARCH_HAS_HCD=y | 1058 | CONFIG_USB_ARCH_HAS_HCD=y |
1140 | CONFIG_USB_ARCH_HAS_OHCI=y | 1059 | CONFIG_USB_ARCH_HAS_OHCI=y |
1141 | CONFIG_USB_ARCH_HAS_EHCI=y | 1060 | CONFIG_USB_ARCH_HAS_EHCI=y |
@@ -1157,7 +1076,6 @@ CONFIG_USB_EHCI_HCD=m | |||
1157 | # CONFIG_USB_EHCI_SPLIT_ISO is not set | 1076 | # CONFIG_USB_EHCI_SPLIT_ISO is not set |
1158 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set | 1077 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set |
1159 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set | 1078 | # CONFIG_USB_EHCI_TT_NEWSCHED is not set |
1160 | # CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set | ||
1161 | # CONFIG_USB_ISP116X_HCD is not set | 1079 | # CONFIG_USB_ISP116X_HCD is not set |
1162 | CONFIG_USB_OHCI_HCD=y | 1080 | CONFIG_USB_OHCI_HCD=y |
1163 | # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set | 1081 | # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set |
@@ -1165,6 +1083,7 @@ CONFIG_USB_OHCI_HCD=y | |||
1165 | CONFIG_USB_OHCI_LITTLE_ENDIAN=y | 1083 | CONFIG_USB_OHCI_LITTLE_ENDIAN=y |
1166 | CONFIG_USB_UHCI_HCD=m | 1084 | CONFIG_USB_UHCI_HCD=m |
1167 | # CONFIG_USB_SL811_HCD is not set | 1085 | # CONFIG_USB_SL811_HCD is not set |
1086 | # CONFIG_USB_R8A66597_HCD is not set | ||
1168 | 1087 | ||
1169 | # | 1088 | # |
1170 | # USB Device Class drivers | 1089 | # USB Device Class drivers |
@@ -1256,17 +1175,9 @@ CONFIG_USB_STORAGE=m | |||
1256 | # | 1175 | # |
1257 | # LED Triggers | 1176 | # LED Triggers |
1258 | # | 1177 | # |
1259 | |||
1260 | # | ||
1261 | # InfiniBand support | ||
1262 | # | ||
1263 | # CONFIG_INFINIBAND is not set | 1178 | # CONFIG_INFINIBAND is not set |
1264 | 1179 | ||
1265 | # | 1180 | # |
1266 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) | ||
1267 | # | ||
1268 | |||
1269 | # | ||
1270 | # Real Time Clock | 1181 | # Real Time Clock |
1271 | # | 1182 | # |
1272 | # CONFIG_RTC_CLASS is not set | 1183 | # CONFIG_RTC_CLASS is not set |
@@ -1387,7 +1298,6 @@ CONFIG_RAMFS=y | |||
1387 | # CONFIG_NCP_FS is not set | 1298 | # CONFIG_NCP_FS is not set |
1388 | # CONFIG_CODA_FS is not set | 1299 | # CONFIG_CODA_FS is not set |
1389 | # CONFIG_AFS_FS is not set | 1300 | # CONFIG_AFS_FS is not set |
1390 | # CONFIG_9P_FS is not set | ||
1391 | 1301 | ||
1392 | # | 1302 | # |
1393 | # Partition Types | 1303 | # Partition Types |
@@ -1465,8 +1375,10 @@ CONFIG_DEBUG_FS=y | |||
1465 | CONFIG_DEBUG_KERNEL=y | 1375 | CONFIG_DEBUG_KERNEL=y |
1466 | # CONFIG_DEBUG_SHIRQ is not set | 1376 | # CONFIG_DEBUG_SHIRQ is not set |
1467 | CONFIG_DETECT_SOFTLOCKUP=y | 1377 | CONFIG_DETECT_SOFTLOCKUP=y |
1378 | # CONFIG_SCHED_DEBUG is not set | ||
1468 | CONFIG_SCHEDSTATS=y | 1379 | CONFIG_SCHEDSTATS=y |
1469 | # CONFIG_TIMER_STATS is not set | 1380 | # CONFIG_TIMER_STATS is not set |
1381 | # CONFIG_SLUB_DEBUG_ON is not set | ||
1470 | # CONFIG_DEBUG_RT_MUTEXES is not set | 1382 | # CONFIG_DEBUG_RT_MUTEXES is not set |
1471 | # CONFIG_RT_MUTEX_TESTER is not set | 1383 | # CONFIG_RT_MUTEX_TESTER is not set |
1472 | # CONFIG_DEBUG_SPINLOCK is not set | 1384 | # CONFIG_DEBUG_SPINLOCK is not set |
@@ -1496,10 +1408,10 @@ CONFIG_FORCED_INLINING=y | |||
1496 | CONFIG_KEYS=y | 1408 | CONFIG_KEYS=y |
1497 | # CONFIG_KEYS_DEBUG_PROC_KEYS is not set | 1409 | # CONFIG_KEYS_DEBUG_PROC_KEYS is not set |
1498 | # CONFIG_SECURITY is not set | 1410 | # CONFIG_SECURITY is not set |
1499 | 1411 | CONFIG_XOR_BLOCKS=m | |
1500 | # | 1412 | CONFIG_ASYNC_CORE=m |
1501 | # Cryptographic options | 1413 | CONFIG_ASYNC_MEMCPY=m |
1502 | # | 1414 | CONFIG_ASYNC_XOR=m |
1503 | CONFIG_CRYPTO=y | 1415 | CONFIG_CRYPTO=y |
1504 | CONFIG_CRYPTO_ALGAPI=y | 1416 | CONFIG_CRYPTO_ALGAPI=y |
1505 | CONFIG_CRYPTO_BLKCIPHER=y | 1417 | CONFIG_CRYPTO_BLKCIPHER=y |
@@ -1539,10 +1451,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=m | |||
1539 | CONFIG_CRYPTO_CRC32C=m | 1451 | CONFIG_CRYPTO_CRC32C=m |
1540 | CONFIG_CRYPTO_CAMELLIA=m | 1452 | CONFIG_CRYPTO_CAMELLIA=m |
1541 | CONFIG_CRYPTO_TEST=m | 1453 | CONFIG_CRYPTO_TEST=m |
1542 | 1454 | CONFIG_CRYPTO_HW=y | |
1543 | # | ||
1544 | # Hardware crypto devices | ||
1545 | # | ||
1546 | 1455 | ||
1547 | # | 1456 | # |
1548 | # Library routines | 1457 | # Library routines |
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index 1c587107cef0..fa1f04d756a2 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c | |||
@@ -228,7 +228,7 @@ static struct ds_cap_state *find_cap_by_string(const char *name) | |||
228 | return NULL; | 228 | return NULL; |
229 | } | 229 | } |
230 | 230 | ||
231 | static int ds_send(struct ldc_channel *lp, void *data, int len) | 231 | static int __ds_send(struct ldc_channel *lp, void *data, int len) |
232 | { | 232 | { |
233 | int err, limit = 1000; | 233 | int err, limit = 1000; |
234 | 234 | ||
@@ -243,6 +243,18 @@ static int ds_send(struct ldc_channel *lp, void *data, int len) | |||
243 | return err; | 243 | return err; |
244 | } | 244 | } |
245 | 245 | ||
246 | static int ds_send(struct ldc_channel *lp, void *data, int len) | ||
247 | { | ||
248 | unsigned long flags; | ||
249 | int err; | ||
250 | |||
251 | spin_lock_irqsave(&ds_lock, flags); | ||
252 | err = __ds_send(lp, data, len); | ||
253 | spin_unlock_irqrestore(&ds_lock, flags); | ||
254 | |||
255 | return err; | ||
256 | } | ||
257 | |||
246 | struct ds_md_update_req { | 258 | struct ds_md_update_req { |
247 | __u64 req_num; | 259 | __u64 req_num; |
248 | }; | 260 | }; |
@@ -267,6 +279,8 @@ static void md_update_data(struct ldc_channel *lp, | |||
267 | 279 | ||
268 | printk(KERN_INFO PFX "Machine description update.\n"); | 280 | printk(KERN_INFO PFX "Machine description update.\n"); |
269 | 281 | ||
282 | mdesc_update(); | ||
283 | |||
270 | memset(&pkt, 0, sizeof(pkt)); | 284 | memset(&pkt, 0, sizeof(pkt)); |
271 | pkt.data.tag.type = DS_DATA; | 285 | pkt.data.tag.type = DS_DATA; |
272 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); | 286 | pkt.data.tag.len = sizeof(pkt) - sizeof(struct ds_msg_tag); |
@@ -275,8 +289,6 @@ static void md_update_data(struct ldc_channel *lp, | |||
275 | pkt.res.result = DS_OK; | 289 | pkt.res.result = DS_OK; |
276 | 290 | ||
277 | ds_send(lp, &pkt, sizeof(pkt)); | 291 | ds_send(lp, &pkt, sizeof(pkt)); |
278 | |||
279 | mdesc_update(); | ||
280 | } | 292 | } |
281 | 293 | ||
282 | struct ds_shutdown_req { | 294 | struct ds_shutdown_req { |
@@ -391,18 +403,6 @@ struct dr_cpu_resp_entry { | |||
391 | __u32 str_off; | 403 | __u32 str_off; |
392 | }; | 404 | }; |
393 | 405 | ||
394 | /* DR cpu requests get queued onto the work list by the | ||
395 | * dr_cpu_data() callback. The list is protected by | ||
396 | * ds_lock, and processed by dr_cpu_process() in order. | ||
397 | */ | ||
398 | static LIST_HEAD(dr_cpu_work_list); | ||
399 | static DECLARE_WAIT_QUEUE_HEAD(dr_cpu_wait); | ||
400 | |||
401 | struct dr_cpu_queue_entry { | ||
402 | struct list_head list; | ||
403 | char req[0]; | ||
404 | }; | ||
405 | |||
406 | static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | 406 | static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) |
407 | { | 407 | { |
408 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); | 408 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); |
@@ -425,7 +425,7 @@ static void __dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | |||
425 | 425 | ||
426 | pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag); | 426 | pkt.data.tag.len = msg_len - sizeof(struct ds_msg_tag); |
427 | 427 | ||
428 | ds_send(dp->lp, &pkt, msg_len); | 428 | __ds_send(dp->lp, &pkt, msg_len); |
429 | } | 429 | } |
430 | 430 | ||
431 | static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) | 431 | static void dr_cpu_send_error(struct ds_cap_state *cp, struct ds_data *data) |
@@ -555,7 +555,7 @@ static int dr_cpu_configure(struct ds_cap_state *cp, u64 req_num, | |||
555 | } | 555 | } |
556 | 556 | ||
557 | spin_lock_irqsave(&ds_lock, flags); | 557 | spin_lock_irqsave(&ds_lock, flags); |
558 | ds_send(ds_info->lp, resp, resp_len); | 558 | __ds_send(ds_info->lp, resp, resp_len); |
559 | spin_unlock_irqrestore(&ds_lock, flags); | 559 | spin_unlock_irqrestore(&ds_lock, flags); |
560 | 560 | ||
561 | kfree(resp); | 561 | kfree(resp); |
@@ -596,7 +596,7 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
596 | } | 596 | } |
597 | 597 | ||
598 | spin_lock_irqsave(&ds_lock, flags); | 598 | spin_lock_irqsave(&ds_lock, flags); |
599 | ds_send(ds_info->lp, resp, resp_len); | 599 | __ds_send(ds_info->lp, resp, resp_len); |
600 | spin_unlock_irqrestore(&ds_lock, flags); | 600 | spin_unlock_irqrestore(&ds_lock, flags); |
601 | 601 | ||
602 | kfree(resp); | 602 | kfree(resp); |
@@ -604,107 +604,49 @@ static int dr_cpu_unconfigure(struct ds_cap_state *cp, u64 req_num, | |||
604 | return 0; | 604 | return 0; |
605 | } | 605 | } |
606 | 606 | ||
607 | static void process_dr_cpu_list(struct ds_cap_state *cp) | 607 | static void dr_cpu_data(struct ldc_channel *lp, |
608 | struct ds_cap_state *cp, | ||
609 | void *buf, int len) | ||
608 | { | 610 | { |
609 | struct dr_cpu_queue_entry *qp, *tmp; | 611 | struct ds_data *data = buf; |
610 | unsigned long flags; | 612 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); |
611 | LIST_HEAD(todo); | 613 | u32 *cpu_list = (u32 *) (tag + 1); |
614 | u64 req_num = tag->req_num; | ||
612 | cpumask_t mask; | 615 | cpumask_t mask; |
616 | unsigned int i; | ||
617 | int err; | ||
613 | 618 | ||
614 | spin_lock_irqsave(&ds_lock, flags); | 619 | switch (tag->type) { |
615 | list_splice(&dr_cpu_work_list, &todo); | 620 | case DR_CPU_CONFIGURE: |
616 | INIT_LIST_HEAD(&dr_cpu_work_list); | 621 | case DR_CPU_UNCONFIGURE: |
617 | spin_unlock_irqrestore(&ds_lock, flags); | 622 | case DR_CPU_FORCE_UNCONFIGURE: |
618 | 623 | break; | |
619 | list_for_each_entry_safe(qp, tmp, &todo, list) { | ||
620 | struct ds_data *data = (struct ds_data *) qp->req; | ||
621 | struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1); | ||
622 | u32 *cpu_list = (u32 *) (tag + 1); | ||
623 | u64 req_num = tag->req_num; | ||
624 | unsigned int i; | ||
625 | int err; | ||
626 | |||
627 | switch (tag->type) { | ||
628 | case DR_CPU_CONFIGURE: | ||
629 | case DR_CPU_UNCONFIGURE: | ||
630 | case DR_CPU_FORCE_UNCONFIGURE: | ||
631 | break; | ||
632 | |||
633 | default: | ||
634 | dr_cpu_send_error(cp, data); | ||
635 | goto next; | ||
636 | } | ||
637 | |||
638 | purge_dups(cpu_list, tag->num_records); | ||
639 | |||
640 | cpus_clear(mask); | ||
641 | for (i = 0; i < tag->num_records; i++) { | ||
642 | if (cpu_list[i] == CPU_SENTINEL) | ||
643 | continue; | ||
644 | |||
645 | if (cpu_list[i] < NR_CPUS) | ||
646 | cpu_set(cpu_list[i], mask); | ||
647 | } | ||
648 | |||
649 | if (tag->type == DR_CPU_CONFIGURE) | ||
650 | err = dr_cpu_configure(cp, req_num, &mask); | ||
651 | else | ||
652 | err = dr_cpu_unconfigure(cp, req_num, &mask); | ||
653 | |||
654 | if (err) | ||
655 | dr_cpu_send_error(cp, data); | ||
656 | 624 | ||
657 | next: | 625 | default: |
658 | list_del(&qp->list); | 626 | dr_cpu_send_error(cp, data); |
659 | kfree(qp); | 627 | return; |
660 | } | 628 | } |
661 | } | ||
662 | 629 | ||
663 | static int dr_cpu_thread(void *__unused) | 630 | purge_dups(cpu_list, tag->num_records); |
664 | { | ||
665 | struct ds_cap_state *cp; | ||
666 | DEFINE_WAIT(wait); | ||
667 | 631 | ||
668 | cp = find_cap_by_string("dr-cpu"); | 632 | cpus_clear(mask); |
669 | 633 | for (i = 0; i < tag->num_records; i++) { | |
670 | while (1) { | 634 | if (cpu_list[i] == CPU_SENTINEL) |
671 | prepare_to_wait(&dr_cpu_wait, &wait, TASK_INTERRUPTIBLE); | 635 | continue; |
672 | if (list_empty(&dr_cpu_work_list)) | ||
673 | schedule(); | ||
674 | finish_wait(&dr_cpu_wait, &wait); | ||
675 | |||
676 | if (kthread_should_stop()) | ||
677 | break; | ||
678 | 636 | ||
679 | process_dr_cpu_list(cp); | 637 | if (cpu_list[i] < NR_CPUS) |
638 | cpu_set(cpu_list[i], mask); | ||
680 | } | 639 | } |
681 | 640 | ||
682 | return 0; | 641 | if (tag->type == DR_CPU_CONFIGURE) |
683 | } | 642 | err = dr_cpu_configure(cp, req_num, &mask); |
684 | 643 | else | |
685 | static void dr_cpu_data(struct ldc_channel *lp, | 644 | err = dr_cpu_unconfigure(cp, req_num, &mask); |
686 | struct ds_cap_state *dp, | ||
687 | void *buf, int len) | ||
688 | { | ||
689 | struct dr_cpu_queue_entry *qp; | ||
690 | struct ds_data *dpkt = buf; | ||
691 | struct dr_cpu_tag *rp; | ||
692 | |||
693 | rp = (struct dr_cpu_tag *) (dpkt + 1); | ||
694 | 645 | ||
695 | qp = kmalloc(sizeof(struct dr_cpu_queue_entry) + len, GFP_ATOMIC); | 646 | if (err) |
696 | if (!qp) { | 647 | dr_cpu_send_error(cp, data); |
697 | struct ds_cap_state *cp; | ||
698 | |||
699 | cp = find_cap_by_string("dr-cpu"); | ||
700 | __dr_cpu_send_error(cp, dpkt); | ||
701 | } else { | ||
702 | memcpy(&qp->req, buf, len); | ||
703 | list_add_tail(&qp->list, &dr_cpu_work_list); | ||
704 | wake_up(&dr_cpu_wait); | ||
705 | } | ||
706 | } | 648 | } |
707 | #endif | 649 | #endif /* CONFIG_HOTPLUG_CPU */ |
708 | 650 | ||
709 | struct ds_pri_msg { | 651 | struct ds_pri_msg { |
710 | __u64 req_num; | 652 | __u64 req_num; |
@@ -820,7 +762,7 @@ void ldom_set_var(const char *var, const char *value) | |||
820 | ds_var_doorbell = 0; | 762 | ds_var_doorbell = 0; |
821 | ds_var_response = -1; | 763 | ds_var_response = -1; |
822 | 764 | ||
823 | ds_send(dp->lp, &pkt, msg_len); | 765 | __ds_send(dp->lp, &pkt, msg_len); |
824 | spin_unlock_irqrestore(&ds_lock, flags); | 766 | spin_unlock_irqrestore(&ds_lock, flags); |
825 | 767 | ||
826 | loops = 1000; | 768 | loops = 1000; |
@@ -904,7 +846,7 @@ static int register_services(struct ds_info *dp) | |||
904 | pbuf.req.minor = 0; | 846 | pbuf.req.minor = 0; |
905 | strcpy(pbuf.req.svc_id, cp->service_id); | 847 | strcpy(pbuf.req.svc_id, cp->service_id); |
906 | 848 | ||
907 | err = ds_send(lp, &pbuf, msg_len); | 849 | err = __ds_send(lp, &pbuf, msg_len); |
908 | if (err > 0) | 850 | if (err > 0) |
909 | cp->state = CAP_STATE_REG_SENT; | 851 | cp->state = CAP_STATE_REG_SENT; |
910 | } | 852 | } |
@@ -960,27 +902,97 @@ conn_reset: | |||
960 | return -ECONNRESET; | 902 | return -ECONNRESET; |
961 | } | 903 | } |
962 | 904 | ||
905 | static void __send_ds_nack(struct ds_info *dp, u64 handle) | ||
906 | { | ||
907 | struct ds_data_nack nack = { | ||
908 | .tag = { | ||
909 | .type = DS_NACK, | ||
910 | .len = (sizeof(struct ds_data_nack) - | ||
911 | sizeof(struct ds_msg_tag)), | ||
912 | }, | ||
913 | .handle = handle, | ||
914 | .result = DS_INV_HDL, | ||
915 | }; | ||
916 | |||
917 | __ds_send(dp->lp, &nack, sizeof(nack)); | ||
918 | } | ||
919 | |||
920 | static LIST_HEAD(ds_work_list); | ||
921 | static DECLARE_WAIT_QUEUE_HEAD(ds_wait); | ||
922 | |||
923 | struct ds_queue_entry { | ||
924 | struct list_head list; | ||
925 | int req_len; | ||
926 | int __pad; | ||
927 | u64 req[0]; | ||
928 | }; | ||
929 | |||
930 | static void process_ds_work(void) | ||
931 | { | ||
932 | struct ds_queue_entry *qp, *tmp; | ||
933 | static struct ds_info *dp; | ||
934 | unsigned long flags; | ||
935 | LIST_HEAD(todo); | ||
936 | |||
937 | spin_lock_irqsave(&ds_lock, flags); | ||
938 | list_splice(&ds_work_list, &todo); | ||
939 | INIT_LIST_HEAD(&ds_work_list); | ||
940 | spin_unlock_irqrestore(&ds_lock, flags); | ||
941 | |||
942 | dp = ds_info; | ||
943 | |||
944 | list_for_each_entry_safe(qp, tmp, &todo, list) { | ||
945 | struct ds_data *dpkt = (struct ds_data *) qp->req; | ||
946 | struct ds_cap_state *cp = find_cap(dpkt->handle); | ||
947 | int req_len = qp->req_len; | ||
948 | |||
949 | if (!cp) { | ||
950 | printk(KERN_ERR PFX "Data for unknown handle %lu\n", | ||
951 | dpkt->handle); | ||
952 | |||
953 | spin_lock_irqsave(&ds_lock, flags); | ||
954 | __send_ds_nack(dp, dpkt->handle); | ||
955 | spin_unlock_irqrestore(&ds_lock, flags); | ||
956 | } else { | ||
957 | cp->data(dp->lp, cp, dpkt, req_len); | ||
958 | } | ||
959 | |||
960 | list_del(&qp->list); | ||
961 | kfree(qp); | ||
962 | } | ||
963 | } | ||
964 | |||
965 | static int ds_thread(void *__unused) | ||
966 | { | ||
967 | DEFINE_WAIT(wait); | ||
968 | |||
969 | while (1) { | ||
970 | prepare_to_wait(&ds_wait, &wait, TASK_INTERRUPTIBLE); | ||
971 | if (list_empty(&ds_work_list)) | ||
972 | schedule(); | ||
973 | finish_wait(&ds_wait, &wait); | ||
974 | |||
975 | if (kthread_should_stop()) | ||
976 | break; | ||
977 | |||
978 | process_ds_work(); | ||
979 | } | ||
980 | |||
981 | return 0; | ||
982 | } | ||
983 | |||
963 | static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len) | 984 | static int ds_data(struct ds_info *dp, struct ds_msg_tag *pkt, int len) |
964 | { | 985 | { |
965 | struct ds_data *dpkt = (struct ds_data *) pkt; | 986 | struct ds_data *dpkt = (struct ds_data *) pkt; |
966 | struct ds_cap_state *cp = find_cap(dpkt->handle); | 987 | struct ds_queue_entry *qp; |
967 | 988 | ||
968 | if (!cp) { | 989 | qp = kmalloc(sizeof(struct ds_queue_entry) + len, GFP_ATOMIC); |
969 | struct ds_data_nack nack = { | 990 | if (!qp) { |
970 | .tag = { | 991 | __send_ds_nack(dp, dpkt->handle); |
971 | .type = DS_NACK, | ||
972 | .len = (sizeof(struct ds_data_nack) - | ||
973 | sizeof(struct ds_msg_tag)), | ||
974 | }, | ||
975 | .handle = dpkt->handle, | ||
976 | .result = DS_INV_HDL, | ||
977 | }; | ||
978 | |||
979 | printk(KERN_ERR PFX "Data for unknown handle %lu\n", | ||
980 | dpkt->handle); | ||
981 | ds_send(dp->lp, &nack, sizeof(nack)); | ||
982 | } else { | 992 | } else { |
983 | cp->data(dp->lp, cp, dpkt, len); | 993 | memcpy(&qp->req, pkt, len); |
994 | list_add_tail(&qp->list, &ds_work_list); | ||
995 | wake_up(&ds_wait); | ||
984 | } | 996 | } |
985 | return 0; | 997 | return 0; |
986 | } | 998 | } |
@@ -996,11 +1008,24 @@ static void ds_up(struct ds_info *dp) | |||
996 | req.ver.major = 1; | 1008 | req.ver.major = 1; |
997 | req.ver.minor = 0; | 1009 | req.ver.minor = 0; |
998 | 1010 | ||
999 | err = ds_send(lp, &req, sizeof(req)); | 1011 | err = __ds_send(lp, &req, sizeof(req)); |
1000 | if (err > 0) | 1012 | if (err > 0) |
1001 | dp->hs_state = DS_HS_START; | 1013 | dp->hs_state = DS_HS_START; |
1002 | } | 1014 | } |
1003 | 1015 | ||
1016 | static void ds_reset(struct ds_info *dp) | ||
1017 | { | ||
1018 | int i; | ||
1019 | |||
1020 | dp->hs_state = 0; | ||
1021 | |||
1022 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) { | ||
1023 | struct ds_cap_state *cp = &ds_states[i]; | ||
1024 | |||
1025 | cp->state = CAP_STATE_UNKNOWN; | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1004 | static void ds_event(void *arg, int event) | 1029 | static void ds_event(void *arg, int event) |
1005 | { | 1030 | { |
1006 | struct ds_info *dp = arg; | 1031 | struct ds_info *dp = arg; |
@@ -1016,6 +1041,12 @@ static void ds_event(void *arg, int event) | |||
1016 | return; | 1041 | return; |
1017 | } | 1042 | } |
1018 | 1043 | ||
1044 | if (event == LDC_EVENT_RESET) { | ||
1045 | ds_reset(dp); | ||
1046 | spin_unlock_irqrestore(&ds_lock, flags); | ||
1047 | return; | ||
1048 | } | ||
1049 | |||
1019 | if (event != LDC_EVENT_DATA_READY) { | 1050 | if (event != LDC_EVENT_DATA_READY) { |
1020 | printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); | 1051 | printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); |
1021 | spin_unlock_irqrestore(&ds_lock, flags); | 1052 | spin_unlock_irqrestore(&ds_lock, flags); |
@@ -1148,9 +1179,7 @@ static int __init ds_init(void) | |||
1148 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) | 1179 | for (i = 0; i < ARRAY_SIZE(ds_states); i++) |
1149 | ds_states[i].handle = ((u64)i << 32); | 1180 | ds_states[i].handle = ((u64)i << 32); |
1150 | 1181 | ||
1151 | #ifdef CONFIG_HOTPLUG_CPU | 1182 | kthread_run(ds_thread, NULL, "kldomd"); |
1152 | kthread_run(dr_cpu_thread, NULL, "kdrcpud"); | ||
1153 | #endif | ||
1154 | 1183 | ||
1155 | return vio_register_driver(&ds_driver); | 1184 | return vio_register_driver(&ds_driver); |
1156 | } | 1185 | } |
diff --git a/arch/sparc64/kernel/hvtramp.S b/arch/sparc64/kernel/hvtramp.S index 76a090e2c2a8..a55c252e18cc 100644 --- a/arch/sparc64/kernel/hvtramp.S +++ b/arch/sparc64/kernel/hvtramp.S | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <asm/hvtramp.h> | 10 | #include <asm/hvtramp.h> |
11 | #include <asm/pstate.h> | 11 | #include <asm/pstate.h> |
12 | #include <asm/ptrace.h> | 12 | #include <asm/ptrace.h> |
13 | #include <asm/head.h> | ||
13 | #include <asm/asi.h> | 14 | #include <asm/asi.h> |
14 | 15 | ||
15 | .text | 16 | .text |
@@ -28,7 +29,7 @@ | |||
28 | * First setup basic privileged cpu state. | 29 | * First setup basic privileged cpu state. |
29 | */ | 30 | */ |
30 | hv_cpu_startup: | 31 | hv_cpu_startup: |
31 | wrpr %g0, 0, %gl | 32 | SET_GL(0) |
32 | wrpr %g0, 15, %pil | 33 | wrpr %g0, 15, %pil |
33 | wrpr %g0, 0, %canrestore | 34 | wrpr %g0, 0, %canrestore |
34 | wrpr %g0, 0, %otherwin | 35 | wrpr %g0, 0, %otherwin |
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c index 62a389793949..302ba5e5a0bb 100644 --- a/arch/sparc64/kernel/mdesc.c +++ b/arch/sparc64/kernel/mdesc.c | |||
@@ -137,7 +137,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size) | |||
137 | sizeof(struct mdesc_hdr) + | 137 | sizeof(struct mdesc_hdr) + |
138 | mdesc_size); | 138 | mdesc_size); |
139 | 139 | ||
140 | base = kmalloc(handle_size + 15, GFP_KERNEL); | 140 | base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL); |
141 | if (base) { | 141 | if (base) { |
142 | struct mdesc_handle *hp; | 142 | struct mdesc_handle *hp; |
143 | unsigned long addr; | 143 | unsigned long addr; |
@@ -214,18 +214,83 @@ void mdesc_release(struct mdesc_handle *hp) | |||
214 | } | 214 | } |
215 | EXPORT_SYMBOL(mdesc_release); | 215 | EXPORT_SYMBOL(mdesc_release); |
216 | 216 | ||
217 | static void do_mdesc_update(struct work_struct *work) | 217 | static DEFINE_MUTEX(mdesc_mutex); |
218 | static struct mdesc_notifier_client *client_list; | ||
219 | |||
220 | void mdesc_register_notifier(struct mdesc_notifier_client *client) | ||
221 | { | ||
222 | u64 node; | ||
223 | |||
224 | mutex_lock(&mdesc_mutex); | ||
225 | client->next = client_list; | ||
226 | client_list = client; | ||
227 | |||
228 | mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name) | ||
229 | client->add(cur_mdesc, node); | ||
230 | |||
231 | mutex_unlock(&mdesc_mutex); | ||
232 | } | ||
233 | |||
234 | /* Run 'func' on nodes which are in A but not in B. */ | ||
235 | static void invoke_on_missing(const char *name, | ||
236 | struct mdesc_handle *a, | ||
237 | struct mdesc_handle *b, | ||
238 | void (*func)(struct mdesc_handle *, u64)) | ||
239 | { | ||
240 | u64 node; | ||
241 | |||
242 | mdesc_for_each_node_by_name(a, node, name) { | ||
243 | const u64 *id = mdesc_get_property(a, node, "id", NULL); | ||
244 | int found = 0; | ||
245 | u64 fnode; | ||
246 | |||
247 | mdesc_for_each_node_by_name(b, fnode, name) { | ||
248 | const u64 *fid = mdesc_get_property(b, fnode, | ||
249 | "id", NULL); | ||
250 | |||
251 | if (*id == *fid) { | ||
252 | found = 1; | ||
253 | break; | ||
254 | } | ||
255 | } | ||
256 | if (!found) | ||
257 | func(a, node); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | static void notify_one(struct mdesc_notifier_client *p, | ||
262 | struct mdesc_handle *old_hp, | ||
263 | struct mdesc_handle *new_hp) | ||
264 | { | ||
265 | invoke_on_missing(p->node_name, old_hp, new_hp, p->remove); | ||
266 | invoke_on_missing(p->node_name, new_hp, old_hp, p->add); | ||
267 | } | ||
268 | |||
269 | static void mdesc_notify_clients(struct mdesc_handle *old_hp, | ||
270 | struct mdesc_handle *new_hp) | ||
271 | { | ||
272 | struct mdesc_notifier_client *p = client_list; | ||
273 | |||
274 | while (p) { | ||
275 | notify_one(p, old_hp, new_hp); | ||
276 | p = p->next; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | void mdesc_update(void) | ||
218 | { | 281 | { |
219 | unsigned long len, real_len, status; | 282 | unsigned long len, real_len, status; |
220 | struct mdesc_handle *hp, *orig_hp; | 283 | struct mdesc_handle *hp, *orig_hp; |
221 | unsigned long flags; | 284 | unsigned long flags; |
222 | 285 | ||
286 | mutex_lock(&mdesc_mutex); | ||
287 | |||
223 | (void) sun4v_mach_desc(0UL, 0UL, &len); | 288 | (void) sun4v_mach_desc(0UL, 0UL, &len); |
224 | 289 | ||
225 | hp = mdesc_alloc(len, &kmalloc_mdesc_memops); | 290 | hp = mdesc_alloc(len, &kmalloc_mdesc_memops); |
226 | if (!hp) { | 291 | if (!hp) { |
227 | printk(KERN_ERR "MD: mdesc alloc fails\n"); | 292 | printk(KERN_ERR "MD: mdesc alloc fails\n"); |
228 | return; | 293 | goto out; |
229 | } | 294 | } |
230 | 295 | ||
231 | status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len); | 296 | status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len); |
@@ -234,25 +299,25 @@ static void do_mdesc_update(struct work_struct *work) | |||
234 | status); | 299 | status); |
235 | atomic_dec(&hp->refcnt); | 300 | atomic_dec(&hp->refcnt); |
236 | mdesc_free(hp); | 301 | mdesc_free(hp); |
237 | return; | 302 | goto out; |
238 | } | 303 | } |
239 | 304 | ||
240 | spin_lock_irqsave(&mdesc_lock, flags); | 305 | spin_lock_irqsave(&mdesc_lock, flags); |
241 | orig_hp = cur_mdesc; | 306 | orig_hp = cur_mdesc; |
242 | cur_mdesc = hp; | 307 | cur_mdesc = hp; |
308 | spin_unlock_irqrestore(&mdesc_lock, flags); | ||
243 | 309 | ||
310 | mdesc_notify_clients(orig_hp, hp); | ||
311 | |||
312 | spin_lock_irqsave(&mdesc_lock, flags); | ||
244 | if (atomic_dec_and_test(&orig_hp->refcnt)) | 313 | if (atomic_dec_and_test(&orig_hp->refcnt)) |
245 | mdesc_free(orig_hp); | 314 | mdesc_free(orig_hp); |
246 | else | 315 | else |
247 | list_add(&orig_hp->list, &mdesc_zombie_list); | 316 | list_add(&orig_hp->list, &mdesc_zombie_list); |
248 | spin_unlock_irqrestore(&mdesc_lock, flags); | 317 | spin_unlock_irqrestore(&mdesc_lock, flags); |
249 | } | ||
250 | |||
251 | static DECLARE_WORK(mdesc_update_work, do_mdesc_update); | ||
252 | 318 | ||
253 | void mdesc_update(void) | 319 | out: |
254 | { | 320 | mutex_unlock(&mdesc_mutex); |
255 | schedule_work(&mdesc_update_work); | ||
256 | } | 321 | } |
257 | 322 | ||
258 | static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) | 323 | static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc) |
@@ -278,13 +343,14 @@ u64 mdesc_node_by_name(struct mdesc_handle *hp, | |||
278 | u64 last_node = hp->mdesc.node_sz / 16; | 343 | u64 last_node = hp->mdesc.node_sz / 16; |
279 | u64 ret; | 344 | u64 ret; |
280 | 345 | ||
281 | if (from_node == MDESC_NODE_NULL) | 346 | if (from_node == MDESC_NODE_NULL) { |
282 | from_node = 0; | 347 | ret = from_node = 0; |
283 | 348 | } else if (from_node >= last_node) { | |
284 | if (from_node >= last_node) | ||
285 | return MDESC_NODE_NULL; | 349 | return MDESC_NODE_NULL; |
350 | } else { | ||
351 | ret = ep[from_node].d.val; | ||
352 | } | ||
286 | 353 | ||
287 | ret = ep[from_node].d.val; | ||
288 | while (ret < last_node) { | 354 | while (ret < last_node) { |
289 | if (ep[ret].tag != MD_NODE) | 355 | if (ep[ret].tag != MD_NODE) |
290 | return MDESC_NODE_NULL; | 356 | return MDESC_NODE_NULL; |
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index dc928e49e341..aafde3dd9fd4 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c | |||
@@ -454,9 +454,9 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) | |||
454 | ncpus_probed, | 454 | ncpus_probed, |
455 | num_online_cpus(), | 455 | num_online_cpus(), |
456 | dcache_parity_tl1_occurred, | 456 | dcache_parity_tl1_occurred, |
457 | icache_parity_tl1_occurred, | 457 | icache_parity_tl1_occurred |
458 | #ifndef CONFIG_SMP | 458 | #ifndef CONFIG_SMP |
459 | cpu_data(0).clock_tick | 459 | , cpu_data(0).clock_tick |
460 | #endif | 460 | #endif |
461 | ); | 461 | ); |
462 | #ifdef CONFIG_SMP | 462 | #ifdef CONFIG_SMP |
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 203e87301005..fb13775b3682 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c | |||
@@ -289,9 +289,7 @@ void do_rt_sigreturn(struct pt_regs *regs) | |||
289 | struct rt_signal_frame __user *sf; | 289 | struct rt_signal_frame __user *sf; |
290 | unsigned long tpc, tnpc, tstate; | 290 | unsigned long tpc, tnpc, tstate; |
291 | __siginfo_fpu_t __user *fpu_save; | 291 | __siginfo_fpu_t __user *fpu_save; |
292 | mm_segment_t old_fs; | ||
293 | sigset_t set; | 292 | sigset_t set; |
294 | stack_t st; | ||
295 | int err; | 293 | int err; |
296 | 294 | ||
297 | /* Always make any pending restarted system calls return -EINTR */ | 295 | /* Always make any pending restarted system calls return -EINTR */ |
@@ -327,20 +325,13 @@ void do_rt_sigreturn(struct pt_regs *regs) | |||
327 | err |= restore_fpu_state(regs, &sf->fpu_state); | 325 | err |= restore_fpu_state(regs, &sf->fpu_state); |
328 | 326 | ||
329 | err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); | 327 | err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); |
330 | err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t)); | 328 | err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); |
331 | 329 | ||
332 | if (err) | 330 | if (err) |
333 | goto segv; | 331 | goto segv; |
334 | 332 | ||
335 | regs->tpc = tpc; | 333 | regs->tpc = tpc; |
336 | regs->tnpc = tnpc; | 334 | regs->tnpc = tnpc; |
337 | |||
338 | /* It is more difficult to avoid calling this function than to | ||
339 | call it and ignore errors. */ | ||
340 | old_fs = get_fs(); | ||
341 | set_fs(KERNEL_DS); | ||
342 | do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); | ||
343 | set_fs(old_fs); | ||
344 | 335 | ||
345 | sigdelsetmask(&set, ~_BLOCKABLE); | 336 | sigdelsetmask(&set, ~_BLOCKABLE); |
346 | spin_lock_irq(¤t->sighand->siglock); | 337 | spin_lock_irq(¤t->sighand->siglock); |
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 00a9e3286c83..6ef2d299fb10 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
@@ -2225,6 +2225,7 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
2225 | notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); | 2225 | notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); |
2226 | __asm__ __volatile__("flushw"); | 2226 | __asm__ __volatile__("flushw"); |
2227 | __show_regs(regs); | 2227 | __show_regs(regs); |
2228 | add_taint(TAINT_DIE); | ||
2228 | if (regs->tstate & TSTATE_PRIV) { | 2229 | if (regs->tstate & TSTATE_PRIV) { |
2229 | struct reg_window *rw = (struct reg_window *) | 2230 | struct reg_window *rw = (struct reg_window *) |
2230 | (regs->u_regs[UREG_FP] + STACK_BIAS); | 2231 | (regs->u_regs[UREG_FP] + STACK_BIAS); |
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index 49569b44ea1f..8d3cc4fdb557 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c | |||
@@ -201,10 +201,11 @@ static void vio_fill_channel_info(struct mdesc_handle *hp, u64 mp, | |||
201 | static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | 201 | static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, |
202 | struct device *parent) | 202 | struct device *parent) |
203 | { | 203 | { |
204 | const char *type, *compat; | 204 | const char *type, *compat, *bus_id_name; |
205 | struct device_node *dp; | 205 | struct device_node *dp; |
206 | struct vio_dev *vdev; | 206 | struct vio_dev *vdev; |
207 | int err, tlen, clen; | 207 | int err, tlen, clen; |
208 | const u64 *id; | ||
208 | 209 | ||
209 | type = mdesc_get_property(hp, mp, "device-type", &tlen); | 210 | type = mdesc_get_property(hp, mp, "device-type", &tlen); |
210 | if (!type) { | 211 | if (!type) { |
@@ -220,6 +221,16 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
220 | return NULL; | 221 | return NULL; |
221 | } | 222 | } |
222 | 223 | ||
224 | bus_id_name = type; | ||
225 | if (!strcmp(type, "domain-services-port")) | ||
226 | bus_id_name = "ds"; | ||
227 | |||
228 | if (strlen(bus_id_name) >= KOBJ_NAME_LEN - 4) { | ||
229 | printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n", | ||
230 | bus_id_name); | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
223 | compat = mdesc_get_property(hp, mp, "device-type", &clen); | 234 | compat = mdesc_get_property(hp, mp, "device-type", &clen); |
224 | if (!compat) { | 235 | if (!compat) { |
225 | clen = 0; | 236 | clen = 0; |
@@ -249,7 +260,14 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
249 | 260 | ||
250 | vio_fill_channel_info(hp, mp, vdev); | 261 | vio_fill_channel_info(hp, mp, vdev); |
251 | 262 | ||
252 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%lx", mp); | 263 | id = mdesc_get_property(hp, mp, "id", NULL); |
264 | if (!id) | ||
265 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s", | ||
266 | bus_id_name); | ||
267 | else | ||
268 | snprintf(vdev->dev.bus_id, BUS_ID_SIZE, "%s-%lu", | ||
269 | bus_id_name, *id); | ||
270 | |||
253 | vdev->dev.parent = parent; | 271 | vdev->dev.parent = parent; |
254 | vdev->dev.bus = &vio_bus_type; | 272 | vdev->dev.bus = &vio_bus_type; |
255 | vdev->dev.release = vio_dev_release; | 273 | vdev->dev.release = vio_dev_release; |
@@ -269,6 +287,8 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
269 | } | 287 | } |
270 | vdev->dp = dp; | 288 | vdev->dp = dp; |
271 | 289 | ||
290 | printk(KERN_ERR "VIO: Adding device %s\n", vdev->dev.bus_id); | ||
291 | |||
272 | err = device_register(&vdev->dev); | 292 | err = device_register(&vdev->dev); |
273 | if (err) { | 293 | if (err) { |
274 | printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", | 294 | printk(KERN_ERR "VIO: Could not register device %s, err=%d\n", |
@@ -283,46 +303,46 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp, | |||
283 | return vdev; | 303 | return vdev; |
284 | } | 304 | } |
285 | 305 | ||
286 | static void walk_tree(struct mdesc_handle *hp, u64 n, struct vio_dev *parent) | 306 | static void vio_add(struct mdesc_handle *hp, u64 node) |
287 | { | 307 | { |
288 | u64 a; | 308 | (void) vio_create_one(hp, node, &root_vdev->dev); |
289 | |||
290 | mdesc_for_each_arc(a, hp, n, MDESC_ARC_TYPE_FWD) { | ||
291 | struct vio_dev *vdev; | ||
292 | u64 target; | ||
293 | |||
294 | target = mdesc_arc_target(hp, a); | ||
295 | vdev = vio_create_one(hp, target, &parent->dev); | ||
296 | if (vdev) | ||
297 | walk_tree(hp, target, vdev); | ||
298 | } | ||
299 | } | 309 | } |
300 | 310 | ||
301 | static void create_devices(struct mdesc_handle *hp, u64 root) | 311 | static int vio_md_node_match(struct device *dev, void *arg) |
302 | { | 312 | { |
303 | u64 mp; | 313 | struct vio_dev *vdev = to_vio_dev(dev); |
304 | 314 | ||
305 | root_vdev = vio_create_one(hp, root, NULL); | 315 | if (vdev->mp == (u64) arg) |
306 | if (!root_vdev) { | 316 | return 1; |
307 | printk(KERN_ERR "VIO: Coult not create root device.\n"); | ||
308 | return; | ||
309 | } | ||
310 | 317 | ||
311 | walk_tree(hp, root, root_vdev); | 318 | return 0; |
319 | } | ||
320 | |||
321 | static void vio_remove(struct mdesc_handle *hp, u64 node) | ||
322 | { | ||
323 | struct device *dev; | ||
312 | 324 | ||
313 | /* Domain services is odd as it doesn't sit underneath the | 325 | dev = device_find_child(&root_vdev->dev, (void *) node, |
314 | * channel-devices node, so we plug it in manually. | 326 | vio_md_node_match); |
315 | */ | 327 | if (dev) { |
316 | mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "domain-services"); | 328 | printk(KERN_INFO "VIO: Removing device %s\n", dev->bus_id); |
317 | if (mp != MDESC_NODE_NULL) { | ||
318 | struct vio_dev *parent = vio_create_one(hp, mp, | ||
319 | &root_vdev->dev); | ||
320 | 329 | ||
321 | if (parent) | 330 | device_unregister(dev); |
322 | walk_tree(hp, mp, parent); | ||
323 | } | 331 | } |
324 | } | 332 | } |
325 | 333 | ||
334 | static struct mdesc_notifier_client vio_device_notifier = { | ||
335 | .add = vio_add, | ||
336 | .remove = vio_remove, | ||
337 | .node_name = "virtual-device-port", | ||
338 | }; | ||
339 | |||
340 | static struct mdesc_notifier_client vio_ds_notifier = { | ||
341 | .add = vio_add, | ||
342 | .remove = vio_remove, | ||
343 | .node_name = "domain-services-port", | ||
344 | }; | ||
345 | |||
326 | const char *channel_devices_node = "channel-devices"; | 346 | const char *channel_devices_node = "channel-devices"; |
327 | const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; | 347 | const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; |
328 | const char *cfg_handle_prop = "cfg-handle"; | 348 | const char *cfg_handle_prop = "cfg-handle"; |
@@ -381,11 +401,19 @@ static int __init vio_init(void) | |||
381 | 401 | ||
382 | cdev_cfg_handle = *cfg_handle; | 402 | cdev_cfg_handle = *cfg_handle; |
383 | 403 | ||
384 | create_devices(hp, root); | 404 | root_vdev = vio_create_one(hp, root, NULL); |
405 | err = -ENODEV; | ||
406 | if (!root_vdev) { | ||
407 | printk(KERN_ERR "VIO: Coult not create root device.\n"); | ||
408 | goto out_release; | ||
409 | } | ||
410 | |||
411 | mdesc_register_notifier(&vio_device_notifier); | ||
412 | mdesc_register_notifier(&vio_ds_notifier); | ||
385 | 413 | ||
386 | mdesc_release(hp); | 414 | mdesc_release(hp); |
387 | 415 | ||
388 | return 0; | 416 | return err; |
389 | 417 | ||
390 | out_release: | 418 | out_release: |
391 | mdesc_release(hp); | 419 | mdesc_release(hp); |
diff --git a/arch/sparc64/kernel/viohs.c b/arch/sparc64/kernel/viohs.c index 15613add45d1..09126fc338ba 100644 --- a/arch/sparc64/kernel/viohs.c +++ b/arch/sparc64/kernel/viohs.c | |||
@@ -78,6 +78,24 @@ static int start_handshake(struct vio_driver_state *vio) | |||
78 | return 0; | 78 | return 0; |
79 | } | 79 | } |
80 | 80 | ||
81 | static void flush_rx_dring(struct vio_driver_state *vio) | ||
82 | { | ||
83 | struct vio_dring_state *dr; | ||
84 | u64 ident; | ||
85 | |||
86 | BUG_ON(!(vio->dr_state & VIO_DR_STATE_RXREG)); | ||
87 | |||
88 | dr = &vio->drings[VIO_DRIVER_RX_RING]; | ||
89 | ident = dr->ident; | ||
90 | |||
91 | BUG_ON(!vio->desc_buf); | ||
92 | kfree(vio->desc_buf); | ||
93 | vio->desc_buf = NULL; | ||
94 | |||
95 | memset(dr, 0, sizeof(*dr)); | ||
96 | dr->ident = ident; | ||
97 | } | ||
98 | |||
81 | void vio_link_state_change(struct vio_driver_state *vio, int event) | 99 | void vio_link_state_change(struct vio_driver_state *vio, int event) |
82 | { | 100 | { |
83 | if (event == LDC_EVENT_UP) { | 101 | if (event == LDC_EVENT_UP) { |
@@ -98,6 +116,16 @@ void vio_link_state_change(struct vio_driver_state *vio, int event) | |||
98 | break; | 116 | break; |
99 | } | 117 | } |
100 | start_handshake(vio); | 118 | start_handshake(vio); |
119 | } else if (event == LDC_EVENT_RESET) { | ||
120 | vio->hs_state = VIO_HS_INVALID; | ||
121 | |||
122 | if (vio->dr_state & VIO_DR_STATE_RXREG) | ||
123 | flush_rx_dring(vio); | ||
124 | |||
125 | vio->dr_state = 0x00; | ||
126 | memset(&vio->ver, 0, sizeof(vio->ver)); | ||
127 | |||
128 | ldc_disconnect(vio->lp); | ||
101 | } | 129 | } |
102 | } | 130 | } |
103 | EXPORT_SYMBOL(vio_link_state_change); | 131 | EXPORT_SYMBOL(vio_link_state_change); |
@@ -396,6 +424,8 @@ static int process_dreg_info(struct vio_driver_state *vio, | |||
396 | if (vio->dr_state & VIO_DR_STATE_RXREG) | 424 | if (vio->dr_state & VIO_DR_STATE_RXREG) |
397 | goto send_nack; | 425 | goto send_nack; |
398 | 426 | ||
427 | BUG_ON(vio->desc_buf); | ||
428 | |||
399 | vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC); | 429 | vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC); |
400 | if (!vio->desc_buf) | 430 | if (!vio->desc_buf) |
401 | goto send_nack; | 431 | goto send_nack; |
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S index 3ad10f3027e4..481861764deb 100644 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ b/arch/sparc64/kernel/vmlinux.lds.S | |||
@@ -90,10 +90,8 @@ SECTIONS | |||
90 | __initramfs_end = .; | 90 | __initramfs_end = .; |
91 | #endif | 91 | #endif |
92 | 92 | ||
93 | . = ALIGN(PAGE_SIZE); | 93 | PERCPU(PAGE_SIZE) |
94 | __per_cpu_start = .; | 94 | |
95 | .data.percpu : { *(.data.percpu) } | ||
96 | __per_cpu_end = .; | ||
97 | . = ALIGN(PAGE_SIZE); | 95 | . = ALIGN(PAGE_SIZE); |
98 | __init_end = .; | 96 | __init_end = .; |
99 | __bss_start = .; | 97 | __bss_start = .; |
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index b582024d2199..17123e9ecf78 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c | |||
@@ -278,7 +278,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
278 | struct mm_struct *mm = current->mm; | 278 | struct mm_struct *mm = current->mm; |
279 | struct vm_area_struct *vma; | 279 | struct vm_area_struct *vma; |
280 | unsigned int insn = 0; | 280 | unsigned int insn = 0; |
281 | int si_code, fault_code; | 281 | int si_code, fault_code, fault; |
282 | unsigned long address, mm_rss; | 282 | unsigned long address, mm_rss; |
283 | 283 | ||
284 | fault_code = get_thread_fault_code(); | 284 | fault_code = get_thread_fault_code(); |
@@ -415,20 +415,18 @@ good_area: | |||
415 | goto bad_area; | 415 | goto bad_area; |
416 | } | 416 | } |
417 | 417 | ||
418 | switch (handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE))) { | 418 | fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE)); |
419 | case VM_FAULT_MINOR: | 419 | if (unlikely(fault & VM_FAULT_ERROR)) { |
420 | current->min_flt++; | 420 | if (fault & VM_FAULT_OOM) |
421 | break; | 421 | goto out_of_memory; |
422 | case VM_FAULT_MAJOR: | 422 | else if (fault & VM_FAULT_SIGBUS) |
423 | current->maj_flt++; | 423 | goto do_sigbus; |
424 | break; | ||
425 | case VM_FAULT_SIGBUS: | ||
426 | goto do_sigbus; | ||
427 | case VM_FAULT_OOM: | ||
428 | goto out_of_memory; | ||
429 | default: | ||
430 | BUG(); | 424 | BUG(); |
431 | } | 425 | } |
426 | if (fault & VM_FAULT_MAJOR) | ||
427 | current->maj_flt++; | ||
428 | else | ||
429 | current->min_flt++; | ||
432 | 430 | ||
433 | up_read(&mm->mmap_sem); | 431 | up_read(&mm->mmap_sem); |
434 | 432 | ||
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c index e94f6e5d9455..7736411f244f 100644 --- a/arch/sparc64/solaris/socksys.c +++ b/arch/sparc64/solaris/socksys.c | |||
@@ -199,6 +199,5 @@ int __init init_socksys(void) | |||
199 | 199 | ||
200 | void __exit cleanup_socksys(void) | 200 | void __exit cleanup_socksys(void) |
201 | { | 201 | { |
202 | if (unregister_chrdev(30, "socksys")) | 202 | unregister_chrdev(30, "socksys"); |
203 | printk ("Couldn't unregister socksys character device\n"); | ||
204 | } | 203 | } |
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index 483aa15222a4..1316456e2a28 100644 --- a/arch/um/drivers/pcap_user.c +++ b/arch/um/drivers/pcap_user.c | |||
@@ -53,7 +53,7 @@ static int pcap_open(void *data) | |||
53 | return -EIO; | 53 | return -EIO; |
54 | } | 54 | } |
55 | 55 | ||
56 | pri->compiled = um_kmalloc(sizeof(struct bpf_program)); | 56 | pri->compiled = kmalloc(sizeof(struct bpf_program), UM_GFP_KERNEL); |
57 | if(pri->compiled == NULL){ | 57 | if(pri->compiled == NULL){ |
58 | printk(UM_KERN_ERR "pcap_open : kmalloc failed\n"); | 58 | printk(UM_KERN_ERR "pcap_open : kmalloc failed\n"); |
59 | return -ENOMEM; | 59 | return -ENOMEM; |
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 627742d89434..6916c8888dba 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
@@ -52,17 +52,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
52 | switch (request) { | 52 | switch (request) { |
53 | /* when I and D space are separate, these will need to be fixed. */ | 53 | /* when I and D space are separate, these will need to be fixed. */ |
54 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 54 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
55 | case PTRACE_PEEKDATA: { | 55 | case PTRACE_PEEKDATA: |
56 | unsigned long tmp; | 56 | ret = generic_ptrace_peekdata(child, addr, data); |
57 | int copied; | ||
58 | |||
59 | ret = -EIO; | ||
60 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
61 | if (copied != sizeof(tmp)) | ||
62 | break; | ||
63 | ret = put_user(tmp, p); | ||
64 | break; | 57 | break; |
65 | } | ||
66 | 58 | ||
67 | /* read the word at location addr in the USER area. */ | 59 | /* read the word at location addr in the USER area. */ |
68 | case PTRACE_PEEKUSR: | 60 | case PTRACE_PEEKUSR: |
@@ -72,11 +64,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
72 | /* when I and D space are separate, this will have to be fixed. */ | 64 | /* when I and D space are separate, this will have to be fixed. */ |
73 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 65 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
74 | case PTRACE_POKEDATA: | 66 | case PTRACE_POKEDATA: |
75 | ret = -EIO; | 67 | ret = generic_ptrace_pokedata(child, addr, data); |
76 | if (access_process_vm(child, addr, &data, sizeof(data), | ||
77 | 1) != sizeof(data)) | ||
78 | break; | ||
79 | ret = 0; | ||
80 | break; | 68 | break; |
81 | 69 | ||
82 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 70 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index abab90c3803f..3850d53f79fd 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -76,23 +76,24 @@ good_area: | |||
76 | goto out; | 76 | goto out; |
77 | 77 | ||
78 | do { | 78 | do { |
79 | int fault; | ||
79 | survive: | 80 | survive: |
80 | switch (handle_mm_fault(mm, vma, address, is_write)){ | 81 | fault = handle_mm_fault(mm, vma, address, is_write); |
81 | case VM_FAULT_MINOR: | 82 | if (unlikely(fault & VM_FAULT_ERROR)) { |
82 | current->min_flt++; | 83 | if (fault & VM_FAULT_OOM) { |
83 | break; | 84 | err = -ENOMEM; |
84 | case VM_FAULT_MAJOR: | 85 | goto out_of_memory; |
85 | current->maj_flt++; | 86 | } else if (fault & VM_FAULT_SIGBUS) { |
86 | break; | 87 | err = -EACCES; |
87 | case VM_FAULT_SIGBUS: | 88 | goto out; |
88 | err = -EACCES; | 89 | } |
89 | goto out; | ||
90 | case VM_FAULT_OOM: | ||
91 | err = -ENOMEM; | ||
92 | goto out_of_memory; | ||
93 | default: | ||
94 | BUG(); | 90 | BUG(); |
95 | } | 91 | } |
92 | if (fault & VM_FAULT_MAJOR) | ||
93 | current->maj_flt++; | ||
94 | else | ||
95 | current->min_flt++; | ||
96 | |||
96 | pgd = pgd_offset(mm, address); | 97 | pgd = pgd_offset(mm, address); |
97 | pud = pud_offset(pgd, address); | 98 | pud = pud_offset(pgd, address); |
98 | pmd = pmd_offset(pud, address); | 99 | pmd = pmd_offset(pud, address); |
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index a9b09343097d..a458ac941b25 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c | |||
@@ -117,24 +117,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
117 | int rval; | 117 | int rval; |
118 | 118 | ||
119 | switch (request) { | 119 | switch (request) { |
120 | unsigned long val, copied; | 120 | unsigned long val; |
121 | 121 | ||
122 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 122 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
123 | case PTRACE_PEEKDATA: | 123 | case PTRACE_PEEKDATA: |
124 | copied = access_process_vm(child, addr, &val, sizeof(val), 0); | 124 | rval = generic_ptrace_peekdata(child, addr, data); |
125 | rval = -EIO; | ||
126 | if (copied != sizeof(val)) | ||
127 | break; | ||
128 | rval = put_user(val, (unsigned long *)data); | ||
129 | goto out; | 125 | goto out; |
130 | 126 | ||
131 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 127 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
132 | case PTRACE_POKEDATA: | 128 | case PTRACE_POKEDATA: |
133 | rval = 0; | 129 | rval = generic_ptrace_pokedata(child, addr, data); |
134 | if (access_process_vm(child, addr, &data, sizeof(data), 1) | ||
135 | == sizeof(data)) | ||
136 | break; | ||
137 | rval = -EIO; | ||
138 | goto out; | 130 | goto out; |
139 | 131 | ||
140 | /* Read/write the word at location ADDR in the registers. */ | 132 | /* Read/write the word at location ADDR in the registers. */ |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 8bdd25ac1542..14bf8ce3ea23 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -774,8 +774,8 @@ menu "Instrumentation Support" | |||
774 | source "arch/x86_64/oprofile/Kconfig" | 774 | source "arch/x86_64/oprofile/Kconfig" |
775 | 775 | ||
776 | config KPROBES | 776 | config KPROBES |
777 | bool "Kprobes (EXPERIMENTAL)" | 777 | bool "Kprobes" |
778 | depends on KALLSYMS && EXPERIMENTAL && MODULES | 778 | depends on KALLSYMS && MODULES |
779 | help | 779 | help |
780 | Kprobes allows you to trap at almost any kernel address and | 780 | Kprobes allows you to trap at almost any kernel address and |
781 | execute a callback function. register_kprobe() establishes | 781 | execute a callback function. register_kprobe() establishes |
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c index fe83edb93c10..08781370256d 100644 --- a/arch/x86_64/ia32/ia32_aout.c +++ b/arch/x86_64/ia32/ia32_aout.c | |||
@@ -404,7 +404,7 @@ beyond_if: | |||
404 | 404 | ||
405 | set_brk(current->mm->start_brk, current->mm->brk); | 405 | set_brk(current->mm->start_brk, current->mm->brk); |
406 | 406 | ||
407 | retval = ia32_setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); | 407 | retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); |
408 | if (retval < 0) { | 408 | if (retval < 0) { |
409 | /* Someone check-me: is this error path enough? */ | 409 | /* Someone check-me: is this error path enough? */ |
410 | send_sig(SIGKILL, current, 0); | 410 | send_sig(SIGKILL, current, 0); |
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 185399baaf6d..ed56a8806eab 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c | |||
@@ -232,9 +232,6 @@ do { \ | |||
232 | #define load_elf_binary load_elf32_binary | 232 | #define load_elf_binary load_elf32_binary |
233 | 233 | ||
234 | #define ELF_PLAT_INIT(r, load_addr) elf32_init(r) | 234 | #define ELF_PLAT_INIT(r, load_addr) elf32_init(r) |
235 | #define setup_arg_pages(bprm, stack_top, exec_stack) \ | ||
236 | ia32_setup_arg_pages(bprm, stack_top, exec_stack) | ||
237 | int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int executable_stack); | ||
238 | 235 | ||
239 | #undef start_thread | 236 | #undef start_thread |
240 | #define start_thread(regs,new_rip,new_rsp) do { \ | 237 | #define start_thread(regs,new_rip,new_rsp) do { \ |
@@ -286,61 +283,6 @@ static void elf32_init(struct pt_regs *regs) | |||
286 | me->thread.es = __USER_DS; | 283 | me->thread.es = __USER_DS; |
287 | } | 284 | } |
288 | 285 | ||
289 | int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, | ||
290 | int executable_stack) | ||
291 | { | ||
292 | unsigned long stack_base; | ||
293 | struct vm_area_struct *mpnt; | ||
294 | struct mm_struct *mm = current->mm; | ||
295 | int i, ret; | ||
296 | |||
297 | stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE; | ||
298 | mm->arg_start = bprm->p + stack_base; | ||
299 | |||
300 | bprm->p += stack_base; | ||
301 | if (bprm->loader) | ||
302 | bprm->loader += stack_base; | ||
303 | bprm->exec += stack_base; | ||
304 | |||
305 | mpnt = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); | ||
306 | if (!mpnt) | ||
307 | return -ENOMEM; | ||
308 | |||
309 | down_write(&mm->mmap_sem); | ||
310 | { | ||
311 | mpnt->vm_mm = mm; | ||
312 | mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; | ||
313 | mpnt->vm_end = stack_top; | ||
314 | if (executable_stack == EXSTACK_ENABLE_X) | ||
315 | mpnt->vm_flags = VM_STACK_FLAGS | VM_EXEC; | ||
316 | else if (executable_stack == EXSTACK_DISABLE_X) | ||
317 | mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC; | ||
318 | else | ||
319 | mpnt->vm_flags = VM_STACK_FLAGS; | ||
320 | mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? | ||
321 | PAGE_COPY_EXEC : PAGE_COPY; | ||
322 | if ((ret = insert_vm_struct(mm, mpnt))) { | ||
323 | up_write(&mm->mmap_sem); | ||
324 | kmem_cache_free(vm_area_cachep, mpnt); | ||
325 | return ret; | ||
326 | } | ||
327 | mm->stack_vm = mm->total_vm = vma_pages(mpnt); | ||
328 | } | ||
329 | |||
330 | for (i = 0 ; i < MAX_ARG_PAGES ; i++) { | ||
331 | struct page *page = bprm->page[i]; | ||
332 | if (page) { | ||
333 | bprm->page[i] = NULL; | ||
334 | install_arg_page(mpnt, page, stack_base); | ||
335 | } | ||
336 | stack_base += PAGE_SIZE; | ||
337 | } | ||
338 | up_write(&mm->mmap_sem); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | EXPORT_SYMBOL(ia32_setup_arg_pages); | ||
343 | |||
344 | #ifdef CONFIG_SYSCTL | 286 | #ifdef CONFIG_SYSCTL |
345 | /* Register vsyscall32 into the ABI table */ | 287 | /* Register vsyscall32 into the ABI table */ |
346 | #include <linux/sysctl.h> | 288 | #include <linux/sysctl.h> |
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 782dea819438..3f66e970d86f 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S | |||
@@ -719,4 +719,5 @@ ia32_sys_call_table: | |||
719 | .quad compat_sys_signalfd | 719 | .quad compat_sys_signalfd |
720 | .quad compat_sys_timerfd | 720 | .quad compat_sys_timerfd |
721 | .quad sys_eventfd | 721 | .quad sys_eventfd |
722 | .quad sys32_fallocate | ||
722 | ia32_syscall_end: | 723 | ia32_syscall_end: |
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index 99a78a3cce7c..bee96d614432 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c | |||
@@ -879,3 +879,11 @@ asmlinkage long sys32_fadvise64(int fd, unsigned offset_lo, unsigned offset_hi, | |||
879 | return sys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo, | 879 | return sys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo, |
880 | len, advice); | 880 | len, advice); |
881 | } | 881 | } |
882 | |||
883 | asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_lo, | ||
884 | unsigned offset_hi, unsigned len_lo, | ||
885 | unsigned len_hi) | ||
886 | { | ||
887 | return sys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo, | ||
888 | ((u64)len_hi << 32) | len_lo); | ||
889 | } | ||
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c index 195b7034a148..4277f2b27e6d 100644 --- a/arch/x86_64/kernel/acpi/sleep.c +++ b/arch/x86_64/kernel/acpi/sleep.c | |||
@@ -55,7 +55,7 @@ | |||
55 | 55 | ||
56 | /* address in low memory of the wakeup routine. */ | 56 | /* address in low memory of the wakeup routine. */ |
57 | unsigned long acpi_wakeup_address = 0; | 57 | unsigned long acpi_wakeup_address = 0; |
58 | unsigned long acpi_video_flags; | 58 | unsigned long acpi_realmode_flags; |
59 | extern char wakeup_start, wakeup_end; | 59 | extern char wakeup_start, wakeup_end; |
60 | 60 | ||
61 | extern unsigned long acpi_copy_wakeup_routine(unsigned long); | 61 | extern unsigned long acpi_copy_wakeup_routine(unsigned long); |
@@ -103,9 +103,11 @@ static int __init acpi_sleep_setup(char *str) | |||
103 | { | 103 | { |
104 | while ((str != NULL) && (*str != '\0')) { | 104 | while ((str != NULL) && (*str != '\0')) { |
105 | if (strncmp(str, "s3_bios", 7) == 0) | 105 | if (strncmp(str, "s3_bios", 7) == 0) |
106 | acpi_video_flags = 1; | 106 | acpi_realmode_flags |= 1; |
107 | if (strncmp(str, "s3_mode", 7) == 0) | 107 | if (strncmp(str, "s3_mode", 7) == 0) |
108 | acpi_video_flags |= 2; | 108 | acpi_realmode_flags |= 2; |
109 | if (strncmp(str, "s3_beep", 7) == 0) | ||
110 | acpi_realmode_flags |= 4; | ||
109 | str = strchr(str, ','); | 111 | str = strchr(str, ','); |
110 | if (str != NULL) | 112 | if (str != NULL) |
111 | str += strspn(str, ", \t"); | 113 | str += strspn(str, ", \t"); |
diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S index 8550a6ffa275..13f1480cbec9 100644 --- a/arch/x86_64/kernel/acpi/wakeup.S +++ b/arch/x86_64/kernel/acpi/wakeup.S | |||
@@ -16,6 +16,21 @@ | |||
16 | # cs = 0x1234, eip = 0x05 | 16 | # cs = 0x1234, eip = 0x05 |
17 | # | 17 | # |
18 | 18 | ||
19 | #define BEEP \ | ||
20 | inb $97, %al; \ | ||
21 | outb %al, $0x80; \ | ||
22 | movb $3, %al; \ | ||
23 | outb %al, $97; \ | ||
24 | outb %al, $0x80; \ | ||
25 | movb $-74, %al; \ | ||
26 | outb %al, $67; \ | ||
27 | outb %al, $0x80; \ | ||
28 | movb $-119, %al; \ | ||
29 | outb %al, $66; \ | ||
30 | outb %al, $0x80; \ | ||
31 | movb $15, %al; \ | ||
32 | outb %al, $66; | ||
33 | |||
19 | 34 | ||
20 | ALIGN | 35 | ALIGN |
21 | .align 16 | 36 | .align 16 |
@@ -33,6 +48,13 @@ wakeup_code: | |||
33 | movw %cs, %ax | 48 | movw %cs, %ax |
34 | movw %ax, %ds # Make ds:0 point to wakeup_start | 49 | movw %ax, %ds # Make ds:0 point to wakeup_start |
35 | movw %ax, %ss | 50 | movw %ax, %ss |
51 | |||
52 | # Data segment must be set up before we can see whether to beep. | ||
53 | testl $4, realmode_flags - wakeup_code | ||
54 | jz 1f | ||
55 | BEEP | ||
56 | 1: | ||
57 | |||
36 | # Private stack is needed for ASUS board | 58 | # Private stack is needed for ASUS board |
37 | mov $(wakeup_stack - wakeup_code), %sp | 59 | mov $(wakeup_stack - wakeup_code), %sp |
38 | 60 | ||
@@ -48,7 +70,7 @@ wakeup_code: | |||
48 | testl %eax, %eax | 70 | testl %eax, %eax |
49 | jnz no_longmode | 71 | jnz no_longmode |
50 | 72 | ||
51 | testl $1, video_flags - wakeup_code | 73 | testl $1, realmode_flags - wakeup_code |
52 | jz 1f | 74 | jz 1f |
53 | lcall $0xc000,$3 | 75 | lcall $0xc000,$3 |
54 | movw %cs, %ax | 76 | movw %cs, %ax |
@@ -56,7 +78,7 @@ wakeup_code: | |||
56 | movw %ax, %ss | 78 | movw %ax, %ss |
57 | 1: | 79 | 1: |
58 | 80 | ||
59 | testl $2, video_flags - wakeup_code | 81 | testl $2, realmode_flags - wakeup_code |
60 | jz 1f | 82 | jz 1f |
61 | mov video_mode - wakeup_code, %ax | 83 | mov video_mode - wakeup_code, %ax |
62 | call mode_seta | 84 | call mode_seta |
@@ -230,7 +252,7 @@ gdt_48a: | |||
230 | 252 | ||
231 | real_magic: .quad 0 | 253 | real_magic: .quad 0 |
232 | video_mode: .quad 0 | 254 | video_mode: .quad 0 |
233 | video_flags: .quad 0 | 255 | realmode_flags: .quad 0 |
234 | 256 | ||
235 | .code16 | 257 | .code16 |
236 | bogus_real_magic: | 258 | bogus_real_magic: |
@@ -346,8 +368,8 @@ ENTRY(acpi_copy_wakeup_routine) | |||
346 | 368 | ||
347 | movl saved_video_mode, %edx | 369 | movl saved_video_mode, %edx |
348 | movl %edx, video_mode - wakeup_start (,%rdi) | 370 | movl %edx, video_mode - wakeup_start (,%rdi) |
349 | movl acpi_video_flags, %edx | 371 | movl acpi_realmode_flags, %edx |
350 | movl %edx, video_flags - wakeup_start (,%rdi) | 372 | movl %edx, realmode_flags - wakeup_start (,%rdi) |
351 | movq $0x12345678, real_magic - wakeup_start (,%rdi) | 373 | movq $0x12345678, real_magic - wakeup_start (,%rdi) |
352 | movq $0x123456789abcdef0, %rdx | 374 | movq $0x123456789abcdef0, %rdx |
353 | movq %rdx, saved_magic | 375 | movq %rdx, saved_magic |
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c index 296d2b0c5d88..fd9aff3f3890 100644 --- a/arch/x86_64/kernel/early_printk.c +++ b/arch/x86_64/kernel/early_printk.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <asm/io.h> | 6 | #include <asm/io.h> |
7 | #include <asm/processor.h> | 7 | #include <asm/processor.h> |
8 | #include <asm/fcntl.h> | 8 | #include <asm/fcntl.h> |
9 | #include <xen/hvc-console.h> | ||
9 | 10 | ||
10 | /* Simple VGA output */ | 11 | /* Simple VGA output */ |
11 | 12 | ||
@@ -242,6 +243,10 @@ static int __init setup_early_printk(char *buf) | |||
242 | simnow_init(buf + 6); | 243 | simnow_init(buf + 6); |
243 | early_console = &simnow_console; | 244 | early_console = &simnow_console; |
244 | keep_early = 1; | 245 | keep_early = 1; |
246 | #ifdef CONFIG_HVC_XEN | ||
247 | } else if (!strncmp(buf, "xen", 3)) { | ||
248 | early_console = &xenboot_console; | ||
249 | #endif | ||
245 | } | 250 | } |
246 | 251 | ||
247 | if (keep_early) | 252 | if (keep_early) |
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c index 3dc5854ba21e..4ff33d4f8551 100644 --- a/arch/x86_64/kernel/init_task.c +++ b/arch/x86_64/kernel/init_task.c | |||
@@ -44,7 +44,7 @@ EXPORT_SYMBOL(init_task); | |||
44 | * section. Since TSS's are completely CPU-local, we want them | 44 | * section. Since TSS's are completely CPU-local, we want them |
45 | * on exact cacheline boundaries, to eliminate cacheline ping-pong. | 45 | * on exact cacheline boundaries, to eliminate cacheline ping-pong. |
46 | */ | 46 | */ |
47 | DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; | 47 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; |
48 | 48 | ||
49 | /* Copies of the original ist values from the tss are only accessed during | 49 | /* Copies of the original ist values from the tss are only accessed during |
50 | * debugging, no special alignment required. | 50 | * debugging, no special alignment required. |
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index aa1d15991794..f3fb8174559e 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c | |||
@@ -174,7 +174,7 @@ static void do_mce_trigger(void) | |||
174 | if (events != atomic_read(&mce_logged) && trigger[0]) { | 174 | if (events != atomic_read(&mce_logged) && trigger[0]) { |
175 | /* Small race window, but should be harmless. */ | 175 | /* Small race window, but should be harmless. */ |
176 | atomic_set(&mce_logged, events); | 176 | atomic_set(&mce_logged, events); |
177 | call_usermodehelper(trigger, trigger_argv, NULL, -1); | 177 | call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT); |
178 | } | 178 | } |
179 | } | 179 | } |
180 | 180 | ||
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 931c64bad5e6..edbbc59b7523 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c | |||
@@ -296,7 +296,7 @@ static DEFINE_PER_CPU(unsigned, last_irq_sum); | |||
296 | static DEFINE_PER_CPU(local_t, alert_counter); | 296 | static DEFINE_PER_CPU(local_t, alert_counter); |
297 | static DEFINE_PER_CPU(int, nmi_touch); | 297 | static DEFINE_PER_CPU(int, nmi_touch); |
298 | 298 | ||
299 | void touch_nmi_watchdog (void) | 299 | void touch_nmi_watchdog(void) |
300 | { | 300 | { |
301 | if (nmi_watchdog > 0) { | 301 | if (nmi_watchdog > 0) { |
302 | unsigned cpu; | 302 | unsigned cpu; |
@@ -306,8 +306,10 @@ void touch_nmi_watchdog (void) | |||
306 | * do it ourselves because the alert count increase is not | 306 | * do it ourselves because the alert count increase is not |
307 | * atomic. | 307 | * atomic. |
308 | */ | 308 | */ |
309 | for_each_present_cpu (cpu) | 309 | for_each_present_cpu(cpu) { |
310 | per_cpu(nmi_touch, cpu) = 1; | 310 | if (per_cpu(nmi_touch, cpu) != 1) |
311 | per_cpu(nmi_touch, cpu) = 1; | ||
312 | } | ||
311 | } | 313 | } |
312 | 314 | ||
313 | touch_softlockup_watchdog(); | 315 | touch_softlockup_watchdog(); |
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 9409117b9f19..e83cc67155ac 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c | |||
@@ -102,16 +102,25 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r | |||
102 | u32 *desc; | 102 | u32 *desc; |
103 | unsigned long base; | 103 | unsigned long base; |
104 | 104 | ||
105 | down(&child->mm->context.sem); | 105 | seg &= ~7UL; |
106 | desc = child->mm->context.ldt + (seg & ~7); | ||
107 | base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000); | ||
108 | 106 | ||
109 | /* 16-bit code segment? */ | 107 | down(&child->mm->context.sem); |
110 | if (!((desc[1] >> 22) & 1)) | 108 | if (unlikely((seg >> 3) >= child->mm->context.size)) |
111 | addr &= 0xffff; | 109 | addr = -1L; /* bogus selector, access would fault */ |
112 | addr += base; | 110 | else { |
111 | desc = child->mm->context.ldt + seg; | ||
112 | base = ((desc[0] >> 16) | | ||
113 | ((desc[1] & 0xff) << 16) | | ||
114 | (desc[1] & 0xff000000)); | ||
115 | |||
116 | /* 16-bit code segment? */ | ||
117 | if (!((desc[1] >> 22) & 1)) | ||
118 | addr &= 0xffff; | ||
119 | addr += base; | ||
120 | } | ||
113 | up(&child->mm->context.sem); | 121 | up(&child->mm->context.sem); |
114 | } | 122 | } |
123 | |||
115 | return addr; | 124 | return addr; |
116 | } | 125 | } |
117 | 126 | ||
@@ -313,17 +322,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
313 | switch (request) { | 322 | switch (request) { |
314 | /* when I and D space are separate, these will need to be fixed. */ | 323 | /* when I and D space are separate, these will need to be fixed. */ |
315 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 324 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
316 | case PTRACE_PEEKDATA: { | 325 | case PTRACE_PEEKDATA: |
317 | unsigned long tmp; | 326 | ret = generic_ptrace_peekdata(child, addr, data); |
318 | int copied; | ||
319 | |||
320 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
321 | ret = -EIO; | ||
322 | if (copied != sizeof(tmp)) | ||
323 | break; | ||
324 | ret = put_user(tmp,(unsigned long __user *) data); | ||
325 | break; | 327 | break; |
326 | } | ||
327 | 328 | ||
328 | /* read the word at location addr in the USER area. */ | 329 | /* read the word at location addr in the USER area. */ |
329 | case PTRACE_PEEKUSR: { | 330 | case PTRACE_PEEKUSR: { |
@@ -367,10 +368,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
367 | /* when I and D space are separate, this will have to be fixed. */ | 368 | /* when I and D space are separate, this will have to be fixed. */ |
368 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 369 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
369 | case PTRACE_POKEDATA: | 370 | case PTRACE_POKEDATA: |
370 | ret = 0; | 371 | ret = generic_ptrace_pokedata(child, addr, data); |
371 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
372 | break; | ||
373 | ret = -EIO; | ||
374 | break; | 372 | break; |
375 | 373 | ||
376 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 374 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 2ff468591625..0694940b2e73 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c | |||
@@ -357,7 +357,7 @@ __smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
357 | } | 357 | } |
358 | 358 | ||
359 | /* | 359 | /* |
360 | * smp_call_function_single - Run a function on another CPU | 360 | * smp_call_function_single - Run a function on a specific CPU |
361 | * @func: The function to run. This must be fast and non-blocking. | 361 | * @func: The function to run. This must be fast and non-blocking. |
362 | * @info: An arbitrary pointer to pass to the function. | 362 | * @info: An arbitrary pointer to pass to the function. |
363 | * @nonatomic: Currently unused. | 363 | * @nonatomic: Currently unused. |
@@ -374,14 +374,18 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info, | |||
374 | { | 374 | { |
375 | /* prevent preemption and reschedule on another processor */ | 375 | /* prevent preemption and reschedule on another processor */ |
376 | int me = get_cpu(); | 376 | int me = get_cpu(); |
377 | |||
378 | /* Can deadlock when called with interrupts disabled */ | ||
379 | WARN_ON(irqs_disabled()); | ||
380 | |||
377 | if (cpu == me) { | 381 | if (cpu == me) { |
382 | local_irq_disable(); | ||
383 | func(info); | ||
384 | local_irq_enable(); | ||
378 | put_cpu(); | 385 | put_cpu(); |
379 | return 0; | 386 | return 0; |
380 | } | 387 | } |
381 | 388 | ||
382 | /* Can deadlock when called with interrupts disabled */ | ||
383 | WARN_ON(irqs_disabled()); | ||
384 | |||
385 | spin_lock_bh(&call_lock); | 389 | spin_lock_bh(&call_lock); |
386 | __smp_call_function_single(cpu, func, info, nonatomic, wait); | 390 | __smp_call_function_single(cpu, func, info, nonatomic, wait); |
387 | spin_unlock_bh(&call_lock); | 391 | spin_unlock_bh(&call_lock); |
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 7fa155c394d9..8713ad4a4db1 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
@@ -34,6 +34,10 @@ | |||
34 | #include <linux/bug.h> | 34 | #include <linux/bug.h> |
35 | #include <linux/kdebug.h> | 35 | #include <linux/kdebug.h> |
36 | 36 | ||
37 | #if defined(CONFIG_EDAC) | ||
38 | #include <linux/edac.h> | ||
39 | #endif | ||
40 | |||
37 | #include <asm/system.h> | 41 | #include <asm/system.h> |
38 | #include <asm/io.h> | 42 | #include <asm/io.h> |
39 | #include <asm/atomic.h> | 43 | #include <asm/atomic.h> |
@@ -330,6 +334,7 @@ static int print_trace_stack(void *data, char *name) | |||
330 | 334 | ||
331 | static void print_trace_address(void *data, unsigned long addr) | 335 | static void print_trace_address(void *data, unsigned long addr) |
332 | { | 336 | { |
337 | touch_nmi_watchdog(); | ||
333 | printk_address(addr); | 338 | printk_address(addr); |
334 | } | 339 | } |
335 | 340 | ||
@@ -518,6 +523,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err) | |||
518 | printk("\n"); | 523 | printk("\n"); |
519 | notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); | 524 | notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); |
520 | show_registers(regs); | 525 | show_registers(regs); |
526 | add_taint(TAINT_DIE); | ||
521 | /* Executive summary in case the oops scrolled away */ | 527 | /* Executive summary in case the oops scrolled away */ |
522 | printk(KERN_ALERT "RIP "); | 528 | printk(KERN_ALERT "RIP "); |
523 | printk_address(regs->rip); | 529 | printk_address(regs->rip); |
@@ -717,6 +723,13 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs) | |||
717 | reason); | 723 | reason); |
718 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); | 724 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); |
719 | 725 | ||
726 | #if defined(CONFIG_EDAC) | ||
727 | if(edac_handler_set()) { | ||
728 | edac_atomic_assert_error(); | ||
729 | return; | ||
730 | } | ||
731 | #endif | ||
732 | |||
720 | if (panic_on_unrecovered_nmi) | 733 | if (panic_on_unrecovered_nmi) |
721 | panic("NMI: Not continuing"); | 734 | panic("NMI: Not continuing"); |
722 | 735 | ||
diff --git a/arch/x86_64/kernel/tsc.c b/arch/x86_64/kernel/tsc.c index 48f9a8e6aa91..e850aa01e1b3 100644 --- a/arch/x86_64/kernel/tsc.c +++ b/arch/x86_64/kernel/tsc.c | |||
@@ -44,7 +44,7 @@ unsigned long long sched_clock(void) | |||
44 | 44 | ||
45 | static int tsc_unstable; | 45 | static int tsc_unstable; |
46 | 46 | ||
47 | static inline int check_tsc_unstable(void) | 47 | inline int check_tsc_unstable(void) |
48 | { | 48 | { |
49 | return tsc_unstable; | 49 | return tsc_unstable; |
50 | } | 50 | } |
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index dbccfda8364f..5c57ea4591c1 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S | |||
@@ -48,7 +48,9 @@ SECTIONS | |||
48 | __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) } | 48 | __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) } |
49 | __stop___ex_table = .; | 49 | __stop___ex_table = .; |
50 | 50 | ||
51 | BUG_TABLE | 51 | NOTES :text :note |
52 | |||
53 | BUG_TABLE :text | ||
52 | 54 | ||
53 | RODATA | 55 | RODATA |
54 | 56 | ||
@@ -194,10 +196,8 @@ SECTIONS | |||
194 | __initramfs_end = .; | 196 | __initramfs_end = .; |
195 | #endif | 197 | #endif |
196 | 198 | ||
197 | . = ALIGN(4096); | 199 | PERCPU(4096) |
198 | __per_cpu_start = .; | 200 | |
199 | .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) } | ||
200 | __per_cpu_end = .; | ||
201 | . = ALIGN(4096); | 201 | . = ALIGN(4096); |
202 | __init_end = .; | 202 | __init_end = .; |
203 | 203 | ||
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 635e58d443d7..84f11728fc76 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c | |||
@@ -317,7 +317,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
317 | struct vm_area_struct * vma; | 317 | struct vm_area_struct * vma; |
318 | unsigned long address; | 318 | unsigned long address; |
319 | const struct exception_table_entry *fixup; | 319 | const struct exception_table_entry *fixup; |
320 | int write; | 320 | int write, fault; |
321 | unsigned long flags; | 321 | unsigned long flags; |
322 | siginfo_t info; | 322 | siginfo_t info; |
323 | 323 | ||
@@ -450,19 +450,18 @@ good_area: | |||
450 | * make sure we exit gracefully rather than endlessly redo | 450 | * make sure we exit gracefully rather than endlessly redo |
451 | * the fault. | 451 | * the fault. |
452 | */ | 452 | */ |
453 | switch (handle_mm_fault(mm, vma, address, write)) { | 453 | fault = handle_mm_fault(mm, vma, address, write); |
454 | case VM_FAULT_MINOR: | 454 | if (unlikely(fault & VM_FAULT_ERROR)) { |
455 | tsk->min_flt++; | 455 | if (fault & VM_FAULT_OOM) |
456 | break; | 456 | goto out_of_memory; |
457 | case VM_FAULT_MAJOR: | 457 | else if (fault & VM_FAULT_SIGBUS) |
458 | tsk->maj_flt++; | 458 | goto do_sigbus; |
459 | break; | 459 | BUG(); |
460 | case VM_FAULT_SIGBUS: | ||
461 | goto do_sigbus; | ||
462 | default: | ||
463 | goto out_of_memory; | ||
464 | } | 460 | } |
465 | 461 | if (fault & VM_FAULT_MAJOR) | |
462 | tsk->maj_flt++; | ||
463 | else | ||
464 | tsk->min_flt++; | ||
466 | up_read(&mm->mmap_sem); | 465 | up_read(&mm->mmap_sem); |
467 | return; | 466 | return; |
468 | 467 | ||
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 14104ff63093..06a13d9b69db 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c | |||
@@ -50,18 +50,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
50 | switch (request) { | 50 | switch (request) { |
51 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 51 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
52 | case PTRACE_PEEKDATA: | 52 | case PTRACE_PEEKDATA: |
53 | { | 53 | ret = generic_ptrace_peekdata(child, addr, data); |
54 | unsigned long tmp; | ||
55 | int copied; | ||
56 | |||
57 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
58 | ret = -EIO; | ||
59 | if (copied != sizeof(tmp)) | ||
60 | break; | ||
61 | ret = put_user(tmp,(unsigned long *) data); | ||
62 | |||
63 | goto out; | 54 | goto out; |
64 | } | ||
65 | 55 | ||
66 | /* Read the word at location addr in the USER area. */ | 56 | /* Read the word at location addr in the USER area. */ |
67 | 57 | ||
@@ -138,10 +128,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
138 | 128 | ||
139 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 129 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
140 | case PTRACE_POKEDATA: | 130 | case PTRACE_POKEDATA: |
141 | if (access_process_vm(child, addr, &data, sizeof(data), 1) | 131 | ret = generic_ptrace_pokedata(child, addr, data); |
142 | == sizeof(data)) | ||
143 | break; | ||
144 | ret = -EIO; | ||
145 | goto out; | 132 | goto out; |
146 | 133 | ||
147 | case PTRACE_POKEUSR: | 134 | case PTRACE_POKEUSR: |
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 693ab268485e..c5e62f9d9f50 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c | |||
@@ -482,6 +482,7 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
482 | if (!user_mode(regs)) | 482 | if (!user_mode(regs)) |
483 | show_stack(NULL, (unsigned long*)regs->areg[1]); | 483 | show_stack(NULL, (unsigned long*)regs->areg[1]); |
484 | 484 | ||
485 | add_taint(TAINT_DIE); | ||
485 | spin_unlock_irq(&die_lock); | 486 | spin_unlock_irq(&die_lock); |
486 | 487 | ||
487 | if (in_interrupt()) | 488 | if (in_interrupt()) |
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index bb3f1f3097a8..ac4ed52034db 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S | |||
@@ -191,10 +191,7 @@ SECTIONS | |||
191 | __initramfs_end = .; | 191 | __initramfs_end = .; |
192 | #endif | 192 | #endif |
193 | 193 | ||
194 | . = ALIGN(4096); | 194 | PERCPU(4096) |
195 | __per_cpu_start = .; | ||
196 | .data.percpu : { *(.data.percpu) } | ||
197 | __per_cpu_end = .; | ||
198 | 195 | ||
199 | 196 | ||
200 | /* We need this dummy segment here */ | 197 | /* We need this dummy segment here */ |
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index 3dc6f2f07bbe..16004067add3 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c | |||
@@ -41,6 +41,7 @@ void do_page_fault(struct pt_regs *regs) | |||
41 | siginfo_t info; | 41 | siginfo_t info; |
42 | 42 | ||
43 | int is_write, is_exec; | 43 | int is_write, is_exec; |
44 | int fault; | ||
44 | 45 | ||
45 | info.si_code = SEGV_MAPERR; | 46 | info.si_code = SEGV_MAPERR; |
46 | 47 | ||
@@ -102,20 +103,18 @@ good_area: | |||
102 | * the fault. | 103 | * the fault. |
103 | */ | 104 | */ |
104 | survive: | 105 | survive: |
105 | switch (handle_mm_fault(mm, vma, address, is_write)) { | 106 | fault = handle_mm_fault(mm, vma, address, is_write); |
106 | case VM_FAULT_MINOR: | 107 | if (unlikely(fault & VM_FAULT_ERROR)) { |
107 | current->min_flt++; | 108 | if (fault & VM_FAULT_OOM) |
108 | break; | 109 | goto out_of_memory; |
109 | case VM_FAULT_MAJOR: | 110 | else if (fault & VM_FAULT_SIGBUS) |
110 | current->maj_flt++; | 111 | goto do_sigbus; |
111 | break; | ||
112 | case VM_FAULT_SIGBUS: | ||
113 | goto do_sigbus; | ||
114 | case VM_FAULT_OOM: | ||
115 | goto out_of_memory; | ||
116 | default: | ||
117 | BUG(); | 112 | BUG(); |
118 | } | 113 | } |
114 | if (fault & VM_FAULT_MAJOR) | ||
115 | current->maj_flt++; | ||
116 | else | ||
117 | current->min_flt++; | ||
119 | 118 | ||
120 | up_read(&mm->mmap_sem); | 119 | up_read(&mm->mmap_sem); |
121 | return; | 120 | return; |