diff options
author | Chen, Gong <gong.chen@linux.intel.com> | 2013-10-18 17:29:25 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2013-10-23 13:10:12 -0400 |
commit | dd6dad4288cb93e79bd7abfa6c6a338c47454d1a (patch) | |
tree | 0e50552871a2ae86513d1a3cce21282f5002241a /drivers/firmware | |
parent | 4b3db708b114fc35ff1e0cd28a2bfb1490dbb5d3 (diff) |
DMI: Parse memory device (type 17) in SMBIOS
This patch adds a new interface to decode memory device (type 17)
to help error reporting on DIMMs.
Original-author: Tony Luck <tony.luck@intel.com>
Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
Acked-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Acked-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/dmi_scan.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index fa0affb699b4..59579a744d58 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
@@ -25,6 +25,13 @@ static int dmi_initialized; | |||
25 | /* DMI system identification string used during boot */ | 25 | /* DMI system identification string used during boot */ |
26 | static char dmi_ids_string[128] __initdata; | 26 | static char dmi_ids_string[128] __initdata; |
27 | 27 | ||
28 | static struct dmi_memdev_info { | ||
29 | const char *device; | ||
30 | const char *bank; | ||
31 | u16 handle; | ||
32 | } *dmi_memdev; | ||
33 | static int dmi_memdev_nr; | ||
34 | |||
28 | static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) | 35 | static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) |
29 | { | 36 | { |
30 | const u8 *bp = ((u8 *) dm) + dm->length; | 37 | const u8 *bp = ((u8 *) dm) + dm->length; |
@@ -322,6 +329,42 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm) | |||
322 | dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1))); | 329 | dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1))); |
323 | } | 330 | } |
324 | 331 | ||
332 | static void __init count_mem_devices(const struct dmi_header *dm, void *v) | ||
333 | { | ||
334 | if (dm->type != DMI_ENTRY_MEM_DEVICE) | ||
335 | return; | ||
336 | dmi_memdev_nr++; | ||
337 | } | ||
338 | |||
339 | static void __init save_mem_devices(const struct dmi_header *dm, void *v) | ||
340 | { | ||
341 | const char *d = (const char *)dm; | ||
342 | static int nr; | ||
343 | |||
344 | if (dm->type != DMI_ENTRY_MEM_DEVICE) | ||
345 | return; | ||
346 | if (nr >= dmi_memdev_nr) { | ||
347 | pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n"); | ||
348 | return; | ||
349 | } | ||
350 | dmi_memdev[nr].handle = dm->handle; | ||
351 | dmi_memdev[nr].device = dmi_string(dm, d[0x10]); | ||
352 | dmi_memdev[nr].bank = dmi_string(dm, d[0x11]); | ||
353 | nr++; | ||
354 | } | ||
355 | |||
356 | void __init dmi_memdev_walk(void) | ||
357 | { | ||
358 | if (!dmi_available) | ||
359 | return; | ||
360 | |||
361 | if (dmi_walk_early(count_mem_devices) == 0 && dmi_memdev_nr) { | ||
362 | dmi_memdev = dmi_alloc(sizeof(*dmi_memdev) * dmi_memdev_nr); | ||
363 | if (dmi_memdev) | ||
364 | dmi_walk_early(save_mem_devices); | ||
365 | } | ||
366 | } | ||
367 | |||
325 | /* | 368 | /* |
326 | * Process a DMI table entry. Right now all we care about are the BIOS | 369 | * Process a DMI table entry. Right now all we care about are the BIOS |
327 | * and machine entries. For 2.5 we should pull the smbus controller info | 370 | * and machine entries. For 2.5 we should pull the smbus controller info |
@@ -815,3 +858,20 @@ bool dmi_match(enum dmi_field f, const char *str) | |||
815 | return !strcmp(info, str); | 858 | return !strcmp(info, str); |
816 | } | 859 | } |
817 | EXPORT_SYMBOL_GPL(dmi_match); | 860 | EXPORT_SYMBOL_GPL(dmi_match); |
861 | |||
862 | void dmi_memdev_name(u16 handle, const char **bank, const char **device) | ||
863 | { | ||
864 | int n; | ||
865 | |||
866 | if (dmi_memdev == NULL) | ||
867 | return; | ||
868 | |||
869 | for (n = 0; n < dmi_memdev_nr; n++) { | ||
870 | if (handle == dmi_memdev[n].handle) { | ||
871 | *bank = dmi_memdev[n].bank; | ||
872 | *device = dmi_memdev[n].device; | ||
873 | break; | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | EXPORT_SYMBOL_GPL(dmi_memdev_name); | ||