[v2,1/2] hdata: Add memory hierarchy under xscom node

Message ID 20171013112119.30164-1-hegdevasant@linux.vnet.ibm.com
State New
Headers show
Series
  • [v2,1/2] hdata: Add memory hierarchy under xscom node
Related show

Commit Message

Vasant Hegde Oct. 13, 2017, 11:21 a.m.
We have memory to chip mapping but doesn't have complete memory hierarchy.
This patch adds memory hierarchy under xscom node. This is specific to
P9 system as these hierarchy may change between processor generation.

It uses memory controller ID details and populates nodes like:
  xscom@<addr>/mcbist@<mcbist_id>/mcs@<mcs_id>/mca@<mca_id>/dimm@<resource_id>

Also this patch adds few properties under dimm node.
Finally make sure xscom nodes created before calling memory_parse().

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
---
 hdata/memory.c               | 130 ++++++++++++++++++++++++++++++++++++++++++-
 hdata/spira.c                |   6 +-
 hdata/test/p8-840-spira.dts  |  10 ++--
 hdata/test/p81-811.spira.dts |  20 +++----
 4 files changed, 146 insertions(+), 20 deletions(-)

Patch

diff --git a/hdata/memory.c b/hdata/memory.c
index dbb0ac4..74eedff 100644
--- a/hdata/memory.c
+++ b/hdata/memory.c
@@ -22,6 +22,7 @@ 
 #include <mem_region.h>
 #include <types.h>
 #include <inttypes.h>
+#include <processor.h>
 
 #include "spira.h"
 #include "hdata.h"
@@ -44,8 +45,13 @@  struct HDIF_ms_area_address_range {
 	__be32 chip;
 	__be32 mirror_attr;
 	__be64 mirror_start;
+	__be32 controller_id;
 } __packed;
 
+#define MS_CONTROLLER_MCBIST_ID(id)	GETFIELD(PPC_BITMASK32(0, 1), id)
+#define MS_CONTROLLER_MCS_ID(id)	GETFIELD(PPC_BITMASK32(4, 7), id)
+#define MS_CONTROLLER_MCA_ID(id)	GETFIELD(PPC_BITMASK32(8, 15), id)
+
 struct HDIF_ms_area_id {
 	__be16 id;
 #define MS_PTYPE_RISER_CARD	0x8000
@@ -313,6 +319,121 @@  static void vpd_add_ram_area(const struct HDIF_common_hdr *msarea)
 	}
 }
 
+static void add_mca_dimm_info(struct dt_node *mca,
+			      const struct HDIF_common_hdr *msarea)
+{
+	unsigned int i;
+	const struct HDIF_child_ptr *ramptr;
+	const struct HDIF_common_hdr *ramarea;
+	const struct spira_fru_id *fru_id;
+	const struct HDIF_ram_area_id *ram_id;
+	const struct HDIF_ram_area_size *ram_area_sz;
+	struct dt_node *dimm;
+
+	ramptr = HDIF_child_arr(msarea, 0);
+	if (!CHECK_SPPTR(ramptr)) {
+		prerror("MS AREA: No RAM area at %p\n", msarea);
+		return;
+	}
+
+	for (i = 0; i < be32_to_cpu(ramptr->count); i++) {
+		ramarea = HDIF_child(msarea, ramptr, i, "RAM   ");
+		if (!CHECK_SPPTR(ramarea))
+			continue;
+
+		fru_id = HDIF_get_idata(ramarea, 0, NULL);
+		if (!fru_id)
+			continue;
+
+		/* Use Resource ID to add dimm node */
+		dimm = dt_find_by_name_addr(mca, "dimm",
+					    be16_to_cpu(fru_id->rsrc_id));
+		if (dimm)
+			continue;
+		dimm= dt_new_addr(mca, "dimm", be16_to_cpu(fru_id->rsrc_id));
+		assert(dimm);
+		dt_add_property_cells(dimm, "reg", be16_to_cpu(fru_id->rsrc_id));
+
+		/* Add location code */
+		slca_vpd_add_loc_code(dimm, be16_to_cpu(fru_id->slca_index));
+
+		/* DIMM size */
+		ram_area_sz = HDIF_get_idata(ramarea, 3, NULL);
+		if (!CHECK_SPPTR(ram_area_sz))
+			continue;
+		dt_add_property_cells(dimm, "size", be32_to_cpu(ram_area_sz->mb));
+
+		/* DIMM state */
+		ram_id = HDIF_get_idata(ramarea, 2, NULL);
+		if (!CHECK_SPPTR(ram_id))
+			continue;
+
+		if ((be16_to_cpu(ram_id->flags) & RAM_AREA_INSTALLED) &&
+		    (be16_to_cpu(ram_id->flags) & RAM_AREA_FUNCTIONAL))
+			dt_add_property_string(dimm, "status", "okay");
+		else
+			dt_add_property_string(dimm, "status", "disabled");
+	}
+}
+
+static inline void dt_add_mem_reg_property(struct dt_node *node, u64 addr)
+{
+	dt_add_property_cells(node, "#address-cells", 1);
+	dt_add_property_cells(node, "#size-cells", 0);
+	dt_add_property_cells(node, "reg", addr);
+}
+
+static void add_memory_controller(const struct HDIF_common_hdr *msarea,
+				  const struct HDIF_ms_area_address_range *arange)
+{
+	uint32_t chip_id, version;
+	uint32_t controller_id, mcbist_id, mcs_id, mca_id;
+	struct dt_node *xscom, *mcbist, *mcs, *mca;
+
+	/*
+	 * Memory hierarchy may change between processor version. Presently
+	 * its creating memory hierarchy for P9 (Nimbus) only.
+	 */
+	version = PVR_TYPE(mfspr(SPR_PVR));
+	if (version != PVR_TYPE_P9)
+		return;
+
+	chip_id = pcid_to_chip_id(be32_to_cpu(arange->chip));
+	controller_id = be32_to_cpu(arange->controller_id);
+	xscom = find_xscom_for_chip(chip_id);
+	if (!xscom) {
+		prlog(PR_WARNING,
+		      "MS AREA: Can't find XSCOM for chip %d\n", chip_id);
+		return;
+	}
+
+	mcbist_id = MS_CONTROLLER_MCBIST_ID(controller_id);
+	mcbist = dt_find_by_name_addr(xscom, "mcbist", mcbist_id);
+	if (!mcbist) {
+		mcbist = dt_new_addr(xscom, "mcbist", mcbist_id);
+		assert(mcbist);
+		dt_add_mem_reg_property(mcbist, mcbist_id);
+	}
+
+	mcs_id = MS_CONTROLLER_MCS_ID(controller_id);
+	mcs = dt_find_by_name_addr(mcbist, "mcs", mcs_id);
+	if (!mcs) {
+		mcs = dt_new_addr(mcbist, "mcs", mcs_id);
+		assert(mcs);
+		dt_add_mem_reg_property(mcs, mcs_id);
+	}
+
+	mca_id = MS_CONTROLLER_MCA_ID(controller_id);
+	mca = dt_find_by_name_addr(mcs, "mca", mca_id);
+	if (!mca) {
+		mca = dt_new_addr(mcs, "mca", mca_id);
+		assert(mca);
+		dt_add_mem_reg_property(mca, mca_id);
+	}
+
+	add_mca_dimm_info(mca, msarea);
+}
+
 static void get_msareas(struct dt_node *root,
 			const struct HDIF_common_hdr *ms_vpd)
 {
@@ -332,7 +453,7 @@  static void get_msareas(struct dt_node *root,
 		const struct HDIF_ms_area_address_range *arange;
 		const struct HDIF_ms_area_id *id;
 		const void *fruid;
-		unsigned int size, j;
+		unsigned int size, j, offset;
 		u16 flags;
 
 		msarea = HDIF_child(ms_vpd, msptr, i, "MSAREA");
@@ -372,7 +493,8 @@  static void get_msareas(struct dt_node *root,
 			return;
 		}
 
-		if (be32_to_cpu(arr->eactsz) < sizeof(*arange)) {
+		offset = offsetof(struct HDIF_ms_area_address_range, mirror_start);
+		if (be32_to_cpu(arr->eactsz) < offset) {
 			prerror("MS VPD: %p msarea #%i arange size too small!\n",
 				ms_vpd, i);
 			return;
@@ -392,6 +514,10 @@  static void get_msareas(struct dt_node *root,
 		/* This offset is from the arr, not the header! */
 		arange = (void *)arr + be32_to_cpu(arr->offset);
 		for (j = 0; j < be32_to_cpu(arr->ecnt); j++) {
+			offset = offsetof(struct HDIF_ms_area_address_range, controller_id);
+			if (be32_to_cpu(arr->eactsz) >= offset)
+				add_memory_controller(msarea, arange);
+
 			if (!add_address_range(root, id, arange))
 				return;
 			arange = (void *)arange + be32_to_cpu(arr->esize);
diff --git a/hdata/spira.c b/hdata/spira.c
index adaa604..a13f38e 100644
--- a/hdata/spira.c
+++ b/hdata/spira.c
@@ -1581,12 +1581,12 @@  int parse_hdat(bool is_opal)
 	/* IPL params */
 	add_iplparams();
 
-	/* Parse MS VPD */
-	memory_parse();
-
 	/* Add XSCOM node (must be before chiptod, IO and FSP) */
 	add_xscom();
 
+	/* Parse MS VPD */
+	memory_parse();
+
 	/* Add any FSPs */
 	fsp_parse();
 
diff --git a/hdata/test/p8-840-spira.dts b/hdata/test/p8-840-spira.dts
index a384434..5ba5149 100644
--- a/hdata/test/p8-840-spira.dts
+++ b/hdata/test/p8-840-spira.dts
@@ -568,7 +568,7 @@ 
 	};
 
 	memory@0 {
-		phandle = <0x41>;
+		phandle = <0x45>;
 		device_type = "memory";
 		ibm,chip-id = <0x0>;
 		reg = <0x0 0x0 0x8 0x0>;
@@ -864,7 +864,7 @@ 
 	};
 
 	xscom@3fc0000000000 {
-		phandle = <0x42>;
+		phandle = <0x41>;
 		ibm,chip-id = <0x0>;
 		ibm,proc-chip-id = <0x0>;
 		#address-cells = <0x1>;
@@ -917,7 +917,7 @@ 
 		};
 
 		psihb@2010900 {
-			phandle = <0x43>;
+			phandle = <0x42>;
 			reg = <0x2010900 0x20>;
 			compatible = "ibm,power8-psihb-x", "ibm,psihb-x";
 			boot-link;
@@ -926,7 +926,7 @@ 
 	};
 
 	xscom@3fc0800000000 {
-		phandle = <0x44>;
+		phandle = <0x43>;
 		ibm,chip-id = <0x1>;
 		ibm,proc-chip-id = <0x1>;
 		#address-cells = <0x1>;
@@ -979,7 +979,7 @@ 
 		};
 
 		psihb@2010900 {
-			phandle = <0x45>;
+			phandle = <0x44>;
 			reg = <0x2010900 0x20>;
 			compatible = "ibm,power8-psihb-x", "ibm,psihb-x";
 		};
diff --git a/hdata/test/p81-811.spira.dts b/hdata/test/p81-811.spira.dts
index c0976e6..43891bb 100644
--- a/hdata/test/p81-811.spira.dts
+++ b/hdata/test/p81-811.spira.dts
@@ -1660,14 +1660,14 @@ 
 	};
 
 	memory@0 {
-		phandle = <0x81>;
+		phandle = <0x89>;
 		device_type = "memory";
 		ibm,chip-id = <0x0>;
 		reg = <0x0 0x0 0x10 0x0>;
 	};
 
 	memory@1000000000 {
-		phandle = <0x82>;
+		phandle = <0x8a>;
 		device_type = "memory";
 		ibm,chip-id = <0x10>;
 		reg = <0x10 0x0 0x10 0x0>;
@@ -2059,7 +2059,7 @@ 
 	};
 
 	xscom@3fc0000000000 {
-		phandle = <0x83>;
+		phandle = <0x81>;
 		ibm,chip-id = <0x0>;
 		ibm,proc-chip-id = <0x0>;
 		#address-cells = <0x1>;
@@ -2112,7 +2112,7 @@ 
 		};
 
 		psihb@2010900 {
-			phandle = <0x84>;
+			phandle = <0x82>;
 			reg = <0x2010900 0x20>;
 			compatible = "ibm,power8-psihb-x", "ibm,psihb-x";
 			boot-link;
@@ -2121,7 +2121,7 @@ 
 	};
 
 	xscom@3fc0800000000 {
-		phandle = <0x85>;
+		phandle = <0x83>;
 		ibm,chip-id = <0x1>;
 		ibm,proc-chip-id = <0x1>;
 		#address-cells = <0x1>;
@@ -2173,14 +2173,14 @@ 
 		};
 
 		psihb@2010900 {
-			phandle = <0x86>;
+			phandle = <0x84>;
 			reg = <0x2010900 0x20>;
 			compatible = "ibm,power8-psihb-x", "ibm,psihb-x";
 		};
 	};
 
 	xscom@3fc8000000000 {
-		phandle = <0x87>;
+		phandle = <0x85>;
 		ibm,chip-id = <0x10>;
 		ibm,proc-chip-id = <0x2>;
 		#address-cells = <0x1>;
@@ -2222,7 +2222,7 @@ 
 		};
 
 		psihb@2010900 {
-			phandle = <0x88>;
+			phandle = <0x86>;
 			reg = <0x2010900 0x20>;
 			compatible = "ibm,power8-psihb-x", "ibm,psihb-x";
 			status = "ok";
@@ -2230,7 +2230,7 @@ 
 	};
 
 	xscom@3fc8800000000 {
-		phandle = <0x89>;
+		phandle = <0x87>;
 		ibm,chip-id = <0x11>;
 		ibm,proc-chip-id = <0x3>;
 		#address-cells = <0x1>;
@@ -2282,7 +2282,7 @@ 
 		};
 
 		psihb@2010900 {
-			phandle = <0x8a>;
+			phandle = <0x88>;
 			reg = <0x2010900 0x20>;
 			compatible = "ibm,power8-psihb-x", "ibm,psihb-x";
 		};