aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/arch/powerpc/platforms/pseries/hotplug-memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/hotplug-memory.c')
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c126
1 files changed, 28 insertions, 98 deletions
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 2e3a317722a8..3fe3ddb30c04 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -21,54 +21,6 @@
#include <asm/drmem.h>
#include "pseries.h"
-unsigned long pseries_memory_block_size(void)
-{
- struct device_node *np;
- u64 memblock_size = MIN_MEMORY_BLOCK_SIZE;
- struct resource r;
-
- np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
- if (np) {
- int len;
- int size_cells;
- const __be32 *prop;
-
- size_cells = of_n_size_cells(np);
-
- prop = of_get_property(np, "ibm,lmb-size", &len);
- if (prop && len >= size_cells * sizeof(__be32))
- memblock_size = of_read_number(prop, size_cells);
- of_node_put(np);
-
- } else if (machine_is(pseries)) {
- /* This fallback really only applies to pseries */
- unsigned int memzero_size = 0;
-
- np = of_find_node_by_path("/memory@0");
- if (np) {
- if (!of_address_to_resource(np, 0, &r))
- memzero_size = resource_size(&r);
- of_node_put(np);
- }
-
- if (memzero_size) {
- /* We now know the size of memory@0, use this to find
- * the first memoryblock and get its size.
- */
- char buf[64];
-
- sprintf(buf, "/memory@%x", memzero_size);
- np = of_find_node_by_path(buf);
- if (np) {
- if (!of_address_to_resource(np, 0, &r))
- memblock_size = resource_size(&r);
- of_node_put(np);
- }
- }
- }
- return memblock_size;
-}
-
static void dlpar_free_property(struct property *prop)
{
kfree(prop->name);
@@ -103,7 +55,8 @@ static bool find_aa_index(struct device_node *dr_node,
struct property *ala_prop,
const u32 *lmb_assoc, u32 *aa_index)
{
- u32 *assoc_arrays, new_prop_size;
+ __be32 *assoc_arrays;
+ u32 new_prop_size;
struct property *new_prop;
int aa_arrays, aa_array_entries, aa_array_sz;
int i, index;
@@ -255,8 +208,10 @@ static int dlpar_change_lmb_state(struct drmem_lmb *lmb, bool online)
int rc;
mem_block = lmb_to_memblock(lmb);
- if (!mem_block)
+ if (!mem_block) {
+ pr_err("Failed memory block lookup for LMB 0x%x\n", lmb->drc_index);
return -EINVAL;
+ }
if (online && mem_block->dev.offline)
rc = device_online(&mem_block->dev);
@@ -283,7 +238,7 @@ static int dlpar_offline_lmb(struct drmem_lmb *lmb)
static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size)
{
- unsigned long block_sz, start_pfn;
+ unsigned long start_pfn;
int sections_per_block;
int i;
@@ -294,8 +249,7 @@ static int pseries_remove_memblock(unsigned long base, unsigned long memblock_si
if (!pfn_valid(start_pfn))
goto out;
- block_sz = pseries_memory_block_size();
- sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
+ sections_per_block = memory_block_size / MIN_MEMORY_BLOCK_SIZE;
for (i = 0; i < sections_per_block; i++) {
__remove_memory(base, MIN_MEMORY_BLOCK_SIZE);
@@ -311,11 +265,8 @@ out:
static int pseries_remove_mem_node(struct device_node *np)
{
- const __be32 *prop;
- unsigned long base;
- unsigned long lmb_size;
- int ret = -EINVAL;
- int addr_cells, size_cells;
+ int ret;
+ struct resource res;
/*
* Check to see if we are actually removing memory
@@ -326,21 +277,11 @@ static int pseries_remove_mem_node(struct device_node *np)
/*
* Find the base address and size of the memblock
*/
- prop = of_get_property(np, "reg", NULL);
- if (!prop)
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
return ret;
- addr_cells = of_n_addr_cells(np);
- size_cells = of_n_size_cells(np);
-
- /*
- * "reg" property represents (addr,size) tuple.
- */
- base = of_read_number(prop, addr_cells);
- prop += addr_cells;
- lmb_size = of_read_number(prop, size_cells);
-
- pseries_remove_memblock(base, lmb_size);
+ pseries_remove_memblock(res.start, resource_size(&res));
return 0;
}
@@ -367,7 +308,6 @@ static int dlpar_add_lmb(struct drmem_lmb *);
static int dlpar_remove_lmb(struct drmem_lmb *lmb)
{
struct memory_block *mem_block;
- unsigned long block_sz;
int rc;
if (!lmb_is_removable(lmb))
@@ -383,13 +323,11 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb)
return rc;
}
- block_sz = pseries_memory_block_size();
-
- __remove_memory(lmb->base_addr, block_sz);
+ __remove_memory(lmb->base_addr, memory_block_size);
put_device(&mem_block->dev);
/* Update memory regions for memory remove */
- memblock_remove(lmb->base_addr, block_sz);
+ memblock_remove(lmb->base_addr, memory_block_size);
invalidate_lmb_associativity_index(lmb);
lmb->flags &= ~DRCONF_MEM_ASSIGNED;
@@ -500,14 +438,15 @@ static int dlpar_memory_remove_by_index(u32 drc_index)
}
}
- if (!lmb_found)
+ if (!lmb_found) {
+ pr_debug("Failed to look up LMB for drc index %x\n", drc_index);
rc = -EINVAL;
-
- if (rc)
+ } else if (rc) {
pr_debug("Failed to hot-remove memory at %llx\n",
lmb->base_addr);
- else
+ } else {
pr_debug("Memory at %llx was hot-removed\n", lmb->base_addr);
+ }
return rc;
}
@@ -639,6 +578,7 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
rc = update_lmb_associativity_index(lmb);
if (rc) {
dlpar_release_drc(lmb->drc_index);
+ pr_err("Failed to configure LMB 0x%x\n", lmb->drc_index);
return rc;
}
@@ -650,14 +590,16 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
nid = first_online_node;
/* Add the memory */
- rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_NONE);
+ rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_MEMMAP_ON_MEMORY);
if (rc) {
+ pr_err("Failed to add LMB 0x%x to node %u", lmb->drc_index, nid);
invalidate_lmb_associativity_index(lmb);
return rc;
}
rc = dlpar_online_lmb(lmb);
if (rc) {
+ pr_err("Failed to online LMB 0x%x on node %u\n", lmb->drc_index, nid);
__remove_memory(lmb->base_addr, block_sz);
invalidate_lmb_associativity_index(lmb);
} else {
@@ -929,11 +871,8 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
static int pseries_add_mem_node(struct device_node *np)
{
- const __be32 *prop;
- unsigned long base;
- unsigned long lmb_size;
- int ret = -EINVAL;
- int addr_cells, size_cells;
+ int ret;
+ struct resource res;
/*
* Check to see if we are actually adding memory
@@ -944,23 +883,14 @@ static int pseries_add_mem_node(struct device_node *np)
/*
* Find the base and size of the memblock
*/
- prop = of_get_property(np, "reg", NULL);
- if (!prop)
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
return ret;
- addr_cells = of_n_addr_cells(np);
- size_cells = of_n_size_cells(np);
- /*
- * "reg" property represents (addr,size) tuple.
- */
- base = of_read_number(prop, addr_cells);
- prop += addr_cells;
- lmb_size = of_read_number(prop, size_cells);
-
/*
* Update memory region to represent the memory add
*/
- ret = memblock_add(base, lmb_size);
+ ret = memblock_add(res.start, resource_size(&res));
return (ret < 0) ? -EINVAL : 0;
}