aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2010-10-12 17:07:09 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2010-10-12 18:37:51 -0400
commitc7fc2de0c83dbd2eaf759c5cd0e2b9cf1eb4df3a (patch)
treec4413e9b3bc164394c2daccf34e18e0b1d6c8811 /include
parent8e4029ee3517084ae00fbfbcb51cc365d8857061 (diff)
memblock, bootmem: Round pfn properly for memory and reserved regions
We need to round memory regions correctly -- specifically, we need to round reserved region in the more expansive direction (lower limit down, upper limit up) whereas usable memory regions need to be rounded in the more restrictive direction (lower limit up, upper limit down). This introduces two set of inlines: memblock_region_memory_base_pfn() memblock_region_memory_end_pfn() memblock_region_reserved_base_pfn() memblock_region_reserved_end_pfn() Although they are antisymmetric (and therefore are technically duplicates) the use of the different inlines explicitly documents the programmer's intention. The lack of proper rounding caused a bug on ARM, which was then found to also affect other architectures. Reported-by: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Yinghai Lu <yinghai@kernel.org> LKML-Reference: <4CB4CDFD.4020105@kernel.org> Cc: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/memblock.h25
1 files changed, 12 insertions, 13 deletions
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 5096458c7535..62a10c2a11f2 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -111,40 +111,39 @@ extern void memblock_set_current_limit(phys_addr_t limit);
111 */ 111 */
112 112
113/** 113/**
114 * memblock_region_base_pfn - Return the lowest pfn intersecting with the region 114 * memblock_region_memory_base_pfn - Return the lowest pfn intersecting with the memory region
115 * @reg: memblock_region structure 115 * @reg: memblock_region structure
116 */ 116 */
117static inline unsigned long memblock_region_base_pfn(const struct memblock_region *reg) 117static inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)
118{ 118{
119 return reg->base >> PAGE_SHIFT; 119 return PFN_UP(reg->base);
120} 120}
121 121
122/** 122/**
123 * memblock_region_last_pfn - Return the highest pfn intersecting with the region 123 * memblock_region_memory_end_pfn - Return the end_pfn this region
124 * @reg: memblock_region structure 124 * @reg: memblock_region structure
125 */ 125 */
126static inline unsigned long memblock_region_last_pfn(const struct memblock_region *reg) 126static inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
127{ 127{
128 return (reg->base + reg->size - 1) >> PAGE_SHIFT; 128 return PFN_DOWN(reg->base + reg->size);
129} 129}
130 130
131/** 131/**
132 * memblock_region_end_pfn - Return the pfn of the first page following the region 132 * memblock_region_reserved_base_pfn - Return the lowest pfn intersecting with the reserved region
133 * but not intersecting it
134 * @reg: memblock_region structure 133 * @reg: memblock_region structure
135 */ 134 */
136static inline unsigned long memblock_region_end_pfn(const struct memblock_region *reg) 135static inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
137{ 136{
138 return memblock_region_last_pfn(reg) + 1; 137 return PFN_DOWN(reg->base);
139} 138}
140 139
141/** 140/**
142 * memblock_region_pages - Return the number of pages covering a region 141 * memblock_region_reserved_end_pfn - Return the end_pfn this region
143 * @reg: memblock_region structure 142 * @reg: memblock_region structure
144 */ 143 */
145static inline unsigned long memblock_region_pages(const struct memblock_region *reg) 144static inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)
146{ 145{
147 return memblock_region_end_pfn(reg) - memblock_region_end_pfn(reg); 146 return PFN_UP(reg->base + reg->size);
148} 147}
149 148
150#define for_each_memblock(memblock_type, region) \ 149#define for_each_memblock(memblock_type, region) \