Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (28 commits)
  ACPI: thermal: add DMI hooks to handle AOpen's broken Award BIOS
  ACPI: thermal: create "thermal.act=" to disable or override active trip point
  ACPI: thermal: create "thermal.nocrt" to disable critical actions
  ACPI: thermal: create "thermal.psv=" to override passive trip points
  ACPI: thermal: expose "thermal.tzp=" to set global polling frequency
  ACPI: thermal: create "thermal.off=1" to disable ACPI thermal support
  ACPI: thinkpad-acpi: fix sysfs paths in documentation
  ACPI: static
  ACPI EC: remove potential deadlock from EC
  ACPI: dock: Send key=value pair instead of plain value
  ACPI: bay: send envp with uevent - fix
  acpi-cpufreq: Fix some x86/x86-64 acpi-cpufreq driver issues
  ACPI: fix "Time Problems with 2.6.23-rc1-gf695baf2"
  ACPI: thinkpad-acpi: change thinkpad-acpi input default and kconfig help
  ACPI: EC: fix run-together printk lines
  ACPI: sbs: remove dead code
  ACPI: EC: acpi_ec_remove(): fix use-after-free
  ACPI: EC: Switch from boot_ec as soon as we find its desc in DSDT.
  ACPI: EC: fix build warning
  ACPI: EC: If ECDT is not found, look up EC in DSDT.
  ...
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index a326487..975f029 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -163,6 +163,8 @@
 	acpi_irq_isa=	[HW,ACPI] If irq_balance, mark listed IRQs used by ISA
 			Format: <irq>,<irq>...
 
+	acpi_no_auto_ssdt	[HW,ACPI] Disable automatic loading of SSDT
+
 	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
 			Format: To spoof as Windows 98: ="Microsoft Windows"
 
@@ -1820,6 +1822,26 @@
 	thash_entries=	[KNL,NET]
 			Set number of hash buckets for TCP connection
 
+	thermal.act=	[HW,ACPI]
+			-1: disable all active trip points in all thermal zones
+			<degrees C>: override all lowest active trip points
+
+	thermal.nocrt=	[HW,ACPI]
+			Set to disable actions on ACPI thermal zone
+			critical and hot trip points.
+
+	thermal.off=	[HW,ACPI]
+			1: disable ACPI thermal control
+
+	thermal.psv=	[HW,ACPI]
+			-1: disable all passive trip points
+			<degrees C>: override all passive trip points to this value
+
+	thermal.tzp=	[HW,ACPI]
+			Specify global default ACPI thermal zone polling rate
+			<deci-seconds>: poll all this frequency
+			0: no polling (default)
+
 	time		Show timing data prefixed to each printk message line
 			[deprecated, see 'printk.time']
 
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt
index 6711fbc..eb2f598 100644
--- a/Documentation/thinkpad-acpi.txt
+++ b/Documentation/thinkpad-acpi.txt
@@ -105,10 +105,10 @@
 as a driver attribute (see below).
 
 Sysfs driver attributes are on the driver's sysfs attribute space,
-for 2.6.20 this is /sys/bus/platform/drivers/thinkpad-acpi/.
+for 2.6.20 this is /sys/bus/platform/drivers/thinkpad_acpi/.
 
 Sysfs device attributes are on the driver's sysfs attribute space,
-for 2.6.20 this is /sys/devices/platform/thinkpad-acpi/.
+for 2.6.20 this is /sys/devices/platform/thinkpad_acpi/.
 
 Driver version
 --------------
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 32d04b0..705e13a 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -68,7 +68,8 @@
 };
 
 static struct acpi_cpufreq_data *drv_data[NR_CPUS];
-static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
+/* acpi_perf_data is a pointer to percpu data. */
+static struct acpi_processor_performance *acpi_perf_data;
 
 static struct cpufreq_driver acpi_cpufreq_driver;
 
@@ -508,24 +509,14 @@
  * do _PDC and _PSD and find out the processor dependency for the
  * actual init that will happen later...
  */
-static int acpi_cpufreq_early_init(void)
+static int __init acpi_cpufreq_early_init(void)
 {
-	struct acpi_processor_performance *data;
-	unsigned int i, j;
-
 	dprintk("acpi_cpufreq_early_init\n");
 
-	for_each_possible_cpu(i) {
-		data = kzalloc(sizeof(struct acpi_processor_performance),
-			       GFP_KERNEL);
-		if (!data) {
-			for_each_possible_cpu(j) {
-				kfree(acpi_perf_data[j]);
-				acpi_perf_data[j] = NULL;
-			}
-			return -ENOMEM;
-		}
-		acpi_perf_data[i] = data;
+	acpi_perf_data = alloc_percpu(struct acpi_processor_performance);
+	if (!acpi_perf_data) {
+		dprintk("Memory allocation error for acpi_perf_data.\n");
+		return -ENOMEM;
 	}
 
 	/* Do initialization in ACPI core */
@@ -574,14 +565,11 @@
 
 	dprintk("acpi_cpufreq_cpu_init\n");
 
-	if (!acpi_perf_data[cpu])
-		return -ENODEV;
-
 	data = kzalloc(sizeof(struct acpi_cpufreq_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	data->acpi_data = acpi_perf_data[cpu];
+	data->acpi_data = percpu_ptr(acpi_perf_data, cpu);
 	drv_data[cpu] = data;
 
 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC))
@@ -778,24 +766,25 @@
 
 static int __init acpi_cpufreq_init(void)
 {
+	int ret;
+
 	dprintk("acpi_cpufreq_init\n");
 
-	acpi_cpufreq_early_init();
+	ret = acpi_cpufreq_early_init();
+	if (ret)
+		return ret;
 
 	return cpufreq_register_driver(&acpi_cpufreq_driver);
 }
 
 static void __exit acpi_cpufreq_exit(void)
 {
-	unsigned int i;
 	dprintk("acpi_cpufreq_exit\n");
 
 	cpufreq_unregister_driver(&acpi_cpufreq_driver);
 
-	for_each_possible_cpu(i) {
-		kfree(acpi_perf_data[i]);
-		acpi_perf_data[i] = NULL;
-	}
+	free_percpu(acpi_perf_data);
+
 	return;
 }
 
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index 9c4bd22..86fd142 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -1192,6 +1192,7 @@
 			break;
 		default:
 			kfree(model);
+			model = NULL;
 			break;
 		}
 	}
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 8165103..d7b499f 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -113,7 +113,7 @@
 	acpi_string oem_info;
 };
 
-enum acpi_battery_files{
+enum acpi_battery_files {
 	ACPI_BATTERY_INFO = 0,
 	ACPI_BATTERY_STATE,
 	ACPI_BATTERY_ALARM,
@@ -129,13 +129,14 @@
 };
 
 struct acpi_battery {
-	struct mutex mutex;
 	struct acpi_device *device;
 	struct acpi_battery_flags flags;
 	struct acpi_buffer bif_data;
 	struct acpi_buffer bst_data;
+	struct mutex lock;
 	unsigned long alarm;
 	unsigned long update_time[ACPI_BATTERY_NUMFILES];
+
 };
 
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -235,10 +236,10 @@
 		return 0;
 
 	/* Evaluate _BIF */
-
-	status =
-	    acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
-				 &buffer);
+	mutex_lock(&battery->lock);
+	status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF",
+				      NULL, &buffer);
+	mutex_unlock(&battery->lock);
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
 		return -ENODEV;
@@ -285,10 +286,10 @@
 		return 0;
 
 	/* Evaluate _BST */
-
-	status =
-	    acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
-				 &buffer);
+	mutex_lock(&battery->lock);
+	status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST",
+				      NULL, &buffer);
+	mutex_unlock(&battery->lock);
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
 		return -ENODEV;
@@ -336,9 +337,10 @@
 
 	arg0.integer.value = alarm;
 
-	status =
-	    acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
+	mutex_lock(&battery->lock);
+	status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
 				 &arg_list, NULL);
+	mutex_unlock(&battery->lock);
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
@@ -658,8 +660,6 @@
 	if (!battery || (count > sizeof(alarm_string) - 1))
 		return -EINVAL;
 
-	mutex_lock(&battery->mutex);
-
 	result = acpi_battery_update(battery, 1, &update_result);
 	if (result) {
 		result = -ENODEV;
@@ -688,9 +688,7 @@
 	acpi_battery_check_result(battery, result);
 
 	if (!result)
-		result = count;
-
-	mutex_unlock(&battery->mutex);
+		return count;
 
 	return result;
 }
@@ -714,8 +712,6 @@
 	int update_result = ACPI_BATTERY_NONE_UPDATE;
 	int update = 0;
 
-	mutex_lock(&battery->mutex);
-
 	update = (get_seconds() - battery->update_time[fid] >= update_time);
 	update = (update | battery->flags.update[fid]);
 
@@ -733,7 +729,6 @@
 	result = acpi_read_funcs[fid].print(seq, result);
 	acpi_battery_check_result(battery, result);
 	battery->flags.update[fid] = result;
-	mutex_unlock(&battery->mutex);
 	return result;
 }
 
@@ -897,10 +892,7 @@
 	if (!battery)
 		return -ENOMEM;
 
-	mutex_init(&battery->mutex);
-
-	mutex_lock(&battery->mutex);
-
+	mutex_init(&battery->lock);
 	battery->device = device;
 	strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
@@ -936,7 +928,6 @@
 		kfree(battery);
 	}
 
-	mutex_unlock(&battery->mutex);
 
 	return result;
 }
@@ -951,8 +942,6 @@
 
 	battery = acpi_driver_data(device);
 
-	mutex_lock(&battery->mutex);
-
 	status = acpi_remove_notify_handler(device->handle,
 					    ACPI_ALL_NOTIFY,
 					    acpi_battery_notify);
@@ -963,9 +952,7 @@
 
 	kfree(battery->bst_data.pointer);
 
-	mutex_unlock(&battery->mutex);
-
-	mutex_destroy(&battery->mutex);
+	mutex_destroy(&battery->lock);
 
 	kfree(battery);
 
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
index 56a5b3f..6daf6088 100644
--- a/drivers/acpi/bay.c
+++ b/drivers/acpi/bay.c
@@ -337,7 +337,7 @@
 	char *envp[] = { event_string, NULL };
 
 	bay_dprintk(handle, "Bay event");
-	sprintf(event_string, "BAY_EVENT=%d\n", event);
+	sprintf(event_string, "BAY_EVENT=%d", event);
 	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 }
 
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 6192c8b..1dabdf4 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -336,13 +336,13 @@
 static void dock_event(struct dock_station *ds, u32 event, int num)
 {
 	struct device *dev = &dock_device->dev;
-	char event_string[7];
+	char event_string[13];
 	char *envp[] = { event_string, NULL };
 
 	if (num == UNDOCK_EVENT)
-		sprintf(event_string, "UNDOCK");
+		sprintf(event_string, "EVENT=undock");
 	else
-		sprintf(event_string, "DOCK");
+		sprintf(event_string, "EVENT=dock");
 
 	/*
 	 * Indicate that the status of the dock station has
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 469f3f5..2300d81 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -471,7 +471,6 @@
 		}
 	}
 	mutex_unlock(&ec->lock);
-	printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value);
 }
 
 static u32 acpi_ec_gpe_handler(void *data)
@@ -653,42 +652,39 @@
 }
 
 static acpi_status
-acpi_ec_register_query_methods(acpi_handle handle, u32 level,
-			       void *context, void **return_value)
+ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
 {
-	struct acpi_namespace_node *node = handle;
-	struct acpi_ec *ec = context;
-	int value = 0;
-	if (sscanf(node->name.ascii, "_Q%x", &value) == 1) {
-		acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
-	}
-	return AE_OK;
-}
+	acpi_status status;
 
-static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle)
-{
-	if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS,
-				     ec_parse_io_ports, ec)))
-		return -EINVAL;
+	struct acpi_ec *ec = context;
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS,
+				     ec_parse_io_ports, ec);
+	if (ACPI_FAILURE(status))
+		return status;
 
 	/* Get GPE bit assignment (EC events). */
 	/* TODO: Add support for _GPE returning a package */
-	if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe)))
-		return -EINVAL;
+	status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
+	if (ACPI_FAILURE(status))
+		return status;
 
 	/* Use the global lock for all EC transactions? */
 	acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
 
-	/* Find and register all query methods */
-	acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
-			    acpi_ec_register_query_methods, ec, NULL);
-
 	ec->handle = handle;
 
-	printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx",
+	printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
 			  ec->gpe, ec->command_addr, ec->data_addr);
 
-	return 0;
+	return AE_CTRL_TERMINATE;
+}
+
+static void ec_remove_handlers(struct acpi_ec *ec)
+{
+	acpi_remove_address_space_handler(ec->handle,
+					  ACPI_ADR_SPACE_EC,
+					  &acpi_ec_space_handler);
+	acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
 }
 
 static int acpi_ec_add(struct acpi_device *device)
@@ -705,7 +701,8 @@
 	if (!ec)
 		return -ENOMEM;
 
-	if (ec_parse_device(ec, device->handle)) {
+	if (ec_parse_device(device->handle, 0, ec, NULL) !=
+	    AE_CTRL_TERMINATE) {
 		kfree(ec);
 		return -EINVAL;
 	}
@@ -713,16 +710,13 @@
 	/* Check if we found the boot EC */
 	if (boot_ec) {
 		if (boot_ec->gpe == ec->gpe) {
-			/* We might have incorrect info for GL at boot time */
-			mutex_lock(&boot_ec->lock);
-			boot_ec->global_lock = ec->global_lock;
-			/* Copy handlers from new ec into boot ec */
-			list_splice(&ec->list, &boot_ec->list);
-			mutex_unlock(&boot_ec->lock);
-			kfree(ec);
-			ec = boot_ec;
+			ec_remove_handlers(boot_ec);
+			mutex_destroy(&boot_ec->lock);
+			kfree(boot_ec);
+			first_ec = boot_ec = NULL;
 		}
-	} else
+	}
+	if (!first_ec)
 		first_ec = ec;
 	ec->handle = device->handle;
 	acpi_driver_data(device) = ec;
@@ -734,14 +728,14 @@
 static int acpi_ec_remove(struct acpi_device *device, int type)
 {
 	struct acpi_ec *ec;
-	struct acpi_ec_query_handler *handler;
+	struct acpi_ec_query_handler *handler, *tmp;
 
 	if (!device)
 		return -EINVAL;
 
 	ec = acpi_driver_data(device);
 	mutex_lock(&ec->lock);
-	list_for_each_entry(handler, &ec->list, node) {
+	list_for_each_entry_safe(handler, tmp, &ec->list, node) {
 		list_del(&handler->node);
 		kfree(handler);
 	}
@@ -751,9 +745,6 @@
 	if (ec == first_ec)
 		first_ec = NULL;
 
-	/* Don't touch boot EC */
-	if (boot_ec != ec)
-		kfree(ec);
 	return 0;
 }
 
@@ -817,9 +808,7 @@
 	if (!ec)
 		return -EINVAL;
 
-	/* Boot EC is already working */
-	if (ec != boot_ec)
-		ret = ec_install_handlers(ec);
+	ret = ec_install_handlers(ec);
 
 	/* EC is fully operational, allow queries */
 	atomic_set(&ec->query_pending, 0);
@@ -829,7 +818,6 @@
 
 static int acpi_ec_stop(struct acpi_device *device, int type)
 {
-	acpi_status status;
 	struct acpi_ec *ec;
 
 	if (!device)
@@ -838,21 +826,7 @@
 	ec = acpi_driver_data(device);
 	if (!ec)
 		return -EINVAL;
-
-	/* Don't touch boot EC */
-	if (ec == boot_ec)
-		return 0;
-
-	status = acpi_remove_address_space_handler(ec->handle,
-						   ACPI_ADR_SPACE_EC,
-						   &acpi_ec_space_handler);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
-	status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
+	ec_remove_handlers(ec);
 	return 0;
 }
 
@@ -868,18 +842,21 @@
 	/*
 	 * Generate a boot ec context
 	 */
-
 	status = acpi_get_table(ACPI_SIG_ECDT, 1,
 				(struct acpi_table_header **)&ecdt_ptr);
-	if (ACPI_FAILURE(status))
-		goto error;
-
-	printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
-
-	boot_ec->command_addr = ecdt_ptr->control.address;
-	boot_ec->data_addr = ecdt_ptr->data.address;
-	boot_ec->gpe = ecdt_ptr->gpe;
-	boot_ec->handle = ACPI_ROOT_OBJECT;
+	if (ACPI_SUCCESS(status)) {
+		printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n\n");
+		boot_ec->command_addr = ecdt_ptr->control.address;
+		boot_ec->data_addr = ecdt_ptr->data.address;
+		boot_ec->gpe = ecdt_ptr->gpe;
+		boot_ec->handle = ACPI_ROOT_OBJECT;
+	} else {
+		printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
+		status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
+						boot_ec, NULL);
+		if (ACPI_FAILURE(status))
+			goto error;
+	}
 
 	ret = ec_install_handlers(boot_ec);
 	if (!ret) {
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index dfa5853..95637a4 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -108,7 +108,7 @@
 };
 
 #ifdef CONFIG_NET
-unsigned int acpi_event_seqnum;
+static unsigned int acpi_event_seqnum;
 struct acpi_genl_event {
 	acpi_device_class device_class;
 	char bus_id[15];
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index a898991..a8634a0 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -969,11 +969,17 @@
 	}
 
 	if (pr->flags.bm_check) {
-		/* bus mastering control is necessary */
 		if (!pr->flags.bm_control) {
-			/* In this case we enter C3 without bus mastering */
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				"C3 support without bus mastering control\n"));
+			if (pr->flags.has_cst != 1) {
+				/* bus mastering control is necessary */
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"C3 support requires BM control\n"));
+				return;
+			} else {
+				/* Here we enter C3 without bus mastering */
+				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					"C3 support without BM control\n"));
+			}
 		}
 	} else {
 		/*
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index c4efc0c..463b024 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -539,7 +539,7 @@
 }
 
 int acpi_processor_preregister_performance(
-		struct acpi_processor_performance **performance)
+		struct acpi_processor_performance *performance)
 {
 	int count, count_target;
 	int retval = 0;
@@ -567,12 +567,12 @@
 			continue;
 		}
 
-		if (!performance || !performance[i]) {
+		if (!performance || !percpu_ptr(performance, i)) {
 			retval = -EINVAL;
 			continue;
 		}
 
-		pr->performance = performance[i];
+		pr->performance = percpu_ptr(performance, i);
 		cpu_set(i, pr->performance->shared_cpu_map);
 		if (acpi_processor_get_psd(pr)) {
 			retval = -EINVAL;
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 7d8e78e..82c3a55 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -1415,7 +1415,7 @@
 	char dir_name[32];
 	int do_battery_init = 0, do_ac_init = 0;
 	int old_remaining_capacity = 0;
-	int update_ac = 1, update_battery = 1;
+	int update_battery = 1;
 	int up_tm = update_time;
 
 	if (sbs_zombie(sbs)) {
@@ -1435,10 +1435,6 @@
 
 	sbs->run_cnt++;
 
-	if (!update_ac && !update_battery) {
-		goto end;
-	}
-
 	old_ac_present = sbs->ac.ac_present;
 
 	result = acpi_ac_get_present(sbs);
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 5b302c4..a9e3331 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -52,6 +52,8 @@
 /* Local prototypes */
 static acpi_status acpi_tb_load_namespace(void);
 
+static int no_auto_ssdt;
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_allocate_root_table
@@ -536,6 +538,10 @@
 
 		ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
 		acpi_tb_print_table_header(0, table);
+
+		if (no_auto_ssdt == 0) {
+			printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"");
+		}
 	}
 
 	status =
@@ -577,6 +583,11 @@
 			continue;
 		}
 
+		if (no_auto_ssdt) {
+			printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n");
+			continue;
+		}
+
 		/* Ignore errors while loading tables, get as many as possible */
 
 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
@@ -622,3 +633,15 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_load_tables)
+
+
+static int __init acpi_no_auto_ssdt_setup(char *s) {
+
+        printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n");
+
+        no_auto_ssdt = 1;
+
+        return 1;
+}
+
+__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 5a62de1..1e06159 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -33,6 +33,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
@@ -74,10 +75,26 @@
 MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
 MODULE_LICENSE("GPL");
 
+static int act;
+module_param(act, int, 0644);
+MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.\n");
+
 static int tzp;
-module_param(tzp, int, 0);
+module_param(tzp, int, 0444);
 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
 
+static int nocrt;
+module_param(nocrt, int, 0);
+MODULE_PARM_DESC(nocrt, "Set to disable action on ACPI thermal zone critical and hot trips.\n");
+
+static int off;
+module_param(off, int, 0);
+MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.\n");
+
+static int psv;
+module_param(psv, int, 0644);
+MODULE_PARM_DESC(psv, "Disable or override all passive trip points.\n");
+
 static int acpi_thermal_add(struct acpi_device *device);
 static int acpi_thermal_remove(struct acpi_device *device, int type);
 static int acpi_thermal_resume(struct acpi_device *device);
@@ -339,9 +356,16 @@
 
 	/* Passive: Processors (optional) */
 
-	status =
-	    acpi_evaluate_integer(tz->device->handle, "_PSV", NULL,
-				  &tz->trips.passive.temperature);
+	if (psv == -1) {
+		status = AE_SUPPORT;
+	} else if (psv > 0) {
+		tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
+		status = AE_OK;
+	} else {
+		status = acpi_evaluate_integer(tz->device->handle,
+			"_PSV", NULL, &tz->trips.passive.temperature);
+	}
+
 	if (ACPI_FAILURE(status)) {
 		tz->trips.passive.flags.valid = 0;
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
@@ -386,11 +410,33 @@
 
 		char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
 
-		status =
-		    acpi_evaluate_integer(tz->device->handle, name, NULL,
-					  &tz->trips.active[i].temperature);
-		if (ACPI_FAILURE(status))
+		if (act == -1)
+			break;	/* disable all active trip points */
+
+		status = acpi_evaluate_integer(tz->device->handle,
+			name, NULL, &tz->trips.active[i].temperature);
+
+		if (ACPI_FAILURE(status)) {
+			if (i == 0)	/* no active trip points */
+				break;
+			if (act <= 0)	/* no override requested */
+				break;
+			if (i == 1) {	/* 1 trip point */
+				tz->trips.active[0].temperature =
+					CELSIUS_TO_KELVIN(act);
+			} else {	/* multiple trips */
+				/*
+				 * Don't allow override higher than
+				 * the next higher trip point
+				 */
+				tz->trips.active[i - 1].temperature =
+				    (tz->trips.active[i - 2].temperature <
+					CELSIUS_TO_KELVIN(act) ?
+					tz->trips.active[i - 2].temperature :
+					CELSIUS_TO_KELVIN(act));
+			}
 			break;
+		}
 
 		name[2] = 'L';
 		status =
@@ -427,7 +473,7 @@
 
 static int acpi_thermal_critical(struct acpi_thermal *tz)
 {
-	if (!tz || !tz->trips.critical.flags.valid)
+	if (!tz || !tz->trips.critical.flags.valid || nocrt)
 		return -EINVAL;
 
 	if (tz->temperature >= tz->trips.critical.temperature) {
@@ -449,7 +495,7 @@
 
 static int acpi_thermal_hot(struct acpi_thermal *tz)
 {
-	if (!tz || !tz->trips.hot.flags.valid)
+	if (!tz || !tz->trips.hot.flags.valid || nocrt)
 		return -EINVAL;
 
 	if (tz->temperature >= tz->trips.hot.temperature) {
@@ -824,12 +870,14 @@
 		goto end;
 
 	if (tz->trips.critical.flags.valid)
-		seq_printf(seq, "critical (S5):           %ld C\n",
-			   KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
+		seq_printf(seq, "critical (S5):           %ld C%s",
+			   KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
+			   nocrt ? " <disabled>\n" : "\n");
 
 	if (tz->trips.hot.flags.valid)
-		seq_printf(seq, "hot (S4):                %ld C\n",
-			   KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
+		seq_printf(seq, "hot (S4):                %ld C%s",
+			   KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
+			   nocrt ? " <disabled>\n" : "\n");
 
 	if (tz->trips.passive.flags.valid) {
 		seq_printf(seq,
@@ -1281,11 +1329,78 @@
 	return AE_OK;
 }
 
+#ifdef CONFIG_DMI
+static int thermal_act(struct dmi_system_id *d) {
+
+	if (act == 0) {
+		printk(KERN_NOTICE "ACPI: %s detected: "
+			"disabling all active thermal trip points\n", d->ident);
+		act = -1;
+	}
+	return 0;
+}
+static int thermal_tzp(struct dmi_system_id *d) {
+
+	if (tzp == 0) {
+		printk(KERN_NOTICE "ACPI: %s detected: "
+			"enabling thermal zone polling\n", d->ident);
+		tzp = 300;	/* 300 dS = 30 Seconds */
+	}
+	return 0;
+}
+static int thermal_psv(struct dmi_system_id *d) {
+
+	if (psv == 0) {
+		printk(KERN_NOTICE "ACPI: %s detected: "
+			"disabling all passive thermal trip points\n", d->ident);
+		psv = -1;
+	}
+	return 0;
+}
+
+static struct dmi_system_id thermal_dmi_table[] __initdata = {
+	/*
+	 * Award BIOS on this AOpen makes thermal control almost worthless.
+	 * http://bugzilla.kernel.org/show_bug.cgi?id=8842
+	 */
+	{
+	 .callback = thermal_act,
+	 .ident = "AOpen i915GMm-HFS",
+	 .matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+		DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+		},
+	},
+	{
+	 .callback = thermal_psv,
+	 .ident = "AOpen i915GMm-HFS",
+	 .matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+		DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+		},
+	},
+	{
+	 .callback = thermal_tzp,
+	 .ident = "AOpen i915GMm-HFS",
+	 .matches = {
+		DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+		DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+		},
+	},
+	{}
+};
+#endif /* CONFIG_DMI */
+
 static int __init acpi_thermal_init(void)
 {
 	int result = 0;
 
+	dmi_check_system(thermal_dmi_table);
 
+	if (off) {
+		printk(KERN_NOTICE "ACPI: thermal control disabled\n");
+		return -ENODEV;
+	}
 	acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
 	if (!acpi_thermal_dir)
 		return -ENODEV;
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 73037a4..aeec67e 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1147,10 +1147,15 @@
 	return 0;
 }
 
+const static struct acpi_device_id sonypi_device_ids[] = {
+	{"SNY6001", 0},
+	{"", 0},
+};
+
 static struct acpi_driver sonypi_acpi_driver = {
 	.name           = "sonypi",
 	.class          = "hkey",
-	.ids            = "SNY6001",
+	.ids            = sonypi_device_ids,
 	.ops            = {
 		           .add = sonypi_acpi_add,
 			   .remove = sonypi_acpi_remove,
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index aaaa61e..518d5d3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -200,14 +200,22 @@
 config THINKPAD_ACPI_INPUT_ENABLED
 	bool "Enable input layer support by default"
 	depends on THINKPAD_ACPI
-	default y
+	default n
 	---help---
-	  Enables hot key handling over the input layer by default.  If unset,
-	  the driver does not enable any hot key handling by default, and also
-	  starts up with a mostly empty keymap.
+	  This option enables thinkpad-acpi hot key handling over the input
+	  layer at driver load time.  When it is unset, the driver does not
+	  enable hot key handling by default, and also starts up with a mostly
+	  empty keymap.
 
-	  If you are not sure, say Y here.  Say N to retain the deprecated
-	  behavior of ibm-acpi, and thinkpad-acpi for kernels up to 2.6.21.
+	  This option should be enabled if you have a new enough HAL or other
+	  userspace support that properly handles the thinkpad-acpi event
+	  device.  It auto-tunes the hot key support to those reported by the
+	  firmware and enables it automatically.
+
+	  If unsure, say N here to retain the old behaviour of ibm-acpi, and
+	  thinkpad-acpi up to kernel 2.6.21: userspace will have to enable and
+	  set up the thinkpad-acpi hot key handling using the sysfs interace
+	  after loading the driver.
 
 
 endif # MISC_DEVICES
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 14ee06c..91da688 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -845,7 +845,7 @@
 };
 
 /* SNC-only model map */
-struct dmi_system_id sony_nc_ids[] = {
+static struct dmi_system_id sony_nc_ids[] = {
 		{
 			.ident = "Sony Vaio FE Series",
 			.callback = sony_nc_C_enable,
@@ -942,6 +942,11 @@
 		}
 	}
 
+	/* set the last requested brightness level */
+	if (sony_backlight_device &&
+			!sony_backlight_update_status(sony_backlight_device))
+		printk(KERN_WARNING DRV_PFX "unable to restore brightness level");
+
 	/* re-initialize models with specific requirements */
 	dmi_check_system(sony_nc_ids);
 
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index fa80f35..f6cd34a 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -4668,12 +4668,15 @@
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
+	tp_features.platform_drv_registered = 1;
+
 	ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
 	if (ret) {
 		printk(IBM_ERR "unable to create sysfs driver attributes\n");
 		thinkpad_acpi_module_exit();
 		return ret;
 	}
+	tp_features.platform_drv_attrs_registered = 1;
 
 
 	/* Device initialization */
@@ -4756,8 +4759,11 @@
 	if (tpacpi_pdev)
 		platform_device_unregister(tpacpi_pdev);
 
-	tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
-	platform_driver_unregister(&tpacpi_pdriver);
+	if (tp_features.platform_drv_attrs_registered)
+		tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
+
+	if (tp_features.platform_drv_registered)
+		platform_driver_unregister(&tpacpi_pdriver);
 
 	if (proc_dir)
 		remove_proc_entry(IBM_PROC_DIR, acpi_root_dir);
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 88af089..eee8809 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -246,6 +246,8 @@
 	u16 wan:1;
 	u16 fan_ctrl_status_undef:1;
 	u16 input_device_registered:1;
+	u16 platform_drv_registered:1;
+	u16 platform_drv_attrs_registered:1;
 } tp_features;
 
 struct thinkpad_id_data {
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index f9f987f..ec3ffda 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -232,7 +232,7 @@
 
 extern int acpi_processor_preregister_performance(struct
 						  acpi_processor_performance
-						  **performance);
+						  *performance);
 
 extern int acpi_processor_register_performance(struct acpi_processor_performance
 					       *performance, unsigned int cpu);