diff options
author | Joel H Schopp <jschopp@us.ibm.com> | 2006-05-01 15:16:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-01 21:17:46 -0400 |
commit | bed120c64eb07b6838bb758109811484af8cebba (patch) | |
tree | 884231ab38d01a2b19c6d062f5230ea8b9f5ecb3 /arch/powerpc/platforms/cell/setup.c | |
parent | 46a66eecdf7bc12562ecb492297447ed0e1ecf59 (diff) |
[PATCH] spufs: fix for CONFIG_NUMA
Based on an older patch from Mike Kravetz <kravetz@us.ibm.com>
We need to have a mem_map for high addresses in order to make fops->no_page
work on spufs mem and register files. So far, we have used the
memory_present() function during early bootup, but that did not work when
CONFIG_NUMA was enabled.
We now use the __add_pages() function to add the mem_map when loading the
spufs module, which is a lot nicer.
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/powerpc/platforms/cell/setup.c')
-rw-r--r-- | arch/powerpc/platforms/cell/setup.c | 78 |
1 files changed, 3 insertions, 75 deletions
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 | ||