diff options
Diffstat (limited to 'lib/lmb.c')
-rw-r--r-- | lib/lmb.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/lmb.c b/lib/lmb.c index 93fc1bea07c..32c787f8adf 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -561,6 +561,39 @@ static __maybe_unused void lmb_reserve_common_spl(void) } } +/** + * lmb_can_reserve_region() - check if the region can be reserved + * @base: base address of region to be reserved + * @size: size of region to be reserved + * @flags: flag of the region to be reserved + * + * Go through all the reserved regions and ensure that the requested + * region does not overlap with any existing regions. An overlap is + * allowed only when the flag of the request region and the existing + * region is LMB_NONE. + * + * Return: true if region can be reserved, false otherwise + */ +static bool lmb_can_reserve_region(phys_addr_t base, phys_size_t size, + u32 flags) +{ + uint i; + struct lmb_region *lmb_reserved = lmb.used_mem.data; + + for (i = 0; i < lmb.used_mem.count; i++) { + u32 rgnflags = lmb_reserved[i].flags; + phys_addr_t rgnbase = lmb_reserved[i].base; + phys_size_t rgnsize = lmb_reserved[i].size; + + if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) { + if (flags != LMB_NONE || flags != rgnflags) + return false; + } + } + + return true; +} + void lmb_add_memory(void) { int i; @@ -633,6 +666,9 @@ long lmb_reserve(phys_addr_t base, phys_size_t size, u32 flags) long ret = 0; struct alist *lmb_rgn_lst = &lmb.used_mem; + if (!lmb_can_reserve_region(base, size, flags)) + return -EEXIST; + ret = lmb_add_region_flags(lmb_rgn_lst, base, size, flags); if (ret) return ret; |