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 ...
This commit is contained in:
commit
96e31022a1
@ -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/
|
||||
|
@ -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
|
||||
------------------
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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).
|
@ -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
|
||||
|
@ -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>.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
* ---------------
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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--;
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -30,8 +30,10 @@
|
||||
#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);
|
||||
|
@ -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>.
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user