diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index b708c5c..5173e49 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -26,6 +26,83 @@
static bool rtas_hp_event;
+static struct drconf_mem {
+ u32 num_lmbs;
+ struct of_drconf_cell *lmbs;
+} drmem;
+
+#define for_each_lmb_range(lmb, start, end) \
+ for ((lmb) = (start); (lmb) < (end); (lmb)++)
+#define for_each_lmb(lmb) for_each_lmb_range((lmb), 0, drmem.num_lmbs)
+
+static u64 lmb_base_address(u32 lmb) {
+ return be64_to_cpu(drmem.lmbs[lmb].base_addr);
+}
+
+static u32 lmb_drc_index(u32 lmb) {
+ return be32_to_cpu(drmem.lmbs[lmb].drc_index);
+}
+
+static void lmb_set_aa_index(u32 lmb, u32 aa_index) {
+ drmem.lmbs[lmb].aa_index = cpu_to_be32(aa_index);
+}
+
+static bool lmb_updated(u32 lmb) {
+ return drmem.lmbs[lmb].reserved;
+}
+
+static void mark_lmb_updated(u32 lmb) {
+ drmem.lmbs[lmb].reserved = 1;
+}
+
+static void rm_lmb_update(u32 lmb) {
+ drmem.lmbs[lmb].reserved = 0;
+}
+
+static bool lmb_reserved(u32 lmb) {
+ return be32_to_cpu(drmem.lmbs[lmb].flags) & DRCONF_MEM_RESERVED;
+}
+
+static bool lmb_assigned(u32 lmb) {
+ return be32_to_cpu(drmem.lmbs[lmb].flags) & DRCONF_MEM_ASSIGNED;
+}
+
+static void mark_lmb_assigned(u32 lmb) {
+ drmem.lmbs[lmb].flags |= cpu_to_be32(DRCONF_MEM_ASSIGNED);
+}
+
+static void mark_lmb_unassigned(u32 lmb) {
+ drmem.lmbs[lmb].flags &= cpu_to_be32(~DRCONF_MEM_ASSIGNED);
+}
+
+static int dlpar_acquire_lmb(u32 lmb) {
+ return dlpar_acquire_drc(be32_to_cpu(drmem.lmbs[lmb].drc_index));
+}
+
+static int dlpar_release_lmb(u32 lmb) {
+ return dlpar_release_drc(be32_to_cpu(drmem.lmbs[lmb].drc_index));
+}
+
+static void __init update_drconf_memory(void)
+{
+ struct device_node *dn;
+ struct property *prop;
+ __be32 *p;
+
+ dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+ if (!dn)
+ return;
+
+ prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
+ of_node_put(dn);
+ if (!prop)
+ return;
+
+ p = prop->value;
+ drmem.num_lmbs = be32_to_cpu(*p++);
+ drmem.lmbs = (struct of_drconf_cell *)p;
+}
+
unsigned long pseries_memory_block_size(void)
{
struct device_node *np;@@ -99,98 +176,6 @@ static struct property *dlpar_clone_property(struct property *prop,
return new_prop;
}
-static struct property *dlpar_clone_drconf_property(struct device_node *dn)
-{
- struct property *prop, *new_prop;
- struct of_drconf_cell *lmbs;
- u32 num_lmbs, *p;
- int i;
-
- prop = of_find_property(dn, "ibm,dynamic-memory", NULL);
- if (!prop)
- return NULL;
-
- new_prop = dlpar_clone_property(prop, prop->length);
- if (!new_prop)
- return NULL;
-
- /* Convert the property to cpu endian-ness */
- p = new_prop->value;
- *p = be32_to_cpu(*p);
-
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
-
- for (i = 0; i < num_lmbs; i++) {
- lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr);
- lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index);
- lmbs[i].flags = be32_to_cpu(lmbs[i].flags);
- }
-
- return new_prop;
-}
-
-static void dlpar_update_drconf_property(struct device_node *dn,
- struct property *prop)
-{
- struct of_drconf_cell *lmbs;
- u32 num_lmbs, *p;
- int i;
-
- /* Convert the property back to BE */
- p = prop->value;
- num_lmbs = *p;
- *p = cpu_to_be32(*p);
- p++;
-
- lmbs = (struct of_drconf_cell *)p;
- for (i = 0; i < num_lmbs; i++) {
- lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
- lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
- lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
- }
-
- rtas_hp_event = true;
- of_update_property(dn, prop);
- rtas_hp_event = false;
-}
-
-static int dlpar_update_device_tree_lmb(struct of_drconf_cell *lmb)
-{
- struct device_node *dn;
- struct property *prop;
- struct of_drconf_cell *lmbs;
- u32 *p, num_lmbs;
- int i;
-
- dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
- if (!dn)
- return -ENODEV;
-
- prop = dlpar_clone_drconf_property(dn);
- if (!prop) {
- of_node_put(dn);
- return -ENODEV;
- }
-
- p = prop->value;
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
-
- for (i = 0; i < num_lmbs; i++) {
- if (lmbs[i].drc_index == lmb->drc_index) {
- lmbs[i].flags = lmb->flags;
- lmbs[i].aa_index = lmb->aa_index;
-
- dlpar_update_drconf_property(dn, prop);
- break;
- }
- }
-
- of_node_put(dn);
- return 0;
-}
-
static u32 find_aa_index(struct device_node *dr_node,
struct property *ala_prop, const u32 *lmb_assoc)
{@@ -253,18 +238,20 @@ static u32 find_aa_index(struct device_node *dr_node,
return aa_index;
}
-static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
+static u32 lookup_lmb_associativity_index(u32 lmb)
{
struct device_node *parent, *lmb_node, *dr_node;
struct property *ala_prop;
const u32 *lmb_assoc;
+ u32 my_drc_index;
u32 aa_index;
parent = of_find_node_by_path("/");
if (!parent)
return -ENODEV;
- lmb_node = dlpar_configure_connector(cpu_to_be32(lmb->drc_index),
+ my_drc_index = lmb_drc_index(lmb);
+ lmb_node = dlpar_configure_connector(cpu_to_be32(my_drc_index),
parent);
of_node_put(parent);
if (!lmb_node)@@ -296,37 +283,35 @@ static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
return aa_index;
}
-static int dlpar_add_device_tree_lmb(struct of_drconf_cell *lmb)
+static int dlpar_add_device_tree_lmb(u32 lmb)
{
int aa_index;
- lmb->flags |= DRCONF_MEM_ASSIGNED;
-
aa_index = lookup_lmb_associativity_index(lmb);
if (aa_index < 0) {
pr_err("Couldn't find associativity index for drc index %x\n",
- lmb->drc_index);
+ lmb_drc_index(lmb));
return aa_index;
}
- lmb->aa_index = aa_index;
- return dlpar_update_device_tree_lmb(lmb);
+ mark_lmb_assigned(lmb);
+ lmb_set_aa_index(lmb, aa_index);
+ return 0;
}
-static int dlpar_remove_device_tree_lmb(struct of_drconf_cell *lmb)
+static void dlpar_remove_device_tree_lmb(u32 lmb)
{
- lmb->flags &= ~DRCONF_MEM_ASSIGNED;
- lmb->aa_index = 0xffffffff;
- return dlpar_update_device_tree_lmb(lmb);
+ mark_lmb_unassigned(lmb);
+ lmb_set_aa_index(lmb, 0xffffffff);
}
-static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
+static struct memory_block *lmb_to_memblock(u32 lmb)
{
unsigned long section_nr;
struct mem_section *mem_sect;
struct memory_block *mem_block;
- section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
+ section_nr = pfn_to_section_nr(PFN_DOWN(lmb_base_address(lmb)));
mem_sect = __nr_to_section(section_nr);
mem_block = find_memory_block(mem_sect);@@ -392,19 +377,19 @@ static int pseries_remove_mem_node(struct device_node *np)
return 0;
}
-static bool lmb_is_removable(struct of_drconf_cell *lmb)
+static bool lmb_is_removable(u32 lmb)
{
int i, scns_per_block;
int rc = 1;
unsigned long pfn, block_sz;
u64 phys_addr;
- if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
+ if (!lmb_assigned(lmb))
return false;
block_sz = memory_block_size_bytes();
scns_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
- phys_addr = lmb->base_addr;
+ phys_addr = lmb_base_address(lmb);
for (i = 0; i < scns_per_block; i++) {
pfn = PFN_DOWN(phys_addr);@@ -418,12 +403,13 @@ static bool lmb_is_removable(struct of_drconf_cell *lmb)
return rc ? true : false;
}
-static int dlpar_add_lmb(struct of_drconf_cell *);
+static int dlpar_add_lmb(u32 lmb);
-static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
+static int dlpar_remove_lmb(u32 lmb)
{
struct memory_block *mem_block;
unsigned long block_sz;
+ u64 base_addr;
int nid, rc;
if (!lmb_is_removable(lmb))@@ -439,84 +425,81 @@ static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
return rc;
block_sz = pseries_memory_block_size();
- nid = memory_add_physaddr_to_nid(lmb->base_addr);
+ base_addr = lmb_base_address(lmb);
+ nid = memory_add_physaddr_to_nid(base_addr);
- remove_memory(nid, lmb->base_addr, block_sz);
+ remove_memory(nid, base_addr, block_sz);
/* Update memory regions for memory remove */
- memblock_remove(lmb->base_addr, block_sz);
+ memblock_remove(base_addr, block_sz);
- dlpar_release_drc(lmb->drc_index);
+ dlpar_release_lmb(lmb);
dlpar_remove_device_tree_lmb(lmb);
return 0;
}
-static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
- struct property *prop)
+static int dlpar_memory_remove_by_count(u32 lmbs_to_remove)
{
- struct of_drconf_cell *lmbs;
+ u32 lmb;
int lmbs_removed = 0;
int lmbs_available = 0;
- u32 num_lmbs, *p;
- int i, rc;
+ int rc;
pr_info("Attempting to hot-remove %d LMB(s)\n", lmbs_to_remove);
if (lmbs_to_remove == 0)
return -EINVAL;
- p = prop->value;
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
-
/* Validate that there are enough LMBs to satisfy the request */
- for (i = 0; i < num_lmbs; i++) {
- if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
+ for_each_lmb(lmb) {
+ if (lmb_assigned(lmb))
lmbs_available++;
}
if (lmbs_available < lmbs_to_remove)
return -EINVAL;
- for (i = 0; i < num_lmbs && lmbs_removed < lmbs_to_remove; i++) {
- rc = dlpar_remove_lmb(&lmbs[i]);
+ for_each_lmb(lmb) {
+ rc = dlpar_remove_lmb(lmb);
if (rc)
continue;
- lmbs_removed++;
-
/* Mark this lmb so we can add it later if all of the
* requested LMBs cannot be removed.
*/
- lmbs[i].reserved = 1;
+ mark_lmb_updated(lmb);
+
+ lmbs_removed++;
+ if (lmbs_removed == lmbs_to_remove)
+ break;
}
if (lmbs_removed != lmbs_to_remove) {
pr_err("Memory hot-remove failed, adding LMB's back\n");
- for (i = 0; i < num_lmbs; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb(lmb) {
+ if (!lmb_updated(lmb))
continue;
- rc = dlpar_add_lmb(&lmbs[i]);
+ rc = dlpar_add_lmb(lmb);
if (rc)
pr_err("Failed to add LMB back, drc index %x\n",
- lmbs[i].drc_index);
+ lmb_drc_index(lmb));
- lmbs[i].reserved = 0;
+ rm_lmb_update(lmb);
}
rc = -EINVAL;
} else {
- for (i = 0; i < num_lmbs; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb(lmb) {
+ if (!lmb_updated(lmb))
continue;
pr_info("Memory at %llx was hot-removed\n",
- lmbs[i].base_addr);
+ lmb_base_address(lmb));
- lmbs[i].reserved = 0;
+ rm_lmb_update(lmb);
}
rc = 0;
}@@ -524,24 +507,19 @@ static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
return rc;
}
-static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
+static int dlpar_memory_remove_by_index(u32 drc_index)
{
- struct of_drconf_cell *lmbs;
- u32 num_lmbs, *p;
+ u32 lmb;
int lmb_found;
- int i, rc;
+ int rc;
pr_info("Attempting to hot-remove LMB, drc index %x\n", drc_index);
- p = prop->value;
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
-
lmb_found = 0;
- for (i = 0; i < num_lmbs; i++) {
- if (lmbs[i].drc_index == drc_index) {
+ for_each_lmb(lmb) {
+ if (lmb_drc_index(lmb) == drc_index) {
lmb_found = 1;
- rc = dlpar_remove_lmb(&lmbs[i]);
+ rc = dlpar_remove_lmb(lmb);
break;
}
}@@ -551,20 +529,19 @@ static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
if (rc)
pr_info("Failed to hot-remove memory at %llx\n",
- lmbs[i].base_addr);
+ lmb_base_address(lmb));
else
- pr_info("Memory at %llx was hot-removed\n", lmbs[i].base_addr);
+ pr_info("Memory at %llx was hot-removed\n",
+ lmb_base_address(lmb));
return rc;
}
-static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
- struct property *prop)
+static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index)
{
- struct of_drconf_cell *lmbs;
- u32 num_lmbs, *p;
- int i, rc, start_lmb_found;
- int lmbs_available = 0, start_index = 0, end_index;
+ u32 lmb, start_lmb, end_lmb;
+ int lmbs_available = 0;
+ int rc;
pr_info("Attempting to hot-remove %u LMB(s) at %x\n",
lmbs_to_remove, drc_index);@@ -572,29 +549,17 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
if (lmbs_to_remove == 0)
return -EINVAL;
- p = prop->value;
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
- start_lmb_found = 0;
-
/* Navigate to drc_index */
- while (start_index < num_lmbs) {
- if (lmbs[start_index].drc_index == drc_index) {
- start_lmb_found = 1;
+ for_each_lmb(start_lmb) {
+ if (lmb_drc_index(start_lmb) == drc_index)
break;
- }
-
- start_index++;
}
- if (!start_lmb_found)
- return -EINVAL;
-
- end_index = start_index + lmbs_to_remove;
+ end_lmb = start_lmb + lmbs_to_remove;
/* Validate that there are enough LMBs to satisfy the request */
- for (i = start_index; i < end_index; i++) {
- if (lmbs[i].flags & DRCONF_MEM_RESERVED)
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (lmb_reserved(lmb))
break;
lmbs_available++;@@ -603,41 +568,41 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index,
if (lmbs_available < lmbs_to_remove)
return -EINVAL;
- for (i = 0; i < end_index; i++) {
- if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED))
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (!lmb_assigned(lmb))
continue;
- rc = dlpar_remove_lmb(&lmbs[i]);
+ rc = dlpar_remove_lmb(lmb);
if (rc)
break;
- lmbs[i].reserved = 1;
+ mark_lmb_updated(lmb);
}
if (rc) {
pr_err("Memory indexed-count-remove failed, adding any removed LMBs\n");
- for (i = start_index; i < end_index; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (!lmb_updated(lmb))
continue;
- rc = dlpar_add_lmb(&lmbs[i]);
+ rc = dlpar_add_lmb(lmb);
if (rc)
pr_err("Failed to add LMB, drc index %x\n",
- be32_to_cpu(lmbs[i].drc_index));
+ lmb_drc_index(lmb));
- lmbs[i].reserved = 0;
+ rm_lmb_update(lmb);
}
rc = -EINVAL;
} else {
- for (i = start_index; i < end_index; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (!lmb_updated(lmb))
continue;
pr_info("Memory at %llx (drc index %x) was hot-removed\n",
- lmbs[i].base_addr, lmbs[i].drc_index);
+ lmb_base_address(lmb), lmb_drc_index(lmb));
- lmbs[i].reserved = 0;
+ rm_lmb_update(lmb);
}
}
@@ -658,143 +623,137 @@ static inline int dlpar_memory_remove(struct pseries_hp_errorlog *hp_elog)
{
return -EOPNOTSUPP;
}
-static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
+static int dlpar_remove_lmb(u32 lmb)
{
return -EOPNOTSUPP;
}
-static int dlpar_memory_remove_by_count(u32 lmbs_to_remove,
- struct property *prop)
+static int dlpar_memory_remove_by_count(u32 lmbs_to_remove)
{
return -EOPNOTSUPP;
}
-static int dlpar_memory_remove_by_index(u32 drc_index, struct property *prop)
+static int dlpar_memory_remove_by_index(u32 drc_index)
{
return -EOPNOTSUPP;
}
#endif /* CONFIG_MEMORY_HOTREMOVE */
-static int dlpar_add_lmb(struct of_drconf_cell *lmb)
+static int dlpar_add_lmb(u32 lmb)
{
unsigned long block_sz;
+ u64 base_addr;
int nid, rc;
- if (lmb->flags & DRCONF_MEM_ASSIGNED)
+ if (lmb_assigned(lmb))
return -EINVAL;
- rc = dlpar_acquire_drc(lmb->drc_index);
+ rc = dlpar_acquire_lmb(lmb);
if (rc)
return rc;
rc = dlpar_add_device_tree_lmb(lmb);
if (rc) {
pr_err("Couldn't update device tree for drc index %x\n",
- lmb->drc_index);
- dlpar_release_drc(lmb->drc_index);
+ lmb_drc_index(lmb));
+ dlpar_release_lmb(lmb);
return rc;
}
block_sz = memory_block_size_bytes();
+ base_addr = lmb_base_address(lmb);
/* Find the node id for this address */
- nid = memory_add_physaddr_to_nid(lmb->base_addr);
+ nid = memory_add_physaddr_to_nid(base_addr);
/* Add the memory */
- rc = add_memory(nid, lmb->base_addr, block_sz);
+ rc = add_memory(nid, base_addr, block_sz);
if (rc) {
dlpar_remove_device_tree_lmb(lmb);
- dlpar_release_drc(lmb->drc_index);
+ dlpar_release_lmb(lmb);
} else {
- lmb->flags |= DRCONF_MEM_ASSIGNED;
+ mark_lmb_assigned(lmb);
}
return rc;
}
-static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
+static int dlpar_memory_add_by_count(u32 lmbs_to_add)
{
- struct of_drconf_cell *lmbs;
- u32 num_lmbs, *p;
int lmbs_available = 0;
int lmbs_added = 0;
- int i, rc;
+ u32 lmb;
+ int rc;
pr_info("Attempting to hot-add %d LMB(s)\n", lmbs_to_add);
if (lmbs_to_add == 0)
return -EINVAL;
- p = prop->value;
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
-
/* Validate that there are enough LMBs to satisfy the request */
- for (i = 0; i < num_lmbs; i++) {
- if (!(lmbs[i].flags & DRCONF_MEM_ASSIGNED))
+ for_each_lmb(lmb) {
+ if (!lmb_assigned(lmb))
lmbs_available++;
}
if (lmbs_available < lmbs_to_add)
return -EINVAL;
- for (i = 0; i < num_lmbs && lmbs_to_add != lmbs_added; i++) {
- rc = dlpar_add_lmb(&lmbs[i]);
+ for_each_lmb(lmb) {
+ rc = dlpar_add_lmb(lmb);
if (rc)
continue;
- lmbs_added++;
/* Mark this lmb so we can remove it later if all of the
* requested LMBs cannot be added.
*/
- lmbs[i].reserved = 1;
+ mark_lmb_updated(lmb);
+
+ lmbs_added++;
+ if (lmbs_added == lmbs_to_add)
+ break;
}
if (lmbs_added != lmbs_to_add) {
pr_err("Memory hot-add failed, removing any added LMBs\n");
- for (i = 0; i < num_lmbs; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb(lmb) {
+ if (!lmb_updated(lmb))
continue;
- rc = dlpar_remove_lmb(&lmbs[i]);
+ rc = dlpar_remove_lmb(lmb);
if (rc)
pr_err("Failed to remove LMB, drc index %x\n",
- be32_to_cpu(lmbs[i].drc_index));
+ lmb_drc_index(lmb));
}
rc = -EINVAL;
} else {
- for (i = 0; i < num_lmbs; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb(lmb) {
+ if (!lmb_updated(lmb))
continue;
pr_info("Memory at %llx (drc index %x) was hot-added\n",
- lmbs[i].base_addr, lmbs[i].drc_index);
- lmbs[i].reserved = 0;
+ lmb_base_address(lmb), lmb_drc_index(lmb));
+ rm_lmb_update(lmb);
}
}
return rc;
}
-static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop)
+static int dlpar_memory_add_by_index(u32 drc_index)
{
- struct of_drconf_cell *lmbs;
- u32 num_lmbs, *p;
- int i, lmb_found;
+ u32 lmb;
+ int lmb_found;
int rc;
pr_info("Attempting to hot-add LMB, drc index %x\n", drc_index);
- p = prop->value;
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
-
lmb_found = 0;
- for (i = 0; i < num_lmbs; i++) {
- if (lmbs[i].drc_index == drc_index) {
+ for_each_lmb(lmb) {
+ if (lmb_drc_index(lmb) == drc_index) {
lmb_found = 1;
- rc = dlpar_add_lmb(&lmbs[i]);
+ rc = dlpar_add_lmb(lmb);
break;
}
}@@ -806,18 +765,16 @@ static int dlpar_memory_add_by_index(u32 drc_index, struct property *prop)
pr_info("Failed to hot-add memory, drc index %x\n", drc_index);
else
pr_info("Memory at %llx (drc index %x) was hot-added\n",
- lmbs[i].base_addr, drc_index);
+ lmb_base_address(lmb), drc_index);
return rc;
}
-static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index,
- struct property *prop)
+static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index)
{
- struct of_drconf_cell *lmbs;
- u32 num_lmbs, *p;
- int i, rc, start_lmb_found;
- int lmbs_available = 0, start_index = 0, end_index;
+ u32 lmb, start_lmb, end_lmb;
+ int lmbs_available = 0;
+ int rc;
pr_info("Attempting to hot-add %u LMB(s) at index %x\n",
lmbs_to_add, drc_index);@@ -825,29 +782,17 @@ static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index,
if (lmbs_to_add == 0)
return -EINVAL;
- p = prop->value;
- num_lmbs = *p++;
- lmbs = (struct of_drconf_cell *)p;
- start_lmb_found = 0;
-
/* Navigate to drc_index */
- while (start_index < num_lmbs) {
- if (lmbs[start_index].drc_index == drc_index) {
- start_lmb_found = 1;
+ for_each_lmb(start_lmb) {
+ if (lmb_drc_index(start_lmb) == drc_index)
break;
- }
-
- start_index++;
}
- if (!start_lmb_found)
- return -EINVAL;
-
- end_index = start_index + lmbs_to_add;
+ end_lmb = start_lmb + lmbs_to_add;
/* Validate that there are enough LMBs to satisfy the request */
- for (i = start_index; i < end_index; i++) {
- if (lmbs[i].flags & DRCONF_MEM_RESERVED)
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (lmb_reserved(lmb))
break;
lmbs_available++;@@ -856,38 +801,38 @@ static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index,
if (lmbs_available < lmbs_to_add)
return -EINVAL;
- for (i = start_index; i < end_index; i++) {
- if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (lmb_assigned(lmb))
continue;
- rc = dlpar_add_lmb(&lmbs[i]);
+ rc = dlpar_add_lmb(lmb);
if (rc)
break;
- lmbs[i].reserved = 1;
+ mark_lmb_updated(lmb);
}
if (rc) {
pr_err("Memory indexed-count-add failed, removing any added LMBs\n");
- for (i = start_index; i < end_index; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (!lmb_updated(lmb))
continue;
- rc = dlpar_remove_lmb(&lmbs[i]);
+ rc = dlpar_remove_lmb(lmb);
if (rc)
pr_err("Failed to remove LMB, drc index %x\n",
- be32_to_cpu(lmbs[i].drc_index));
+ lmb_drc_index(lmb));
}
rc = -EINVAL;
} else {
- for (i = start_index; i < end_index; i++) {
- if (!lmbs[i].reserved)
+ for_each_lmb_range(lmb, start_lmb, end_lmb) {
+ if (!lmb_updated(lmb))
continue;
pr_info("Memory at %llx (drc index %x) was hot-added\n",
- lmbs[i].base_addr, lmbs[i].drc_index);
- lmbs[i].reserved = 0;
+ lmb_base_address(lmb), lmb_drc_index(lmb));
+ rm_lmb_update(lmb);
}
}
@@ -896,37 +841,23 @@ static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index,
int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
{
- struct device_node *dn;
- struct property *prop;
u32 count, drc_index;
int rc;
lock_device_hotplug();
- dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
- if (!dn) {
- rc = -EINVAL;
- goto dlpar_memory_out;
- }
-
- prop = dlpar_clone_drconf_property(dn);
- if (!prop) {
- rc = -EINVAL;
- goto dlpar_memory_out;
- }
-
switch (hp_elog->action) {
case PSERIES_HP_ELOG_ACTION_ADD:
if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
count = hp_elog->_drc_u.drc_count;
- rc = dlpar_memory_add_by_count(count, prop);
+ rc = dlpar_memory_add_by_count(count);
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
drc_index = hp_elog->_drc_u.drc_index;
- rc = dlpar_memory_add_by_index(drc_index, prop);
+ rc = dlpar_memory_add_by_index(drc_index);
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
count = hp_elog->_drc_u.indexed_count[0];
drc_index = hp_elog->_drc_u.indexed_count[1];
- rc = dlpar_memory_add_by_ic(count, drc_index, prop);
+ rc = dlpar_memory_add_by_ic(count, drc_index);
} else {
rc = -EINVAL;
}@@ -935,14 +866,14 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
case PSERIES_HP_ELOG_ACTION_REMOVE:
if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_COUNT) {
count = hp_elog->_drc_u.drc_count;
- rc = dlpar_memory_remove_by_count(count, prop);
+ rc = dlpar_memory_remove_by_count(count);
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_INDEX) {
drc_index = hp_elog->_drc_u.drc_index;
- rc = dlpar_memory_remove_by_index(drc_index, prop);
+ rc = dlpar_memory_remove_by_index(drc_index);
} else if (hp_elog->id_type == PSERIES_HP_ELOG_ID_DRC_IC) {
count = hp_elog->_drc_u.indexed_count[0];
drc_index = hp_elog->_drc_u.indexed_count[1];
- rc = dlpar_memory_remove_by_ic(count, drc_index, prop);
+ rc = dlpar_memory_remove_by_ic(count, drc_index);
} else {
rc = -EINVAL;
}@@ -954,10 +885,6 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
break;
}
- dlpar_free_property(prop);
-
-dlpar_memory_out:
- of_node_put(dn);
unlock_device_hotplug();
return rc;
}
@@ -1005,6 +932,8 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
if (rtas_hp_event)
return 0;
+ update_drconf_memory();
+
memblock_size = pseries_memory_block_size();
if (!memblock_size)
return -EINVAL;
@@ -1075,6 +1004,7 @@ static int __init pseries_memory_hotplug_init(void)
if (firmware_has_feature(FW_FEATURE_LPAR))
of_reconfig_notifier_register(&pseries_mem_nb);
+ update_drconf_memory();
return 0;
}
machine_device_initcall(pseries, pseries_memory_hotplug_init);