273 lines
6.6 KiB
Diff
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;
|
|
}
|