Commit 867a89e0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
  [RAPIDIO] Change RapidIO doorbell source and target ID field to 16-bit
  [RAPIDIO] Add RapidIO connection info print out and re-training for broken connections
  [RAPIDIO] Add serial RapidIO controller support, which includes MPC8548, MPC8641
  [RAPIDIO] Add RapidIO node probing into MPC86xx_HPCN board id table
  [RAPIDIO] Add RapidIO node into MPC8641HPCN dts file
  [RAPIDIO] Auto-probe the RapidIO system size
  [RAPIDIO] Add OF-tree support to RapidIO controller driver
  [RAPIDIO] Add RapidIO multi mport support
  [RAPIDIO] Move include/asm-ppc/rio.h to asm-powerpc
  [RAPIDIO] Add RapidIO option to kernel configuration
  [RAPIDIO] Change RIO function mpc85xx_ to fsl_
  [POWERPC] Provide walk_memory_resource() for powerpc
  [POWERPC] Update lmb data structures for hotplug memory add/remove
  [POWERPC] Hotplug memory remove notifications for powerpc
  [POWERPC] windfarm: Add PowerMac 12,1 support
  [POWERPC] Fix building of pmac32 when CONFIG_NVRAM=m
  [POWERPC] Add IRQSTACKS support on ppc32
  [POWERPC] Use __always_inline for xchg* and cmpxchg*
  [POWERPC] Add fast little-endian switch system call
parents 44473d99 6c39103c
......@@ -46,14 +46,13 @@ void lmb_dump_all(void)
#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)));
}
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)
return 1;
......@@ -63,7 +62,7 @@ static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
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)
{
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);
}
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;
......@@ -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 */
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)
{
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;
}
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;
long adjacent, i;
......@@ -182,7 +181,7 @@ static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
return 0;
}
long __init lmb_add(u64 base, u64 size)
long lmb_add(u64 base, u64 size)
{
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)
{
struct lmb_region *_rgn = &lmb.reserved;
......@@ -426,3 +474,36 @@ int __init lmb_is_reserved(u64 addr)
}
return 0;
}
/*
* Given a <base, len>, find which memory regions belong to this range.
* Adjust the request and return a contiguous chunk.
*/
int lmb_find(struct lmb_property *res)
{
int i;
u64 rstart, rend;
rstart = res->base;
rend = rstart + res->size - 1;
for (i = 0; i < lmb.memory.cnt; i++) {
u64 start = lmb.memory.region[i].base;
u64 end = start + lmb.memory.region[i].size - 1;
if (start > rend)
return -1;
if ((end >= rstart) && (start < rend)) {
/* adjust the request */
if (rstart < start)
rstart = start;
if (rend > end)
rend = end;
res->base = rstart;
res->size = rend - rstart + 1;
return 0;
}
}
return -1;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment