]> Pileus Git - ~andy/linux/blobdiff - drivers/firmware/dmi_scan.c
drivers/rtc/rtc-sh.c: use dev_get_platdata()
[~andy/linux] / drivers / firmware / dmi_scan.c
index fa0affb699b42f51a070fb336d2f66df38b9dce6..c7e81ff8f3ef7079a7ccc3e4c04bc6ec59516015 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/bootmem.h>
 #include <linux/random.h>
 #include <asm/dmi.h>
+#include <asm/unaligned.h>
 
 /*
  * DMI stands for "Desktop Management Interface".  It is part
@@ -25,6 +26,13 @@ static int dmi_initialized;
 /* DMI system identification string used during boot */
 static char dmi_ids_string[128] __initdata;
 
+static struct dmi_memdev_info {
+       const char *device;
+       const char *bank;
+       u16 handle;
+} *dmi_memdev;
+static int dmi_memdev_nr;
+
 static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
 {
        const u8 *bp = ((u8 *) dm) + dm->length;
@@ -322,6 +330,42 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
        dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
 }
 
+static void __init count_mem_devices(const struct dmi_header *dm, void *v)
+{
+       if (dm->type != DMI_ENTRY_MEM_DEVICE)
+               return;
+       dmi_memdev_nr++;
+}
+
+static void __init save_mem_devices(const struct dmi_header *dm, void *v)
+{
+       const char *d = (const char *)dm;
+       static int nr;
+
+       if (dm->type != DMI_ENTRY_MEM_DEVICE)
+               return;
+       if (nr >= dmi_memdev_nr) {
+               pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
+               return;
+       }
+       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]);
+       nr++;
+}
+
+void __init dmi_memdev_walk(void)
+{
+       if (!dmi_available)
+               return;
+
+       if (dmi_walk_early(count_mem_devices) == 0 && dmi_memdev_nr) {
+               dmi_memdev = dmi_alloc(sizeof(*dmi_memdev) * dmi_memdev_nr);
+               if (dmi_memdev)
+                       dmi_walk_early(save_mem_devices);
+       }
+}
+
 /*
  *     Process a DMI table entry. Right now all we care about are the BIOS
  *     and machine entries. For 2.5 we should pull the smbus controller info
@@ -815,3 +859,20 @@ bool dmi_match(enum dmi_field f, const char *str)
        return !strcmp(info, str);
 }
 EXPORT_SYMBOL_GPL(dmi_match);
+
+void dmi_memdev_name(u16 handle, const char **bank, const char **device)
+{
+       int n;
+
+       if (dmi_memdev == NULL)
+               return;
+
+       for (n = 0; n < dmi_memdev_nr; n++) {
+               if (handle == dmi_memdev[n].handle) {
+                       *bank = dmi_memdev[n].bank;
+                       *device = dmi_memdev[n].device;
+                       break;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(dmi_memdev_name);