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); }