Prechádzať zdrojové kódy

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: (23 commits)
  ACPICA: fix stray va_end() caused by mis-merge
  ACPI: Reject below-freezing temperatures as invalid critical temperatures
  ACPICA: Fix for access to deleted object <regression>
  ACPICA: Fix to make _SST method optional
  ACPICA: Fix for Load operator, load table at the namespace root
  ACPICA: Ignore ACPI table signature for Load() operator
  ACPICA: Fix to allow zero-length ASL field declarations
  ACPI: use memory_read_from_buffer()
  bay: exit if notify handler cannot be installed
  dock.c remove trailing printk whitespace
  proper prototype for acpi_processor_tstate_has_changed()
  ACPI: handle invalid ACPI SLIT table
  PNPACPI: use _CRS IRQ descriptor length for _SRS
  pnpacpi: fix shareable IRQ encode/decode
  pnpacpi: fix IRQ flag decoding
  MAINTAINERS: update ACPI homepage
  ACPI 2.6.26-rc2: Add missing newline to DSDT/SSDT warning message
  ACPI: EC: Use msleep instead of udelay while waiting for event.
  thinkpad-acpi: fix LED handling on older ThinkPads
  thinkpad-acpi: fix initialization error paths
  ...
Linus Torvalds 17 rokov pred
rodič
commit
da50ccc6a0

+ 1 - 1
Documentation/laptops/thinkpad-acpi.txt

@@ -503,7 +503,7 @@ generate input device EV_KEY events.
 In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW
 events for switches:
 
-SW_RADIO	T60 and later hardare rfkill rocker switch
+SW_RFKILL_ALL	T60 and later hardare rfkill rocker switch
 SW_TABLET_MODE	Tablet ThinkPads HKEY events 0x5009 and 0x500A
 
 Non hot-key ACPI HKEY event map:

+ 5 - 5
MAINTAINERS

@@ -228,21 +228,21 @@ ACPI BATTERY DRIVERS
 P:	Alexey Starikovskiy
 M:	astarikovskiy@suse.de
 L:	linux-acpi@vger.kernel.org
-W:	http://acpi.sourceforge.net/
+W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 
 ACPI EC DRIVER
 P:	Alexey Starikovskiy
 M:	astarikovskiy@suse.de
 L:	linux-acpi@vger.kernel.org
-W:	http://acpi.sourceforge.net/
+W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 
 ACPI FAN DRIVER
 P:	Len Brown
 M:	len.brown@intel.com
 L:	linux-acpi@vger.kernel.org
-W:	http://acpi.sourceforge.net/
+W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 
 ACPI PCI HOTPLUG DRIVER
@@ -255,14 +255,14 @@ ACPI THERMAL DRIVER
 P:	Len Brown
 M:	len.brown@intel.com
 L:	linux-acpi@vger.kernel.org
-W:	http://acpi.sourceforge.net/
+W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 
 ACPI VIDEO DRIVER
 P:	Rui Zhang
 M:	rui.zhang@intel.com
 L:	linux-acpi@vger.kernel.org
-W:	http://acpi.sourceforge.net/
+W:	http://www.lesswatts.org/projects/acpi/
 S:	Supported
 
 ACPI WMI DRIVER

+ 7 - 2
arch/ia64/kernel/acpi.c

@@ -465,7 +465,6 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 		printk(KERN_ERR
 		       "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
 		       len, slit->header.length);
-		memset(numa_slit, 10, sizeof(numa_slit));
 		return;
 	}
 	slit_table = slit;
@@ -574,8 +573,14 @@ void __init acpi_numa_arch_fixup(void)
 	printk(KERN_INFO "Number of memory chunks in system = %d\n",
 	       num_node_memblks);
 
-	if (!slit_table)
+	if (!slit_table) {
+		for (i = 0; i < MAX_NUMNODES; i++)
+			for (j = 0; j < MAX_NUMNODES; j++)
+				node_distance(i, j) = i == j ? LOCAL_DISTANCE :
+							REMOTE_DISTANCE;
 		return;
+	}
+
 	memset(numa_slit, -1, sizeof(numa_slit));
 	for (i = 0; i < slit_table->locality_count; i++) {
 		if (!pxm_bit_test(i))

+ 0 - 27
arch/x86/mm/srat_64.c

@@ -97,36 +97,9 @@ static __init inline int srat_disabled(void)
 	return numa_off || acpi_numa < 0;
 }
 
-/*
- * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
- * up the NUMA heuristics which wants the local node to have a smaller
- * distance than the others.
- * Do some quick checks here and only use the SLIT if it passes.
- */
-static __init int slit_valid(struct acpi_table_slit *slit)
-{
-	int i, j;
-	int d = slit->locality_count;
-	for (i = 0; i < d; i++) {
-		for (j = 0; j < d; j++)  {
-			u8 val = slit->entry[d*i + j];
-			if (i == j) {
-				if (val != LOCAL_DISTANCE)
-					return 0;
-			} else if (val <= LOCAL_DISTANCE)
-				return 0;
-		}
-	}
-	return 1;
-}
-
 /* Callback for SLIT parsing */
 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 {
-	if (!slit_valid(slit)) {
-		printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
-		return;
-	}
 	acpi_slit = slit;
 }
 

+ 10 - 6
drivers/acpi/bay.c

@@ -301,16 +301,20 @@ static int bay_add(acpi_handle handle, int id)
 	 */
 	pdev->dev.uevent_suppress = 0;
 
-	if (acpi_bay_add_fs(new_bay)) {
-		platform_device_unregister(new_bay->pdev);
-		goto bay_add_err;
-	}
-
 	/* register for events on this device */
 	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
 			bay_notify, new_bay);
 	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PREFIX "Error installing bay notify handler\n");
+		printk(KERN_INFO PREFIX "Error installing bay notify handler\n");
+		platform_device_unregister(new_bay->pdev);
+		goto bay_add_err;
+	}
+
+	if (acpi_bay_add_fs(new_bay)) {
+		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					   bay_notify);
+		platform_device_unregister(new_bay->pdev);
+		goto bay_add_err;
 	}
 
 	/* if we are on a dock station, we should register for dock

+ 1 - 4
drivers/acpi/dispatcher/dsfield.c

@@ -450,10 +450,6 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	if (!arg) {
-		return_ACPI_STATUS(AE_AML_NO_OPERAND);
-	}
-
 	/* Creating new namespace node(s), should not already exist */
 
 	flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
@@ -467,6 +463,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
 
 	/*
 	 * Walk the list of entries in the field_list
+	 * Note: field_list can be of zero length. In this case, Arg will be NULL.
 	 */
 	while (arg) {
 		/*

+ 1 - 1
drivers/acpi/dock.c

@@ -834,7 +834,7 @@ static int dock_add(acpi_handle handle)
 		goto dock_add_err;
 	}
 
-	printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION);
+	printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION);
 
 	return 0;
 

+ 1 - 1
drivers/acpi/ec.c

@@ -194,7 +194,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
 		while (time_before(jiffies, delay)) {
 			if (acpi_ec_check_status(ec, event))
 				return 0;
-			udelay(ACPI_EC_UDELAY);
+			msleep(1);
 		}
 	}
 	pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n",

+ 8 - 2
drivers/acpi/executer/exconfig.c

@@ -375,9 +375,15 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
 		goto cleanup;
 	}
 
+	/*
+	 * Add the table to the namespace.
+	 *
+	 * Note: We load the table objects relative to the root of the namespace.
+	 * This appears to go against the ACPI specification, but we do it for
+	 * compatibility with other ACPI implementations.
+	 */
 	status =
-	    acpi_ex_add_table(table_index, walk_state->scope_info->scope.node,
-			      &ddb_handle);
+	    acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
 	if (ACPI_FAILURE(status)) {
 
 		/* On error, table_ptr was deallocated above */

+ 6 - 0
drivers/acpi/glue.c

@@ -272,6 +272,12 @@ static u32 rtc_handler(void *context)
 static inline void rtc_wake_setup(void)
 {
 	acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+	/*
+	 * After the RTC handler is installed, the Fixed_RTC event should
+	 * be disabled. Only when the RTC alarm is set will it be enabled.
+	 */
+	acpi_clear_event(ACPI_EVENT_RTC);
+	acpi_disable_event(ACPI_EVENT_RTC, 0);
 }
 
 static void rtc_wake_on(struct device *dev)

+ 5 - 3
drivers/acpi/hardware/hwsleep.c

@@ -223,15 +223,17 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
 		break;
 	}
 
-	/* Set the system indicators to show the desired sleep state. */
-
+	/*
+	 * Set the system indicators to show the desired sleep state.
+	 * _SST is an optional method (return no error if not found)
+	 */
 	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
 		ACPI_EXCEPTION((AE_INFO, status,
 				"While executing method _SST"));
 	}
 
-	return_ACPI_STATUS(status);
+	return_ACPI_STATUS(AE_OK);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)

+ 27 - 4
drivers/acpi/numa.c

@@ -140,19 +140,42 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 	}
 }
 
+/*
+ * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
+ * up the NUMA heuristics which wants the local node to have a smaller
+ * distance than the others.
+ * Do some quick checks here and only use the SLIT if it passes.
+ */
+static __init int slit_valid(struct acpi_table_slit *slit)
+{
+	int i, j;
+	int d = slit->locality_count;
+	for (i = 0; i < d; i++) {
+		for (j = 0; j < d; j++)  {
+			u8 val = slit->entry[d*i + j];
+			if (i == j) {
+				if (val != LOCAL_DISTANCE)
+					return 0;
+			} else if (val <= LOCAL_DISTANCE)
+				return 0;
+		}
+	}
+	return 1;
+}
+
 static int __init acpi_parse_slit(struct acpi_table_header *table)
 {
 	struct acpi_table_slit *slit;
-	u32 localities;
 
 	if (!table)
 		return -EINVAL;
 
 	slit = (struct acpi_table_slit *)table;
 
-	/* downcast just for %llu vs %lu for i386/ia64  */
-	localities = (u32) slit->locality_count;
-
+	if (!slit_valid(slit)) {
+		printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
+		return -EINVAL;
+	}
 	acpi_numa_slit_init(slit);
 
 	return 0;

+ 2 - 2
drivers/acpi/parser/psargs.c

@@ -268,7 +268,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
 	 */
 	if (ACPI_SUCCESS(status) &&
 	    possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
-		if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
+		if (walk_state->opcode == AML_UNLOAD_OP) {
 			/*
 			 * acpi_ps_get_next_namestring has increased the AML pointer,
 			 * so we need to restore the saved AML pointer for method call.
@@ -691,7 +691,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
 
 			/* To support super_name arg of Unload */
 
-			if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) {
+			if (walk_state->opcode == AML_UNLOAD_OP) {
 				status =
 				    acpi_ps_get_next_namepath(walk_state,
 							      parser_state, arg,

+ 0 - 1
drivers/acpi/processor_core.c

@@ -86,7 +86,6 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file);
 static void acpi_processor_notify(acpi_handle handle, u32 event, void *data);
 static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu);
 static int acpi_processor_handle_eject(struct acpi_processor *pr);
-extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
 
 
 static const struct acpi_device_id processor_device_ids[] = {

+ 7 - 6
drivers/acpi/processor_idle.c

@@ -1669,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
 		return -EINVAL;
 	}
 
+	dev->cpu = pr->id;
 	for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
 		dev->states[i].name[0] = '\0';
 		dev->states[i].desc[0] = '\0';
@@ -1738,7 +1739,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
 
 int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 {
-	int ret;
+	int ret = 0;
 
 	if (boot_option_idle_override)
 		return 0;
@@ -1756,8 +1757,10 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 	cpuidle_pause_and_lock();
 	cpuidle_disable_device(&pr->power.dev);
 	acpi_processor_get_power_info(pr);
-	acpi_processor_setup_cpuidle(pr);
-	ret = cpuidle_enable_device(&pr->power.dev);
+	if (pr->flags.power) {
+		acpi_processor_setup_cpuidle(pr);
+		ret = cpuidle_enable_device(&pr->power.dev);
+	}
 	cpuidle_resume_and_unlock();
 
 	return ret;
@@ -1813,7 +1816,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 	if (pr->flags.power) {
 #ifdef CONFIG_CPU_IDLE
 		acpi_processor_setup_cpuidle(pr);
-		pr->power.dev.cpu = pr->id;
 		if (cpuidle_register_device(&pr->power.dev))
 			return -EIO;
 #endif
@@ -1850,8 +1852,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
 		return 0;
 
 #ifdef CONFIG_CPU_IDLE
-	if (pr->flags.power)
-		cpuidle_unregister_device(&pr->power.dev);
+	cpuidle_unregister_device(&pr->power.dev);
 #endif
 	pr->flags.power_setup_done = 0;
 

+ 6 - 0
drivers/acpi/sleep/proc.c

@@ -495,6 +495,12 @@ static int __init acpi_sleep_proc_init(void)
 		    acpi_root_dir, &acpi_system_alarm_fops);
 
 	acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
+	/*
+	 * Disable the RTC event after installing RTC handler.
+	 * Only when RTC alarm is set will it be enabled.
+	 */
+	acpi_clear_event(ACPI_EVENT_RTC);
+	acpi_disable_event(ACPI_EVENT_RTC, 0);
 #endif				/* HAVE_ACPI_LEGACY_ALARM */
 
 	/* 'wakeup device' [R/W] */

+ 2 - 13
drivers/acpi/system.c

@@ -77,7 +77,6 @@ static ssize_t acpi_table_show(struct kobject *kobj,
 	    container_of(bin_attr, struct acpi_table_attr, attr);
 	struct acpi_table_header *table_header = NULL;
 	acpi_status status;
-	ssize_t ret_count = count;
 
 	status =
 	    acpi_get_table(table_attr->name, table_attr->instance,
@@ -85,18 +84,8 @@ static ssize_t acpi_table_show(struct kobject *kobj,
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	if (offset >= table_header->length) {
-		ret_count = 0;
-		goto end;
-	}
-
-	if (offset + ret_count > table_header->length)
-		ret_count = table_header->length - offset;
-
-	memcpy(buf, ((char *)table_header) + offset, ret_count);
-
-      end:
-	return ret_count;
+	return memory_read_from_buffer(buf, count, &offset,
+					table_header, table_header->length);
 }
 
 static void acpi_table_attr_init(struct acpi_table_attr *table_attr,

+ 7 - 18
drivers/acpi/tables/tbinstal.c

@@ -123,24 +123,13 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc,
 		}
 	}
 
-	/* The table must be either an SSDT or a PSDT or an OEMx */
-
-	if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&&
-	    !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&&
-	    strncmp(table_desc->pointer->signature, "OEM", 3)) {
-		/* Check for a printable name */
-		if (acpi_ut_valid_acpi_name(
-			*(u32 *) table_desc->pointer->signature)) {
-			ACPI_ERROR((AE_INFO, "Table has invalid signature "
-					"[%4.4s], must be SSDT or PSDT",
-				    table_desc->pointer->signature));
-		} else {
-			ACPI_ERROR((AE_INFO, "Table has invalid signature "
-					"(0x%8.8X), must be SSDT or PSDT",
-				    *(u32 *) table_desc->pointer->signature));
-		}
-		return_ACPI_STATUS(AE_BAD_SIGNATURE);
-	}
+	/*
+	 * Originally, we checked the table signature for "SSDT" or "PSDT" here.
+	 * Next, we added support for OEMx tables, signature "OEM".
+	 * Valid tables were encountered with a null signature, so we've just
+	 * given up on validating the signature, since it seems to be a waste
+	 * of code. The original code was removed (05/2008).
+	 */
 
 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 

+ 1 - 1
drivers/acpi/tables/tbxface.c

@@ -540,7 +540,7 @@ static acpi_status acpi_tb_load_namespace(void)
 		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\"");
+			printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n");
 		}
 	}
 

+ 9 - 2
drivers/acpi/thermal.c

@@ -364,10 +364,17 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 	if (flag & ACPI_TRIPS_CRITICAL) {
 		status = acpi_evaluate_integer(tz->device->handle,
 				"_CRT", NULL, &tz->trips.critical.temperature);
-		if (ACPI_FAILURE(status)) {
+		/*
+		 * Treat freezing temperatures as invalid as well; some
+		 * BIOSes return really low values and cause reboots at startup.
+		 * Below zero (Celcius) values clearly aren't right for sure..
+		 * ... so lets discard those as invalid.
+		 */
+		if (ACPI_FAILURE(status) ||
+				tz->trips.critical.temperature <= 2732) {
 			tz->trips.critical.flags.valid = 0;
 			ACPI_EXCEPTION((AE_INFO, status,
-					"No critical threshold"));
+					"No or invalid critical threshold"));
 			return -ENODEV;
 		} else {
 			tz->trips.critical.flags.valid = 1;

+ 1 - 1
drivers/acpi/utilities/utmisc.c

@@ -1048,6 +1048,7 @@ acpi_ut_exception(char *module_name,
 	va_start(args, format);
 	acpi_os_vprintf(format, args);
 	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
+	va_end(args);
 }
 
 EXPORT_SYMBOL(acpi_ut_exception);
@@ -1063,7 +1064,6 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...)
 	acpi_os_vprintf(format, args);
 	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
 	va_end(args);
-	va_end(args);
 }
 
 void ACPI_INTERNAL_VAR_XFACE

+ 35 - 5
drivers/cpuidle/cpuidle.c

@@ -38,6 +38,8 @@ static void cpuidle_kick_cpus(void)
 static void cpuidle_kick_cpus(void) {}
 #endif
 
+static int __cpuidle_register_device(struct cpuidle_device *dev);
+
 /**
  * cpuidle_idle_call - the main idle loop
  *
@@ -138,6 +140,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
 	if (!dev->state_count)
 		return -EINVAL;
 
+	if (dev->registered == 0) {
+		ret = __cpuidle_register_device(dev);
+		if (ret)
+			return ret;
+	}
+
 	if ((ret = cpuidle_add_state_sysfs(dev)))
 		return ret;
 
@@ -232,10 +240,13 @@ static void poll_idle_init(struct cpuidle_device *dev) {}
 #endif /* CONFIG_ARCH_HAS_CPU_RELAX */
 
 /**
- * cpuidle_register_device - registers a CPU's idle PM feature
+ * __cpuidle_register_device - internal register function called before register
+ * and enable routines
  * @dev: the cpu
+ *
+ * cpuidle_lock mutex must be held before this is called
  */
-int cpuidle_register_device(struct cpuidle_device *dev)
+static int __cpuidle_register_device(struct cpuidle_device *dev)
 {
 	int ret;
 	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
@@ -247,18 +258,34 @@ int cpuidle_register_device(struct cpuidle_device *dev)
 
 	init_completion(&dev->kobj_unregister);
 
-	mutex_lock(&cpuidle_lock);
-
 	poll_idle_init(dev);
 
 	per_cpu(cpuidle_devices, dev->cpu) = dev;
 	list_add(&dev->device_list, &cpuidle_detected_devices);
 	if ((ret = cpuidle_add_sysfs(sys_dev))) {
-		mutex_unlock(&cpuidle_lock);
 		module_put(cpuidle_curr_driver->owner);
 		return ret;
 	}
 
+	dev->registered = 1;
+	return 0;
+}
+
+/**
+ * cpuidle_register_device - registers a CPU's idle PM feature
+ * @dev: the cpu
+ */
+int cpuidle_register_device(struct cpuidle_device *dev)
+{
+	int ret;
+
+	mutex_lock(&cpuidle_lock);
+
+	if ((ret = __cpuidle_register_device(dev))) {
+		mutex_unlock(&cpuidle_lock);
+		return ret;
+	}
+
 	cpuidle_enable_device(dev);
 	cpuidle_install_idle_handler();
 
@@ -278,6 +305,9 @@ void cpuidle_unregister_device(struct cpuidle_device *dev)
 {
 	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
 
+	if (dev->registered == 0)
+		return;
+
 	cpuidle_pause_and_lock();
 
 	cpuidle_disable_device(dev);

+ 259 - 235
drivers/misc/thinkpad_acpi.c

@@ -1293,7 +1293,7 @@ static void tpacpi_input_send_radiosw(void)
 		mutex_lock(&tpacpi_inputdev_send_mutex);
 
 		input_report_switch(tpacpi_inputdev,
-				    SW_RADIO, !!wlsw);
+				    SW_RFKILL_ALL, !!wlsw);
 		input_sync(tpacpi_inputdev);
 
 		mutex_unlock(&tpacpi_inputdev_send_mutex);
@@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
 	&dev_attr_hotkey_wakeup_hotunplug_complete.attr,
 };
 
+static void hotkey_exit(void)
+{
+#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
+	hotkey_poll_stop_sync();
+#endif
+
+	if (hotkey_dev_attributes)
+		delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
+
+	kfree(hotkey_keycode_map);
+
+	if (tp_features.hotkey) {
+		dbg_printk(TPACPI_DBG_EXIT,
+			   "restoring original hot key mask\n");
+		/* no short-circuit boolean operator below! */
+		if ((hotkey_mask_set(hotkey_orig_mask) |
+		     hotkey_status_set(hotkey_orig_status)) != 0)
+			printk(TPACPI_ERR
+			       "failed to restore hot key mask "
+			       "to BIOS defaults\n");
+	}
+}
+
 static int __init hotkey_init(struct ibm_init_struct *iibm)
 {
 	/* Requirements for changing the default keymaps:
@@ -2060,226 +2083,220 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 	vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n",
 		str_supported(tp_features.hotkey));
 
-	if (tp_features.hotkey) {
-		hotkey_dev_attributes = create_attr_set(13, NULL);
-		if (!hotkey_dev_attributes)
-			return -ENOMEM;
-		res = add_many_to_attr_set(hotkey_dev_attributes,
-				hotkey_attributes,
-				ARRAY_SIZE(hotkey_attributes));
-		if (res)
-			return res;
+	if (!tp_features.hotkey)
+		return 1;
 
-		/* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
-		   A30, R30, R31, T20-22, X20-21, X22-24.  Detected by checking
-		   for HKEY interface version 0x100 */
-		if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
-			if ((hkeyv >> 8) != 1) {
-				printk(TPACPI_ERR "unknown version of the "
-				       "HKEY interface: 0x%x\n", hkeyv);
-				printk(TPACPI_ERR "please report this to %s\n",
-				       TPACPI_MAIL);
-			} else {
-				/*
-				 * MHKV 0x100 in A31, R40, R40e,
-				 * T4x, X31, and later
-				 */
-				tp_features.hotkey_mask = 1;
-			}
+	hotkey_dev_attributes = create_attr_set(13, NULL);
+	if (!hotkey_dev_attributes)
+		return -ENOMEM;
+	res = add_many_to_attr_set(hotkey_dev_attributes,
+			hotkey_attributes,
+			ARRAY_SIZE(hotkey_attributes));
+	if (res)
+		goto err_exit;
+
+	/* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
+	   A30, R30, R31, T20-22, X20-21, X22-24.  Detected by checking
+	   for HKEY interface version 0x100 */
+	if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
+		if ((hkeyv >> 8) != 1) {
+			printk(TPACPI_ERR "unknown version of the "
+			       "HKEY interface: 0x%x\n", hkeyv);
+			printk(TPACPI_ERR "please report this to %s\n",
+			       TPACPI_MAIL);
+		} else {
+			/*
+			 * MHKV 0x100 in A31, R40, R40e,
+			 * T4x, X31, and later
+			 */
+			tp_features.hotkey_mask = 1;
 		}
+	}
 
-		vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
-			str_supported(tp_features.hotkey_mask));
+	vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
+		str_supported(tp_features.hotkey_mask));
 
-		if (tp_features.hotkey_mask) {
-			if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
-					"MHKA", "qd")) {
-				printk(TPACPI_ERR
-				       "missing MHKA handler, "
-				       "please report this to %s\n",
-				       TPACPI_MAIL);
-				/* FN+F12, FN+F4, FN+F3 */
-				hotkey_all_mask = 0x080cU;
-			}
+	if (tp_features.hotkey_mask) {
+		if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
+				"MHKA", "qd")) {
+			printk(TPACPI_ERR
+			       "missing MHKA handler, "
+			       "please report this to %s\n",
+			       TPACPI_MAIL);
+			/* FN+F12, FN+F4, FN+F3 */
+			hotkey_all_mask = 0x080cU;
 		}
+	}
 
-		/* hotkey_source_mask *must* be zero for
-		 * the first hotkey_mask_get */
-		res = hotkey_status_get(&hotkey_orig_status);
-		if (!res && tp_features.hotkey_mask) {
-			res = hotkey_mask_get();
-			hotkey_orig_mask = hotkey_mask;
-			if (!res) {
-				res = add_many_to_attr_set(
-					hotkey_dev_attributes,
-					hotkey_mask_attributes,
-					ARRAY_SIZE(hotkey_mask_attributes));
-			}
-		}
+	/* hotkey_source_mask *must* be zero for
+	 * the first hotkey_mask_get */
+	res = hotkey_status_get(&hotkey_orig_status);
+	if (res)
+		goto err_exit;
+
+	if (tp_features.hotkey_mask) {
+		res = hotkey_mask_get();
+		if (res)
+			goto err_exit;
+
+		hotkey_orig_mask = hotkey_mask;
+		res = add_many_to_attr_set(
+				hotkey_dev_attributes,
+				hotkey_mask_attributes,
+				ARRAY_SIZE(hotkey_mask_attributes));
+		if (res)
+			goto err_exit;
+	}
 
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
-		if (tp_features.hotkey_mask) {
-			hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
-						& ~hotkey_all_mask;
-		} else {
-			hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
-		}
+	if (tp_features.hotkey_mask) {
+		hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK
+					& ~hotkey_all_mask;
+	} else {
+		hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
+	}
 
-		vdbg_printk(TPACPI_DBG_INIT,
-			    "hotkey source mask 0x%08x, polling freq %d\n",
-			    hotkey_source_mask, hotkey_poll_freq);
+	vdbg_printk(TPACPI_DBG_INIT,
+		    "hotkey source mask 0x%08x, polling freq %d\n",
+		    hotkey_source_mask, hotkey_poll_freq);
 #endif
 
-		/* Not all thinkpads have a hardware radio switch */
-		if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
-			tp_features.hotkey_wlsw = 1;
-			printk(TPACPI_INFO
-				"radio switch found; radios are %s\n",
-				enabled(status, 0));
-			res = add_to_attr_set(hotkey_dev_attributes,
-					&dev_attr_hotkey_radio_sw.attr);
-		}
+	/* Not all thinkpads have a hardware radio switch */
+	if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
+		tp_features.hotkey_wlsw = 1;
+		printk(TPACPI_INFO
+			"radio switch found; radios are %s\n",
+			enabled(status, 0));
+		res = add_to_attr_set(hotkey_dev_attributes,
+				&dev_attr_hotkey_radio_sw.attr);
+	}
 
-		/* For X41t, X60t, X61t Tablets... */
-		if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
-			tp_features.hotkey_tablet = 1;
-			printk(TPACPI_INFO
-				"possible tablet mode switch found; "
-				"ThinkPad in %s mode\n",
-				(status & TP_HOTKEY_TABLET_MASK)?
-					"tablet" : "laptop");
-			res = add_to_attr_set(hotkey_dev_attributes,
-					&dev_attr_hotkey_tablet_mode.attr);
-		}
+	/* For X41t, X60t, X61t Tablets... */
+	if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
+		tp_features.hotkey_tablet = 1;
+		printk(TPACPI_INFO
+			"possible tablet mode switch found; "
+			"ThinkPad in %s mode\n",
+			(status & TP_HOTKEY_TABLET_MASK)?
+				"tablet" : "laptop");
+		res = add_to_attr_set(hotkey_dev_attributes,
+				&dev_attr_hotkey_tablet_mode.attr);
+	}
 
-		if (!res)
-			res = register_attr_set_with_sysfs(
-					hotkey_dev_attributes,
-					&tpacpi_pdev->dev.kobj);
-		if (res)
-			return res;
+	if (!res)
+		res = register_attr_set_with_sysfs(
+				hotkey_dev_attributes,
+				&tpacpi_pdev->dev.kobj);
+	if (res)
+		goto err_exit;
 
-		/* Set up key map */
+	/* Set up key map */
 
-		hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
-						GFP_KERNEL);
-		if (!hotkey_keycode_map) {
-			printk(TPACPI_ERR
-				"failed to allocate memory for key map\n");
-			return -ENOMEM;
-		}
+	hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE,
+					GFP_KERNEL);
+	if (!hotkey_keycode_map) {
+		printk(TPACPI_ERR
+			"failed to allocate memory for key map\n");
+		res = -ENOMEM;
+		goto err_exit;
+	}
 
-		if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
-			dbg_printk(TPACPI_DBG_INIT,
-				   "using Lenovo default hot key map\n");
-			memcpy(hotkey_keycode_map, &lenovo_keycode_map,
-				TPACPI_HOTKEY_MAP_SIZE);
+	if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
+		dbg_printk(TPACPI_DBG_INIT,
+			   "using Lenovo default hot key map\n");
+		memcpy(hotkey_keycode_map, &lenovo_keycode_map,
+			TPACPI_HOTKEY_MAP_SIZE);
+	} else {
+		dbg_printk(TPACPI_DBG_INIT,
+			   "using IBM default hot key map\n");
+		memcpy(hotkey_keycode_map, &ibm_keycode_map,
+			TPACPI_HOTKEY_MAP_SIZE);
+	}
+
+	set_bit(EV_KEY, tpacpi_inputdev->evbit);
+	set_bit(EV_MSC, tpacpi_inputdev->evbit);
+	set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
+	tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
+	tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
+	tpacpi_inputdev->keycode = hotkey_keycode_map;
+	for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
+		if (hotkey_keycode_map[i] != KEY_RESERVED) {
+			set_bit(hotkey_keycode_map[i],
+				tpacpi_inputdev->keybit);
 		} else {
-			dbg_printk(TPACPI_DBG_INIT,
-				   "using IBM default hot key map\n");
-			memcpy(hotkey_keycode_map, &ibm_keycode_map,
-				TPACPI_HOTKEY_MAP_SIZE);
-		}
-
-		set_bit(EV_KEY, tpacpi_inputdev->evbit);
-		set_bit(EV_MSC, tpacpi_inputdev->evbit);
-		set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
-		tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
-		tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
-		tpacpi_inputdev->keycode = hotkey_keycode_map;
-		for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
-			if (hotkey_keycode_map[i] != KEY_RESERVED) {
-				set_bit(hotkey_keycode_map[i],
-					tpacpi_inputdev->keybit);
-			} else {
-				if (i < sizeof(hotkey_reserved_mask)*8)
-					hotkey_reserved_mask |= 1 << i;
-			}
-		}
-
-		if (tp_features.hotkey_wlsw) {
-			set_bit(EV_SW, tpacpi_inputdev->evbit);
-			set_bit(SW_RADIO, tpacpi_inputdev->swbit);
-		}
-		if (tp_features.hotkey_tablet) {
-			set_bit(EV_SW, tpacpi_inputdev->evbit);
-			set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
+			if (i < sizeof(hotkey_reserved_mask)*8)
+				hotkey_reserved_mask |= 1 << i;
 		}
+	}
 
-		/* Do not issue duplicate brightness change events to
-		 * userspace */
-		if (!tp_features.bright_acpimode)
-			/* update bright_acpimode... */
-			tpacpi_check_std_acpi_brightness_support();
-
-		if (tp_features.bright_acpimode) {
-			printk(TPACPI_INFO
-			       "This ThinkPad has standard ACPI backlight "
-			       "brightness control, supported by the ACPI "
-			       "video driver\n");
-			printk(TPACPI_NOTICE
-			       "Disabling thinkpad-acpi brightness events "
-			       "by default...\n");
-
-			/* The hotkey_reserved_mask change below is not
-			 * necessary while the keys are at KEY_RESERVED in the
-			 * default map, but better safe than sorry, leave it
-			 * here as a marker of what we have to do, especially
-			 * when we finally become able to set this at runtime
-			 * on response to X.org requests */
-			hotkey_reserved_mask |=
-				(1 << TP_ACPI_HOTKEYSCAN_FNHOME)
-				| (1 << TP_ACPI_HOTKEYSCAN_FNEND);
-		}
+	if (tp_features.hotkey_wlsw) {
+		set_bit(EV_SW, tpacpi_inputdev->evbit);
+		set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
+	}
+	if (tp_features.hotkey_tablet) {
+		set_bit(EV_SW, tpacpi_inputdev->evbit);
+		set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
+	}
 
-		dbg_printk(TPACPI_DBG_INIT,
-				"enabling hot key handling\n");
-		res = hotkey_status_set(1);
-		if (res)
-			return res;
-		res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask)
-					& ~hotkey_reserved_mask)
-					| hotkey_orig_mask);
-		if (res < 0 && res != -ENXIO)
-			return res;
+	/* Do not issue duplicate brightness change events to
+	 * userspace */
+	if (!tp_features.bright_acpimode)
+		/* update bright_acpimode... */
+		tpacpi_check_std_acpi_brightness_support();
 
-		dbg_printk(TPACPI_DBG_INIT,
-				"legacy hot key reporting over procfs %s\n",
-				(hotkey_report_mode < 2) ?
-					"enabled" : "disabled");
+	if (tp_features.bright_acpimode) {
+		printk(TPACPI_INFO
+		       "This ThinkPad has standard ACPI backlight "
+		       "brightness control, supported by the ACPI "
+		       "video driver\n");
+		printk(TPACPI_NOTICE
+		       "Disabling thinkpad-acpi brightness events "
+		       "by default...\n");
+
+		/* The hotkey_reserved_mask change below is not
+		 * necessary while the keys are at KEY_RESERVED in the
+		 * default map, but better safe than sorry, leave it
+		 * here as a marker of what we have to do, especially
+		 * when we finally become able to set this at runtime
+		 * on response to X.org requests */
+		hotkey_reserved_mask |=
+			(1 << TP_ACPI_HOTKEYSCAN_FNHOME)
+			| (1 << TP_ACPI_HOTKEYSCAN_FNEND);
+	}
+
+	dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n");
+	res = hotkey_status_set(1);
+	if (res) {
+		hotkey_exit();
+		return res;
+	}
+	res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask)
+				& ~hotkey_reserved_mask)
+				| hotkey_orig_mask);
+	if (res < 0 && res != -ENXIO) {
+		hotkey_exit();
+		return res;
+	}
 
-		tpacpi_inputdev->open = &hotkey_inputdev_open;
-		tpacpi_inputdev->close = &hotkey_inputdev_close;
+	dbg_printk(TPACPI_DBG_INIT,
+			"legacy hot key reporting over procfs %s\n",
+			(hotkey_report_mode < 2) ?
+				"enabled" : "disabled");
 
-		hotkey_poll_setup_safe(1);
-		tpacpi_input_send_radiosw();
-		tpacpi_input_send_tabletsw();
-	}
+	tpacpi_inputdev->open = &hotkey_inputdev_open;
+	tpacpi_inputdev->close = &hotkey_inputdev_close;
 
-	return (tp_features.hotkey)? 0 : 1;
-}
+	hotkey_poll_setup_safe(1);
+	tpacpi_input_send_radiosw();
+	tpacpi_input_send_tabletsw();
 
-static void hotkey_exit(void)
-{
-#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
-	hotkey_poll_stop_sync();
-#endif
+	return 0;
 
-	if (tp_features.hotkey) {
-		dbg_printk(TPACPI_DBG_EXIT,
-			   "restoring original hot key mask\n");
-		/* no short-circuit boolean operator below! */
-		if ((hotkey_mask_set(hotkey_orig_mask) |
-		     hotkey_status_set(hotkey_orig_status)) != 0)
-			printk(TPACPI_ERR
-			       "failed to restore hot key mask "
-			       "to BIOS defaults\n");
-	}
+err_exit:
+	delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
+	hotkey_dev_attributes = NULL;
 
-	if (hotkey_dev_attributes) {
-		delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
-		hotkey_dev_attributes = NULL;
-	}
+	return (res < 0)? res : 1;
 }
 
 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = {
 
 static int __init light_init(struct ibm_init_struct *iibm)
 {
-	int rc = 0;
+	int rc;
 
 	vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n");
 
@@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm)
 		tp_features.light_status =
 			acpi_evalf(ec_handle, NULL, "KBLT", "qv");
 
-	vdbg_printk(TPACPI_DBG_INIT, "light is %s\n",
-		str_supported(tp_features.light));
+	vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n",
+		str_supported(tp_features.light),
+		str_supported(tp_features.light_status));
 
-	if (tp_features.light) {
-		rc = led_classdev_register(&tpacpi_pdev->dev,
-					   &tpacpi_led_thinklight.led_classdev);
-	}
+	if (!tp_features.light)
+		return 1;
+
+	rc = led_classdev_register(&tpacpi_pdev->dev,
+				   &tpacpi_led_thinklight.led_classdev);
 
 	if (rc < 0) {
 		tp_features.light = 0;
 		tp_features.light_status = 0;
-	} else {
-		rc = (tp_features.light)? 0 : 1;
+	} else  {
+		rc = 0;
 	}
+
 	return rc;
 }
 
@@ -3833,7 +3853,7 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
 	"tpacpi::standby",
 };
 
-static int led_get_status(unsigned int led)
+static int led_get_status(const unsigned int led)
 {
 	int status;
 	enum led_status_t led_s;
@@ -3857,41 +3877,42 @@ static int led_get_status(unsigned int led)
 	/* not reached */
 }
 
-static int led_set_status(unsigned int led, enum led_status_t ledstatus)
+static int led_set_status(const unsigned int led,
+			  const enum led_status_t ledstatus)
 {
 	/* off, on, blink. Index is led_status_t */
-	static const int led_sled_arg1[] = { 0, 1, 3 };
-	static const int led_exp_hlbl[] = { 0, 0, 1 };	/* led# * */
-	static const int led_exp_hlcl[] = { 0, 1, 1 };	/* led# * */
-	static const int led_led_arg1[] = { 0, 0x80, 0xc0 };
+	static const unsigned int led_sled_arg1[] = { 0, 1, 3 };
+	static const unsigned int led_led_arg1[] = { 0, 0x80, 0xc0 };
 
 	int rc = 0;
 
 	switch (led_supported) {
 	case TPACPI_LED_570:
-			/* 570 */
-			led = 1 << led;
-			if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
-					led, led_sled_arg1[ledstatus]))
-				rc = -EIO;
-			break;
+		/* 570 */
+		if (led > 7)
+			return -EINVAL;
+		if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+				(1 << led), led_sled_arg1[ledstatus]))
+			rc = -EIO;
+		break;
 	case TPACPI_LED_OLD:
-			/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
-			led = 1 << led;
-			rc = ec_write(TPACPI_LED_EC_HLMS, led);
-			if (rc >= 0)
-				rc = ec_write(TPACPI_LED_EC_HLBL,
-					      led * led_exp_hlbl[ledstatus]);
-			if (rc >= 0)
-				rc = ec_write(TPACPI_LED_EC_HLCL,
-					      led * led_exp_hlcl[ledstatus]);
-			break;
+		/* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
+		if (led > 7)
+			return -EINVAL;
+		rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led));
+		if (rc >= 0)
+			rc = ec_write(TPACPI_LED_EC_HLBL,
+				      (ledstatus == TPACPI_LED_BLINK) << led);
+		if (rc >= 0)
+			rc = ec_write(TPACPI_LED_EC_HLCL,
+				      (ledstatus != TPACPI_LED_OFF) << led);
+		break;
 	case TPACPI_LED_NEW:
-			/* all others */
-			if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
-					led, led_led_arg1[ledstatus]))
-				rc = -EIO;
-			break;
+		/* all others */
+		if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
+				led, led_led_arg1[ledstatus]))
+			rc = -EIO;
+		break;
 	default:
 		rc = -ENXIO;
 	}
@@ -3978,7 +3999,6 @@ static void led_exit(void)
 	}
 
 	kfree(tpacpi_leds);
-	tpacpi_leds = NULL;
 }
 
 static int __init led_init(struct ibm_init_struct *iibm)
@@ -4802,7 +4822,6 @@ static void brightness_exit(void)
 		vdbg_printk(TPACPI_DBG_EXIT,
 			    "calling backlight_device_unregister()\n");
 		backlight_device_unregister(ibm_backlight_device);
-		ibm_backlight_device = NULL;
 	}
 }
 
@@ -5764,11 +5783,16 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 	    fan_control_access_mode != TPACPI_FAN_WR_NONE) {
 		rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
 					 &fan_attr_group);
-		if (!(rc < 0))
-			rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
-					&driver_attr_fan_watchdog);
 		if (rc < 0)
 			return rc;
+
+		rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
+					&driver_attr_fan_watchdog);
+		if (rc < 0) {
+			sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
+					&fan_attr_group);
+			return rc;
+		}
 		return 0;
 	} else
 		return 1;

+ 29 - 17
drivers/pnp/pnpacpi/rsparser.c

@@ -50,15 +50,17 @@ static int irq_flags(int triggering, int polarity, int shareable)
 			flags = IORESOURCE_IRQ_HIGHEDGE;
 	}
 
-	if (shareable)
+	if (shareable == ACPI_SHARED)
 		flags |= IORESOURCE_IRQ_SHAREABLE;
 
 	return flags;
 }
 
-static void decode_irq_flags(int flag, int *triggering, int *polarity)
+static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
+			     int *polarity, int *shareable)
 {
-	switch (flag) {
+	switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL |
+			 IORESOURCE_IRQ_LOWEDGE  | IORESOURCE_IRQ_HIGHEDGE)) {
 	case IORESOURCE_IRQ_LOWLEVEL:
 		*triggering = ACPI_LEVEL_SENSITIVE;
 		*polarity = ACPI_ACTIVE_LOW;
@@ -75,7 +77,18 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity)
 		*triggering = ACPI_EDGE_SENSITIVE;
 		*polarity = ACPI_ACTIVE_HIGH;
 		break;
+	default:
+		dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n",
+			flags);
+		*triggering = ACPI_EDGE_SENSITIVE;
+		*polarity = ACPI_ACTIVE_HIGH;
+		break;
 	}
+
+	if (flags & IORESOURCE_IRQ_SHAREABLE)
+		*shareable = ACPI_SHARED;
+	else
+		*shareable = ACPI_EXCLUSIVE;
 }
 
 static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
@@ -742,6 +755,9 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
 	if (pnpacpi_supported_resource(res)) {
 		(*resource)->type = res->type;
 		(*resource)->length = sizeof(struct acpi_resource);
+		if (res->type == ACPI_RESOURCE_TYPE_IRQ)
+			(*resource)->data.irq.descriptor_length =
+					res->data.irq.descriptor_length;
 		(*resource)++;
 	}
 
@@ -788,22 +804,21 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev,
 			       struct resource *p)
 {
 	struct acpi_resource_irq *irq = &resource->data.irq;
-	int triggering, polarity;
+	int triggering, polarity, shareable;
 
-	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
+	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 	irq->triggering = triggering;
 	irq->polarity = polarity;
-	if (triggering == ACPI_EDGE_SENSITIVE)
-		irq->sharable = ACPI_EXCLUSIVE;
-	else
-		irq->sharable = ACPI_SHARED;
+	irq->sharable = shareable;
 	irq->interrupt_count = 1;
 	irq->interrupts[0] = p->start;
 
-	dev_dbg(&dev->dev, "  encode irq %d %s %s %s\n", (int) p->start,
+	dev_dbg(&dev->dev, "  encode irq %d %s %s %s (%d-byte descriptor)\n",
+		(int) p->start,
 		triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge",
 		polarity == ACPI_ACTIVE_LOW ? "low" : "high",
-		irq->sharable == ACPI_SHARED ? "shared" : "exclusive");
+		irq->sharable == ACPI_SHARED ? "shared" : "exclusive",
+		irq->descriptor_length);
 }
 
 static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
@@ -811,16 +826,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev,
 				   struct resource *p)
 {
 	struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq;
-	int triggering, polarity;
+	int triggering, polarity, shareable;
 
-	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
+	decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable);
 	extended_irq->producer_consumer = ACPI_CONSUMER;
 	extended_irq->triggering = triggering;
 	extended_irq->polarity = polarity;
-	if (triggering == ACPI_EDGE_SENSITIVE)
-		extended_irq->sharable = ACPI_EXCLUSIVE;
-	else
-		extended_irq->sharable = ACPI_SHARED;
+	extended_irq->sharable = shareable;
 	extended_irq->interrupt_count = 1;
 	extended_irq->interrupts[0] = p->start;
 

+ 1 - 0
include/acpi/processor.h

@@ -319,6 +319,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
 #endif				/* CONFIG_CPU_FREQ */
 
 /* in processor_throttling.c */
+int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
 extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
 extern struct file_operations acpi_processor_throttling_fops;

+ 1 - 0
include/linux/cpuidle.h

@@ -82,6 +82,7 @@ struct cpuidle_state_kobj {
 };
 
 struct cpuidle_device {
+	unsigned int		registered:1;
 	unsigned int		enabled:1;
 	unsigned int		cpu;
 

+ 3 - 3
include/linux/ioport.h

@@ -53,14 +53,14 @@ struct resource_list {
 #define IORESOURCE_AUTO		0x40000000
 #define IORESOURCE_BUSY		0x80000000	/* Driver has marked this resource busy */
 
-/* ISA PnP IRQ specific bits (IORESOURCE_BITS) */
+/* PnP IRQ specific bits (IORESOURCE_BITS) */
 #define IORESOURCE_IRQ_HIGHEDGE		(1<<0)
 #define IORESOURCE_IRQ_LOWEDGE		(1<<1)
 #define IORESOURCE_IRQ_HIGHLEVEL	(1<<2)
 #define IORESOURCE_IRQ_LOWLEVEL		(1<<3)
 #define IORESOURCE_IRQ_SHAREABLE	(1<<4)
 
-/* ISA PnP DMA specific bits (IORESOURCE_BITS) */
+/* PnP DMA specific bits (IORESOURCE_BITS) */
 #define IORESOURCE_DMA_TYPE_MASK	(3<<0)
 #define IORESOURCE_DMA_8BIT		(0<<0)
 #define IORESOURCE_DMA_8AND16BIT	(1<<0)
@@ -76,7 +76,7 @@ struct resource_list {
 #define IORESOURCE_DMA_TYPEB		(2<<6)
 #define IORESOURCE_DMA_TYPEF		(3<<6)
 
-/* ISA PnP memory I/O specific bits (IORESOURCE_BITS) */
+/* PnP memory I/O specific bits (IORESOURCE_BITS) */
 #define IORESOURCE_MEM_WRITEABLE	(1<<0)	/* dup: IORESOURCE_READONLY */
 #define IORESOURCE_MEM_CACHEABLE	(1<<1)	/* dup: IORESOURCE_CACHEABLE */
 #define IORESOURCE_MEM_RANGELENGTH	(1<<2)	/* dup: IORESOURCE_RANGELENGTH */