aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-30 21:37:12 -0500
committerPaul Mackerras <paulus@samba.org>2005-10-30 21:37:12 -0500
commit23fd07750a789a66fe88cf173d52a18f1a387da4 (patch)
tree06fdd6df35fdb835abdaa9b754d62f6b84b97250 /arch/powerpc/mm
parentbd787d438a59266af3c9f6351644c85ef1dd21fe (diff)
parented28f96ac1960f30f818374d65be71d2fdf811b0 (diff)
Merge ../linux-2.6 by hand
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/mem.c80
-rw-r--r--arch/powerpc/mm/pgtable_64.c4
2 files changed, 81 insertions, 3 deletions
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index e43e8ef70088..117b00012e14 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -102,6 +102,83 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
102} 102}
103EXPORT_SYMBOL(phys_mem_access_prot); 103EXPORT_SYMBOL(phys_mem_access_prot);
104 104
105#ifdef CONFIG_MEMORY_HOTPLUG
106
107void online_page(struct page *page)
108{
109 ClearPageReserved(page);
110 free_cold_page(page);
111 totalram_pages++;
112 num_physpages++;
113}
114
115/*
116 * This works only for the non-NUMA case. Later, we'll need a lookup
117 * to convert from real physical addresses to nid, that doesn't use
118 * pfn_to_nid().
119 */
120int __devinit add_memory(u64 start, u64 size)
121{
122 struct pglist_data *pgdata = NODE_DATA(0);
123 struct zone *zone;
124 unsigned long start_pfn = start >> PAGE_SHIFT;
125 unsigned long nr_pages = size >> PAGE_SHIFT;
126
127 /* this should work for most non-highmem platforms */
128 zone = pgdata->node_zones;
129
130 return __add_pages(zone, start_pfn, nr_pages);
131
132 return 0;
133}
134
135/*
136 * First pass at this code will check to determine if the remove
137 * request is within the RMO. Do not allow removal within the RMO.
138 */
139int __devinit remove_memory(u64 start, u64 size)
140{
141 struct zone *zone;
142 unsigned long start_pfn, end_pfn, nr_pages;
143
144 start_pfn = start >> PAGE_SHIFT;
145 nr_pages = size >> PAGE_SHIFT;
146 end_pfn = start_pfn + nr_pages;
147
148 printk("%s(): Attempting to remove memoy in range "
149 "%lx to %lx\n", __func__, start, start+size);
150 /*
151 * check for range within RMO
152 */
153 zone = page_zone(pfn_to_page(start_pfn));
154
155 printk("%s(): memory will be removed from "
156 "the %s zone\n", __func__, zone->name);
157
158 /*
159 * not handling removing memory ranges that
160 * overlap multiple zones yet
161 */
162 if (end_pfn > (zone->zone_start_pfn + zone->spanned_pages))
163 goto overlap;
164
165 /* make sure it is NOT in RMO */
166 if ((start < lmb.rmo_size) || ((start+size) < lmb.rmo_size)) {
167 printk("%s(): range to be removed must NOT be in RMO!\n",
168 __func__);
169 goto in_rmo;
170 }
171
172 return __remove_pages(zone, start_pfn, nr_pages);
173
174overlap:
175 printk("%s(): memory range to be removed overlaps "
176 "multiple zones!!!\n", __func__);
177in_rmo:
178 return -1;
179}
180#endif /* CONFIG_MEMORY_HOTPLUG */
181
105void show_mem(void) 182void show_mem(void)
106{ 183{
107 unsigned long total = 0, reserved = 0; 184 unsigned long total = 0, reserved = 0;
@@ -115,6 +192,8 @@ void show_mem(void)
115 show_free_areas(); 192 show_free_areas();
116 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); 193 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
117 for_each_pgdat(pgdat) { 194 for_each_pgdat(pgdat) {
195 unsigned long flags;
196 pgdat_resize_lock(pgdat, &flags);
118 for (i = 0; i < pgdat->node_spanned_pages; i++) { 197 for (i = 0; i < pgdat->node_spanned_pages; i++) {
119 page = pgdat_page_nr(pgdat, i); 198 page = pgdat_page_nr(pgdat, i);
120 total++; 199 total++;
@@ -127,6 +206,7 @@ void show_mem(void)
127 else if (page_count(page)) 206 else if (page_count(page))
128 shared += page_count(page) - 1; 207 shared += page_count(page) - 1;
129 } 208 }
209 pgdat_resize_unlock(pgdat, &flags);
130 } 210 }
131 printk("%ld pages of RAM\n", total); 211 printk("%ld pages of RAM\n", total);
132#ifdef CONFIG_HIGHMEM 212#ifdef CONFIG_HIGHMEM
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 484d24f9208b..b79a78206135 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -104,7 +104,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
104 unsigned long vsid; 104 unsigned long vsid;
105 105
106 if (mem_init_done) { 106 if (mem_init_done) {
107 spin_lock(&init_mm.page_table_lock);
108 pgdp = pgd_offset_k(ea); 107 pgdp = pgd_offset_k(ea);
109 pudp = pud_alloc(&init_mm, pgdp, ea); 108 pudp = pud_alloc(&init_mm, pgdp, ea);
110 if (!pudp) 109 if (!pudp)
@@ -112,12 +111,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
112 pmdp = pmd_alloc(&init_mm, pudp, ea); 111 pmdp = pmd_alloc(&init_mm, pudp, ea);
113 if (!pmdp) 112 if (!pmdp)
114 return -ENOMEM; 113 return -ENOMEM;
115 ptep = pte_alloc_kernel(&init_mm, pmdp, ea); 114 ptep = pte_alloc_kernel(pmdp, ea);
116 if (!ptep) 115 if (!ptep)
117 return -ENOMEM; 116 return -ENOMEM;
118 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, 117 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
119 __pgprot(flags))); 118 __pgprot(flags)));
120 spin_unlock(&init_mm.page_table_lock);
121 } else { 119 } else {
122 unsigned long va, vpn, hash, hpteg; 120 unsigned long va, vpn, hash, hpteg;
123 121