Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Mar 2008 20:13:47 +0000 (13:13 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Mar 2008 20:13:47 +0000 (13:13 -0700)
* '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
  ...

38 files changed:
Documentation/00-INDEX
Documentation/filesystems/proc.txt
Documentation/kernel-parameters.txt
Documentation/laptops/00-INDEX
Documentation/laptops/acer-wmi.txt
Documentation/laptops/laptop-mode.txt [moved from Documentation/laptop-mode.txt with 100% similarity]
Documentation/power/00-INDEX
Documentation/power/pm.txt [moved from Documentation/pm.txt with 99% similarity]
Documentation/power/pm_qos_interface.txt [moved from Documentation/pm_qos_interface.txt with 100% similarity]
Documentation/power/power_supply_class.txt [moved from Documentation/power_supply_class.txt with 100% similarity]
Documentation/thermal/sysfs-api.txt
arch/x86/Kconfig
drivers/acpi/Kconfig
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/ec.c
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_root.c
drivers/acpi/processor_core.c
drivers/acpi/scan.c
drivers/acpi/sleep/main.c
drivers/acpi/system.c
drivers/acpi/thermal.c
drivers/acpi/toshiba_acpi.c
drivers/acpi/utilities/utdebug.c
drivers/acpi/utilities/utobject.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/acpi/wmi.c
drivers/misc/Kconfig
drivers/misc/acer-wmi.c
drivers/misc/sony-laptop.c
drivers/pci/pci-acpi.c
drivers/thermal/Kconfig
drivers/thermal/thermal.c
kernel/power/Kconfig
kernel/power/snapshot.c

index 042073f656e53e01daff332e1e9ee500ad99efc0..fc8e7c7d182f5cbcc179fc5dec2575912ce46653 100644 (file)
@@ -225,8 +225,6 @@ kprobes.txt
        - documents the kernel probes debugging feature.
 kref.txt
        - docs on adding reference counters (krefs) to kernel objects.
-laptop-mode.txt
-       - how to conserve battery power using laptop-mode.
 laptops/
        - directory with laptop related info and laptop driver documentation.
 ldm.txt
@@ -301,12 +299,8 @@ pcmcia/
        - info on the Linux PCMCIA driver.
 pi-futex.txt
        - documentation on lightweight PI-futexes.
-pm.txt
-       - info on Linux power management support.
 pnp.txt
        - Linux Plug and Play documentation.
-power_supply_class.txt
-       - Tells userspace about battery, UPS, AC or DC power supply properties
 power/
        - directory with info on Linux PCI power management.
 powerpc/
index 5681e2fa1496167e6f876b6dab39e9605597a117..518ebe609e2b1c9392580c9ae840d5da4aa84e68 100644 (file)
@@ -1506,13 +1506,13 @@ laptop_mode
 -----------
 
 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 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
 ------------------
index 533e67febf813a18d6af172ac40fcf7c9e0def88..49318b99e581406b7ec32793560c01546e69402d 100644 (file)
@@ -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
                                strictly ACPI specification compliant.
 
-                       See also Documentation/pm.txt, pci=noacpi
+                       See also Documentation/power/pm.txt, pci=noacpi
 
        acpi_apic_instance=     [ACPI, IOAPIC]
                        Format: <int>
index 729c2c062e109ab0d57a5b8760d4a29821cb9943..ee5692b26dd4d629901cabc387e791c0576df243 100644 (file)
@@ -2,6 +2,8 @@
        - This file
 acer-wmi.txt
        - information on the Acer Laptop WMI Extras driver.
+laptop-mode.txt
+       - how to conserve battery power using laptop-mode.
 sony-laptop.txt
        - Sony Notebook Control Driver (SNC) Readme.
 sonypi.txt
index b06696329cffceccc0477a6fa38b0351fc9e013c..23df051dbf69f4a10c10cbbf82188b581c245e66 100644 (file)
@@ -48,7 +48,7 @@ DSDT.
 
 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.
 
@@ -169,7 +169,7 @@ can be added to acer-wmi.
 
 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
 be registered.
index 8db4e41a052d9a9df37bfa39dc5dda1a7b1d12a1..a55d7f1c836d7de2ad0b09b9ea2c138562db01a6 100644 (file)
@@ -14,6 +14,12 @@ notifiers.txt
        - Registering suspend notifiers in device drivers
 pci.txt
        - 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
        - How to get suspend to ram working (and debug it when it isn't)
 states.txt
similarity index 99%
rename from Documentation/pm.txt
rename to Documentation/power/pm.txt
index da8589a0e07df08b77ae15c5bb83f7800f9b2bdf..be841507e43fa0745f6c6eef55e06356ae725709 100644 (file)
@@ -108,7 +108,7 @@ void pm_unregister_all(pm_callback cback);
  *          EINVAL if the request is not supported
  *          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
- *          
+ *
  * Details: The device request callback will be called before the
  *          device/system enters a suspend state (ACPI D1-D3) or
  *          or after the device/system resumes from suspend (ACPI D0).
index ba9c2da5a8c200fbb6a27b84c7a2f85a441e979d..d9f28be75403cea53c07cfe8e965074a71037619 100644 (file)
@@ -143,10 +143,10 @@ type                              Strings which represent the thermal zone type.
                                This is given by thermal zone driver as part of registration.
                                Eg: "ACPI thermal zone" indicates it's a ACPI thermal device
                                RO
-                               Optional
+                               Required
 
 temp                           Current temperature as reported by thermal zone (sensor)
-                               Unit: degree Celsius
+                               Unit: millidegree Celsius
                                RO
                                Required
 
@@ -163,7 +163,7 @@ mode                                One of the predefined values in [kernel, user]
                                          charge of the thermal management.
 
 trip_point_[0-*]_temp          The temperature above which trip point will be fired
-                               Unit: degree Celsius
+                               Unit: millidegree Celsius
                                RO
                                Optional
 
@@ -193,7 +193,7 @@ type                                String which represents the type of device
                                eg. For memory controller device on intel_menlow platform:
                                this should be "Memory controller"
                                RO
-                               Optional
+                               Required
 
 max_state                      The maximum permissible cooling state of this cooling device.
                                RO
@@ -219,16 +219,16 @@ the sys I/F structure will be built like this:
 
 |thermal_zone1:
        |-----type:                     ACPI thermal zone
-       |-----temp:                     37
+       |-----temp:                     37000
        |-----mode:                     kernel
-       |-----trip_point_0_temp:        100
+       |-----trip_point_0_temp:        100000
        |-----trip_point_0_type:        critical
-       |-----trip_point_1_temp:        80
+       |-----trip_point_1_temp:        80000
        |-----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_trip_point:         1       /* cdev0 can be used for passive */
        |-----cdev1:                    --->/sys/class/thermal/cooling_device3
index 237fc128143d43fbe3c232de29cb47ffec331d90..6c70fed0f9a0f9e35cd027072a464b8c42b85434 100644 (file)
@@ -1259,7 +1259,7 @@ menuconfig APM
          machines with more than one CPU.
 
          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
          <http://www.tldp.org/docs.html#howto>.
 
index f688c214be0c67110df1d039be5566d3c7f59bfe..fbcaa069be86678f0a3725f5250f5c662d5e989b 100644 (file)
@@ -283,24 +283,23 @@ config ACPI_TOSHIBA
          If you have a legacy free Toshiba laptop (such as the Libretto L1
          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
-       default n 
        help
          This option supports a custom DSDT by linking it into the kernel.
          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
          declaration.
 
+         If unsure, don't enter a file name.
+
+config ACPI_CUSTOM_DSDT
+       bool
+       default ACPI_CUSTOM_DSDT_FILE != ""
+
 config ACPI_CUSTOM_DSDT_INITRD
        bool "Read Custom DSDT from initramfs"
        depends on BLK_DEV_INITRD
index ce3c0a2cbac4dc81e9c5ff2712b100ec8a942b46..5b6760e0f9571d20e34dcb47346c354ad6dff116 100644 (file)
@@ -776,7 +776,7 @@ static int __init acpi_init(void)
 
        acpi_kobj = kobject_create_and_add("acpi", firmware_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;
        }
 
index 24a7865a57cb2515c740fbee5d9b038ca3927630..6c5da83cdb6807be36db10253bd42c2c332c0402 100644 (file)
@@ -449,6 +449,7 @@ static int acpi_button_add(struct acpi_device *device)
        input->phys = button->phys;
        input->id.bustype = BUS_HOST;
        input->id.product = button->type;
+       input->dev.parent = &device->dev;
 
        switch (button->type) {
        case ACPI_BUTTON_TYPE_POWER:
index caf873c14bfb244a89ba9c322ada05c3c2b3c04e..e7e197e3a4ffce2151d61f5e6b48f89c98087dfa 100644 (file)
@@ -129,6 +129,7 @@ static struct acpi_ec {
        struct mutex lock;
        wait_queue_head_t wait;
        struct list_head list;
+       atomic_t irq_count;
        u8 handlers_installed;
 } *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;
 
+       atomic_set(&ec->irq_count, 0);
+
        if (unlikely(event == ACPI_EC_EVENT_OBF_1 &&
                     test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags)))
                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)) {
                        if (acpi_ec_check_status(ec, event))
                                goto end;
+                       msleep(5);
                }
        }
        pr_err(PREFIX "acpi_ec_wait timeout,"
@@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data)
        struct acpi_ec *ec = data;
 
        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);
        if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
                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->data_addr = ecdt_ptr->data.address;
                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 {
                /* This workaround is needed only on some broken machines,
                 * which require early EC, but fail to provide ECDT */
index 8edba7b678eb9d33493f422472dc16fdb4c6f84e..065819ba87c7ee5a6969674d3e654200b35f4da5 100644 (file)
@@ -1237,7 +1237,7 @@ int acpi_check_resource_conflict(struct resource *res)
 
        if (clash) {
                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"
                               " [0x%llx-0x%llx]\n",
                               acpi_enforce_resources == ENFORCE_RESOURCES_LAX
index 7f19859580c7efcbdf9675d6be44436573d0e8d6..7af414a3c63ee89f3ec0624d256437f9d74a2825 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 
+#include <linux/dmi.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -76,6 +77,101 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
        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
 acpi_pci_irq_add_entry(acpi_handle handle,
                       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->pin = prt->pin;
 
+       do_prt_fixups(entry, prt);
+
        /*
         * Type 1: Dynamic
         * ---------------
index f14ff1ffab29c24156d2cff92d75340460337745..c3fed31166b552761f2bb9c3b26ef2b7c3e47592 100644 (file)
@@ -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;
        struct acpi_pci_root *root = NULL;
index a3cc8a98255cf724248c7efbf749a912bc9ef4f1..36a68fa114e3e7b97b85585e40e3f74929110d79 100644 (file)
@@ -840,17 +840,19 @@ static int is_processor_present(acpi_handle handle)
 
 
        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))
                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;
 }
 
@@ -886,8 +888,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
        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_device *device = NULL;
@@ -897,9 +899,10 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
        switch (event) {
        case ACPI_NOTIFY_BUS_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) ?
-                      "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
+                      "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));
 
                if (!is_processor_present(handle))
                        break;
index 3fac011f9cf964082b463ef20913542ca9bce173..57570ac47803f4d590da5f8254547119ab10aec3 100644 (file)
@@ -609,7 +609,8 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd)
        status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);
        if (ACPI_SUCCESS(status)) {
                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);
        }
        return status;
@@ -966,7 +967,7 @@ static void acpi_device_set_id(struct acpi_device *device,
        case ACPI_BUS_TYPE_DEVICE:
                status = acpi_get_object_info(handle, &buffer);
                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;
                }
 
index 293a1cbb47c05776b543894bc32ee145de0153b7..d2f71a54726c5c988bdc680a892599966e0744df 100644 (file)
@@ -504,7 +504,7 @@ static void acpi_power_off_prepare(void)
 static void acpi_power_off(void)
 {
        /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
-       printk("%s called\n", __FUNCTION__);
+       printk("%s called\n", __func__);
        local_irq_disable();
        acpi_enable_wakeup_device(ACPI_STATE_S5);
        acpi_enter_sleep_state(ACPI_STATE_S5);
index 55cf4c05bb74edc7714ddb4a000b729395feb291..4749f379a915a4c4f6308f21b21de4205f399387 100644 (file)
@@ -319,7 +319,7 @@ void acpi_irq_stats_init(void)
                goto fail;
 
        for (i = 0; i < num_counters; ++i) {
-               char buffer[10];
+               char buffer[12];
                char *name;
 
                if (i < num_gpes)
index 8d4b79b4f933c631281e23ce8b602e3bcbbf3d9f..c4e00ac8ea855ac980b05b5e6bf60b8e52b5016b 100644 (file)
@@ -879,6 +879,8 @@ static void acpi_thermal_check(void *data)
 }
 
 /* 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)
 {
        struct acpi_thermal *tz = thermal->devdata;
@@ -886,7 +888,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
        if (!tz)
                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";
@@ -980,21 +982,21 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.critical.flags.valid) {
                if (!trip)
-                       return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
                                tz->trips.critical.temperature));
                trip--;
        }
 
        if (tz->trips.hot.flags.valid) {
                if (!trip)
-                       return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
                                        tz->trips.hot.temperature));
                trip--;
        }
 
        if (tz->trips.passive.flags.valid) {
                if (!trip)
-                       return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
                                        tz->trips.passive.temperature));
                trip--;
        }
@@ -1002,7 +1004,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
                tz->trips.active[i].flags.valid; i++) {
                if (!trip)
-                       return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
                                        tz->trips.active[i].temperature));
                trip--;
        }
index 9e8c20c6a0b7243e708876a4dfffa30dd8f47506..0a43c8e0eff323fe55f29846695c71e750ffedf3 100644 (file)
@@ -99,6 +99,13 @@ MODULE_LICENSE("GPL");
 #define HCI_VIDEO_OUT_CRT              0x2
 #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
  */
 
index c7e128e5369b2d5853acf17e8ff109dc2d1fe021..7361204b1eef2114ca22a65902dae2b6ae75276f 100644 (file)
@@ -109,7 +109,7 @@ void acpi_ut_track_stack_ptr(void)
  * RETURN:      Updated pointer to the function name
  *
  * 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.
  *
  ******************************************************************************/
index 76ee766c84f948ed2d8749f06486338a792f7e05..e08b3fa6639f593c0c1d4c893d591be26d36243c 100644 (file)
@@ -432,7 +432,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
         * element -- which is legal)
         */
        if (!internal_object) {
-               *obj_length = 0;
+               *obj_length = sizeof(union acpi_object);
                return_ACPI_STATUS(AE_OK);
        }
 
index eba55b7d6c95ad63479430fc3c63c57dce3a5b19..44ea60cf21c09c00adc1135394decbb4af2faa1d 100644 (file)
@@ -407,6 +407,12 @@ acpi_evaluate_reference(acpi_handle handle,
                        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. */
 
                list->handles[i] = element->reference.handle;
index 12cce69b5441e98a7bd8da23031dc250daaa88f1..1bc0c74f2755d1c3bbf8264c01a27dbd208ce227 100644 (file)
@@ -713,7 +713,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
        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;
                static int count = 0;
                char *name;
@@ -1201,7 +1201,7 @@ static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
        if (!video)
                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");
 
       end:
index efacc9f8bfe31a0b9c84b5aec4ea11c8285dc527..c33b1c6e93b11b4b975c859de79abbf63b797593 100644 (file)
@@ -293,7 +293,7 @@ struct acpi_buffer *out)
 {
        struct guid_block *block = NULL;
        struct wmi_block *wblock = NULL;
-       acpi_handle handle;
+       acpi_handle handle, wc_handle;
        acpi_status status, wc_status = AE_ERROR;
        struct acpi_object_list input, wc_input;
        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
                 * 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");
@@ -351,7 +353,7 @@ struct acpi_buffer *out)
         * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
         * 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;
                status = acpi_evaluate_object(handle,
                wc_method, &wc_input, NULL);
index 982e27b86d101a15ebb2f579652a67d4ae08f806..962817e49fba02e063dc164a3d0971e221eaa3a7 100644 (file)
@@ -108,6 +108,7 @@ config ACER_WMI
        depends on ACPI
        depends on LEDS_CLASS
        depends on BACKLIGHT_CLASS_DEVICE
+       depends on SERIO_I8042
        select ACPI_WMI
        ---help---
          This is a driver for newer Acer (and Wistron) laptops. It adds
index 74d12b4a3abdae48be072857ec75a34c90496dcb..dd13a3749927494804aa4566c59df652d963f40b 100644 (file)
@@ -217,6 +217,15 @@ static struct dmi_system_id acer_quirks[] = {
                },
                .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,
                .ident = "Acer Aspire 5100",
@@ -226,6 +235,15 @@ static struct dmi_system_id acer_quirks[] = {
                },
                .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,
                .ident = "Acer Aspire 5630",
@@ -761,11 +779,11 @@ enum led_brightness value)
 }
 
 static struct led_classdev mail_led = {
-       .name = "acer-mail:green",
+       .name = "acer-wmi::mail",
        .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);
 }
@@ -798,7 +816,7 @@ static struct backlight_ops acer_bl_ops = {
        .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;
 
@@ -817,7 +835,7 @@ static int __init acer_backlight_init(struct device *dev)
        return 0;
 }
 
-static void __exit acer_backlight_exit(void)
+static void acer_backlight_exit(void)
 {
        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 (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;
                }
        } 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;
        }
 
@@ -1064,21 +1083,20 @@ static int __init acer_wmi_init(void)
                interface = &AMW0_interface;
 
                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;
                }
        }
 
-       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();
 
        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;
        }
 
index 899e3f75f288dd853a50f61e9c15772ea3d60b01..02ff3d19b1ccaf40981c861e9977c43eea634f3f 100644 (file)
@@ -315,7 +315,7 @@ static void sony_laptop_report_input_event(u8 event)
                break;
 
        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);
                        break;
                }
index 4a23654184fc04da02eb1a73468818709fbe6371..72f7476930c857ffa20a4c323dff3af6bf7c9baa 100644 (file)
@@ -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 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)
                return -ENODEV;
        /* If the ACPI device has _EJ0, ignore the device */
        if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
                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;
 }
 
 
index 69f19f22487566e2e12110236c550265da7b7ff5..3ab313ed441cc07a4c9ef17ee62c3e325493a32c 100644 (file)
@@ -4,6 +4,7 @@
 
 menuconfig THERMAL
        bool "Generic Thermal sysfs driver"
+       select HWMON
        default y
        help
          Generic Thermal Sysfs driver offers a generic mechanism for
index 8b86e53ccf7a081586d32d09350dce072f2ef75e..41bd4c805ace249c6c43f44066df7c049d0cdac4 100644 (file)
 #include <linux/idr.h>
 #include <linux/thermal.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_LICENSE("GPL");
 
@@ -56,6 +58,9 @@ static LIST_HEAD(thermal_tz_list);
 static LIST_HEAD(thermal_cdev_list);
 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)
 {
        int err;
@@ -87,7 +92,67 @@ static void release_idr(struct idr *idr, struct mutex *lock, int id)
                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) \
        container_of(_dev, struct thermal_zone_device, device)
@@ -214,7 +279,7 @@ do {        \
        device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]);    \
 } while (0)
 
-/* sys I/F for cooling device */
+/* cooling device sys I/F */
 #define to_cooling_device(_dev)        \
        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;
        int result;
 
+       if (!type)
+               return ERR_PTR(-EINVAL);
+
        if (strlen(type) >= THERMAL_NAME_LENGTH)
                return ERR_PTR(-EINVAL);
 
@@ -477,11 +545,9 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type,
        }
 
        /* 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);
        if (result)
@@ -547,8 +613,8 @@ void thermal_cooling_device_unregister(struct
                tz->ops->unbind(tz, cdev);
        }
        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_cur_state);
 
@@ -580,6 +646,9 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
        int result;
        int count;
 
+       if (!type)
+               return ERR_PTR(-EINVAL);
+
        if (strlen(type) >= THERMAL_NAME_LENGTH)
                return ERR_PTR(-EINVAL);
 
@@ -601,6 +670,13 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
                kfree(tz);
                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);
        tz->ops = ops;
@@ -615,13 +691,28 @@ struct thermal_zone_device *thermal_zone_device_register(char *type,
                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);
        if (result)
                goto unregister;
@@ -687,8 +778,17 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
                    tz->ops->unbind(tz, cdev);
        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);
        if (tz->ops->get_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);
 
+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)
 {
        int result = 0;
@@ -716,16 +829,20 @@ static int __init thermal_init(void)
                mutex_destroy(&thermal_idr_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);
index 79833170bb9cddf4aad9b6bde7806628856ffde5..6233f3b4ae6628c0676c73f09a2937f5039fcd5c 100644 (file)
@@ -190,7 +190,7 @@ config APM_EMULATION
          notification of APM "events" (e.g. battery status change).
 
          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
          <http://www.tldp.org/docs.html#howto>.
 
index 72a020cabb4c5238f395c1aa6420a630dc8b49dc..5f91a07c4eac7e104f3fc9c333a481be11ead921 100644 (file)
@@ -447,7 +447,7 @@ static void memory_bm_free(struct memory_bitmap *bm, int clear_nosave_free)
  *     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)
 {
        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) {
                        zone_bm = zone_bm->next;
 
-                       BUG_ON(!zone_bm);
+                       if (!zone_bm)
+                               return -EFAULT;
                }
                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;
        *bit_nr = 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)
 {
        void *addr;
        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);
 }
 
+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)
 {
        void *addr;
        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);
 }
 
@@ -503,8 +521,10 @@ static int memory_bm_test_bit(struct memory_bitmap *bm, unsigned long pfn)
 {
        void *addr;
        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);
 }
 
@@ -709,8 +729,15 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
                                region->end_pfn << PAGE_SHIFT);
 
                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);
+                       }
        }
 }