From patchwork Sun Dec 21 18:30:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neelesh Gupta X-Patchwork-Id: 423195 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 582EE1400A0 for ; Mon, 22 Dec 2014 05:32:41 +1100 (AEDT) Received: from ozlabs.org (ozlabs.org [103.22.144.67]) by lists.ozlabs.org (Postfix) with ESMTP id 4896C1A0198 for ; Mon, 22 Dec 2014 05:32:41 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e28smtp03.in.ibm.com (e28smtp03.in.ibm.com [122.248.162.3]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 1C9791A0147 for ; Mon, 22 Dec 2014 05:32:38 +1100 (AEDT) Received: from /spool/local by e28smtp03.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 22 Dec 2014 00:02:35 +0530 Received: from d28dlp01.in.ibm.com (9.184.220.126) by e28smtp03.in.ibm.com (192.168.1.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 22 Dec 2014 00:02:32 +0530 Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp01.in.ibm.com (Postfix) with ESMTP id B5536E003F for ; Mon, 22 Dec 2014 00:03:18 +0530 (IST) Received: from d28av05.in.ibm.com (d28av05.in.ibm.com [9.184.220.67]) by d28relay03.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id sBLIYcRa61014142 for ; Mon, 22 Dec 2014 00:04:38 +0530 Received: from d28av05.in.ibm.com (localhost [127.0.0.1]) by d28av05.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id sBLIWWO8022776 for ; Mon, 22 Dec 2014 00:02:32 +0530 Received: from [192.168.1.2] ([9.80.67.85]) by d28av05.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id sBLIWTMa022597; Mon, 22 Dec 2014 00:02:30 +0530 To: skiboot@lists.ozlabs.org, dipankar@in.ibm.com, ananth@in.ibm.com, benh@kernel.crashing.org From: Neelesh Gupta Date: Mon, 22 Dec 2014 00:00:43 +0530 Message-ID: <20141221183037.7062.77269.stgit@ZyXEL0> In-Reply-To: <20141221182235.7062.868.stgit@ZyXEL0> References: <20141221182235.7062.868.stgit@ZyXEL0> User-Agent: StGit/0.16 MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14122118-0009-0000-0000-0000030D0B70 Subject: [Skiboot] [PATCH v1 3/3] vpd: Use slca parent-child relationship to create vpd tree X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" SLCA entries available through hdat have parent-child relationship of various FRUs of the system, the patch makes use of this data to create VPD nodes in hierarchial fashion. This is further useful for the user space tools like 'lshw'/'lsvpd' to plug-in the support easily on POWER. Signed-off-by: Neelesh Gupta --- hdata/vpd.c | 220 +++++++++++++++++++++-------------------------------------- 1 file changed, 78 insertions(+), 142 deletions(-) diff --git a/hdata/vpd.c b/hdata/vpd.c index e568a06..1bf233d 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,113 @@ 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) { + const struct slca_entry *slca_root; + slca_root = slca_get_root_entry(be16_to_cpu( + fru_id->slca_index)); + if (!slca_root) { + prerror("VPD: slca root entry at index %d couldn't be " + "found\n", be16_to_cpu(fru_id->slca_index)); + return NULL; + } + + node = dt_create_vpd_node(dt_vpd, slca_root); + 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; }