diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/kprobes.c | 14 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 70 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/sysfs.c | 18 | ||||
-rw-r--r-- | arch/powerpc/mm/numa.c | 32 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/Kconfig | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/setup.c | 78 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 91 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_event.c | 8 |
9 files changed, 205 insertions, 114 deletions
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 856ef1a832b9..f78866367b70 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -90,15 +90,15 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) | |||
90 | 90 | ||
91 | static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 91 | static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
92 | { | 92 | { |
93 | kprobe_opcode_t insn = *p->ainsn.insn; | ||
94 | |||
95 | regs->msr |= MSR_SE; | 93 | regs->msr |= MSR_SE; |
96 | 94 | ||
97 | /* single step inline if it is a trap variant */ | 95 | /* |
98 | if (is_trap(insn)) | 96 | * On powerpc we should single step on the original |
99 | regs->nip = (unsigned long)p->addr; | 97 | * instruction even if the probed insn is a trap |
100 | else | 98 | * variant as values in regs could play a part in |
101 | regs->nip = (unsigned long)p->ainsn.insn; | 99 | * if the trap is taken or not |
100 | */ | ||
101 | regs->nip = (unsigned long)p->ainsn.insn; | ||
102 | } | 102 | } |
103 | 103 | ||
104 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | 104 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 1cb69e8fb0b1..9a07f97f0712 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -885,6 +885,74 @@ void __init unflatten_device_tree(void) | |||
885 | DBG(" <- unflatten_device_tree()\n"); | 885 | DBG(" <- unflatten_device_tree()\n"); |
886 | } | 886 | } |
887 | 887 | ||
888 | /* | ||
889 | * ibm,pa-features is a per-cpu property that contains a string of | ||
890 | * attribute descriptors, each of which has a 2 byte header plus up | ||
891 | * to 254 bytes worth of processor attribute bits. First header | ||
892 | * byte specifies the number of bytes following the header. | ||
893 | * Second header byte is an "attribute-specifier" type, of which | ||
894 | * zero is the only currently-defined value. | ||
895 | * Implementation: Pass in the byte and bit offset for the feature | ||
896 | * that we are interested in. The function will return -1 if the | ||
897 | * pa-features property is missing, or a 1/0 to indicate if the feature | ||
898 | * is supported/not supported. Note that the bit numbers are | ||
899 | * big-endian to match the definition in PAPR. | ||
900 | */ | ||
901 | static struct ibm_pa_feature { | ||
902 | unsigned long cpu_features; /* CPU_FTR_xxx bit */ | ||
903 | unsigned int cpu_user_ftrs; /* PPC_FEATURE_xxx bit */ | ||
904 | unsigned char pabyte; /* byte number in ibm,pa-features */ | ||
905 | unsigned char pabit; /* bit number (big-endian) */ | ||
906 | unsigned char invert; /* if 1, pa bit set => clear feature */ | ||
907 | } ibm_pa_features[] __initdata = { | ||
908 | {0, PPC_FEATURE_HAS_MMU, 0, 0, 0}, | ||
909 | {0, PPC_FEATURE_HAS_FPU, 0, 1, 0}, | ||
910 | {CPU_FTR_SLB, 0, 0, 2, 0}, | ||
911 | {CPU_FTR_CTRL, 0, 0, 3, 0}, | ||
912 | {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, | ||
913 | {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, | ||
914 | {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, | ||
915 | }; | ||
916 | |||
917 | static void __init check_cpu_pa_features(unsigned long node) | ||
918 | { | ||
919 | unsigned char *pa_ftrs; | ||
920 | unsigned long len, tablelen, i, bit; | ||
921 | |||
922 | pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); | ||
923 | if (pa_ftrs == NULL) | ||
924 | return; | ||
925 | |||
926 | /* find descriptor with type == 0 */ | ||
927 | for (;;) { | ||
928 | if (tablelen < 3) | ||
929 | return; | ||
930 | len = 2 + pa_ftrs[0]; | ||
931 | if (tablelen < len) | ||
932 | return; /* descriptor 0 not found */ | ||
933 | if (pa_ftrs[1] == 0) | ||
934 | break; | ||
935 | tablelen -= len; | ||
936 | pa_ftrs += len; | ||
937 | } | ||
938 | |||
939 | /* loop over bits we know about */ | ||
940 | for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) { | ||
941 | struct ibm_pa_feature *fp = &ibm_pa_features[i]; | ||
942 | |||
943 | if (fp->pabyte >= pa_ftrs[0]) | ||
944 | continue; | ||
945 | bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1; | ||
946 | if (bit ^ fp->invert) { | ||
947 | cur_cpu_spec->cpu_features |= fp->cpu_features; | ||
948 | cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; | ||
949 | } else { | ||
950 | cur_cpu_spec->cpu_features &= ~fp->cpu_features; | ||
951 | cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs; | ||
952 | } | ||
953 | } | ||
954 | } | ||
955 | |||
888 | static int __init early_init_dt_scan_cpus(unsigned long node, | 956 | static int __init early_init_dt_scan_cpus(unsigned long node, |
889 | const char *uname, int depth, | 957 | const char *uname, int depth, |
890 | void *data) | 958 | void *data) |
@@ -969,6 +1037,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
969 | } | 1037 | } |
970 | #endif /* CONFIG_ALTIVEC */ | 1038 | #endif /* CONFIG_ALTIVEC */ |
971 | 1039 | ||
1040 | check_cpu_pa_features(node); | ||
1041 | |||
972 | #ifdef CONFIG_PPC_PSERIES | 1042 | #ifdef CONFIG_PPC_PSERIES |
973 | if (nthreads > 1) | 1043 | if (nthreads > 1) |
974 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; | 1044 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index bcb83574335b..4a677d1bd4ef 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -538,7 +538,7 @@ void do_syscall_trace_enter(struct pt_regs *regs) | |||
538 | do_syscall_trace(); | 538 | do_syscall_trace(); |
539 | 539 | ||
540 | if (unlikely(current->audit_context)) | 540 | if (unlikely(current->audit_context)) |
541 | audit_syscall_entry(current, | 541 | audit_syscall_entry( |
542 | #ifdef CONFIG_PPC32 | 542 | #ifdef CONFIG_PPC32 |
543 | AUDIT_ARCH_PPC, | 543 | AUDIT_ARCH_PPC, |
544 | #else | 544 | #else |
@@ -556,8 +556,7 @@ void do_syscall_trace_leave(struct pt_regs *regs) | |||
556 | #endif | 556 | #endif |
557 | 557 | ||
558 | if (unlikely(current->audit_context)) | 558 | if (unlikely(current->audit_context)) |
559 | audit_syscall_exit(current, | 559 | audit_syscall_exit((regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, |
560 | (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, | ||
561 | regs->result); | 560 | regs->result); |
562 | 561 | ||
563 | if ((test_thread_flag(TIF_SYSCALL_TRACE) | 562 | if ((test_thread_flag(TIF_SYSCALL_TRACE) |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index ed737cacf92d..5bc2585c8036 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -322,13 +322,31 @@ static void register_nodes(void) | |||
322 | } | 322 | } |
323 | } | 323 | } |
324 | } | 324 | } |
325 | |||
326 | int sysfs_add_device_to_node(struct sys_device *dev, int nid) | ||
327 | { | ||
328 | struct node *node = &node_devices[nid]; | ||
329 | return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, | ||
330 | kobject_name(&dev->kobj)); | ||
331 | } | ||
332 | |||
333 | void sysfs_remove_device_from_node(struct sys_device *dev, int nid) | ||
334 | { | ||
335 | struct node *node = &node_devices[nid]; | ||
336 | sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); | ||
337 | } | ||
338 | |||
325 | #else | 339 | #else |
326 | static void register_nodes(void) | 340 | static void register_nodes(void) |
327 | { | 341 | { |
328 | return; | 342 | return; |
329 | } | 343 | } |
344 | |||
330 | #endif | 345 | #endif |
331 | 346 | ||
347 | EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); | ||
348 | EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); | ||
349 | |||
332 | /* Only valid if CPU is present. */ | 350 | /* Only valid if CPU is present. */ |
333 | static ssize_t show_physical_id(struct sys_device *dev, char *buf) | 351 | static ssize_t show_physical_id(struct sys_device *dev, char *buf) |
334 | { | 352 | { |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 0a335f34974c..092355f37399 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -194,7 +194,7 @@ static int *of_get_associativity(struct device_node *dev) | |||
194 | /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa | 194 | /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa |
195 | * info is found. | 195 | * info is found. |
196 | */ | 196 | */ |
197 | static int of_node_to_nid(struct device_node *device) | 197 | static int of_node_to_nid_single(struct device_node *device) |
198 | { | 198 | { |
199 | int nid = -1; | 199 | int nid = -1; |
200 | unsigned int *tmp; | 200 | unsigned int *tmp; |
@@ -216,6 +216,28 @@ out: | |||
216 | return nid; | 216 | return nid; |
217 | } | 217 | } |
218 | 218 | ||
219 | /* Walk the device tree upwards, looking for an associativity id */ | ||
220 | int of_node_to_nid(struct device_node *device) | ||
221 | { | ||
222 | struct device_node *tmp; | ||
223 | int nid = -1; | ||
224 | |||
225 | of_node_get(device); | ||
226 | while (device) { | ||
227 | nid = of_node_to_nid_single(device); | ||
228 | if (nid != -1) | ||
229 | break; | ||
230 | |||
231 | tmp = device; | ||
232 | device = of_get_parent(tmp); | ||
233 | of_node_put(tmp); | ||
234 | } | ||
235 | of_node_put(device); | ||
236 | |||
237 | return nid; | ||
238 | } | ||
239 | EXPORT_SYMBOL_GPL(of_node_to_nid); | ||
240 | |||
219 | /* | 241 | /* |
220 | * In theory, the "ibm,associativity" property may contain multiple | 242 | * In theory, the "ibm,associativity" property may contain multiple |
221 | * associativity lists because a resource may be multiply connected | 243 | * associativity lists because a resource may be multiply connected |
@@ -300,7 +322,7 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu) | |||
300 | goto out; | 322 | goto out; |
301 | } | 323 | } |
302 | 324 | ||
303 | nid = of_node_to_nid(cpu); | 325 | nid = of_node_to_nid_single(cpu); |
304 | 326 | ||
305 | if (nid < 0 || !node_online(nid)) | 327 | if (nid < 0 || !node_online(nid)) |
306 | nid = any_online_node(NODE_MASK_ALL); | 328 | nid = any_online_node(NODE_MASK_ALL); |
@@ -393,7 +415,7 @@ static int __init parse_numa_properties(void) | |||
393 | 415 | ||
394 | cpu = find_cpu_node(i); | 416 | cpu = find_cpu_node(i); |
395 | BUG_ON(!cpu); | 417 | BUG_ON(!cpu); |
396 | nid = of_node_to_nid(cpu); | 418 | nid = of_node_to_nid_single(cpu); |
397 | of_node_put(cpu); | 419 | of_node_put(cpu); |
398 | 420 | ||
399 | /* | 421 | /* |
@@ -437,7 +459,7 @@ new_range: | |||
437 | * have associativity properties. If none, then | 459 | * have associativity properties. If none, then |
438 | * everything goes to default_nid. | 460 | * everything goes to default_nid. |
439 | */ | 461 | */ |
440 | nid = of_node_to_nid(memory); | 462 | nid = of_node_to_nid_single(memory); |
441 | if (nid < 0) | 463 | if (nid < 0) |
442 | nid = default_nid; | 464 | nid = default_nid; |
443 | node_set_online(nid); | 465 | node_set_online(nid); |
@@ -776,7 +798,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr) | |||
776 | ha_new_range: | 798 | ha_new_range: |
777 | start = read_n_cells(n_mem_addr_cells, &memcell_buf); | 799 | start = read_n_cells(n_mem_addr_cells, &memcell_buf); |
778 | size = read_n_cells(n_mem_size_cells, &memcell_buf); | 800 | size = read_n_cells(n_mem_size_cells, &memcell_buf); |
779 | nid = of_node_to_nid(memory); | 801 | nid = of_node_to_nid_single(memory); |
780 | 802 | ||
781 | /* Domains not present at boot default to 0 */ | 803 | /* Domains not present at boot default to 0 */ |
782 | if (nid < 0 || !node_online(nid)) | 804 | if (nid < 0 || !node_online(nid)) |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index c2a3db8edb0c..6a02d51086c8 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -12,7 +12,8 @@ config SPU_FS | |||
12 | 12 | ||
13 | config SPUFS_MMAP | 13 | config SPUFS_MMAP |
14 | bool | 14 | bool |
15 | depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES | 15 | depends on SPU_FS && SPARSEMEM |
16 | select MEMORY_HOTPLUG | ||
16 | default y | 17 | default y |
17 | 18 | ||
18 | endmenu | 19 | endmenu |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index dac5d0365fde..6574b22b3cf3 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
30 | #include <linux/root_dev.h> | 30 | #include <linux/root_dev.h> |
31 | #include <linux/console.h> | 31 | #include <linux/console.h> |
32 | #include <linux/mutex.h> | ||
33 | #include <linux/memory_hotplug.h> | ||
32 | 34 | ||
33 | #include <asm/mmu.h> | 35 | #include <asm/mmu.h> |
34 | #include <asm/processor.h> | 36 | #include <asm/processor.h> |
@@ -46,6 +48,7 @@ | |||
46 | #include <asm/cputable.h> | 48 | #include <asm/cputable.h> |
47 | #include <asm/ppc-pci.h> | 49 | #include <asm/ppc-pci.h> |
48 | #include <asm/irq.h> | 50 | #include <asm/irq.h> |
51 | #include <asm/spu.h> | ||
49 | 52 | ||
50 | #include "interrupt.h" | 53 | #include "interrupt.h" |
51 | #include "iommu.h" | 54 | #include "iommu.h" |
@@ -69,77 +72,6 @@ static void cell_show_cpuinfo(struct seq_file *m) | |||
69 | of_node_put(root); | 72 | of_node_put(root); |
70 | } | 73 | } |
71 | 74 | ||
72 | #ifdef CONFIG_SPARSEMEM | ||
73 | static int __init find_spu_node_id(struct device_node *spe) | ||
74 | { | ||
75 | unsigned int *id; | ||
76 | #ifdef CONFIG_NUMA | ||
77 | struct device_node *cpu; | ||
78 | cpu = spe->parent->parent; | ||
79 | id = (unsigned int *)get_property(cpu, "node-id", NULL); | ||
80 | #else | ||
81 | id = NULL; | ||
82 | #endif | ||
83 | return id ? *id : 0; | ||
84 | } | ||
85 | |||
86 | static void __init cell_spuprop_present(struct device_node *spe, | ||
87 | const char *prop, int early) | ||
88 | { | ||
89 | struct address_prop { | ||
90 | unsigned long address; | ||
91 | unsigned int len; | ||
92 | } __attribute__((packed)) *p; | ||
93 | int proplen; | ||
94 | |||
95 | unsigned long start_pfn, end_pfn, pfn; | ||
96 | int node_id; | ||
97 | |||
98 | p = (void*)get_property(spe, prop, &proplen); | ||
99 | WARN_ON(proplen != sizeof (*p)); | ||
100 | |||
101 | node_id = find_spu_node_id(spe); | ||
102 | |||
103 | start_pfn = p->address >> PAGE_SHIFT; | ||
104 | end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
105 | |||
106 | /* We need to call memory_present *before* the call to sparse_init, | ||
107 | but we can initialize the page structs only *after* that call. | ||
108 | Thus, we're being called twice. */ | ||
109 | if (early) | ||
110 | memory_present(node_id, start_pfn, end_pfn); | ||
111 | else { | ||
112 | /* As the pages backing SPU LS and I/O are outside the range | ||
113 | of regular memory, their page structs were not initialized | ||
114 | by free_area_init. Do it here instead. */ | ||
115 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { | ||
116 | struct page *page = pfn_to_page(pfn); | ||
117 | set_page_links(page, ZONE_DMA, node_id, pfn); | ||
118 | init_page_count(page); | ||
119 | reset_page_mapcount(page); | ||
120 | SetPageReserved(page); | ||
121 | INIT_LIST_HEAD(&page->lru); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void __init cell_spumem_init(int early) | ||
127 | { | ||
128 | struct device_node *node; | ||
129 | for (node = of_find_node_by_type(NULL, "spe"); | ||
130 | node; node = of_find_node_by_type(node, "spe")) { | ||
131 | cell_spuprop_present(node, "local-store", early); | ||
132 | cell_spuprop_present(node, "problem", early); | ||
133 | cell_spuprop_present(node, "priv1", early); | ||
134 | cell_spuprop_present(node, "priv2", early); | ||
135 | } | ||
136 | } | ||
137 | #else | ||
138 | static void __init cell_spumem_init(int early) | ||
139 | { | ||
140 | } | ||
141 | #endif | ||
142 | |||
143 | static void cell_progress(char *s, unsigned short hex) | 75 | static void cell_progress(char *s, unsigned short hex) |
144 | { | 76 | { |
145 | printk("*** %04x : %s\n", hex, s ? s : ""); | 77 | printk("*** %04x : %s\n", hex, s ? s : ""); |
@@ -172,8 +104,6 @@ static void __init cell_setup_arch(void) | |||
172 | #endif | 104 | #endif |
173 | 105 | ||
174 | mmio_nvram_init(); | 106 | mmio_nvram_init(); |
175 | |||
176 | cell_spumem_init(0); | ||
177 | } | 107 | } |
178 | 108 | ||
179 | /* | 109 | /* |
@@ -189,8 +119,6 @@ static void __init cell_init_early(void) | |||
189 | 119 | ||
190 | ppc64_interrupt_controller = IC_CELL_PIC; | 120 | ppc64_interrupt_controller = IC_CELL_PIC; |
191 | 121 | ||
192 | cell_spumem_init(1); | ||
193 | |||
194 | DBG(" <- cell_init_early()\n"); | 122 | DBG(" <- cell_init_early()\n"); |
195 | } | 123 | } |
196 | 124 | ||
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index ef47a6239d48..ad141fe8d52d 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -520,8 +520,50 @@ void spu_irq_setaffinity(struct spu *spu, int cpu) | |||
520 | } | 520 | } |
521 | EXPORT_SYMBOL_GPL(spu_irq_setaffinity); | 521 | EXPORT_SYMBOL_GPL(spu_irq_setaffinity); |
522 | 522 | ||
523 | static void __iomem * __init map_spe_prop(struct device_node *n, | 523 | static int __init find_spu_node_id(struct device_node *spe) |
524 | const char *name) | 524 | { |
525 | unsigned int *id; | ||
526 | struct device_node *cpu; | ||
527 | cpu = spe->parent->parent; | ||
528 | id = (unsigned int *)get_property(cpu, "node-id", NULL); | ||
529 | return id ? *id : 0; | ||
530 | } | ||
531 | |||
532 | static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe, | ||
533 | const char *prop) | ||
534 | { | ||
535 | static DEFINE_MUTEX(add_spumem_mutex); | ||
536 | |||
537 | struct address_prop { | ||
538 | unsigned long address; | ||
539 | unsigned int len; | ||
540 | } __attribute__((packed)) *p; | ||
541 | int proplen; | ||
542 | |||
543 | unsigned long start_pfn, nr_pages; | ||
544 | struct pglist_data *pgdata; | ||
545 | struct zone *zone; | ||
546 | int ret; | ||
547 | |||
548 | p = (void*)get_property(spe, prop, &proplen); | ||
549 | WARN_ON(proplen != sizeof (*p)); | ||
550 | |||
551 | start_pfn = p->address >> PAGE_SHIFT; | ||
552 | nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
553 | |||
554 | pgdata = NODE_DATA(spu->nid); | ||
555 | zone = pgdata->node_zones; | ||
556 | |||
557 | /* XXX rethink locking here */ | ||
558 | mutex_lock(&add_spumem_mutex); | ||
559 | ret = __add_pages(zone, start_pfn, nr_pages); | ||
560 | mutex_unlock(&add_spumem_mutex); | ||
561 | |||
562 | return ret; | ||
563 | } | ||
564 | |||
565 | static void __iomem * __init map_spe_prop(struct spu *spu, | ||
566 | struct device_node *n, const char *name) | ||
525 | { | 567 | { |
526 | struct address_prop { | 568 | struct address_prop { |
527 | unsigned long address; | 569 | unsigned long address; |
@@ -530,6 +572,8 @@ static void __iomem * __init map_spe_prop(struct device_node *n, | |||
530 | 572 | ||
531 | void *p; | 573 | void *p; |
532 | int proplen; | 574 | int proplen; |
575 | void* ret = NULL; | ||
576 | int err = 0; | ||
533 | 577 | ||
534 | p = get_property(n, name, &proplen); | 578 | p = get_property(n, name, &proplen); |
535 | if (proplen != sizeof (struct address_prop)) | 579 | if (proplen != sizeof (struct address_prop)) |
@@ -537,7 +581,14 @@ static void __iomem * __init map_spe_prop(struct device_node *n, | |||
537 | 581 | ||
538 | prop = p; | 582 | prop = p; |
539 | 583 | ||
540 | return ioremap(prop->address, prop->len); | 584 | err = cell_spuprop_present(spu, n, name); |
585 | if (err && (err != -EEXIST)) | ||
586 | goto out; | ||
587 | |||
588 | ret = ioremap(prop->address, prop->len); | ||
589 | |||
590 | out: | ||
591 | return ret; | ||
541 | } | 592 | } |
542 | 593 | ||
543 | static void spu_unmap(struct spu *spu) | 594 | static void spu_unmap(struct spu *spu) |
@@ -548,44 +599,45 @@ static void spu_unmap(struct spu *spu) | |||
548 | iounmap((u8 __iomem *)spu->local_store); | 599 | iounmap((u8 __iomem *)spu->local_store); |
549 | } | 600 | } |
550 | 601 | ||
551 | static int __init spu_map_device(struct spu *spu, struct device_node *spe) | 602 | static int __init spu_map_device(struct spu *spu, struct device_node *node) |
552 | { | 603 | { |
553 | char *prop; | 604 | char *prop; |
554 | int ret; | 605 | int ret; |
555 | 606 | ||
556 | ret = -ENODEV; | 607 | ret = -ENODEV; |
557 | prop = get_property(spe, "isrc", NULL); | 608 | prop = get_property(node, "isrc", NULL); |
558 | if (!prop) | 609 | if (!prop) |
559 | goto out; | 610 | goto out; |
560 | spu->isrc = *(unsigned int *)prop; | 611 | spu->isrc = *(unsigned int *)prop; |
561 | 612 | ||
562 | spu->name = get_property(spe, "name", NULL); | 613 | spu->name = get_property(node, "name", NULL); |
563 | if (!spu->name) | 614 | if (!spu->name) |
564 | goto out; | 615 | goto out; |
565 | 616 | ||
566 | prop = get_property(spe, "local-store", NULL); | 617 | prop = get_property(node, "local-store", NULL); |
567 | if (!prop) | 618 | if (!prop) |
568 | goto out; | 619 | goto out; |
569 | spu->local_store_phys = *(unsigned long *)prop; | 620 | spu->local_store_phys = *(unsigned long *)prop; |
570 | 621 | ||
571 | /* we use local store as ram, not io memory */ | 622 | /* we use local store as ram, not io memory */ |
572 | spu->local_store = (void __force *)map_spe_prop(spe, "local-store"); | 623 | spu->local_store = (void __force *) |
624 | map_spe_prop(spu, node, "local-store"); | ||
573 | if (!spu->local_store) | 625 | if (!spu->local_store) |
574 | goto out; | 626 | goto out; |
575 | 627 | ||
576 | prop = get_property(spe, "problem", NULL); | 628 | prop = get_property(node, "problem", NULL); |
577 | if (!prop) | 629 | if (!prop) |
578 | goto out_unmap; | 630 | goto out_unmap; |
579 | spu->problem_phys = *(unsigned long *)prop; | 631 | spu->problem_phys = *(unsigned long *)prop; |
580 | 632 | ||
581 | spu->problem= map_spe_prop(spe, "problem"); | 633 | spu->problem= map_spe_prop(spu, node, "problem"); |
582 | if (!spu->problem) | 634 | if (!spu->problem) |
583 | goto out_unmap; | 635 | goto out_unmap; |
584 | 636 | ||
585 | spu->priv1= map_spe_prop(spe, "priv1"); | 637 | spu->priv1= map_spe_prop(spu, node, "priv1"); |
586 | /* priv1 is not available on a hypervisor */ | 638 | /* priv1 is not available on a hypervisor */ |
587 | 639 | ||
588 | spu->priv2= map_spe_prop(spe, "priv2"); | 640 | spu->priv2= map_spe_prop(spu, node, "priv2"); |
589 | if (!spu->priv2) | 641 | if (!spu->priv2) |
590 | goto out_unmap; | 642 | goto out_unmap; |
591 | ret = 0; | 643 | ret = 0; |
@@ -597,17 +649,6 @@ out: | |||
597 | return ret; | 649 | return ret; |
598 | } | 650 | } |
599 | 651 | ||
600 | static int __init find_spu_node_id(struct device_node *spe) | ||
601 | { | ||
602 | unsigned int *id; | ||
603 | struct device_node *cpu; | ||
604 | |||
605 | cpu = spe->parent->parent; | ||
606 | id = (unsigned int *)get_property(cpu, "node-id", NULL); | ||
607 | |||
608 | return id ? *id : 0; | ||
609 | } | ||
610 | |||
611 | static int __init create_spu(struct device_node *spe) | 652 | static int __init create_spu(struct device_node *spe) |
612 | { | 653 | { |
613 | struct spu *spu; | 654 | struct spu *spu; |
@@ -624,6 +665,10 @@ static int __init create_spu(struct device_node *spe) | |||
624 | goto out_free; | 665 | goto out_free; |
625 | 666 | ||
626 | spu->node = find_spu_node_id(spe); | 667 | spu->node = find_spu_node_id(spe); |
668 | spu->nid = of_node_to_nid(spe); | ||
669 | if (spu->nid == -1) | ||
670 | spu->nid = 0; | ||
671 | |||
627 | spu->stop_code = 0; | 672 | spu->stop_code = 0; |
628 | spu->slb_replace = 0; | 673 | spu->slb_replace = 0; |
629 | spu->mm = NULL; | 674 | spu->mm = NULL; |
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index a1bda6f96fd1..40020c65c89e 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c | |||
@@ -118,7 +118,15 @@ int eeh_send_failure_event (struct device_node *dn, | |||
118 | { | 118 | { |
119 | unsigned long flags; | 119 | unsigned long flags; |
120 | struct eeh_event *event; | 120 | struct eeh_event *event; |
121 | char *location; | ||
121 | 122 | ||
123 | if (!mem_init_done) { | ||
124 | printk(KERN_ERR "EEH: event during early boot not handled\n"); | ||
125 | location = (char *) get_property(dn, "ibm,loc-code", NULL); | ||
126 | printk(KERN_ERR "EEH: device node = %s\n", dn->full_name); | ||
127 | printk(KERN_ERR "EEH: PCI location = %s\n", location); | ||
128 | return 1; | ||
129 | } | ||
122 | event = kmalloc(sizeof(*event), GFP_ATOMIC); | 130 | event = kmalloc(sizeof(*event), GFP_ATOMIC); |
123 | if (event == NULL) { | 131 | if (event == NULL) { |
124 | printk (KERN_ERR "EEH: out of memory, event not handled\n"); | 132 | printk (KERN_ERR "EEH: out of memory, event not handled\n"); |