|
@@ -46,14 +46,13 @@ void lmb_dump_all(void)
|
|
#endif /* DEBUG */
|
|
#endif /* DEBUG */
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long __init lmb_addrs_overlap(u64 base1, u64 size1,
|
|
|
|
- u64 base2, u64 size2)
|
|
|
|
|
|
+static unsigned long lmb_addrs_overlap(u64 base1, u64 size1, u64 base2,
|
|
|
|
+ u64 size2)
|
|
{
|
|
{
|
|
return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
|
|
return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
|
|
}
|
|
}
|
|
|
|
|
|
-static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
|
|
|
|
- u64 base2, u64 size2)
|
|
|
|
|
|
+static long lmb_addrs_adjacent(u64 base1, u64 size1, u64 base2, u64 size2)
|
|
{
|
|
{
|
|
if (base2 == base1 + size1)
|
|
if (base2 == base1 + size1)
|
|
return 1;
|
|
return 1;
|
|
@@ -63,7 +62,7 @@ static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static long __init lmb_regions_adjacent(struct lmb_region *rgn,
|
|
|
|
|
|
+static long lmb_regions_adjacent(struct lmb_region *rgn,
|
|
unsigned long r1, unsigned long r2)
|
|
unsigned long r1, unsigned long r2)
|
|
{
|
|
{
|
|
u64 base1 = rgn->region[r1].base;
|
|
u64 base1 = rgn->region[r1].base;
|
|
@@ -74,7 +73,7 @@ static long __init lmb_regions_adjacent(struct lmb_region *rgn,
|
|
return lmb_addrs_adjacent(base1, size1, base2, size2);
|
|
return lmb_addrs_adjacent(base1, size1, base2, size2);
|
|
}
|
|
}
|
|
|
|
|
|
-static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
|
|
|
|
|
|
+static void lmb_remove_region(struct lmb_region *rgn, unsigned long r)
|
|
{
|
|
{
|
|
unsigned long i;
|
|
unsigned long i;
|
|
|
|
|
|
@@ -86,7 +85,7 @@ static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
|
|
}
|
|
}
|
|
|
|
|
|
/* Assumption: base addr of region 1 < base addr of region 2 */
|
|
/* Assumption: base addr of region 1 < base addr of region 2 */
|
|
-static void __init lmb_coalesce_regions(struct lmb_region *rgn,
|
|
|
|
|
|
+static void lmb_coalesce_regions(struct lmb_region *rgn,
|
|
unsigned long r1, unsigned long r2)
|
|
unsigned long r1, unsigned long r2)
|
|
{
|
|
{
|
|
rgn->region[r1].size += rgn->region[r2].size;
|
|
rgn->region[r1].size += rgn->region[r2].size;
|
|
@@ -118,7 +117,7 @@ void __init lmb_analyze(void)
|
|
lmb.memory.size += lmb.memory.region[i].size;
|
|
lmb.memory.size += lmb.memory.region[i].size;
|
|
}
|
|
}
|
|
|
|
|
|
-static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
|
|
|
|
|
|
+static long lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
|
|
{
|
|
{
|
|
unsigned long coalesced = 0;
|
|
unsigned long coalesced = 0;
|
|
long adjacent, i;
|
|
long adjacent, i;
|
|
@@ -182,7 +181,7 @@ static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-long __init lmb_add(u64 base, u64 size)
|
|
|
|
|
|
+long lmb_add(u64 base, u64 size)
|
|
{
|
|
{
|
|
struct lmb_region *_rgn = &lmb.memory;
|
|
struct lmb_region *_rgn = &lmb.memory;
|
|
|
|
|
|
@@ -194,6 +193,55 @@ long __init lmb_add(u64 base, u64 size)
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+long lmb_remove(u64 base, u64 size)
|
|
|
|
+{
|
|
|
|
+ struct lmb_region *rgn = &(lmb.memory);
|
|
|
|
+ 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 __init lmb_reserve(u64 base, u64 size)
|
|
long __init lmb_reserve(u64 base, u64 size)
|
|
{
|
|
{
|
|
struct lmb_region *_rgn = &lmb.reserved;
|
|
struct lmb_region *_rgn = &lmb.reserved;
|