summaryrefslogtreecommitdiff
path: root/lib_generic
diff options
context:
space:
mode:
authorAndy Fleming <afleming@freescale.com>2008-06-16 13:58:54 -0500
committerWolfgang Denk <wd@denx.de>2008-06-28 22:21:38 +0200
commit63796c4e61b207d2e635729d41b7a7f7d188b03c (patch)
treeda0c738e9e584b253cf6220348058907450af15c /lib_generic
parent4b03ac8b5102ad95f9fede7d13fa236977593e7d (diff)
Add lmb_free
lmb_free allows us to unreserve some memory so we can use lmb_alloc_base or lmb_reserve to temporarily reserve some memory. Signed-off-by: Andy Fleming <afleming@freescale.com>
Diffstat (limited to 'lib_generic')
-rw-r--r--lib_generic/lmb.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib_generic/lmb.c b/lib_generic/lmb.c
index afe33197de..3240f66bf9 100644
--- a/lib_generic/lmb.c
+++ b/lib_generic/lmb.c
@@ -181,6 +181,55 @@ long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size)
return lmb_add_region(_rgn, base, size);
}
+long lmb_free(struct lmb *lmb, u64 base, u64 size)
+{
+ struct lmb_region *rgn = &(lmb->reserved);
+ u64 rgnbegin, rgnend;
+ u64 end = base + size;
+ int i;
+
+ rgnbegin = rgnend = 0; /* supress gcc warnings */
+
+ /* Find the region where (base, size) belongs to */
+ for (i=0; i < rgn->cnt; i++) {
+ rgnbegin = rgn->region[i].base;
+ rgnend = rgnbegin + rgn->region[i].size;
+
+ if ((rgnbegin <= base) && (end <= rgnend))
+ break;
+ }
+
+ /* Didn't find the region */
+ if (i == rgn->cnt)
+ return -1;
+
+ /* Check to see if we are removing entire region */
+ if ((rgnbegin == base) && (rgnend == end)) {
+ lmb_remove_region(rgn, i);
+ return 0;
+ }
+
+ /* Check to see if region is matching at the front */
+ if (rgnbegin == base) {
+ rgn->region[i].base = end;
+ rgn->region[i].size -= size;
+ return 0;
+ }
+
+ /* Check to see if the region is matching at the end */
+ if (rgnend == end) {
+ rgn->region[i].size -= size;
+ return 0;
+ }
+
+ /*
+ * We need to split the entry - adjust the current one to the
+ * beginging of the hole and add the region after hole.
+ */
+ rgn->region[i].size = base - rgn->region[i].base;
+ return lmb_add_region(rgn, end, rgnend - end);
+}
+
long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size)
{
struct lmb_region *_rgn = &(lmb->reserved);