aboutsummaryrefslogtreecommitdiff
path: root/hdata
diff options
context:
space:
mode:
Diffstat (limited to 'hdata')
-rw-r--r--hdata/spira.h2
-rw-r--r--hdata/vpd.c217
2 files changed, 77 insertions, 142 deletions
diff --git a/hdata/spira.h b/hdata/spira.h
index fa73452..a1ed79d 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -599,6 +599,8 @@ struct cpu_ctl_init_data {
*/
#define SLCA_IDATA_ARRAY 0
+#define SLCA_ROOT_INDEX 0
+
/* Note: An "index" (or idx) is always an index into the SLCA array
* and "id" is a reference to some other object.
*/
diff --git a/hdata/vpd.c b/hdata/vpd.c
index e568a06..38b0737 100644
--- a/hdata/vpd.c
+++ b/hdata/vpd.c
@@ -70,6 +70,9 @@ static const struct card_info card_table[] = {
/* Other cards */
};
+static struct dt_node *dt_create_vpd_node(struct dt_node *parent,
+ const struct slca_entry *entry);
+
static const struct card_info *card_info_lookup(char *ccin)
{
int i;
@@ -425,88 +428,6 @@ static const char *vpd_map_name(const char *vpd_name)
static bool valid_child_entry(const struct slca_entry *entry)
{
- if (!entry)
- return false;
-
- /*
- * Skip entries with independent ntuple FRUVPD/MSVPD, etc.,
- * representations, since they have a unique PN, FN, SN, et al.
- * We add details for those devices via the ntuple walk.
- */
- switch (entry->fru_id[0]) {
- case 'A':
- switch (entry->fru_id[1]) {
- case 'V': /* AV */
- return false;
- }
- break;
- case 'B':
- switch (entry->fru_id[1]) {
- case 'P': /* BP */
- case 'X': /* BX */
- return false;
- }
- break;
- case 'C':
- switch (entry->fru_id[1]) {
- case 'C': /* CC */
- return false;
- }
- break;
- case 'D':
- switch (entry->fru_id[1]) {
- case 'B': /* DB */
- return false;
- }
- break;
- case 'E':
- switch (entry->fru_id[1]) {
- case 'V': /* EV */
- return false;
- }
- break;
- case 'M':
- switch (entry->fru_id[1]) {
- case 'S': /* MS */
- return false;
- }
- break;
- case 'O':
- switch (entry->fru_id[1]) {
- case 'P': /* OP */
- return false;
- }
- break;
- case 'R':
- switch (entry->fru_id[1]) {
- case 'I': /* RI */
- return false;
- }
- break;
- case 'P':
- switch (entry->fru_id[1]) {
- case '2': /* P2 */
- case '5': /* P5 */
- case 'F': /* PF */
- return false;
- }
- break;
- case 'S':
- switch (entry->fru_id[1]) {
- case 'P': /* SP */
- return false;
- }
- break;
- case 'T':
- switch (entry->fru_id[1]) {
- case 'P': /* TP */
- return false;
- }
- break;
- default:
- break;
- }
-
if ((entry->install_indic == SLCA_INSTALL_INSTALLED) &&
(entry->vpd_collected == SLCA_VPD_COLLECTED))
return true;
@@ -546,26 +467,11 @@ static void vpd_add_children(struct dt_node *parent, uint16_t slca_index)
return;
if (valid_child_entry(child)) {
- const char *name;
- uint64_t addr;
struct dt_node *node;
- /* create new node, add location code */
- name = vpd_map_name(child->fru_id);
- addr = (uint64_t)be16_to_cpu(child->rsrc_id);
- node = dt_new_addr(parent, name, addr);
- if (!node) {
- prerror("VPD: Creating node at %s@%llx failed\n",
- name, addr);
+ node = dt_create_vpd_node(parent, child);
+ if (!node)
return;
- }
- slca_vpd_add_loc_code(node, be16_to_cpu(child->my_index));
-
- /* Add child FRU type */
- dt_add_property(node, "fru-type", child->fru_id, 2);
-
- /* recursively add children */
- vpd_add_children(node, be16_to_cpu(child->my_index));
}
/* Skip dups -- currently we presume dups are contiguous */
@@ -576,83 +482,110 @@ static void vpd_add_children(struct dt_node *parent, uint16_t slca_index)
return;
}
+/* Create the vpd node and add its children */
+static struct dt_node *dt_create_vpd_node(struct dt_node *parent,
+ const struct slca_entry *entry)
+{
+ struct dt_node *node;
+ const char *name;
+ uint64_t addr;
+
+ name = vpd_map_name(entry->fru_id);
+ addr = (uint64_t)be16_to_cpu(entry->rsrc_id);
+ node = dt_new_addr(parent, name, addr);
+ if (!node) {
+ prerror("VPD: Creating node at %s@%llx failed\n", name, addr);
+ return NULL;
+ }
+
+ /* Add location code */
+ slca_vpd_add_loc_code(node, be16_to_cpu(entry->my_index));
+ /* Add FRU label */
+ dt_add_property(node, "fru-type", entry->fru_id, 2);
+ /* Recursively add children */
+ vpd_add_children(node, be16_to_cpu(entry->my_index));
+
+ return node;
+}
+
struct dt_node *dt_add_vpd_node(const struct HDIF_common_hdr *hdr,
int indx_fru, int indx_vpd)
{
- const void *fruvpd;
- unsigned int fruvpd_sz;
- unsigned int fru_id_sz;
- uint64_t addr;
- struct dt_node *dt_vpd;
- struct dt_node *node;
const struct spira_fru_id *fru_id;
- const struct slca_entry *s_entry;
- const char *vpd_name;
+ unsigned int fruvpd_sz, fru_id_sz;
+ const struct slca_entry *entry;
+ struct dt_node *dt_vpd, *node;
+ static bool first = true;
+ const void *fruvpd;
const char *name;
- int len;
+ uint64_t addr;
char *lname;
+ int len;
fru_id = HDIF_get_idata(hdr, indx_fru, &fru_id_sz);
if (!fru_id)
return NULL;
- s_entry = slca_get_entry(be16_to_cpu(fru_id->slca_index));
- if (valid_child_entry(s_entry)) /* Don't populate child VPD here */
- return NULL;
-
fruvpd = HDIF_get_idata(hdr, indx_vpd, &fruvpd_sz);
if (!CHECK_SPPTR(fruvpd))
return NULL;
- vpd_name = slca_get_vpd_name(be16_to_cpu(fru_id->slca_index));
- if (!vpd_name) {
- prerror("VPD: VPD name at index %d couldn't be found\n",
- fru_id->slca_index);
+ dt_vpd = dt_find_by_path(dt_root, "/vpd");
+ if (!dt_vpd)
return NULL;
+
+ if (first) {
+ entry = slca_get_entry(SLCA_ROOT_INDEX);
+ if (!entry) {
+ prerror("VPD: Could not find the slca root entry\n");
+ return NULL;
+ }
+
+ node = dt_create_vpd_node(dt_vpd, entry);
+ if (!node)
+ return NULL;
+
+ first = false;
}
- dt_vpd = dt_find_by_path(dt_root, "/vpd");
- if (!dt_vpd)
+ entry = slca_get_entry(fru_id->slca_index);
+ if (!entry)
return NULL;
- /* Get node name */
- name = vpd_map_name(vpd_name);
- addr = (uint64_t)be16_to_cpu(fru_id->rsrc_id);
+ name = vpd_map_name(entry->fru_id);
+ addr = (uint64_t)be16_to_cpu(entry->rsrc_id);
len = strlen(name) + STR_MAX_CHARS(addr) + 2;
lname = zalloc(len);
if (!lname) {
prerror("VPD: Failed to allocate memory\n");
return NULL;
}
+
snprintf(lname, len, "%s@%llx", name, (long long)addr);
+ /* Get the node already created */
+ node = dt_find_by_name(dt_vpd, lname);
+ free(lname);
/*
- * FRU can be a child of some other FRU. Make sure
- * we have not added this node already.
+ * It is unlikely that node not found because vpd nodes have the
+ * corresponding slca entry which we would have used to populate the vpd
+ * tree during the 'first' pass above so that we just need to perform
+ * VINI parse and add the vpd data..
+ * Still, we consider this case and create fresh node under '/vpd' if
+ * 'node' not found.
*/
- node = dt_find_by_path(dt_vpd, lname);
- if (node) {
- free(lname);
- return NULL;
- }
-
- node = dt_new(dt_vpd, lname);
if (!node) {
- free(lname);
- return NULL;
+ node = dt_create_vpd_node(dt_vpd, entry);
+ if (!node)
+ return NULL;
}
- /* Parse VPD fields */
- dt_add_property(node, "ibm,vpd", fruvpd, fruvpd_sz);
- vpd_vini_parse(node, fruvpd, fruvpd_sz);
-
- /* Location code */
- slca_vpd_add_loc_code(node, be16_to_cpu(fru_id->slca_index));
- /* Add FRU label */
- dt_add_property(node, "fru-type", vpd_name, 2);
- vpd_add_children(node, be16_to_cpu(fru_id->slca_index));
+ /* Parse VPD fields, ensure that it has not been added already */
+ if (!dt_find_property(node, "ibm,vpd")) {
+ dt_add_property(node, "ibm,vpd", fruvpd, fruvpd_sz);
+ vpd_vini_parse(node, fruvpd, fruvpd_sz);
+ }
- free(lname);
return node;
}