aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm/init.c')
-rw-r--r--arch/s390/mm/init.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 5d633019d8f3..50236610de83 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -223,16 +223,38 @@ void free_initrd_mem(unsigned long start, unsigned long end)
223#ifdef CONFIG_MEMORY_HOTPLUG 223#ifdef CONFIG_MEMORY_HOTPLUG
224int arch_add_memory(int nid, u64 start, u64 size) 224int arch_add_memory(int nid, u64 start, u64 size)
225{ 225{
226 struct pglist_data *pgdat; 226 unsigned long zone_start_pfn, zone_end_pfn, nr_pages;
227 unsigned long start_pfn = PFN_DOWN(start);
228 unsigned long size_pages = PFN_DOWN(size);
227 struct zone *zone; 229 struct zone *zone;
228 int rc; 230 int rc;
229 231
230 pgdat = NODE_DATA(nid);
231 zone = pgdat->node_zones + ZONE_MOVABLE;
232 rc = vmem_add_mapping(start, size); 232 rc = vmem_add_mapping(start, size);
233 if (rc) 233 if (rc)
234 return rc; 234 return rc;
235 rc = __add_pages(nid, zone, PFN_DOWN(start), PFN_DOWN(size)); 235 for_each_zone(zone) {
236 if (zone_idx(zone) != ZONE_MOVABLE) {
237 /* Add range within existing zone limits */
238 zone_start_pfn = zone->zone_start_pfn;
239 zone_end_pfn = zone->zone_start_pfn +
240 zone->spanned_pages;
241 } else {
242 /* Add remaining range to ZONE_MOVABLE */
243 zone_start_pfn = start_pfn;
244 zone_end_pfn = start_pfn + size_pages;
245 }
246 if (start_pfn < zone_start_pfn || start_pfn >= zone_end_pfn)
247 continue;
248 nr_pages = (start_pfn + size_pages > zone_end_pfn) ?
249 zone_end_pfn - start_pfn : size_pages;
250 rc = __add_pages(nid, zone, start_pfn, nr_pages);
251 if (rc)
252 break;
253 start_pfn += nr_pages;
254 size_pages -= nr_pages;
255 if (!size_pages)
256 break;
257 }
236 if (rc) 258 if (rc)
237 vmem_remove_mapping(start, size); 259 vmem_remove_mapping(start, size);
238 return rc; 260 return rc;