Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 94792
b: refs/heads/master
c: 98d5c21
h: refs/heads/master
v: v3
  • Loading branch information
Badari Pulavarty authored and Paul Mackerras committed Apr 29, 2008
1 parent 1cd7ca4 commit 7491d49
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 57b539269e9eef4dedc533d83c94877bc6b4d44d
refs/heads/master: 98d5c21c812e4e3b795f5bd912f407ed7c5e4e38
43 changes: 43 additions & 0 deletions trunk/arch/powerpc/platforms/pseries/hotplug-memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*/

#include <linux/of.h>
#include <linux/lmb.h>
#include <asm/firmware.h>
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
Expand Down Expand Up @@ -57,6 +58,11 @@ static int pseries_remove_memory(struct device_node *np)
if (ret)
return ret;

/*
* Update memory regions for memory remove
*/
lmb_remove(start_pfn << PAGE_SHIFT, regs[3]);

/*
* Remove htab bolted mappings for this section of memory
*/
Expand All @@ -65,13 +71,50 @@ static int pseries_remove_memory(struct device_node *np)
return ret;
}

static int pseries_add_memory(struct device_node *np)
{
const char *type;
const unsigned int *my_index;
const unsigned int *regs;
u64 start_pfn;
int ret = -EINVAL;

/*
* Check to see if we are actually adding memory
*/
type = of_get_property(np, "device_type", NULL);
if (type == NULL || strcmp(type, "memory") != 0)
return 0;

/*
* Find the memory index and size of the added section
*/
my_index = of_get_property(np, "ibm,my-drc-index", NULL);
if (!my_index)
return ret;

regs = of_get_property(np, "reg", NULL);
if (!regs)
return ret;

start_pfn = section_nr_to_pfn(*my_index & 0xffff);

/*
* Update memory region to represent the memory add
*/
lmb_add(start_pfn << PAGE_SHIFT, regs[3]);
return 0;
}

static int pseries_memory_notifier(struct notifier_block *nb,
unsigned long action, void *node)
{
int err = NOTIFY_OK;

switch (action) {
case PSERIES_RECONFIG_ADD:
if (pseries_add_memory(node))
err = NOTIFY_BAD;
break;
case PSERIES_RECONFIG_REMOVE:
if (pseries_remove_memory(node))
Expand Down
3 changes: 2 additions & 1 deletion trunk/include/linux/lmb.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ extern struct lmb lmb;

extern void __init lmb_init(void);
extern void __init lmb_analyze(void);
extern long __init lmb_add(u64 base, u64 size);
extern long lmb_add(u64 base, u64 size);
extern long lmb_remove(u64 base, u64 size);
extern long __init lmb_reserve(u64 base, u64 size);
extern u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
u64 (*nid_range)(u64, u64, int *));
Expand Down
66 changes: 57 additions & 9 deletions trunk/lib/lmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down

0 comments on commit 7491d49

Please sign in to comment.