diff options
Diffstat (limited to 'mm/memory_hotplug.c')
-rw-r--r-- | mm/memory_hotplug.c | 39 |
1 files changed, 18 insertions, 21 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 9bbd6982d4e4..b2bd52ff7605 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -247,7 +247,7 @@ void __init register_page_bootmem_info_node(struct pglist_data *pgdat) | |||
247 | #endif /* CONFIG_HAVE_BOOTMEM_INFO_NODE */ | 247 | #endif /* CONFIG_HAVE_BOOTMEM_INFO_NODE */ |
248 | 248 | ||
249 | static int __meminit __add_section(int nid, unsigned long phys_start_pfn, | 249 | static int __meminit __add_section(int nid, unsigned long phys_start_pfn, |
250 | bool want_memblock) | 250 | struct vmem_altmap *altmap, bool want_memblock) |
251 | { | 251 | { |
252 | int ret; | 252 | int ret; |
253 | int i; | 253 | int i; |
@@ -255,7 +255,7 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn, | |||
255 | if (pfn_valid(phys_start_pfn)) | 255 | if (pfn_valid(phys_start_pfn)) |
256 | return -EEXIST; | 256 | return -EEXIST; |
257 | 257 | ||
258 | ret = sparse_add_one_section(NODE_DATA(nid), phys_start_pfn); | 258 | ret = sparse_add_one_section(NODE_DATA(nid), phys_start_pfn, altmap); |
259 | if (ret < 0) | 259 | if (ret < 0) |
260 | return ret; | 260 | return ret; |
261 | 261 | ||
@@ -289,18 +289,17 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn, | |||
289 | * add the new pages. | 289 | * add the new pages. |
290 | */ | 290 | */ |
291 | int __ref __add_pages(int nid, unsigned long phys_start_pfn, | 291 | int __ref __add_pages(int nid, unsigned long phys_start_pfn, |
292 | unsigned long nr_pages, bool want_memblock) | 292 | unsigned long nr_pages, struct vmem_altmap *altmap, |
293 | bool want_memblock) | ||
293 | { | 294 | { |
294 | unsigned long i; | 295 | unsigned long i; |
295 | int err = 0; | 296 | int err = 0; |
296 | int start_sec, end_sec; | 297 | int start_sec, end_sec; |
297 | struct vmem_altmap *altmap; | ||
298 | 298 | ||
299 | /* during initialize mem_map, align hot-added range to section */ | 299 | /* during initialize mem_map, align hot-added range to section */ |
300 | start_sec = pfn_to_section_nr(phys_start_pfn); | 300 | start_sec = pfn_to_section_nr(phys_start_pfn); |
301 | end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1); | 301 | end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1); |
302 | 302 | ||
303 | altmap = to_vmem_altmap((unsigned long) pfn_to_page(phys_start_pfn)); | ||
304 | if (altmap) { | 303 | if (altmap) { |
305 | /* | 304 | /* |
306 | * Validate altmap is within bounds of the total request | 305 | * Validate altmap is within bounds of the total request |
@@ -315,7 +314,8 @@ int __ref __add_pages(int nid, unsigned long phys_start_pfn, | |||
315 | } | 314 | } |
316 | 315 | ||
317 | for (i = start_sec; i <= end_sec; i++) { | 316 | for (i = start_sec; i <= end_sec; i++) { |
318 | err = __add_section(nid, section_nr_to_pfn(i), want_memblock); | 317 | err = __add_section(nid, section_nr_to_pfn(i), altmap, |
318 | want_memblock); | ||
319 | 319 | ||
320 | /* | 320 | /* |
321 | * EEXIST is finally dealt with by ioresource collision | 321 | * EEXIST is finally dealt with by ioresource collision |
@@ -331,7 +331,6 @@ int __ref __add_pages(int nid, unsigned long phys_start_pfn, | |||
331 | out: | 331 | out: |
332 | return err; | 332 | return err; |
333 | } | 333 | } |
334 | EXPORT_SYMBOL_GPL(__add_pages); | ||
335 | 334 | ||
336 | #ifdef CONFIG_MEMORY_HOTREMOVE | 335 | #ifdef CONFIG_MEMORY_HOTREMOVE |
337 | /* find the smallest valid pfn in the range [start_pfn, end_pfn) */ | 336 | /* find the smallest valid pfn in the range [start_pfn, end_pfn) */ |
@@ -534,7 +533,7 @@ static void __remove_zone(struct zone *zone, unsigned long start_pfn) | |||
534 | } | 533 | } |
535 | 534 | ||
536 | static int __remove_section(struct zone *zone, struct mem_section *ms, | 535 | static int __remove_section(struct zone *zone, struct mem_section *ms, |
537 | unsigned long map_offset) | 536 | unsigned long map_offset, struct vmem_altmap *altmap) |
538 | { | 537 | { |
539 | unsigned long start_pfn; | 538 | unsigned long start_pfn; |
540 | int scn_nr; | 539 | int scn_nr; |
@@ -551,7 +550,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms, | |||
551 | start_pfn = section_nr_to_pfn((unsigned long)scn_nr); | 550 | start_pfn = section_nr_to_pfn((unsigned long)scn_nr); |
552 | __remove_zone(zone, start_pfn); | 551 | __remove_zone(zone, start_pfn); |
553 | 552 | ||
554 | sparse_remove_one_section(zone, ms, map_offset); | 553 | sparse_remove_one_section(zone, ms, map_offset, altmap); |
555 | return 0; | 554 | return 0; |
556 | } | 555 | } |
557 | 556 | ||
@@ -567,7 +566,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms, | |||
567 | * calling offline_pages(). | 566 | * calling offline_pages(). |
568 | */ | 567 | */ |
569 | int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, | 568 | int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, |
570 | unsigned long nr_pages) | 569 | unsigned long nr_pages, struct vmem_altmap *altmap) |
571 | { | 570 | { |
572 | unsigned long i; | 571 | unsigned long i; |
573 | unsigned long map_offset = 0; | 572 | unsigned long map_offset = 0; |
@@ -575,10 +574,6 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, | |||
575 | 574 | ||
576 | /* In the ZONE_DEVICE case device driver owns the memory region */ | 575 | /* In the ZONE_DEVICE case device driver owns the memory region */ |
577 | if (is_dev_zone(zone)) { | 576 | if (is_dev_zone(zone)) { |
578 | struct page *page = pfn_to_page(phys_start_pfn); | ||
579 | struct vmem_altmap *altmap; | ||
580 | |||
581 | altmap = to_vmem_altmap((unsigned long) page); | ||
582 | if (altmap) | 577 | if (altmap) |
583 | map_offset = vmem_altmap_offset(altmap); | 578 | map_offset = vmem_altmap_offset(altmap); |
584 | } else { | 579 | } else { |
@@ -609,7 +604,8 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, | |||
609 | for (i = 0; i < sections_to_remove; i++) { | 604 | for (i = 0; i < sections_to_remove; i++) { |
610 | unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION; | 605 | unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION; |
611 | 606 | ||
612 | ret = __remove_section(zone, __pfn_to_section(pfn), map_offset); | 607 | ret = __remove_section(zone, __pfn_to_section(pfn), map_offset, |
608 | altmap); | ||
613 | map_offset = 0; | 609 | map_offset = 0; |
614 | if (ret) | 610 | if (ret) |
615 | break; | 611 | break; |
@@ -799,8 +795,8 @@ static void __meminit resize_pgdat_range(struct pglist_data *pgdat, unsigned lon | |||
799 | pgdat->node_spanned_pages = max(start_pfn + nr_pages, old_end_pfn) - pgdat->node_start_pfn; | 795 | pgdat->node_spanned_pages = max(start_pfn + nr_pages, old_end_pfn) - pgdat->node_start_pfn; |
800 | } | 796 | } |
801 | 797 | ||
802 | void __ref move_pfn_range_to_zone(struct zone *zone, | 798 | void __ref move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn, |
803 | unsigned long start_pfn, unsigned long nr_pages) | 799 | unsigned long nr_pages, struct vmem_altmap *altmap) |
804 | { | 800 | { |
805 | struct pglist_data *pgdat = zone->zone_pgdat; | 801 | struct pglist_data *pgdat = zone->zone_pgdat; |
806 | int nid = pgdat->node_id; | 802 | int nid = pgdat->node_id; |
@@ -825,7 +821,8 @@ void __ref move_pfn_range_to_zone(struct zone *zone, | |||
825 | * expects the zone spans the pfn range. All the pages in the range | 821 | * expects the zone spans the pfn range. All the pages in the range |
826 | * are reserved so nobody should be touching them so we should be safe | 822 | * are reserved so nobody should be touching them so we should be safe |
827 | */ | 823 | */ |
828 | memmap_init_zone(nr_pages, nid, zone_idx(zone), start_pfn, MEMMAP_HOTPLUG); | 824 | memmap_init_zone(nr_pages, nid, zone_idx(zone), start_pfn, |
825 | MEMMAP_HOTPLUG, altmap); | ||
829 | 826 | ||
830 | set_zone_contiguous(zone); | 827 | set_zone_contiguous(zone); |
831 | } | 828 | } |
@@ -897,7 +894,7 @@ static struct zone * __meminit move_pfn_range(int online_type, int nid, | |||
897 | struct zone *zone; | 894 | struct zone *zone; |
898 | 895 | ||
899 | zone = zone_for_pfn_range(online_type, nid, start_pfn, nr_pages); | 896 | zone = zone_for_pfn_range(online_type, nid, start_pfn, nr_pages); |
900 | move_pfn_range_to_zone(zone, start_pfn, nr_pages); | 897 | move_pfn_range_to_zone(zone, start_pfn, nr_pages, NULL); |
901 | return zone; | 898 | return zone; |
902 | } | 899 | } |
903 | 900 | ||
@@ -1146,7 +1143,7 @@ int __ref add_memory_resource(int nid, struct resource *res, bool online) | |||
1146 | } | 1143 | } |
1147 | 1144 | ||
1148 | /* call arch's memory hotadd */ | 1145 | /* call arch's memory hotadd */ |
1149 | ret = arch_add_memory(nid, start, size, true); | 1146 | ret = arch_add_memory(nid, start, size, NULL, true); |
1150 | 1147 | ||
1151 | if (ret < 0) | 1148 | if (ret < 0) |
1152 | goto error; | 1149 | goto error; |
@@ -1888,7 +1885,7 @@ void __ref remove_memory(int nid, u64 start, u64 size) | |||
1888 | memblock_free(start, size); | 1885 | memblock_free(start, size); |
1889 | memblock_remove(start, size); | 1886 | memblock_remove(start, size); |
1890 | 1887 | ||
1891 | arch_remove_memory(start, size); | 1888 | arch_remove_memory(start, size, NULL); |
1892 | 1889 | ||
1893 | try_offline_node(nid); | 1890 | try_offline_node(nid); |
1894 | 1891 | ||