aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm')
-rw-r--r--arch/sh/mm/Kconfig87
-rw-r--r--arch/sh/mm/Makefile5
-rw-r--r--arch/sh/mm/fault.c45
-rw-r--r--arch/sh/mm/init.c107
-rw-r--r--arch/sh/mm/numa.c92
-rw-r--r--arch/sh/mm/pg-dma.c95
6 files changed, 248 insertions, 183 deletions
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
index 253346d7b316..28d79a474cde 100644
--- a/arch/sh/mm/Kconfig
+++ b/arch/sh/mm/Kconfig
@@ -1,5 +1,3 @@
1menu "Processor selection"
2
3# 1#
4# Processor families 2# Processor families
5# 3#
@@ -38,27 +36,31 @@ config CPU_SUBTYPE_ST40
38config CPU_SHX2 36config CPU_SHX2
39 bool 37 bool
40 38
39config CPU_SHX3
40 bool
41
42choice
43 prompt "Processor sub-type selection"
44
41# 45#
42# Processor subtypes 46# Processor subtypes
43# 47#
44 48
45comment "SH-2 Processor Support" 49# SH-2 Processor Support
46
47config CPU_SUBTYPE_SH7604
48 bool "Support SH7604 processor"
49 select CPU_SH2
50 50
51config CPU_SUBTYPE_SH7619 51config CPU_SUBTYPE_SH7619
52 bool "Support SH7619 processor" 52 bool "Support SH7619 processor"
53 select CPU_SH2 53 select CPU_SH2
54 select CPU_HAS_IPR_IRQ
54 55
55comment "SH-2A Processor Support" 56# SH-2A Processor Support
56 57
57config CPU_SUBTYPE_SH7206 58config CPU_SUBTYPE_SH7206
58 bool "Support SH7206 processor" 59 bool "Support SH7206 processor"
59 select CPU_SH2A 60 select CPU_SH2A
61 select CPU_HAS_IPR_IRQ
60 62
61comment "SH-3 Processor Support" 63# SH-3 Processor Support
62 64
63config CPU_SUBTYPE_SH7300 65config CPU_SUBTYPE_SH7300
64 bool "Support SH7300 processor" 66 bool "Support SH7300 processor"
@@ -113,7 +115,7 @@ config CPU_SUBTYPE_SH7712
113 help 115 help
114 Select SH7712 if you have a SH3-DSP SH7712 CPU. 116 Select SH7712 if you have a SH3-DSP SH7712 CPU.
115 117
116comment "SH-4 Processor Support" 118# SH-4 Processor Support
117 119
118config CPU_SUBTYPE_SH7750 120config CPU_SUBTYPE_SH7750
119 bool "Support SH7750 processor" 121 bool "Support SH7750 processor"
@@ -125,7 +127,7 @@ config CPU_SUBTYPE_SH7750
125config CPU_SUBTYPE_SH7091 127config CPU_SUBTYPE_SH7091
126 bool "Support SH7091 processor" 128 bool "Support SH7091 processor"
127 select CPU_SH4 129 select CPU_SH4
128 select CPU_SUBTYPE_SH7750 130 select CPU_HAS_IPR_IRQ
129 help 131 help
130 Select SH7091 if you have an SH-4 based Sega device (such as 132 Select SH7091 if you have an SH-4 based Sega device (such as
131 the Dreamcast, Naomi, and Naomi 2). 133 the Dreamcast, Naomi, and Naomi 2).
@@ -133,13 +135,11 @@ config CPU_SUBTYPE_SH7091
133config CPU_SUBTYPE_SH7750R 135config CPU_SUBTYPE_SH7750R
134 bool "Support SH7750R processor" 136 bool "Support SH7750R processor"
135 select CPU_SH4 137 select CPU_SH4
136 select CPU_SUBTYPE_SH7750
137 select CPU_HAS_IPR_IRQ 138 select CPU_HAS_IPR_IRQ
138 139
139config CPU_SUBTYPE_SH7750S 140config CPU_SUBTYPE_SH7750S
140 bool "Support SH7750S processor" 141 bool "Support SH7750S processor"
141 select CPU_SH4 142 select CPU_SH4
142 select CPU_SUBTYPE_SH7750
143 select CPU_HAS_IPR_IRQ 143 select CPU_HAS_IPR_IRQ
144 144
145config CPU_SUBTYPE_SH7751 145config CPU_SUBTYPE_SH7751
@@ -153,7 +153,6 @@ config CPU_SUBTYPE_SH7751
153config CPU_SUBTYPE_SH7751R 153config CPU_SUBTYPE_SH7751R
154 bool "Support SH7751R processor" 154 bool "Support SH7751R processor"
155 select CPU_SH4 155 select CPU_SH4
156 select CPU_SUBTYPE_SH7751
157 select CPU_HAS_IPR_IRQ 156 select CPU_HAS_IPR_IRQ
158 157
159config CPU_SUBTYPE_SH7760 158config CPU_SUBTYPE_SH7760
@@ -166,7 +165,7 @@ config CPU_SUBTYPE_SH4_202
166 bool "Support SH4-202 processor" 165 bool "Support SH4-202 processor"
167 select CPU_SH4 166 select CPU_SH4
168 167
169comment "ST40 Processor Support" 168# ST40 Processor Support
170 169
171config CPU_SUBTYPE_ST40STB1 170config CPU_SUBTYPE_ST40STB1
172 bool "Support ST40STB1/ST40RA processors" 171 bool "Support ST40STB1/ST40RA processors"
@@ -181,7 +180,7 @@ config CPU_SUBTYPE_ST40GX1
181 help 180 help
182 Select ST40GX1 if you have a ST40GX1 CPU. 181 Select ST40GX1 if you have a ST40GX1 CPU.
183 182
184comment "SH-4A Processor Support" 183# SH-4A Processor Support
185 184
186config CPU_SUBTYPE_SH7770 185config CPU_SUBTYPE_SH7770
187 bool "Support SH7770 processor" 186 bool "Support SH7770 processor"
@@ -198,7 +197,13 @@ config CPU_SUBTYPE_SH7785
198 select CPU_SHX2 197 select CPU_SHX2
199 select CPU_HAS_INTC2_IRQ 198 select CPU_HAS_INTC2_IRQ
200 199
201comment "SH4AL-DSP Processor Support" 200config CPU_SUBTYPE_SHX3
201 bool "Support SH-X3 processor"
202 select CPU_SH4A
203 select CPU_SHX3
204 select CPU_HAS_INTC2_IRQ
205
206# SH4AL-DSP Processor Support
202 207
203config CPU_SUBTYPE_SH73180 208config CPU_SUBTYPE_SH73180
204 bool "Support SH73180 processor" 209 bool "Support SH73180 processor"
@@ -213,8 +218,10 @@ config CPU_SUBTYPE_SH7722
213 select CPU_SH4AL_DSP 218 select CPU_SH4AL_DSP
214 select CPU_SHX2 219 select CPU_SHX2
215 select CPU_HAS_IPR_IRQ 220 select CPU_HAS_IPR_IRQ
221 select ARCH_SPARSEMEM_ENABLE
222 select SYS_SUPPORTS_NUMA
216 223
217endmenu 224endchoice
218 225
219menu "Memory management options" 226menu "Memory management options"
220 227
@@ -266,7 +273,7 @@ config MEMORY_SIZE
266 273
267config 32BIT 274config 32BIT
268 bool "Support 32-bit physical addressing through PMB" 275 bool "Support 32-bit physical addressing through PMB"
269 depends on CPU_SH4A && MMU && (!X2TLB || BROKEN) 276 depends on MMU && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785)
270 default y 277 default y
271 help 278 help
272 If you say Y here, physical addressing will be extended to 279 If you say Y here, physical addressing will be extended to
@@ -295,6 +302,17 @@ config VSYSCALL
295 For systems with an MMU that can afford to give up a page, 302 For systems with an MMU that can afford to give up a page,
296 (the default value) say Y. 303 (the default value) say Y.
297 304
305config NUMA
306 bool "Non Uniform Memory Access (NUMA) Support"
307 depends on MMU && SYS_SUPPORTS_NUMA && EXPERIMENTAL
308 default n
309 help
310 Some SH systems have many various memories scattered around
311 the address space, each with varying latencies. This enables
312 support for these blocks by binding them to nodes and allowing
313 memory policies to be used for prioritizing and controlling
314 allocation behaviour.
315
298config NODES_SHIFT 316config NODES_SHIFT
299 int 317 int
300 default "1" 318 default "1"
@@ -302,14 +320,34 @@ config NODES_SHIFT
302 320
303config ARCH_FLATMEM_ENABLE 321config ARCH_FLATMEM_ENABLE
304 def_bool y 322 def_bool y
323 depends on !NUMA
324
325config ARCH_SPARSEMEM_ENABLE
326 def_bool y
327 select SPARSEMEM_STATIC
328
329config ARCH_SPARSEMEM_DEFAULT
330 def_bool y
305 331
306config MAX_ACTIVE_REGIONS 332config MAX_ACTIVE_REGIONS
307 int 333 int
334 default "2" if (CPU_SUBTYPE_SH7722 && SPARSEMEM)
308 default "1" 335 default "1"
309 336
310config ARCH_POPULATES_NODE_MAP 337config ARCH_POPULATES_NODE_MAP
311 def_bool y 338 def_bool y
312 339
340config ARCH_SELECT_MEMORY_MODEL
341 def_bool y
342
343config ARCH_ENABLE_MEMORY_HOTPLUG
344 def_bool y
345 depends on SPARSEMEM
346
347config ARCH_MEMORY_PROBE
348 def_bool y
349 depends on MEMORY_HOTPLUG
350
313choice 351choice
314 prompt "Kernel page size" 352 prompt "Kernel page size"
315 default PAGE_SIZE_4KB 353 default PAGE_SIZE_4KB
@@ -394,15 +432,4 @@ config SH_WRITETHROUGH
394 432
395 If unsure, say N. 433 If unsure, say N.
396 434
397config SH_OCRAM
398 bool "Operand Cache RAM (OCRAM) support"
399 help
400 Selecting this option will automatically tear down the number of
401 sets in the dcache by half, which in turn exposes a memory range.
402
403 The addresses for the OC RAM base will vary according to the
404 processor version. Consult vendor documentation for specifics.
405
406 If unsure, say N.
407
408endmenu 435endmenu
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 3ffd7f68c0a2..d677d7f3afc1 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -8,9 +8,6 @@ obj-$(CONFIG_CPU_SH2) += cache-sh2.o
8obj-$(CONFIG_CPU_SH3) += cache-sh3.o 8obj-$(CONFIG_CPU_SH3) += cache-sh3.o
9obj-$(CONFIG_CPU_SH4) += cache-sh4.o 9obj-$(CONFIG_CPU_SH4) += cache-sh4.o
10 10
11obj-$(CONFIG_DMA_PAGE_OPS) += pg-dma.o
12obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
13
14mmu-y := fault-nommu.o tlb-nommu.o pg-nommu.o 11mmu-y := fault-nommu.o tlb-nommu.o pg-nommu.o
15mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush.o \ 12mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush.o \
16 ioremap.o 13 ioremap.o
@@ -27,5 +24,7 @@ obj-$(CONFIG_CPU_SH4) += tlb-sh4.o pg-sh4.o
27obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o 24obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
28endif 25endif
29 26
27obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
30obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o 28obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
31obj-$(CONFIG_32BIT) += pmb.o 29obj-$(CONFIG_32BIT) += pmb.o
30obj-$(CONFIG_NUMA) += numa.o
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index c878faa4ae46..0b3eaf6fbb28 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -32,7 +32,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
32 struct task_struct *tsk; 32 struct task_struct *tsk;
33 struct mm_struct *mm; 33 struct mm_struct *mm;
34 struct vm_area_struct * vma; 34 struct vm_area_struct * vma;
35 unsigned long page;
36 int si_code; 35 int si_code;
37 siginfo_t info; 36 siginfo_t info;
38 37
@@ -170,24 +169,38 @@ no_context:
170 * terminate things with extreme prejudice. 169 * terminate things with extreme prejudice.
171 * 170 *
172 */ 171 */
173 if (address < PAGE_SIZE) 172
174 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); 173 bust_spinlocks(1);
175 else 174
176 printk(KERN_ALERT "Unable to handle kernel paging request"); 175 if (oops_may_print()) {
177 printk(" at virtual address %08lx\n", address); 176 __typeof__(pte_val(__pte(0))) page;
178 printk(KERN_ALERT "pc = %08lx\n", regs->pc); 177
179 page = (unsigned long)get_TTB(); 178 if (address < PAGE_SIZE)
180 if (page) { 179 printk(KERN_ALERT "Unable to handle kernel NULL "
181 page = ((unsigned long *) page)[address >> PGDIR_SHIFT]; 180 "pointer dereference");
182 printk(KERN_ALERT "*pde = %08lx\n", page); 181 else
183 if (page & _PAGE_PRESENT) { 182 printk(KERN_ALERT "Unable to handle kernel paging "
184 page &= PAGE_MASK; 183 "request");
185 address &= 0x003ff000; 184 printk(" at virtual address %08lx\n", address);
186 page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; 185 printk(KERN_ALERT "pc = %08lx\n", regs->pc);
187 printk(KERN_ALERT "*pte = %08lx\n", page); 186 page = (unsigned long)get_TTB();
187 if (page) {
188 page = ((__typeof__(page) *) __va(page))[address >>
189 PGDIR_SHIFT];
190 printk(KERN_ALERT "*pde = %08lx\n", page);
191 if (page & _PAGE_PRESENT) {
192 page &= PAGE_MASK;
193 address &= 0x003ff000;
194 page = ((__typeof__(page) *)
195 __va(page))[address >>
196 PAGE_SHIFT];
197 printk(KERN_ALERT "*pte = %08lx\n", page);
198 }
188 } 199 }
189 } 200 }
201
190 die("Oops", regs, writeaccess); 202 die("Oops", regs, writeaccess);
203 bust_spinlocks(0);
191 do_exit(SIGKILL); 204 do_exit(SIGKILL);
192 205
193/* 206/*
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index e0e644ff3204..82b68c789a5f 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -18,6 +18,7 @@
18#include <asm/mmu_context.h> 18#include <asm/mmu_context.h>
19#include <asm/tlb.h> 19#include <asm/tlb.h>
20#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
21#include <asm/sections.h>
21#include <asm/cache.h> 22#include <asm/cache.h>
22 23
23DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 24DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -36,14 +37,11 @@ void show_mem(void)
36 show_free_areas(); 37 show_free_areas();
37 38
38 for_each_online_pgdat(pgdat) { 39 for_each_online_pgdat(pgdat) {
39 struct page *page, *end; 40 unsigned long flags, i;
40 unsigned long flags;
41 41
42 pgdat_resize_lock(pgdat, &flags); 42 pgdat_resize_lock(pgdat, &flags);
43 page = pgdat->node_mem_map; 43 for (i = 0; i < pgdat->node_spanned_pages; i++) {
44 end = page + pgdat->node_spanned_pages; 44 struct page *page = pgdat_page_nr(pgdat, i);
45
46 do {
47 total++; 45 total++;
48 if (PageReserved(page)) 46 if (PageReserved(page))
49 reserved++; 47 reserved++;
@@ -55,9 +53,7 @@ void show_mem(void)
55 free++; 53 free++;
56 else 54 else
57 shared += page_count(page) - 1; 55 shared += page_count(page) - 1;
58 page++; 56 }
59 } while (page < end);
60
61 pgdat_resize_unlock(pgdat, &flags); 57 pgdat_resize_unlock(pgdat, &flags);
62 } 58 }
63 59
@@ -137,16 +133,12 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
137} 133}
138#endif /* CONFIG_MMU */ 134#endif /* CONFIG_MMU */
139 135
140/* References to section boundaries */
141
142extern char _text, _etext, _edata, __bss_start, _end;
143extern char __init_begin, __init_end;
144
145/* 136/*
146 * paging_init() sets up the page tables 137 * paging_init() sets up the page tables
147 */ 138 */
148void __init paging_init(void) 139void __init paging_init(void)
149{ 140{
141 unsigned long max_zone_pfns[MAX_NR_ZONES];
150 int nid; 142 int nid;
151 143
152 /* We don't need to map the kernel through the TLB, as 144 /* We don't need to map the kernel through the TLB, as
@@ -158,43 +150,39 @@ void __init paging_init(void)
158 * check for a null value. */ 150 * check for a null value. */
159 set_TTB(swapper_pg_dir); 151 set_TTB(swapper_pg_dir);
160 152
153 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
154
161 for_each_online_node(nid) { 155 for_each_online_node(nid) {
162 pg_data_t *pgdat = NODE_DATA(nid); 156 pg_data_t *pgdat = NODE_DATA(nid);
163 unsigned long max_zone_pfns[MAX_NR_ZONES];
164 unsigned long low, start_pfn; 157 unsigned long low, start_pfn;
165 158
166 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
167
168 start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT; 159 start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
169 low = pgdat->bdata->node_low_pfn; 160 low = pgdat->bdata->node_low_pfn;
170 161
171 max_zone_pfns[ZONE_NORMAL] = low; 162 if (max_zone_pfns[ZONE_NORMAL] < low)
172 add_active_range(nid, start_pfn, low); 163 max_zone_pfns[ZONE_NORMAL] = low;
173 164
174 printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n", 165 printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
175 nid, start_pfn, low); 166 nid, start_pfn, low);
176
177 free_area_init_nodes(max_zone_pfns);
178
179 printk("Node %u: mem_map starts at %p\n",
180 pgdat->node_id, pgdat->node_mem_map);
181 } 167 }
168
169 free_area_init_nodes(max_zone_pfns);
182} 170}
183 171
184static struct kcore_list kcore_mem, kcore_vmalloc; 172static struct kcore_list kcore_mem, kcore_vmalloc;
185 173
186void __init mem_init(void) 174void __init mem_init(void)
187{ 175{
188 int codesize, reservedpages, datasize, initsize; 176 int codesize, datasize, initsize;
189 int nid; 177 int nid;
190 178
191 reservedpages = 0; 179 num_physpages = 0;
180 high_memory = NULL;
192 181
193 for_each_online_node(nid) { 182 for_each_online_node(nid) {
194 pg_data_t *pgdat = NODE_DATA(nid); 183 pg_data_t *pgdat = NODE_DATA(nid);
195 unsigned long node_pages = 0; 184 unsigned long node_pages = 0;
196 void *node_high_memory; 185 void *node_high_memory;
197 int i;
198 186
199 num_physpages += pgdat->node_present_pages; 187 num_physpages += pgdat->node_present_pages;
200 188
@@ -203,13 +191,9 @@ void __init mem_init(void)
203 191
204 totalram_pages += node_pages; 192 totalram_pages += node_pages;
205 193
206 for (i = 0; i < node_pages; i++) 194 node_high_memory = (void *)__va((pgdat->node_start_pfn +
207 if (PageReserved(pgdat->node_mem_map + i)) 195 pgdat->node_spanned_pages) <<
208 reservedpages++; 196 PAGE_SHIFT);
209
210 node_high_memory = (void *)((pgdat->node_start_pfn +
211 pgdat->node_spanned_pages) <<
212 PAGE_SHIFT);
213 if (node_high_memory > high_memory) 197 if (node_high_memory > high_memory)
214 high_memory = node_high_memory; 198 high_memory = node_high_memory;
215 } 199 }
@@ -239,11 +223,10 @@ void __init mem_init(void)
239 VMALLOC_END - VMALLOC_START); 223 VMALLOC_END - VMALLOC_START);
240 224
241 printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, " 225 printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
242 "%dk reserved, %dk data, %dk init)\n", 226 "%dk data, %dk init)\n",
243 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), 227 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
244 totalram_pages << (PAGE_SHIFT-10), 228 num_physpages << (PAGE_SHIFT-10),
245 codesize >> 10, 229 codesize >> 10,
246 reservedpages << (PAGE_SHIFT-10),
247 datasize >> 10, 230 datasize >> 10,
248 initsize >> 10); 231 initsize >> 10);
249 232
@@ -264,7 +247,9 @@ void free_initmem(void)
264 free_page(addr); 247 free_page(addr);
265 totalram_pages++; 248 totalram_pages++;
266 } 249 }
267 printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); 250 printk("Freeing unused kernel memory: %ldk freed\n",
251 ((unsigned long)&__init_end -
252 (unsigned long)&__init_begin) >> 10);
268} 253}
269 254
270#ifdef CONFIG_BLK_DEV_INITRD 255#ifdef CONFIG_BLK_DEV_INITRD
@@ -277,6 +262,50 @@ void free_initrd_mem(unsigned long start, unsigned long end)
277 free_page(p); 262 free_page(p);
278 totalram_pages++; 263 totalram_pages++;
279 } 264 }
280 printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); 265 printk("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
266}
267#endif
268
269#ifdef CONFIG_MEMORY_HOTPLUG
270void online_page(struct page *page)
271{
272 ClearPageReserved(page);
273 init_page_count(page);
274 __free_page(page);
275 totalram_pages++;
276 num_physpages++;
281} 277}
278
279int arch_add_memory(int nid, u64 start, u64 size)
280{
281 pg_data_t *pgdat;
282 unsigned long start_pfn = start >> PAGE_SHIFT;
283 unsigned long nr_pages = size >> PAGE_SHIFT;
284 int ret;
285
286 pgdat = NODE_DATA(nid);
287
288 /* We only have ZONE_NORMAL, so this is easy.. */
289 ret = __add_pages(pgdat->node_zones + ZONE_NORMAL, start_pfn, nr_pages);
290 if (unlikely(ret))
291 printk("%s: Failed, __add_pages() == %d\n", __FUNCTION__, ret);
292
293 return ret;
294}
295EXPORT_SYMBOL_GPL(arch_add_memory);
296
297int remove_memory(u64 start, u64 size)
298{
299 return -EINVAL;
300}
301EXPORT_SYMBOL_GPL(remove_memory);
302
303#ifdef CONFIG_NUMA
304int memory_add_physaddr_to_nid(u64 addr)
305{
306 /* Node 0 for now.. */
307 return 0;
308}
309EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
310#endif
282#endif 311#endif
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
new file mode 100644
index 000000000000..8aff065dd307
--- /dev/null
+++ b/arch/sh/mm/numa.c
@@ -0,0 +1,92 @@
1/*
2 * arch/sh/mm/numa.c - Multiple node support for SH machines
3 *
4 * Copyright (C) 2007 Paul Mundt
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#include <linux/module.h>
11#include <linux/bootmem.h>
12#include <linux/mm.h>
13#include <linux/numa.h>
14#include <linux/pfn.h>
15#include <asm/sections.h>
16
17static bootmem_data_t plat_node_bdata[MAX_NUMNODES];
18struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
19EXPORT_SYMBOL_GPL(node_data);
20
21/*
22 * On SH machines the conventional approach is to stash system RAM
23 * in node 0, and other memory blocks in to node 1 and up, ordered by
24 * latency. Each node's pgdat is node-local at the beginning of the node,
25 * immediately followed by the node mem map.
26 */
27void __init setup_memory(void)
28{
29 unsigned long free_pfn = PFN_UP(__pa(_end));
30
31 /*
32 * Node 0 sets up its pgdat at the first available pfn,
33 * and bumps it up before setting up the bootmem allocator.
34 */
35 NODE_DATA(0) = pfn_to_kaddr(free_pfn);
36 memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
37 free_pfn += PFN_UP(sizeof(struct pglist_data));
38 NODE_DATA(0)->bdata = &plat_node_bdata[0];
39
40 /* Set up node 0 */
41 setup_bootmem_allocator(free_pfn);
42
43 /* Give the platforms a chance to hook up their nodes */
44 plat_mem_setup();
45}
46
47void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
48{
49 unsigned long bootmap_pages, bootmap_start, bootmap_size;
50 unsigned long start_pfn, free_pfn, end_pfn;
51
52 /* Don't allow bogus node assignment */
53 BUG_ON(nid > MAX_NUMNODES || nid == 0);
54
55 /*
56 * The free pfn starts at the beginning of the range, and is
57 * advanced as necessary for pgdat and node map allocations.
58 */
59 free_pfn = start_pfn = start >> PAGE_SHIFT;
60 end_pfn = end >> PAGE_SHIFT;
61
62 add_active_range(nid, start_pfn, end_pfn);
63
64 /* Node-local pgdat */
65 NODE_DATA(nid) = pfn_to_kaddr(free_pfn);
66 free_pfn += PFN_UP(sizeof(struct pglist_data));
67 memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
68
69 NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
70 NODE_DATA(nid)->node_start_pfn = start_pfn;
71 NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
72
73 /* Node-local bootmap */
74 bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
75 bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn);
76 bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn,
77 end_pfn);
78
79 free_bootmem_with_active_regions(nid, end_pfn);
80
81 /* Reserve the pgdat and bootmap space with the bootmem allocator */
82 reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
83 sizeof(struct pglist_data));
84 reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT,
85 bootmap_pages << PAGE_SHIFT);
86
87 /* It's up */
88 node_set_online(nid);
89
90 /* Kick sparsemem */
91 sparse_memory_present_with_active_regions(nid);
92}
diff --git a/arch/sh/mm/pg-dma.c b/arch/sh/mm/pg-dma.c
deleted file mode 100644
index bb23679369d6..000000000000
--- a/arch/sh/mm/pg-dma.c
+++ /dev/null
@@ -1,95 +0,0 @@
1/*
2 * arch/sh/mm/pg-dma.c
3 *
4 * Fast clear_page()/copy_page() implementation using the SH DMAC
5 *
6 * Copyright (C) 2003 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <asm/semaphore.h>
16#include <asm/mmu_context.h>
17#include <asm/addrspace.h>
18#include <asm/atomic.h>
19#include <asm/page.h>
20#include <asm/dma.h>
21#include <asm/io.h>
22
23/* Channel to use for page ops, must be dual-address mode capable. */
24static int dma_channel = CONFIG_DMA_PAGE_OPS_CHANNEL;
25
26static void copy_page_dma(void *to, void *from)
27{
28 /*
29 * This doesn't seem to get triggered until further along in the
30 * boot process, at which point the DMAC is already initialized.
31 * Fix this in the same fashion as clear_page_dma() in the event
32 * that this crashes due to the DMAC not being initialized.
33 */
34
35 flush_icache_range((unsigned long)from, PAGE_SIZE);
36 dma_write_page(dma_channel, (unsigned long)from, (unsigned long)to);
37 dma_wait_for_completion(dma_channel);
38}
39
40static void clear_page_dma(void *to)
41{
42 /*
43 * We get invoked quite early on, if the DMAC hasn't been initialized
44 * yet, fall back on the slow manual implementation.
45 */
46 if (dma_info[dma_channel].chan != dma_channel) {
47 clear_page_slow(to);
48 return;
49 }
50
51 dma_write_page(dma_channel, (unsigned long)empty_zero_page,
52 (unsigned long)to);
53
54 /*
55 * FIXME: Something is a bit racy here, if we poll the counter right
56 * away, we seem to lock. flushing the page from the dcache doesn't
57 * seem to make a difference one way or the other, though either a full
58 * icache or dcache flush does.
59 *
60 * The location of this is important as well, and must happen prior to
61 * the completion loop but after the transfer was initiated.
62 *
63 * Oddly enough, this doesn't appear to be an issue for copy_page()..
64 */
65 flush_icache_range((unsigned long)to, PAGE_SIZE);
66
67 dma_wait_for_completion(dma_channel);
68}
69
70static int __init pg_dma_init(void)
71{
72 int ret;
73
74 ret = request_dma(dma_channel, "page ops");
75 if (ret != 0)
76 return ret;
77
78 copy_page = copy_page_dma;
79 clear_page = clear_page_dma;
80
81 return ret;
82}
83
84static void __exit pg_dma_exit(void)
85{
86 free_dma(dma_channel);
87}
88
89module_init(pg_dma_init);
90module_exit(pg_dma_exit);
91
92MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
93MODULE_DESCRIPTION("Optimized page copy/clear routines using a dual-address mode capable DMAC channel");
94MODULE_LICENSE("GPL");
95