[Skiboot] [PATCH v8 6/7] nest mcs unit support

Madhavan Srinivasan maddy at linux.vnet.ibm.com
Mon Mar 14 15:02:02 AEDT 2016


Add support functions for nest memory control subsystem (mcs) unit.
Support function will add device tree node for each
event supported by mcs unit and corresponding reg, id, unit and scale
entries to pass on information about the event.

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

diff --git a/hw/nest.c b/hw/nest.c
index ac77b2f146b2..4e1866f66853 100644
--- a/hw/nest.c
+++ b/hw/nest.c
@@ -76,6 +76,96 @@ dt_add_device_node(struct dt_node *ptr, const char *name)
 	return type;
 }
 
+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 int dt_create_nest_unit_events(struct dt_node *pt, int index, u32 offset,
+					const char *name, const char *scale,
+					const char *unit)
+{
+	struct dt_node *type;
+
+	/*
+	 * Create an event node to pass event information.
+	 * "reg" property is must for event and rest of the properties
+	 * such as id, scale, unit are optional.
+	 */
+	type = dt_new_addr(pt, name, offset);
+	if (!type)
+		return -1;
+
+	/*
+	 * "reg" property:
+	 *
+	 * event offset where counter data gets accumulated
+	 */
+	dt_add_property_cells(type, "reg", offset, sizeof(u64));
+
+	/*
+	 * "id" property:
+	 *
+	 * event id to be appended to the event name. In some units like abus,
+	 * we have events such as abus0, abus1 and abus2. Since having numbers
+	 * in the dt node name are not suggested, we pass these numbers as
+	 * id peroperty.
+	 */
+	if (index >= 0)
+		 dt_add_property_cells(type, "id", index);
+
+	/*
+	 * "unit" and "scale" property:
+	 *
+	 * unit and scale properties, when used on raw counter value,
+	 * provide metric information.
+	 *
+	 * TODO:
+	 * Event names we get from catalog are awkward
+	 * and we make some transformations to these.
+	 * May need to add property to hold corresponding catalog name.
+	 */
+	if (unit)
+		dt_add_property_string(type, "unit", unit);
+
+	if (scale)
+		dt_add_property_string(type, "scale", scale);
+
+	return 0;
+}
+
+static int dt_create_nest_mcs_node(struct dt_node *type,
+			struct nest_catalog_group_data *gptr, const char *name)
+{
+	int idx;
+	u32 offset;
+	const char *unit = "MiB", *scale = "1.2207e-4";
+
+	for (idx = 0; idx < gptr->event_count; idx++) {
+		offset = get_chip_event_offset(gptr->event_index[idx],
+								DOMAIN_CHIP);
+		if (dt_create_nest_unit_events(type, idx, offset, name, scale, unit))
+			return -1;
+	}
+
+	return 0;
+}
+
 /*
  * Wrapper function to call corresponding nest unit functions
  * for event dt creation. Not all the chip groups in the catalog are
@@ -85,6 +175,26 @@ static int
 dt_create_nest_unit(struct dt_node *ima,
 				struct nest_catalog_group_data *gptr)
 {
+	char *name;
+
+	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, "read_mc"))
+			goto out;
+	} else if (strstr(name, "MCS_Write_BW")) {
+		if (dt_create_nest_mcs_node(ima, gptr, "write_mc"))
+			goto out;
+	} else
+		free(name);
+
+	return OPAL_SUCCESS;
+out:
+	free(name);
+	return OPAL_RESOURCE;
 }
 
 static void add_grp_to_nest_unit_table(struct nest_catalog_group_data *gptr)
-- 
1.9.1



More information about the Skiboot mailing list