All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] powerpc/devtree: Add support for 'ibm, dynamic-memory-v2' property
@ 2017-04-12 18:36 Michael Bringmann
  2017-04-12 18:36 ` [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features, [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features Michael Bringmann
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Michael Bringmann @ 2017-04-12 18:36 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev

"ibm,dynamic-memory-v2": This property replaces the "ibm,dynamic-memory"
node representation within the "ibm,dynamic-reconfiguration-memory"
property provided by the BMC.  This element format is intended to provide
a more compact representation of memory, especially, for systems with
massive amounts of RAM.  To simplify portability, this property is
converted to the "ibm,dynamic-memory" property during system boot.

"ibm,architecture.vec": Bidirectional communication mechanism between
the host system and the front end processor indicating what features
the host system supports and what features the front end processor will
actually provide.  In this case, we are indicating that the host system
can support the new device tree structure "ibm,dynamic-memory-v2".

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>

Michael Bringmann (5):
  powerpc: Check arch.vec earlier during boot for memory features
  powerpc/memory: Parse new memory property to register blocks.
  powerpc/memory: Parse new memory property to initialize structures.
  pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  powerpc: Enable support for new 'ibm,dynamic-memory-v2' devtree property

 arch/powerpc/include/asm/firmware.h             |    4 
 arch/powerpc/include/asm/prom.h                 |   33 +++-
 arch/powerpc/kernel/prom.c                      |  131 +++++++++++---
 arch/powerpc/kernel/prom_init.c                 |    2 
 arch/powerpc/mm/numa.c                          |  213 ++++++++++++++++++-----
 arch/powerpc/platforms/pseries/Makefile         |    4 
 arch/powerpc/platforms/pseries/firmware.c       |    1 
 arch/powerpc/platforms/pseries/hotplug-memory.c |   96 ++++++++++
 8 files changed, 398 insertions(+), 86 deletions(-)

--

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features, [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features
  2017-04-12 18:36 [PATCH 0/5] powerpc/devtree: Add support for 'ibm, dynamic-memory-v2' property Michael Bringmann
@ 2017-04-12 18:36 ` Michael Bringmann
  2017-04-12 18:36 ` [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks., [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks Michael Bringmann
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Michael Bringmann @ 2017-04-12 18:36 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

architecture.vec5 features: The boot-time memory management needs to
know the form of the "ibm,dynamic-memory-v2" property early during
scanning of the flattened device tree.  This patch moves execution of
the function pseries_probe_fw_features() early enough to be before
the scanning of the memory properties in the device tree to allow
recognition of the supported properties.

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/prom.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f5d399e..bca4abd 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -679,6 +679,9 @@ void __init early_init_devtree(void *params)
 	 */
 	of_scan_flat_dt(early_init_dt_scan_chosen_ppc, boot_command_line);
 
+	/* Now try to figure out if we are running on LPAR and so on */
+	pseries_probe_fw_features();
+
 	/* Scan memory nodes and rebuild MEMBLOCKs */
 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
@@ -746,9 +749,6 @@ void __init early_init_devtree(void *params)
 #endif
 	epapr_paravirt_early_init();
 
-	/* Now try to figure out if we are running on LPAR and so on */
-	pseries_probe_fw_features();
-
 #ifdef CONFIG_PPC_PS3
 	/* Identify PS3 firmware */
 	if (of_flat_dt_is_compatible(of_get_flat_dt_root(), "sony,ps3"))

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks., [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks.
  2017-04-12 18:36 [PATCH 0/5] powerpc/devtree: Add support for 'ibm, dynamic-memory-v2' property Michael Bringmann
  2017-04-12 18:36 ` [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features, [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features Michael Bringmann
@ 2017-04-12 18:36 ` Michael Bringmann
  2017-04-12 18:37 ` [PATCH 3/5] powerpc/memory: Parse new memory property to initialize structures Michael Bringmann
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Michael Bringmann @ 2017-04-12 18:36 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

powerpc/memory: Add parallel routines to parse the new property
"ibm,dynamic-memory-v2" property when it is present, and then to
register the relevant memory blocks with the operating system.
This property format is intended to provide a more compact
representation of memory when communicating with the front end
processor, especially when describing vast amounts of RAM.

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/firmware.h       |    4 +
 arch/powerpc/include/asm/prom.h           |   25 +++++-
 arch/powerpc/kernel/prom.c                |  125 ++++++++++++++++++++++++-----
 arch/powerpc/mm/numa.c                    |   20 ++++-
 arch/powerpc/platforms/pseries/firmware.c |    1 
 5 files changed, 146 insertions(+), 29 deletions(-)

diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
index 329d537..062e5f5 100644
--- a/arch/powerpc/include/asm/firmware.h
+++ b/arch/powerpc/include/asm/firmware.h
@@ -52,6 +52,7 @@
 #define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
 #define FW_FEATURE_PRRN		ASM_CONST(0x0000000200000000)
 #define FW_FEATURE_DRC_INFO	ASM_CONST(0x0000000400000000)
+#define FW_FEATURE_DYN_MEM_V2	ASM_CONST(0x0000000800000000)
 
 #ifndef __ASSEMBLY__
 
@@ -68,7 +69,8 @@ enum {
 		FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO |
 		FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY |
 		FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN |
-		FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRC_INFO,
+		FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRC_INFO |
+		FW_FEATURE_DYN_MEM_V2,
 	FW_FEATURE_PSERIES_ALWAYS = 0,
 	FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL,
 	FW_FEATURE_POWERNV_ALWAYS = 0,
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index d469d7c..77d76d8 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -69,6 +69,8 @@ struct boot_param_header {
  * OF address retreival & translation
  */
 
+extern int n_mem_addr_cells;
+
 /* Parse the ibm,dma-window property of an OF node into the busno, phys and
  * size parameters.
  */
@@ -81,8 +83,9 @@ void of_parse_dma_window(struct device_node *dn, const __be32 *dma_window,
 extern int of_get_ibm_chip_id(struct device_node *np);
 
 /* The of_drconf_cell struct defines the layout of the LMB array
- * specified in the device tree property
- * ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
+ * specified in the device tree properties,
+ *     ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
+ *     ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory-v2
  */
 struct of_drconf_cell {
 	u64	base_addr;
@@ -92,9 +95,20 @@ struct of_drconf_cell {
 	u32	flags;
 };
 
-#define DRCONF_MEM_ASSIGNED	0x00000008
-#define DRCONF_MEM_AI_INVALID	0x00000040
-#define DRCONF_MEM_RESERVED	0x00000080
+#define DRCONF_MEM_ASSIGNED		0x00000008
+#define DRCONF_MEM_AI_INVALID		0x00000040
+#define DRCONF_MEM_RESERVED		0x00000080
+
+struct of_drconf_cell_v2 {
+	u32	num_seq_lmbs;
+	u64	base_addr;
+	u32	drc_index;
+	u32	aa_index;
+	u32	flags;
+} __attribute__((packed));
+
+extern void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem,
+				const __be32 **cellp);
 
 extern int of_one_drc_info(struct property **prop, void **curval,
 			char **dtype, char **dname,
@@ -180,6 +194,7 @@ extern int of_one_drc_info(struct property **prop, void **curval,
 /* Radix Table Extensions */
 #define OV5_RADIX_GTSE		0x1A40	/* Guest Translation Shoot Down Avail */
 #define OV5_DRC_INFO		0x1640	/* Redef Prop Structures: drc-info   */
+#define OV5_DYN_MEM_V2		0x1680	/* Redef Prop Structures: dyn-mem-v2   */
 
 /* Option Vector 6: IBM PAPR hints */
 #define OV6_LINUX		0x02	/* Linux is our OS */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index bca4abd..1bc0a36 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -76,6 +76,21 @@
 static phys_addr_t first_memblock_size;
 static int __initdata boot_cpu_count;
 
+#ifdef	CONFIG_PPC64
+static int if_iommu_is_off(u64 base, u64 *size)
+{
+	if (iommu_is_off) {
+		if (base >= 0x80000000ul)
+			return 1;
+		if ((base + (*size)) > 0x80000000ul)
+			(*size) = 0x80000000ul - base;
+	}
+	return 0;
+}
+#else
+#define	if_iommu_is_off(base, size)	0
+#endif
+
 static int __init early_parse_mem(char *p)
 {
 	if (!p)
@@ -444,23 +459,34 @@ static int __init early_init_dt_scan_chosen_ppc(unsigned long node,
 
 #ifdef CONFIG_PPC_PSERIES
 /*
- * Interpret the ibm,dynamic-memory property in the
- * /ibm,dynamic-reconfiguration-memory node.
+ * Retrieve and validate the ibm,lmb-size property for drconf memory
+ * from the flattened device tree.
+ */
+static u64 __init get_lmb_size(unsigned long node)
+{
+	const __be32 *ls;
+	int len;
+	ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &len);
+	if (!ls || len < dt_root_size_cells * sizeof(__be32))
+		return 0;
+	return dt_mem_next_cell(dt_root_size_cells, &ls);
+}
+
+/*
+ * Interpret the ibm,dynamic-memory property/ibm,dynamic-memory-v2
+ * in the /ibm,dynamic-reconfiguration-memory node.
  * This contains a list of memory blocks along with NUMA affinity
  * information.
  */
-static int __init early_init_dt_scan_drconf_memory(unsigned long node)
+static int __init early_init_dt_scan_drconf_memory_v1(unsigned long node)
 {
-	const __be32 *dm, *ls, *usm;
+	const __be32 *dm, *usm;
 	int l;
 	unsigned long n, flags;
 	u64 base, size, memblock_size;
 	unsigned int is_kexec_kdump = 0, rngs;
 
-	ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
-	if (ls == NULL || l < dt_root_size_cells * sizeof(__be32))
-		return 0;
-	memblock_size = dt_mem_next_cell(dt_root_size_cells, &ls);
+	memblock_size = get_lmb_size(node);
 
 	dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
 	if (dm == NULL || l < sizeof(__be32))
@@ -507,18 +533,78 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
 				size = dt_mem_next_cell(dt_root_size_cells,
 							 &usm);
 			}
-			if (iommu_is_off) {
-				if (base >= 0x80000000ul)
-					continue;
-				if ((base + size) > 0x80000000ul)
-					size = 0x80000000ul - base;
-			}
+			if (if_iommu_is_off(base, &size))
+				continue;
 			memblock_add(base, size);
 		} while (--rngs);
 	}
 	memblock_dump_all();
 	return 0;
 }
+
+static int __init early_init_dt_scan_drconf_memory_v2(unsigned long node)
+{
+	const __be32 *dm;
+	int l;
+	unsigned long num_sets;
+	u64 size, base, memblock_size;
+
+	memblock_size = get_lmb_size(node);
+
+	dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory-v2", &l);
+	if (dm == NULL || l < sizeof(__be32))
+		return 0;
+
+	/* Verify expected length of the array of ibm,dynamic-memory-v2
+	 * structs fits in the actual size of the property data.
+	 */
+	num_sets = of_read_number(dm++, 1);
+	if (l < (num_sets * (dt_root_addr_cells + 4) + 1) * sizeof(__be32))
+		return 0;
+
+	if (n_mem_addr_cells == 0)
+		n_mem_addr_cells = dt_root_addr_cells;
+
+	for (; num_sets != 0; --num_sets) {
+		struct of_drconf_cell_v2 drmem;
+		unsigned long nsl;
+
+		read_drconf_cell_v2(&drmem, &dm);
+		base = drmem.base_addr;
+		nsl = drmem.num_seq_lmbs;
+		size = memblock_size;
+
+		/* SKip this block if the reserved bit is set in flags
+		 * or if the block is not assigned to this partition
+		 */
+		if ((drmem.flags & DRCONF_MEM_RESERVED) ||
+		    !(drmem.flags & DRCONF_MEM_ASSIGNED))
+			continue;
+
+		for (; nsl != 0; nsl--) {
+			size = memblock_size;
+			if (if_iommu_is_off(base, &size))
+				continue;
+			memblock_add(base, size);
+			base += size;
+		}
+	}
+
+	memblock_dump_all();
+	return 0;
+}
+
+static int __init early_init_dt_scan_drconf_memory(unsigned long node)
+{
+	const __be32 *dm;
+	int l;
+	dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory-v2", &l);
+	if (dm == NULL || l < sizeof(__be32))
+		return early_init_dt_scan_drconf_memory_v1(node);
+	else
+		return early_init_dt_scan_drconf_memory_v2(node);
+}
+
 #else
 #define early_init_dt_scan_drconf_memory(node)	0
 #endif /* CONFIG_PPC_PSERIES */
@@ -550,14 +636,9 @@ static int __init early_init_dt_scan_memory_ppc(unsigned long node,
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
-#ifdef CONFIG_PPC64
-	if (iommu_is_off) {
-		if (base >= 0x80000000ul)
-			return;
-		if ((base + size) > 0x80000000ul)
-			size = 0x80000000ul - base;
-	}
-#endif
+	if (if_iommu_is_off(base, &size))
+		return;
+
 	/* Keep track of the beginning of memory -and- the size of
 	 * the very first block in the device-tree as it represents
 	 * the RMA on ppc64 server
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 9befaee..4fdc5ff 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -57,7 +57,8 @@
 EXPORT_SYMBOL(node_data);
 
 static int min_common_depth;
-static int n_mem_addr_cells, n_mem_size_cells;
+int n_mem_addr_cells;
+static int n_mem_size_cells;
 static int form1_affinity;
 
 #define MAX_DISTANCE_REF_POINTS 4
@@ -405,6 +406,23 @@ static void read_drconf_cell(struct of_drconf_cell *drmem, const __be32 **cellp)
 
 	*cellp = cp + 4;
 }
+ 
+ /*
+ * Retrieve and validate the ibm,dynamic-memory property of the device tree.
+ * Read the next memory block set entry from the ibm,dynamic-memory-v2 property
+ * and return the information in the provided of_drconf_cell_v2 structure.
+ */
+void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem, const __be32 **cellp)
+{
+	const __be32 *cp = (const __be32 *)*cellp;
+	drmem->num_seq_lmbs = be32_to_cpu(*cp++);
+	drmem->base_addr = read_n_cells(n_mem_addr_cells, &cp);
+	drmem->drc_index = be32_to_cpu(*cp++);
+	drmem->aa_index = be32_to_cpu(*cp++);
+	drmem->flags = be32_to_cpu(*cp++);
+
+	*cellp = cp;
+}
 
 /*
  * Retrieve and validate the ibm,dynamic-memory property of the device tree.
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 757d757..eb688ae 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -115,6 +115,7 @@ struct vec5_fw_feature {
 	{FW_FEATURE_TYPE1_AFFINITY,	OV5_TYPE1_AFFINITY},
 	{FW_FEATURE_PRRN,		OV5_PRRN},
 	{FW_FEATURE_DRC_INFO,		OV5_DRC_INFO},
+	{FW_FEATURE_DYN_MEM_V2,		OV5_DYN_MEM_V2},
 };
 
 static void __init fw_vec5_feature_init(const char *vec5, unsigned long len)

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] powerpc/memory: Parse new memory property to initialize structures.
  2017-04-12 18:36 [PATCH 0/5] powerpc/devtree: Add support for 'ibm, dynamic-memory-v2' property Michael Bringmann
  2017-04-12 18:36 ` [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features, [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features Michael Bringmann
  2017-04-12 18:36 ` [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks., [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks Michael Bringmann
@ 2017-04-12 18:37 ` Michael Bringmann
  2017-04-12 18:37 ` [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
  2017-04-12 18:37 ` [PATCH 5/5] powerpc: Enable support for new 'ibm, dynamic-memory-v2' devtree property Michael Bringmann
  4 siblings, 0 replies; 8+ messages in thread
From: Michael Bringmann @ 2017-04-12 18:37 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

powerpc/memory: Add parallel routines to parse the new property
"ibm,dynamic-memory-v2" property when it is present, and then to
finish initialization of the relevant memory structures with the
operating system.  This code is shared between the boot-time
initialization functions and the runtime functions for memory
hotplug, so it needs to be able to handle both formats.

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/prom.h |    8 ++
 arch/powerpc/mm/numa.c          |  193 +++++++++++++++++++++++++++++----------
 2 files changed, 152 insertions(+), 49 deletions(-)

diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index 77d76d8..b919c1e 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -117,6 +117,14 @@ extern int of_one_drc_info(struct property **prop, void **curval,
 			u32 *sequential_inc_p,
 			u32 *last_drc_index_p);
 
+static inline int dyn_mem_v2_len(int entries)
+{
+	/* Calculate for counter + number of cells that follow */
+	int drconf_v2_cells = (n_mem_addr_cells + 4);
+	int drconf_v2_cells_len = (drconf_v2_cells * sizeof(unsigned int));
+	return (((entries) * drconf_v2_cells_len) + sizeof(unsigned int));
+}
+
 /*
  * There are two methods for telling firmware what our capabilities are.
  * Newer machines have an "ibm,client-architecture-support" method on the
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 4fdc5ff..b035a8a 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -425,30 +425,55 @@ void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem, const __be32 **cellp)
 }
 
 /*
- * Retrieve and validate the ibm,dynamic-memory property of the device tree.
+ * Retrieve and validate the ibm,dynamic-memory[-v2] property of the
+ * device tree.
+ *
+ * The layout of the ibm,dynamic-memory property is a number N of memory
+ * block description list entries followed by N memory block description
+ * list entries.  Each memory block description list entry contains
+ * information as laid out in the of_drconf_cell struct above.
  *
- * The layout of the ibm,dynamic-memory property is a number N of memblock
- * list entries followed by N memblock list entries.  Each memblock list entry
- * contains information as laid out in the of_drconf_cell struct above.
+ * The layout of the ibm,dynamic-memory-v2 property is a number N of memory
+ * block set description list entries, followed by N memory block set
+ * description set entries.
  */
 static int of_get_drconf_memory(struct device_node *memory, const __be32 **dm)
 {
 	const __be32 *prop;
 	u32 len, entries;
 
-	prop = of_get_property(memory, "ibm,dynamic-memory", &len);
-	if (!prop || len < sizeof(unsigned int))
-		return 0;
+	if (firmware_has_feature(FW_FEATURE_DYN_MEM_V2)) {
 
-	entries = of_read_number(prop++, 1);
+		prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len);
+		if (!prop || len < sizeof(unsigned int))
+			return 0;
 
-	/* Now that we know the number of entries, revalidate the size
-	 * of the property read in to ensure we have everything
-	 */
-	if (len < (entries * (n_mem_addr_cells + 4) + 1) * sizeof(unsigned int))
-		return 0;
+		entries = of_read_number(prop++, 1);
+
+		/* Now that we know the number of set entries, revalidate the
+		 * size of the property read in to ensure we have everything.
+		 */
+		if (len < dyn_mem_v2_len(entries))
+			return 0;
+
+		*dm = prop;
+	} else {
+		prop = of_get_property(memory, "ibm,dynamic-memory", &len);
+		if (!prop || len < sizeof(unsigned int))
+			return 0;
+
+		entries = of_read_number(prop++, 1);
+
+		/* Now that we know the number of entries, revalidate the size
+		 * of the property read in to ensure we have everything
+		 */
+		if (len < (entries * (n_mem_addr_cells + 4) + 1) *
+			   sizeof(unsigned int))
+			return 0;
+
+		*dm = prop;
+	}
 
-	*dm = prop;
 	return entries;
 }
 
@@ -511,7 +536,7 @@ static int of_get_assoc_arrays(struct device_node *memory,
  * This is like of_node_to_nid_single() for memory represented in the
  * ibm,dynamic-reconfiguration-memory node.
  */
-static int of_drconf_to_nid_single(struct of_drconf_cell *drmem,
+static int of_drconf_to_nid_single(u32 drmem_flags, u32 drmem_aa_index,
 				   struct assoc_arrays *aa)
 {
 	int default_nid = 0;
@@ -519,16 +544,16 @@ static int of_drconf_to_nid_single(struct of_drconf_cell *drmem,
 	int index;
 
 	if (min_common_depth > 0 && min_common_depth <= aa->array_sz &&
-	    !(drmem->flags & DRCONF_MEM_AI_INVALID) &&
-	    drmem->aa_index < aa->n_arrays) {
-		index = drmem->aa_index * aa->array_sz + min_common_depth - 1;
+	    !(drmem_flags & DRCONF_MEM_AI_INVALID) &&
+	    drmem_aa_index < aa->n_arrays) {
+		index = drmem_aa_index * aa->array_sz + min_common_depth - 1;
 		nid = of_read_number(&aa->arrays[index], 1);
 
 		if (nid == 0xffff || nid >= MAX_NUMNODES)
 			nid = default_nid;
 
 		if (nid > 0) {
-			index = drmem->aa_index * aa->array_sz;
+			index = drmem_aa_index * aa->array_sz;
 			initialize_distance_lookup_table(nid,
 							&aa->arrays[index]);
 		}
@@ -660,28 +685,37 @@ static inline int __init read_usm_ranges(const __be32 **usm)
 }
 
 /*
+ * Support routine for parse_drconf_memory_[v1/v2]
+ */
+static unsigned long __init parse_drconf_memory_common(u32 flags,
+			u32 aa_index, struct assoc_arrays *aa,
+			unsigned long base, unsigned long size)
+{
+	unsigned int nid;
+	unsigned long sz;
+
+	nid = of_drconf_to_nid_single(flags, aa_index, aa);
+	fake_numa_create_new_node(((base + size) >> PAGE_SHIFT),
+				&nid);
+	node_set_online(nid);
+	sz = numa_enforce_memory_limit(base, size);
+	if (sz)
+		memblock_set_node(base, sz, &memblock.memory, nid);
+
+	return sz;
+}
+
+/*
  * Extract NUMA information from the ibm,dynamic-reconfiguration-memory
  * node.  This assumes n_mem_{addr,size}_cells have been set.
  */
-static void __init parse_drconf_memory(struct device_node *memory)
+static void __init parse_drconf_memory_v1(struct device_node *memory,
+			unsigned int n, unsigned long lmb_size,
+			struct assoc_arrays *aa, const __be32 **dm)
 {
-	const __be32 *uninitialized_var(dm), *usm;
-	unsigned int n, rc, ranges, is_kexec_kdump = 0;
-	unsigned long lmb_size, base, size, sz;
-	int nid;
-	struct assoc_arrays aa = { .arrays = NULL };
-
-	n = of_get_drconf_memory(memory, &dm);
-	if (!n)
-		return;
-
-	lmb_size = of_get_lmb_size(memory);
-	if (!lmb_size)
-		return;
-
-	rc = of_get_assoc_arrays(memory, &aa);
-	if (rc)
-		return;
+	const __be32 *usm;
+	unsigned int ranges, is_kexec_kdump = 0;
+	unsigned long base, size;
 
 	/* check if this is a kexec/kdump kernel */
 	usm = of_get_usable_memory(memory);
@@ -691,7 +725,7 @@ static void __init parse_drconf_memory(struct device_node *memory)
 	for (; n != 0; --n) {
 		struct of_drconf_cell drmem;
 
-		read_drconf_cell(&drmem, &dm);
+		read_drconf_cell(&drmem, dm);
 
 		/* skip this block if the reserved bit is set in flags (0x80)
 		   or if the block is not assigned to this partition (0x8) */
@@ -713,19 +747,80 @@ static void __init parse_drconf_memory(struct device_node *memory)
 				base = read_n_cells(n_mem_addr_cells, &usm);
 				size = read_n_cells(n_mem_size_cells, &usm);
 			}
-			nid = of_drconf_to_nid_single(&drmem, &aa);
-			fake_numa_create_new_node(
-				((base + size) >> PAGE_SHIFT),
-					   &nid);
-			node_set_online(nid);
-			sz = numa_enforce_memory_limit(base, size);
-			if (sz)
-				memblock_set_node(base, sz,
-						  &memblock.memory, nid);
+
+			parse_drconf_memory_common(drmem.flags,
+				drmem.aa_index, aa, base, size);
+
 		} while (--ranges);
 	}
 }
 
+static void __init parse_drconf_memory_v2(struct device_node *memory,
+			unsigned int n, unsigned long lmb_size,
+			struct assoc_arrays *aa, unsigned int v2len,
+			const __be32 *v2prop, const __be32 **dm)
+{
+	unsigned long base;
+	unsigned long size;
+
+	for (; n != 0; n--) {
+		struct of_drconf_cell_v2 drmem;
+		unsigned long nsl;
+
+		/* Get the current LMB set */
+		read_drconf_cell_v2(&drmem, dm);
+
+		/* Skip this block if the reserved bit is set in
+		 * flags (0x80) or if the block is not assigned
+		 * to this partition (0x8)
+		 */
+		if ((drmem.flags & DRCONF_MEM_RESERVED)
+		    || !(drmem.flags & DRCONF_MEM_ASSIGNED))
+			continue;
+
+		base = drmem.base_addr;
+		nsl = drmem.num_seq_lmbs;
+
+		for (; nsl != 0; nsl--) {
+			size = lmb_size;
+
+			base += parse_drconf_memory_common(drmem.flags,
+					drmem.aa_index, aa, base, size);
+		}
+	}
+}
+
+static void __init parse_drconf_memory(struct device_node *memory)
+{
+	const __be32 *uninitialized_var(dm);
+	unsigned int n, v2len;
+	unsigned long lmb_size;
+	struct assoc_arrays aa = { .arrays = NULL };
+	const __be32 *v2prop;
+	int rc;
+
+	/* Get the number of sub-structures to be processed */
+	n = of_get_drconf_memory(memory, &dm);
+	if (!n)
+		return;
+
+	lmb_size = of_get_lmb_size(memory);
+	if (!lmb_size)
+		return;
+
+	rc = of_get_assoc_arrays(memory, &aa);
+	if (rc)
+		return;
+
+	v2prop = of_get_property(memory, "ibm,dynamic-memory-v2", &v2len);
+
+	if (!v2prop || v2len < sizeof(unsigned int))
+		parse_drconf_memory_v1(memory, n, lmb_size, &aa, &dm);
+	else
+		parse_drconf_memory_v2(memory, n, lmb_size, &aa,
+					v2len, v2prop, &dm);
+}
+
 static int __init parse_numa_properties(void)
 {
 	struct device_node *memory;
@@ -1039,8 +1134,8 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory,
 		if ((scn_addr < drmem.base_addr)
 		    || (scn_addr >= (drmem.base_addr + lmb_size)))
 			continue;
-
-		nid = of_drconf_to_nid_single(&drmem, &aa);
+		nid = of_drconf_to_nid_single(drmem.flags,
+						drmem.aa_index, &aa);
 		break;
 	}
 

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  2017-04-12 18:36 [PATCH 0/5] powerpc/devtree: Add support for 'ibm, dynamic-memory-v2' property Michael Bringmann
                   ` (2 preceding siblings ...)
  2017-04-12 18:37 ` [PATCH 3/5] powerpc/memory: Parse new memory property to initialize structures Michael Bringmann
@ 2017-04-12 18:37 ` Michael Bringmann
  2017-04-14 22:18   ` Tyrel Datwyler
  2017-04-14 22:21   ` Tyrel Datwyler
  2017-04-12 18:37 ` [PATCH 5/5] powerpc: Enable support for new 'ibm, dynamic-memory-v2' devtree property Michael Bringmann
  4 siblings, 2 replies; 8+ messages in thread
From: Michael Bringmann @ 2017-04-12 18:37 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

hotplug_init: Simplify the code needed for runtime memory hotplug and
maintenance with a conversion routine that transforms the compressed
property "ibm,dynamic-memory-v2" to the form of "ibm,dynamic-memory"
within the "ibm,dynamic-reconfiguration-memory" property.  Thus only
a single set of routines should be required at runtime to parse, edit,
and manipulate the memory representation in the device tree.  Similarly,
any userspace applications that need this information will only need
to recognize the older format to be able to continue to operate.

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/Makefile         |    4 -
 arch/powerpc/platforms/pseries/hotplug-memory.c |   96 +++++++++++++++++++++++
 2 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 8f4ba08..87eb665 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -5,14 +5,14 @@ obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
 			   of_helpers.o \
 			   setup.o iommu.o event_sources.o ras.o \
 			   firmware.o power.o dlpar.o mobility.o rng.o \
-			   pci.o pci_dlpar.o eeh_pseries.o msi.o
+			   pci.o pci_dlpar.o eeh_pseries.o msi.o \
+			   hotplug-memory.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
 obj-$(CONFIG_KEXEC_CORE)	+= kexec.o
 obj-$(CONFIG_PSERIES_ENERGY)	+= pseries_energy.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
-obj-$(CONFIG_MEMORY_HOTPLUG)	+= hotplug-memory.o
 
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index e104c71..92f41a1 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -24,8 +24,6 @@
 #include <asm/sparsemem.h>
 #include "pseries.h"
 
-static bool rtas_hp_event;
-
 unsigned long pseries_memory_block_size(void)
 {
 	struct device_node *np;
@@ -69,6 +67,10 @@ unsigned long pseries_memory_block_size(void)
 	return memblock_size;
 }
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+static bool rtas_hp_event;
+
 static void dlpar_free_property(struct property *prop)
 {
 	kfree(prop->name);
@@ -1165,11 +1167,101 @@ static int pseries_memory_notifier(struct notifier_block *nb,
 static struct notifier_block pseries_mem_nb = {
 	.notifier_call = pseries_memory_notifier,
 };
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
+static int pseries_rewrite_dynamic_memory_v2(void)
+{
+	unsigned long memblock_size;
+	struct device_node *dn;
+	struct property *prop, *prop_v2;
+	__be32 *p;
+	struct of_drconf_cell *lmbs;
+	u32 num_lmb_desc_sets, num_lmbs;
+	int i, j, k;
+
+	dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+	if (!dn)
+		return -EINVAL;
+
+	prop_v2 = of_find_property(dn, "ibm,dynamic-memory-v2", NULL);
+	if (!prop_v2)
+		return -EINVAL;
+
+	memblock_size = pseries_memory_block_size();
+	if (!memblock_size)
+		return -EINVAL;
+
+	/* The first int of the property is the number of lmb sets
+	 * described by the property.
+	 */
+	p = (__be32 *)prop_v2->value;
+	num_lmb_desc_sets = be32_to_cpu(*p++);
+
+	/* Count the number of LMBs for generating the alternate format
+	 */
+	for (i = 0, num_lmbs = 0; i < num_lmb_desc_sets; i++) {
+		struct of_drconf_cell_v2 drmem;
+
+		read_drconf_cell_v2(&drmem, (const __be32 **)&p);
+		num_lmbs += drmem.num_seq_lmbs;
+	}
+
+	/* Create an empty copy of the new 'ibm,dynamic-memory' property
+	 */
+	prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+	if (!prop)
+		return -ENOMEM;
+	prop->name = kstrdup("ibm,dynamic-memory", GFP_KERNEL);
+	prop->length = dyn_mem_v2_len(num_lmbs);
+	prop->value = kzalloc(prop->length, GFP_KERNEL);
+
+	/* Copy/expand the ibm,dynamic-memory-v2 format to produce the
+	 * ibm,dynamic-memory format.
+	 */
+	p = (__be32 *)prop->value;
+	*p = cpu_to_be32(num_lmbs);
+	p++;
+	lmbs = (struct of_drconf_cell *)p;
+
+	p = (__be32 *)prop_v2->value;
+	p++;
+
+	for (i = 0, k = 0; i < num_lmb_desc_sets; i++) {
+		struct of_drconf_cell_v2 drmem;
+
+		read_drconf_cell_v2(&drmem, (const __be32 **)&p);
+
+		for (j = 0; j < drmem.num_seq_lmbs; j++) {
+			lmbs[k+j].base_addr = be64_to_cpu(drmem.base_addr);
+			lmbs[k+j].drc_index = be32_to_cpu(drmem.drc_index);
+			lmbs[k+j].aa_index  = be32_to_cpu(drmem.aa_index);
+			lmbs[k+i].flags     = be32_to_cpu(drmem.flags);
+
+			drmem.base_addr += memblock_size;
+			drmem.drc_index++;
+		}
+
+		k += drmem.num_seq_lmbs;
+	}
+
+	of_remove_property(dn, prop_v2);
+
+	of_add_property(dn, prop);
+
+	/* And disable feature flag since the property has gone away */
+	powerpc_firmware_features &= ~FW_FEATURE_DYN_MEM_V2;
+
+	return 0;
+}
 
 static int __init pseries_memory_hotplug_init(void)
 {
+	if (firmware_has_feature(FW_FEATURE_DYN_MEM_V2))
+		pseries_rewrite_dynamic_memory_v2();
+#ifdef CONFIG_MEMORY_HOTPLUG
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		of_reconfig_notifier_register(&pseries_mem_nb);
+#endif /* CONFIG_MEMORY_HOTPLUG */
 
 	return 0;
 }

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] powerpc: Enable support for new 'ibm, dynamic-memory-v2' devtree property
  2017-04-12 18:36 [PATCH 0/5] powerpc/devtree: Add support for 'ibm, dynamic-memory-v2' property Michael Bringmann
                   ` (3 preceding siblings ...)
  2017-04-12 18:37 ` [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
@ 2017-04-12 18:37 ` Michael Bringmann
  4 siblings, 0 replies; 8+ messages in thread
From: Michael Bringmann @ 2017-04-12 18:37 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

prom_init.c: Enable support for new DRC device tree properties
"ibm,dynamic-memory-v2" in initial handshake between the Linux kernel
and the front end processor.

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/prom_init.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 102b1a1..6ab7b6a 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -869,7 +869,7 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
 		.mmu = 0,
 		.hash_ext = 0,
 		.radix_ext = 0,
-		.byte22 = OV5_FEAT(OV5_DRC_INFO),
+		.byte22 = OV5_FEAT(OV5_DRC_INFO) | OV5_FEAT(OV5_DYN_MEM_V2),
 	},
 
 	/* option vector 6: IBM PAPR hints */

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  2017-04-12 18:37 ` [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
@ 2017-04-14 22:18   ` Tyrel Datwyler
  2017-04-14 22:21   ` Tyrel Datwyler
  1 sibling, 0 replies; 8+ messages in thread
From: Tyrel Datwyler @ 2017-04-14 22:18 UTC (permalink / raw)
  To: Michael Bringmann, ltc-virtual-io, linuxppc-dev; +Cc: nfont

On 04/12/2017 11:37 AM, Michael Bringmann wrote:
> hotplug_init: Simplify the code needed for runtime memory hotplug and
> maintenance with a conversion routine that transforms the compressed
> property "ibm,dynamic-memory-v2" to the form of "ibm,dynamic-memory"
> within the "ibm,dynamic-reconfiguration-memory" property.  Thus only
> a single set of routines should be required at runtime to parse, edit,
> and manipulate the memory representation in the device tree.  Similarly,
> any userspace applications that need this information will only need
> to recognize the older format to be able to continue to operate.
> 
> Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
> ---
>  arch/powerpc/platforms/pseries/Makefile         |    4 -
>  arch/powerpc/platforms/pseries/hotplug-memory.c |   96 +++++++++++++++++++++++
>  2 files changed, 96 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
> index 8f4ba08..87eb665 100644
> --- a/arch/powerpc/platforms/pseries/Makefile
> +++ b/arch/powerpc/platforms/pseries/Makefile
> @@ -5,14 +5,14 @@ obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
>  			   of_helpers.o \
>  			   setup.o iommu.o event_sources.o ras.o \
>  			   firmware.o power.o dlpar.o mobility.o rng.o \
> -			   pci.o pci_dlpar.o eeh_pseries.o msi.o
> +			   pci.o pci_dlpar.o eeh_pseries.o msi.o \
> +			   hotplug-memory.o
>  obj-$(CONFIG_SMP)	+= smp.o
>  obj-$(CONFIG_SCANLOG)	+= scanlog.o
>  obj-$(CONFIG_KEXEC_CORE)	+= kexec.o
>  obj-$(CONFIG_PSERIES_ENERGY)	+= pseries_energy.o
> 
>  obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
> -obj-$(CONFIG_MEMORY_HOTPLUG)	+= hotplug-memory.o
> 
>  obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
>  obj-$(CONFIG_HVCS)		+= hvcserver.o
> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
> index e104c71..92f41a1 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> @@ -24,8 +24,6 @@
>  #include <asm/sparsemem.h>
>  #include "pseries.h"
> 
> -static bool rtas_hp_event;
> -
>  unsigned long pseries_memory_block_size(void)
>  {
>  	struct device_node *np;
> @@ -69,6 +67,10 @@ unsigned long pseries_memory_block_size(void)
>  	return memblock_size;
>  }
> 
> +#ifdef CONFIG_MEMORY_HOTPLUG
> +
> +static bool rtas_hp_event;
> +
>  static void dlpar_free_property(struct property *prop)
>  {
>  	kfree(prop->name);
> @@ -1165,11 +1167,101 @@ static int pseries_memory_notifier(struct notifier_block *nb,
>  static struct notifier_block pseries_mem_nb = {
>  	.notifier_call = pseries_memory_notifier,
>  };
> +#endif /* CONFIG_MEMORY_HOTPLUG */
> +
> +static int pseries_rewrite_dynamic_memory_v2(void)
> +{
> +	unsigned long memblock_size;
> +	struct device_node *dn;
> +	struct property *prop, *prop_v2;
> +	__be32 *p;
> +	struct of_drconf_cell *lmbs;
> +	u32 num_lmb_desc_sets, num_lmbs;
> +	int i, j, k;
> +
> +	dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");

This call returns a node pointer with its refcount incremented. You need
to call of_node_put() when you are finished or you will leak a reference.

-Tyrel

> +	if (!dn)
> +		return -EINVAL;
> +
> +	prop_v2 = of_find_property(dn, "ibm,dynamic-memory-v2", NULL);
> +	if (!prop_v2)
> +		return -EINVAL;
> +
> +	memblock_size = pseries_memory_block_size();
> +	if (!memblock_size)
> +		return -EINVAL;
> +
> +	/* The first int of the property is the number of lmb sets
> +	 * described by the property.
> +	 */
> +	p = (__be32 *)prop_v2->value;
> +	num_lmb_desc_sets = be32_to_cpu(*p++);
> +
> +	/* Count the number of LMBs for generating the alternate format
> +	 */
> +	for (i = 0, num_lmbs = 0; i < num_lmb_desc_sets; i++) {
> +		struct of_drconf_cell_v2 drmem;
> +
> +		read_drconf_cell_v2(&drmem, (const __be32 **)&p);
> +		num_lmbs += drmem.num_seq_lmbs;
> +	}
> +
> +	/* Create an empty copy of the new 'ibm,dynamic-memory' property
> +	 */
> +	prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> +	if (!prop)
> +		return -ENOMEM;
> +	prop->name = kstrdup("ibm,dynamic-memory", GFP_KERNEL);
> +	prop->length = dyn_mem_v2_len(num_lmbs);
> +	prop->value = kzalloc(prop->length, GFP_KERNEL);
> +
> +	/* Copy/expand the ibm,dynamic-memory-v2 format to produce the
> +	 * ibm,dynamic-memory format.
> +	 */
> +	p = (__be32 *)prop->value;
> +	*p = cpu_to_be32(num_lmbs);
> +	p++;
> +	lmbs = (struct of_drconf_cell *)p;
> +
> +	p = (__be32 *)prop_v2->value;
> +	p++;
> +
> +	for (i = 0, k = 0; i < num_lmb_desc_sets; i++) {
> +		struct of_drconf_cell_v2 drmem;
> +
> +		read_drconf_cell_v2(&drmem, (const __be32 **)&p);
> +
> +		for (j = 0; j < drmem.num_seq_lmbs; j++) {
> +			lmbs[k+j].base_addr = be64_to_cpu(drmem.base_addr);
> +			lmbs[k+j].drc_index = be32_to_cpu(drmem.drc_index);
> +			lmbs[k+j].aa_index  = be32_to_cpu(drmem.aa_index);
> +			lmbs[k+i].flags     = be32_to_cpu(drmem.flags);
> +
> +			drmem.base_addr += memblock_size;
> +			drmem.drc_index++;
> +		}
> +
> +		k += drmem.num_seq_lmbs;
> +	}
> +
> +	of_remove_property(dn, prop_v2);
> +
> +	of_add_property(dn, prop);
> +
> +	/* And disable feature flag since the property has gone away */
> +	powerpc_firmware_features &= ~FW_FEATURE_DYN_MEM_V2;
> +
> +	return 0;
> +}
> 
>  static int __init pseries_memory_hotplug_init(void)
>  {
> +	if (firmware_has_feature(FW_FEATURE_DYN_MEM_V2))
> +		pseries_rewrite_dynamic_memory_v2();
> +#ifdef CONFIG_MEMORY_HOTPLUG
>  	if (firmware_has_feature(FW_FEATURE_LPAR))
>  		of_reconfig_notifier_register(&pseries_mem_nb);
> +#endif /* CONFIG_MEMORY_HOTPLUG */
> 
>  	return 0;
>  }
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  2017-04-12 18:37 ` [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
  2017-04-14 22:18   ` Tyrel Datwyler
@ 2017-04-14 22:21   ` Tyrel Datwyler
  1 sibling, 0 replies; 8+ messages in thread
From: Tyrel Datwyler @ 2017-04-14 22:21 UTC (permalink / raw)
  To: Michael Bringmann, ltc-virtual-io, linuxppc-dev; +Cc: nfont

On 04/12/2017 11:37 AM, Michael Bringmann wrote:
> hotplug_init: Simplify the code needed for runtime memory hotplug and
> maintenance with a conversion routine that transforms the compressed
> property "ibm,dynamic-memory-v2" to the form of "ibm,dynamic-memory"
> within the "ibm,dynamic-reconfiguration-memory" property.  Thus only

ibm,dynamic-reconfiguration-memory is a device tree node not a property.
So, s/property/node.

-Tyrel

> a single set of routines should be required at runtime to parse, edit,
> and manipulate the memory representation in the device tree.  Similarly,
> any userspace applications that need this information will only need
> to recognize the older format to be able to continue to operate.
> 
> Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
> ---
>  arch/powerpc/platforms/pseries/Makefile         |    4 -
>  arch/powerpc/platforms/pseries/hotplug-memory.c |   96 +++++++++++++++++++++++
>  2 files changed, 96 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
> index 8f4ba08..87eb665 100644
> --- a/arch/powerpc/platforms/pseries/Makefile
> +++ b/arch/powerpc/platforms/pseries/Makefile
> @@ -5,14 +5,14 @@ obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
>  			   of_helpers.o \
>  			   setup.o iommu.o event_sources.o ras.o \
>  			   firmware.o power.o dlpar.o mobility.o rng.o \
> -			   pci.o pci_dlpar.o eeh_pseries.o msi.o
> +			   pci.o pci_dlpar.o eeh_pseries.o msi.o \
> +			   hotplug-memory.o
>  obj-$(CONFIG_SMP)	+= smp.o
>  obj-$(CONFIG_SCANLOG)	+= scanlog.o
>  obj-$(CONFIG_KEXEC_CORE)	+= kexec.o
>  obj-$(CONFIG_PSERIES_ENERGY)	+= pseries_energy.o
> 
>  obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
> -obj-$(CONFIG_MEMORY_HOTPLUG)	+= hotplug-memory.o
> 
>  obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
>  obj-$(CONFIG_HVCS)		+= hvcserver.o
> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
> index e104c71..92f41a1 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> @@ -24,8 +24,6 @@
>  #include <asm/sparsemem.h>
>  #include "pseries.h"
> 
> -static bool rtas_hp_event;
> -
>  unsigned long pseries_memory_block_size(void)
>  {
>  	struct device_node *np;
> @@ -69,6 +67,10 @@ unsigned long pseries_memory_block_size(void)
>  	return memblock_size;
>  }
> 
> +#ifdef CONFIG_MEMORY_HOTPLUG
> +
> +static bool rtas_hp_event;
> +
>  static void dlpar_free_property(struct property *prop)
>  {
>  	kfree(prop->name);
> @@ -1165,11 +1167,101 @@ static int pseries_memory_notifier(struct notifier_block *nb,
>  static struct notifier_block pseries_mem_nb = {
>  	.notifier_call = pseries_memory_notifier,
>  };
> +#endif /* CONFIG_MEMORY_HOTPLUG */
> +
> +static int pseries_rewrite_dynamic_memory_v2(void)
> +{
> +	unsigned long memblock_size;
> +	struct device_node *dn;
> +	struct property *prop, *prop_v2;
> +	__be32 *p;
> +	struct of_drconf_cell *lmbs;
> +	u32 num_lmb_desc_sets, num_lmbs;
> +	int i, j, k;
> +
> +	dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
> +	if (!dn)
> +		return -EINVAL;
> +
> +	prop_v2 = of_find_property(dn, "ibm,dynamic-memory-v2", NULL);
> +	if (!prop_v2)
> +		return -EINVAL;
> +
> +	memblock_size = pseries_memory_block_size();
> +	if (!memblock_size)
> +		return -EINVAL;
> +
> +	/* The first int of the property is the number of lmb sets
> +	 * described by the property.
> +	 */
> +	p = (__be32 *)prop_v2->value;
> +	num_lmb_desc_sets = be32_to_cpu(*p++);
> +
> +	/* Count the number of LMBs for generating the alternate format
> +	 */
> +	for (i = 0, num_lmbs = 0; i < num_lmb_desc_sets; i++) {
> +		struct of_drconf_cell_v2 drmem;
> +
> +		read_drconf_cell_v2(&drmem, (const __be32 **)&p);
> +		num_lmbs += drmem.num_seq_lmbs;
> +	}
> +
> +	/* Create an empty copy of the new 'ibm,dynamic-memory' property
> +	 */
> +	prop = kzalloc(sizeof(*prop), GFP_KERNEL);
> +	if (!prop)
> +		return -ENOMEM;
> +	prop->name = kstrdup("ibm,dynamic-memory", GFP_KERNEL);
> +	prop->length = dyn_mem_v2_len(num_lmbs);
> +	prop->value = kzalloc(prop->length, GFP_KERNEL);
> +
> +	/* Copy/expand the ibm,dynamic-memory-v2 format to produce the
> +	 * ibm,dynamic-memory format.
> +	 */
> +	p = (__be32 *)prop->value;
> +	*p = cpu_to_be32(num_lmbs);
> +	p++;
> +	lmbs = (struct of_drconf_cell *)p;
> +
> +	p = (__be32 *)prop_v2->value;
> +	p++;
> +
> +	for (i = 0, k = 0; i < num_lmb_desc_sets; i++) {
> +		struct of_drconf_cell_v2 drmem;
> +
> +		read_drconf_cell_v2(&drmem, (const __be32 **)&p);
> +
> +		for (j = 0; j < drmem.num_seq_lmbs; j++) {
> +			lmbs[k+j].base_addr = be64_to_cpu(drmem.base_addr);
> +			lmbs[k+j].drc_index = be32_to_cpu(drmem.drc_index);
> +			lmbs[k+j].aa_index  = be32_to_cpu(drmem.aa_index);
> +			lmbs[k+i].flags     = be32_to_cpu(drmem.flags);
> +
> +			drmem.base_addr += memblock_size;
> +			drmem.drc_index++;
> +		}
> +
> +		k += drmem.num_seq_lmbs;
> +	}
> +
> +	of_remove_property(dn, prop_v2);
> +
> +	of_add_property(dn, prop);
> +
> +	/* And disable feature flag since the property has gone away */
> +	powerpc_firmware_features &= ~FW_FEATURE_DYN_MEM_V2;
> +
> +	return 0;
> +}
> 
>  static int __init pseries_memory_hotplug_init(void)
>  {
> +	if (firmware_has_feature(FW_FEATURE_DYN_MEM_V2))
> +		pseries_rewrite_dynamic_memory_v2();
> +#ifdef CONFIG_MEMORY_HOTPLUG
>  	if (firmware_has_feature(FW_FEATURE_LPAR))
>  		of_reconfig_notifier_register(&pseries_mem_nb);
> +#endif /* CONFIG_MEMORY_HOTPLUG */
> 
>  	return 0;
>  }
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-04-14 22:21 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-12 18:36 [PATCH 0/5] powerpc/devtree: Add support for 'ibm, dynamic-memory-v2' property Michael Bringmann
2017-04-12 18:36 ` [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features, [PATCH 1/5] powerpc/dynmemv2: Check arch.vec earlier during boot for memory features Michael Bringmann
2017-04-12 18:36 ` [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks., [PATCH 2/5] powerpc/memory: Parse new memory property to register blocks Michael Bringmann
2017-04-12 18:37 ` [PATCH 3/5] powerpc/memory: Parse new memory property to initialize structures Michael Bringmann
2017-04-12 18:37 ` [PATCH 4/5] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
2017-04-14 22:18   ` Tyrel Datwyler
2017-04-14 22:21   ` Tyrel Datwyler
2017-04-12 18:37 ` [PATCH 5/5] powerpc: Enable support for new 'ibm, dynamic-memory-v2' devtree property Michael Bringmann

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.