Jesse Keating 2f82dd
From: Carlos Corbacho <carlos@strangeworlds.co.uk>
Jesse Keating 2f82dd
Date: Sat, 26 Dec 2009 19:14:59 +0000 (+0000)
Jesse Keating 2f82dd
Subject: ACPI: WMI: Survive BIOS with duplicate GUIDs
Jesse Keating 2f82dd
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=d1f9e4970742bb1e22d07b01bd44f9c357d25c42
Jesse Keating 2f82dd
Jesse Keating 2f82dd
ACPI: WMI: Survive BIOS with duplicate GUIDs
Jesse Keating 2f82dd
Jesse Keating 2f82dd
It would appear that in BIOS's with nVidia hooks, the GUID
Jesse Keating 2f82dd
05901221-D566-11D1-B2F0-00A0C9062910 is duplicated. For now, the simplest
Jesse Keating 2f82dd
solution is to just ignore any duplicate GUIDs. These particular hooks are not
Jesse Keating 2f82dd
currently supported/ used in the kernel, so whoever does that can figure out
Jesse Keating 2f82dd
what the 'right' solution should be (if there's a better one).
Jesse Keating 2f82dd
Jesse Keating 2f82dd
http://bugzilla.kernel.org/show_bug.cgi?id=14846
Jesse Keating 2f82dd
Jesse Keating 2f82dd
Signed-off-by: Carlos Corbacho <carlos@strangeworlds.co.uk>
Jesse Keating 2f82dd
Reported-by: Larry Finger <larry.finger@lwfinger.net>
Jesse Keating 2f82dd
Reported-by: Oldřich Jedlička <oldium.pro@seznam.cz>
Jesse Keating 2f82dd
Signed-off-by: Len Brown <len.brown@intel.com>
Jesse Keating 2f82dd
---
Jesse Keating 2f82dd
Jesse Keating 2f82dd
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
Jesse Keating 2f82dd
index cc9ad74..b104302 100644
Jesse Keating 2f82dd
--- a/drivers/platform/x86/wmi.c
Jesse Keating 2f82dd
+++ b/drivers/platform/x86/wmi.c
Jesse Keating 2f82dd
@@ -714,6 +714,22 @@ static int wmi_class_init(void)
Jesse Keating 2f82dd
 	return ret;
Jesse Keating 2f82dd
 }
Jesse Keating 2f82dd
 
Jesse Keating 2f82dd
+static bool guid_already_parsed(const char *guid_string)
Jesse Keating 2f82dd
+{
Jesse Keating 2f82dd
+	struct guid_block *gblock;
Jesse Keating 2f82dd
+	struct wmi_block *wblock;
Jesse Keating 2f82dd
+	struct list_head *p;
Jesse Keating 2f82dd
+
Jesse Keating 2f82dd
+	list_for_each(p, &wmi_blocks.list) {
Jesse Keating 2f82dd
+		wblock = list_entry(p, struct wmi_block, list);
Jesse Keating 2f82dd
+		gblock = &wblock->gblock;
Jesse Keating 2f82dd
+
Jesse Keating 2f82dd
+		if (strncmp(gblock->guid, guid_string, 16) == 0)
Jesse Keating 2f82dd
+			return true;
Jesse Keating 2f82dd
+	}
Jesse Keating 2f82dd
+	return false;
Jesse Keating 2f82dd
+}
Jesse Keating 2f82dd
+
Jesse Keating 2f82dd
 /*
Jesse Keating 2f82dd
  * Parse the _WDG method for the GUID data blocks
Jesse Keating 2f82dd
  */
Jesse Keating 2f82dd
@@ -723,6 +739,7 @@ static __init acpi_status parse_wdg(acpi_handle handle)
Jesse Keating 2f82dd
 	union acpi_object *obj;
Jesse Keating 2f82dd
 	struct guid_block *gblock;
Jesse Keating 2f82dd
 	struct wmi_block *wblock;
Jesse Keating 2f82dd
+	char guid_string[37];
Jesse Keating 2f82dd
 	acpi_status status;
Jesse Keating 2f82dd
 	u32 i, total;
Jesse Keating 2f82dd
 
Jesse Keating 2f82dd
@@ -745,6 +762,19 @@ static __init acpi_status parse_wdg(acpi_handle handle)
Jesse Keating 2f82dd
 	memcpy(gblock, obj->buffer.pointer, obj->buffer.length);
Jesse Keating 2f82dd
 
Jesse Keating 2f82dd
 	for (i = 0; i < total; i++) {
Jesse Keating 2f82dd
+		/*
Jesse Keating 2f82dd
+		  Some WMI devices, like those for nVidia hooks, have a
Jesse Keating 2f82dd
+		  duplicate GUID. It's not clear what we should do in this
Jesse Keating 2f82dd
+		  case yet, so for now, we'll just ignore the duplicate.
Jesse Keating 2f82dd
+		  Anyone who wants to add support for that device can come
Jesse Keating 2f82dd
+		  up with a better workaround for the mess then.
Jesse Keating 2f82dd
+		*/
Jesse Keating 2f82dd
+		if (guid_already_parsed(gblock[i].guid) == true) {
Jesse Keating 2f82dd
+			wmi_gtoa(gblock[i].guid, guid_string);
Jesse Keating 2f82dd
+			printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n",
Jesse Keating 2f82dd
+				guid_string);
Jesse Keating 2f82dd
+			continue;
Jesse Keating 2f82dd
+		}
Jesse Keating 2f82dd
 		wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
Jesse Keating 2f82dd
 		if (!wblock)
Jesse Keating 2f82dd
 			return AE_NO_MEMORY;