[Skiboot] [PATCH v8 4/7] Catalog parser function to detect Nest units

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


Catalog have "group" structure to group events with similiar functions.
All the events within a group will be from same nest unit or domain.
A Nest unit can have multiple groups for its events in the catalog.
But, device tree will have only one dt node for a nest unit and all the
events supported by that nest unit should end up under it.

Two data structures are added:
        1)struct "map_grp_name_to_dt_name"
        2)struct "catalog_grp_to_dt_node"

Function detect_nest_units(), scans all the chip groups in the
catalog file and passes each chip group to add_grp_to_nest_unit_table().
add_grp_to_nest_unit_table() routine using lookup table identify the
group to a nest unit. Function then save the group address in
the "catalog_grp_to_dt_node" structure under the identified nest unit.

Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
---
 hw/nest.c      | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/nest.h | 25 ++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/hw/nest.c b/hw/nest.c
index 46d930384649..279da186f4aa 100644
--- a/hw/nest.c
+++ b/hw/nest.c
@@ -33,6 +33,23 @@
 struct nest_catalog_desc *catalog_desc;
 
 /*
+ * Lookup table to map the catalog nest group to
+ * hardware nest unit.
+ */
+struct map_grp_name_to_dt_name lookup_table[] = {
+        {"MCS_Read",            "mcs",          8,      MCS},
+        {"MCS_Write",           "mcs",          9,      MCS},
+};
+
+#define LOOKUP_TABLE_ENTRIES	\
+		(sizeof(lookup_table)/sizeof(struct map_grp_name_to_dt_name))
+
+/*
+ * Structure to hold catalog groups information for each nest unit
+ */
+struct catalog_grp_to_dt_node dev_grp_map[NEST_DT_DEVICE_MAX];
+
+/*
  * Catalog Page-0 (each page is 4K bytes long) contains
  * information about event, group, formula structure offsets
  * in the catalog. Cache these offsets in struct nest_catalog_page_0
@@ -40,6 +57,64 @@ struct nest_catalog_desc *catalog_desc;
  */
 struct nest_catalog_page_0 *page0_desc;
 
+static void add_grp_to_nest_unit_table(struct nest_catalog_group_data *gptr)
+{
+	int i, rc, unit, cnt;
+	int len;
+
+	for (i = 0; i < LOOKUP_TABLE_ENTRIES; i++) {
+		len = lookup_table[i].length;
+		if (len > gptr->group_name_len)
+			len = gptr->group_name_len;
+
+		rc = strncmp(gptr->remainder, lookup_table[i].catalog_grp_name, len);
+		if (!rc) {
+			unit = lookup_table[i].unit_id;
+			cnt = dev_grp_map[unit].grp_count;
+			dev_grp_map[unit].groups[cnt] = (u64) gptr;
+			dev_grp_map[unit].grp_count++;
+
+			/*
+			 * Link the device name if not linked already.
+			 * This is needed when creating the device tree.
+			 */
+			if (!dev_grp_map[unit].nest_unit_name)
+				dev_grp_map[unit].nest_unit_name = lookup_table[i].dt_unit_name;
+		}
+	}
+}
+
+static int detect_nest_units(struct dt_node *ima)
+{
+	struct nest_catalog_group_data *group;
+	char *marker;
+	int rc = 0;
+
+	/* Zero out to avoid issues in multi node/chip config */
+	memset((void *)dev_grp_map, 0,
+		(sizeof(struct catalog_grp_to_dt_node) * NEST_DT_DEVICE_MAX));
+
+	/*
+	 * Scan all available groups in the chip domain from
+	 * the CATALOG and update the catalog_grp_to_dt_node table.
+	 * Note that 1) Catalog can have multiple groups for a
+	 * same nest unit. 2) All the events for a nest unit should end up
+	 * in the same dt node even though they are placed in different groups.
+	 * ex. Catalog could have groups like "MCS_Read_BW" and "MCS_Write_BW",
+	 * but events from both these groups should end up in the device tree
+	 * node of "mcs".
+	 */
+	marker = CHIP_GROUP_ENTRY(catalog_desc);
+	group = (struct nest_catalog_group_data *)marker;
+	while (group->domain == DOMAIN_CHIP) {
+		add_grp_to_nest_unit_table(group);
+		marker += group->length;
+		group = (struct nest_catalog_group_data *)marker;
+	};
+
+	return rc;
+}
+
 int preload_catalog_lid()
 {
 	struct proc_chip *chip = get_chip(this_cpu()->chip_id);
@@ -177,6 +252,13 @@ void nest_pmu_init(int loaded)
 		dt_add_property_cells(chip_dev, "#size-cells", 1);
 		dt_add_property_cells(chip_dev, "ranges", 0, hi32(addr),
 						lo32(addr), SLW_IMA_SIZE);
+
+		/*
+		 * Call catalog parser to create nest unit dt nodes and
+		 * add events to it.
+		 */
+		if (detect_nest_units(chip_dev))
+			goto fail;
 	}
 
 	return;
diff --git a/include/nest.h b/include/nest.h
index 4fbaa41b4e0b..757b18ea741d 100644
--- a/include/nest.h
+++ b/include/nest.h
@@ -204,6 +204,31 @@ struct nest_catalog_desc {
 /* Size of Nest Catalog LID (256KBytes) */
 #define NEST_CATALOG_SIZE	0x40000
 
+/* Max number of groups for a nest unit in catalog */
+#define MAX_CATALOG_GROUPS_PER_NEST_UNIT	5
+
+/*
+ * If new nest units are added to catalog then append to the enum.
+ */
+enum nest_unit_id {
+	MCS,
+	NEST_DT_DEVICE_MAX,
+};
+
+struct map_grp_name_to_dt_name {
+	char catalog_grp_name[32];
+	char dt_unit_name[32];
+	u32 length;
+	u32 unit_id;
+};
+
+struct catalog_grp_to_dt_node {
+	char *nest_unit_name;
+	u64 groups[MAX_CATALOG_GROUPS_PER_NEST_UNIT];
+	u32 grp_count;
+	struct dt_node *dt_node;
+};
+
 /*
  * Function prototypes
  */
-- 
1.9.1



More information about the Skiboot mailing list