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: (30 commits) ACPI: Kconfig text - Fix the ACPI_CONTAINER module name according to the real module name. eeepc-laptop: fix oops when changing backlight brightness during eeepc-laptop init ACPICA: Fix table entry truncation calculation ACPI: Enable bit 11 in _PDC to advertise hw coord ACPI: struct device - replace bus_id with dev_name(), dev_set_name() ACPI: add missing KERN_* constants to printks ACPI: dock: Don't eval _STA on every show_docked sysfs read ACPI: disable ACPI cleanly when bad RSDP found ACPI: delete CPU_IDLE=n code ACPI: cpufreq: Remove deprecated /proc/acpi/processor/../performance proc entries ACPI: make some IO ports off-limits to AML ACPICA: add debug dump of BIOS _OSI strings ACPI: proc_dir_entry 'video/VGA' already registered ACPI: Skip the first two elements in the _BCL package ACPI: remove BM_RLD access from idle entry path ACPI: remove locking from PM1x_STS register reads eeepc-laptop: use netlink interface eeepc-laptop: Implement rfkill hotplugging in eeepc-laptop eeepc-laptop: Check return values from rfkill_register eeepc-laptop: Add support for extended hotkeys ...
This commit is contained in:
@@ -195,19 +195,3 @@ scaling_setspeed. By "echoing" a new frequency into this
|
|||||||
you can change the speed of the CPU,
|
you can change the speed of the CPU,
|
||||||
but only within the limits of
|
but only within the limits of
|
||||||
scaling_min_freq and scaling_max_freq.
|
scaling_min_freq and scaling_max_freq.
|
||||||
|
|
||||||
|
|
||||||
3.2 Deprecated Interfaces
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Depending on your kernel configuration, you might find the following
|
|
||||||
cpufreq-related files:
|
|
||||||
/proc/cpufreq
|
|
||||||
/proc/sys/cpu/*/speed
|
|
||||||
/proc/sys/cpu/*/speed-min
|
|
||||||
/proc/sys/cpu/*/speed-max
|
|
||||||
|
|
||||||
These are files for deprecated interfaces to cpufreq, which offer far
|
|
||||||
less functionality. Because of this, these interfaces aren't described
|
|
||||||
here.
|
|
||||||
|
|
||||||
|
@@ -156,11 +156,11 @@ static int __init acpi_sleep_setup(char *str)
|
|||||||
#ifdef CONFIG_HIBERNATION
|
#ifdef CONFIG_HIBERNATION
|
||||||
if (strncmp(str, "s4_nohwsig", 10) == 0)
|
if (strncmp(str, "s4_nohwsig", 10) == 0)
|
||||||
acpi_no_s4_hw_signature();
|
acpi_no_s4_hw_signature();
|
||||||
|
if (strncmp(str, "s4_nonvs", 8) == 0)
|
||||||
|
acpi_s4_no_nvs();
|
||||||
#endif
|
#endif
|
||||||
if (strncmp(str, "old_ordering", 12) == 0)
|
if (strncmp(str, "old_ordering", 12) == 0)
|
||||||
acpi_old_suspend_ordering();
|
acpi_old_suspend_ordering();
|
||||||
if (strncmp(str, "s4_nonvs", 8) == 0)
|
|
||||||
acpi_s4_no_nvs();
|
|
||||||
str = strchr(str, ',');
|
str = strchr(str, ',');
|
||||||
if (str != NULL)
|
if (str != NULL)
|
||||||
str += strspn(str, ", \t");
|
str += strspn(str, ", \t");
|
||||||
|
@@ -245,17 +245,6 @@ config X86_E_POWERSAVER
|
|||||||
|
|
||||||
comment "shared options"
|
comment "shared options"
|
||||||
|
|
||||||
config X86_ACPI_CPUFREQ_PROC_INTF
|
|
||||||
bool "/proc/acpi/processor/../performance interface (deprecated)"
|
|
||||||
depends on PROC_FS
|
|
||||||
depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
|
|
||||||
help
|
|
||||||
This enables the deprecated /proc/acpi/processor/../performance
|
|
||||||
interface. While it is helpful for debugging, the generic,
|
|
||||||
cross-architecture cpufreq interfaces should be used.
|
|
||||||
|
|
||||||
If in doubt, say N.
|
|
||||||
|
|
||||||
config X86_SPEEDSTEP_LIB
|
config X86_SPEEDSTEP_LIB
|
||||||
tristate
|
tristate
|
||||||
default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
|
default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
|
||||||
|
@@ -9,6 +9,7 @@ menuconfig ACPI
|
|||||||
depends on PCI
|
depends on PCI
|
||||||
depends on PM
|
depends on PM
|
||||||
select PNP
|
select PNP
|
||||||
|
select CPU_IDLE
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
Advanced Configuration and Power Interface (ACPI) support for
|
Advanced Configuration and Power Interface (ACPI) support for
|
||||||
@@ -287,7 +288,7 @@ config ACPI_CONTAINER
|
|||||||
support physical cpu/memory hot-plug.
|
support physical cpu/memory hot-plug.
|
||||||
|
|
||||||
If one selects "m", this driver can be loaded with
|
If one selects "m", this driver can be loaded with
|
||||||
"modprobe acpi_container".
|
"modprobe container".
|
||||||
|
|
||||||
config ACPI_HOTPLUG_MEMORY
|
config ACPI_HOTPLUG_MEMORY
|
||||||
tristate "Memory Hotplug"
|
tristate "Memory Hotplug"
|
||||||
|
@@ -538,10 +538,9 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
|
|||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
ACPI_WARNING((AE_INFO,
|
ACPI_WARNING((AE_INFO,
|
||||||
"Truncating %u table entries!",
|
"Truncating %u table entries!",
|
||||||
(unsigned)
|
(unsigned) (table_count -
|
||||||
(acpi_gbl_root_table_list.size -
|
(acpi_gbl_root_table_list.
|
||||||
acpi_gbl_root_table_list.
|
count - 2))));
|
||||||
count)));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -116,9 +116,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
|
|||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default return value is SUPPORTED */
|
/* Default return value is 0, NOT-SUPPORTED */
|
||||||
|
|
||||||
return_desc->integer.value = ACPI_UINT32_MAX;
|
return_desc->integer.value = 0;
|
||||||
walk_state->return_desc = return_desc;
|
walk_state->return_desc = return_desc;
|
||||||
|
|
||||||
/* Compare input string to static table of supported interfaces */
|
/* Compare input string to static table of supported interfaces */
|
||||||
@@ -127,10 +127,8 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
|
|||||||
if (!ACPI_STRCMP
|
if (!ACPI_STRCMP
|
||||||
(string_desc->string.pointer,
|
(string_desc->string.pointer,
|
||||||
acpi_interfaces_supported[i])) {
|
acpi_interfaces_supported[i])) {
|
||||||
|
return_desc->integer.value = ACPI_UINT32_MAX;
|
||||||
/* The interface is supported */
|
goto done;
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,15 +139,14 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
|
|||||||
*/
|
*/
|
||||||
status = acpi_os_validate_interface(string_desc->string.pointer);
|
status = acpi_os_validate_interface(string_desc->string.pointer);
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
return_desc->integer.value = ACPI_UINT32_MAX;
|
||||||
/* The interface is supported */
|
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The interface is not supported */
|
done:
|
||||||
|
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, "ACPI: BIOS _OSI(%s) %ssupported\n",
|
||||||
|
string_desc->string.pointer,
|
||||||
|
return_desc->integer.value == 0 ? "not-" : ""));
|
||||||
|
|
||||||
return_desc->integer.value = 0;
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
return_ACPI_STATUS(AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -163,7 +163,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
|||||||
case ACPI_NOTIFY_BUS_CHECK:
|
case ACPI_NOTIFY_BUS_CHECK:
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||||
printk("Container driver received %s event\n",
|
printk(KERN_WARNING "Container driver received %s event\n",
|
||||||
(type == ACPI_NOTIFY_BUS_CHECK) ?
|
(type == ACPI_NOTIFY_BUS_CHECK) ?
|
||||||
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
|
"ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
|
||||||
status = acpi_bus_get_device(handle, &device);
|
status = acpi_bus_get_device(handle, &device);
|
||||||
@@ -174,7 +174,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
|||||||
kobject_uevent(&device->dev.kobj,
|
kobject_uevent(&device->dev.kobj,
|
||||||
KOBJ_ONLINE);
|
KOBJ_ONLINE);
|
||||||
else
|
else
|
||||||
printk("Failed to add container\n");
|
printk(KERN_WARNING
|
||||||
|
"Failed to add container\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
@@ -855,10 +855,14 @@ fdd_out:
|
|||||||
static ssize_t show_docked(struct device *dev,
|
static ssize_t show_docked(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
struct acpi_device *tmp;
|
||||||
|
|
||||||
struct dock_station *dock_station = *((struct dock_station **)
|
struct dock_station *dock_station = *((struct dock_station **)
|
||||||
dev->platform_data);
|
dev->platform_data);
|
||||||
return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
|
|
||||||
|
|
||||||
|
if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
|
||||||
|
return snprintf(buf, PAGE_SIZE, "1\n");
|
||||||
|
return snprintf(buf, PAGE_SIZE, "0\n");
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
|
static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
|
||||||
|
|
||||||
@@ -984,7 +988,7 @@ static int dock_add(acpi_handle handle)
|
|||||||
|
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_docked);
|
ret = device_create_file(&dock_device->dev, &dev_attr_docked);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
platform_device_unregister(dock_device);
|
platform_device_unregister(dock_device);
|
||||||
kfree(dock_station);
|
kfree(dock_station);
|
||||||
dock_station = NULL;
|
dock_station = NULL;
|
||||||
@@ -992,7 +996,7 @@ static int dock_add(acpi_handle handle)
|
|||||||
}
|
}
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_undock);
|
ret = device_create_file(&dock_device->dev, &dev_attr_undock);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||||
platform_device_unregister(dock_device);
|
platform_device_unregister(dock_device);
|
||||||
kfree(dock_station);
|
kfree(dock_station);
|
||||||
@@ -1001,7 +1005,7 @@ static int dock_add(acpi_handle handle)
|
|||||||
}
|
}
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_uid);
|
ret = device_create_file(&dock_device->dev, &dev_attr_uid);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
||||||
platform_device_unregister(dock_device);
|
platform_device_unregister(dock_device);
|
||||||
@@ -1011,7 +1015,7 @@ static int dock_add(acpi_handle handle)
|
|||||||
}
|
}
|
||||||
ret = device_create_file(&dock_device->dev, &dev_attr_flags);
|
ret = device_create_file(&dock_device->dev, &dev_attr_flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("Error %d adding sysfs file\n", ret);
|
printk(KERN_ERR "Error %d adding sysfs file\n", ret);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
device_remove_file(&dock_device->dev, &dev_attr_docked);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
device_remove_file(&dock_device->dev, &dev_attr_undock);
|
||||||
device_remove_file(&dock_device->dev, &dev_attr_uid);
|
device_remove_file(&dock_device->dev, &dev_attr_uid);
|
||||||
|
@@ -982,7 +982,7 @@ int __init acpi_ec_ecdt_probe(void)
|
|||||||
saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
||||||
if (!saved_ec)
|
if (!saved_ec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memcpy(&saved_ec, boot_ec, sizeof(saved_ec));
|
memcpy(saved_ec, boot_ec, sizeof(*saved_ec));
|
||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
/* This workaround is needed only on some broken machines,
|
/* This workaround is needed only on some broken machines,
|
||||||
|
@@ -255,12 +255,12 @@ static int acpi_platform_notify(struct device *dev)
|
|||||||
}
|
}
|
||||||
type = acpi_get_bus_type(dev->bus);
|
type = acpi_get_bus_type(dev->bus);
|
||||||
if (!type) {
|
if (!type) {
|
||||||
DBG("No ACPI bus support for %s\n", dev->bus_id);
|
DBG("No ACPI bus support for %s\n", dev_name(dev));
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if ((ret = type->find_device(dev, &handle)) != 0)
|
if ((ret = type->find_device(dev, &handle)) != 0)
|
||||||
DBG("Can't get handler for %s\n", dev->bus_id);
|
DBG("Can't get handler for %s\n", dev_name(dev));
|
||||||
end:
|
end:
|
||||||
if (!ret)
|
if (!ret)
|
||||||
acpi_bind_one(dev, handle);
|
acpi_bind_one(dev, handle);
|
||||||
@@ -271,10 +271,10 @@ static int acpi_platform_notify(struct device *dev)
|
|||||||
|
|
||||||
acpi_get_name(dev->archdata.acpi_handle,
|
acpi_get_name(dev->archdata.acpi_handle,
|
||||||
ACPI_FULL_PATHNAME, &buffer);
|
ACPI_FULL_PATHNAME, &buffer);
|
||||||
DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
|
DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
|
||||||
kfree(buffer.pointer);
|
kfree(buffer.pointer);
|
||||||
} else
|
} else
|
||||||
DBG("Device %s -> No ACPI support\n", dev->bus_id);
|
DBG("Device %s -> No ACPI support\n", dev_name(dev));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@@ -228,10 +228,10 @@ void acpi_os_vprintf(const char *fmt, va_list args)
|
|||||||
if (acpi_in_debugger) {
|
if (acpi_in_debugger) {
|
||||||
kdb_printf("%s", buffer);
|
kdb_printf("%s", buffer);
|
||||||
} else {
|
} else {
|
||||||
printk("%s", buffer);
|
printk(KERN_CONT "%s", buffer);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
printk("%s", buffer);
|
printk(KERN_CONT "%s", buffer);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1317,6 +1317,54 @@ acpi_os_validate_interface (char *interface)
|
|||||||
return AE_SUPPORT;
|
return AE_SUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86
|
||||||
|
|
||||||
|
struct aml_port_desc {
|
||||||
|
uint start;
|
||||||
|
uint end;
|
||||||
|
char* name;
|
||||||
|
char warned;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct aml_port_desc aml_invalid_port_list[] = {
|
||||||
|
{0x20, 0x21, "PIC0", 0},
|
||||||
|
{0xA0, 0xA1, "PIC1", 0},
|
||||||
|
{0x4D0, 0x4D1, "ELCR", 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* valid_aml_io_address()
|
||||||
|
*
|
||||||
|
* if valid, return true
|
||||||
|
* else invalid, warn once, return false
|
||||||
|
*/
|
||||||
|
static bool valid_aml_io_address(uint address, uint length)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc);
|
||||||
|
|
||||||
|
for (i = 0; i < entries; ++i) {
|
||||||
|
if ((address >= aml_invalid_port_list[i].start &&
|
||||||
|
address <= aml_invalid_port_list[i].end) ||
|
||||||
|
(address + length >= aml_invalid_port_list[i].start &&
|
||||||
|
address + length <= aml_invalid_port_list[i].end))
|
||||||
|
{
|
||||||
|
if (!aml_invalid_port_list[i].warned)
|
||||||
|
{
|
||||||
|
printk(KERN_ERR "ACPI: Denied BIOS AML access"
|
||||||
|
" to invalid port 0x%x+0x%x (%s)\n",
|
||||||
|
address, length,
|
||||||
|
aml_invalid_port_list[i].name);
|
||||||
|
aml_invalid_port_list[i].warned = 1;
|
||||||
|
}
|
||||||
|
return false; /* invalid */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true; /* valid */
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline bool valid_aml_io_address(uint address, uint length) { return true; }
|
||||||
|
#endif
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_os_validate_address
|
* FUNCTION: acpi_os_validate_address
|
||||||
@@ -1346,6 +1394,8 @@ acpi_os_validate_address (
|
|||||||
|
|
||||||
switch (space_id) {
|
switch (space_id) {
|
||||||
case ACPI_ADR_SPACE_SYSTEM_IO:
|
case ACPI_ADR_SPACE_SYSTEM_IO:
|
||||||
|
if (!valid_aml_io_address(address, length))
|
||||||
|
return AE_AML_ILLEGAL_ADDRESS;
|
||||||
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
|
||||||
/* Only interference checks against SystemIO and SytemMemory
|
/* Only interference checks against SystemIO and SytemMemory
|
||||||
are needed */
|
are needed */
|
||||||
|
@@ -593,7 +593,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
} else {
|
} else {
|
||||||
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
|
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
|
||||||
printk(PREFIX "%s [%s] enabled at IRQ %d\n",
|
printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
|
||||||
acpi_device_name(link->device),
|
acpi_device_name(link->device),
|
||||||
acpi_device_bid(link->device), link->irq.active);
|
acpi_device_bid(link->device), link->irq.active);
|
||||||
}
|
}
|
||||||
|
@@ -66,43 +66,17 @@ ACPI_MODULE_NAME("processor_idle");
|
|||||||
#define ACPI_PROCESSOR_FILE_POWER "power"
|
#define ACPI_PROCESSOR_FILE_POWER "power"
|
||||||
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
|
#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
|
||||||
#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY)
|
#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY)
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
#define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */
|
|
||||||
#define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */
|
|
||||||
static void (*pm_idle_save) (void) __read_mostly;
|
|
||||||
#else
|
|
||||||
#define C2_OVERHEAD 1 /* 1us */
|
#define C2_OVERHEAD 1 /* 1us */
|
||||||
#define C3_OVERHEAD 1 /* 1us */
|
#define C3_OVERHEAD 1 /* 1us */
|
||||||
#endif
|
|
||||||
#define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
|
#define PM_TIMER_TICKS_TO_US(p) (((p) * 1000)/(PM_TIMER_FREQUENCY/1000))
|
||||||
|
|
||||||
static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
|
static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;
|
||||||
#ifdef CONFIG_CPU_IDLE
|
|
||||||
module_param(max_cstate, uint, 0000);
|
module_param(max_cstate, uint, 0000);
|
||||||
#else
|
|
||||||
module_param(max_cstate, uint, 0644);
|
|
||||||
#endif
|
|
||||||
static unsigned int nocst __read_mostly;
|
static unsigned int nocst __read_mostly;
|
||||||
module_param(nocst, uint, 0000);
|
module_param(nocst, uint, 0000);
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
/*
|
|
||||||
* bm_history -- bit-mask with a bit per jiffy of bus-master activity
|
|
||||||
* 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms
|
|
||||||
* 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms
|
|
||||||
* 100 HZ: 0x0000000F: 4 jiffies = 40ms
|
|
||||||
* reduce history for more aggressive entry into C3
|
|
||||||
*/
|
|
||||||
static unsigned int bm_history __read_mostly =
|
|
||||||
(HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
|
|
||||||
module_param(bm_history, uint, 0644);
|
|
||||||
|
|
||||||
static int acpi_processor_set_power_policy(struct acpi_processor *pr);
|
|
||||||
|
|
||||||
#else /* CONFIG_CPU_IDLE */
|
|
||||||
static unsigned int latency_factor __read_mostly = 2;
|
static unsigned int latency_factor __read_mostly = 2;
|
||||||
module_param(latency_factor, uint, 0644);
|
module_param(latency_factor, uint, 0644);
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
|
* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
|
||||||
@@ -224,71 +198,6 @@ static void acpi_safe_halt(void)
|
|||||||
current_thread_info()->status |= TS_POLLING;
|
current_thread_info()->status |= TS_POLLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
|
|
||||||
static void
|
|
||||||
acpi_processor_power_activate(struct acpi_processor *pr,
|
|
||||||
struct acpi_processor_cx *new)
|
|
||||||
{
|
|
||||||
struct acpi_processor_cx *old;
|
|
||||||
|
|
||||||
if (!pr || !new)
|
|
||||||
return;
|
|
||||||
|
|
||||||
old = pr->power.state;
|
|
||||||
|
|
||||||
if (old)
|
|
||||||
old->promotion.count = 0;
|
|
||||||
new->demotion.count = 0;
|
|
||||||
|
|
||||||
/* Cleanup from old state. */
|
|
||||||
if (old) {
|
|
||||||
switch (old->type) {
|
|
||||||
case ACPI_STATE_C3:
|
|
||||||
/* Disable bus master reload */
|
|
||||||
if (new->type != ACPI_STATE_C3 && pr->flags.bm_check)
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare to use new state. */
|
|
||||||
switch (new->type) {
|
|
||||||
case ACPI_STATE_C3:
|
|
||||||
/* Enable bus master reload */
|
|
||||||
if (old->type != ACPI_STATE_C3 && pr->flags.bm_check)
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr->power.state = new;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static atomic_t c3_cpu_count;
|
|
||||||
|
|
||||||
/* Common C-state entry for C2, C3, .. */
|
|
||||||
static void acpi_cstate_enter(struct acpi_processor_cx *cstate)
|
|
||||||
{
|
|
||||||
/* Don't trace irqs off for idle */
|
|
||||||
stop_critical_timings();
|
|
||||||
if (cstate->entry_method == ACPI_CSTATE_FFH) {
|
|
||||||
/* Call into architectural FFH based C-state */
|
|
||||||
acpi_processor_ffh_cstate_enter(cstate);
|
|
||||||
} else {
|
|
||||||
int unused;
|
|
||||||
/* IO port based C-state */
|
|
||||||
inb(cstate->address);
|
|
||||||
/* Dummy wait op - must do something useless after P_LVL2 read
|
|
||||||
because chipsets cannot guarantee that STPCLK# signal
|
|
||||||
gets asserted in time to freeze execution properly. */
|
|
||||||
unused = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
}
|
|
||||||
start_critical_timings();
|
|
||||||
}
|
|
||||||
#endif /* !CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
#ifdef ARCH_APICTIMER_STOPS_ON_C3
|
#ifdef ARCH_APICTIMER_STOPS_ON_C3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -390,421 +299,6 @@ static int tsc_halts_in_c(int state)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
static void acpi_processor_idle(void)
|
|
||||||
{
|
|
||||||
struct acpi_processor *pr = NULL;
|
|
||||||
struct acpi_processor_cx *cx = NULL;
|
|
||||||
struct acpi_processor_cx *next_state = NULL;
|
|
||||||
int sleep_ticks = 0;
|
|
||||||
u32 t1, t2 = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Interrupts must be disabled during bus mastering calculations and
|
|
||||||
* for C2/C3 transitions.
|
|
||||||
*/
|
|
||||||
local_irq_disable();
|
|
||||||
|
|
||||||
pr = __get_cpu_var(processors);
|
|
||||||
if (!pr) {
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check whether we truly need to go idle, or should
|
|
||||||
* reschedule:
|
|
||||||
*/
|
|
||||||
if (unlikely(need_resched())) {
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cx = pr->power.state;
|
|
||||||
if (!cx || acpi_idle_suspend) {
|
|
||||||
if (pm_idle_save) {
|
|
||||||
pm_idle_save(); /* enables IRQs */
|
|
||||||
} else {
|
|
||||||
acpi_safe_halt();
|
|
||||||
local_irq_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check BM Activity
|
|
||||||
* -----------------
|
|
||||||
* Check for bus mastering activity (if required), record, and check
|
|
||||||
* for demotion.
|
|
||||||
*/
|
|
||||||
if (pr->flags.bm_check) {
|
|
||||||
u32 bm_status = 0;
|
|
||||||
unsigned long diff = jiffies - pr->power.bm_check_timestamp;
|
|
||||||
|
|
||||||
if (diff > 31)
|
|
||||||
diff = 31;
|
|
||||||
|
|
||||||
pr->power.bm_activity <<= diff;
|
|
||||||
|
|
||||||
acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
|
|
||||||
if (bm_status) {
|
|
||||||
pr->power.bm_activity |= 0x1;
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* PIIX4 Erratum #18: Note that BM_STS doesn't always reflect
|
|
||||||
* the true state of bus mastering activity; forcing us to
|
|
||||||
* manually check the BMIDEA bit of each IDE channel.
|
|
||||||
*/
|
|
||||||
else if (errata.piix4.bmisx) {
|
|
||||||
if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01)
|
|
||||||
|| (inb_p(errata.piix4.bmisx + 0x0A) & 0x01))
|
|
||||||
pr->power.bm_activity |= 0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr->power.bm_check_timestamp = jiffies;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If bus mastering is or was active this jiffy, demote
|
|
||||||
* to avoid a faulty transition. Note that the processor
|
|
||||||
* won't enter a low-power state during this call (to this
|
|
||||||
* function) but should upon the next.
|
|
||||||
*
|
|
||||||
* TBD: A better policy might be to fallback to the demotion
|
|
||||||
* state (use it for this quantum only) istead of
|
|
||||||
* demoting -- and rely on duration as our sole demotion
|
|
||||||
* qualification. This may, however, introduce DMA
|
|
||||||
* issues (e.g. floppy DMA transfer overrun/underrun).
|
|
||||||
*/
|
|
||||||
if ((pr->power.bm_activity & 0x1) &&
|
|
||||||
cx->demotion.threshold.bm) {
|
|
||||||
local_irq_enable();
|
|
||||||
next_state = cx->demotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
/*
|
|
||||||
* Check for P_LVL2_UP flag before entering C2 and above on
|
|
||||||
* an SMP system. We do it here instead of doing it at _CST/P_LVL
|
|
||||||
* detection phase, to work cleanly with logical CPU hotplug.
|
|
||||||
*/
|
|
||||||
if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
|
||||||
!pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
|
|
||||||
cx = &pr->power.states[ACPI_STATE_C1];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sleep:
|
|
||||||
* ------
|
|
||||||
* Invoke the current Cx state to put the processor to sleep.
|
|
||||||
*/
|
|
||||||
if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
|
|
||||||
current_thread_info()->status &= ~TS_POLLING;
|
|
||||||
/*
|
|
||||||
* TS_POLLING-cleared state must be visible before we
|
|
||||||
* test NEED_RESCHED:
|
|
||||||
*/
|
|
||||||
smp_mb();
|
|
||||||
if (need_resched()) {
|
|
||||||
current_thread_info()->status |= TS_POLLING;
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cx->type) {
|
|
||||||
|
|
||||||
case ACPI_STATE_C1:
|
|
||||||
/*
|
|
||||||
* Invoke C1.
|
|
||||||
* Use the appropriate idle routine, the one that would
|
|
||||||
* be used without acpi C-states.
|
|
||||||
*/
|
|
||||||
if (pm_idle_save) {
|
|
||||||
pm_idle_save(); /* enables IRQs */
|
|
||||||
} else {
|
|
||||||
acpi_safe_halt();
|
|
||||||
local_irq_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TBD: Can't get time duration while in C1, as resumes
|
|
||||||
* go to an ISR rather than here. Need to instrument
|
|
||||||
* base interrupt handler.
|
|
||||||
*
|
|
||||||
* Note: the TSC better not stop in C1, sched_clock() will
|
|
||||||
* skew otherwise.
|
|
||||||
*/
|
|
||||||
sleep_ticks = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_STATE_C2:
|
|
||||||
/* Get start time (ticks) */
|
|
||||||
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
/* Tell the scheduler that we are going deep-idle: */
|
|
||||||
sched_clock_idle_sleep_event();
|
|
||||||
/* Invoke C2 */
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
|
||||||
acpi_cstate_enter(cx);
|
|
||||||
/* Get end time (ticks) */
|
|
||||||
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
|
|
||||||
#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
|
|
||||||
/* TSC halts in C2, so notify users */
|
|
||||||
if (tsc_halts_in_c(ACPI_STATE_C2))
|
|
||||||
mark_tsc_unstable("possible TSC halt in C2");
|
|
||||||
#endif
|
|
||||||
/* Compute time (ticks) that we were actually asleep */
|
|
||||||
sleep_ticks = ticks_elapsed(t1, t2);
|
|
||||||
|
|
||||||
/* Tell the scheduler how much we idled: */
|
|
||||||
sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
|
|
||||||
|
|
||||||
/* Re-enable interrupts */
|
|
||||||
local_irq_enable();
|
|
||||||
/* Do not account our idle-switching overhead: */
|
|
||||||
sleep_ticks -= cx->latency_ticks + C2_OVERHEAD;
|
|
||||||
|
|
||||||
current_thread_info()->status |= TS_POLLING;
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACPI_STATE_C3:
|
|
||||||
acpi_unlazy_tlb(smp_processor_id());
|
|
||||||
/*
|
|
||||||
* Must be done before busmaster disable as we might
|
|
||||||
* need to access HPET !
|
|
||||||
*/
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
|
||||||
/*
|
|
||||||
* disable bus master
|
|
||||||
* bm_check implies we need ARB_DIS
|
|
||||||
* !bm_check implies we need cache flush
|
|
||||||
* bm_control implies whether we can do ARB_DIS
|
|
||||||
*
|
|
||||||
* That leaves a case where bm_check is set and bm_control is
|
|
||||||
* not set. In that case we cannot do much, we enter C3
|
|
||||||
* without doing anything.
|
|
||||||
*/
|
|
||||||
if (pr->flags.bm_check && pr->flags.bm_control) {
|
|
||||||
if (atomic_inc_return(&c3_cpu_count) ==
|
|
||||||
num_online_cpus()) {
|
|
||||||
/*
|
|
||||||
* All CPUs are trying to go to C3
|
|
||||||
* Disable bus master arbitration
|
|
||||||
*/
|
|
||||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
|
|
||||||
}
|
|
||||||
} else if (!pr->flags.bm_check) {
|
|
||||||
/* SMP with no shared cache... Invalidate cache */
|
|
||||||
ACPI_FLUSH_CPU_CACHE();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get start time (ticks) */
|
|
||||||
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
/* Invoke C3 */
|
|
||||||
/* Tell the scheduler that we are going deep-idle: */
|
|
||||||
sched_clock_idle_sleep_event();
|
|
||||||
acpi_cstate_enter(cx);
|
|
||||||
/* Get end time (ticks) */
|
|
||||||
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
|
||||||
if (pr->flags.bm_check && pr->flags.bm_control) {
|
|
||||||
/* Enable bus master arbitration */
|
|
||||||
atomic_dec(&c3_cpu_count);
|
|
||||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86)
|
|
||||||
/* TSC halts in C3, so notify users */
|
|
||||||
if (tsc_halts_in_c(ACPI_STATE_C3))
|
|
||||||
mark_tsc_unstable("TSC halts in C3");
|
|
||||||
#endif
|
|
||||||
/* Compute time (ticks) that we were actually asleep */
|
|
||||||
sleep_ticks = ticks_elapsed(t1, t2);
|
|
||||||
/* Tell the scheduler how much we idled: */
|
|
||||||
sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
|
|
||||||
|
|
||||||
/* Re-enable interrupts */
|
|
||||||
local_irq_enable();
|
|
||||||
/* Do not account our idle-switching overhead: */
|
|
||||||
sleep_ticks -= cx->latency_ticks + C3_OVERHEAD;
|
|
||||||
|
|
||||||
current_thread_info()->status |= TS_POLLING;
|
|
||||||
acpi_state_timer_broadcast(pr, cx, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
local_irq_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cx->usage++;
|
|
||||||
if ((cx->type != ACPI_STATE_C1) && (sleep_ticks > 0))
|
|
||||||
cx->time += sleep_ticks;
|
|
||||||
|
|
||||||
next_state = pr->power.state;
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
|
||||||
/* Don't do promotion/demotion */
|
|
||||||
if ((cx->type == ACPI_STATE_C1) && (num_online_cpus() > 1) &&
|
|
||||||
!pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) {
|
|
||||||
next_state = cx;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Promotion?
|
|
||||||
* ----------
|
|
||||||
* Track the number of longs (time asleep is greater than threshold)
|
|
||||||
* and promote when the count threshold is reached. Note that bus
|
|
||||||
* mastering activity may prevent promotions.
|
|
||||||
* Do not promote above max_cstate.
|
|
||||||
*/
|
|
||||||
if (cx->promotion.state &&
|
|
||||||
((cx->promotion.state - pr->power.states) <= max_cstate)) {
|
|
||||||
if (sleep_ticks > cx->promotion.threshold.ticks &&
|
|
||||||
cx->promotion.state->latency <=
|
|
||||||
pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
|
|
||||||
cx->promotion.count++;
|
|
||||||
cx->demotion.count = 0;
|
|
||||||
if (cx->promotion.count >=
|
|
||||||
cx->promotion.threshold.count) {
|
|
||||||
if (pr->flags.bm_check) {
|
|
||||||
if (!
|
|
||||||
(pr->power.bm_activity & cx->
|
|
||||||
promotion.threshold.bm)) {
|
|
||||||
next_state =
|
|
||||||
cx->promotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next_state = cx->promotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Demotion?
|
|
||||||
* ---------
|
|
||||||
* Track the number of shorts (time asleep is less than time threshold)
|
|
||||||
* and demote when the usage threshold is reached.
|
|
||||||
*/
|
|
||||||
if (cx->demotion.state) {
|
|
||||||
if (sleep_ticks < cx->demotion.threshold.ticks) {
|
|
||||||
cx->demotion.count++;
|
|
||||||
cx->promotion.count = 0;
|
|
||||||
if (cx->demotion.count >= cx->demotion.threshold.count) {
|
|
||||||
next_state = cx->demotion.state;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
|
||||||
/*
|
|
||||||
* Demote if current state exceeds max_cstate
|
|
||||||
* or if the latency of the current state is unacceptable
|
|
||||||
*/
|
|
||||||
if ((pr->power.state - pr->power.states) > max_cstate ||
|
|
||||||
pr->power.state->latency >
|
|
||||||
pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
|
|
||||||
if (cx->demotion.state)
|
|
||||||
next_state = cx->demotion.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* New Cx State?
|
|
||||||
* -------------
|
|
||||||
* If we're going to start using a new Cx state we must clean up
|
|
||||||
* from the previous and prepare to use the new.
|
|
||||||
*/
|
|
||||||
if (next_state != pr->power.state)
|
|
||||||
acpi_processor_power_activate(pr, next_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acpi_processor_set_power_policy(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned int state_is_set = 0;
|
|
||||||
struct acpi_processor_cx *lower = NULL;
|
|
||||||
struct acpi_processor_cx *higher = NULL;
|
|
||||||
struct acpi_processor_cx *cx;
|
|
||||||
|
|
||||||
|
|
||||||
if (!pr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function sets the default Cx state policy (OS idle handler).
|
|
||||||
* Our scheme is to promote quickly to C2 but more conservatively
|
|
||||||
* to C3. We're favoring C2 for its characteristics of low latency
|
|
||||||
* (quick response), good power savings, and ability to allow bus
|
|
||||||
* mastering activity. Note that the Cx state policy is completely
|
|
||||||
* customizable and can be altered dynamically.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* startup state */
|
|
||||||
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
|
|
||||||
cx = &pr->power.states[i];
|
|
||||||
if (!cx->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!state_is_set)
|
|
||||||
pr->power.state = cx;
|
|
||||||
state_is_set++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state_is_set)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/* demotion */
|
|
||||||
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
|
|
||||||
cx = &pr->power.states[i];
|
|
||||||
if (!cx->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (lower) {
|
|
||||||
cx->demotion.state = lower;
|
|
||||||
cx->demotion.threshold.ticks = cx->latency_ticks;
|
|
||||||
cx->demotion.threshold.count = 1;
|
|
||||||
if (cx->type == ACPI_STATE_C3)
|
|
||||||
cx->demotion.threshold.bm = bm_history;
|
|
||||||
}
|
|
||||||
|
|
||||||
lower = cx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* promotion */
|
|
||||||
for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) {
|
|
||||||
cx = &pr->power.states[i];
|
|
||||||
if (!cx->valid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (higher) {
|
|
||||||
cx->promotion.state = higher;
|
|
||||||
cx->promotion.threshold.ticks = cx->latency_ticks;
|
|
||||||
if (cx->type >= ACPI_STATE_C2)
|
|
||||||
cx->promotion.threshold.count = 4;
|
|
||||||
else
|
|
||||||
cx->promotion.threshold.count = 10;
|
|
||||||
if (higher->type == ACPI_STATE_C3)
|
|
||||||
cx->promotion.threshold.bm = bm_history;
|
|
||||||
}
|
|
||||||
|
|
||||||
higher = cx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* !CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
|
static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1047,11 +541,7 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx)
|
|||||||
*/
|
*/
|
||||||
cx->valid = 1;
|
cx->valid = 1;
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
|
|
||||||
#else
|
|
||||||
cx->latency_ticks = cx->latency;
|
cx->latency_ticks = cx->latency;
|
||||||
#endif
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1121,7 +611,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
|||||||
" for C3 to be enabled on SMP systems\n"));
|
" for C3 to be enabled on SMP systems\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1132,11 +621,16 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
|||||||
*/
|
*/
|
||||||
cx->valid = 1;
|
cx->valid = 1;
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency);
|
|
||||||
#else
|
|
||||||
cx->latency_ticks = cx->latency;
|
cx->latency_ticks = cx->latency;
|
||||||
#endif
|
/*
|
||||||
|
* On older chipsets, BM_RLD needs to be set
|
||||||
|
* in order for Bus Master activity to wake the
|
||||||
|
* system from C3. Newer chipsets handle DMA
|
||||||
|
* during C3 automatically and BM_RLD is a NOP.
|
||||||
|
* In either case, the proper way to
|
||||||
|
* handle BM_RLD is to set it and leave it set.
|
||||||
|
*/
|
||||||
|
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1201,20 +695,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr)
|
|||||||
|
|
||||||
pr->power.count = acpi_processor_power_verify(pr);
|
pr->power.count = acpi_processor_power_verify(pr);
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
/*
|
|
||||||
* Set Default Policy
|
|
||||||
* ------------------
|
|
||||||
* Now that we know which states are supported, set the default
|
|
||||||
* policy. Note that this policy can be changed dynamically
|
|
||||||
* (e.g. encourage deeper sleeps to conserve battery life when
|
|
||||||
* not on AC).
|
|
||||||
*/
|
|
||||||
result = acpi_processor_set_power_policy(pr);
|
|
||||||
if (result)
|
|
||||||
return result;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if one state of type C2 or C3 is available, mark this
|
* if one state of type C2 or C3 is available, mark this
|
||||||
* CPU as being "idle manageable"
|
* CPU as being "idle manageable"
|
||||||
@@ -1312,69 +792,6 @@ static const struct file_operations acpi_processor_power_fops = {
|
|||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
|
|
||||||
int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
if (boot_option_idle_override)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!pr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (nocst) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pr->flags.power_setup_done)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fall back to the default idle loop, when pm_idle_save had
|
|
||||||
* been initialized.
|
|
||||||
*/
|
|
||||||
if (pm_idle_save) {
|
|
||||||
pm_idle = pm_idle_save;
|
|
||||||
/* Relies on interrupts forcing exit from idle. */
|
|
||||||
synchronize_sched();
|
|
||||||
}
|
|
||||||
|
|
||||||
pr->flags.power = 0;
|
|
||||||
result = acpi_processor_get_power_info(pr);
|
|
||||||
if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
|
|
||||||
pm_idle = acpi_processor_idle;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
static void smp_callback(void *v)
|
|
||||||
{
|
|
||||||
/* we already woke the CPU up, nothing more to do */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This function gets called when a part of the kernel has a new latency
|
|
||||||
* requirement. This means we need to get all processors out of their C-state,
|
|
||||||
* and then recalculate a new suitable C-state. Just do a cross-cpu IPI; that
|
|
||||||
* wakes them all right up.
|
|
||||||
*/
|
|
||||||
static int acpi_processor_latency_notify(struct notifier_block *b,
|
|
||||||
unsigned long l, void *v)
|
|
||||||
{
|
|
||||||
smp_call_function(smp_callback, NULL, 1);
|
|
||||||
return NOTIFY_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct notifier_block acpi_processor_latency_notifier = {
|
|
||||||
.notifier_call = acpi_processor_latency_notify,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else /* CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_idle_bm_check - checks if bus master activity was detected
|
* acpi_idle_bm_check - checks if bus master activity was detected
|
||||||
@@ -1383,7 +800,7 @@ static int acpi_idle_bm_check(void)
|
|||||||
{
|
{
|
||||||
u32 bm_status = 0;
|
u32 bm_status = 0;
|
||||||
|
|
||||||
acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
|
acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status);
|
||||||
if (bm_status)
|
if (bm_status)
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
|
acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1);
|
||||||
/*
|
/*
|
||||||
@@ -1399,25 +816,6 @@ static int acpi_idle_bm_check(void)
|
|||||||
return bm_status;
|
return bm_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* acpi_idle_update_bm_rld - updates the BM_RLD bit depending on target state
|
|
||||||
* @pr: the processor
|
|
||||||
* @target: the new target state
|
|
||||||
*/
|
|
||||||
static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr,
|
|
||||||
struct acpi_processor_cx *target)
|
|
||||||
{
|
|
||||||
if (pr->flags.bm_rld_set && target->type != ACPI_STATE_C3) {
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
|
|
||||||
pr->flags.bm_rld_set = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pr->flags.bm_rld_set && target->type == ACPI_STATE_C3) {
|
|
||||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
|
|
||||||
pr->flags.bm_rld_set = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_idle_do_entry - a helper function that does C2 and C3 type entry
|
* acpi_idle_do_entry - a helper function that does C2 and C3 type entry
|
||||||
* @cx: cstate data
|
* @cx: cstate data
|
||||||
@@ -1473,9 +871,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pr->flags.bm_check)
|
|
||||||
acpi_idle_update_bm_rld(pr, cx);
|
|
||||||
|
|
||||||
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
||||||
acpi_idle_do_entry(cx);
|
acpi_idle_do_entry(cx);
|
||||||
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
|
||||||
@@ -1527,9 +922,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
|
|||||||
*/
|
*/
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
acpi_state_timer_broadcast(pr, cx, 1);
|
||||||
|
|
||||||
if (pr->flags.bm_check)
|
|
||||||
acpi_idle_update_bm_rld(pr, cx);
|
|
||||||
|
|
||||||
if (cx->type == ACPI_STATE_C3)
|
if (cx->type == ACPI_STATE_C3)
|
||||||
ACPI_FLUSH_CPU_CACHE();
|
ACPI_FLUSH_CPU_CACHE();
|
||||||
|
|
||||||
@@ -1621,8 +1013,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
|
|||||||
*/
|
*/
|
||||||
acpi_state_timer_broadcast(pr, cx, 1);
|
acpi_state_timer_broadcast(pr, cx, 1);
|
||||||
|
|
||||||
acpi_idle_update_bm_rld(pr, cx);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* disable bus master
|
* disable bus master
|
||||||
* bm_check implies we need ARB_DIS
|
* bm_check implies we need ARB_DIS
|
||||||
@@ -1795,8 +1185,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_CPU_IDLE */
|
|
||||||
|
|
||||||
int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
||||||
struct acpi_device *device)
|
struct acpi_device *device)
|
||||||
{
|
{
|
||||||
@@ -1825,10 +1213,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
|||||||
"ACPI: processor limited to max C-state %d\n",
|
"ACPI: processor limited to max C-state %d\n",
|
||||||
max_cstate);
|
max_cstate);
|
||||||
first_run++;
|
first_run++;
|
||||||
#if !defined(CONFIG_CPU_IDLE) && defined(CONFIG_SMP)
|
|
||||||
pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
|
|
||||||
&acpi_processor_latency_notifier);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pr)
|
if (!pr)
|
||||||
@@ -1852,11 +1236,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
|||||||
* platforms that only support C1.
|
* platforms that only support C1.
|
||||||
*/
|
*/
|
||||||
if (pr->flags.power) {
|
if (pr->flags.power) {
|
||||||
#ifdef CONFIG_CPU_IDLE
|
|
||||||
acpi_processor_setup_cpuidle(pr);
|
acpi_processor_setup_cpuidle(pr);
|
||||||
if (cpuidle_register_device(&pr->power.dev))
|
if (cpuidle_register_device(&pr->power.dev))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
#endif
|
|
||||||
|
|
||||||
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
|
printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id);
|
||||||
for (i = 1; i <= pr->power.count; i++)
|
for (i = 1; i <= pr->power.count; i++)
|
||||||
@@ -1864,13 +1246,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
|
|||||||
printk(" C%d[C%d]", i,
|
printk(" C%d[C%d]", i,
|
||||||
pr->power.states[i].type);
|
pr->power.states[i].type);
|
||||||
printk(")\n");
|
printk(")\n");
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
if (pr->id == 0) {
|
|
||||||
pm_idle_save = pm_idle;
|
|
||||||
pm_idle = acpi_processor_idle;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'power' [R] */
|
/* 'power' [R] */
|
||||||
@@ -1889,34 +1264,12 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
|
|||||||
if (boot_option_idle_override)
|
if (boot_option_idle_override)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_IDLE
|
|
||||||
cpuidle_unregister_device(&pr->power.dev);
|
cpuidle_unregister_device(&pr->power.dev);
|
||||||
#endif
|
|
||||||
pr->flags.power_setup_done = 0;
|
pr->flags.power_setup_done = 0;
|
||||||
|
|
||||||
if (acpi_device_dir(device))
|
if (acpi_device_dir(device))
|
||||||
remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
|
remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,
|
||||||
acpi_device_dir(device));
|
acpi_device_dir(device));
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_IDLE
|
|
||||||
|
|
||||||
/* Unregister the idle handler when processor #0 is removed. */
|
|
||||||
if (pr->id == 0) {
|
|
||||||
if (pm_idle_save)
|
|
||||||
pm_idle = pm_idle_save;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We are about to unload the current idle thread pm callback
|
|
||||||
* (pm_idle), Wait for all processors to update cached/local
|
|
||||||
* copies of pm_idle before proceeding.
|
|
||||||
*/
|
|
||||||
cpu_idle_wait();
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
|
|
||||||
&acpi_processor_latency_notifier);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -31,14 +31,6 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
|
|
||||||
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
|
|
||||||
#include <linux/proc_fs.h>
|
|
||||||
#include <linux/seq_file.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86
|
#ifdef CONFIG_X86
|
||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -434,96 +426,6 @@ int acpi_processor_notify_smm(struct module *calling_module)
|
|||||||
|
|
||||||
EXPORT_SYMBOL(acpi_processor_notify_smm);
|
EXPORT_SYMBOL(acpi_processor_notify_smm);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
|
|
||||||
/* /proc/acpi/processor/../performance interface (DEPRECATED) */
|
|
||||||
|
|
||||||
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
|
|
||||||
static struct file_operations acpi_processor_perf_fops = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.open = acpi_processor_perf_open_fs,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
|
|
||||||
{
|
|
||||||
struct acpi_processor *pr = seq->private;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
|
||||||
if (!pr)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (!pr->performance) {
|
|
||||||
seq_puts(seq, "<not supported>\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
seq_printf(seq, "state count: %d\n"
|
|
||||||
"active state: P%d\n",
|
|
||||||
pr->performance->state_count, pr->performance->state);
|
|
||||||
|
|
||||||
seq_puts(seq, "states:\n");
|
|
||||||
for (i = 0; i < pr->performance->state_count; i++)
|
|
||||||
seq_printf(seq,
|
|
||||||
" %cP%d: %d MHz, %d mW, %d uS\n",
|
|
||||||
(i == pr->performance->state ? '*' : ' '), i,
|
|
||||||
(u32) pr->performance->states[i].core_frequency,
|
|
||||||
(u32) pr->performance->states[i].power,
|
|
||||||
(u32) pr->performance->states[i].transition_latency);
|
|
||||||
|
|
||||||
end:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, acpi_processor_perf_seq_show,
|
|
||||||
PDE(inode)->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void acpi_cpufreq_add_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
struct acpi_device *device = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
if (acpi_bus_get_device(pr->handle, &device))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* add file 'performance' [R/W] */
|
|
||||||
proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO,
|
|
||||||
acpi_device_dir(device),
|
|
||||||
&acpi_processor_perf_fops, acpi_driver_data(device));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
struct acpi_device *device = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
if (acpi_bus_get_device(pr->handle, &device))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* remove file 'performance' */
|
|
||||||
remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
|
|
||||||
acpi_device_dir(device));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
static void acpi_cpufreq_add_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
|
|
||||||
|
|
||||||
static int acpi_processor_get_psd(struct acpi_processor *pr)
|
static int acpi_processor_get_psd(struct acpi_processor *pr)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@@ -747,14 +649,12 @@ err_ret:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(acpi_processor_preregister_performance);
|
EXPORT_SYMBOL(acpi_processor_preregister_performance);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
acpi_processor_register_performance(struct acpi_processor_performance
|
acpi_processor_register_performance(struct acpi_processor_performance
|
||||||
*performance, unsigned int cpu)
|
*performance, unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct acpi_processor *pr;
|
struct acpi_processor *pr;
|
||||||
|
|
||||||
|
|
||||||
if (!(acpi_processor_ppc_status & PPC_REGISTERED))
|
if (!(acpi_processor_ppc_status & PPC_REGISTERED))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -781,8 +681,6 @@ acpi_processor_register_performance(struct acpi_processor_performance
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_cpufreq_add_file(pr);
|
|
||||||
|
|
||||||
mutex_unlock(&performance_mutex);
|
mutex_unlock(&performance_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -795,7 +693,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
|
|||||||
{
|
{
|
||||||
struct acpi_processor *pr;
|
struct acpi_processor *pr;
|
||||||
|
|
||||||
|
|
||||||
mutex_lock(&performance_mutex);
|
mutex_lock(&performance_mutex);
|
||||||
|
|
||||||
pr = per_cpu(processors, cpu);
|
pr = per_cpu(processors, cpu);
|
||||||
@@ -808,8 +705,6 @@ acpi_processor_unregister_performance(struct acpi_processor_performance
|
|||||||
kfree(pr->performance->states);
|
kfree(pr->performance->states);
|
||||||
pr->performance = NULL;
|
pr->performance = NULL;
|
||||||
|
|
||||||
acpi_cpufreq_remove_file(pr);
|
|
||||||
|
|
||||||
mutex_unlock(&performance_mutex);
|
mutex_unlock(&performance_mutex);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@@ -90,31 +90,6 @@ void __init acpi_old_suspend_ordering(void)
|
|||||||
old_suspend_ordering = true;
|
old_suspend_ordering = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* According to the ACPI specification the BIOS should make sure that ACPI is
|
|
||||||
* enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still,
|
|
||||||
* some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
|
|
||||||
* on such systems during resume. Unfortunately that doesn't help in
|
|
||||||
* particularly pathological cases in which SCI_EN has to be set directly on
|
|
||||||
* resume, although the specification states very clearly that this flag is
|
|
||||||
* owned by the hardware. The set_sci_en_on_resume variable will be set in such
|
|
||||||
* cases.
|
|
||||||
*/
|
|
||||||
static bool set_sci_en_on_resume;
|
|
||||||
/*
|
|
||||||
* The ACPI specification wants us to save NVS memory regions during hibernation
|
|
||||||
* and to restore them during the subsequent resume. However, it is not certain
|
|
||||||
* if this mechanism is going to work on all machines, so we allow the user to
|
|
||||||
* disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
|
|
||||||
* option.
|
|
||||||
*/
|
|
||||||
static bool s4_no_nvs;
|
|
||||||
|
|
||||||
void __init acpi_s4_no_nvs(void)
|
|
||||||
{
|
|
||||||
s4_no_nvs = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* acpi_pm_disable_gpes - Disable the GPEs.
|
* acpi_pm_disable_gpes - Disable the GPEs.
|
||||||
*/
|
*/
|
||||||
@@ -193,6 +168,18 @@ static void acpi_pm_end(void)
|
|||||||
#endif /* CONFIG_ACPI_SLEEP */
|
#endif /* CONFIG_ACPI_SLEEP */
|
||||||
|
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
|
/*
|
||||||
|
* According to the ACPI specification the BIOS should make sure that ACPI is
|
||||||
|
* enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still,
|
||||||
|
* some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI
|
||||||
|
* on such systems during resume. Unfortunately that doesn't help in
|
||||||
|
* particularly pathological cases in which SCI_EN has to be set directly on
|
||||||
|
* resume, although the specification states very clearly that this flag is
|
||||||
|
* owned by the hardware. The set_sci_en_on_resume variable will be set in such
|
||||||
|
* cases.
|
||||||
|
*/
|
||||||
|
static bool set_sci_en_on_resume;
|
||||||
|
|
||||||
extern void do_suspend_lowlevel(void);
|
extern void do_suspend_lowlevel(void);
|
||||||
|
|
||||||
static u32 acpi_suspend_states[] = {
|
static u32 acpi_suspend_states[] = {
|
||||||
@@ -396,6 +383,20 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
|
|||||||
#endif /* CONFIG_SUSPEND */
|
#endif /* CONFIG_SUSPEND */
|
||||||
|
|
||||||
#ifdef CONFIG_HIBERNATION
|
#ifdef CONFIG_HIBERNATION
|
||||||
|
/*
|
||||||
|
* The ACPI specification wants us to save NVS memory regions during hibernation
|
||||||
|
* and to restore them during the subsequent resume. However, it is not certain
|
||||||
|
* if this mechanism is going to work on all machines, so we allow the user to
|
||||||
|
* disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
|
||||||
|
* option.
|
||||||
|
*/
|
||||||
|
static bool s4_no_nvs;
|
||||||
|
|
||||||
|
void __init acpi_s4_no_nvs(void)
|
||||||
|
{
|
||||||
|
s4_no_nvs = true;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long s4_hardware_signature;
|
static unsigned long s4_hardware_signature;
|
||||||
static struct acpi_table_facs *facs;
|
static struct acpi_table_facs *facs;
|
||||||
static bool nosigcheck;
|
static bool nosigcheck;
|
||||||
@@ -679,7 +680,7 @@ static void acpi_power_off_prepare(void)
|
|||||||
static void acpi_power_off(void)
|
static void acpi_power_off(void)
|
||||||
{
|
{
|
||||||
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
|
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
|
||||||
printk("%s called\n", __func__);
|
printk(KERN_DEBUG "%s called\n", __func__);
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
acpi_enable_wakeup_device(ACPI_STATE_S5);
|
acpi_enable_wakeup_device(ACPI_STATE_S5);
|
||||||
acpi_enter_sleep_state(ACPI_STATE_S5);
|
acpi_enter_sleep_state(ACPI_STATE_S5);
|
||||||
|
@@ -293,7 +293,12 @@ static void __init check_multiple_madt(void)
|
|||||||
|
|
||||||
int __init acpi_table_init(void)
|
int __init acpi_table_init(void)
|
||||||
{
|
{
|
||||||
acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
return 1;
|
||||||
|
|
||||||
check_multiple_madt();
|
check_multiple_madt();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1020,7 +1020,7 @@ acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(seq, "levels: ");
|
seq_printf(seq, "levels: ");
|
||||||
for (i = 0; i < dev->brightness->count; i++)
|
for (i = 2; i < dev->brightness->count; i++)
|
||||||
seq_printf(seq, " %d", dev->brightness->levels[i]);
|
seq_printf(seq, " %d", dev->brightness->levels[i]);
|
||||||
seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
|
seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
|
||||||
|
|
||||||
@@ -1059,7 +1059,7 @@ acpi_video_device_write_brightness(struct file *file,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/* validate through the list of available levels */
|
/* validate through the list of available levels */
|
||||||
for (i = 0; i < dev->brightness->count; i++)
|
for (i = 2; i < dev->brightness->count; i++)
|
||||||
if (level == dev->brightness->levels[i]) {
|
if (level == dev->brightness->levels[i]) {
|
||||||
if (ACPI_SUCCESS
|
if (ACPI_SUCCESS
|
||||||
(acpi_video_device_lcd_set_level(dev, level)))
|
(acpi_video_device_lcd_set_level(dev, level)))
|
||||||
@@ -1260,7 +1260,7 @@ static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
|
|||||||
printk(KERN_WARNING PREFIX
|
printk(KERN_WARNING PREFIX
|
||||||
"This indicates a BIOS bug. Please contact the manufacturer.\n");
|
"This indicates a BIOS bug. Please contact the manufacturer.\n");
|
||||||
}
|
}
|
||||||
printk("%llx\n", options);
|
printk(KERN_WARNING "%llx\n", options);
|
||||||
seq_printf(seq, "can POST: <integrated video>");
|
seq_printf(seq, "can POST: <integrated video>");
|
||||||
if (options & 2)
|
if (options & 2)
|
||||||
seq_printf(seq, " <PCI video>");
|
seq_printf(seq, " <PCI video>");
|
||||||
@@ -1712,7 +1712,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
|
|||||||
max = max_below = 0;
|
max = max_below = 0;
|
||||||
min = min_above = 255;
|
min = min_above = 255;
|
||||||
/* Find closest level to level_current */
|
/* Find closest level to level_current */
|
||||||
for (i = 0; i < device->brightness->count; i++) {
|
for (i = 2; i < device->brightness->count; i++) {
|
||||||
l = device->brightness->levels[i];
|
l = device->brightness->levels[i];
|
||||||
if (abs(l - level_current) < abs(delta)) {
|
if (abs(l - level_current) < abs(delta)) {
|
||||||
delta = l - level_current;
|
delta = l - level_current;
|
||||||
@@ -1722,7 +1722,7 @@ acpi_video_get_next_level(struct acpi_video_device *device,
|
|||||||
}
|
}
|
||||||
/* Ajust level_current to closest available level */
|
/* Ajust level_current to closest available level */
|
||||||
level_current += delta;
|
level_current += delta;
|
||||||
for (i = 0; i < device->brightness->count; i++) {
|
for (i = 2; i < device->brightness->count; i++) {
|
||||||
l = device->brightness->levels[i];
|
l = device->brightness->levels[i];
|
||||||
if (l < min)
|
if (l < min)
|
||||||
min = l;
|
min = l;
|
||||||
@@ -2006,6 +2006,12 @@ static int acpi_video_bus_add(struct acpi_device *device)
|
|||||||
device->pnp.bus_id[3] = '0' + instance;
|
device->pnp.bus_id[3] = '0' + instance;
|
||||||
instance ++;
|
instance ++;
|
||||||
}
|
}
|
||||||
|
/* a hack to fix the duplicate name "VGA" problem on Pa 3553 */
|
||||||
|
if (!strcmp(device->pnp.bus_id, "VGA")) {
|
||||||
|
if (instance)
|
||||||
|
device->pnp.bus_id[3] = '0' + instance;
|
||||||
|
instance++;
|
||||||
|
}
|
||||||
|
|
||||||
video->device = device;
|
video->device = device;
|
||||||
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
|
strcpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME);
|
||||||
|
@@ -42,6 +42,7 @@ config ASUS_LAPTOP
|
|||||||
depends on LEDS_CLASS
|
depends on LEDS_CLASS
|
||||||
depends on NEW_LEDS
|
depends on NEW_LEDS
|
||||||
depends on BACKLIGHT_CLASS_DEVICE
|
depends on BACKLIGHT_CLASS_DEVICE
|
||||||
|
depends on INPUT
|
||||||
---help---
|
---help---
|
||||||
This is the new Linux driver for Asus laptops. It may also support some
|
This is the new Linux driver for Asus laptops. It may also support some
|
||||||
MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
|
MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
|
||||||
|
@@ -46,6 +46,7 @@
|
|||||||
#include <acpi/acpi_drivers.h>
|
#include <acpi/acpi_drivers.h>
|
||||||
#include <acpi/acpi_bus.h>
|
#include <acpi/acpi_bus.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
#define ASUS_LAPTOP_VERSION "0.42"
|
#define ASUS_LAPTOP_VERSION "0.42"
|
||||||
|
|
||||||
@@ -181,6 +182,8 @@ struct asus_hotk {
|
|||||||
u8 light_level; //light sensor level
|
u8 light_level; //light sensor level
|
||||||
u8 light_switch; //light sensor switch value
|
u8 light_switch; //light sensor switch value
|
||||||
u16 event_count[128]; //count for each event TODO make this better
|
u16 event_count[128]; //count for each event TODO make this better
|
||||||
|
struct input_dev *inputdev;
|
||||||
|
u16 *keycode_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -250,6 +253,37 @@ ASUS_LED(rled, "record");
|
|||||||
ASUS_LED(pled, "phone");
|
ASUS_LED(pled, "phone");
|
||||||
ASUS_LED(gled, "gaming");
|
ASUS_LED(gled, "gaming");
|
||||||
|
|
||||||
|
struct key_entry {
|
||||||
|
char type;
|
||||||
|
u8 code;
|
||||||
|
u16 keycode;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { KE_KEY, KE_END };
|
||||||
|
|
||||||
|
static struct key_entry asus_keymap[] = {
|
||||||
|
{KE_KEY, 0x30, KEY_VOLUMEUP},
|
||||||
|
{KE_KEY, 0x31, KEY_VOLUMEDOWN},
|
||||||
|
{KE_KEY, 0x32, KEY_MUTE},
|
||||||
|
{KE_KEY, 0x33, KEY_SWITCHVIDEOMODE},
|
||||||
|
{KE_KEY, 0x34, KEY_SWITCHVIDEOMODE},
|
||||||
|
{KE_KEY, 0x40, KEY_PREVIOUSSONG},
|
||||||
|
{KE_KEY, 0x41, KEY_NEXTSONG},
|
||||||
|
{KE_KEY, 0x43, KEY_STOP},
|
||||||
|
{KE_KEY, 0x45, KEY_PLAYPAUSE},
|
||||||
|
{KE_KEY, 0x50, KEY_EMAIL},
|
||||||
|
{KE_KEY, 0x51, KEY_WWW},
|
||||||
|
{KE_KEY, 0x5C, BTN_EXTRA}, /* Performance */
|
||||||
|
{KE_KEY, 0x5D, KEY_WLAN},
|
||||||
|
{KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
|
||||||
|
{KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */
|
||||||
|
{KE_KEY, 0x82, KEY_CAMERA},
|
||||||
|
{KE_KEY, 0x8A, KEY_TV},
|
||||||
|
{KE_KEY, 0x95, KEY_MEDIA},
|
||||||
|
{KE_KEY, 0x99, KEY_PHONE},
|
||||||
|
{KE_END, 0},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function evaluates an ACPI method, given an int as parameter, the
|
* This function evaluates an ACPI method, given an int as parameter, the
|
||||||
* method is searched within the scope of the handle, can be NULL. The output
|
* method is searched within the scope of the handle, can be NULL. The output
|
||||||
@@ -720,8 +754,68 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
|
|||||||
return store_status(buf, count, NULL, GPS_ON);
|
return store_status(buf, count, NULL, GPS_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hotkey functions
|
||||||
|
*/
|
||||||
|
static struct key_entry *asus_get_entry_by_scancode(int code)
|
||||||
|
{
|
||||||
|
struct key_entry *key;
|
||||||
|
|
||||||
|
for (key = asus_keymap; key->type != KE_END; key++)
|
||||||
|
if (code == key->code)
|
||||||
|
return key;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct key_entry *asus_get_entry_by_keycode(int code)
|
||||||
|
{
|
||||||
|
struct key_entry *key;
|
||||||
|
|
||||||
|
for (key = asus_keymap; key->type != KE_END; key++)
|
||||||
|
if (code == key->keycode && key->type == KE_KEY)
|
||||||
|
return key;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
|
||||||
|
{
|
||||||
|
struct key_entry *key = asus_get_entry_by_scancode(scancode);
|
||||||
|
|
||||||
|
if (key && key->type == KE_KEY) {
|
||||||
|
*keycode = key->keycode;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
|
||||||
|
{
|
||||||
|
struct key_entry *key;
|
||||||
|
int old_keycode;
|
||||||
|
|
||||||
|
if (keycode < 0 || keycode > KEY_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
key = asus_get_entry_by_scancode(scancode);
|
||||||
|
if (key && key->type == KE_KEY) {
|
||||||
|
old_keycode = key->keycode;
|
||||||
|
key->keycode = keycode;
|
||||||
|
set_bit(keycode, dev->keybit);
|
||||||
|
if (!asus_get_entry_by_keycode(old_keycode))
|
||||||
|
clear_bit(old_keycode, dev->keybit);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
|
static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
|
||||||
{
|
{
|
||||||
|
static struct key_entry *key;
|
||||||
|
|
||||||
/* TODO Find a better way to handle events count. */
|
/* TODO Find a better way to handle events count. */
|
||||||
if (!hotk)
|
if (!hotk)
|
||||||
return;
|
return;
|
||||||
@@ -738,10 +832,24 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
|
|||||||
lcd_blank(FB_BLANK_POWERDOWN);
|
lcd_blank(FB_BLANK_POWERDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_bus_generate_proc_event(hotk->device, event,
|
acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
|
||||||
hotk->event_count[event % 128]++);
|
dev_name(&hotk->device->dev), event,
|
||||||
|
hotk->event_count[event % 128]++);
|
||||||
|
|
||||||
return;
|
if (hotk->inputdev) {
|
||||||
|
key = asus_get_entry_by_scancode(event);
|
||||||
|
if (!key)
|
||||||
|
return ;
|
||||||
|
|
||||||
|
switch (key->type) {
|
||||||
|
case KE_KEY:
|
||||||
|
input_report_key(hotk->inputdev, key->keycode, 1);
|
||||||
|
input_sync(hotk->inputdev);
|
||||||
|
input_report_key(hotk->inputdev, key->keycode, 0);
|
||||||
|
input_sync(hotk->inputdev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ASUS_CREATE_DEVICE_ATTR(_name) \
|
#define ASUS_CREATE_DEVICE_ATTR(_name) \
|
||||||
@@ -959,6 +1067,38 @@ static int asus_hotk_get_info(void)
|
|||||||
return AE_OK;
|
return AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int asus_input_init(void)
|
||||||
|
{
|
||||||
|
const struct key_entry *key;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
hotk->inputdev = input_allocate_device();
|
||||||
|
if (!hotk->inputdev) {
|
||||||
|
printk(ASUS_INFO "Unable to allocate input device\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
hotk->inputdev->name = "Asus Laptop extra buttons";
|
||||||
|
hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
|
||||||
|
hotk->inputdev->id.bustype = BUS_HOST;
|
||||||
|
hotk->inputdev->getkeycode = asus_getkeycode;
|
||||||
|
hotk->inputdev->setkeycode = asus_setkeycode;
|
||||||
|
|
||||||
|
for (key = asus_keymap; key->type != KE_END; key++) {
|
||||||
|
switch (key->type) {
|
||||||
|
case KE_KEY:
|
||||||
|
set_bit(EV_KEY, hotk->inputdev->evbit);
|
||||||
|
set_bit(key->keycode, hotk->inputdev->keybit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = input_register_device(hotk->inputdev);
|
||||||
|
if (result) {
|
||||||
|
printk(ASUS_INFO "Unable to register input device\n");
|
||||||
|
input_free_device(hotk->inputdev);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static int asus_hotk_check(void)
|
static int asus_hotk_check(void)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@@ -1044,7 +1184,7 @@ static int asus_hotk_add(struct acpi_device *device)
|
|||||||
/* GPS is on by default */
|
/* GPS is on by default */
|
||||||
write_status(NULL, 1, GPS_ON);
|
write_status(NULL, 1, GPS_ON);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (result) {
|
if (result) {
|
||||||
kfree(hotk->name);
|
kfree(hotk->name);
|
||||||
kfree(hotk);
|
kfree(hotk);
|
||||||
@@ -1091,10 +1231,17 @@ static void asus_led_exit(void)
|
|||||||
ASUS_LED_UNREGISTER(gled);
|
ASUS_LED_UNREGISTER(gled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void asus_input_exit(void)
|
||||||
|
{
|
||||||
|
if (hotk->inputdev)
|
||||||
|
input_unregister_device(hotk->inputdev);
|
||||||
|
}
|
||||||
|
|
||||||
static void __exit asus_laptop_exit(void)
|
static void __exit asus_laptop_exit(void)
|
||||||
{
|
{
|
||||||
asus_backlight_exit();
|
asus_backlight_exit();
|
||||||
asus_led_exit();
|
asus_led_exit();
|
||||||
|
asus_input_exit();
|
||||||
|
|
||||||
acpi_bus_unregister_driver(&asus_hotk_driver);
|
acpi_bus_unregister_driver(&asus_hotk_driver);
|
||||||
sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
|
sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
|
||||||
@@ -1216,6 +1363,10 @@ static int __init asus_laptop_init(void)
|
|||||||
printk(ASUS_INFO "Brightness ignored, must be controlled by "
|
printk(ASUS_INFO "Brightness ignored, must be controlled by "
|
||||||
"ACPI video driver\n");
|
"ACPI video driver\n");
|
||||||
|
|
||||||
|
result = asus_input_init();
|
||||||
|
if (result)
|
||||||
|
goto fail_input;
|
||||||
|
|
||||||
result = asus_led_init(dev);
|
result = asus_led_init(dev);
|
||||||
if (result)
|
if (result)
|
||||||
goto fail_led;
|
goto fail_led;
|
||||||
@@ -1242,22 +1393,25 @@ static int __init asus_laptop_init(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_sysfs:
|
fail_sysfs:
|
||||||
platform_device_del(asuspf_device);
|
platform_device_del(asuspf_device);
|
||||||
|
|
||||||
fail_platform_device2:
|
fail_platform_device2:
|
||||||
platform_device_put(asuspf_device);
|
platform_device_put(asuspf_device);
|
||||||
|
|
||||||
fail_platform_device1:
|
fail_platform_device1:
|
||||||
platform_driver_unregister(&asuspf_driver);
|
platform_driver_unregister(&asuspf_driver);
|
||||||
|
|
||||||
fail_platform_driver:
|
fail_platform_driver:
|
||||||
asus_led_exit();
|
asus_led_exit();
|
||||||
|
|
||||||
fail_led:
|
fail_led:
|
||||||
|
asus_input_exit();
|
||||||
|
|
||||||
|
fail_input:
|
||||||
asus_backlight_exit();
|
asus_backlight_exit();
|
||||||
|
|
||||||
fail_backlight:
|
fail_backlight:
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -143,6 +143,7 @@ struct asus_hotk {
|
|||||||
S1300N, S5200N*/
|
S1300N, S5200N*/
|
||||||
A4S, /* Z81sp */
|
A4S, /* Z81sp */
|
||||||
F3Sa, /* (Centrino) */
|
F3Sa, /* (Centrino) */
|
||||||
|
R1F,
|
||||||
END_MODEL
|
END_MODEL
|
||||||
} model; /* Models currently supported */
|
} model; /* Models currently supported */
|
||||||
u16 event_count[128]; /* Count for each event TODO make this better */
|
u16 event_count[128]; /* Count for each event TODO make this better */
|
||||||
@@ -420,7 +421,18 @@ static struct model_data model_conf[END_MODEL] = {
|
|||||||
.display_get = "\\ADVG",
|
.display_get = "\\ADVG",
|
||||||
.display_set = "SDSP",
|
.display_set = "SDSP",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "R1F",
|
||||||
|
.mt_bt_switch = "BLED",
|
||||||
|
.mt_mled = "MLED",
|
||||||
|
.mt_wled = "WLED",
|
||||||
|
.mt_lcd_switch = "\\Q10",
|
||||||
|
.lcd_status = "\\GP06",
|
||||||
|
.brightness_set = "SPLV",
|
||||||
|
.brightness_get = "GPLV",
|
||||||
|
.display_set = "SDSP",
|
||||||
|
.display_get = "\\INFB"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* procdir we use */
|
/* procdir we use */
|
||||||
@@ -1165,6 +1177,8 @@ static int asus_model_match(char *model)
|
|||||||
return W3V;
|
return W3V;
|
||||||
else if (strncmp(model, "W5A", 3) == 0)
|
else if (strncmp(model, "W5A", 3) == 0)
|
||||||
return W5A;
|
return W5A;
|
||||||
|
else if (strncmp(model, "R1F", 3) == 0)
|
||||||
|
return R1F;
|
||||||
else if (strncmp(model, "A4S", 3) == 0)
|
else if (strncmp(model, "A4S", 3) == 0)
|
||||||
return A4S;
|
return A4S;
|
||||||
else if (strncmp(model, "F3Sa", 4) == 0)
|
else if (strncmp(model, "F3Sa", 4) == 0)
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/rfkill.h>
|
#include <linux/rfkill.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#define EEEPC_LAPTOP_VERSION "0.1"
|
#define EEEPC_LAPTOP_VERSION "0.1"
|
||||||
|
|
||||||
@@ -161,6 +162,10 @@ static struct key_entry eeepc_keymap[] = {
|
|||||||
{KE_KEY, 0x13, KEY_MUTE },
|
{KE_KEY, 0x13, KEY_MUTE },
|
||||||
{KE_KEY, 0x14, KEY_VOLUMEDOWN },
|
{KE_KEY, 0x14, KEY_VOLUMEDOWN },
|
||||||
{KE_KEY, 0x15, KEY_VOLUMEUP },
|
{KE_KEY, 0x15, KEY_VOLUMEUP },
|
||||||
|
{KE_KEY, 0x1a, KEY_COFFEE },
|
||||||
|
{KE_KEY, 0x1b, KEY_ZOOM },
|
||||||
|
{KE_KEY, 0x1c, KEY_PROG2 },
|
||||||
|
{KE_KEY, 0x1d, KEY_PROG3 },
|
||||||
{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
|
{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
|
||||||
{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
|
{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
|
||||||
{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
|
{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
|
||||||
@@ -510,7 +515,43 @@ static int eeepc_hotk_check(void)
|
|||||||
static void notify_brn(void)
|
static void notify_brn(void)
|
||||||
{
|
{
|
||||||
struct backlight_device *bd = eeepc_backlight_device;
|
struct backlight_device *bd = eeepc_backlight_device;
|
||||||
bd->props.brightness = read_brightness(bd);
|
if (bd)
|
||||||
|
bd->props.brightness = read_brightness(bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
|
||||||
|
{
|
||||||
|
struct pci_dev *dev;
|
||||||
|
struct pci_bus *bus = pci_find_bus(0, 1);
|
||||||
|
|
||||||
|
if (event != ACPI_NOTIFY_BUS_CHECK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!bus) {
|
||||||
|
printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_acpi(CM_ASL_WLAN) == 1) {
|
||||||
|
dev = pci_get_slot(bus, 0);
|
||||||
|
if (dev) {
|
||||||
|
/* Device already present */
|
||||||
|
pci_dev_put(dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dev = pci_scan_single_device(bus, 0);
|
||||||
|
if (dev) {
|
||||||
|
pci_bus_assign_resources(bus);
|
||||||
|
if (pci_bus_add_device(dev))
|
||||||
|
printk(EEEPC_ERR "Unable to hotplug wifi\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dev = pci_get_slot(bus, 0);
|
||||||
|
if (dev) {
|
||||||
|
pci_remove_bus_device(dev);
|
||||||
|
pci_dev_put(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
||||||
@@ -520,8 +561,9 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
|||||||
return;
|
return;
|
||||||
if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
|
if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
|
||||||
notify_brn();
|
notify_brn();
|
||||||
acpi_bus_generate_proc_event(ehotk->device, event,
|
acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
|
||||||
ehotk->event_count[event % 128]++);
|
dev_name(&ehotk->device->dev), event,
|
||||||
|
ehotk->event_count[event % 128]++);
|
||||||
if (ehotk->inputdev) {
|
if (ehotk->inputdev) {
|
||||||
key = eepc_get_entry_by_scancode(event);
|
key = eepc_get_entry_by_scancode(event);
|
||||||
if (key) {
|
if (key) {
|
||||||
@@ -539,6 +581,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int eeepc_register_rfkill_notifier(char *node)
|
||||||
|
{
|
||||||
|
acpi_status status = AE_OK;
|
||||||
|
acpi_handle handle;
|
||||||
|
|
||||||
|
status = acpi_get_handle(NULL, node, &handle);
|
||||||
|
|
||||||
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
status = acpi_install_notify_handler(handle,
|
||||||
|
ACPI_SYSTEM_NOTIFY,
|
||||||
|
eeepc_rfkill_notify,
|
||||||
|
NULL);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
printk(EEEPC_WARNING
|
||||||
|
"Failed to register notify on %s\n", node);
|
||||||
|
} else
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eeepc_unregister_rfkill_notifier(char *node)
|
||||||
|
{
|
||||||
|
acpi_status status = AE_OK;
|
||||||
|
acpi_handle handle;
|
||||||
|
|
||||||
|
status = acpi_get_handle(NULL, node, &handle);
|
||||||
|
|
||||||
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
status = acpi_remove_notify_handler(handle,
|
||||||
|
ACPI_SYSTEM_NOTIFY,
|
||||||
|
eeepc_rfkill_notify);
|
||||||
|
if (ACPI_FAILURE(status))
|
||||||
|
printk(EEEPC_ERR
|
||||||
|
"Error removing rfkill notify handler %s\n",
|
||||||
|
node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int eeepc_hotk_add(struct acpi_device *device)
|
static int eeepc_hotk_add(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
acpi_status status = AE_OK;
|
acpi_status status = AE_OK;
|
||||||
@@ -558,7 +639,7 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
|||||||
ehotk->device = device;
|
ehotk->device = device;
|
||||||
result = eeepc_hotk_check();
|
result = eeepc_hotk_check();
|
||||||
if (result)
|
if (result)
|
||||||
goto end;
|
goto ehotk_fail;
|
||||||
status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
|
status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
|
||||||
eeepc_hotk_notify, ehotk);
|
eeepc_hotk_notify, ehotk);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
@@ -569,18 +650,25 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
|||||||
RFKILL_TYPE_WLAN);
|
RFKILL_TYPE_WLAN);
|
||||||
|
|
||||||
if (!ehotk->eeepc_wlan_rfkill)
|
if (!ehotk->eeepc_wlan_rfkill)
|
||||||
goto end;
|
goto wlan_fail;
|
||||||
|
|
||||||
ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
|
ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
|
||||||
ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
|
ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
|
||||||
ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
|
ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
|
||||||
if (get_acpi(CM_ASL_WLAN) == 1)
|
if (get_acpi(CM_ASL_WLAN) == 1) {
|
||||||
ehotk->eeepc_wlan_rfkill->state =
|
ehotk->eeepc_wlan_rfkill->state =
|
||||||
RFKILL_STATE_UNBLOCKED;
|
RFKILL_STATE_UNBLOCKED;
|
||||||
else
|
rfkill_set_default(RFKILL_TYPE_WLAN,
|
||||||
|
RFKILL_STATE_UNBLOCKED);
|
||||||
|
} else {
|
||||||
ehotk->eeepc_wlan_rfkill->state =
|
ehotk->eeepc_wlan_rfkill->state =
|
||||||
RFKILL_STATE_SOFT_BLOCKED;
|
RFKILL_STATE_SOFT_BLOCKED;
|
||||||
rfkill_register(ehotk->eeepc_wlan_rfkill);
|
rfkill_set_default(RFKILL_TYPE_WLAN,
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED);
|
||||||
|
}
|
||||||
|
result = rfkill_register(ehotk->eeepc_wlan_rfkill);
|
||||||
|
if (result)
|
||||||
|
goto wlan_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
|
if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
|
||||||
@@ -588,27 +676,47 @@ static int eeepc_hotk_add(struct acpi_device *device)
|
|||||||
rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
|
rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
|
||||||
|
|
||||||
if (!ehotk->eeepc_bluetooth_rfkill)
|
if (!ehotk->eeepc_bluetooth_rfkill)
|
||||||
goto end;
|
goto bluetooth_fail;
|
||||||
|
|
||||||
ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
|
ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
|
||||||
ehotk->eeepc_bluetooth_rfkill->toggle_radio =
|
ehotk->eeepc_bluetooth_rfkill->toggle_radio =
|
||||||
eeepc_bluetooth_rfkill_set;
|
eeepc_bluetooth_rfkill_set;
|
||||||
ehotk->eeepc_bluetooth_rfkill->get_state =
|
ehotk->eeepc_bluetooth_rfkill->get_state =
|
||||||
eeepc_bluetooth_rfkill_state;
|
eeepc_bluetooth_rfkill_state;
|
||||||
if (get_acpi(CM_ASL_BLUETOOTH) == 1)
|
if (get_acpi(CM_ASL_BLUETOOTH) == 1) {
|
||||||
ehotk->eeepc_bluetooth_rfkill->state =
|
ehotk->eeepc_bluetooth_rfkill->state =
|
||||||
RFKILL_STATE_UNBLOCKED;
|
RFKILL_STATE_UNBLOCKED;
|
||||||
else
|
rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
|
||||||
|
RFKILL_STATE_UNBLOCKED);
|
||||||
|
} else {
|
||||||
ehotk->eeepc_bluetooth_rfkill->state =
|
ehotk->eeepc_bluetooth_rfkill->state =
|
||||||
RFKILL_STATE_SOFT_BLOCKED;
|
RFKILL_STATE_SOFT_BLOCKED;
|
||||||
rfkill_register(ehotk->eeepc_bluetooth_rfkill);
|
rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
|
||||||
|
RFKILL_STATE_SOFT_BLOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
|
||||||
|
if (result)
|
||||||
|
goto bluetooth_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
|
||||||
if (result) {
|
eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
|
||||||
kfree(ehotk);
|
|
||||||
ehotk = NULL;
|
return 0;
|
||||||
}
|
|
||||||
|
bluetooth_fail:
|
||||||
|
if (ehotk->eeepc_bluetooth_rfkill)
|
||||||
|
rfkill_free(ehotk->eeepc_bluetooth_rfkill);
|
||||||
|
rfkill_unregister(ehotk->eeepc_wlan_rfkill);
|
||||||
|
ehotk->eeepc_wlan_rfkill = NULL;
|
||||||
|
wlan_fail:
|
||||||
|
if (ehotk->eeepc_wlan_rfkill)
|
||||||
|
rfkill_free(ehotk->eeepc_wlan_rfkill);
|
||||||
|
ehotk_fail:
|
||||||
|
kfree(ehotk);
|
||||||
|
ehotk = NULL;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,6 +730,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
|
|||||||
eeepc_hotk_notify);
|
eeepc_hotk_notify);
|
||||||
if (ACPI_FAILURE(status))
|
if (ACPI_FAILURE(status))
|
||||||
printk(EEEPC_ERR "Error removing notify handler\n");
|
printk(EEEPC_ERR "Error removing notify handler\n");
|
||||||
|
|
||||||
|
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
|
||||||
|
eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
|
||||||
|
|
||||||
kfree(ehotk);
|
kfree(ehotk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -737,13 +849,21 @@ static void eeepc_backlight_exit(void)
|
|||||||
{
|
{
|
||||||
if (eeepc_backlight_device)
|
if (eeepc_backlight_device)
|
||||||
backlight_device_unregister(eeepc_backlight_device);
|
backlight_device_unregister(eeepc_backlight_device);
|
||||||
if (ehotk->inputdev)
|
eeepc_backlight_device = NULL;
|
||||||
input_unregister_device(ehotk->inputdev);
|
}
|
||||||
|
|
||||||
|
static void eeepc_rfkill_exit(void)
|
||||||
|
{
|
||||||
if (ehotk->eeepc_wlan_rfkill)
|
if (ehotk->eeepc_wlan_rfkill)
|
||||||
rfkill_unregister(ehotk->eeepc_wlan_rfkill);
|
rfkill_unregister(ehotk->eeepc_wlan_rfkill);
|
||||||
if (ehotk->eeepc_bluetooth_rfkill)
|
if (ehotk->eeepc_bluetooth_rfkill)
|
||||||
rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
|
rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
|
||||||
eeepc_backlight_device = NULL;
|
}
|
||||||
|
|
||||||
|
static void eeepc_input_exit(void)
|
||||||
|
{
|
||||||
|
if (ehotk->inputdev)
|
||||||
|
input_unregister_device(ehotk->inputdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eeepc_hwmon_exit(void)
|
static void eeepc_hwmon_exit(void)
|
||||||
@@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void)
|
|||||||
static void __exit eeepc_laptop_exit(void)
|
static void __exit eeepc_laptop_exit(void)
|
||||||
{
|
{
|
||||||
eeepc_backlight_exit();
|
eeepc_backlight_exit();
|
||||||
|
eeepc_rfkill_exit();
|
||||||
|
eeepc_input_exit();
|
||||||
eeepc_hwmon_exit();
|
eeepc_hwmon_exit();
|
||||||
acpi_bus_unregister_driver(&eeepc_hotk_driver);
|
acpi_bus_unregister_driver(&eeepc_hotk_driver);
|
||||||
sysfs_remove_group(&platform_device->dev.kobj,
|
sysfs_remove_group(&platform_device->dev.kobj,
|
||||||
@@ -865,6 +987,8 @@ fail_platform_driver:
|
|||||||
fail_hwmon:
|
fail_hwmon:
|
||||||
eeepc_backlight_exit();
|
eeepc_backlight_exit();
|
||||||
fail_backlight:
|
fail_backlight:
|
||||||
|
eeepc_input_exit();
|
||||||
|
eeepc_rfkill_exit();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -507,7 +507,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
|
|||||||
|
|
||||||
hkey_num = result & 0xf;
|
hkey_num = result & 0xf;
|
||||||
|
|
||||||
if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) {
|
if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||||
"hotkey number out of range: %d\n",
|
"hotkey number out of range: %d\n",
|
||||||
hkey_num));
|
hkey_num));
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
|
#define ACPI_PDC_SMP_T_SWCOORD (0x0080)
|
||||||
#define ACPI_PDC_C_C1_FFH (0x0100)
|
#define ACPI_PDC_C_C1_FFH (0x0100)
|
||||||
#define ACPI_PDC_C_C2C3_FFH (0x0200)
|
#define ACPI_PDC_C_C2C3_FFH (0x0200)
|
||||||
|
#define ACPI_PDC_SMP_P_HWCOORD (0x0800)
|
||||||
|
|
||||||
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
|
#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
|
||||||
ACPI_PDC_C_C1_HALT | \
|
ACPI_PDC_C_C1_HALT | \
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
#define ACPI_PDC_EST_CAPABILITY_SWSMP (ACPI_PDC_SMP_C1PT | \
|
#define ACPI_PDC_EST_CAPABILITY_SWSMP (ACPI_PDC_SMP_C1PT | \
|
||||||
ACPI_PDC_C_C1_HALT | \
|
ACPI_PDC_C_C1_HALT | \
|
||||||
ACPI_PDC_SMP_P_SWCOORD | \
|
ACPI_PDC_SMP_P_SWCOORD | \
|
||||||
|
ACPI_PDC_SMP_P_HWCOORD | \
|
||||||
ACPI_PDC_P_FFH)
|
ACPI_PDC_P_FFH)
|
||||||
|
|
||||||
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
|
#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
|
||||||
|
@@ -57,16 +57,6 @@ int pm_notifier_call_chain(unsigned long val)
|
|||||||
#ifdef CONFIG_PM_DEBUG
|
#ifdef CONFIG_PM_DEBUG
|
||||||
int pm_test_level = TEST_NONE;
|
int pm_test_level = TEST_NONE;
|
||||||
|
|
||||||
static int suspend_test(int level)
|
|
||||||
{
|
|
||||||
if (pm_test_level == level) {
|
|
||||||
printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
|
|
||||||
mdelay(5000);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char * const pm_tests[__TEST_AFTER_LAST] = {
|
static const char * const pm_tests[__TEST_AFTER_LAST] = {
|
||||||
[TEST_NONE] = "none",
|
[TEST_NONE] = "none",
|
||||||
[TEST_CORE] = "core",
|
[TEST_CORE] = "core",
|
||||||
@@ -125,14 +115,24 @@ static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
power_attr(pm_test);
|
power_attr(pm_test);
|
||||||
#else /* !CONFIG_PM_DEBUG */
|
#endif /* CONFIG_PM_DEBUG */
|
||||||
static inline int suspend_test(int level) { return 0; }
|
|
||||||
#endif /* !CONFIG_PM_DEBUG */
|
|
||||||
|
|
||||||
#endif /* CONFIG_PM_SLEEP */
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
#ifdef CONFIG_SUSPEND
|
#ifdef CONFIG_SUSPEND
|
||||||
|
|
||||||
|
static int suspend_test(int level)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PM_DEBUG
|
||||||
|
if (pm_test_level == level) {
|
||||||
|
printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
|
||||||
|
mdelay(5000);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* !CONFIG_PM_DEBUG */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_TEST_SUSPEND
|
#ifdef CONFIG_PM_TEST_SUSPEND
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user