http://linux-acpi.bkbits.net/linux-acpi-test-2.6.7
len.brown@intel.com|ChangeSet|20040518203627|40332 len.brown

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/05/18 14:22:47-07:00 akpm@bix.(none) 
#   Merge http://linux-acpi.bkbits.net/linux-acpi-test-2.6.7
#   into bix.(none):/usr/src/bk-acpi
# 
# arch/ia64/kernel/acpi.c
#   2004/05/18 14:22:44-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/i386/kernel/acpi/boot.c
#   2004/05/18 14:22:44-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/18 14:39:54-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/old/linux-acpi-test-2.6.5
#   into intel.com:/home/lenb/src/linux-acpi-test-2.6.6
# 
# drivers/acpi/scan.c
#   2004/05/18 14:39:52-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/18 14:30:02-04:00 len.brown@intel.com 
#   [ACPI] remove /proc files before unloading modules
#   from Sau Dan Lee, Zhenyu Wang
#   http://bugzilla.kernel.org/show_bug.cgi?id=2705
# 
# drivers/acpi/thermal.c
#   2004/05/18 14:29:57-04:00 len.brown@intel.com +10 -0
#   remove /proc files before unloading modules
# 
# drivers/acpi/power.c
#   2004/05/18 14:29:57-04:00 len.brown@intel.com +2 -0
#   remove /proc files before unloading modules
# 
# drivers/acpi/fan.c
#   2004/05/18 14:29:57-04:00 len.brown@intel.com +2 -0
#   remove /proc files before unloading modules
# 
# drivers/acpi/ec.c
#   2004/05/18 14:29:56-04:00 len.brown@intel.com +6 -0
#   remove /proc files before unloading modules
# 
# drivers/acpi/button.c
#   2004/05/18 14:29:56-04:00 len.brown@intel.com +10 -0
#   remove /proc files before unloading modules
# 
# drivers/acpi/battery.c
#   2004/05/18 14:29:56-04:00 len.brown@intel.com +7 -0
#   remove /proc files before unloading modules
# 
# drivers/acpi/asus_acpi.c
#   2004/05/18 14:29:56-04:00 len.brown@intel.com +25 -1
#   remove /proc files before unloading modules
# 
# drivers/acpi/ac.c
#   2004/05/18 14:29:56-04:00 len.brown@intel.com +3 -0
#   remove /proc files before unloading modules
# 
# ChangeSet
#   2004/05/18 12:19:00-04:00 len.brown@intel.com 
#   [ACPI] revert button module unload fix (2281)
#   Cset exclude: len.brown@intel.com|ChangeSet|20040503042906|02093
#   Cset exclude: len.brown@intel.com|ChangeSet|20040428081825|02121
#   Cset exclude: len.brown@intel.com[lenb]|ChangeSet|20040428071221|03892
# 
# drivers/acpi/scan.c
#   2004/05/18 12:18:58-04:00 len.brown@intel.com +0 -0
#   [ACPI] revert button module unload fix (2281)
# 
# drivers/acpi/button.c
#   2004/05/18 12:18:58-04:00 len.brown@intel.com +0 -0
#   [ACPI] revert button module unload fix (2281)
# 
# ChangeSet
#   2004/05/16 01:19:02-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-acpi
# 
# arch/ia64/kernel/acpi.c
#   2004/05/16 01:18:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# arch/i386/kernel/acpi/boot.c
#   2004/05/16 01:18:58-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/15 17:32:48-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/bk/linux-2.6.7
#   into intel.com:/home/lenb/src/linux-acpi-test-2.6.7
# 
# arch/ia64/kernel/acpi.c
#   2004/05/15 17:32:44-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/i386/kernel/acpi/boot.c
#   2004/05/15 17:32:44-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/14 23:14:04-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.6
#   into intel.com:/home/lenb/src/linux-acpi-test-2.6.7
# 
# arch/x86_64/kernel/io_apic.c
#   2004/05/14 23:14:00-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/05/14 23:09:23-04:00 len.brown@intel.com 
#   [ACPI] delete IOAPIC-disable workaround on x86_64/VIA
#   http://bugme.osdl.org/show_bug.cgi?id=1530
# 
# arch/x86_64/kernel/io_apic.c
#   2004/05/14 23:09:16-04:00 len.brown@intel.com +1 -1
#   delete IOAPIC-disable workaround on x86_64/VIA
# 
# ChangeSet
#   2004/05/13 00:10:47-04:00 len.brown@intel.com 
#   [ACPI] create kacpid thread to handle ACPI work in process context.
#   Also will be needed for cpu hot-unplug.
#   from Anil S Keshavamurthy and David Shaohua Li
#   http://bugzilla.kernel.org/show_bug.cgi?id=2515
# 
# include/acpi/acpiosxf.h
#   2004/04/19 23:34:36-04:00 len.brown@intel.com +4 -0
#   create kacpid
# 
# drivers/acpi/scan.c
#   2004/04/19 23:34:36-04:00 len.brown@intel.com +2 -0
#   create kacpid
# 
# drivers/acpi/osl.c
#   2004/04/19 23:33:26-04:00 len.brown@intel.com +14 -2
#   create kacpid
# 
# drivers/acpi/events/evxface.c
#   2004/04/19 23:34:36-04:00 len.brown@intel.com +27 -0
#   create kacpid
# 
# drivers/acpi/acpi_ksyms.c
#   2004/04/19 23:34:36-04:00 len.brown@intel.com +1 -1
#   create kacpid
# 
# ChangeSet
#   2004/05/12 23:31:01-04:00 len.brown@intel.com 
#   [ACPI] Add MADT error checking (Yi Zhu)
#   http://bugzilla.kernel.org/show_bug.cgi?id=1434
# 
# include/linux/acpi.h
#   2004/05/12 23:30:55-04:00 len.brown@intel.com +1 -1
#   Add MADT error checking
# 
# drivers/acpi/tables.c
#   2004/05/12 23:30:55-04:00 len.brown@intel.com +3 -2
#   Add MADT error checking
# 
# arch/ia64/kernel/acpi.c
#   2004/05/12 23:30:55-04:00 len.brown@intel.com +27 -14
#   Add MADT error checking
# 
# arch/i386/kernel/acpi/boot.c
#   2004/05/12 23:30:55-04:00 len.brown@intel.com +29 -13
#   Add MADT error checking
# 
# ChangeSet
#   2004/05/12 01:57:31-04:00 len.brown@intel.com 
#   Merge intel.com:/home/lenb/src/linux-acpi-test-2.6.6
#   into intel.com:/home/lenb/src/linux-acpi-test-2.6.7
# 
# arch/i386/mach-es7000/es7000plat.c
#   2004/05/12 01:57:24-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# BitKeeper/deleted/.del-setup.c~1b687d49b2d0b042
#   2004/05/12 01:57:24-04:00 len.brown@intel.com +0 -0
#   Auto merged
# 
# arch/i386/mach-es7000/es7000plat.c
#   2004/05/12 01:57:24-04:00 len.brown@intel.com +0 -0
#   Merge rename: arch/i386/mach-es7000/es7000.c -> arch/i386/mach-es7000/es7000plat.c
# 
# BitKeeper/deleted/.del-setup.c~1b687d49b2d0b042
#   2004/05/12 01:57:24-04:00 len.brown@intel.com +0 -0
#   Merge rename: arch/i386/mach-es7000/setup.c -> BitKeeper/deleted/.del-setup.c~1b687d49b2d0b042
# 
# ChangeSet
#   2004/05/12 00:37:02-04:00 len.brown@intel.com 
#   [ACPI] if _STA.functional, set _STA.present (Bjorn Helgaas)
#   workaround for Big Sur and Bull systems
# 
# drivers/acpi/bus.c
#   2004/05/12 00:36:55-04:00 len.brown@intel.com +8 -0
#   if _STA.functional, set _STA.present
#   workaround for Big Sur and Bull systems
# 
# ChangeSet
#   2004/05/11 23:53:05-04:00 len.brown@intel.com 
#   [ACPI] create platform_rename_gsi() so ES7000 can munge IRQ numbers
#   from Natalie Protasevich
# 
# arch/i386/mach-es7000/es7000.c
#   2004/05/11 23:53:00-04:00 len.brown@intel.com +24 -0
#   platform_rename_gsi = es7000_rename_gsi
# 
# arch/i386/kernel/mpparse.c
#   2004/05/11 23:53:00-04:00 len.brown@intel.com +4 -4
#   call platform_rename_gsi() to allow ES7000 to munge IRQ#'s
# 
# arch/i386/mach-es7000/setup.c
#   2004/05/11 17:18:42-04:00 len.brown@intel.com +2 -1
#   whitespace
# 
diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
--- a/arch/i386/kernel/acpi/boot.c	Tue May 18 23:39:17 2004
+++ b/arch/i386/kernel/acpi/boot.c	Tue May 18 23:39:17 2004
@@ -51,6 +51,10 @@
 
 #endif	/* X86 */
 
+#define BAD_MADT_ENTRY(entry, end) (					    \
+		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
+		((acpi_table_entry_header *)entry)->length != sizeof(*entry))
+
 #define PREFIX			"ACPI: "
 
 #ifdef CONFIG_ACPI_PCI
@@ -204,12 +208,13 @@
 
 static int __init
 acpi_parse_lapic (
-	acpi_table_entry_header *header)
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_lapic	*processor = NULL;
 
 	processor = (struct acpi_table_lapic*) header;
-	if (!processor)
+
+	if (BAD_MADT_ENTRY(processor, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -225,15 +230,15 @@
 	return 0;
 }
 
-
 static int __init
 acpi_parse_lapic_addr_ovr (
-	acpi_table_entry_header *header)
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
 
 	lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
-	if (!lapic_addr_ovr)
+
+	if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
 		return -EINVAL;
 
 	acpi_lapic_addr = lapic_addr_ovr->address;
@@ -243,12 +248,13 @@
 
 static int __init
 acpi_parse_lapic_nmi (
-	acpi_table_entry_header *header)
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_lapic_nmi *lapic_nmi = NULL;
 
 	lapic_nmi = (struct acpi_table_lapic_nmi*) header;
-	if (!lapic_nmi)
+
+	if (BAD_MADT_ENTRY(lapic_nmi, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -266,12 +272,13 @@
 
 static int __init
 acpi_parse_ioapic (
-	acpi_table_entry_header *header)
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_ioapic *ioapic = NULL;
 
 	ioapic = (struct acpi_table_ioapic*) header;
-	if (!ioapic)
+
+	if (BAD_MADT_ENTRY(ioapic, end))
 		return -EINVAL;
  
 	acpi_table_print_madt_entry(header);
@@ -320,12 +327,13 @@
 
 static int __init
 acpi_parse_int_src_ovr (
-	acpi_table_entry_header *header)
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_int_src_ovr *intsrc = NULL;
 
 	intsrc = (struct acpi_table_int_src_ovr*) header;
-	if (!intsrc)
+
+	if (BAD_MADT_ENTRY(intsrc, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -354,12 +362,13 @@
 
 static int __init
 acpi_parse_nmi_src (
-	acpi_table_entry_header *header)
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_nmi_src *nmi_src = NULL;
 
 	nmi_src = (struct acpi_table_nmi_src*) header;
-	if (!nmi_src)
+
+	if (BAD_MADT_ENTRY(nmi_src, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -718,6 +727,13 @@
 				smp_found_config = 1;
 				clustered_apic_check();
 			}
+		}
+		if (error == -EINVAL) {
+			/*
+			 * Dell Precision Workstation 410, 610 come here.
+			 */
+			printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n");
+			disable_acpi();
 		}
 	}
 #endif
diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
--- a/arch/i386/kernel/mpparse.c	Tue May 18 23:39:17 2004
+++ b/arch/i386/kernel/mpparse.c	Tue May 18 23:39:17 2004
@@ -1029,6 +1029,8 @@
 
 #ifdef CONFIG_ACPI_PCI
 
+int (*platform_rename_gsi)(int ioapic, int gsi);
+
 void __init mp_parse_prt (void)
 {
 	struct list_head	*node = NULL;
@@ -1072,10 +1074,8 @@
 			continue;
 		ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
 
-		if (es7000_plat) {
-			if (!ioapic && (gsi < 16))
-				gsi += 16;
-		}
+		if (platform_rename_gsi)
+			gsi = platform_rename_gsi(ioapic, gsi);
 
 		/* 
 		 * Avoid pin reprogramming.  PRTs typically include entries  
diff -Nru a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
--- a/arch/i386/mach-es7000/es7000plat.c	Tue May 18 23:39:17 2004
+++ b/arch/i386/mach-es7000/es7000plat.c	Tue May 18 23:39:17 2004
@@ -50,6 +50,29 @@
 struct mip_reg		*host_reg;
 int 			mip_port;
 unsigned long		mip_addr, host_addr;
+extern int (*platform_rename_gsi)();
+
+static int __init
+es7000_rename_gsi(int ioapic, int gsi)
+{
+	if (ioapic)
+		return gsi;
+	else {
+		if (gsi == 0)
+			return 13;
+		if (gsi == 1)
+			return 16;
+		if (gsi == 4)
+			return 17;
+		if (gsi == 6)
+			return 18;
+		if (gsi == 7)
+			return 19;
+		if (gsi == 8)
+			return 20;
+		return gsi;
+        }
+}
 
 /*
  * Parse the OEM Table
@@ -116,6 +139,7 @@
 	} else {
 		printk("\nEnabling ES7000 specific features...\n");
 		es7000_plat = 1;
+		platform_rename_gsi = es7000_rename_gsi;
 	}
 	return es7000_plat;
 }
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Tue May 18 23:39:17 2004
+++ b/arch/ia64/kernel/acpi.c	Tue May 18 23:39:17 2004
@@ -52,6 +52,9 @@
 #include <asm/sal.h>
 #include <asm/cyclone.h>
 
+#define BAD_MADT_ENTRY(entry, end) (                                        \
+		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
+		((acpi_table_entry_header *)entry)->length != sizeof(*entry))
 
 #define PREFIX			"ACPI: "
 
@@ -158,12 +161,14 @@
 
 
 static int __init
-acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header)
+acpi_parse_lapic_addr_ovr (
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_lapic_addr_ovr *lapic;
 
 	lapic = (struct acpi_table_lapic_addr_ovr *) header;
-	if (!lapic)
+
+	if (BAD_MADT_ENTRY(lapic, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -177,12 +182,13 @@
 
 
 static int __init
-acpi_parse_lsapic (acpi_table_entry_header *header)
+acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_lsapic *lsapic;
 
 	lsapic = (struct acpi_table_lsapic *) header;
-	if (!lsapic)
+
+	if (BAD_MADT_ENTRY(lsapic, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -210,12 +216,13 @@
 
 
 static int __init
-acpi_parse_lapic_nmi (acpi_table_entry_header *header)
+acpi_parse_lapic_nmi (acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_lapic_nmi *lacpi_nmi;
 
 	lacpi_nmi = (struct acpi_table_lapic_nmi*) header;
-	if (!lacpi_nmi)
+
+	if (BAD_MADT_ENTRY(lacpi_nmi, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -226,12 +233,13 @@
 
 
 static int __init
-acpi_parse_iosapic (acpi_table_entry_header *header)
+acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_iosapic *iosapic;
 
 	iosapic = (struct acpi_table_iosapic *) header;
-	if (!iosapic)
+
+	if (BAD_MADT_ENTRY(iosapic, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -243,13 +251,15 @@
 
 
 static int __init
-acpi_parse_plat_int_src (acpi_table_entry_header *header)
+acpi_parse_plat_int_src (
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_plat_int_src *plintsrc;
 	int vector;
 
 	plintsrc = (struct acpi_table_plat_int_src *) header;
-	if (!plintsrc)
+
+	if (BAD_MADT_ENTRY(plintsrc, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -272,12 +282,14 @@
 
 
 static int __init
-acpi_parse_int_src_ovr (acpi_table_entry_header *header)
+acpi_parse_int_src_ovr (
+	acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_int_src_ovr *p;
 
 	p = (struct acpi_table_int_src_ovr *) header;
-	if (!p)
+
+	if (BAD_MADT_ENTRY(p, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
@@ -290,12 +302,13 @@
 
 
 static int __init
-acpi_parse_nmi_src (acpi_table_entry_header *header)
+acpi_parse_nmi_src (acpi_table_entry_header *header, const unsigned long end)
 {
 	struct acpi_table_nmi_src *nmi_src;
 
 	nmi_src = (struct acpi_table_nmi_src*) header;
-	if (!nmi_src)
+
+	if (BAD_MADT_ENTRY(nmi_src, end))
 		return -EINVAL;
 
 	acpi_table_print_madt_entry(header);
diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
--- a/arch/x86_64/kernel/io_apic.c	Tue May 18 23:39:17 2004
+++ b/arch/x86_64/kernel/io_apic.c	Tue May 18 23:39:17 2004
@@ -259,7 +259,7 @@
 						iommu_aperture_disabled = 1;
 					}
 #endif
-					/* FALL THROUGH */
+					return;
 				case PCI_VENDOR_ID_NVIDIA:
 #ifndef CONFIG_SMP
 					printk(KERN_INFO 
diff -Nru a/drivers/acpi/ac.c b/drivers/acpi/ac.c
--- a/drivers/acpi/ac.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/ac.c	Tue May 18 23:39:17 2004
@@ -185,6 +185,9 @@
 	ACPI_FUNCTION_TRACE("acpi_ac_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_AC_FILE_STATE,
+				  acpi_device_dir(device));
+
 		remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
 		acpi_device_dir(device) = NULL;
 	}
diff -Nru a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c
--- a/drivers/acpi/acpi_ksyms.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/acpi_ksyms.c	Tue May 18 23:39:17 2004
@@ -106,7 +106,7 @@
 EXPORT_SYMBOL(acpi_os_create_semaphore);
 EXPORT_SYMBOL(acpi_os_delete_semaphore);
 EXPORT_SYMBOL(acpi_os_wait_semaphore);
-
+EXPORT_SYMBOL(acpi_os_wait_events_complete);
 EXPORT_SYMBOL(acpi_os_read_pci_configuration);
 
 /* ACPI Utilities (acpi_utils.c) */
diff -Nru a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
--- a/drivers/acpi/asus_acpi.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/asus_acpi.c	Tue May 18 23:39:17 2004
@@ -863,6 +863,29 @@
 	return 0;
 }
 
+static int asus_hotk_remove_fs(struct acpi_device* device)
+{
+	struct asus_hotk* hotk = acpi_driver_data(device);
+
+
+	if(acpi_device_dir(device)){
+		remove_proc_entry(PROC_INFO,acpi_device_dir(device));
+		if (hotk->methods->mt_wled)
+			remove_proc_entry(PROC_WLED,acpi_device_dir(device));
+		if (hotk->methods->mt_mled)
+			remove_proc_entry(PROC_MLED,acpi_device_dir(device));
+		if (hotk->methods->mt_tled)
+			remove_proc_entry(PROC_TLED,acpi_device_dir(device));
+		if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) 
+			remove_proc_entry(PROC_LCD, acpi_device_dir(device));
+		if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_get)) 
+			remove_proc_entry(PROC_BRN, acpi_device_dir(device));
+		if (hotk->methods->display_set) 
+			remove_proc_entry(PROC_DISP, acpi_device_dir(device));
+	}
+	return 0;
+}
+
 
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
@@ -1111,7 +1134,6 @@
 	return(result);
 }
 
-
 static int asus_hotk_remove(struct acpi_device *device, int type)
 {
 	acpi_status status = 0;
@@ -1126,6 +1148,8 @@
 					    asus_hotk_notify);
 	if (ACPI_FAILURE(status))
 		printk(KERN_ERR "Asus ACPI: Error removing notify handler\n");
+
+	asus_hotk_remove_fs(device);
 
 	kfree(hotk);
 
diff -Nru a/drivers/acpi/battery.c b/drivers/acpi/battery.c
--- a/drivers/acpi/battery.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/battery.c	Tue May 18 23:39:17 2004
@@ -679,6 +679,13 @@
 	ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_BATTERY_FILE_INFO,
+				  acpi_device_dir(device));
+
 		remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
 		acpi_device_dir(device) = NULL;
 	}
diff -Nru a/drivers/acpi/bus.c b/drivers/acpi/bus.c
--- a/drivers/acpi/bus.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/bus.c	Tue May 18 23:39:17 2004
@@ -112,6 +112,14 @@
 	else
 		STRUCT_TO_INT(device->status) = 0x0F;
 
+	if (device->status.functional && !device->status.present) {
+		printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: "
+			"functional but not present; setting present\n",
+			device->pnp.bus_id,
+			(u32) STRUCT_TO_INT(device->status));
+		device->status.present = 1;
+	}
+
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", 
 		device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)));
 
diff -Nru a/drivers/acpi/button.c b/drivers/acpi/button.c
--- a/drivers/acpi/button.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/button.c	Tue May 18 23:39:17 2004
@@ -108,9 +108,6 @@
    -------------------------------------------------------------------------- */
 
 static struct proc_dir_entry	*acpi_button_dir;
-extern struct acpi_device 	*acpi_fixed_pwr_button;
-extern struct acpi_device	*acpi_fixed_sleep_button;
-
 
 static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
 {
@@ -241,6 +238,16 @@
 
 	button = acpi_driver_data(device);
 	if (acpi_device_dir(device)) {
+		if (button->type == ACPI_BUTTON_TYPE_LID)
+			remove_proc_entry(ACPI_BUTTON_FILE_STATE,
+					     acpi_device_dir(device));
+		remove_proc_entry(ACPI_BUTTON_FILE_INFO,
+				     acpi_device_dir(device));
+
+		remove_proc_entry(acpi_device_bid(device),
+				     acpi_device_dir(device)->parent);
+
+
 		switch (button->type) {
 			case ACPI_BUTTON_TYPE_POWER:
 			case ACPI_BUTTON_TYPE_POWERF:
@@ -529,12 +536,6 @@
 acpi_button_exit (void)
 {
 	ACPI_FUNCTION_TRACE("acpi_button_exit");
-
-	if(acpi_fixed_pwr_button) 
-		acpi_button_remove(acpi_fixed_pwr_button, ACPI_BUS_TYPE_POWER_BUTTON);
-
-	if(acpi_fixed_sleep_button)
-		acpi_button_remove(acpi_fixed_sleep_button, ACPI_BUS_TYPE_SLEEP_BUTTON);
 
 	acpi_bus_unregister_driver(&acpi_button_driver);
 
diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c
--- a/drivers/acpi/ec.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/ec.c	Tue May 18 23:39:17 2004
@@ -548,6 +548,12 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_ec_remove_fs");
 
+	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
+		remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
+		acpi_device_dir(device) = NULL;
+	}
+
 	return_VALUE(0);
 }
 
diff -Nru a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
--- a/drivers/acpi/events/evxface.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/events/evxface.c	Tue May 18 23:39:17 2004
@@ -406,6 +406,15 @@
 			goto unlock_and_exit;
 		}
 
+		/* Make sure all deferred tasks are completed */
+
+		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+		acpi_os_wait_events_complete(NULL);
+		status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+ 		}
+
 		if (handler_type == ACPI_SYSTEM_NOTIFY) {
 			acpi_gbl_system_notify.node  = NULL;
 			acpi_gbl_system_notify.handler = NULL;
@@ -452,6 +461,15 @@
 			goto unlock_and_exit;
 		}
 
+		/* Make sure all deferred tasks are completed */
+
+		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+		acpi_os_wait_events_complete(NULL);
+		status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+ 		}
+
 		/* Remove the handler */
 
 		if (handler_type == ACPI_SYSTEM_NOTIFY) {
@@ -613,6 +631,15 @@
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
 	}
+
+	/* Make sure all deferred tasks are completed */
+
+	(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+	acpi_os_wait_events_complete(NULL);
+	status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+ 	}
 
 	/* Remove the handler */
 
diff -Nru a/drivers/acpi/fan.c b/drivers/acpi/fan.c
--- a/drivers/acpi/fan.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/fan.c	Tue May 18 23:39:17 2004
@@ -185,6 +185,8 @@
 	ACPI_FUNCTION_TRACE("acpi_fan_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_FAN_FILE_STATE,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
 		acpi_device_dir(device) = NULL;
 	}
diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c
--- a/drivers/acpi/osl.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/osl.c	Tue May 18 23:39:17 2004
@@ -66,6 +66,7 @@
 static unsigned int acpi_irq_irq;
 static OSD_HANDLER acpi_irq_handler;
 static void *acpi_irq_context;
+static struct workqueue_struct *kacpid_wq;
 
 acpi_status
 acpi_os_initialize(void)
@@ -80,6 +81,8 @@
 		return AE_NULL_ENTRY;
 	}
 #endif
+	kacpid_wq = create_singlethread_workqueue("kacpid");
+	BUG_ON(!kacpid_wq);
 
 	return AE_OK;
 }
@@ -92,6 +95,8 @@
 						 acpi_irq_handler);
 	}
 
+	destroy_workqueue(kacpid_wq);
+
 	return AE_OK;
 }
 
@@ -654,13 +659,20 @@
 	task = (void *)(dpc+1);
 	INIT_WORK(task, acpi_os_execute_deferred, (void*)dpc);
 
-	if (!schedule_work(task)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to schedule_work() failed.\n"));
+	if (!queue_work(kacpid_wq, task)) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Call to queue_work() failed.\n"));
 		kfree(dpc);
 		status = AE_ERROR;
 	}
 
 	return_ACPI_STATUS (status);
+}
+
+void
+acpi_os_wait_events_complete(
+	void *context)
+{
+	flush_workqueue(kacpid_wq);
 }
 
 /*
diff -Nru a/drivers/acpi/power.c b/drivers/acpi/power.c
--- a/drivers/acpi/power.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/power.c	Tue May 18 23:39:17 2004
@@ -482,6 +482,8 @@
 	ACPI_FUNCTION_TRACE("acpi_power_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_POWER_FILE_STATUS,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_power_dir);
 		acpi_device_dir(device) = NULL;
 	}
diff -Nru a/drivers/acpi/scan.c b/drivers/acpi/scan.c
--- a/drivers/acpi/scan.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/scan.c	Tue May 18 23:39:17 2004
@@ -4,7 +4,6 @@
 
 #include <linux/init.h>
 #include <linux/acpi.h>
-#include <linux/module.h>
 
 #include <acpi/acpi_drivers.h>
 #include <acpi/acinterp.h>	/* for acpi_ex_eisa_id_to_string() */
@@ -16,12 +15,6 @@
 #define STRUCT_TO_INT(s)	(*((int*)&s))
 
 extern struct acpi_device		*acpi_root;
-struct acpi_device 		*acpi_fixed_pwr_button;
-struct acpi_device 		*acpi_fixed_sleep_button;
-
-EXPORT_SYMBOL(acpi_fixed_pwr_button);
-EXPORT_SYMBOL(acpi_fixed_sleep_button);
-
 
 
 #define ACPI_BUS_CLASS			"system_bus"
@@ -318,8 +311,10 @@
 		struct acpi_device * dev = container_of(node,struct acpi_device,g_list);
 
 		if (dev->driver == drv) {
+			spin_unlock(&acpi_device_lock);
 			if (drv->ops.remove)
 				drv->ops.remove(dev,ACPI_BUS_REMOVAL_NORMAL);
+			spin_lock(&acpi_device_lock);
 			dev->driver = NULL;
 			dev->driver_data = NULL;
 			atomic_dec(&drv->references);
@@ -907,13 +902,10 @@
 	struct acpi_device	*root)
 {
 	int			result = 0;
+	struct acpi_device	*device = NULL;
 
 	ACPI_FUNCTION_TRACE("acpi_bus_scan_fixed");
 
-	acpi_fixed_pwr_button = NULL;
-	acpi_fixed_sleep_button = NULL;
-
-
 	if (!root)
 		return_VALUE(-ENODEV);
 
@@ -921,11 +913,11 @@
 	 * Enumerate all fixed-feature devices.
 	 */
 	if (acpi_fadt.pwr_button == 0)
-		result = acpi_bus_add(&acpi_fixed_pwr_button, acpi_root, 
+		result = acpi_bus_add(&device, acpi_root, 
 			NULL, ACPI_BUS_TYPE_POWER_BUTTON);
 
 	if (acpi_fadt.sleep_button == 0)
-		result = acpi_bus_add(&acpi_fixed_sleep_button, acpi_root, 
+		result = acpi_bus_add(&device, acpi_root, 
 			NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
 
 	return_VALUE(result);
diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c
--- a/drivers/acpi/tables.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/tables.c	Tue May 18 23:39:17 2004
@@ -343,10 +343,11 @@
 	entry = (acpi_table_entry_header *)
 		((unsigned long) madt + madt_size);
 
-	while (((unsigned long) entry) < madt_end) {
+	while (((unsigned long) entry) + sizeof(acpi_table_entry_header) < madt_end) {
 		if (entry->type == entry_id &&
 		    (!max_entries || count++ < max_entries))
-			handler(entry);
+			if (handler(entry, madt_end))
+				return -EINVAL;
 
 		entry = (acpi_table_entry_header *)
 			((unsigned long) entry + entry->length);
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	Tue May 18 23:39:17 2004
+++ b/drivers/acpi/thermal.c	Tue May 18 23:39:17 2004
@@ -1139,6 +1139,16 @@
 	ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_STATE,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
 		acpi_device_dir(device) = NULL;
 	}
diff -Nru a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
--- a/include/acpi/acpiosxf.h	Tue May 18 23:39:17 2004
+++ b/include/acpi/acpiosxf.h	Tue May 18 23:39:17 2004
@@ -213,6 +213,10 @@
 	void                            *context);
 
 void
+acpi_os_wait_events_complete(
+	void * context);
+
+void
 acpi_os_sleep (
 	u32                             seconds,
 	u32                             milliseconds);
diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h
--- a/include/linux/acpi.h	Tue May 18 23:39:17 2004
+++ b/include/linux/acpi.h	Tue May 18 23:39:17 2004
@@ -374,7 +374,7 @@
 
 extern acpi_table_handler acpi_table_ops[ACPI_TABLE_COUNT];
 
-typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header);
+typedef int (*acpi_madt_entry_handler) (acpi_table_entry_header *header, const unsigned long end);
 
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 unsigned long acpi_find_rsdp (void);