All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties
@ 2016-12-07  7:13 Michael Bringmann
  2016-12-07  7:14 ` [PATCH V9 1/8] powerpc/firmware: Add definitions for new firmware features Michael Bringmann
                   ` (8 more replies)
  0 siblings, 9 replies; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:13 UTC (permalink / raw)
  To: linuxppc-dev, ltc-virtual-io, linuxppc-dev, ; +Cc: nfont

Several properties in the DRC device tree format are replaced by
more compact representations to allow, for example, for the encoding
of vast amounts of memory, and or reduced duplication of information
in related data structures.

"ibm,drc-info": This property, when present, replaces the following
four properties: "ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains".  This property is defined for all
dynamically reconfigurable platform nodes.  The "ibm,drc-info" elements
are intended to provide a more compact representation, and reduce some
search overhead.

"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 structures "ibm,drc-info" and
"ibm,dynamic-memory-v2".

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

Michael Bringmann (8):
  powerpc/firmware: Add definitions for new firmware 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
  pseries/drc-info: Search new DRC properties for CPU indexes
  hotplug/drc-info: Add code to search new devtree properties
  powerpc: Check arch.vec earlier during boot for memory features
  powerpc: Enable support for new DRC devtree properties
---
Changes in V9:
  -- Various code cleanup measures

 arch/powerpc/include/asm/firmware.h             |    5 -
 arch/powerpc/include/asm/prom.h                 |   38 ++++
 arch/powerpc/kernel/prom.c                      |  103 ++++++++++--
 arch/powerpc/kernel/prom_init.c                 |    3 
 arch/powerpc/mm/numa.c                          |  168 ++++++++++++++++---
 arch/powerpc/platforms/pseries/firmware.c       |    2 
 arch/powerpc/platforms/pseries/pseries_energy.c |  202 ++++++++++++++++++++---
 drivers/pci/hotplug/rpadlpar_core.c             |   13 +
 drivers/pci/hotplug/rpaphp.h                    |    4 
 drivers/pci/hotplug/rpaphp_core.c               |  108 +++++++++---
 10 files changed, 543 insertions(+), 103 deletions(-)

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

* [PATCH V9 1/8] powerpc/firmware: Add definitions for new firmware features.
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
@ 2016-12-07  7:14 ` Michael Bringmann
  2016-12-12 15:19   ` Nathan Fontenot
  2016-12-07  7:14 ` [PATCH V9 2/8] powerpc/memory: Parse new memory property to register blocks Michael Bringmann
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:14 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

Firmware Features: Define new bit flags representing the presence of
new device tree properties "ibm,drc-info", and "ibm,dynamic-memory-v2".
These flags are used to tell the front end processor when the Linux
kernel supports the new properties, and by the front end processor to
tell the Linux kernel that the new properties are present in the devie
tree.

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/firmware.h       |    5 ++++-
 arch/powerpc/include/asm/prom.h           |    2 ++
 arch/powerpc/platforms/pseries/firmware.c |    2 ++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
index 1e0b5a5..6b5cf38 100644
--- a/arch/powerpc/include/asm/firmware.h
+++ b/arch/powerpc/include/asm/firmware.h
@@ -51,6 +51,8 @@
 #define FW_FEATURE_BEST_ENERGY	ASM_CONST(0x0000000080000000)
 #define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
 #define FW_FEATURE_PRRN		ASM_CONST(0x0000000200000000)
+#define FW_FEATURE_DYN_MEM_V2	ASM_CONST(0x0000000400000000)
+#define FW_FEATURE_DRC_INFO	ASM_CONST(0x0000000800000000)
 
 #ifndef __ASSEMBLY__
 
@@ -66,7 +68,8 @@ enum {
 		FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
 		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_TYPE1_AFFINITY | FW_FEATURE_PRRN |
+		FW_FEATURE_DYN_MEM_V2 | FW_FEATURE_DRC_INFO,
 	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 7f436ba..bc7c4b5 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -155,6 +155,8 @@ struct of_drconf_cell {
 #define OV5_PFO_HW_842		0x0E40	/* PFO Compression Accelerator */
 #define OV5_PFO_HW_ENCR		0x0E20	/* PFO Encryption Accelerator */
 #define OV5_SUB_PROCESSORS	0x0F01	/* 1,2,or 4 Sub-Processors supported */
+#define OV5_DYN_MEM_V2		0x1680	/* Redef Prop Structures: dyn-mem-v2 */
+#define OV5_DRC_INFO		0x1640	/* Redef Prop Structures: drc-info   */
 
 /* Option Vector 6: IBM PAPR hints */
 #define OV6_LINUX		0x02	/* Linux is our OS */
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index ea7f09b..d2d23f5 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -113,6 +113,8 @@ struct vec5_fw_feature {
 vec5_fw_features_table[] = {
 	{FW_FEATURE_TYPE1_AFFINITY,	OV5_TYPE1_AFFINITY},
 	{FW_FEATURE_PRRN,		OV5_PRRN},
+	{FW_FEATURE_DYN_MEM_V2,		OV5_DYN_MEM_V2},
+	{FW_FEATURE_DRC_INFO,		OV5_DRC_INFO},
 };
 
 static void __init fw_vec5_feature_init(const char *vec5, unsigned long len)

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

* [PATCH V9 2/8] powerpc/memory: Parse new memory property to register blocks.
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
  2016-12-07  7:14 ` [PATCH V9 1/8] powerpc/firmware: Add definitions for new firmware features Michael Bringmann
@ 2016-12-07  7:14 ` Michael Bringmann
  2016-12-12 15:24   ` Nathan Fontenot
  2016-12-07  7:14 ` [PATCH V9 3/8] powerpc/memory: Parse new memory property to initialize structures Michael Bringmann
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:14 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/prom.h |   24 ++++++++--
 arch/powerpc/kernel/prom.c      |   97 ++++++++++++++++++++++++++++++++++++---
 arch/powerpc/mm/numa.c          |   22 ++++++++-
 3 files changed, 129 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index bc7c4b5..43a002b 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);
 
 /*
  * There are two methods for telling firmware what our capabilities are.
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index b0245be..2d49887 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -443,23 +443,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))
@@ -518,6 +529,76 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
 	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 (iommu_is_off) {
+				if (base >= 0x80000000ul)
+					continue;
+				if ((base + size) > 0x80000000ul)
+					size = 0x80000000ul - base;
+			}
+			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 */
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index a51c188..67dc989 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -57,8 +57,10 @@
 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;
+EXPORT_SYMBOL(n_mem_addr_cells);
 
 #define MAX_DISTANCE_REF_POINTS 4
 static int distance_ref_points_depth;
@@ -405,6 +407,24 @@ 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;
+}
+EXPORT_SYMBOL(read_drconf_cell_v2);
 
 /*
  * Retrieve and validate the ibm,dynamic-memory property of the device tree.

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

* [PATCH V9 3/8] powerpc/memory: Parse new memory property to initialize structures.
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
  2016-12-07  7:14 ` [PATCH V9 1/8] powerpc/firmware: Add definitions for new firmware features Michael Bringmann
  2016-12-07  7:14 ` [PATCH V9 2/8] powerpc/memory: Parse new memory property to register blocks Michael Bringmann
@ 2016-12-07  7:14 ` Michael Bringmann
  2016-12-12 15:27   ` Nathan Fontenot
  2016-12-07  7:14 ` [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:14 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>
---
Changes in V9:
 - Remove unnecessary multiplier from a property length calculation
---
 arch/powerpc/include/asm/prom.h |   12 +++
 arch/powerpc/mm/numa.c          |  146 +++++++++++++++++++++++++++++++++------
 2 files changed, 135 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index 43a002b..01842a7 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -110,6 +110,18 @@ struct of_drconf_cell_v2 {
 extern void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem,
 				const __be32 **cellp);
 
+extern void read_one_drc_info(int **info, char **drc_type, char **drc_name,
+			unsigned long int *fdi_p, unsigned long int *nsl_p,
+			unsigned long int *si_p, unsigned long int *ldi_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 67dc989..4cbcae8 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -427,30 +427,55 @@ void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem, const __be32 **cellp)
 EXPORT_SYMBOL(read_drconf_cell_v2);
 
 /*
- * 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;
 }
 
@@ -513,7 +538,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;
@@ -521,16 +546,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]);
 		}
@@ -665,7 +690,7 @@ static inline int __init read_usm_ranges(const __be32 **usm)
  * 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)
 {
 	const __be32 *uninitialized_var(dm), *usm;
 	unsigned int n, rc, ranges, is_kexec_kdump = 0;
@@ -715,7 +740,8 @@ 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);
+			nid = of_drconf_to_nid_single(drmem.flags,
+							drmem.aa_index, &aa);
 			fake_numa_create_new_node(
 				((base + size) >> PAGE_SHIFT),
 					   &nid);
@@ -728,6 +754,80 @@ static void __init parse_drconf_memory(struct device_node *memory)
 	}
 }
 
+static void __init parse_drconf_memory_v2(struct device_node *memory)
+{
+	const __be32 *uninitialized_var(dm);
+	unsigned int num_lmb_sets, rc;
+	unsigned long lmb_size, base;
+	unsigned long size, sz;
+	int nid;
+	struct assoc_arrays aa = { .arrays = NULL };
+	const __be32 *prop;
+	u32	len;
+
+	prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len);
+	if (!prop)
+		return;
+
+	num_lmb_sets = of_get_drconf_memory(memory, &dm);
+	if (!num_lmb_sets)
+		return;
+
+	lmb_size = of_get_lmb_size(memory);
+	if (!lmb_size)
+		return;
+
+	rc = of_get_assoc_arrays(memory, &aa);
+	if (rc)
+		return;
+
+	for (; num_lmb_sets != 0; num_lmb_sets--) {
+		struct of_drconf_cell_v2 drmem;
+		unsigned long nsl;
+
+		/* Get the current LMB set */
+		read_drconf_cell_v2(&drmem, &dm);
+		base = drmem.base_addr;
+		nsl = drmem.num_seq_lmbs;
+
+		/* 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;
+
+		for (; nsl != 0; nsl--) {
+			size = lmb_size;
+
+			nid = of_drconf_to_nid_single(drmem.flags,
+						drmem.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);
+
+			base += sz;
+		}
+	}
+}
+
+static void __init parse_drconf_memory(struct device_node *memory)
+{
+	const __be32 *prop;
+	int len;
+	prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len);
+	if (!prop || len < sizeof(unsigned int))
+		parse_drconf_memory_v1(memory);
+	else
+		parse_drconf_memory_v2(memory);
+}
+
 static int __init parse_numa_properties(void)
 {
 	struct device_node *memory;
@@ -1046,8 +1146,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] 19+ messages in thread

* [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
                   ` (2 preceding siblings ...)
  2016-12-07  7:14 ` [PATCH V9 3/8] powerpc/memory: Parse new memory property to initialize structures Michael Bringmann
@ 2016-12-07  7:14 ` Michael Bringmann
  2016-12-12 15:29   ` Nathan Fontenot
  2017-01-31  2:53   ` Michael Ellerman
  2016-12-07  7:15 ` [PATCH V9 5/8] pseries/drc-info: Search new DRC properties for CPU indexes Michael Bringmann
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:14 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>
---
Changes in V9:
  - Remove unnecessary field initialization in allocated memory block
---
 arch/powerpc/platforms/pseries/Makefile         |    4 +
 arch/powerpc/platforms/pseries/hotplug-memory.c |   92 +++++++++++++++++++++++
 2 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index fedc2ccf0..e74cf6c 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)	+= 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 76ec104..7b63639 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -24,6 +24,8 @@
 #include <asm/sparsemem.h>
 #include "pseries.h"
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+
 static bool rtas_hp_event;
 
 unsigned long pseries_memory_block_size(void)
@@ -887,11 +889,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] 19+ messages in thread

* [PATCH V9 5/8] pseries/drc-info: Search new DRC properties for CPU indexes
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
                   ` (3 preceding siblings ...)
  2016-12-07  7:14 ` [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
@ 2016-12-07  7:15 ` Michael Bringmann
  2016-12-07  7:15 ` [PATCH V9 6/8] hotplug/drc-info: Add code to search new devtree properties Michael Bringmann
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:15 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

pseries/drc-info: Provide parallel routines to convert between
drc_index and CPU numbers at runtime, using the older device-tree
properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
Changes in V9:
  -- Correct cpu-to-thread calculation for drc-info structs in function
     drc_index_to_cpu
  -- Change OR operators in WARN_ON test
---
 arch/powerpc/platforms/pseries/pseries_energy.c |  202 ++++++++++++++++++++---
 1 file changed, 176 insertions(+), 26 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c
index 164a13d..549efdb 100644
--- a/arch/powerpc/platforms/pseries/pseries_energy.c
+++ b/arch/powerpc/platforms/pseries/pseries_energy.c
@@ -35,10 +35,73 @@
 
 /* Helper Routines to convert between drc_index to cpu numbers */
 
+void read_one_drc_info(int **info, char **dtype, char **dname,
+			unsigned long int *drc_index_start_p,
+			unsigned long int *num_sequential_elems_p,
+			unsigned long int *sequential_inc_p,
+			unsigned long int *last_drc_index_p)
+{
+	char *drc_type, *drc_name_prefix, *pc;
+	u32 drc_index_start, num_sequential_elems;
+	u32 sequential_inc, last_drc_index;
+
+	drc_index_start = num_sequential_elems = 0;
+	sequential_inc = last_drc_index = 0;
+
+	/* Get drc-type:encode-string */
+	pc = (char *)info;
+	drc_type = pc;
+	pc += (strlen(drc_type) + 1);
+
+	/* Get drc-name-prefix:encode-string */
+	drc_name_prefix = (char *)pc;
+	pc += (strlen(drc_name_prefix) + 1);
+
+	/* Get drc-index-start:encode-int */
+	memcpy(&drc_index_start, pc, 4);
+	drc_index_start = be32_to_cpu(drc_index_start);
+	pc += 4;
+
+	/* Get/skip drc-name-suffix-start:encode-int */
+	pc += 4;
+
+	/* Get number-sequential-elements:encode-int */
+	memcpy(&num_sequential_elems, pc, 4);
+	num_sequential_elems = be32_to_cpu(num_sequential_elems);
+	pc += 4;
+
+	/* Get sequential-increment:encode-int */
+	memcpy(&sequential_inc, pc, 4);
+	sequential_inc = be32_to_cpu(sequential_inc);
+	pc += 4;
+
+	/* Get/skip drc-power-domain:encode-int */
+	pc += 4;
+
+	/* Should now know end of current entry */
+	last_drc_index = drc_index_start +
+			((num_sequential_elems-1)*sequential_inc);
+
+	(*info) = (int *)pc;
+
+	if (dtype)
+		*dtype = drc_type;
+	if (dname)
+		*dname = drc_name_prefix;
+	if (drc_index_start_p)
+		*drc_index_start_p = drc_index_start;
+	if (num_sequential_elems_p)
+		*num_sequential_elems_p = num_sequential_elems;
+	if (sequential_inc_p)
+		*sequential_inc_p = sequential_inc;
+	if (last_drc_index_p)
+		*last_drc_index_p = last_drc_index;
+}
+EXPORT_SYMBOL(read_one_drc_info);
+
 static u32 cpu_to_drc_index(int cpu)
 {
 	struct device_node *dn = NULL;
-	const int *indexes;
 	int i;
 	int rc = 1;
 	u32 ret = 0;
@@ -46,18 +109,60 @@ static u32 cpu_to_drc_index(int cpu)
 	dn = of_find_node_by_path("/cpus");
 	if (dn == NULL)
 		goto err;
-	indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
-	if (indexes == NULL)
-		goto err_of_node_put;
+
 	/* Convert logical cpu number to core number */
 	i = cpu_core_index_of_thread(cpu);
-	/*
-	 * The first element indexes[0] is the number of drc_indexes
-	 * returned in the list.  Hence i+1 will get the drc_index
-	 * corresponding to core number i.
-	 */
-	WARN_ON(i > indexes[0]);
-	ret = indexes[i + 1];
+
+	if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
+		int *info = (int *)4;
+		unsigned long int num_set_entries, j, check_val = i;
+		unsigned long int drc_index_start = 0;
+		unsigned long int last_drc_index = 0;
+		unsigned long int num_sequential_elems = 0;
+		unsigned long int sequential_inc = 0;
+		char *dtype;
+		char *dname;
+
+		info = (int *)of_get_property(dn, "ibm,drc-info", NULL);
+		if (info == NULL)
+			goto err_of_node_put;
+
+		num_set_entries = be32_to_cpu(*info++);
+
+		for (j = 0; j < num_set_entries; j++) {
+
+			read_one_drc_info(&info, &dtype, &dname,
+					&drc_index_start,
+					&num_sequential_elems,
+					&sequential_inc, &last_drc_index);
+			if (strcmp(dtype, "CPU"))
+				goto err;
+
+			if (check_val < last_drc_index)
+				break;
+
+			WARN_ON(((check_val-drc_index_start)%
+					sequential_inc) != 0);
+		}
+		WARN_ON((num_sequential_elems == 0) || (sequential_inc == 0));
+
+		ret = last_drc_index + (check_val*sequential_inc);
+	} else {
+		const int *indexes;
+
+		indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+		if (indexes == NULL)
+			goto err_of_node_put;
+
+		/*
+		 * The first element indexes[0] is the number of drc_indexes
+		 * returned in the list.  Hence i+1 will get the drc_index
+		 * corresponding to core number i.
+		 */
+		WARN_ON(i > indexes[0]);
+		ret = indexes[i + 1];
+	}
+
 	rc = 0;
 
 err_of_node_put:
@@ -72,34 +177,79 @@ static int drc_index_to_cpu(u32 drc_index)
 {
 	struct device_node *dn = NULL;
 	const int *indexes;
-	int i, cpu = 0;
+	int thread = 0, cpu = 0;
 	int rc = 1;
 
 	dn = of_find_node_by_path("/cpus");
 	if (dn == NULL)
 		goto err;
-	indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
-	if (indexes == NULL)
-		goto err_of_node_put;
-	/*
-	 * First element in the array is the number of drc_indexes
-	 * returned.  Search through the list to find the matching
-	 * drc_index and get the core number
-	 */
-	for (i = 0; i < indexes[0]; i++) {
-		if (indexes[i + 1] == drc_index)
+
+	if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
+		int *info = (int *)dn;
+		unsigned long int num_set_entries, j;
+		unsigned long int drc_index_start = 0;
+		unsigned long int last_drc_index = 0;
+		unsigned long int num_sequential_elems = 0;
+		unsigned long int sequential_inc = 0;
+		char *dtype, *dname;
+
+		info = (int *)of_get_property(dn, "ibm,drc-info", NULL);
+		if (info == NULL)
+			goto err_of_node_put;
+
+		num_set_entries = be32_to_cpu(*info++);
+
+		for (j = 0; j < num_set_entries; j++) {
+			read_one_drc_info(&info, &dtype, &dname,
+					&drc_index_start,
+					&num_sequential_elems,
+					&sequential_inc, &last_drc_index);
+			if (strcmp(dtype, "CPU"))
+				goto err;
+
+			WARN_ON(drc_index < drc_index_start);
+			WARN_ON(((drc_index-drc_index_start)%
+					sequential_inc) != 0);
+
+			if (drc_index > last_drc_index) {
+				cpu += ((last_drc_index-drc_index_start)/
+					sequential_inc);
+				continue;
+			} else {
+				cpu += ((drc_index-drc_index_start)/
+					sequential_inc);
+			}
+
+			thread = cpu_first_thread_of_core(cpu);
+			rc = 0;
 			break;
+		}
+	} else {
+		unsigned long int i;
+
+		indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
+		if (indexes == NULL)
+			goto err_of_node_put;
+		/*
+		 * First element in the array is the number of drc_indexes
+		 * returned.  Search through the list to find the matching
+		 * drc_index and get the core number
+		 */
+		for (i = 0; i < indexes[0]; i++) {
+			if (indexes[i + 1] == drc_index)
+				break;
+		}
+		/* Convert core number to logical cpu number */
+		thread = cpu_first_thread_of_core(i);
+		rc = 0;
 	}
-	/* Convert core number to logical cpu number */
-	cpu = cpu_first_thread_of_core(i);
-	rc = 0;
 
 err_of_node_put:
 	of_node_put(dn);
 err:
 	if (rc)
 		printk(KERN_WARNING "drc_index_to_cpu(%d) failed", drc_index);
-	return cpu;
+	return thread;
 }
 
 /*

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

* [PATCH V9 6/8] hotplug/drc-info: Add code to search new devtree properties
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
                   ` (4 preceding siblings ...)
  2016-12-07  7:15 ` [PATCH V9 5/8] pseries/drc-info: Search new DRC properties for CPU indexes Michael Bringmann
@ 2016-12-07  7:15 ` Michael Bringmann
  2016-12-12 15:39   ` Nathan Fontenot
  2016-12-07  7:15 ` [PATCH V9 7/8] powerpc: Check arch.vec earlier during boot for memory features Michael Bringmann
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:15 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

rpadlpar_core.c: Provide parallel routines to search the older device-
tree properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
and "ibm,drc-power-domains"), or the new property "ibm,drc-info".

The interface to examine the DRC information is changed from a "get"
function that returns values for local verification elsewhere, to a
"check" function that validates the 'name' and/or 'type' of a device
node.  This update hides the format of the underlying device-tree
properties, and concentrates the value checks into a single function
without requiring the user to verify whether a search was successful.

Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
---
Changes in V9:
  -- Remove unnecessary code from rpaphp_check_drc_props_v2()
---
 drivers/pci/hotplug/rpadlpar_core.c |   13 ++--
 drivers/pci/hotplug/rpaphp.h        |    4 +
 drivers/pci/hotplug/rpaphp_core.c   |  108 +++++++++++++++++++++++++++--------
 3 files changed, 90 insertions(+), 35 deletions(-)

diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index dc67f39..bea9723 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -27,6 +27,7 @@
 #include <linux/mutex.h>
 #include <asm/rtas.h>
 #include <asm/vio.h>
+#include <linux/firmware.h>
 
 #include "../pci.h"
 #include "rpaphp.h"
@@ -44,15 +45,14 @@ static struct device_node *find_vio_slot_node(char *drc_name)
 {
 	struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
 	struct device_node *dn = NULL;
-	char *name;
 	int rc;
 
 	if (!parent)
 		return NULL;
 
 	while ((dn = of_get_next_child(parent, dn))) {
-		rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
-		if ((rc == 0) && (!strcmp(drc_name, name)))
+		rc = rpaphp_check_drc_props(dn, drc_name, NULL);
+		if (rc == 0)
 			break;
 	}
 
@@ -64,15 +64,12 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
 						  char *drc_type)
 {
 	struct device_node *np = NULL;
-	char *name;
-	char *type;
 	int rc;
 
 	while ((np = of_find_node_by_name(np, "pci"))) {
-		rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL);
+		rc = rpaphp_check_drc_props(np, drc_name, drc_type);
 		if (rc == 0)
-			if (!strcmp(drc_name, name) && !strcmp(drc_type, type))
-				break;
+			break;
 	}
 
 	return np;
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 7db024e..8db5f2e 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -91,8 +91,8 @@ struct slot {
 
 /* rpaphp_core.c */
 int rpaphp_add_slot(struct device_node *dn);
-int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
-		char **drc_name, char **drc_type, int *drc_power_domain);
+int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
+		char *drc_type);
 
 /* rpaphp_slot.c */
 void dealloc_slot_struct(struct slot *slot);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 8d13202..f9c9ce5 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -30,6 +30,7 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/vmalloc.h>
+#include <asm/firmware.h>
 #include <asm/eeh.h>       /* for eeh_add_device() */
 #include <asm/rtas.h>		/* rtas_call */
 #include <asm/pci-bridge.h>	/* for pci_controller */
@@ -196,25 +197,21 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes,
 	return 0;
 }
 
-/* To get the DRC props describing the current node, first obtain it's
- * my-drc-index property.  Next obtain the DRC list from it's parent.  Use
- * the my-drc-index for correlation, and obtain the requested properties.
+
+/* Verify the existence of 'drc_name' and/or 'drc_type' within the
+ * current node.  First obtain it's my-drc-index property.  Next,
+ * obtain the DRC info from it's parent.  Use the my-drc-index for
+ * correlation, and obtain/validate the requested properties.
  */
-int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
-		char **drc_name, char **drc_type, int *drc_power_domain)
+
+static int rpaphp_check_drc_props_v1(struct device_node *dn, char *drc_name,
+				char *drc_type, unsigned int my_index)
 {
+	char *name_tmp, *type_tmp;
 	const int *indexes, *names;
 	const int *types, *domains;
-	const unsigned int *my_index;
-	char *name_tmp, *type_tmp;
 	int i, rc;
 
-	my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
-	if (!my_index) {
-		/* Node isn't DLPAR/hotplug capable */
-		return -EINVAL;
-	}
-
 	rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
 	if (rc < 0) {
 		return -EINVAL;
@@ -225,24 +222,85 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
 
 	/* Iterate through parent properties, looking for my-drc-index */
 	for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
-		if ((unsigned int) indexes[i + 1] == *my_index) {
-			if (drc_name)
-				*drc_name = name_tmp;
-			if (drc_type)
-				*drc_type = type_tmp;
-			if (drc_index)
-				*drc_index = be32_to_cpu(*my_index);
-			if (drc_power_domain)
-				*drc_power_domain = be32_to_cpu(domains[i+1]);
-			return 0;
-		}
+		if ((unsigned int) indexes[i + 1] == my_index)
+			break;
+
 		name_tmp += (strlen(name_tmp) + 1);
 		type_tmp += (strlen(type_tmp) + 1);
 	}
 
+	if (((drc_name == NULL) || (drc_name && !strcmp(drc_name, name_tmp))) &&
+	    ((drc_type == NULL) || (drc_type && !strcmp(drc_type, type_tmp))))
+		return 0;
+
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
+
+static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
+				char *drc_type, unsigned int my_index)
+{
+	int *info = (int *)dn;
+	unsigned int entries;
+	unsigned long int drc_index_start = 0, last_drc_index = 0;
+	unsigned long int num_sequential_elems = 0, sequential_inc = 0;
+	char *name_tmp, *type_tmp;
+	int j;
+
+	info = (int *)of_get_property(dn->parent, "ibm,drc-info", NULL);
+	if (info == NULL)
+		return -EINVAL;
+
+	entries = be32_to_cpu(*info++);
+
+	for (j = 0; j < entries; j++) {
+		read_one_drc_info(&info, &type_tmp, &name_tmp,
+				&drc_index_start, &num_sequential_elems,
+				&sequential_inc, &last_drc_index);
+
+		/* Should now know end of current entry */
+
+		last_drc_index = drc_index_start +
+				((num_sequential_elems-1)*sequential_inc);
+
+		WARN_ON((my_index < drc_index_start) ||
+			(((my_index-drc_index_start)%sequential_inc) != 0));
+
+		if (my_index > last_drc_index)
+			continue;
+
+		break;
+	}
+	/* Found it */
+
+	if (((drc_name == NULL) ||
+	     (drc_name && !strcmp(drc_name, name_tmp))) &&
+	    ((drc_type == NULL) ||
+	     (drc_type && !strcmp(drc_type, type_tmp))))
+		return 0;
+
+	return -EINVAL;
+}
+
+int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
+			char *drc_type)
+{
+	const unsigned int *my_index;
+
+	my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
+	if (!my_index) {
+		/* Node isn't DLPAR/hotplug capable */
+		return -EINVAL;
+	}
+
+	if (firmware_has_feature(FW_FEATURE_DRC_INFO))
+		return rpaphp_check_drc_props_v2(dn, drc_name, drc_type,
+						*my_index);
+	else
+		return rpaphp_check_drc_props_v1(dn, drc_name, drc_type,
+						*my_index);
+}
+EXPORT_SYMBOL_GPL(rpaphp_check_drc_props);
+
 
 static int is_php_type(char *drc_type)
 {

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

* [PATCH V9 7/8] powerpc: Check arch.vec earlier during boot for memory features
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
                   ` (5 preceding siblings ...)
  2016-12-07  7:15 ` [PATCH V9 6/8] hotplug/drc-info: Add code to search new devtree properties Michael Bringmann
@ 2016-12-07  7:15 ` Michael Bringmann
  2016-12-12 15:39   ` Nathan Fontenot
  2016-12-07  7:16 ` [PATCH V9 8/8] powerpc: Enable support for new DRC devtree properties Michael Bringmann
  2017-01-24 19:41 ` [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
  8 siblings, 1 reply; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:15 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 2d49887..bd07157 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -759,6 +759,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);
@@ -826,9 +829,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] 19+ messages in thread

* [PATCH V9 8/8] powerpc: Enable support for new DRC devtree properties
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
                   ` (6 preceding siblings ...)
  2016-12-07  7:15 ` [PATCH V9 7/8] powerpc: Check arch.vec earlier during boot for memory features Michael Bringmann
@ 2016-12-07  7:16 ` Michael Bringmann
  2016-12-12 15:40   ` Nathan Fontenot
  2017-01-24 19:41 ` [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
  8 siblings, 1 reply; 19+ messages in thread
From: Michael Bringmann @ 2016-12-07  7:16 UTC (permalink / raw)
  To: ltc-virtual-io, linuxppc-dev; +Cc: nfont

prom_init.c: Enable support for new DRC device tree properties
"ibm,drc-info" and "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 |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 88ac964..6e6454f 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -696,7 +696,7 @@ static void __init early_cmdline_parse(void)
 	OV4_MIN_ENT_CAP,		/* minimum VP entitled capacity */
 
 	/* option vector 5: PAPR/OF options */
-	VECTOR_LENGTH(21),		/* length */
+	VECTOR_LENGTH(22),		/* length */
 	0,				/* don't ignore, don't halt */
 	OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
 	OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
@@ -732,6 +732,7 @@ static void __init early_cmdline_parse(void)
 	0,							/* Byte 19 */
 	0,							/* Byte 20 */
 	OV5_FEAT(OV5_SUB_PROCESSORS),				/* Byte 21 */
+	OV5_FEAT(OV5_DYN_MEM_V2) | OV5_FEAT(OV5_DRC_INFO),	/* Byte 22 */
 
 	/* option vector 6: IBM PAPR hints */
 	VECTOR_LENGTH(3),		/* length */

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

* Re: [PATCH V9 1/8] powerpc/firmware: Add definitions for new firmware features.
  2016-12-07  7:14 ` [PATCH V9 1/8] powerpc/firmware: Add definitions for new firmware features Michael Bringmann
@ 2016-12-12 15:19   ` Nathan Fontenot
  0 siblings, 0 replies; 19+ messages in thread
From: Nathan Fontenot @ 2016-12-12 15:19 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev

On 12/07/2016 01:14 AM, Michael Bringmann wrote:
> Firmware Features: Define new bit flags representing the presence of
> new device tree properties "ibm,drc-info", and "ibm,dynamic-memory-v2".
> These flags are used to tell the front end processor when the Linux
> kernel supports the new properties, and by the front end processor to
> tell the Linux kernel that the new properties are present in the devie
> tree.
> 
> Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>

Reviewed-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

> ---
>  arch/powerpc/include/asm/firmware.h       |    5 ++++-
>  arch/powerpc/include/asm/prom.h           |    2 ++
>  arch/powerpc/platforms/pseries/firmware.c |    2 ++
>  3 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
> index 1e0b5a5..6b5cf38 100644
> --- a/arch/powerpc/include/asm/firmware.h
> +++ b/arch/powerpc/include/asm/firmware.h
> @@ -51,6 +51,8 @@
>  #define FW_FEATURE_BEST_ENERGY	ASM_CONST(0x0000000080000000)
>  #define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
>  #define FW_FEATURE_PRRN		ASM_CONST(0x0000000200000000)
> +#define FW_FEATURE_DYN_MEM_V2	ASM_CONST(0x0000000400000000)
> +#define FW_FEATURE_DRC_INFO	ASM_CONST(0x0000000800000000)
> 
>  #ifndef __ASSEMBLY__
> 
> @@ -66,7 +68,8 @@ enum {
>  		FW_FEATURE_MULTITCE | FW_FEATURE_SPLPAR | FW_FEATURE_LPAR |
>  		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_TYPE1_AFFINITY | FW_FEATURE_PRRN |
> +		FW_FEATURE_DYN_MEM_V2 | FW_FEATURE_DRC_INFO,
>  	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 7f436ba..bc7c4b5 100644
> --- a/arch/powerpc/include/asm/prom.h
> +++ b/arch/powerpc/include/asm/prom.h
> @@ -155,6 +155,8 @@ struct of_drconf_cell {
>  #define OV5_PFO_HW_842		0x0E40	/* PFO Compression Accelerator */
>  #define OV5_PFO_HW_ENCR		0x0E20	/* PFO Encryption Accelerator */
>  #define OV5_SUB_PROCESSORS	0x0F01	/* 1,2,or 4 Sub-Processors supported */
> +#define OV5_DYN_MEM_V2		0x1680	/* Redef Prop Structures: dyn-mem-v2 */
> +#define OV5_DRC_INFO		0x1640	/* Redef Prop Structures: drc-info   */
> 
>  /* Option Vector 6: IBM PAPR hints */
>  #define OV6_LINUX		0x02	/* Linux is our OS */
> diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
> index ea7f09b..d2d23f5 100644
> --- a/arch/powerpc/platforms/pseries/firmware.c
> +++ b/arch/powerpc/platforms/pseries/firmware.c
> @@ -113,6 +113,8 @@ struct vec5_fw_feature {
>  vec5_fw_features_table[] = {
>  	{FW_FEATURE_TYPE1_AFFINITY,	OV5_TYPE1_AFFINITY},
>  	{FW_FEATURE_PRRN,		OV5_PRRN},
> +	{FW_FEATURE_DYN_MEM_V2,		OV5_DYN_MEM_V2},
> +	{FW_FEATURE_DRC_INFO,		OV5_DRC_INFO},
>  };
> 
>  static void __init fw_vec5_feature_init(const char *vec5, unsigned long len)
> 

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

* Re: [PATCH V9 2/8] powerpc/memory: Parse new memory property to register blocks.
  2016-12-07  7:14 ` [PATCH V9 2/8] powerpc/memory: Parse new memory property to register blocks Michael Bringmann
@ 2016-12-12 15:24   ` Nathan Fontenot
  0 siblings, 0 replies; 19+ messages in thread
From: Nathan Fontenot @ 2016-12-12 15:24 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev

On 12/07/2016 01:14 AM, Michael Bringmann wrote:
> 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>

Reviewed-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

> ---
>  arch/powerpc/include/asm/prom.h |   24 ++++++++--
>  arch/powerpc/kernel/prom.c      |   97 ++++++++++++++++++++++++++++++++++++---
>  arch/powerpc/mm/numa.c          |   22 ++++++++-
>  3 files changed, 129 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
> index bc7c4b5..43a002b 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);
> 
>  /*
>   * There are two methods for telling firmware what our capabilities are.
> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index b0245be..2d49887 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -443,23 +443,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))
> @@ -518,6 +529,76 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
>  	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 (iommu_is_off) {
> +				if (base >= 0x80000000ul)
> +					continue;
> +				if ((base + size) > 0x80000000ul)
> +					size = 0x80000000ul - base;
> +			}
> +			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 */
> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index a51c188..67dc989 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -57,8 +57,10 @@
>  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;
> +EXPORT_SYMBOL(n_mem_addr_cells);
> 
>  #define MAX_DISTANCE_REF_POINTS 4
>  static int distance_ref_points_depth;
> @@ -405,6 +407,24 @@ 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;
> +}
> +EXPORT_SYMBOL(read_drconf_cell_v2);
> 
>  /*
>   * Retrieve and validate the ibm,dynamic-memory property of the device tree.
> 

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

* Re: [PATCH V9 3/8] powerpc/memory: Parse new memory property to initialize structures.
  2016-12-07  7:14 ` [PATCH V9 3/8] powerpc/memory: Parse new memory property to initialize structures Michael Bringmann
@ 2016-12-12 15:27   ` Nathan Fontenot
  0 siblings, 0 replies; 19+ messages in thread
From: Nathan Fontenot @ 2016-12-12 15:27 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev

On 12/07/2016 01:14 AM, Michael Bringmann wrote:
> 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>

Reviewd-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

> ---
> Changes in V9:
>  - Remove unnecessary multiplier from a property length calculation
> ---
>  arch/powerpc/include/asm/prom.h |   12 +++
>  arch/powerpc/mm/numa.c          |  146 +++++++++++++++++++++++++++++++++------
>  2 files changed, 135 insertions(+), 23 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
> index 43a002b..01842a7 100644
> --- a/arch/powerpc/include/asm/prom.h
> +++ b/arch/powerpc/include/asm/prom.h
> @@ -110,6 +110,18 @@ struct of_drconf_cell_v2 {
>  extern void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem,
>  				const __be32 **cellp);
> 
> +extern void read_one_drc_info(int **info, char **drc_type, char **drc_name,
> +			unsigned long int *fdi_p, unsigned long int *nsl_p,
> +			unsigned long int *si_p, unsigned long int *ldi_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 67dc989..4cbcae8 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -427,30 +427,55 @@ void read_drconf_cell_v2(struct of_drconf_cell_v2 *drmem, const __be32 **cellp)
>  EXPORT_SYMBOL(read_drconf_cell_v2);
> 
>  /*
> - * 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;
>  }
> 
> @@ -513,7 +538,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;
> @@ -521,16 +546,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]);
>  		}
> @@ -665,7 +690,7 @@ static inline int __init read_usm_ranges(const __be32 **usm)
>   * 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)
>  {
>  	const __be32 *uninitialized_var(dm), *usm;
>  	unsigned int n, rc, ranges, is_kexec_kdump = 0;
> @@ -715,7 +740,8 @@ 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);
> +			nid = of_drconf_to_nid_single(drmem.flags,
> +							drmem.aa_index, &aa);
>  			fake_numa_create_new_node(
>  				((base + size) >> PAGE_SHIFT),
>  					   &nid);
> @@ -728,6 +754,80 @@ static void __init parse_drconf_memory(struct device_node *memory)
>  	}
>  }
> 
> +static void __init parse_drconf_memory_v2(struct device_node *memory)
> +{
> +	const __be32 *uninitialized_var(dm);
> +	unsigned int num_lmb_sets, rc;
> +	unsigned long lmb_size, base;
> +	unsigned long size, sz;
> +	int nid;
> +	struct assoc_arrays aa = { .arrays = NULL };
> +	const __be32 *prop;
> +	u32	len;
> +
> +	prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len);
> +	if (!prop)
> +		return;
> +
> +	num_lmb_sets = of_get_drconf_memory(memory, &dm);
> +	if (!num_lmb_sets)
> +		return;
> +
> +	lmb_size = of_get_lmb_size(memory);
> +	if (!lmb_size)
> +		return;
> +
> +	rc = of_get_assoc_arrays(memory, &aa);
> +	if (rc)
> +		return;
> +
> +	for (; num_lmb_sets != 0; num_lmb_sets--) {
> +		struct of_drconf_cell_v2 drmem;
> +		unsigned long nsl;
> +
> +		/* Get the current LMB set */
> +		read_drconf_cell_v2(&drmem, &dm);
> +		base = drmem.base_addr;
> +		nsl = drmem.num_seq_lmbs;
> +
> +		/* 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;
> +
> +		for (; nsl != 0; nsl--) {
> +			size = lmb_size;
> +
> +			nid = of_drconf_to_nid_single(drmem.flags,
> +						drmem.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);
> +
> +			base += sz;
> +		}
> +	}
> +}
> +
> +static void __init parse_drconf_memory(struct device_node *memory)
> +{
> +	const __be32 *prop;
> +	int len;
> +	prop = of_get_property(memory, "ibm,dynamic-memory-v2", &len);
> +	if (!prop || len < sizeof(unsigned int))
> +		parse_drconf_memory_v1(memory);
> +	else
> +		parse_drconf_memory_v2(memory);
> +}
> +
>  static int __init parse_numa_properties(void)
>  {
>  	struct device_node *memory;
> @@ -1046,8 +1146,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	[flat|nested] 19+ messages in thread

* Re: [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  2016-12-07  7:14 ` [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
@ 2016-12-12 15:29   ` Nathan Fontenot
  2017-01-31  2:53   ` Michael Ellerman
  1 sibling, 0 replies; 19+ messages in thread
From: Nathan Fontenot @ 2016-12-12 15:29 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev

On 12/07/2016 01:14 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>

Reviewd-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

> ---
> Changes in V9:
>   - Remove unnecessary field initialization in allocated memory block
> ---
>  arch/powerpc/platforms/pseries/Makefile         |    4 +
>  arch/powerpc/platforms/pseries/hotplug-memory.c |   92 +++++++++++++++++++++++
>  2 files changed, 94 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
> index fedc2ccf0..e74cf6c 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)	+= 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 76ec104..7b63639 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> @@ -24,6 +24,8 @@
>  #include <asm/sparsemem.h>
>  #include "pseries.h"
> 
> +#ifdef CONFIG_MEMORY_HOTPLUG
> +
>  static bool rtas_hp_event;
> 
>  unsigned long pseries_memory_block_size(void)
> @@ -887,11 +889,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] 19+ messages in thread

* Re: [PATCH V9 6/8] hotplug/drc-info: Add code to search new devtree properties
  2016-12-07  7:15 ` [PATCH V9 6/8] hotplug/drc-info: Add code to search new devtree properties Michael Bringmann
@ 2016-12-12 15:39   ` Nathan Fontenot
  0 siblings, 0 replies; 19+ messages in thread
From: Nathan Fontenot @ 2016-12-12 15:39 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev

On 12/07/2016 01:15 AM, Michael Bringmann wrote:
> rpadlpar_core.c: Provide parallel routines to search the older device-
> tree properties ("ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
> and "ibm,drc-power-domains"), or the new property "ibm,drc-info".
> 
> The interface to examine the DRC information is changed from a "get"
> function that returns values for local verification elsewhere, to a
> "check" function that validates the 'name' and/or 'type' of a device
> node.  This update hides the format of the underlying device-tree
> properties, and concentrates the value checks into a single function
> without requiring the user to verify whether a search was successful.
> 
> Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>

Reviewed-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

> ---
> Changes in V9:
>   -- Remove unnecessary code from rpaphp_check_drc_props_v2()
> ---
>  drivers/pci/hotplug/rpadlpar_core.c |   13 ++--
>  drivers/pci/hotplug/rpaphp.h        |    4 +
>  drivers/pci/hotplug/rpaphp_core.c   |  108 +++++++++++++++++++++++++++--------
>  3 files changed, 90 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
> index dc67f39..bea9723 100644
> --- a/drivers/pci/hotplug/rpadlpar_core.c
> +++ b/drivers/pci/hotplug/rpadlpar_core.c
> @@ -27,6 +27,7 @@
>  #include <linux/mutex.h>
>  #include <asm/rtas.h>
>  #include <asm/vio.h>
> +#include <linux/firmware.h>
> 
>  #include "../pci.h"
>  #include "rpaphp.h"
> @@ -44,15 +45,14 @@ static struct device_node *find_vio_slot_node(char *drc_name)
>  {
>  	struct device_node *parent = of_find_node_by_name(NULL, "vdevice");
>  	struct device_node *dn = NULL;
> -	char *name;
>  	int rc;
> 
>  	if (!parent)
>  		return NULL;
> 
>  	while ((dn = of_get_next_child(parent, dn))) {
> -		rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
> -		if ((rc == 0) && (!strcmp(drc_name, name)))
> +		rc = rpaphp_check_drc_props(dn, drc_name, NULL);
> +		if (rc == 0)
>  			break;
>  	}
> 
> @@ -64,15 +64,12 @@ static struct device_node *find_php_slot_pci_node(char *drc_name,
>  						  char *drc_type)
>  {
>  	struct device_node *np = NULL;
> -	char *name;
> -	char *type;
>  	int rc;
> 
>  	while ((np = of_find_node_by_name(np, "pci"))) {
> -		rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL);
> +		rc = rpaphp_check_drc_props(np, drc_name, drc_type);
>  		if (rc == 0)
> -			if (!strcmp(drc_name, name) && !strcmp(drc_type, type))
> -				break;
> +			break;
>  	}
> 
>  	return np;
> diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
> index 7db024e..8db5f2e 100644
> --- a/drivers/pci/hotplug/rpaphp.h
> +++ b/drivers/pci/hotplug/rpaphp.h
> @@ -91,8 +91,8 @@ struct slot {
> 
>  /* rpaphp_core.c */
>  int rpaphp_add_slot(struct device_node *dn);
> -int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
> -		char **drc_name, char **drc_type, int *drc_power_domain);
> +int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
> +		char *drc_type);
> 
>  /* rpaphp_slot.c */
>  void dealloc_slot_struct(struct slot *slot);
> diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
> index 8d13202..f9c9ce5 100644
> --- a/drivers/pci/hotplug/rpaphp_core.c
> +++ b/drivers/pci/hotplug/rpaphp_core.c
> @@ -30,6 +30,7 @@
>  #include <linux/smp.h>
>  #include <linux/init.h>
>  #include <linux/vmalloc.h>
> +#include <asm/firmware.h>
>  #include <asm/eeh.h>       /* for eeh_add_device() */
>  #include <asm/rtas.h>		/* rtas_call */
>  #include <asm/pci-bridge.h>	/* for pci_controller */
> @@ -196,25 +197,21 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes,
>  	return 0;
>  }
> 
> -/* To get the DRC props describing the current node, first obtain it's
> - * my-drc-index property.  Next obtain the DRC list from it's parent.  Use
> - * the my-drc-index for correlation, and obtain the requested properties.
> +
> +/* Verify the existence of 'drc_name' and/or 'drc_type' within the
> + * current node.  First obtain it's my-drc-index property.  Next,
> + * obtain the DRC info from it's parent.  Use the my-drc-index for
> + * correlation, and obtain/validate the requested properties.
>   */
> -int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
> -		char **drc_name, char **drc_type, int *drc_power_domain)
> +
> +static int rpaphp_check_drc_props_v1(struct device_node *dn, char *drc_name,
> +				char *drc_type, unsigned int my_index)
>  {
> +	char *name_tmp, *type_tmp;
>  	const int *indexes, *names;
>  	const int *types, *domains;
> -	const unsigned int *my_index;
> -	char *name_tmp, *type_tmp;
>  	int i, rc;
> 
> -	my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
> -	if (!my_index) {
> -		/* Node isn't DLPAR/hotplug capable */
> -		return -EINVAL;
> -	}
> -
>  	rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
>  	if (rc < 0) {
>  		return -EINVAL;
> @@ -225,24 +222,85 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
> 
>  	/* Iterate through parent properties, looking for my-drc-index */
>  	for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
> -		if ((unsigned int) indexes[i + 1] == *my_index) {
> -			if (drc_name)
> -				*drc_name = name_tmp;
> -			if (drc_type)
> -				*drc_type = type_tmp;
> -			if (drc_index)
> -				*drc_index = be32_to_cpu(*my_index);
> -			if (drc_power_domain)
> -				*drc_power_domain = be32_to_cpu(domains[i+1]);
> -			return 0;
> -		}
> +		if ((unsigned int) indexes[i + 1] == my_index)
> +			break;
> +
>  		name_tmp += (strlen(name_tmp) + 1);
>  		type_tmp += (strlen(type_tmp) + 1);
>  	}
> 
> +	if (((drc_name == NULL) || (drc_name && !strcmp(drc_name, name_tmp))) &&
> +	    ((drc_type == NULL) || (drc_type && !strcmp(drc_type, type_tmp))))
> +		return 0;
> +
>  	return -EINVAL;
>  }
> -EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
> +
> +static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
> +				char *drc_type, unsigned int my_index)
> +{
> +	int *info = (int *)dn;
> +	unsigned int entries;
> +	unsigned long int drc_index_start = 0, last_drc_index = 0;
> +	unsigned long int num_sequential_elems = 0, sequential_inc = 0;
> +	char *name_tmp, *type_tmp;
> +	int j;
> +
> +	info = (int *)of_get_property(dn->parent, "ibm,drc-info", NULL);
> +	if (info == NULL)
> +		return -EINVAL;
> +
> +	entries = be32_to_cpu(*info++);
> +
> +	for (j = 0; j < entries; j++) {
> +		read_one_drc_info(&info, &type_tmp, &name_tmp,
> +				&drc_index_start, &num_sequential_elems,
> +				&sequential_inc, &last_drc_index);
> +
> +		/* Should now know end of current entry */
> +
> +		last_drc_index = drc_index_start +
> +				((num_sequential_elems-1)*sequential_inc);
> +
> +		WARN_ON((my_index < drc_index_start) ||
> +			(((my_index-drc_index_start)%sequential_inc) != 0));
> +
> +		if (my_index > last_drc_index)
> +			continue;
> +
> +		break;
> +	}
> +	/* Found it */
> +
> +	if (((drc_name == NULL) ||
> +	     (drc_name && !strcmp(drc_name, name_tmp))) &&
> +	    ((drc_type == NULL) ||
> +	     (drc_type && !strcmp(drc_type, type_tmp))))
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
> +			char *drc_type)
> +{
> +	const unsigned int *my_index;
> +
> +	my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
> +	if (!my_index) {
> +		/* Node isn't DLPAR/hotplug capable */
> +		return -EINVAL;
> +	}
> +
> +	if (firmware_has_feature(FW_FEATURE_DRC_INFO))
> +		return rpaphp_check_drc_props_v2(dn, drc_name, drc_type,
> +						*my_index);
> +	else
> +		return rpaphp_check_drc_props_v1(dn, drc_name, drc_type,
> +						*my_index);
> +}
> +EXPORT_SYMBOL_GPL(rpaphp_check_drc_props);
> +
> 
>  static int is_php_type(char *drc_type)
>  {
> 

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

* Re: [PATCH V9 7/8] powerpc: Check arch.vec earlier during boot for memory features
  2016-12-07  7:15 ` [PATCH V9 7/8] powerpc: Check arch.vec earlier during boot for memory features Michael Bringmann
@ 2016-12-12 15:39   ` Nathan Fontenot
  0 siblings, 0 replies; 19+ messages in thread
From: Nathan Fontenot @ 2016-12-12 15:39 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev

On 12/07/2016 01:15 AM, Michael Bringmann wrote:
> 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>

Reviewed-by: Nathan Fontenot <nfont@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 2d49887..bd07157 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -759,6 +759,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);
> @@ -826,9 +829,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	[flat|nested] 19+ messages in thread

* Re: [PATCH V9 8/8] powerpc: Enable support for new DRC devtree properties
  2016-12-07  7:16 ` [PATCH V9 8/8] powerpc: Enable support for new DRC devtree properties Michael Bringmann
@ 2016-12-12 15:40   ` Nathan Fontenot
  0 siblings, 0 replies; 19+ messages in thread
From: Nathan Fontenot @ 2016-12-12 15:40 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev

On 12/07/2016 01:16 AM, Michael Bringmann wrote:
> prom_init.c: Enable support for new DRC device tree properties
> "ibm,drc-info" and "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>

Reviewed-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

> ---
>  arch/powerpc/kernel/prom_init.c |    3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index 88ac964..6e6454f 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -696,7 +696,7 @@ static void __init early_cmdline_parse(void)
>  	OV4_MIN_ENT_CAP,		/* minimum VP entitled capacity */
> 
>  	/* option vector 5: PAPR/OF options */
> -	VECTOR_LENGTH(21),		/* length */
> +	VECTOR_LENGTH(22),		/* length */
>  	0,				/* don't ignore, don't halt */
>  	OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
>  	OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
> @@ -732,6 +732,7 @@ static void __init early_cmdline_parse(void)
>  	0,							/* Byte 19 */
>  	0,							/* Byte 20 */
>  	OV5_FEAT(OV5_SUB_PROCESSORS),				/* Byte 21 */
> +	OV5_FEAT(OV5_DYN_MEM_V2) | OV5_FEAT(OV5_DRC_INFO),	/* Byte 22 */
> 
>  	/* option vector 6: IBM PAPR hints */
>  	VECTOR_LENGTH(3),		/* length */
> 

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

* Re: [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties
  2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
                   ` (7 preceding siblings ...)
  2016-12-07  7:16 ` [PATCH V9 8/8] powerpc: Enable support for new DRC devtree properties Michael Bringmann
@ 2017-01-24 19:41 ` Michael Bringmann
  8 siblings, 0 replies; 19+ messages in thread
From: Michael Bringmann @ 2017-01-24 19:41 UTC (permalink / raw)
  To: linuxppc-dev, ltc-virtual-io, linuxppc-dev, ; +Cc: nfont

Ping

On 12/07/2016 01:13 AM, Michael Bringmann wrote:
> Several properties in the DRC device tree format are replaced by
> more compact representations to allow, for example, for the encoding
> of vast amounts of memory, and or reduced duplication of information
> in related data structures.
> 
> "ibm,drc-info": This property, when present, replaces the following
> four properties: "ibm,drc-indexes", "ibm,drc-names", "ibm,drc-types"
> and "ibm,drc-power-domains".  This property is defined for all
> dynamically reconfigurable platform nodes.  The "ibm,drc-info" elements
> are intended to provide a more compact representation, and reduce some
> search overhead.
> 
> "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 structures "ibm,drc-info" and
> "ibm,dynamic-memory-v2".
> 
> Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
> 
> Michael Bringmann (8):
>   powerpc/firmware: Add definitions for new firmware 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
>   pseries/drc-info: Search new DRC properties for CPU indexes
>   hotplug/drc-info: Add code to search new devtree properties
>   powerpc: Check arch.vec earlier during boot for memory features
>   powerpc: Enable support for new DRC devtree properties
> ---
> Changes in V9:
>   -- Various code cleanup measures
> 
>  arch/powerpc/include/asm/firmware.h             |    5 -
>  arch/powerpc/include/asm/prom.h                 |   38 ++++
>  arch/powerpc/kernel/prom.c                      |  103 ++++++++++--
>  arch/powerpc/kernel/prom_init.c                 |    3 
>  arch/powerpc/mm/numa.c                          |  168 ++++++++++++++++---
>  arch/powerpc/platforms/pseries/firmware.c       |    2 
>  arch/powerpc/platforms/pseries/pseries_energy.c |  202 ++++++++++++++++++++---
>  drivers/pci/hotplug/rpadlpar_core.c             |   13 +
>  drivers/pci/hotplug/rpaphp.h                    |    4 
>  drivers/pci/hotplug/rpaphp_core.c               |  108 +++++++++---
>  10 files changed, 543 insertions(+), 103 deletions(-)
> 
> 

-- 
Michael W. Bringmann
Linux Technology Center
IBM Corporation
Tie-Line  363-5196
External: (512) 286-5196
Cell:       (512) 466-0650
mwb@linux.vnet.ibm.com

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

* Re: [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  2016-12-07  7:14 ` [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
  2016-12-12 15:29   ` Nathan Fontenot
@ 2017-01-31  2:53   ` Michael Ellerman
  2017-02-01 16:27     ` [PATCH V10 " Michael Bringmann
  1 sibling, 1 reply; 19+ messages in thread
From: Michael Ellerman @ 2017-01-31  2:53 UTC (permalink / raw)
  To: Michael Bringmann, ltc-virtual-io, linuxppc-dev; +Cc: nfont

Michael Bringmann <mwb@linux.vnet.ibm.com> writes:

> 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>

This is breaking the ppc64_defconfig build:

  arch/powerpc/platforms/built-in.o: In function `.__machine_initcall_pseries_pseries_memory_hotplug_init':
  hotplug-memory.c:(.init.text+0x8cdc): undefined reference to `.pseries_memory_block_size'


cheers

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

* [PATCH V10 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime
  2017-01-31  2:53   ` Michael Ellerman
@ 2017-02-01 16:27     ` Michael Bringmann
  0 siblings, 0 replies; 19+ messages in thread
From: Michael Bringmann @ 2017-02-01 16:27 UTC (permalink / raw)
  To: Michael Ellerman, 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>
Reviewed-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
---
Changes in V10:
  - Fix export of pseries_memory_block_size() for pseries_defconfig config.
---
 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 2617f9f..497a916 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);
@@ -890,11 +892,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] 19+ messages in thread

end of thread, other threads:[~2017-02-01 16:27 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-07  7:13 [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties Michael Bringmann
2016-12-07  7:14 ` [PATCH V9 1/8] powerpc/firmware: Add definitions for new firmware features Michael Bringmann
2016-12-12 15:19   ` Nathan Fontenot
2016-12-07  7:14 ` [PATCH V9 2/8] powerpc/memory: Parse new memory property to register blocks Michael Bringmann
2016-12-12 15:24   ` Nathan Fontenot
2016-12-07  7:14 ` [PATCH V9 3/8] powerpc/memory: Parse new memory property to initialize structures Michael Bringmann
2016-12-12 15:27   ` Nathan Fontenot
2016-12-07  7:14 ` [PATCH V9 4/8] pseries/hotplug init: Convert new DRC memory property for hotplug runtime Michael Bringmann
2016-12-12 15:29   ` Nathan Fontenot
2017-01-31  2:53   ` Michael Ellerman
2017-02-01 16:27     ` [PATCH V10 " Michael Bringmann
2016-12-07  7:15 ` [PATCH V9 5/8] pseries/drc-info: Search new DRC properties for CPU indexes Michael Bringmann
2016-12-07  7:15 ` [PATCH V9 6/8] hotplug/drc-info: Add code to search new devtree properties Michael Bringmann
2016-12-12 15:39   ` Nathan Fontenot
2016-12-07  7:15 ` [PATCH V9 7/8] powerpc: Check arch.vec earlier during boot for memory features Michael Bringmann
2016-12-12 15:39   ` Nathan Fontenot
2016-12-07  7:16 ` [PATCH V9 8/8] powerpc: Enable support for new DRC devtree properties Michael Bringmann
2016-12-12 15:40   ` Nathan Fontenot
2017-01-24 19:41 ` [PATCH V9 0/8] powerpc/devtree: Add support for 2 new DRC properties 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.