From 3dadd152b06756ae3dafa21d579885d9bff5a27e Mon Sep 17 00:00:00 2001 From: Oliver O'Halloran Date: Fri, 13 Jan 2017 17:56:18 +1100 Subject: [PATCH] hdat: handle ISDIMM SPD blobs Previously the HDAT format was only ever used with IBM hardware so it would store vital product data (VPD) blobs in the IBM ASCII Keyword VPD format. With P9 HDAT is used on OpenPower machines which use Industry Standard DIMMs that provide their product data through a "Serial Present Detect" EEPROM mounted on the DIMM. The SPD blob has a different format and is exported in the device-tree under the "spd" property rather than the "ibm,vpd" property. This patch adds support for recognising these blobs and placing them in the appropriate DT property. Signed-off-by: Oliver O'Halloran Signed-off-by: Stewart Smith --- hdata/memory.c | 37 ++++++++++++++++++++++++++++--------- hdata/vpd.c | 3 ++- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/hdata/memory.c b/hdata/memory.c index a066f1eb10dd..f16f4cb03713 100644 --- a/hdata/memory.c +++ b/hdata/memory.c @@ -269,6 +269,7 @@ static void vpd_add_ram_area(const struct HDIF_common_hdr *msarea) const struct HDIF_ram_area_id *ram_id; struct dt_node *ram_node; u32 chip_id; + const void *vpd_blob; ramptr = HDIF_child_arr(msarea, 0); if (!CHECK_SPPTR(ramptr)) { @@ -285,15 +286,33 @@ static void vpd_add_ram_area(const struct HDIF_common_hdr *msarea) if (!CHECK_SPPTR(ram_id)) continue; - if ((be16_to_cpu(ram_id->flags) & RAM_AREA_INSTALLED) && - (be16_to_cpu(ram_id->flags) & RAM_AREA_FUNCTIONAL)) { - ram_node = dt_add_vpd_node(ramarea, 0, 1); - if (ram_node) { - chip_id = add_chip_id_to_ram_area(msarea, - ram_node); - add_bus_freq_to_ram_area(ram_node, chip_id); - add_size_to_ram_area(ram_node, ramarea, 1); - } + /* Don't add VPD for non-existent RAM */ + if (!(be16_to_cpu(ram_id->flags) & RAM_AREA_INSTALLED)) + continue; + + ram_node = dt_add_vpd_node(ramarea, 0, 1); + if (!ram_node) + continue; + + chip_id = add_chip_id_to_ram_area(msarea, ram_node); + add_bus_freq_to_ram_area(ram_node, chip_id); + + vpd_blob = HDIF_get_idata(ramarea, 1, &ram_sz); + + /* + * For direct-attached memory we have a DDR "Serial + * Presence Detection" blob rather than an IBM keyword + * blob. + */ + if (vpd_valid(vpd_blob, ram_sz)) { + /* the ibm,vpd blob was added in dt_add_vpd_node() */ + add_size_to_ram_area(ram_node, ramarea, 1); + } else { + /* + * FIXME: There's probably a way to calculate the + * size of the DIMM from the SPD info. + */ + dt_add_property(ram_node, "spd", vpd_blob, ram_sz); } } } diff --git a/hdata/vpd.c b/hdata/vpd.c index d9ee77c6335b..cb7a8daa398f 100644 --- a/hdata/vpd.c +++ b/hdata/vpd.c @@ -590,7 +590,8 @@ struct dt_node *dt_add_vpd_node(const struct HDIF_common_hdr *hdr, } /* Parse VPD fields, ensure that it has not been added already */ - if (!dt_find_property(node, "ibm,vpd")) { + if (vpd_valid(fruvpd, fruvpd_sz) + && !dt_find_property(node, "ibm,vpd")) { dt_add_property(node, "ibm,vpd", fruvpd, fruvpd_sz); vpd_vini_parse(node, fruvpd, fruvpd_sz); }