On Fri, Jun 06, 2025 at 10:10:52AM +0200, Jean Delvare wrote:
> Hi Jerry,
>
> On Thu, 5 Jun 2025 15:29:01 -0600, Jerry Hoemann wrote:
> > Record type 202: DIMM Location Record
>
> Thanks for contributing this type, it seems very useful.
>
> > Signed-off-by: Jerry Hoemann <[email protected]>
> > ---
> > dmioem.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 90 insertions(+)
> >
> > diff --git a/dmioem.c b/dmioem.c
> > index d4d83e2..b5d0402 100644
> > --- a/dmioem.c
> > +++ b/dmioem.c
> > @@ -1147,6 +1147,96 @@ static int dmi_decode_hp(const struct dmi_header *h)
> > }
> > break;
> >
> > + case 202:
> > + /*
> > + * Vendor Specific: HPE DIMM Location Record
> > + *
> > + * This record allows software to correlate a Type 17
> > Memory Device Record
> > + * with a specific DIMM (DIMM, Board, and/or Processor
> > number if appropriate).
> > + *
> > + * There will be one Record Type 202 for each DIMM
> > socket possible in the system.
> > + * A system will include a record for each DIMM socket
> > even if that DIMM socket
> > + * is on a memory board which is not currently
> > installed.
> > + *
> > + * Offset | Name | Width | Description
> > + * -------------------------------------
> > + * 0x00 | Type | BYTE | 0xCA, DIMM Location
> > Record
> > + * 0x01 | Length | BYTE | Length of structure
> > + * 0x02 | Handle | WORD | Unique handle
> > + * 0x04 | Assoc Record | WORD | Handle of Associated
> > Type 17 Memory Record
> > + * 0x06 | Board Number | BYTE | 1-based Memory Board
> > number. 0FFh: DIMM on system board
> > + * 0x07 | DIMM Number | BYTE | 1-based DIMM number
> > + * 0x08 | Proc Number | BYTE | 1-based procssor
> > number. 0FFh don't display
> > + * 0x09 | Log DIMM Num | BYTE | 1-based Logical DIMM
> > number mapping to ACPI numbering
> > + * 0x0A | UEFI Dev Path| STRING| String number for
> > UEFI Device Path
> > + * 0x0B | UEFI Dev Name| STRING| String number for
> > UEFI Device Structured Name
> > + * 0x0C | Device Name | STRING| String number for
> > Device Name
> > + * 0x0D | Mem Cntr Num | BYTE | 1-based Memory
> > controller number
>
> Cntr -> Cntrl for consistency.
done.
>
> > + * 0x0E | Mem Chan Num | BYTE | 1-based memory
> > channel number (matches silk screen)
> > + * 0x0F | IE DIMM Num | BYTE | 0-based DIMM number
> > repored by IE. FF -> not supported
> > + * | Reserved G12 or later
> > + * 0x10 | IE PLDM ID | BYTE | IE PLDM Sensor ID.
> > FF -> not supported
> > + * | Reserved G12 or later
>
> Out of curiosity, what do "IE" and "PLDM" stand for in this context? It
> may be worth spelling them out in the description for reference.
IE Innovation Engine (IE) Firmware. (Intel based fw.)
I believe PLDM is "Platform Level Data Model"
>
> > + * 0x11 | Vendor ID | WORD | Module manufacturers
> > ID code as read by SPD
> > + * 0x13 | Device ID | WORD | (NVDIMM only) Module
> > product ID code from SPD
>
> I find it suspicious that Device ID is for NVDIMM only, if Vendor ID is
> not.
Vendor ID is not just for NVDIMM. I have several examples were Vendor ID is
defined, but device id is not.
>
> > + * 0x15 | Sys Cntrl Ven| WORD | (NVDIMM only)
> > Controller manufacturer ID from SPD
> > + * 0x17 | Sub Cntrl Dev| WORD | (NVDIMM only)
> > Controller product ID from SPD
>
> Inconsistent name fields, I think it should be either "Sys" for both, of
> "Sub" for both (or maybe neither, as "Cntrl" seems descriptive enough).
fixed.
Sub for both.
>
> > + * 0x19 | Interleave | BYTE | 1-based unique
> > interleave set within Procssor Number
> > + * 0x1A | Part Number | STRING| String number for
> > HPE part number from OEM SPD
> > + * 0x1B | DIMM Index | BYTE | 0-based DIMM Index
> > Per Channel
> > + */
> > +
> > + if (gen < G9) return 0;
> > + pr_handle_name("%s DIMM Location Record", company);
> > +
> > + if (h->length < 0x09) break;
> > + pr_attr("Associated Memory Record", "0x%04X", WORD(data
> > + 0x04));
>
> We traditionally don't display handle references in quiet mode, so
> please add a conditional: if (!(opt.flags & FLAG_QUIET)).
done.
>
> > + if (data[0x06] == 0xFF)
> > + pr_attr("Board Number", "%s", "System Board");
> > + else
> > + pr_attr("Board Number", "%d", data[0x06]);
> > + pr_attr("DIMM Number", "%d", data[0x07]);
> > + if (data[0x08] != 0xFF)
> > + pr_attr("Processor Number", "%d", data[0x08]);
> > +
> > + if (h->length < 0x0A) break;
> > + pr_attr("Logical DIMM Number", "%d", data[0x09]);
> > +
> > + if (h->length < 0x0B) break;
> > + if (data[0x0A])
> > + pr_attr("UEFI Device Path", "%s", dmi_string(h,
> > data[0x0A]));
> > +
> > + if (h->length < 0x0E) break;
> > + if (data[0x0B])
> > + pr_attr("UEFI Device Name", "%s", dmi_string(h,
> > data[0x0B]));
> > + if (data[0x0C])
> > + pr_attr("Device Name", "%s", dmi_string(h,
> > data[0x0C]));
> > + if (data[0x0D])
> > + pr_attr("Memory Controller Number", "%d",
> > data[0x0D]);
> > +
> > + if (h->length < 0x1B) break;
>
> In my collection of HPE DMI tables, I see type 202 records of length 25
> (=0x19, DL380/DL385/DL560 Gen10) and 26 (=0x1A, various Gen10 and Gen10
> Plus). These lengths are not tested, which causes some available fields
> not to be displayed on these systems.
done.
>
> > + if (data[0x0E])
> > + pr_attr("Memory Channel Number", "%d",
> > data[0x0E]);
> > + if (gen < G12 && data[0x0F] != 0xFF)
> > + pr_attr("IE DIMM Number", "%d", data[0x0F]);
> > + if (gen < G12 && data[0x10] != 0xFF)
> > + pr_attr("IE PLDM ID", "%d", data[0x10]);
> > + if (data[0x11] || data[0x12])
> > + pr_attr("Vendor ID", "0x%x", WORD(data + 0x11));
> > + if (data[0x13] || data[0x14])
> > + pr_attr("Device ID", "0x%x", WORD(data + 0x13));
> > + if (data[0x15] || data[0x16])
> > + pr_attr("Controller Manufacturing ID", "0x%x",
> > WORD(data + 0x15));
>
> I think it's rather "Manufacturer"?
done.
>
> > + if (data[0x17] || data[0x18])
> > + pr_attr("Controller Product ID", "0x%x",
> > WORD(data + 0x17));
>
> I recommend format "0x%04X" for the 4 fields above, to be consistent
> with dmi_memory_product_id(). In fact it might make sense to export
> this function and reuse it here, and maybe dmi_memory_manufacturer_id()
> too. The latter prints things in a different way, I don't know if that
> would be a problem or a benefit for you.
done.
>
> > + if (data[0x19])
> > + pr_attr("Best Interleave", "0x%x", data[0x19]);
>
> This needs to be clarified. The description mentions an "interleave
> set", which I would expect to be a decimal number. Not sure what "best"
> refers to in the attribute label above. Please check with your firmware
> team what this field contains and how its contents should be
> interpreted.
This is for persistant memory supported only on Gen10/+.
Quoating the spec:
----------------------------------------
For certain NVDIMMs configurations, there is a defined “best-interleave”
DIMM combination that will provide optimal memory performance. The Best
Interleaved Set field in this record will contain a unique
interleave set number (1-based) within the indicated Processor Number if
the DIMM is a part of this “best-interleaved” set. DIMMs with identical
Best Interleaved Set values and identical Processor Numbers means those
DIMMs are best-interleaved together on that specific
processor. If a DIMM is not interleaved, the value of the Best
Interleaved Set field will be set to 0
----------------------------------------
There are RBSU controls w.r.t. PMM interleave settings.
A starting point for more information:
https://support.hpe.com/hpesc/public/docDisplay?docId=a00077643en_us&docLocale=en_US
>
> > + pr_attr("Part Number", "%s", dmi_string(h, data[0x1A]));
> > +
> > + if (h->length < 0x1C) break;
> > + pr_attr("DIMM Index", "%d", data[0x1B]);
> > + break;
> > +
> > case 203:
> > /*
> > * Vendor Specific: HP Device Correlation Record
>
> Thanks,
> --
> Jean Delvare
> SUSE L3 Support
--
-----------------------------------------------------------------------------
Jerry Hoemann Software Engineer Hewlett Packard Enterprise
-----------------------------------------------------------------------------