diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 653265a40b7f9721eed8fcf1c08d6f75cdfdba3d..de3027521bfaf5ece0ff6e20bfcddeb448ad80da 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -10,10 +10,9 @@
 
 static char dmi_empty_string[] = "        ";
 
-static char * __init dmi_string(const struct dmi_header *dm, u8 s)
+static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
 {
 	const u8 *bp = ((u8 *) dm) + dm->length;
-	char *str = "";
 
 	if (s) {
 		s--;
@@ -28,14 +27,29 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s)
 
 			if (!memcmp(bp, dmi_empty_string, cmp_len))
 				return dmi_empty_string;
-			str = dmi_alloc(len);
-			if (str != NULL)
-				strcpy(str, bp);
-			else
-				printk(KERN_ERR "dmi_string: cannot allocate %Zu bytes.\n", len);
+			return bp;
 		}
 	}
 
+	return "";
+}
+
+static char * __init dmi_string(const struct dmi_header *dm, u8 s)
+{
+	const char *bp = dmi_string_nosave(dm, s);
+	char *str;
+	size_t len;
+
+	if (bp == dmi_empty_string)
+		return dmi_empty_string;
+
+	len = strlen(bp) + 1;
+	str = dmi_alloc(len);
+	if (str != NULL)
+		strcpy(str, bp);
+	else
+		printk(KERN_ERR "dmi_string: cannot allocate %Zu bytes.\n", len);
+
 	return str;
 }
 
@@ -167,10 +181,30 @@ static void __init dmi_save_type(const struct dmi_header *dm, int slot, int inde
 	dmi_ident[slot] = s;
 }
 
+static void __init dmi_save_one_device(int type, const char *name)
+{
+	struct dmi_device *dev;
+
+	/* No duplicate device */
+	if (dmi_find_device(type, name, NULL))
+		return;
+
+	dev = dmi_alloc(sizeof(*dev) + strlen(name) + 1);
+	if (!dev) {
+		printk(KERN_ERR "dmi_save_one_device: out of memory.\n");
+		return;
+	}
+
+	dev->type = type;
+	strcpy((char *)(dev + 1), name);
+	dev->name = (char *)(dev + 1);
+	dev->device_data = NULL;
+	list_add(&dev->list, &dmi_devices);
+}
+
 static void __init dmi_save_devices(const struct dmi_header *dm)
 {
 	int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
-	struct dmi_device *dev;
 
 	for (i = 0; i < count; i++) {
 		const char *d = (char *)(dm + 1) + (i * 2);
@@ -179,16 +213,7 @@ static void __init dmi_save_devices(const struct dmi_header *dm)
 		if ((*d & 0x80) == 0)
 			continue;
 
-		dev = dmi_alloc(sizeof(*dev));
-		if (!dev) {
-			printk(KERN_ERR "dmi_save_devices: out of memory.\n");
-			break;
-		}
-
-		dev->type = *d++ & 0x7f;
-		dev->name = dmi_string(dm, *d);
-		dev->device_data = NULL;
-		list_add(&dev->list, &dmi_devices);
+		dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d + 1)));
 	}
 }
 
@@ -253,23 +278,12 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
 static void __init dmi_save_extended_devices(const struct dmi_header *dm)
 {
 	const u8 *d = (u8*) dm + 5;
-	struct dmi_device *dev;
 
 	/* Skip disabled device */
 	if ((*d & 0x80) == 0)
 		return;
 
-	dev = dmi_alloc(sizeof(*dev));
-	if (!dev) {
-		printk(KERN_ERR "dmi_save_extended_devices: out of memory.\n");
-		return;
-	}
-
-	dev->type = *d-- & 0x7f;
-	dev->name = dmi_string(dm, *d);
-	dev->device_data = NULL;
-
-	list_add(&dev->list, &dmi_devices);
+	dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
 }
 
 /*