diff options
Diffstat (limited to 'mm/cma.c')
-rw-r--r-- | mm/cma.c | 21 |
1 files changed, 21 insertions, 0 deletions
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/log2.h> | 33 | #include <linux/log2.h> |
34 | #include <linux/cma.h> | 34 | #include <linux/cma.h> |
35 | #include <linux/highmem.h> | ||
35 | 36 | ||
36 | struct cma { | 37 | struct cma { |
37 | unsigned long base_pfn; | 38 | unsigned long base_pfn; |
@@ -163,6 +164,8 @@ int __init cma_declare_contiguous(phys_addr_t base, | |||
163 | bool fixed, struct cma **res_cma) | 164 | bool fixed, struct cma **res_cma) |
164 | { | 165 | { |
165 | struct cma *cma; | 166 | struct cma *cma; |
167 | phys_addr_t memblock_end = memblock_end_of_DRAM(); | ||
168 | phys_addr_t highmem_start = __pa(high_memory); | ||
166 | int ret = 0; | 169 | int ret = 0; |
167 | 170 | ||
168 | pr_debug("%s(size %lx, base %08lx, limit %08lx alignment %08lx)\n", | 171 | pr_debug("%s(size %lx, base %08lx, limit %08lx alignment %08lx)\n", |
@@ -196,6 +199,24 @@ int __init cma_declare_contiguous(phys_addr_t base, | |||
196 | if (!IS_ALIGNED(size >> PAGE_SHIFT, 1 << order_per_bit)) | 199 | if (!IS_ALIGNED(size >> PAGE_SHIFT, 1 << order_per_bit)) |
197 | return -EINVAL; | 200 | return -EINVAL; |
198 | 201 | ||
202 | /* | ||
203 | * adjust limit to avoid crossing low/high memory boundary for | ||
204 | * automatically allocated regions | ||
205 | */ | ||
206 | if (((limit == 0 || limit > memblock_end) && | ||
207 | (memblock_end - size < highmem_start && | ||
208 | memblock_end > highmem_start)) || | ||
209 | (!fixed && limit > highmem_start && limit - size < highmem_start)) { | ||
210 | limit = highmem_start; | ||
211 | } | ||
212 | |||
213 | if (fixed && base < highmem_start && base+size > highmem_start) { | ||
214 | ret = -EINVAL; | ||
215 | pr_err("Region at %08lx defined on low/high memory boundary (%08lx)\n", | ||
216 | (unsigned long)base, (unsigned long)highmem_start); | ||
217 | goto err; | ||
218 | } | ||
219 | |||
199 | /* Reserve memory */ | 220 | /* Reserve memory */ |
200 | if (base && fixed) { | 221 | if (base && fixed) { |
201 | if (memblock_is_region_reserved(base, size) || | 222 | if (memblock_is_region_reserved(base, size) || |