aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
authorGerald Schaefer <gerald.schaefer@de.ibm.com>2016-10-18 11:32:18 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-10-24 04:26:17 -0400
commit4a65429457a5d271dd3b00598b3ec75fe8b5103c (patch)
treea9735a2cb0d695fda2e79532519d21e6629e0b7e /arch/s390/mm
parent47ece7fef4e4206cdcee7c28ac3bca3ede0a1908 (diff)
s390/mm: fix zone calculation in arch_add_memory()
Standby (hotplug) memory should be added to ZONE_MOVABLE on s390. After commit 199071f1 "s390/mm: make arch_add_memory() NUMA aware", arch_add_memory() used memblock_end_of_DRAM() to find out the end of ZONE_NORMAL and the beginning of ZONE_MOVABLE. However, commit 7f36e3e5 "memory-hotplug: add hot-added memory ranges to memblock before allocate node_data for a node." moved the call of memblock_add_node() before the call of arch_add_memory() in add_memory_resource(), and thus changed the return value of memblock_end_of_DRAM() when called in arch_add_memory(). As a result, arch_add_memory() will think that all memory blocks should be added to ZONE_NORMAL. Fix this by changing the logic in arch_add_memory() so that it will manually iterate over all zones of a given node to find out which zone a memory block should be added to. Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/init.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index f56a39bd8ba6..b3e9d18f2ec6 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -151,36 +151,40 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
151#ifdef CONFIG_MEMORY_HOTPLUG 151#ifdef CONFIG_MEMORY_HOTPLUG
152int arch_add_memory(int nid, u64 start, u64 size, bool for_device) 152int arch_add_memory(int nid, u64 start, u64 size, bool for_device)
153{ 153{
154 unsigned long normal_end_pfn = PFN_DOWN(memblock_end_of_DRAM()); 154 unsigned long zone_start_pfn, zone_end_pfn, nr_pages;
155 unsigned long dma_end_pfn = PFN_DOWN(MAX_DMA_ADDRESS);
156 unsigned long start_pfn = PFN_DOWN(start); 155 unsigned long start_pfn = PFN_DOWN(start);
157 unsigned long size_pages = PFN_DOWN(size); 156 unsigned long size_pages = PFN_DOWN(size);
158 unsigned long nr_pages; 157 pg_data_t *pgdat = NODE_DATA(nid);
159 int rc, zone_enum; 158 struct zone *zone;
159 int rc, i;
160 160
161 rc = vmem_add_mapping(start, size); 161 rc = vmem_add_mapping(start, size);
162 if (rc) 162 if (rc)
163 return rc; 163 return rc;
164 164
165 while (size_pages > 0) { 165 for (i = 0; i < MAX_NR_ZONES; i++) {
166 if (start_pfn < dma_end_pfn) { 166 zone = pgdat->node_zones + i;
167 nr_pages = (start_pfn + size_pages > dma_end_pfn) ? 167 if (zone_idx(zone) != ZONE_MOVABLE) {
168 dma_end_pfn - start_pfn : size_pages; 168 /* Add range within existing zone limits, if possible */
169 zone_enum = ZONE_DMA; 169 zone_start_pfn = zone->zone_start_pfn;
170 } else if (start_pfn < normal_end_pfn) { 170 zone_end_pfn = zone->zone_start_pfn +
171 nr_pages = (start_pfn + size_pages > normal_end_pfn) ? 171 zone->spanned_pages;
172 normal_end_pfn - start_pfn : size_pages;
173 zone_enum = ZONE_NORMAL;
174 } else { 172 } else {
175 nr_pages = size_pages; 173 /* Add remaining range to ZONE_MOVABLE */
176 zone_enum = ZONE_MOVABLE; 174 zone_start_pfn = start_pfn;
175 zone_end_pfn = start_pfn + size_pages;
177 } 176 }
178 rc = __add_pages(nid, NODE_DATA(nid)->node_zones + zone_enum, 177 if (start_pfn < zone_start_pfn || start_pfn >= zone_end_pfn)
179 start_pfn, size_pages); 178 continue;
179 nr_pages = (start_pfn + size_pages > zone_end_pfn) ?
180 zone_end_pfn - start_pfn : size_pages;
181 rc = __add_pages(nid, zone, start_pfn, nr_pages);
180 if (rc) 182 if (rc)
181 break; 183 break;
182 start_pfn += nr_pages; 184 start_pfn += nr_pages;
183 size_pages -= nr_pages; 185 size_pages -= nr_pages;
186 if (!size_pages)
187 break;
184 } 188 }
185 if (rc) 189 if (rc)
186 vmem_remove_mapping(start, size); 190 vmem_remove_mapping(start, size);