firmware: dmi: Remember the memory type
authorJean Delvare <jdelvare@suse.de>
Tue, 3 Dec 2019 10:20:37 +0000 (11:20 +0100)
committerJean Delvare <jdelvare@suse.de>
Tue, 3 Dec 2019 10:20:37 +0000 (11:20 +0100)
Store the memory type while walking the memory slots, and provide a
way to retrieve it later.

Signed-off-by: Jean Delvare <jdelvare@suse.de>
drivers/firmware/dmi_scan.c
include/linux/dmi.h

index 1e21fc3e9851a4e6a322173ebffcc2ad1561c9c6..6f28e515fdc0a97507b3298fda35fbf9498d96bd 100644 (file)
@@ -35,6 +35,7 @@ static struct dmi_memdev_info {
        const char *bank;
        u64 size;               /* bytes */
        u16 handle;
+       u8 type;                /* DDR2, DDR3, DDR4 etc */
 } *dmi_memdev;
 static int dmi_memdev_nr;
 
@@ -391,7 +392,7 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
        u64 bytes;
        u16 size;
 
-       if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12)
+       if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x13)
                return;
        if (nr >= dmi_memdev_nr) {
                pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
@@ -400,6 +401,7 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
        dmi_memdev[nr].handle = get_unaligned(&dm->handle);
        dmi_memdev[nr].device = dmi_string(dm, d[0x10]);
        dmi_memdev[nr].bank = dmi_string(dm, d[0x11]);
+       dmi_memdev[nr].type = d[0x12];
 
        size = get_unaligned((u16 *)&d[0xC]);
        if (size == 0)
@@ -1128,3 +1130,24 @@ u64 dmi_memdev_size(u16 handle)
        return ~0ull;
 }
 EXPORT_SYMBOL_GPL(dmi_memdev_size);
+
+/**
+ * dmi_memdev_type - get the memory type
+ * @handle: DMI structure handle
+ *
+ * Return the DMI memory type of the module in the slot associated with the
+ * given DMI handle, or 0x0 if no such DMI handle exists.
+ */
+u8 dmi_memdev_type(u16 handle)
+{
+       int n;
+
+       if (dmi_memdev) {
+               for (n = 0; n < dmi_memdev_nr; n++) {
+                       if (handle == dmi_memdev[n].handle)
+                               return dmi_memdev[n].type;
+               }
+       }
+       return 0x0;     /* Not a valid value */
+}
+EXPORT_SYMBOL_GPL(dmi_memdev_type);
index 8de8c4f15163a9ecc7e9459df85976b1eff0b614..13a48b167e2d69ed55c4a26ee53b6c69c173d66f 100644 (file)
@@ -113,6 +113,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *),
 extern bool dmi_match(enum dmi_field f, const char *str);
 extern void dmi_memdev_name(u16 handle, const char **bank, const char **device);
 extern u64 dmi_memdev_size(u16 handle);
+extern u8 dmi_memdev_type(u16 handle);
 
 #else
 
@@ -142,6 +143,7 @@ static inline bool dmi_match(enum dmi_field f, const char *str)
 static inline void dmi_memdev_name(u16 handle, const char **bank,
                const char **device) { }
 static inline u64 dmi_memdev_size(u16 handle) { return ~0ul; }
+static inline u8 dmi_memdev_type(u16 handle) { return 0x0; }
 static inline const struct dmi_system_id *
        dmi_first_match(const struct dmi_system_id *list) { return NULL; }