Skip to content
Snippets Groups Projects
Commit 7570a994 authored by Andy Fleming's avatar Andy Fleming Committed by Wolfgang Denk
Browse files

Fix an underflow bug in __lmb_alloc_base


__lmb_alloc_base can underflow if it fails to find free space.  This was fixed
in linux with commit d9024df02ffe74d723d97d552f86de3b34beb8cc.  This patch
merely updates __lmb_alloc_base to resemble the current version in Linux.

Signed-off-by: default avatarAndy Fleming <afleming@freescale.com>
parent 63796c4e
Branches
Tags
No related merge requests found
...@@ -285,11 +285,14 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy ...@@ -285,11 +285,14 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy
{ {
long i, j; long i, j;
phys_addr_t base = 0; phys_addr_t base = 0;
phys_addr_t res_base;
for (i = lmb->memory.cnt-1; i >= 0; i--) { for (i = lmb->memory.cnt-1; i >= 0; i--) {
phys_addr_t lmbbase = lmb->memory.region[i].base; phys_addr_t lmbbase = lmb->memory.region[i].base;
phys_size_t lmbsize = lmb->memory.region[i].size; phys_size_t lmbsize = lmb->memory.region[i].size;
if (lmbsize < size)
continue;
if (max_addr == LMB_ALLOC_ANYWHERE) if (max_addr == LMB_ALLOC_ANYWHERE)
base = lmb_align_down(lmbbase + lmbsize - size, align); base = lmb_align_down(lmbbase + lmbsize - size, align);
else if (lmbbase < max_addr) { else if (lmbbase < max_addr) {
...@@ -298,22 +301,23 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy ...@@ -298,22 +301,23 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy
} else } else
continue; continue;
while ((lmbbase <= base) && while (base && lmbbase <= base) {
((j = lmb_overlaps_region(&(lmb->reserved), base, size)) >= 0) ) j = lmb_overlaps_region(&lmb->reserved, base, size);
base = lmb_align_down(lmb->reserved.region[j].base - size, if (j < 0) {
align); /* This area isn't reserved, take it */
if (lmb_add_region(&lmb->reserved, base,
if ((base != 0) && (lmbbase <= base)) lmb_align_up(size,
align)) < 0)
return 0;
return base;
}
res_base = lmb->reserved.region[j].base;
if (res_base < size)
break; break;
base = lmb_align_down(res_base - size, align);
}
} }
if (i < 0)
return 0;
if (lmb_add_region(&(lmb->reserved), base, lmb_align_up(size, align)) < 0)
return 0; return 0;
return base;
} }
int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr) int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment