diff options
Diffstat (limited to 'mm/sparse.c')
| -rw-r--r-- | mm/sparse.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/mm/sparse.c b/mm/sparse.c index fac95f2888f2..6b5fb762e2ca 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
| @@ -617,7 +617,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) | |||
| 617 | { | 617 | { |
| 618 | return; /* XXX: Not implemented yet */ | 618 | return; /* XXX: Not implemented yet */ |
| 619 | } | 619 | } |
| 620 | static void free_map_bootmem(struct page *page, unsigned long nr_pages) | 620 | static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) |
| 621 | { | 621 | { |
| 622 | } | 622 | } |
| 623 | #else | 623 | #else |
| @@ -638,7 +638,6 @@ static struct page *__kmalloc_section_memmap(unsigned long nr_pages) | |||
| 638 | got_map_page: | 638 | got_map_page: |
| 639 | ret = (struct page *)pfn_to_kaddr(page_to_pfn(page)); | 639 | ret = (struct page *)pfn_to_kaddr(page_to_pfn(page)); |
| 640 | got_map_ptr: | 640 | got_map_ptr: |
| 641 | memset(ret, 0, memmap_size); | ||
| 642 | 641 | ||
| 643 | return ret; | 642 | return ret; |
| 644 | } | 643 | } |
| @@ -658,10 +657,11 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) | |||
| 658 | get_order(sizeof(struct page) * nr_pages)); | 657 | get_order(sizeof(struct page) * nr_pages)); |
| 659 | } | 658 | } |
| 660 | 659 | ||
| 661 | static void free_map_bootmem(struct page *page, unsigned long nr_pages) | 660 | static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) |
| 662 | { | 661 | { |
| 663 | unsigned long maps_section_nr, removing_section_nr, i; | 662 | unsigned long maps_section_nr, removing_section_nr, i; |
| 664 | unsigned long magic; | 663 | unsigned long magic; |
| 664 | struct page *page = virt_to_page(memmap); | ||
| 665 | 665 | ||
| 666 | for (i = 0; i < nr_pages; i++, page++) { | 666 | for (i = 0; i < nr_pages; i++, page++) { |
| 667 | magic = (unsigned long) page->lru.next; | 667 | magic = (unsigned long) page->lru.next; |
| @@ -710,13 +710,10 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap) | |||
| 710 | */ | 710 | */ |
| 711 | 711 | ||
| 712 | if (memmap) { | 712 | if (memmap) { |
| 713 | struct page *memmap_page; | ||
| 714 | memmap_page = virt_to_page(memmap); | ||
| 715 | |||
| 716 | nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page)) | 713 | nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page)) |
| 717 | >> PAGE_SHIFT; | 714 | >> PAGE_SHIFT; |
| 718 | 715 | ||
| 719 | free_map_bootmem(memmap_page, nr_pages); | 716 | free_map_bootmem(memmap, nr_pages); |
| 720 | } | 717 | } |
| 721 | } | 718 | } |
| 722 | 719 | ||
| @@ -760,6 +757,8 @@ int __meminit sparse_add_one_section(struct zone *zone, unsigned long start_pfn, | |||
| 760 | goto out; | 757 | goto out; |
| 761 | } | 758 | } |
| 762 | 759 | ||
| 760 | memset(memmap, 0, sizeof(struct page) * nr_pages); | ||
| 761 | |||
| 763 | ms->section_mem_map |= SECTION_MARKED_PRESENT; | 762 | ms->section_mem_map |= SECTION_MARKED_PRESENT; |
| 764 | 763 | ||
| 765 | ret = sparse_init_one_section(ms, section_nr, memmap, usemap); | 764 | ret = sparse_init_one_section(ms, section_nr, memmap, usemap); |
| @@ -773,6 +772,27 @@ out: | |||
| 773 | return ret; | 772 | return ret; |
| 774 | } | 773 | } |
| 775 | 774 | ||
| 775 | #ifdef CONFIG_MEMORY_FAILURE | ||
| 776 | static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) | ||
| 777 | { | ||
| 778 | int i; | ||
| 779 | |||
| 780 | if (!memmap) | ||
| 781 | return; | ||
| 782 | |||
| 783 | for (i = 0; i < PAGES_PER_SECTION; i++) { | ||
| 784 | if (PageHWPoison(&memmap[i])) { | ||
| 785 | atomic_long_sub(1, &mce_bad_pages); | ||
| 786 | ClearPageHWPoison(&memmap[i]); | ||
| 787 | } | ||
| 788 | } | ||
| 789 | } | ||
| 790 | #else | ||
| 791 | static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) | ||
| 792 | { | ||
| 793 | } | ||
| 794 | #endif | ||
| 795 | |||
| 776 | void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) | 796 | void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) |
| 777 | { | 797 | { |
| 778 | struct page *memmap = NULL; | 798 | struct page *memmap = NULL; |
| @@ -786,6 +806,7 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) | |||
| 786 | ms->pageblock_flags = NULL; | 806 | ms->pageblock_flags = NULL; |
| 787 | } | 807 | } |
| 788 | 808 | ||
| 809 | clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION); | ||
| 789 | free_section_usemap(memmap, usemap); | 810 | free_section_usemap(memmap, usemap); |
| 790 | } | 811 | } |
| 791 | #endif | 812 | #endif |
