Commit 063b8b12 authored by Nathan Fontenot's avatar Nathan Fontenot Committed by Michael Ellerman

powerpc/pseries/memory-hotplug: Only update DT once per memory DLPAR request

The updates to powerpc numa and memory hotplug code now use the
in-kernel LMB array instead of the device tree. This change allows the
pseries memory DLPAR code to only update the device tree once after
successfully handling a DLPAR request.

Prior to the in-kernel LMB array, the numa code looked up the affinity
for memory being added in the device tree, the code now looks this up
in the LMB array. This change means the memory hotplug code can just
update the affinity for an LMB in the LMB array instead of updating
the device tree.

This also provides a savings in kernel memory. When updating the
device tree old properties are never free'ed since there is no
usecount on properties. This behavior leads to a new copy of the
property being allocated every time a LMB is added or removed (i.e. a
request to add 100 LMBs creates 100 new copies of the property). With
this update only a single new property is created when a DLPAR request
completes successfully.
Signed-off-by: default avatarNathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 6977f95e
...@@ -99,4 +99,9 @@ void __init walk_drmem_lmbs_early(unsigned long node, ...@@ -99,4 +99,9 @@ void __init walk_drmem_lmbs_early(unsigned long node,
void (*func)(struct drmem_lmb *, const __be32 **)); void (*func)(struct drmem_lmb *, const __be32 **));
#endif #endif
static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb)
{
lmb->aa_index = 0xffffffff;
}
#endif /* _ASM_POWERPC_LMB_H */ #endif /* _ASM_POWERPC_LMB_H */
...@@ -163,7 +163,7 @@ static u32 find_aa_index(struct device_node *dr_node, ...@@ -163,7 +163,7 @@ static u32 find_aa_index(struct device_node *dr_node,
return aa_index; return aa_index;
} }
static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) static int update_lmb_associativity_index(struct drmem_lmb *lmb)
{ {
struct device_node *parent, *lmb_node, *dr_node; struct device_node *parent, *lmb_node, *dr_node;
struct property *ala_prop; struct property *ala_prop;
...@@ -203,43 +203,14 @@ static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) ...@@ -203,43 +203,14 @@ static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb)
aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc); aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc);
dlpar_free_cc_nodes(lmb_node); dlpar_free_cc_nodes(lmb_node);
return aa_index;
}
static int dlpar_add_device_tree_lmb(struct drmem_lmb *lmb)
{
int rc, aa_index;
lmb->flags |= DRCONF_MEM_ASSIGNED;
aa_index = lookup_lmb_associativity_index(lmb);
if (aa_index < 0) { if (aa_index < 0) {
pr_err("Couldn't find associativity index for drc index %x\n", pr_err("Could not find LMB associativity\n");
lmb->drc_index); return -1;
return aa_index;
} }
lmb->aa_index = aa_index; lmb->aa_index = aa_index;
return 0;
rtas_hp_event = true;
rc = drmem_update_dt();
rtas_hp_event = false;
return rc;
}
static int dlpar_remove_device_tree_lmb(struct drmem_lmb *lmb)
{
int rc;
lmb->flags &= ~DRCONF_MEM_ASSIGNED;
lmb->aa_index = 0xffffffff;
rtas_hp_event = true;
rc = drmem_update_dt();
rtas_hp_event = false;
return rc;
} }
static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb) static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb)
...@@ -428,7 +399,9 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) ...@@ -428,7 +399,9 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb)
/* Update memory regions for memory remove */ /* Update memory regions for memory remove */
memblock_remove(lmb->base_addr, block_sz); memblock_remove(lmb->base_addr, block_sz);
dlpar_remove_device_tree_lmb(lmb); invalidate_lmb_associativity_index(lmb);
lmb->flags &= ~DRCONF_MEM_ASSIGNED;
return 0; return 0;
} }
...@@ -688,10 +661,8 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) ...@@ -688,10 +661,8 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
if (lmb->flags & DRCONF_MEM_ASSIGNED) if (lmb->flags & DRCONF_MEM_ASSIGNED)
return -EINVAL; return -EINVAL;
rc = dlpar_add_device_tree_lmb(lmb); rc = update_lmb_associativity_index(lmb);
if (rc) { if (rc) {
pr_err("Couldn't update device tree for drc index %x\n",
lmb->drc_index);
dlpar_release_drc(lmb->drc_index); dlpar_release_drc(lmb->drc_index);
return rc; return rc;
} }
...@@ -704,14 +675,14 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) ...@@ -704,14 +675,14 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
/* Add the memory */ /* Add the memory */
rc = add_memory(nid, lmb->base_addr, block_sz); rc = add_memory(nid, lmb->base_addr, block_sz);
if (rc) { if (rc) {
dlpar_remove_device_tree_lmb(lmb); invalidate_lmb_associativity_index(lmb);
return rc; return rc;
} }
rc = dlpar_online_lmb(lmb); rc = dlpar_online_lmb(lmb);
if (rc) { if (rc) {
remove_memory(nid, lmb->base_addr, block_sz); remove_memory(nid, lmb->base_addr, block_sz);
dlpar_remove_device_tree_lmb(lmb); invalidate_lmb_associativity_index(lmb);
} else { } else {
lmb->flags |= DRCONF_MEM_ASSIGNED; lmb->flags |= DRCONF_MEM_ASSIGNED;
} }
...@@ -958,6 +929,12 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) ...@@ -958,6 +929,12 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
break; break;
} }
if (!rc) {
rtas_hp_event = true;
rc = drmem_update_dt();
rtas_hp_event = false;
}
unlock_device_hotplug(); unlock_device_hotplug();
return rc; return rc;
} }
......
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