* [PATCH 1/3] hotplug/memory: Apply assoc mem updates Post Migration Topo
2017-11-02 20:52 [PATCH 0/3] powerpc/hotplug: Fix affinity assoc for LPAR migration Michael Bringmann
@ 2017-11-02 20:53 ` Michael Bringmann
2017-11-02 20:53 ` [PATCH 2/3] postmigration/memory: Review assoc lookup array changes Michael Bringmann
2017-11-02 20:53 ` [PATCH 3/3] postmigration/memory: Associativity & ibm,dynamic-memory-v2 Michael Bringmann
2 siblings, 0 replies; 4+ messages in thread
From: Michael Bringmann @ 2017-11-02 20:53 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
Cc: Michael Ellerman, Michael Bringmann, Nathan Fontenot, John Allen,
Tyrel Datwyler, Thomas Falcon
hotplug/memory: Recognize more changes to the associativity of memory
blocks described by the 'ibm,dynamic-memory' property regarding the
topology of LPARS in Post Migration events. Previous efforts only
recognized whether a block's assignment had changed in the property.
Topology migration requires us to compare the aa_index values of the
old/new properties and 'readd' any block for which the setting has
changed.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/hotplug-cpu.c | 64 +++++++++++++++++++++++
arch/powerpc/platforms/pseries/hotplug-memory.c | 6 ++
arch/powerpc/platforms/pseries/mobility.c | 47 +++++++++++++----
arch/powerpc/platforms/pseries/pseries.h | 2 +
4 files changed, 109 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index fadb95e..d127c3a 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -634,6 +634,27 @@ static int dlpar_cpu_remove_by_index(u32 drc_index)
return rc;
}
+static int dlpar_cpu_readd_by_index(u32 drc_index)
+{
+ int rc = 0;
+
+ pr_info("Attempting to update CPU, drc index %x\n", drc_index);
+
+ if (dlpar_cpu_remove_by_index(drc_index))
+ rc = -EINVAL;
+ else if (dlpar_cpu_add(drc_index))
+ rc = -EINVAL;
+
+ if (rc)
+ pr_info("Failed to update cpu at drc_index %lx\n",
+ (unsigned long int)drc_index);
+ else
+ pr_info("CPU at drc_index %lx was updated\n",
+ (unsigned long int)drc_index);
+
+ return rc;
+}
+
static int find_dlpar_cpus_to_remove(u32 *cpu_drcs, int cpus_to_remove)
{
struct device_node *dn;
@@ -824,6 +845,9 @@ int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
else
rc = -EINVAL;
break;
+ case PSERIES_HP_ELOG_ACTION_READD:
+ rc = dlpar_cpu_readd_by_index(drc_index);
+ break;
default:
pr_err("Invalid action (%d) specified\n", hp_elog->action);
rc = -EINVAL;
@@ -874,6 +898,42 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count)
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
+static int pseries_update_drconf_cpu(struct of_reconfig_data *pr)
+{
+ u32 old_entries, new_entries;
+ __be32 *p, *old_assoc, *new_assoc;
+
+ if (strcmp(pr->dn->type, "cpu"))
+ return 0;
+
+ /* The first int of the property is the number of domains's
+ * described. This is followed by an array of level values.
+ */
+ p = (__be32 *) pr->old_prop->value;
+ if (!p)
+ return -EINVAL;
+ old_entries = be32_to_cpu(*p++);
+ old_assoc = p;
+
+ p = (__be32 *)pr->prop->value;
+ if (!p)
+ return -EINVAL;
+ new_entries = be32_to_cpu(*p++);
+ new_assoc = p;
+
+ if (old_entries == new_entries) {
+ int sz = old_entries * sizeof(int);
+
+ if (!memcmp(old_assoc, new_assoc, sz))
+ pseries_cpu_readd_by_index(pr->dn->phandle);
+
+ } else {
+ pseries_cpu_readd_by_index(pr->dn->phandle);
+ }
+
+ return 0;
+}
+
static int pseries_smp_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
@@ -887,6 +947,10 @@ static int pseries_smp_notifier(struct notifier_block *nb,
case OF_RECONFIG_DETACH_NODE:
pseries_remove_processor(rd->dn);
break;
+ case OF_RECONFIG_UPDATE_PROPERTY:
+ if (!strcmp(rd->prop->name, "ibm,associativity"))
+ err = pseries_update_drconf_cpu(rd);
+ break;
}
return notifier_from_errno(err);
}
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 1d48ab4..c61cfc6 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -1160,6 +1160,12 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
break;
+ } else if ((be32_to_cpu(old_drmem[i].aa_index) !=
+ be32_to_cpu(new_drmem[i].aa_index)) &&
+ (be32_to_cpu(new_drmem[i].flags) &
+ DRCONF_MEM_ASSIGNED)) {
+ pseries_memory_readd_by_index(
+ be32_to_cpu(new_drmem[i].drc_index));
}
}
return rc;
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index f7042ad..7c19b23 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -239,9 +239,30 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index)
return rc;
}
+static void pseries_readd_by_index(int resource, __be32 phandle)
+{
+ struct pseries_hp_errorlog hp_elog;
+
+ hp_elog.resource = resource;
+ hp_elog.action = PSERIES_HP_ELOG_ACTION_READD;
+ hp_elog.id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
+ hp_elog._drc_u.drc_index = phandle;
+
+ queue_hotplug_event(&hp_elog, NULL, NULL);
+}
+
+void pseries_memory_readd_by_index(__be32 phandle)
+{
+ pseries_readd_by_index(PSERIES_HP_ELOG_RESOURCE_MEM, phandle);
+}
+
+void pseries_cpu_readd_by_index(__be32 phandle)
+{
+ pseries_readd_by_index(PSERIES_HP_ELOG_RESOURCE_CPU, phandle);
+}
+
static void prrn_update_node(__be32 phandle)
{
- struct pseries_hp_errorlog *hp_elog;
struct device_node *dn;
/*
@@ -254,18 +275,21 @@ static void prrn_update_node(__be32 phandle)
return;
}
- hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
- if(!hp_elog)
- return;
+ pseries_memory_readd_by_index(phandle);
+}
- hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM;
- hp_elog->action = PSERIES_HP_ELOG_ACTION_READD;
- hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
- hp_elog->_drc_u.drc_index = phandle;
+static void prrn_update_node_other(s32 scope, __be32 phandle)
+{
+ struct device_node *dn;
+ __be32 drc_index = be32_to_cpu(phandle);
- queue_hotplug_event(hp_elog, NULL, NULL);
+ dn = of_find_node_by_phandle(drc_index);
+ if (dn) {
+ of_node_put(dn);
- kfree(hp_elog);
+ if (!strcmp(dn->type, "cpu"))
+ pseries_cpu_readd_by_index(phandle);
+ }
}
int pseries_devicetree_update(s32 scope)
@@ -309,6 +333,9 @@ int pseries_devicetree_update(s32 scope)
if (scope == PRRN_SCOPE)
prrn_update_node(phandle);
+ else
+ prrn_update_node_other(
+ scope, phandle);
break;
case ADD_DT_NODE:
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 4470a31..b9a69a6 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -55,6 +55,7 @@ void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog,
struct completion *hotplug_done, int *rc);
#ifdef CONFIG_MEMORY_HOTPLUG
int dlpar_memory(struct pseries_hp_errorlog *hp_elog);
+extern void pseries_memory_readd_by_index(__be32 drc_index);
#else
static inline int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
{
@@ -64,6 +65,7 @@ static inline int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
#ifdef CONFIG_HOTPLUG_CPU
int dlpar_cpu(struct pseries_hp_errorlog *hp_elog);
+extern void pseries_cpu_readd_by_index(__be32 drc_index);
#else
static inline int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
{
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] postmigration/memory: Review assoc lookup array changes
2017-11-02 20:52 [PATCH 0/3] powerpc/hotplug: Fix affinity assoc for LPAR migration Michael Bringmann
2017-11-02 20:53 ` [PATCH 1/3] hotplug/memory: Apply assoc mem updates Post Migration Topo Michael Bringmann
@ 2017-11-02 20:53 ` Michael Bringmann
2017-11-02 20:53 ` [PATCH 3/3] postmigration/memory: Associativity & ibm,dynamic-memory-v2 Michael Bringmann
2 siblings, 0 replies; 4+ messages in thread
From: Michael Bringmann @ 2017-11-02 20:53 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
Cc: Michael Ellerman, Michael Bringmann, Nathan Fontenot, John Allen,
Tyrel Datwyler, Thomas Falcon
powerpc/hotplug/memory: In an LPAR migration scenario, the property
"ibm,associativity-lookup-arrays" may change. In the event that a
row of the array differs, locate all assigned memory blocks with that
'aa_index' and 're-add' them to the system memory block data structures.
In the process of the 're-add', the appropriate entry of the property
'ibm,dynamic-memory' would be updated as well as any other applicable
system data structures.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/hotplug-memory.c | 123 +++++++++++++++++++++++
1 file changed, 121 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index c61cfc6..7aba515 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -1150,14 +1150,14 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
(!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
rc = pseries_remove_memblock(
be64_to_cpu(old_drmem[i].base_addr),
- memblock_size);
+ memblock_size);
break;
} else if ((!(be32_to_cpu(old_drmem[i].flags) &
DRCONF_MEM_ASSIGNED)) &&
(be32_to_cpu(new_drmem[i].flags) &
DRCONF_MEM_ASSIGNED)) {
rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
- memblock_size);
+ memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
break;
} else if ((be32_to_cpu(old_drmem[i].aa_index) !=
@@ -1171,6 +1171,122 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
return rc;
}
+struct assoc_arrays {
+ u32 n_arrays;
+ u32 array_sz;
+ const __be32 *arrays;
+};
+
+static int pseries_update_ala_memory_aai(int aa_index,
+ struct property *dmprop)
+{
+ struct of_drconf_cell *drmem;
+ u32 entries;
+ __be32 *p;
+ int i;
+
+ p = (__be32 *) dmprop->value;
+ if (!p)
+ return -EINVAL;
+
+ /* The first int of the property is the number of lmb's
+ * described by the property. This is followed by an array
+ * of of_drconf_cell entries. Get the number of entries
+ * and skip to the array of of_drconf_cell's.
+ */
+ entries = be32_to_cpu(*p++);
+ drmem = (struct of_drconf_cell *)p;
+
+ for (i = 0; i < entries; i++) {
+ if ((be32_to_cpu(drmem[i].aa_index) != aa_index) &&
+ (be32_to_cpu(drmem[i].flags) & DRCONF_MEM_ASSIGNED)) {
+ pseries_memory_readd_by_index(
+ be32_to_cpu(drmem[i].drc_index));
+ }
+ }
+
+ return 0;
+}
+
+static int pseries_update_ala_memory(struct of_reconfig_data *pr)
+{
+ struct assoc_arrays new_ala, old_ala;
+ struct device_node *dn;
+ struct property *dmprop;
+ __be32 *p;
+ int i, lim;
+
+ if (rtas_hp_event)
+ return 0;
+
+ dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+ if (!dn)
+ return -ENODEV;
+
+ dmprop = of_find_property(dn, "ibm,dynamic-memory", NULL);
+ if (!dmprop) {
+ of_node_put(dn);
+ return -ENODEV;
+ }
+
+ /*
+ * The layout of the ibm,associativity-lookup-arrays
+ * property is a number N indicating the number of
+ * associativity arrays, followed by a number M
+ * indicating the size of each associativity array,
+ * followed by a list of N associativity arrays.
+ */
+
+ p = (__be32 *) pr->old_prop->value;
+ if (!p) {
+ of_node_put(dn);
+ return -EINVAL;
+ }
+ old_ala.n_arrays = of_read_number(p++, 1);
+ old_ala.array_sz = of_read_number(p++, 1);
+ old_ala.arrays = p;
+
+ p = (__be32 *) pr->prop->value;
+ if (!p) {
+ of_node_put(dn);
+ return -EINVAL;
+ }
+ new_ala.n_arrays = of_read_number(p++, 1);
+ new_ala.array_sz = of_read_number(p++, 1);
+ new_ala.arrays = p;
+
+ lim = (new_ala.n_arrays > old_ala.n_arrays) ? old_ala.n_arrays :
+ new_ala.n_arrays;
+
+ if (old_ala.array_sz == new_ala.array_sz) {
+
+ for (i = 0; i < lim; i++) {
+ int index = (i * new_ala.array_sz);
+
+ if (!memcmp(&old_ala.arrays[index],
+ &new_ala.arrays[index],
+ new_ala.array_sz))
+ continue;
+
+ pseries_update_ala_memory_aai(i, dmprop);
+ }
+
+ for (i = lim; i < new_ala.n_arrays; i++)
+ pseries_update_ala_memory_aai(i, dmprop);
+
+ } else {
+ /* Update all entries representing these rows;
+ * as all rows have different sizes, none can
+ * have equivalent values.
+ */
+ for (i = 0; i < lim; i++)
+ pseries_update_ala_memory_aai(i, dmprop);
+ }
+
+ of_node_put(dn);
+ return 0;
+}
+
static int pseries_memory_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
@@ -1187,6 +1303,9 @@ static int pseries_memory_notifier(struct notifier_block *nb,
case OF_RECONFIG_UPDATE_PROPERTY:
if (!strcmp(rd->prop->name, "ibm,dynamic-memory"))
err = pseries_update_drconf_memory(rd);
+ if (!strcmp(rd->prop->name,
+ "ibm,associativity-lookup-arrays"))
+ err = pseries_update_ala_memory(rd);
break;
}
return notifier_from_errno(err);
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] postmigration/memory: Associativity & ibm,dynamic-memory-v2
2017-11-02 20:52 [PATCH 0/3] powerpc/hotplug: Fix affinity assoc for LPAR migration Michael Bringmann
2017-11-02 20:53 ` [PATCH 1/3] hotplug/memory: Apply assoc mem updates Post Migration Topo Michael Bringmann
2017-11-02 20:53 ` [PATCH 2/3] postmigration/memory: Review assoc lookup array changes Michael Bringmann
@ 2017-11-02 20:53 ` Michael Bringmann
2 siblings, 0 replies; 4+ messages in thread
From: Michael Bringmann @ 2017-11-02 20:53 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
Cc: Michael Ellerman, Michael Bringmann, Nathan Fontenot, John Allen,
Tyrel Datwyler, Thomas Falcon
powerpc/hotplug/memory: Apply changes to the associativity of memory
blocks described by the 'ibm,dynamic-memory-v2' property regarding
the topology of LPARS in Post Migration events. Previous efforts
only recognized whether a block's assignment had changed in the
property. Topology migration requires us to compare the 'aa_index'
values of the old/new properties and 'readd' any block for which the
setting has changed.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/prom.h | 12 ++
arch/powerpc/platforms/pseries/hotplug-memory.c | 175 +++++++++++++++++++++--
2 files changed, 175 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index 825bd59..e16ef0f 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -92,6 +92,18 @@ struct of_drconf_cell {
u32 flags;
};
+/* The of_drconf_cell_v2 struct defines the layout of the LMB array
+ * specified in the device tree property
+ * ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory-v2
+ */
+struct of_drconf_cell_v2 {
+ u32 num_seq_lmbs;
+ u64 base_address;
+ u32 drc_index;
+ u32 aa_index;
+ u32 flags;
+} __attribute__((packed));
+
#define DRCONF_MEM_ASSIGNED 0x00000008
#define DRCONF_MEM_AI_INVALID 0x00000040
#define DRCONF_MEM_RESERVED 0x00000080
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 7aba515..aa44011 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -1153,9 +1153,9 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
memblock_size);
break;
} else if ((!(be32_to_cpu(old_drmem[i].flags) &
- DRCONF_MEM_ASSIGNED)) &&
- (be32_to_cpu(new_drmem[i].flags) &
- DRCONF_MEM_ASSIGNED)) {
+ DRCONF_MEM_ASSIGNED)) &&
+ (be32_to_cpu(new_drmem[i].flags) &
+ DRCONF_MEM_ASSIGNED)) {
rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
@@ -1171,14 +1171,111 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
return rc;
}
+static inline int pseries_memory_v2_find_drc(u32 drc_index,
+ u64 *base_addr, unsigned long memblock_size,
+ struct of_drconf_cell_v2 **drmem,
+ struct of_drconf_cell_v2 *last_drmem)
+{
+ struct of_drconf_cell_v2 *dm = (*drmem);
+
+ while (dm < last_drmem) {
+ if ((be32_to_cpu(dm->drc_index) <= drc_index) &&
+ (drc_index <= (be32_to_cpu(dm->drc_index)+
+ be32_to_cpu(dm->num_seq_lmbs)-1))) {
+ int offset = drc_index - be32_to_cpu(dm->drc_index);
+ (*base_addr) = be64_to_cpu(dm->base_address) +
+ (offset * memblock_size);
+ break;
+ } else if (drc_index > (be32_to_cpu(dm->drc_index)+
+ be32_to_cpu(dm->num_seq_lmbs)-1)) {
+ dm++;
+ (*drmem) = dm;
+ } else if (be32_to_cpu(dm->drc_index) > drc_index) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int pseries_update_drconf_memory_v2(struct of_reconfig_data *pr)
+{
+ struct of_drconf_cell_v2 *new_drmem, *old_drmem, *last_old_drmem;
+ unsigned long memblock_size;
+ u32 new_entries, old_entries;
+ u64 old_base_addr;
+ __be32 *p;
+ int i, rc = 0;
+
+ if (rtas_hp_event)
+ return 0;
+
+ memblock_size = pseries_memory_block_size();
+ if (!memblock_size)
+ return -EINVAL;
+
+ /* The first int of the property is the number of lmb's
+ * described by the property. This is followed by an array
+ * of of_drconf_cell_v2 entries. Get the number of entries
+ * and skip to the array of of_drconf_cell_v2's.
+ */
+ p = (__be32 *) pr->old_prop->value;
+ if (!p)
+ return -EINVAL;
+ old_entries = be32_to_cpu(*p++);
+ old_drmem = (struct of_drconf_cell_v2 *)p;
+ last_old_drmem = old_drmem +
+ (sizeof(struct of_drconf_cell_v2) * old_entries);
+
+ p = (__be32 *)pr->prop->value;
+ new_entries = be32_to_cpu(*p++);
+ new_drmem = (struct of_drconf_cell_v2 *)p;
+
+ for (i = 0; i < new_entries; i++) {
+ int j;
+ u32 new_drc_index = be32_to_cpu(new_drmem->drc_index);
+
+ for (j = 0; j < new_drmem->num_seq_lmbs; j++) {
+ if (!pseries_memory_v2_find_drc(new_drc_index+j,
+ &old_base_addr,
+ memblock_size,
+ &old_drmem,
+ last_old_drmem)) {
+ if ((be32_to_cpu(old_drmem->flags) &
+ DRCONF_MEM_ASSIGNED) &&
+ (!(be32_to_cpu(new_drmem->flags) &
+ DRCONF_MEM_ASSIGNED))) {
+ rc = pseries_remove_memblock(
+ old_base_addr,
+ memblock_size);
+ } else if ((!(be32_to_cpu(old_drmem->flags) &
+ DRCONF_MEM_ASSIGNED)) &&
+ (be32_to_cpu(new_drmem->flags) &
+ DRCONF_MEM_ASSIGNED)) {
+ rc = memblock_add(
+ old_base_addr, memblock_size);
+ } else if ((be32_to_cpu(old_drmem->aa_index) !=
+ be32_to_cpu(new_drmem->aa_index)) &&
+ (be32_to_cpu(new_drmem->flags) &
+ DRCONF_MEM_ASSIGNED)) {
+ pseries_memory_readd_by_index(
+ new_drc_index+j);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
struct assoc_arrays {
u32 n_arrays;
u32 array_sz;
const __be32 *arrays;
};
-static int pseries_update_ala_memory_aai(int aa_index,
- struct property *dmprop)
+static int pseries_update_ala_memory_aai_v1(int aa_index,
+ struct property *dmprop)
{
struct of_drconf_cell *drmem;
u32 entries;
@@ -1208,11 +1305,47 @@ static int pseries_update_ala_memory_aai(int aa_index,
return 0;
}
+static int pseries_update_ala_memory_aai_v2(int aa_index,
+ struct property *dmprop)
+{
+ struct of_drconf_cell_v2 *drmem;
+ u32 entries;
+ __be32 *p;
+ int i;
+
+ p = (__be32 *) dmprop->value;
+ if (!p)
+ return -EINVAL;
+
+ /* The first int of the property is the number of lmb's
+ * described by the property. This is followed by an array
+ * of of_drconf_cell_v2 entries. Get the number of entries
+ * and skip to the array of of_drconf_cell_v2's.
+ */
+ entries = be32_to_cpu(*p++);
+ drmem = (struct of_drconf_cell_v2 *)p;
+
+ for (i = 0; i < entries; i++) {
+ if ((be32_to_cpu(drmem[i].aa_index) != aa_index) &&
+ (be32_to_cpu(drmem[i].flags) & DRCONF_MEM_ASSIGNED)) {
+ int j;
+ int lim = be32_to_cpu(drmem->num_seq_lmbs);
+ u32 drc_index = be32_to_cpu(drmem->drc_index);
+
+ for (j = 0; j < lim; j++)
+ pseries_memory_readd_by_index(drc_index+j);
+ }
+ }
+
+ return 0;
+}
+
static int pseries_update_ala_memory(struct of_reconfig_data *pr)
{
struct assoc_arrays new_ala, old_ala;
struct device_node *dn;
struct property *dmprop;
+ bool v1 = true;
__be32 *p;
int i, lim;
@@ -1225,8 +1358,13 @@ static int pseries_update_ala_memory(struct of_reconfig_data *pr)
dmprop = of_find_property(dn, "ibm,dynamic-memory", NULL);
if (!dmprop) {
- of_node_put(dn);
- return -ENODEV;
+ v1 = false;
+ dmprop = of_find_property(dn, "ibm,dynamic-memory-v2",
+ NULL);
+ if (!dmprop) {
+ of_node_put(dn);
+ return -ENODEV;
+ }
}
/*
@@ -1268,19 +1406,30 @@ static int pseries_update_ala_memory(struct of_reconfig_data *pr)
new_ala.array_sz))
continue;
- pseries_update_ala_memory_aai(i, dmprop);
+ if (v1)
+ pseries_update_ala_memory_aai_v1(i, dmprop);
+ else
+ pseries_update_ala_memory_aai_v2(i, dmprop);
}
- for (i = lim; i < new_ala.n_arrays; i++)
- pseries_update_ala_memory_aai(i, dmprop);
+ for (i = lim; i < new_ala.n_arrays; i++) {
+ if (v1)
+ pseries_update_ala_memory_aai_v1(i, dmprop);
+ else
+ pseries_update_ala_memory_aai_v2(i, dmprop);
+ }
} else {
/* Update all entries representing these rows;
* as all rows have different sizes, none can
* have equivalent values.
*/
- for (i = 0; i < lim; i++)
- pseries_update_ala_memory_aai(i, dmprop);
+ for (i = 0; i < lim; i++) {
+ if (v1)
+ pseries_update_ala_memory_aai_v1(i, dmprop);
+ else
+ pseries_update_ala_memory_aai_v2(i, dmprop);
+ }
}
of_node_put(dn);
@@ -1303,6 +1452,8 @@ static int pseries_memory_notifier(struct notifier_block *nb,
case OF_RECONFIG_UPDATE_PROPERTY:
if (!strcmp(rd->prop->name, "ibm,dynamic-memory"))
err = pseries_update_drconf_memory(rd);
+ if (!strcmp(rd->prop->name, "ibm,dynamic-memory-v2"))
+ err = pseries_update_drconf_memory_v2(rd);
if (!strcmp(rd->prop->name,
"ibm,associativity-lookup-arrays"))
err = pseries_update_ala_memory(rd);
^ permalink raw reply related [flat|nested] 4+ messages in thread