diff options
author | Dave Hansen <haveblue@us.ibm.com> | 2005-10-29 21:16:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 00:40:45 -0400 |
commit | bb7e7e032d2cb8e0e9a88a2be209de5e61033b39 (patch) | |
tree | 90cf33b97fed90f21b6f896198f8fdece695bbde | |
parent | 05039b926374212b2d861860cf54b9e839d4dd76 (diff) |
[PATCH] memory hotplug: ppc64 specific hot-add functions
Here is a set of ppc64 specific patches that at least allow
compilation/booting with the following configurations:
FLATMEM
SPARSEMEN
SPARSEMEM + MEMORY_HOTPLUG
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/ppc64/mm/init.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c index 975b26de34d6..e2bd7776622f 100644 --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c | |||
@@ -871,3 +871,80 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | |||
871 | return vma_prot; | 871 | return vma_prot; |
872 | } | 872 | } |
873 | EXPORT_SYMBOL(phys_mem_access_prot); | 873 | EXPORT_SYMBOL(phys_mem_access_prot); |
874 | |||
875 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
876 | |||
877 | void online_page(struct page *page) | ||
878 | { | ||
879 | ClearPageReserved(page); | ||
880 | free_cold_page(page); | ||
881 | totalram_pages++; | ||
882 | num_physpages++; | ||
883 | } | ||
884 | |||
885 | /* | ||
886 | * This works only for the non-NUMA case. Later, we'll need a lookup | ||
887 | * to convert from real physical addresses to nid, that doesn't use | ||
888 | * pfn_to_nid(). | ||
889 | */ | ||
890 | int __devinit add_memory(u64 start, u64 size) | ||
891 | { | ||
892 | struct pglist_data *pgdata = NODE_DATA(0); | ||
893 | struct zone *zone; | ||
894 | unsigned long start_pfn = start >> PAGE_SHIFT; | ||
895 | unsigned long nr_pages = size >> PAGE_SHIFT; | ||
896 | |||
897 | /* this should work for most non-highmem platforms */ | ||
898 | zone = pgdata->node_zones; | ||
899 | |||
900 | return __add_pages(zone, start_pfn, nr_pages); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | /* | ||
906 | * First pass at this code will check to determine if the remove | ||
907 | * request is within the RMO. Do not allow removal within the RMO. | ||
908 | */ | ||
909 | int __devinit remove_memory(u64 start, u64 size) | ||
910 | { | ||
911 | struct zone *zone; | ||
912 | unsigned long start_pfn, end_pfn, nr_pages; | ||
913 | |||
914 | start_pfn = start >> PAGE_SHIFT; | ||
915 | nr_pages = size >> PAGE_SHIFT; | ||
916 | end_pfn = start_pfn + nr_pages; | ||
917 | |||
918 | printk("%s(): Attempting to remove memoy in range " | ||
919 | "%lx to %lx\n", __func__, start, start+size); | ||
920 | /* | ||
921 | * check for range within RMO | ||
922 | */ | ||
923 | zone = page_zone(pfn_to_page(start_pfn)); | ||
924 | |||
925 | printk("%s(): memory will be removed from " | ||
926 | "the %s zone\n", __func__, zone->name); | ||
927 | |||
928 | /* | ||
929 | * not handling removing memory ranges that | ||
930 | * overlap multiple zones yet | ||
931 | */ | ||
932 | if (end_pfn > (zone->zone_start_pfn + zone->spanned_pages)) | ||
933 | goto overlap; | ||
934 | |||
935 | /* make sure it is NOT in RMO */ | ||
936 | if ((start < lmb.rmo_size) || ((start+size) < lmb.rmo_size)) { | ||
937 | printk("%s(): range to be removed must NOT be in RMO!\n", | ||
938 | __func__); | ||
939 | goto in_rmo; | ||
940 | } | ||
941 | |||
942 | return __remove_pages(zone, start_pfn, nr_pages); | ||
943 | |||
944 | overlap: | ||
945 | printk("%s(): memory range to be removed overlaps " | ||
946 | "multiple zones!!!\n", __func__); | ||
947 | in_rmo: | ||
948 | return -1; | ||
949 | } | ||
950 | #endif /* CONFIG_MEMORY_HOTPLUG */ | ||