Browse Source

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: (32 commits)
  ACPI: thermal: show temperature in millidegree Celsius
  thermal: fix generic thermal I/F for hwmon
  acer-wmi: build depends on i8042
  documentation:  Move power-related files to Documentation/power/
  ACPI: buffer array too short in drivers/acpi/system.c
  acer-wmi: Add DMI quirk for mail LED support on Acer Aspire 3610/ 5610
  acer-wmi: Fix DSDT path in documentation
  acer-wmi: Make device detection error messages more descriptive
  laptops: move laptop-mode.txt to Documentation/laptops/
  ACPICA: Warn if packages with invalid references are evaluated
  ACPI: add _PRT quirks to work around broken firmware
  Hibernation: Fix mark_nosave_pages()
  ACPI: Ignore _BQC object when registering backlight device
  ACPI: WMI: Clean up handling of spec violating data blocks
  acer-wmi: Don't warn if mail LED cannot be detected
  acer-wmi: Rename mail LED correctly & remove hardcoded colour
  ACPI: use ACPI_DEBUG_PRINT instead of printk in acpi_processor_hotplug_notify()
  ACPI: button: make real parent for input devices in device tree
  toshiba_acpi: Enable autoloading
  ACPI: EC: Handle IRQ storm on Acer laptops
  ...
Linus Torvalds 17 years ago
parent
commit
96e31022a1

+ 0 - 6
Documentation/00-INDEX

@@ -225,8 +225,6 @@ kprobes.txt
 	- documents the kernel probes debugging feature.
 	- documents the kernel probes debugging feature.
 kref.txt
 kref.txt
 	- docs on adding reference counters (krefs) to kernel objects.
 	- docs on adding reference counters (krefs) to kernel objects.
-laptop-mode.txt
-	- how to conserve battery power using laptop-mode.
 laptops/
 laptops/
 	- directory with laptop related info and laptop driver documentation.
 	- directory with laptop related info and laptop driver documentation.
 ldm.txt
 ldm.txt
@@ -301,12 +299,8 @@ pcmcia/
 	- info on the Linux PCMCIA driver.
 	- info on the Linux PCMCIA driver.
 pi-futex.txt
 pi-futex.txt
 	- documentation on lightweight PI-futexes.
 	- documentation on lightweight PI-futexes.
-pm.txt
-	- info on Linux power management support.
 pnp.txt
 pnp.txt
 	- Linux Plug and Play documentation.
 	- Linux Plug and Play documentation.
-power_supply_class.txt
-	- Tells userspace about battery, UPS, AC or DC power supply properties
 power/
 power/
 	- directory with info on Linux PCI power management.
 	- directory with info on Linux PCI power management.
 powerpc/
 powerpc/

+ 2 - 2
Documentation/filesystems/proc.txt

@@ -1506,13 +1506,13 @@ laptop_mode
 -----------
 -----------
 
 
 laptop_mode is a knob that controls "laptop mode". All the things that are
 laptop_mode is a knob that controls "laptop mode". All the things that are
-controlled by this knob are discussed in Documentation/laptop-mode.txt.
+controlled by this knob are discussed in Documentation/laptops/laptop-mode.txt.
 
 
 block_dump
 block_dump
 ----------
 ----------
 
 
 block_dump enables block I/O debugging when set to a nonzero value. More
 block_dump enables block I/O debugging when set to a nonzero value. More
-information on block I/O debugging is in Documentation/laptop-mode.txt.
+information on block I/O debugging is in Documentation/laptops/laptop-mode.txt.
 
 
 swap_token_timeout
 swap_token_timeout
 ------------------
 ------------------

+ 1 - 1
Documentation/kernel-parameters.txt

@@ -138,7 +138,7 @@ and is between 256 and 4096 characters. It is defined in the file
 			strict -- Be less tolerant of platforms that are not
 			strict -- Be less tolerant of platforms that are not
 				strictly ACPI specification compliant.
 				strictly ACPI specification compliant.
 
 
-			See also Documentation/pm.txt, pci=noacpi
+			See also Documentation/power/pm.txt, pci=noacpi
 
 
 	acpi_apic_instance=	[ACPI, IOAPIC]
 	acpi_apic_instance=	[ACPI, IOAPIC]
 			Format: <int>
 			Format: <int>

+ 2 - 0
Documentation/laptops/00-INDEX

@@ -2,6 +2,8 @@
 	- This file
 	- This file
 acer-wmi.txt
 acer-wmi.txt
 	- information on the Acer Laptop WMI Extras driver.
 	- information on the Acer Laptop WMI Extras driver.
+laptop-mode.txt
+	- how to conserve battery power using laptop-mode.
 sony-laptop.txt
 sony-laptop.txt
 	- Sony Notebook Control Driver (SNC) Readme.
 	- Sony Notebook Control Driver (SNC) Readme.
 sonypi.txt
 sonypi.txt

+ 2 - 2
Documentation/laptops/acer-wmi.txt

@@ -48,7 +48,7 @@ DSDT.
 
 
 To send me the DSDT, as root/sudo:
 To send me the DSDT, as root/sudo:
 
 
-cat /sys/firmware/acpi/DSDT > dsdt
+cat /sys/firmware/acpi/tables/DSDT > dsdt
 
 
 And send me the resulting 'dsdt' file.
 And send me the resulting 'dsdt' file.
 
 
@@ -169,7 +169,7 @@ can be added to acer-wmi.
 
 
 The LED is exposed through the LED subsystem, and can be found in:
 The LED is exposed through the LED subsystem, and can be found in:
 
 
-/sys/devices/platform/acer-wmi/leds/acer-mail:green/
+/sys/devices/platform/acer-wmi/leds/acer-wmi::mail/
 
 
 The mail LED is autodetected, so if you don't have one, the LED device won't
 The mail LED is autodetected, so if you don't have one, the LED device won't
 be registered.
 be registered.

+ 0 - 0
Documentation/laptop-mode.txt → Documentation/laptops/laptop-mode.txt


+ 6 - 0
Documentation/power/00-INDEX

@@ -14,6 +14,12 @@ notifiers.txt
 	- Registering suspend notifiers in device drivers
 	- Registering suspend notifiers in device drivers
 pci.txt
 pci.txt
 	- How the PCI Subsystem Does Power Management
 	- How the PCI Subsystem Does Power Management
+pm.txt
+	- info on Linux power management support.
+pm_qos_interface.txt
+	- info on Linux PM Quality of Service interface
+power_supply_class.txt
+	- Tells userspace about battery, UPS, AC or DC power supply properties
 s2ram.txt
 s2ram.txt
 	- How to get suspend to ram working (and debug it when it isn't)
 	- How to get suspend to ram working (and debug it when it isn't)
 states.txt
 states.txt

+ 1 - 1
Documentation/pm.txt → Documentation/power/pm.txt

@@ -108,7 +108,7 @@ void pm_unregister_all(pm_callback cback);
  *          EINVAL if the request is not supported
  *          EINVAL if the request is not supported
  *          EBUSY if the device is now busy and cannot handle the request
  *          EBUSY if the device is now busy and cannot handle the request
  *          ENOMEM if the device was unable to handle the request due to memory
  *          ENOMEM if the device was unable to handle the request due to memory
- *          
+ *
  * Details: The device request callback will be called before the
  * Details: The device request callback will be called before the
  *          device/system enters a suspend state (ACPI D1-D3) or
  *          device/system enters a suspend state (ACPI D1-D3) or
  *          or after the device/system resumes from suspend (ACPI D0).
  *          or after the device/system resumes from suspend (ACPI D0).

+ 0 - 0
Documentation/pm_qos_interface.txt → Documentation/power/pm_qos_interface.txt


+ 0 - 0
Documentation/power_supply_class.txt → Documentation/power/power_supply_class.txt


+ 11 - 11
Documentation/thermal/sysfs-api.txt

@@ -143,10 +143,10 @@ type				Strings which represent the thermal zone type.
 				This is given by thermal zone driver as part of registration.
 				This is given by thermal zone driver as part of registration.
 				Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
 				Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
 				RO
 				RO
-				Optional
+				Required
 
 
 temp				Current temperature as reported by thermal zone (sensor)
 temp				Current temperature as reported by thermal zone (sensor)
-				Unit: degree Celsius
+				Unit: millidegree Celsius
 				RO
 				RO
 				Required
 				Required
 
 
@@ -163,7 +163,7 @@ mode				One of the predefined values in [kernel, user]
 					  charge of the thermal management.
 					  charge of the thermal management.
 
 
 trip_point_[0-*]_temp		The temperature above which trip point will be fired
 trip_point_[0-*]_temp		The temperature above which trip point will be fired
-				Unit: degree Celsius
+				Unit: millidegree Celsius
 				RO
 				RO
 				Optional
 				Optional
 
 
@@ -193,7 +193,7 @@ type				String which represents the type of device
 				eg. For memory controller device on intel_menlow platform:
 				eg. For memory controller device on intel_menlow platform:
 				this should be "Memory controller"
 				this should be "Memory controller"
 				RO
 				RO
-				Optional
+				Required
 
 
 max_state			The maximum permissible cooling state of this cooling device.
 max_state			The maximum permissible cooling state of this cooling device.
 				RO
 				RO
@@ -219,16 +219,16 @@ the sys I/F structure will be built like this:
 
 
 |thermal_zone1:
 |thermal_zone1:
 	|-----type:			ACPI thermal zone
 	|-----type:			ACPI thermal zone
-	|-----temp:			37
+	|-----temp:			37000
 	|-----mode:			kernel
 	|-----mode:			kernel
-	|-----trip_point_0_temp:	100
+	|-----trip_point_0_temp:	100000
 	|-----trip_point_0_type:	critical
 	|-----trip_point_0_type:	critical
-	|-----trip_point_1_temp:	80
+	|-----trip_point_1_temp:	80000
 	|-----trip_point_1_type:	passive
 	|-----trip_point_1_type:	passive
-	|-----trip_point_2_temp:	70
-	|-----trip_point_2_type:	active[0]
-	|-----trip_point_3_temp:	60
-	|-----trip_point_3_type:	active[1]
+	|-----trip_point_2_temp:	70000
+	|-----trip_point_2_type:	active0
+	|-----trip_point_3_temp:	60000
+	|-----trip_point_3_type:	active1
 	|-----cdev0:			--->/sys/class/thermal/cooling_device0
 	|-----cdev0:			--->/sys/class/thermal/cooling_device0
 	|-----cdev0_trip_point:		1	/* cdev0 can be used for passive */
 	|-----cdev0_trip_point:		1	/* cdev0 can be used for passive */
 	|-----cdev1:			--->/sys/class/thermal/cooling_device3
 	|-----cdev1:			--->/sys/class/thermal/cooling_device3

+ 1 - 1
arch/x86/Kconfig

@@ -1259,7 +1259,7 @@ menuconfig APM
 	  machines with more than one CPU.
 	  machines with more than one CPU.
 
 
 	  In order to use APM, you will need supporting software. For location
 	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/pm.txt> and the
+	  and more information, read <file:Documentation/power/pm.txt> and the
 	  Battery Powered Linux mini-HOWTO, available from
 	  Battery Powered Linux mini-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 	  <http://www.tldp.org/docs.html#howto>.
 
 

+ 9 - 10
drivers/acpi/Kconfig

@@ -283,24 +283,23 @@ config ACPI_TOSHIBA
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
 	  series), say Y.
 
 
-config ACPI_CUSTOM_DSDT
-	bool "Include Custom DSDT"
+config ACPI_CUSTOM_DSDT_FILE
+	string "Custom DSDT Table file to include"
+	default ""
 	depends on !STANDALONE
 	depends on !STANDALONE
-	default n 
 	help
 	help
 	  This option supports a custom DSDT by linking it into the kernel.
 	  This option supports a custom DSDT by linking it into the kernel.
 	  See Documentation/acpi/dsdt-override.txt
 	  See Documentation/acpi/dsdt-override.txt
 
 
-	  If unsure, say N.
-
-config ACPI_CUSTOM_DSDT_FILE
-	string "Custom DSDT Table file to include"
-	depends on ACPI_CUSTOM_DSDT
-	default ""
-	help
 	  Enter the full path name to the file which includes the AmlCode
 	  Enter the full path name to the file which includes the AmlCode
 	  declaration.
 	  declaration.
 
 
+	  If unsure, don't enter a file name.
+
+config ACPI_CUSTOM_DSDT
+	bool
+	default ACPI_CUSTOM_DSDT_FILE != ""
+
 config ACPI_CUSTOM_DSDT_INITRD
 config ACPI_CUSTOM_DSDT_INITRD
 	bool "Read Custom DSDT from initramfs"
 	bool "Read Custom DSDT from initramfs"
 	depends on BLK_DEV_INITRD
 	depends on BLK_DEV_INITRD

+ 1 - 1
drivers/acpi/bus.c

@@ -776,7 +776,7 @@ static int __init acpi_init(void)
 
 
 	acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
 	acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
 	if (!acpi_kobj) {
 	if (!acpi_kobj) {
-		printk(KERN_WARNING "%s: kset create error\n", __FUNCTION__);
+		printk(KERN_WARNING "%s: kset create error\n", __func__);
 		acpi_kobj = NULL;
 		acpi_kobj = NULL;
 	}
 	}
 
 

+ 1 - 0
drivers/acpi/button.c

@@ -449,6 +449,7 @@ static int acpi_button_add(struct acpi_device *device)
 	input->phys = button->phys;
 	input->phys = button->phys;
 	input->id.bustype = BUS_HOST;
 	input->id.bustype = BUS_HOST;
 	input->id.product = button->type;
 	input->id.product = button->type;
+	input->dev.parent = &device->dev;
 
 
 	switch (button->type) {
 	switch (button->type) {
 	case ACPI_BUTTON_TYPE_POWER:
 	case ACPI_BUTTON_TYPE_POWER:

+ 12 - 5
drivers/acpi/ec.c

@@ -129,6 +129,7 @@ static struct acpi_ec {
 	struct mutex lock;
 	struct mutex lock;
 	wait_queue_head_t wait;
 	wait_queue_head_t wait;
 	struct list_head list;
 	struct list_head list;
+	atomic_t irq_count;
 	u8 handlers_installed;
 	u8 handlers_installed;
 } *boot_ec, *first_ec;
 } *boot_ec, *first_ec;
 
 
@@ -181,6 +182,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
 {
 {
 	int ret = 0;
 	int ret = 0;
 
 
+	atomic_set(&ec->irq_count, 0);
+
 	if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
 	if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
 		     test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
 		     test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
 		force_poll = 1;
 		force_poll = 1;
@@ -227,6 +230,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
 		while (time_before(jiffies, delay)) {
 		while (time_before(jiffies, delay)) {
 			if (acpi_ec_check_status(ec, event))
 			if (acpi_ec_check_status(ec, event))
 				goto end;
 				goto end;
+			msleep(5);
 		}
 		}
 	}
 	}
 	pr_err(PREFIX "acpi_ec_wait timeout,"
 	pr_err(PREFIX "acpi_ec_wait timeout,"
@@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data)
 	struct acpi_ec *ec = data;
 	struct acpi_ec *ec = data;
 
 
 	pr_debug(PREFIX "~~~> interrupt\n");
 	pr_debug(PREFIX "~~~> interrupt\n");
+	atomic_inc(&ec->irq_count);
+	if (atomic_read(&ec->irq_count) > 5) {
+		pr_err(PREFIX "GPE storm detected, disabling EC GPE\n");
+		acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR);
+		clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
+		return ACPI_INTERRUPT_HANDLED;
+	}
 	clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
 	clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
 	if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
 	if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
 		wake_up(&ec->wait);
 		wake_up(&ec->wait);
@@ -943,11 +954,7 @@ int __init acpi_ec_ecdt_probe(void)
 		boot_ec->command_addr = ecdt_ptr->control.address;
 		boot_ec->command_addr = ecdt_ptr->control.address;
 		boot_ec->data_addr = ecdt_ptr->data.address;
 		boot_ec->data_addr = ecdt_ptr->data.address;
 		boot_ec->gpe = ecdt_ptr->gpe;
 		boot_ec->gpe = ecdt_ptr->gpe;
-		if (ACPI_FAILURE(acpi_get_handle(NULL, ecdt_ptr->id,
-				&boot_ec->handle))) {
-			pr_info("Failed to locate handle for boot EC\n");
-			boot_ec->handle = ACPI_ROOT_OBJECT;
-		}
+		boot_ec->handle = ACPI_ROOT_OBJECT;
 	} else {
 	} else {
 		/* This workaround is needed only on some broken machines,
 		/* This workaround is needed only on some broken machines,
 		 * which require early EC, but fail to provide ECDT */
 		 * which require early EC, but fail to provide ECDT */

+ 1 - 1
drivers/acpi/osl.c

@@ -1237,7 +1237,7 @@ int acpi_check_resource_conflict(struct resource *res)
 
 
 	if (clash) {
 	if (clash) {
 		if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
 		if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
-			printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]"
+			printk("%sACPI: %s resource %s [0x%llx-0x%llx]"
 			       " conflicts with ACPI region %s"
 			       " conflicts with ACPI region %s"
 			       " [0x%llx-0x%llx]\n",
 			       " [0x%llx-0x%llx]\n",
 			       acpi_enforce_resources == ENFORCE_RESOURCES_LAX
 			       acpi_enforce_resources == ENFORCE_RESOURCES_LAX

+ 98 - 0
drivers/acpi/pci_irq.c

@@ -25,6 +25,7 @@
  */
  */
 
 
 
 
+#include <linux/dmi.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/init.h>
@@ -76,6 +77,101 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
 	return NULL;
 	return NULL;
 }
 }
 
 
+/* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */
+static struct dmi_system_id medion_md9580[] = {
+	{
+		.ident = "Medion MD9580-F laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "A555"),
+		},
+	},
+	{ }
+};
+
+/* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */
+static struct dmi_system_id dell_optiplex[] = {
+	{
+		.ident = "Dell Optiplex GX1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"),
+		},
+	},
+	{ }
+};
+
+/* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */
+static struct dmi_system_id hp_t5710[] = {
+	{
+		.ident = "HP t5710",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"),
+			DMI_MATCH(DMI_BOARD_NAME, "098Ch"),
+		},
+	},
+	{ }
+};
+
+struct prt_quirk {
+	struct dmi_system_id	*system;
+	unsigned int		segment;
+	unsigned int		bus;
+	unsigned int		device;
+	unsigned char		pin;
+	char			*source;	/* according to BIOS */
+	char			*actual_source;
+};
+
+/*
+ * These systems have incorrect _PRT entries.  The BIOS claims the PCI
+ * interrupt at the listed segment/bus/device/pin is connected to the first
+ * link device, but it is actually connected to the second.
+ */
+static struct prt_quirk prt_quirks[] = {
+	{ medion_md9580, 0, 0, 9, 'A',
+		"\\_SB_.PCI0.ISA.LNKA",
+		"\\_SB_.PCI0.ISA.LNKB"},
+	{ dell_optiplex, 0, 0, 0xd, 'A',
+		"\\_SB_.LNKB",
+		"\\_SB_.LNKA"},
+	{ hp_t5710, 0, 0, 1, 'A',
+		"\\_SB_.PCI0.LNK1",
+		"\\_SB_.PCI0.LNK3"},
+};
+
+static void
+do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
+{
+	int i;
+	struct prt_quirk *quirk;
+
+	for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) {
+		quirk = &prt_quirks[i];
+
+		/* All current quirks involve link devices, not GSIs */
+		if (!prt->source)
+			continue;
+
+		if (dmi_check_system(quirk->system) &&
+		    entry->id.segment == quirk->segment &&
+		    entry->id.bus == quirk->bus &&
+		    entry->id.device == quirk->device &&
+		    entry->pin + 'A' == quirk->pin &&
+		    !strcmp(prt->source, quirk->source) &&
+		    strlen(prt->source) >= strlen(quirk->actual_source)) {
+			printk(KERN_WARNING PREFIX "firmware reports "
+				"%04x:%02x:%02x[%c] connected to %s; "
+				"changing to %s\n",
+				entry->id.segment, entry->id.bus,
+				entry->id.device, 'A' + entry->pin,
+				prt->source, quirk->actual_source);
+			strcpy(prt->source, quirk->actual_source);
+		}
+	}
+}
+
 static int
 static int
 acpi_pci_irq_add_entry(acpi_handle handle,
 acpi_pci_irq_add_entry(acpi_handle handle,
 		       int segment, int bus, struct acpi_pci_routing_table *prt)
 		       int segment, int bus, struct acpi_pci_routing_table *prt)
@@ -96,6 +192,8 @@ acpi_pci_irq_add_entry(acpi_handle handle,
 	entry->id.function = prt->address & 0xFFFF;
 	entry->id.function = prt->address & 0xFFFF;
 	entry->pin = prt->pin;
 	entry->pin = prt->pin;
 
 
+	do_prt_fixups(entry, prt);
+
 	/*
 	/*
 	 * Type 1: Dynamic
 	 * Type 1: Dynamic
 	 * ---------------
 	 * ---------------

+ 1 - 1
drivers/acpi/pci_root.c

@@ -184,7 +184,7 @@ static void acpi_pci_bridge_scan(struct acpi_device *device)
 		}
 		}
 }
 }
 
 
-static int acpi_pci_root_add(struct acpi_device *device)
+static int __devinit acpi_pci_root_add(struct acpi_device *device)
 {
 {
 	int result = 0;
 	int result = 0;
 	struct acpi_pci_root *root = NULL;
 	struct acpi_pci_root *root = NULL;

+ 14 - 11
drivers/acpi/processor_core.c

@@ -840,17 +840,19 @@ static int is_processor_present(acpi_handle handle)
 
 
 
 
 	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
 	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-	/*
-	 * if a processor object does not have an _STA object,
-	 * OSPM assumes that the processor is present.
-	 */
-	if (status == AE_NOT_FOUND)
-		return 1;
 
 
 	if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
 	if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
 		return 1;
 		return 1;
 
 
-	ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present"));
+	/*
+	 * _STA is mandatory for a processor that supports hot plug
+	 */
+	if (status == AE_NOT_FOUND)
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"Processor does not support hot plug\n"));
+	else
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Processor Device is not present"));
 	return 0;
 	return 0;
 }
 }
 
 
@@ -886,8 +888,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
 	return 0;
 	return 0;
 }
 }
 
 
-static void
-acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
+static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
+						u32 event, void *data)
 {
 {
 	struct acpi_processor *pr;
 	struct acpi_processor *pr;
 	struct acpi_device *device = NULL;
 	struct acpi_device *device = NULL;
@@ -897,9 +899,10 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
 	switch (event) {
 	switch (event) {
 	case ACPI_NOTIFY_BUS_CHECK:
 	case ACPI_NOTIFY_BUS_CHECK:
 	case ACPI_NOTIFY_DEVICE_CHECK:
 	case ACPI_NOTIFY_DEVICE_CHECK:
-		printk("Processor driver received %s event\n",
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+		"Processor driver received %s event\n",
 		       (event == ACPI_NOTIFY_BUS_CHECK) ?
 		       (event == ACPI_NOTIFY_BUS_CHECK) ?
-		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
+		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));
 
 
 		if (!is_processor_present(handle))
 		if (!is_processor_present(handle))
 			break;
 			break;

+ 3 - 2
drivers/acpi/scan.c

@@ -609,7 +609,8 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
 	status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);
 	status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);
 	if (ACPI_SUCCESS(status)) {
 	if (ACPI_SUCCESS(status)) {
 		obj = buffer.pointer;
 		obj = buffer.pointer;
-		status = acpi_get_handle(NULL, obj->string.pointer, ejd);
+		status = acpi_get_handle(ACPI_ROOT_OBJECT, obj->string.pointer,
+					 ejd);
 		kfree(buffer.pointer);
 		kfree(buffer.pointer);
 	}
 	}
 	return status;
 	return status;
@@ -966,7 +967,7 @@ static void acpi_device_set_id(struct acpi_device *device,
 	case ACPI_BUS_TYPE_DEVICE:
 	case ACPI_BUS_TYPE_DEVICE:
 		status = acpi_get_object_info(handle, &buffer);
 		status = acpi_get_object_info(handle, &buffer);
 		if (ACPI_FAILURE(status)) {
 		if (ACPI_FAILURE(status)) {
-			printk(KERN_ERR PREFIX "%s: Error reading device info\n", __FUNCTION__);
+			printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
 			return;
 			return;
 		}
 		}
 
 

+ 1 - 1
drivers/acpi/sleep/main.c

@@ -504,7 +504,7 @@ static void acpi_power_off_prepare(void)
 static void acpi_power_off(void)
 static void acpi_power_off(void)
 {
 {
 	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
 	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
-	printk("%s called\n", __FUNCTION__);
+	printk("%s called\n", __func__);
 	local_irq_disable();
 	local_irq_disable();
 	acpi_enable_wakeup_device(ACPI_STATE_S5);
 	acpi_enable_wakeup_device(ACPI_STATE_S5);
 	acpi_enter_sleep_state(ACPI_STATE_S5);
 	acpi_enter_sleep_state(ACPI_STATE_S5);

+ 1 - 1
drivers/acpi/system.c

@@ -319,7 +319,7 @@ void acpi_irq_stats_init(void)
 		goto fail;
 		goto fail;
 
 
 	for (i = 0; i < num_counters; ++i) {
 	for (i = 0; i < num_counters; ++i) {
-		char buffer[10];
+		char buffer[12];
 		char *name;
 		char *name;
 
 
 		if (i < num_gpes)
 		if (i < num_gpes)

+ 7 - 5
drivers/acpi/thermal.c

@@ -879,6 +879,8 @@ static void acpi_thermal_check(void *data)
 }
 }
 
 
 /* sys I/F for generic thermal sysfs support */
 /* sys I/F for generic thermal sysfs support */
+#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
+
 static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
 static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
 {
 {
 	struct acpi_thermal *tz = thermal->devdata;
 	struct acpi_thermal *tz = thermal->devdata;
@@ -886,7 +888,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
 	if (!tz)
 	if (!tz)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(tz->temperature));
+	return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature));
 }
 }
 
 
 static const char enabled[] = "kernel";
 static const char enabled[] = "kernel";
@@ -980,21 +982,21 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
 
 	if (tz->trips.critical.flags.valid) {
 	if (tz->trips.critical.flags.valid) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 				tz->trips.critical.temperature));
 				tz->trips.critical.temperature));
 		trip--;
 		trip--;
 	}
 	}
 
 
 	if (tz->trips.hot.flags.valid) {
 	if (tz->trips.hot.flags.valid) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 					tz->trips.hot.temperature));
 					tz->trips.hot.temperature));
 		trip--;
 		trip--;
 	}
 	}
 
 
 	if (tz->trips.passive.flags.valid) {
 	if (tz->trips.passive.flags.valid) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 					tz->trips.passive.temperature));
 					tz->trips.passive.temperature));
 		trip--;
 		trip--;
 	}
 	}
@@ -1002,7 +1004,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
 		tz->trips.active[i].flags.valid; i++) {
 		tz->trips.active[i].flags.valid; i++) {
 		if (!trip)
 		if (!trip)
-			return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+			return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
 					tz->trips.active[i].temperature));
 					tz->trips.active[i].temperature));
 		trip--;
 		trip--;
 	}
 	}

+ 7 - 0
drivers/acpi/toshiba_acpi.c

@@ -99,6 +99,13 @@ MODULE_LICENSE("GPL");
 #define HCI_VIDEO_OUT_CRT		0x2
 #define HCI_VIDEO_OUT_CRT		0x2
 #define HCI_VIDEO_OUT_TV		0x4
 #define HCI_VIDEO_OUT_TV		0x4
 
 
+static const struct acpi_device_id toshiba_device_ids[] = {
+	{"TOS6200", 0},
+	{"TOS1900", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
+
 /* utility
 /* utility
  */
  */
 
 

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

@@ -109,7 +109,7 @@ void acpi_ut_track_stack_ptr(void)
  * RETURN:      Updated pointer to the function name
  * RETURN:      Updated pointer to the function name
  *
  *
  * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
  * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
- *              This allows compiler macros such as __FUNCTION__ to be used
+ *              This allows compiler macros such as __func__ to be used
  *              with no change to the debug output.
  *              with no change to the debug output.
  *
  *
  ******************************************************************************/
  ******************************************************************************/

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

@@ -432,7 +432,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
 	 * element -- which is legal)
 	 * element -- which is legal)
 	 */
 	 */
 	if (!internal_object) {
 	if (!internal_object) {
-		*obj_length = 0;
+		*obj_length = sizeof(union acpi_object);
 		return_ACPI_STATUS(AE_OK);
 		return_ACPI_STATUS(AE_OK);
 	}
 	}
 
 

+ 6 - 0
drivers/acpi/utils.c

@@ -407,6 +407,12 @@ acpi_evaluate_reference(acpi_handle handle,
 			break;
 			break;
 		}
 		}
 
 
+		if (!element->reference.handle) {
+			printk(KERN_WARNING PREFIX "Invalid reference in"
+			       " package %s\n", pathname);
+			status = AE_NULL_ENTRY;
+			break;
+		}
 		/* Get the  acpi_handle. */
 		/* Get the  acpi_handle. */
 
 
 		list->handles[i] = element->reference.handle;
 		list->handles[i] = element->reference.handle;

+ 2 - 2
drivers/acpi/video.c

@@ -713,7 +713,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
 
 	kfree(obj);
 	kfree(obj);
 
 
-	if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){
+	if (device->cap._BCL && device->cap._BCM && max_level > 0) {
 		int result;
 		int result;
 		static int count = 0;
 		static int count = 0;
 		char *name;
 		char *name;
@@ -1201,7 +1201,7 @@ static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
 	if (!video)
 	if (!video)
 		goto end;
 		goto end;
 
 
-	printk(KERN_INFO PREFIX "Please implement %s\n", __FUNCTION__);
+	printk(KERN_INFO PREFIX "Please implement %s\n", __func__);
 	seq_printf(seq, "<TODO>\n");
 	seq_printf(seq, "<TODO>\n");
 
 
       end:
       end:

+ 6 - 4
drivers/acpi/wmi.c

@@ -293,7 +293,7 @@ struct acpi_buffer *out)
 {
 {
 	struct guid_block *block = NULL;
 	struct guid_block *block = NULL;
 	struct wmi_block *wblock = NULL;
 	struct wmi_block *wblock = NULL;
-	acpi_handle handle;
+	acpi_handle handle, wc_handle;
 	acpi_status status, wc_status = AE_ERROR;
 	acpi_status status, wc_status = AE_ERROR;
 	struct acpi_object_list input, wc_input;
 	struct acpi_object_list input, wc_input;
 	union acpi_object wc_params[1], wq_params[1];
 	union acpi_object wc_params[1], wq_params[1];
@@ -338,8 +338,10 @@ struct acpi_buffer *out)
 		 * expensive, but have no corresponding WCxx method. So we
 		 * expensive, but have no corresponding WCxx method. So we
 		 * should not fail if this happens.
 		 * should not fail if this happens.
 		 */
 		 */
-		wc_status = acpi_evaluate_object(handle, wc_method,
-			&wc_input, NULL);
+		wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
+		if (ACPI_SUCCESS(wc_status))
+			wc_status = acpi_evaluate_object(handle, wc_method,
+				&wc_input, NULL);
 	}
 	}
 
 
 	strcpy(method, "WQ");
 	strcpy(method, "WQ");
@@ -351,7 +353,7 @@ struct acpi_buffer *out)
 	 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
 	 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
 	 * the WQxx method failed - we should disable collection anyway.
 	 * the WQxx method failed - we should disable collection anyway.
 	 */
 	 */
-	if ((block->flags & ACPI_WMI_EXPENSIVE) && wc_status) {
+	if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
 		wc_params[0].integer.value = 0;
 		wc_params[0].integer.value = 0;
 		status = acpi_evaluate_object(handle,
 		status = acpi_evaluate_object(handle,
 		wc_method, &wc_input, NULL);
 		wc_method, &wc_input, NULL);

+ 1 - 0
drivers/misc/Kconfig

@@ -108,6 +108,7 @@ config ACER_WMI
 	depends on ACPI
 	depends on ACPI
 	depends on LEDS_CLASS
 	depends on LEDS_CLASS
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on BACKLIGHT_CLASS_DEVICE
+	depends on SERIO_I8042
 	select ACPI_WMI
 	select ACPI_WMI
 	---help---
 	---help---
 	  This is a driver for newer Acer (and Wistron) laptops. It adds
 	  This is a driver for newer Acer (and Wistron) laptops. It adds

+ 31 - 13
drivers/misc/acer-wmi.c

@@ -217,6 +217,15 @@ static struct dmi_system_id acer_quirks[] = {
 		},
 		},
 		.driver_data = &quirk_acer_travelmate_2490,
 		.driver_data = &quirk_acer_travelmate_2490,
 	},
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer Aspire 3610",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3610"),
+		},
+		.driver_data = &quirk_acer_travelmate_2490,
+	},
 	{
 	{
 		.callback = dmi_matched,
 		.callback = dmi_matched,
 		.ident = "Acer Aspire 5100",
 		.ident = "Acer Aspire 5100",
@@ -226,6 +235,15 @@ static struct dmi_system_id acer_quirks[] = {
 		},
 		},
 		.driver_data = &quirk_acer_travelmate_2490,
 		.driver_data = &quirk_acer_travelmate_2490,
 	},
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "Acer Aspire 5610",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
+		},
+		.driver_data = &quirk_acer_travelmate_2490,
+	},
 	{
 	{
 		.callback = dmi_matched,
 		.callback = dmi_matched,
 		.ident = "Acer Aspire 5630",
 		.ident = "Acer Aspire 5630",
@@ -761,11 +779,11 @@ enum led_brightness value)
 }
 }
 
 
 static struct led_classdev mail_led = {
 static struct led_classdev mail_led = {
-	.name = "acer-mail:green",
+	.name = "acer-wmi::mail",
 	.brightness_set = mail_led_set,
 	.brightness_set = mail_led_set,
 };
 };
 
 
-static int __init acer_led_init(struct device *dev)
+static int __devinit acer_led_init(struct device *dev)
 {
 {
 	return led_classdev_register(dev, &mail_led);
 	return led_classdev_register(dev, &mail_led);
 }
 }
@@ -798,7 +816,7 @@ static struct backlight_ops acer_bl_ops = {
 	.update_status = update_bl_status,
 	.update_status = update_bl_status,
 };
 };
 
 
-static int __init acer_backlight_init(struct device *dev)
+static int __devinit acer_backlight_init(struct device *dev)
 {
 {
 	struct backlight_device *bd;
 	struct backlight_device *bd;
 
 
@@ -817,7 +835,7 @@ static int __init acer_backlight_init(struct device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
-static void __exit acer_backlight_exit(void)
+static void acer_backlight_exit(void)
 {
 {
 	backlight_device_unregister(acer_backlight_device);
 	backlight_device_unregister(acer_backlight_device);
 }
 }
@@ -1052,11 +1070,12 @@ static int __init acer_wmi_init(void)
 
 
 	if (wmi_has_guid(WMID_GUID2) && interface) {
 	if (wmi_has_guid(WMID_GUID2) && interface) {
 		if (ACPI_FAILURE(WMID_set_capabilities())) {
 		if (ACPI_FAILURE(WMID_set_capabilities())) {
-			printk(ACER_ERR "Unable to detect available devices\n");
+			printk(ACER_ERR "Unable to detect available WMID "
+					"devices\n");
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 	} else if (!wmi_has_guid(WMID_GUID2) && interface) {
 	} else if (!wmi_has_guid(WMID_GUID2) && interface) {
-		printk(ACER_ERR "Unable to detect available devices\n");
+		printk(ACER_ERR "No WMID device detection method found\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -1064,21 +1083,20 @@ static int __init acer_wmi_init(void)
 		interface = &AMW0_interface;
 		interface = &AMW0_interface;
 
 
 		if (ACPI_FAILURE(AMW0_set_capabilities())) {
 		if (ACPI_FAILURE(AMW0_set_capabilities())) {
-			printk(ACER_ERR "Unable to detect available devices\n");
+			printk(ACER_ERR "Unable to detect available AMW0 "
+					"devices\n");
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}
 	}
 	}
 
 
-	if (wmi_has_guid(AMW0_GUID1)) {
-		if (ACPI_FAILURE(AMW0_find_mailled()))
-			printk(ACER_ERR "Unable to detect mail LED\n");
-	}
+	if (wmi_has_guid(AMW0_GUID1))
+		AMW0_find_mailled();
 
 
 	find_quirks();
 	find_quirks();
 
 
 	if (!interface) {
 	if (!interface) {
-		printk(ACER_ERR "No or unsupported WMI interface, unable to ");
-		printk(KERN_CONT "load.\n");
+		printk(ACER_ERR "No or unsupported WMI interface, unable to "
+				"load\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 

+ 1 - 1
drivers/misc/sony-laptop.c

@@ -315,7 +315,7 @@ static void sony_laptop_report_input_event(u8 event)
 		break;
 		break;
 
 
 	default:
 	default:
-		if (event > ARRAY_SIZE(sony_laptop_input_index)) {
+		if (event >= ARRAY_SIZE(sony_laptop_input_index)) {
 			dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
 			dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
 			break;
 			break;
 		}
 		}

+ 16 - 8
drivers/pci/pci-acpi.c

@@ -272,21 +272,29 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 {
 {
 	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
 	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
 	acpi_handle tmp;
 	acpi_handle tmp;
-	static int state_conv[] = {
-		[0] = 0,
-		[1] = 1,
-		[2] = 2,
-		[3] = 3,
-		[4] = 3
+	static const u8 state_conv[] = {
+		[PCI_D0] = ACPI_STATE_D0,
+		[PCI_D1] = ACPI_STATE_D1,
+		[PCI_D2] = ACPI_STATE_D2,
+		[PCI_D3hot] = ACPI_STATE_D3,
+		[PCI_D3cold] = ACPI_STATE_D3
 	};
 	};
-	int acpi_state = state_conv[(int __force) state];
 
 
 	if (!handle)
 	if (!handle)
 		return -ENODEV;
 		return -ENODEV;
 	/* If the ACPI device has _EJ0, ignore the device */
 	/* If the ACPI device has _EJ0, ignore the device */
 	if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
 	if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
 		return 0;
 		return 0;
-	return acpi_bus_set_power(handle, acpi_state);
+
+	switch (state) {
+	case PCI_D0:
+	case PCI_D1:
+	case PCI_D2:
+	case PCI_D3hot:
+	case PCI_D3cold:
+		return acpi_bus_set_power(handle, state_conv[state]);
+	}
+	return -EINVAL;
 }
 }
 
 
 
 

+ 1 - 0
drivers/thermal/Kconfig

@@ -4,6 +4,7 @@
 
 
 menuconfig THERMAL
 menuconfig THERMAL
 	bool "Generic Thermal sysfs driver"
 	bool "Generic Thermal sysfs driver"
+	select HWMON
 	default y
 	default y
 	help
 	help
 	  Generic Thermal Sysfs driver offers a generic mechanism for
 	  Generic Thermal Sysfs driver offers a generic mechanism for

+ 143 - 26
drivers/thermal/thermal.c

@@ -30,8 +30,10 @@
 #include <linux/idr.h>
 #include <linux/idr.h>
 #include <linux/thermal.h>
 #include <linux/thermal.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 
 
-MODULE_AUTHOR("Zhang Rui")
+MODULE_AUTHOR("Zhang Rui");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_DESCRIPTION("Generic thermal management sysfs support");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
@@ -56,6 +58,9 @@ static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_cdev_list);
 static LIST_HEAD(thermal_cdev_list);
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(thermal_list_lock);
 
 
+static struct device *thermal_hwmon;
+#define MAX_THERMAL_ZONES	10
+
 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
 static int get_idr(struct idr *idr, struct mutex *lock, int *id)
 {
 {
 	int err;
 	int err;
@@ -87,7 +92,67 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
 		mutex_unlock(lock);
 		mutex_unlock(lock);
 }
 }
 
 
-/* sys I/F for thermal zone */
+/* hwmon sys I/F*/
+static ssize_t
+name_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "thermal_sys_class\n");
+}
+
+static ssize_t
+temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct thermal_zone_device *tz;
+	struct sensor_device_attribute *sensor_attr
+						= to_sensor_dev_attr(attr);
+
+	list_for_each_entry(tz, &thermal_tz_list, node)
+		if (tz->id == sensor_attr->index)
+			return tz->ops->get_temp(tz, buf);
+
+	return -ENODEV;
+}
+
+static ssize_t
+temp_crit_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct thermal_zone_device *tz;
+	struct sensor_device_attribute *sensor_attr
+						= to_sensor_dev_attr(attr);
+
+	list_for_each_entry(tz, &thermal_tz_list, node)
+		if (tz->id == sensor_attr->index)
+			return tz->ops->get_trip_temp(tz, 0, buf);
+
+	return -ENODEV;
+}
+
+static DEVICE_ATTR(name, 0444, name_show, NULL);
+static struct sensor_device_attribute sensor_attrs[] = {
+	SENSOR_ATTR(temp1_input, 0444, temp_input_show, NULL, 0),
+	SENSOR_ATTR(temp1_crit, 0444, temp_crit_show, NULL, 0),
+	SENSOR_ATTR(temp2_input, 0444, temp_input_show, NULL, 1),
+	SENSOR_ATTR(temp2_crit, 0444, temp_crit_show, NULL, 1),
+	SENSOR_ATTR(temp3_input, 0444, temp_input_show, NULL, 2),
+	SENSOR_ATTR(temp3_crit, 0444, temp_crit_show, NULL, 2),
+	SENSOR_ATTR(temp4_input, 0444, temp_input_show, NULL, 3),
+	SENSOR_ATTR(temp4_crit, 0444, temp_crit_show, NULL, 3),
+	SENSOR_ATTR(temp5_input, 0444, temp_input_show, NULL, 4),
+	SENSOR_ATTR(temp5_crit, 0444, temp_crit_show, NULL, 4),
+	SENSOR_ATTR(temp6_input, 0444, temp_input_show, NULL, 5),
+	SENSOR_ATTR(temp6_crit, 0444, temp_crit_show, NULL, 5),
+	SENSOR_ATTR(temp7_input, 0444, temp_input_show, NULL, 6),
+	SENSOR_ATTR(temp7_crit, 0444, temp_crit_show, NULL, 6),
+	SENSOR_ATTR(temp8_input, 0444, temp_input_show, NULL, 7),
+	SENSOR_ATTR(temp8_crit, 0444, temp_crit_show, NULL, 7),
+	SENSOR_ATTR(temp9_input, 0444, temp_input_show, NULL, 8),
+	SENSOR_ATTR(temp9_crit, 0444, temp_crit_show, NULL, 8),
+	SENSOR_ATTR(temp10_input, 0444, temp_input_show, NULL, 9),
+	SENSOR_ATTR(temp10_crit, 0444, temp_crit_show, NULL, 9),
+};
+
+/* thermal zone sys I/F */
 
 
 #define to_thermal_zone(_dev) \
 #define to_thermal_zone(_dev) \
 	container_of(_dev, struct thermal_zone_device, device)
 	container_of(_dev, struct thermal_zone_device, device)
@@ -214,7 +279,7 @@ do {	\
 	device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]);	\
 	device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]);	\
 } while (0)
 } while (0)
 
 
-/* sys I/F for cooling device */
+/* cooling device sys I/F */
 #define to_cooling_device(_dev)	\
 #define to_cooling_device(_dev)	\
 	container_of(_dev, struct thermal_cooling_device, device)
 	container_of(_dev, struct thermal_cooling_device, device)
 
 
@@ -447,6 +512,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
 	struct thermal_zone_device *pos;
 	struct thermal_zone_device *pos;
 	int result;
 	int result;
 
 
+	if (!type)
+		return ERR_PTR(-EINVAL);
+
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 		return ERR_PTR(-EINVAL);
 		return ERR_PTR(-EINVAL);
 
 
@@ -477,11 +545,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
 	}
 	}
 
 
 	/* sys I/F */
 	/* sys I/F */
-	if (type) {
-		result = device_create_file(&cdev->device, &dev_attr_cdev_type);
-		if (result)
-			goto unregister;
-	}
+	result = device_create_file(&cdev->device, &dev_attr_cdev_type);
+	if (result)
+		goto unregister;
 
 
 	result = device_create_file(&cdev->device, &dev_attr_max_state);
 	result = device_create_file(&cdev->device, &dev_attr_max_state);
 	if (result)
 	if (result)
@@ -547,8 +613,8 @@ void thermal_cooling_device_unregister(struct
 		tz->ops->unbind(tz, cdev);
 		tz->ops->unbind(tz, cdev);
 	}
 	}
 	mutex_unlock(&thermal_list_lock);
 	mutex_unlock(&thermal_list_lock);
-	if (cdev->type[0])
-		device_remove_file(&cdev->device, &dev_attr_cdev_type);
+
+	device_remove_file(&cdev->device, &dev_attr_cdev_type);
 	device_remove_file(&cdev->device, &dev_attr_max_state);
 	device_remove_file(&cdev->device, &dev_attr_max_state);
 	device_remove_file(&cdev->device, &dev_attr_cur_state);
 	device_remove_file(&cdev->device, &dev_attr_cur_state);
 
 
@@ -580,6 +646,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 	int result;
 	int result;
 	int count;
 	int count;
 
 
+	if (!type)
+		return ERR_PTR(-EINVAL);
+
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 	if (strlen(type) >= THERMAL_NAME_LENGTH)
 		return ERR_PTR(-EINVAL);
 		return ERR_PTR(-EINVAL);
 
 
@@ -601,6 +670,13 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 		kfree(tz);
 		kfree(tz);
 		return ERR_PTR(result);
 		return ERR_PTR(result);
 	}
 	}
+	if (tz->id >= MAX_THERMAL_ZONES) {
+		printk(KERN_ERR PREFIX
+			"Too many thermal zones\n");
+		release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id);
+		kfree(tz);
+		return ERR_PTR(-EINVAL);
+	}
 
 
 	strcpy(tz->type, type);
 	strcpy(tz->type, type);
 	tz->ops = ops;
 	tz->ops = ops;
@@ -615,13 +691,28 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
 		return ERR_PTR(result);
 		return ERR_PTR(result);
 	}
 	}
 
 
-	/* sys I/F */
-	if (type) {
-		result = device_create_file(&tz->device, &dev_attr_type);
-		if (result)
-			goto unregister;
+	/* hwmon sys I/F */
+	result = device_create_file(thermal_hwmon,
+					&sensor_attrs[tz->id * 2].dev_attr);
+	if (result)
+		goto unregister;
+
+	if (trips > 0) {
+		char buf[40];
+		result = tz->ops->get_trip_type(tz, 0, buf);
+		if (result > 0 && !strcmp(buf, "critical\n")) {
+			result = device_create_file(thermal_hwmon,
+					&sensor_attrs[tz->id * 2 + 1].dev_attr);
+			if (result)
+				goto unregister;
+		}
 	}
 	}
 
 
+	/* sys I/F */
+	result = device_create_file(&tz->device, &dev_attr_type);
+	if (result)
+		goto unregister;
+
 	result = device_create_file(&tz->device, &dev_attr_temp);
 	result = device_create_file(&tz->device, &dev_attr_temp);
 	if (result)
 	if (result)
 		goto unregister;
 		goto unregister;
@@ -687,8 +778,17 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 		    tz->ops->unbind(tz, cdev);
 		    tz->ops->unbind(tz, cdev);
 	mutex_unlock(&thermal_list_lock);
 	mutex_unlock(&thermal_list_lock);
 
 
-	if (tz->type[0])
-		device_remove_file(&tz->device, &dev_attr_type);
+	device_remove_file(thermal_hwmon,
+				&sensor_attrs[tz->id * 2].dev_attr);
+	if (tz->trips > 0) {
+		char buf[40];
+		if (tz->ops->get_trip_type(tz, 0, buf) > 0)
+			if (!strcmp(buf, "critical\n"))
+				device_remove_file(thermal_hwmon,
+				&sensor_attrs[tz->id * 2 + 1].dev_attr);
+	}
+
+	device_remove_file(&tz->device, &dev_attr_type);
 	device_remove_file(&tz->device, &dev_attr_temp);
 	device_remove_file(&tz->device, &dev_attr_temp);
 	if (tz->ops->get_mode)
 	if (tz->ops->get_mode)
 		device_remove_file(&tz->device, &dev_attr_mode);
 		device_remove_file(&tz->device, &dev_attr_mode);
@@ -705,6 +805,19 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 
 
 EXPORT_SYMBOL(thermal_zone_device_unregister);
 EXPORT_SYMBOL(thermal_zone_device_unregister);
 
 
+static void thermal_exit(void)
+{
+	if (thermal_hwmon) {
+		device_remove_file(thermal_hwmon, &dev_attr_name);
+		hwmon_device_unregister(thermal_hwmon);
+	}
+	class_unregister(&thermal_class);
+	idr_destroy(&thermal_tz_idr);
+	idr_destroy(&thermal_cdev_idr);
+	mutex_destroy(&thermal_idr_lock);
+	mutex_destroy(&thermal_list_lock);
+}
+
 static int __init thermal_init(void)
 static int __init thermal_init(void)
 {
 {
 	int result = 0;
 	int result = 0;
@@ -716,16 +829,20 @@ static int __init thermal_init(void)
 		mutex_destroy(&thermal_idr_lock);
 		mutex_destroy(&thermal_idr_lock);
 		mutex_destroy(&thermal_list_lock);
 		mutex_destroy(&thermal_list_lock);
 	}
 	}
-	return result;
-}
 
 
-static void __exit thermal_exit(void)
-{
-	class_unregister(&thermal_class);
-	idr_destroy(&thermal_tz_idr);
-	idr_destroy(&thermal_cdev_idr);
-	mutex_destroy(&thermal_idr_lock);
-	mutex_destroy(&thermal_list_lock);
+	thermal_hwmon = hwmon_device_register(NULL);
+	if (IS_ERR(thermal_hwmon)) {
+		result = PTR_ERR(thermal_hwmon);
+		thermal_hwmon = NULL;
+		printk(KERN_ERR PREFIX
+			"unable to register hwmon device\n");
+		thermal_exit();
+		return result;
+	}
+
+	result = device_create_file(thermal_hwmon, &dev_attr_name);
+
+	return result;
 }
 }
 
 
 subsys_initcall(thermal_init);
 subsys_initcall(thermal_init);

+ 1 - 1
kernel/power/Kconfig

@@ -190,7 +190,7 @@ config APM_EMULATION
 	  notification of APM "events" (e.g. battery status change).
 	  notification of APM "events" (e.g. battery status change).
 
 
 	  In order to use APM, you will need supporting software. For location
 	  In order to use APM, you will need supporting software. For location
-	  and more information, read <file:Documentation/pm.txt> and the
+	  and more information, read <file:Documentation/power/pm.txt> and the
 	  Battery Powered Linux mini-HOWTO, available from
 	  Battery Powered Linux mini-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>.
 	  <http://www.tldp.org/docs.html#howto>.
 
 

+ 34 - 7
kernel/power/snapshot.c

@@ -447,7 +447,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
  *	of @bm->cur_zone_bm are updated.
  *	of @bm->cur_zone_bm are updated.
  */
  */
 
 
-static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
+static int memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
 				void **addr, unsigned int *bit_nr)
 				void **addr, unsigned int *bit_nr)
 {
 {
 	struct zone_bitmap *zone_bm;
 	struct zone_bitmap *zone_bm;
@@ -461,7 +461,8 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
 		while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) {
 		while (pfn < zone_bm->start_pfn || pfn >= zone_bm->end_pfn) {
 			zone_bm = zone_bm->next;
 			zone_bm = zone_bm->next;
 
 
-			BUG_ON(!zone_bm);
+			if (!zone_bm)
+				return -EFAULT;
 		}
 		}
 		bm->cur.zone_bm = zone_bm;
 		bm->cur.zone_bm = zone_bm;
 	}
 	}
@@ -479,23 +480,40 @@ static void memory_bm_find_bit(struct memory_bitmap *bm, unsigned long pfn,
 	pfn -= bb->start_pfn;
 	pfn -= bb->start_pfn;
 	*bit_nr = pfn % BM_BITS_PER_CHUNK;
 	*bit_nr = pfn % BM_BITS_PER_CHUNK;
 	*addr = bb->data + pfn / BM_BITS_PER_CHUNK;
 	*addr = bb->data + pfn / BM_BITS_PER_CHUNK;
+	return 0;
 }
 }
 
 
 static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
 static void memory_bm_set_bit(struct memory_bitmap *bm, unsigned long pfn)
 {
 {
 	void *addr;
 	void *addr;
 	unsigned int bit;
 	unsigned int bit;
+	int error;
 
 
-	memory_bm_find_bit(bm, pfn, &addr, &bit);
+	error = memory_bm_find_bit(bm, pfn, &addr, &bit);
+	BUG_ON(error);
 	set_bit(bit, addr);
 	set_bit(bit, addr);
 }
 }
 
 
+static int mem_bm_set_bit_check(struct memory_bitmap *bm, unsigned long pfn)
+{
+	void *addr;
+	unsigned int bit;
+	int error;
+
+	error = memory_bm_find_bit(bm, pfn, &addr, &bit);
+	if (!error)
+		set_bit(bit, addr);
+	return error;
+}
+
 static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
 static void memory_bm_clear_bit(struct memory_bitmap *bm, unsigned long pfn)
 {
 {
 	void *addr;
 	void *addr;
 	unsigned int bit;
 	unsigned int bit;
+	int error;
 
 
-	memory_bm_find_bit(bm, pfn, &addr, &bit);
+	error = memory_bm_find_bit(bm, pfn, &addr, &bit);
+	BUG_ON(error);
 	clear_bit(bit, addr);
 	clear_bit(bit, addr);
 }
 }
 
 
@@ -503,8 +521,10 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
 {
 {
 	void *addr;
 	void *addr;
 	unsigned int bit;
 	unsigned int bit;
+	int error;
 
 
-	memory_bm_find_bit(bm, pfn, &addr, &bit);
+	error = memory_bm_find_bit(bm, pfn, &addr, &bit);
+	BUG_ON(error);
 	return test_bit(bit, addr);
 	return test_bit(bit, addr);
 }
 }
 
 
@@ -709,8 +729,15 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
 				region->end_pfn << PAGE_SHIFT);
 				region->end_pfn << PAGE_SHIFT);
 
 
 		for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
 		for (pfn = region->start_pfn; pfn < region->end_pfn; pfn++)
-			if (pfn_valid(pfn))
-				memory_bm_set_bit(bm, pfn);
+			if (pfn_valid(pfn)) {
+				/*
+				 * It is safe to ignore the result of
+				 * mem_bm_set_bit_check() here, since we won't
+				 * touch the PFNs for which the error is
+				 * returned anyway.
+				 */
+				mem_bm_set_bit_check(bm, pfn);
+			}
 	}
 	}
 }
 }