powerpc-utils/SOURCES/powerpc-utils-b0586b5938e9d...

273 lines
6.6 KiB
Diff

commit b0586b5938e9d371e55671422b2f0a5d2cd10c54
Author: Michael Bringmann <mwb@linux.vnet.ibm.com>
Date: Wed Oct 2 16:54:52 2019 -0500
powerpc-utils/devtree: Parse 'ibm,drc-info' property
Parse new DRC Info: Define data structures to support parsing
the new "ibm,drc-info" device tree property. Integrate the new
property information into the existing search mechanisms of the
userspace 'drmgr' driver.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
diff --git a/src/drmgr/common_ofdt.c b/src/drmgr/common_ofdt.c
index 8c9e224..c110bc0 100644
--- a/src/drmgr/common_ofdt.c
+++ b/src/drmgr/common_ofdt.c
@@ -41,6 +41,16 @@ struct drc_prop_grp {
struct of_list_prop drc_domains;
};
+struct drc_info {
+ char *drc_type;
+ char *drc_name_prefix;
+ int drc_index_start;
+ int drc_name_suffix_start;
+ int n_seq_elems;
+ int seq_inc;
+ int drc_power_domain;
+};
+
struct dr_connector *all_drc_lists = NULL;
/**
@@ -186,6 +196,169 @@ build_connectors_list(struct drc_prop_grp *group, int n_entries,
return 0;
}
+/**
+ * drc_info_connectors_v1
+ *
+ * @param full_path
+ * @param ofdt_path
+ * @param list
+ * @returns 0 on success, !0 otherwise
+ */
+static int drc_info_connectors_v1(char *full_path, char *ofdt_path,
+ struct dr_connector **list)
+{
+ struct dr_connector *out_list = NULL;
+ struct drc_prop_grp prop_grp;
+ struct of_list_prop *drc_names;
+ int n_drcs;
+ int rc = 0;
+
+ rc = get_drc_prop_grp(full_path, &prop_grp);
+ if (rc) {
+ say(DEBUG,
+ "Could not find DRC property group in path: %s.\n",
+ full_path);
+ goto done;
+ }
+
+ drc_names = &prop_grp.drc_names;
+ n_drcs = drc_names->n_entries;
+
+ out_list = zalloc(n_drcs * sizeof(struct dr_connector));
+ if (out_list == NULL)
+ goto done;
+
+ build_connectors_list(&prop_grp, n_drcs, out_list);
+
+done:
+ if (rc) {
+ free_drc_props(&prop_grp);
+ free(out_list);
+ } else {
+ snprintf(out_list->ofdt_path, DR_PATH_MAX, "%s", ofdt_path);
+ *list = out_list;
+ }
+
+ return rc;
+}
+
+/**
+ * drc_info_connectors_v2
+ *
+ * @param full_path
+ * @param ofdt_path
+ * @param list
+ * @returns 0 on success, !0 otherwise
+ */
+static int drc_info_connectors_v2(char *full_path, char *ofdt_path,
+ struct dr_connector **list)
+{
+ struct dr_connector *out_list = NULL;
+ struct drc_info info;
+ char *prop_name = "ibm,drc-info";
+ char *prop_data, *data_ptr;
+ int i, j, n_entries, size, connector_size, ics, rc;
+
+ size = get_property_size(full_path, prop_name);
+ prop_data = zalloc(size);
+ if (prop_data == NULL)
+ return -1;
+ rc = get_property(full_path, prop_name, prop_data, size);
+ if (rc) {
+ free(prop_data);
+ return -1;
+ }
+
+ /* Num of DRC-info sets */
+ data_ptr = prop_data;
+ n_entries = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ /* Extract drc-info data */
+ for (j = 0, connector_size = 0; j < n_entries; j++) {
+ info.drc_type = data_ptr;
+ data_ptr += strlen(info.drc_type)+1;
+ info.drc_name_prefix = data_ptr;
+ data_ptr += strlen(info.drc_name_prefix)+1;
+ data_ptr += 4; /* Skip drc-index-start */
+ data_ptr += 4; /* Skip drc-name-suffix-start */
+ info.n_seq_elems = be32toh(*(uint *)data_ptr);
+ data_ptr += 4; /* Advance over n-seq-elems */
+ data_ptr += 4; /* Skip sequential-increment */
+ data_ptr += 4; /* Skip drc-power-domain */
+ if (info.n_seq_elems <= 0)
+ continue;
+ connector_size += info.n_seq_elems;
+ }
+
+ /* Allocate list entry */
+ out_list = zalloc(connector_size * sizeof(struct dr_connector));
+ if (out_list == NULL) {
+ rc = -1;
+ goto done;
+ }
+
+ /* Extract drc-info data */
+ data_ptr = prop_data;
+ data_ptr += 4;
+ for (j = 0, ics = 0; j < n_entries; j++) {
+ info.drc_type = data_ptr;
+ data_ptr += strlen(info.drc_type)+1;
+ info.drc_name_prefix = data_ptr;
+ data_ptr += strlen(info.drc_name_prefix)+1;
+
+ info.drc_index_start = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.drc_name_suffix_start = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.n_seq_elems = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.seq_inc = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ info.drc_power_domain = be32toh(*(uint *)data_ptr);
+ data_ptr += 4;
+
+ /* Build connector list */
+ if (info.n_seq_elems <= 0)
+ continue;
+
+ for (i = 0; i < info.n_seq_elems; i++, ics++) {
+ out_list[ics].index = info.drc_index_start+
+ (i*info.seq_inc);
+ out_list[ics].powerdomain = info.drc_power_domain;
+
+ sprintf(out_list[ics].name, "%s%d",
+ info.drc_name_prefix,
+ info.drc_name_suffix_start+(i*info.seq_inc));
+
+ strncpy(out_list[ics].type, info.drc_type, DRC_STR_MAX);
+
+ out_list[ics].next = &out_list[ics+1];
+ }
+ }
+ if (ics > 0)
+ out_list[ics-1].next = NULL;
+
+done:
+ if (prop_data)
+ free(prop_data);
+
+ if (rc) {
+ free(out_list);
+ *list = NULL;
+ } else {
+ snprintf(out_list->ofdt_path, DR_PATH_MAX, "%s", ofdt_path);
+ *list = out_list;
+ }
+
+ return rc;
+}
+
+
/**
* of_to_full_path
*
@@ -232,11 +405,12 @@ of_to_full_path(const char *of_path)
struct dr_connector *
get_drc_info(const char *of_path)
{
- struct dr_connector *list = NULL;
- struct of_list_prop *drc_names;
- struct drc_prop_grp prop_grp;
+ struct stat sbuf;
+ char fname[DR_PATH_MAX];
+ char ofdt_path[DR_PATH_MAX];
char *full_path = NULL;
- int rc, n_drcs;
+ struct dr_connector *list = NULL;
+ int rc;
for (list = all_drc_lists; list; list = list->all_next) {
if (! strcmp(list->ofdt_path, of_path))
@@ -246,33 +420,24 @@ get_drc_info(const char *of_path)
full_path = of_to_full_path(of_path);
if (full_path == NULL)
return NULL;
-
- rc = get_drc_prop_grp(full_path, &prop_grp);
- if (rc) {
- say(DEBUG, "Could not find DRC property group in path: %s.\n",
- full_path);
- goto done;
- }
- drc_names = &prop_grp.drc_names;
- n_drcs = drc_names->n_entries;
-
- list = zalloc(n_drcs * sizeof(struct dr_connector));
- if (list == NULL)
- goto done;
-
- /* XXX Unchecked rc */
- rc = build_connectors_list(&prop_grp, n_drcs, list);
-
- snprintf(list->ofdt_path, DR_PATH_MAX, "%s", of_path);
-
- list->all_next = all_drc_lists;
- all_drc_lists = list;
+ /* ibm,drc-info vs the old implementation */
+ sprintf(fname, "%s/%s", full_path, "ibm,drc-info");
+ snprintf(ofdt_path, DR_PATH_MAX, "%s", of_path);
+ rc = stat(fname, &sbuf);
+ if (rc)
+ rc = drc_info_connectors_v1(full_path, ofdt_path, &list);
+ else
+ rc = drc_info_connectors_v2(full_path, ofdt_path, &list);
-done:
- free_drc_props(&prop_grp);
- if (full_path)
- free(full_path);
+ if (rc == 0) {
+ list->all_next = all_drc_lists;
+ all_drc_lists = list;
+ } else {
+ if (full_path)
+ free(full_path);
+ list = NULL;
+ }
return list;
}