All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nathan Fontenot <nfont@linux.vnet.ibm.com>
To: linuxppc-dev@lists.ozlabs.org
Subject: [PATCH v2 7/8] powerpc/pseries: Add support for ibm, dynamic-memory-v2 property
Date: Fri, 20 Oct 2017 08:22:30 -0500	[thread overview]
Message-ID: <150850575007.9118.17716980650930524298.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com> (raw)
In-Reply-To: <150850568437.9118.13945089249591962212.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com>

The Power Hypervisor has introduced a new device tree format for
the property describing the dynamic reconfiguration LMBs for a system.
This new format condenses the size of the property, especially
on large memory systems.

Instead of the current format that contains an entry for every
possible LMB, the new format contains an entry for every range
of LMBs that possess the same flags and associativity index.

This patch updates the powerpc/mm/drmem.c code to parse the new
property format at boot and create the LMB array. This also updates
the device tree updating routine to build a device tree property
in this format.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/drmem.h |   12 ++
 arch/powerpc/mm/drmem.c          |  188 ++++++++++++++++++++++++++++++++++----
 2 files changed, 182 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h
index 32d859c84202..b7becafc528d 100644
--- a/arch/powerpc/include/asm/drmem.h
+++ b/arch/powerpc/include/asm/drmem.h
@@ -49,6 +49,18 @@ struct of_drconf_cell_v1 {
 	u32     flags;
 };
 
+/* Version 2 of the ibm,dynamic-memory property is defined as a
+ * 32-bit value specifying the number of LMB sets followed by an
+ * array of of_drconf_cell_v2 entries, one per LMB set.
+ */
+struct of_drconf_cell_v2 {
+	u32	seq_lmbs;
+	u64	base_addr;
+	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/mm/drmem.c b/arch/powerpc/mm/drmem.c
index 9cd9e680874e..b5b8b8f46292 100644
--- a/arch/powerpc/mm/drmem.c
+++ b/arch/powerpc/mm/drmem.c
@@ -21,25 +21,13 @@
 static struct drmem_lmb_info __drmem_info;
 struct drmem_lmb_info *drmem_info = &__drmem_info;
 
-int __init init_drmem_lmbs(unsigned long node)
+static int __init init_drmem_lmbs_v1(const __be32 *prop, u32 len)
 {
 	struct drmem_lmb *lmb;
-	const __be32 *prop;
-	int prop_sz;
-	u32 len;
-
-	prop = of_get_flat_dt_prop(node, "ibm,lmb-size", &len);
-	if (!prop || len < dt_root_size_cells * sizeof(__be32))
-		return -1;
-
-	drmem_info->lmb_size = dt_mem_next_cell(dt_root_size_cells, &prop);
-
-	prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &len);
-	if (!prop || len < dt_root_size_cells * sizeof(__be32))
-		return -1;
+	u32 prop_sz;
 
 	drmem_info->n_lmbs = of_read_number(prop++, 1);
-	prop_sz = drmem_info->n_lmbs * sizeof(struct of_drconf_cell)
+	prop_sz = drmem_info->n_lmbs * sizeof(struct of_drconf_cell_v1)
 		  + sizeof(__be32);
 	if (prop_sz < len)
 		return -1;
@@ -61,6 +49,89 @@ int __init init_drmem_lmbs(unsigned long node)
 	return 0;
 }
 
+static void read_one_drconf_v2_cell(const __be32 **cell,
+				    struct of_drconf_cell_v2 *dr_cell)
+{
+	const __be32 *p = *cell;
+
+	dr_cell->seq_lmbs = of_read_number(p++, 1);
+	dr_cell->base_addr = dt_mem_next_cell(dt_root_addr_cells, &p);
+	dr_cell->drc_index = of_read_number(p++, 1);
+	dr_cell->aa_index = of_read_number(p++, 1);
+	dr_cell->flags = of_read_number(p++, 1);
+
+	*cell = p;
+}
+
+static int __init init_drmem_lmbs_v2(const __be32 *prop, u32 len)
+{
+	struct drmem_lmb *lmb;
+	struct of_drconf_cell_v2 dr_cell;
+	const __be32 *p;
+	u32 lmb_sets, prop_sz;
+	int i, j, lmb_index;
+
+	lmb_sets = of_read_number(prop++, 1);
+	prop_sz = lmb_sets * sizeof(struct of_drconf_cell_v2)
+		  + sizeof(__be32);
+	if (prop_sz < len)
+		return -1;
+
+	/* first pass, calculate the number of LMBs */
+	p = prop;
+	for (i = 0; i < lmb_sets; i++) {
+		read_one_drconf_v2_cell(&p, &dr_cell);
+		drmem_info->n_lmbs += dr_cell.seq_lmbs;
+	}
+
+	drmem_info->lmbs = alloc_bootmem(drmem_info->n_lmbs * sizeof(*lmb));
+	if (!drmem_info->lmbs)
+		return -1;
+
+	lmb_index = 0;
+	p = prop;
+	for (i = 0; i < lmb_sets; i++) {
+		read_one_drconf_v2_cell(&p, &dr_cell);
+
+		for (j = 0; j < dr_cell.seq_lmbs; j++) {
+			lmb = &drmem_info->lmbs[lmb_index++];
+
+			lmb->base_addr = dr_cell.base_addr;
+			dr_cell.base_addr += drmem_info->lmb_size;
+
+			lmb->drc_index = dr_cell.drc_index;
+			dr_cell.drc_index++;
+
+			lmb->aa_index = dr_cell.aa_index;
+			lmb->flags = dr_cell.flags;
+		}
+	}
+
+	return 0;
+}
+
+int __init init_drmem_lmbs(unsigned long node)
+{
+	const __be32 *prop;
+	u32 len;
+
+	prop = of_get_flat_dt_prop(node, "ibm,lmb-size", &len);
+	if (!prop || len < dt_root_size_cells * sizeof(__be32))
+		return -1;
+
+	drmem_info->lmb_size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+	prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &len);
+	if (prop)
+		return init_drmem_lmbs_v1(prop, len);
+
+	prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory-v2", &len);
+	if (prop)
+		return init_drmem_lmbs_v2(prop, len);
+
+	return -1;
+}
+
 u64 drmem_lmb_memory_max(void)
 {
 	struct drmem_lmb *last_lmb;
@@ -130,6 +201,82 @@ static int drmem_update_dt_v1(struct device_node *memory,
 	return 0;
 }
 
+static void init_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell,
+				struct drmem_lmb *lmb)
+{
+	dr_cell->base_addr = cpu_to_be64(lmb->base_addr);
+	dr_cell->drc_index = cpu_to_be32(lmb->drc_index);
+	dr_cell->aa_index = cpu_to_be32(lmb->aa_index);
+	dr_cell->flags = cpu_to_be32(lmb->flags);
+}
+
+static int drmem_update_dt_v2(struct device_node *memory,
+			      struct property *prop)
+{
+	struct property *new_prop;
+	struct of_drconf_cell_v2 *dr_cell;
+	struct drmem_lmb *lmb, *prev_lmb;
+	u32 lmb_sets, prop_sz, seq_lmbs;
+	u32 *p;
+
+	lmb_sets = 0;
+	prev_lmb = NULL;
+	for_each_drmem_lmb(lmb) {
+		if (!prev_lmb) {
+			prev_lmb = lmb;
+			lmb_sets++;
+			continue;
+		}
+
+		if (prev_lmb->aa_index != lmb->aa_index ||
+		    prev_lmb->flags != drmem_lmb_flags(lmb))
+			lmb_sets++;
+
+		prev_lmb = lmb;
+	}
+
+	prop_sz = lmb_sets * sizeof(*dr_cell) + sizeof(__be32);
+	new_prop = clone_property(prop, prop_sz);
+	if (!new_prop)
+		return -1;
+
+	p = new_prop->value;
+	*p++ = cpu_to_be32(lmb_sets);
+
+	dr_cell = (struct of_drconf_cell_v2 *)p;
+
+	prev_lmb = NULL;
+	seq_lmbs = 0;
+	for_each_drmem_lmb(lmb) {
+		if (prev_lmb == NULL) {
+			/* Start of first set */
+			prev_lmb = lmb;
+			init_drconf_v2_cell(dr_cell, lmb);
+			seq_lmbs++;
+			continue;
+		}
+
+		if (prev_lmb->aa_index != lmb->aa_index ||
+		    prev_lmb->flags != drmem_lmb_flags(lmb)) {
+			/* end of one set, start of another */
+			dr_cell->seq_lmbs = cpu_to_be32(seq_lmbs);
+			dr_cell++;
+
+			init_drconf_v2_cell(dr_cell, lmb);
+			seq_lmbs = 1;
+		} else {
+			seq_lmbs++;
+		}
+
+		prev_lmb = lmb;
+	}
+
+	/* close out last dr_cell */
+	dr_cell->seq_lmbs = cpu_to_be32(seq_lmbs);
+	of_update_property(memory, new_prop);
+	return 0;
+}
+
 int drmem_update_dt(void)
 {
 	struct device_node *memory;
@@ -141,10 +288,15 @@ int drmem_update_dt(void)
 		return -1;
 
 	prop = of_find_property(memory, "ibm,dynamic-memory", NULL);
-	if (prop)
+	if (prop) {
 		rc = drmem_update_dt_v1(memory, prop);
-	else
-		rc = -1;
+	} else {
+		prop = of_find_property(memory, "ibm,dynamic-memory-v2", NULL);
+		if (prop)
+			rc = drmem_update_dt_v2(memory, prop);
+		else
+			rc = -1;
+	}
 
 	of_node_put(memory);
 	return rc;

  parent reply	other threads:[~2017-10-20 13:37 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-20 13:21 [PATCH v2 0/8] powerpc: Support ibm,dynamic-memory-v2 property Nathan Fontenot
2017-10-20 13:21 ` [PATCH v2 1/8] powerpc/numa: Look up device node in of_get_assoc_arrays() Nathan Fontenot
2017-10-20 13:22 ` [PATCH v2 2/8] powerpc/numa: Look up device node in of_get_usable_memory() Nathan Fontenot
2017-10-20 13:22 ` [PATCH v2 3/8] powerpc/mm: Separate ibm, dynamic-memory data from DT format Nathan Fontenot
2017-10-24  6:08   ` Michael Ellerman
2017-10-24 20:33     ` Nathan Fontenot
2017-10-25  9:16       ` Michael Ellerman
2017-11-12 12:43   ` Michael Ellerman
2017-11-13 14:51     ` Nathan Fontenot
2017-11-14 10:25       ` Michael Ellerman
2017-10-20 13:22 ` [PATCH v2 4/8] powerpc/numa: Update numa code use drmem LMB array Nathan Fontenot
2017-10-20 13:22 ` [PATCH v2 5/8] powerpc/pseries: Update memory hotplug code to " Nathan Fontenot
2017-10-20 13:22 ` [PATCH v2 6/8] powerpc: Move of_drconf_cell struct to asm/drmem.h Nathan Fontenot
2017-10-20 13:22 ` Nathan Fontenot [this message]
2017-10-20 13:22 ` [PATCH v2 8/8] powerpc: Enable support of ibm,dynamic-memory-v2 Nathan Fontenot
2017-11-16  5:37 ` [PATCH v2 0/8] powerpc: Support ibm,dynamic-memory-v2 property Bharata B Rao
2017-11-16 16:01   ` Nathan Fontenot
2017-11-17  4:51     ` Bharata B Rao
2017-11-20 14:48       ` Nathan Fontenot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=150850575007.9118.17716980650930524298.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com \
    --to=nfont@linux.vnet.ibm.com \
    --cc=linuxppc-dev@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.