Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Chen, Gong and committed by
Tony Luck
dd6dad42 4b3db708

+67
+1
arch/ia64/kernel/setup.c
··· 1063 1063 static int __init run_dmi_scan(void) 1064 1064 { 1065 1065 dmi_scan_machine(); 1066 + dmi_memdev_walk(); 1066 1067 dmi_set_dump_stack_arch_desc(); 1067 1068 return 0; 1068 1069 }
+1
arch/x86/kernel/setup.c
··· 993 993 efi_init(); 994 994 995 995 dmi_scan_machine(); 996 + dmi_memdev_walk(); 996 997 dmi_set_dump_stack_arch_desc(); 997 998 998 999 /*
+60
drivers/firmware/dmi_scan.c
··· 25 25 /* DMI system identification string used during boot */ 26 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 35 static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s) 29 36 { 30 37 const u8 *bp = ((u8 *) dm) + dm->length; ··· 327 320 dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5), 328 321 dmi_string_nosave(dm, *(d-1))); 329 322 dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1))); 323 + } 324 + 325 + static void __init count_mem_devices(const struct dmi_header *dm, void *v) 326 + { 327 + if (dm->type != DMI_ENTRY_MEM_DEVICE) 328 + return; 329 + dmi_memdev_nr++; 330 + } 331 + 332 + static void __init save_mem_devices(const struct dmi_header *dm, void *v) 333 + { 334 + const char *d = (const char *)dm; 335 + static int nr; 336 + 337 + if (dm->type != DMI_ENTRY_MEM_DEVICE) 338 + return; 339 + if (nr >= dmi_memdev_nr) { 340 + pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n"); 341 + return; 342 + } 343 + dmi_memdev[nr].handle = dm->handle; 344 + dmi_memdev[nr].device = dmi_string(dm, d[0x10]); 345 + dmi_memdev[nr].bank = dmi_string(dm, d[0x11]); 346 + nr++; 347 + } 348 + 349 + void __init dmi_memdev_walk(void) 350 + { 351 + if (!dmi_available) 352 + return; 353 + 354 + if (dmi_walk_early(count_mem_devices) == 0 && dmi_memdev_nr) { 355 + dmi_memdev = dmi_alloc(sizeof(*dmi_memdev) * dmi_memdev_nr); 356 + if (dmi_memdev) 357 + dmi_walk_early(save_mem_devices); 358 + } 330 359 } 331 360 332 361 /* ··· 858 815 return !strcmp(info, str); 859 816 } 860 817 EXPORT_SYMBOL_GPL(dmi_match); 818 + 819 + void dmi_memdev_name(u16 handle, const char **bank, const char **device) 820 + { 821 + int n; 822 + 823 + if (dmi_memdev == NULL) 824 + return; 825 + 826 + for (n = 0; n < dmi_memdev_nr; n++) { 827 + if (handle == dmi_memdev[n].handle) { 828 + *bank = dmi_memdev[n].bank; 829 + *device = dmi_memdev[n].device; 830 + break; 831 + } 832 + } 833 + } 834 + EXPORT_SYMBOL_GPL(dmi_memdev_name);
+5
include/linux/dmi.h
··· 99 99 extern const struct dmi_device * dmi_find_device(int type, const char *name, 100 100 const struct dmi_device *from); 101 101 extern void dmi_scan_machine(void); 102 + extern void dmi_memdev_walk(void); 102 103 extern void dmi_set_dump_stack_arch_desc(void); 103 104 extern bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp); 104 105 extern int dmi_name_in_vendors(const char *str); ··· 108 107 extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), 109 108 void *private_data); 110 109 extern bool dmi_match(enum dmi_field f, const char *str); 110 + extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); 111 111 112 112 #else 113 113 ··· 117 115 static inline const struct dmi_device * dmi_find_device(int type, const char *name, 118 116 const struct dmi_device *from) { return NULL; } 119 117 static inline void dmi_scan_machine(void) { return; } 118 + static inline void dmi_memdev_walk(void) { } 120 119 static inline void dmi_set_dump_stack_arch_desc(void) { } 121 120 static inline bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp) 122 121 { ··· 136 133 void *private_data) { return -1; } 137 134 static inline bool dmi_match(enum dmi_field f, const char *str) 138 135 { return false; } 136 + static inline void dmi_memdev_name(u16 handle, const char **bank, 137 + const char **device) { } 139 138 static inline const struct dmi_system_id * 140 139 dmi_first_match(const struct dmi_system_id *list) { return NULL; } 141 140