From beda769050cb097aa17fdcec5a05d6f6cfdf72a7 Mon Sep 17 00:00:00 2001 From: Michael Bringmann Date: Wed, 2 Oct 2019 16:54:52 -0500 Subject: [PATCH 1/2] 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 Signed-off-by: Tyrel Datwyler --- src/drmgr/common_ofdt.c | 223 ++++++++++++++++++++++++++++++++++------ 1 file changed, 194 insertions(+), 29 deletions(-) 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; } -- 2.39.3