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 |