[Skiboot] [PATCH v4 4/9] nest unit parser and nest mcs unit support functions

Madhavan Srinivasan maddy at linux.vnet.ibm.com
Mon Aug 17 03:19:22 AEST 2015


Add catalog parser function to detect Nest units. Add
support functions for nest memory control subsystem (mcs) unit.
Support function will add device tree entry for each
event supported by mcs unit and a corresponding
unit and scale file to pass on information.

Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
---
 hw/nest.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 133 insertions(+)

diff --git a/hw/nest.c b/hw/nest.c
index 77fa271b71f7..cdf638c7bd8f 100644
--- a/hw/nest.c
+++ b/hw/nest.c
@@ -27,6 +27,8 @@
 #include <io.h>
 #include <platform.h>
 
+#define MAX_NAME_SIZE	64
+
 /*
  * Pointer holding the Catalog file in memory
  */
@@ -40,6 +42,129 @@ struct nest_catalog_desc *catalog_desc;
  */
 struct nest_catalog_page_0 *page0_desc;
 
+static u32 get_chip_event_offset(int idx, int domain)
+{
+	char *marker;
+	struct nest_catalog_events_data *ev;
+	int i;
+
+	if (domain == DOMAIN_CHIP)
+		marker = CHIP_EVENT_ENTRY(catalog_desc);
+	else
+		marker = CORE_EVENT_ENTRY(catalog_desc);
+
+	ev = (struct nest_catalog_events_data *)marker;
+	for (i = 0; i < idx ; i++) {
+		marker += ev->length;
+		ev = (struct nest_catalog_events_data *)marker;
+	}
+
+	return (ev->event_group_record_offs + ev->event_counter_offs);
+}
+
+static void dt_create_nest_unit_events(struct dt_node *ima, u32 offset,
+					const char *name, const char *scale,
+					const char *unit)
+{
+	char ev_name[MAX_NAME_SIZE];
+
+	dt_add_property_cells(ima, name, offset);
+
+	if (unit) {
+		snprintf(ev_name, MAX_NAME_SIZE, "%s.unit", name);
+		dt_add_property_string(ima, ev_name, unit);
+	}
+
+	if (scale) {
+		snprintf(ev_name, MAX_NAME_SIZE, "%s.scale", name);
+		dt_add_property_string(ima, ev_name, scale);
+	}
+}
+
+static int dt_create_nest_mcs_node(struct dt_node *ima,
+		struct nest_catalog_group_data *gptr, const char *name)
+{
+	struct dt_node *type;
+	int idx;
+	u32 offset;
+	const char ev_name[MAX_NAME_SIZE];
+	const char *unit = "MiB", *scale = "1.2207e-4";
+
+	type = dt_new(ima, name);
+	if (!type) {
+		prlog(PR_ERR, "nest_counters: %s type creation failed\n", name);
+		return -1;
+	}
+
+	/*
+	 *  Create device tree entries for events in this group
+	 */
+	dt_add_property_strings(type, "compatible", "ibm,nest-counters-chip");
+	for (idx = 0; idx < (gptr->event_count / 2); idx++) {
+		snprintf((char *)ev_name, MAX_NAME_SIZE, "mcs0%d", idx);
+		offset = get_chip_event_offset(gptr->event_index[idx],
+								DOMAIN_CHIP);
+		dt_create_nest_unit_events(type, offset, ev_name, scale, unit);
+	}
+
+	return 0;
+}
+
+/*
+ * Wrapper function to call corresponding nest unit functions
+ * for event dt creation. Not all the chip groups in the catalog are
+ * supported at this point.
+ */
+static int dt_create_nest_unit(struct dt_node *ima,
+				struct nest_catalog_group_data *gptr)
+{
+	char *name;
+
+	/*
+	 * Names provided in the catalog for each nest group/unit are
+	 * not valid device tree node names.
+	 */
+	const char mcs_read[] = "mcs_read", mcs_write[] = "mcs_write";
+
+	name = malloc(gptr->group_name_len);
+	if (!name)
+		return OPAL_NO_MEM;
+
+	memcpy((void *)name, (void *)gptr->remainder, gptr->group_name_len);
+	if (strstr(name, "MCS_Read_BW")) {
+		if (dt_create_nest_mcs_node(ima, gptr, mcs_read))
+			goto out;
+	} else if (strstr(name, "MCS_Write_BW")) {
+		if (dt_create_nest_mcs_node(ima, gptr, mcs_write))
+			goto out;
+	} else
+		free(name);
+
+	return OPAL_SUCCESS;
+out:
+	free(name);
+	return OPAL_RESOURCE;
+}
+
+static int detect_nest_units(struct dt_node *ima)
+{
+	struct nest_catalog_group_data *group_ptr;
+	char *marker;
+	int rc = CHIP_EVENTS_NOT_SUPPORTED;
+
+	marker = CHIP_GROUP_ENTRY(catalog_desc);
+	group_ptr = (struct nest_catalog_group_data *)marker;
+        while(group_ptr->domain == DOMAIN_CHIP) {
+		rc = dt_create_nest_unit(ima, group_ptr);
+		if (rc)
+			break;
+		marker += group_ptr->length;
+		group_ptr = (struct nest_catalog_group_data *)marker;
+	};
+
+	return rc;
+}
+
 int preload_catalog_lid()
 {
 	size_t size = NEST_CATALOG_SIZE;
@@ -168,6 +293,14 @@ void nest_pmu_init(int loaded)
 		dt_add_property_u64(chip_dev, "size", SLW_IMA_SIZE);
 	}
 
+	/*
+	 * Second type of node folder created under the "nest-counters" is
+	 * for nest units. Now parse the catalog, detect the nest unit
+	 * groups and create device tree entries.
+	 */
+	if (detect_nest_units(dev))
+		goto fail;
+
 	return;
 
 fail:
-- 
1.9.1



More information about the Skiboot mailing list