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"); |
