diff options
-rw-r--r-- | include/linux/memblock.h | 17 | ||||
-rw-r--r-- | mm/memblock.c | 53 |
2 files changed, 70 insertions, 0 deletions
diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 9a805ec6e794..b788faa71563 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h | |||
@@ -19,6 +19,9 @@ | |||
19 | 19 | ||
20 | #define INIT_MEMBLOCK_REGIONS 128 | 20 | #define INIT_MEMBLOCK_REGIONS 128 |
21 | 21 | ||
22 | /* Definition of memblock flags. */ | ||
23 | #define MEMBLOCK_HOTPLUG 0x1 /* hotpluggable region */ | ||
24 | |||
22 | struct memblock_region { | 25 | struct memblock_region { |
23 | phys_addr_t base; | 26 | phys_addr_t base; |
24 | phys_addr_t size; | 27 | phys_addr_t size; |
@@ -60,6 +63,8 @@ int memblock_remove(phys_addr_t base, phys_addr_t size); | |||
60 | int memblock_free(phys_addr_t base, phys_addr_t size); | 63 | int memblock_free(phys_addr_t base, phys_addr_t size); |
61 | int memblock_reserve(phys_addr_t base, phys_addr_t size); | 64 | int memblock_reserve(phys_addr_t base, phys_addr_t size); |
62 | void memblock_trim_memory(phys_addr_t align); | 65 | void memblock_trim_memory(phys_addr_t align); |
66 | int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size); | ||
67 | int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size); | ||
63 | 68 | ||
64 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 69 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
65 | int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn, | 70 | int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn, |
@@ -122,6 +127,18 @@ void __next_free_mem_range_rev(u64 *idx, int nid, phys_addr_t *out_start, | |||
122 | i != (u64)ULLONG_MAX; \ | 127 | i != (u64)ULLONG_MAX; \ |
123 | __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid)) | 128 | __next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid)) |
124 | 129 | ||
130 | static inline void memblock_set_region_flags(struct memblock_region *r, | ||
131 | unsigned long flags) | ||
132 | { | ||
133 | r->flags |= flags; | ||
134 | } | ||
135 | |||
136 | static inline void memblock_clear_region_flags(struct memblock_region *r, | ||
137 | unsigned long flags) | ||
138 | { | ||
139 | r->flags &= ~flags; | ||
140 | } | ||
141 | |||
125 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 142 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
126 | int memblock_set_node(phys_addr_t base, phys_addr_t size, int nid); | 143 | int memblock_set_node(phys_addr_t base, phys_addr_t size, int nid); |
127 | 144 | ||
diff --git a/mm/memblock.c b/mm/memblock.c index 270b005ca964..2121ec4c7fa0 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
@@ -683,6 +683,59 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) | |||
683 | } | 683 | } |
684 | 684 | ||
685 | /** | 685 | /** |
686 | * memblock_mark_hotplug - Mark hotpluggable memory with flag MEMBLOCK_HOTPLUG. | ||
687 | * @base: the base phys addr of the region | ||
688 | * @size: the size of the region | ||
689 | * | ||
690 | * This function isolates region [@base, @base + @size), and mark it with flag | ||
691 | * MEMBLOCK_HOTPLUG. | ||
692 | * | ||
693 | * Return 0 on succees, -errno on failure. | ||
694 | */ | ||
695 | int __init_memblock memblock_mark_hotplug(phys_addr_t base, phys_addr_t size) | ||
696 | { | ||
697 | struct memblock_type *type = &memblock.memory; | ||
698 | int i, ret, start_rgn, end_rgn; | ||
699 | |||
700 | ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn); | ||
701 | if (ret) | ||
702 | return ret; | ||
703 | |||
704 | for (i = start_rgn; i < end_rgn; i++) | ||
705 | memblock_set_region_flags(&type->regions[i], MEMBLOCK_HOTPLUG); | ||
706 | |||
707 | memblock_merge_regions(type); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | /** | ||
712 | * memblock_clear_hotplug - Clear flag MEMBLOCK_HOTPLUG for a specified region. | ||
713 | * @base: the base phys addr of the region | ||
714 | * @size: the size of the region | ||
715 | * | ||
716 | * This function isolates region [@base, @base + @size), and clear flag | ||
717 | * MEMBLOCK_HOTPLUG for the isolated regions. | ||
718 | * | ||
719 | * Return 0 on succees, -errno on failure. | ||
720 | */ | ||
721 | int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size) | ||
722 | { | ||
723 | struct memblock_type *type = &memblock.memory; | ||
724 | int i, ret, start_rgn, end_rgn; | ||
725 | |||
726 | ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn); | ||
727 | if (ret) | ||
728 | return ret; | ||
729 | |||
730 | for (i = start_rgn; i < end_rgn; i++) | ||
731 | memblock_clear_region_flags(&type->regions[i], | ||
732 | MEMBLOCK_HOTPLUG); | ||
733 | |||
734 | memblock_merge_regions(type); | ||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | /** | ||
686 | * __next_free_mem_range - next function for for_each_free_mem_range() | 739 | * __next_free_mem_range - next function for for_each_free_mem_range() |
687 | * @idx: pointer to u64 loop variable | 740 | * @idx: pointer to u64 loop variable |
688 | * @nid: node selector, %MAX_NUMNODES for all nodes | 741 | * @nid: node selector, %MAX_NUMNODES for all nodes |