diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 3 | ||||
-rw-r--r-- | drivers/acpi/ac.c | 2 | ||||
-rw-r--r-- | drivers/acpi/bay.c | 2 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 240 | ||||
-rw-r--r-- | drivers/acpi/events/evgpe.c | 4 | ||||
-rw-r--r-- | drivers/acpi/fan.c | 35 | ||||
-rw-r--r-- | drivers/acpi/glue.c | 20 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 90 | ||||
-rw-r--r-- | drivers/acpi/power.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_core.c | 31 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 37 | ||||
-rw-r--r-- | drivers/acpi/processor_thermal.c | 30 | ||||
-rw-r--r-- | drivers/acpi/processor_throttling.c | 10 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 60 | ||||
-rw-r--r-- | drivers/acpi/sleep/main.c | 42 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 22 | ||||
-rw-r--r-- | drivers/acpi/utilities/utxface.c | 35 | ||||
-rw-r--r-- | drivers/acpi/video.c | 316 |
18 files changed, 512 insertions, 469 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b4f5e8542829..c52fca833268 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -140,6 +140,7 @@ config ACPI_VIDEO tristate "Video" depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL depends on INPUT + select THERMAL help This driver implement the ACPI Extensions For Display Adapters for integrated graphics devices on motherboard, as specified in @@ -151,6 +152,7 @@ config ACPI_VIDEO config ACPI_FAN tristate "Fan" + select THERMAL default y help This driver adds support for ACPI fan devices, allowing user-mode @@ -172,6 +174,7 @@ config ACPI_BAY config ACPI_PROCESSOR tristate "Processor" + select THERMAL default y help This driver installs ACPI as the idle handler for Linux, and uses diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 76b9bea98b6d..43a95e5640de 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -63,7 +63,7 @@ static int acpi_ac_add(struct acpi_device *device); static int acpi_ac_remove(struct acpi_device *device, int type); static int acpi_ac_resume(struct acpi_device *device); -const static struct acpi_device_id ac_device_ids[] = { +static const struct acpi_device_id ac_device_ids[] = { {"ACPI0003", 0}, {"", 0}, }; diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 1fa86811b8ee..d2fc94161848 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -201,6 +201,7 @@ static int is_ejectable_bay(acpi_handle handle) return 0; } +#if 0 /** * eject_removable_drive - try to eject this drive * @dev : the device structure of the drive @@ -225,6 +226,7 @@ int eject_removable_drive(struct device *dev) return 0; } EXPORT_SYMBOL_GPL(eject_removable_drive); +#endif /* 0 */ static int acpi_bay_add_fs(struct bay *bay) { diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7222a18a0319..3d9362140831 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -73,38 +73,14 @@ enum ec_event { #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ enum { EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ - EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ - EC_FLAGS_ADDRESS, /* Address is being written */ - EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ - EC_FLAGS_WDATA, /* Data is being written */ - EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ -}; - -static int acpi_ec_remove(struct acpi_device *device, int type); -static int acpi_ec_start(struct acpi_device *device); -static int acpi_ec_stop(struct acpi_device *device, int type); -static int acpi_ec_add(struct acpi_device *device); - -static const struct acpi_device_id ec_device_ids[] = { - {"PNP0C09", 0}, - {"", 0}, -}; - -static struct acpi_driver acpi_ec_driver = { - .name = "ec", - .class = ACPI_EC_CLASS, - .ids = ec_device_ids, - .ops = { - .add = acpi_ec_add, - .remove = acpi_ec_remove, - .start = acpi_ec_start, - .stop = acpi_ec_stop, - }, + EC_FLAGS_NO_GPE, /* Don't use GPE mode */ + EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ }; /* If we find an EC via the ECDT, we need to keep a ptr to its context */ @@ -129,6 +105,8 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; + struct delayed_work work; + atomic_t irq_count; u8 handlers_installed; } *boot_ec, *first_ec; @@ -177,65 +155,52 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) return 0; } -static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) +static void ec_schedule_ec_poll(struct acpi_ec *ec) { - int ret = 0; + if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) + schedule_delayed_work(&ec->work, + msecs_to_jiffies(ACPI_EC_DELAY)); +} - if (unlikely(event == ACPI_EC_EVENT_OBF_1 && - test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) - force_poll = 1; - if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && - test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) - force_poll = 1; - if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && - test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) - force_poll = 1; +static void ec_switch_to_poll_mode(struct acpi_ec *ec) +{ + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); +} + +static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) +{ + atomic_set(&ec->irq_count, 0); if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && likely(!force_poll)) { if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), msecs_to_jiffies(ACPI_EC_DELAY))) - goto end; + return 0; clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (acpi_ec_check_status(ec, event)) { - if (event == ACPI_EC_EVENT_OBF_1) { - /* miss OBF_1 GPE, don't expect it */ - pr_info(PREFIX "missing OBF confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); - } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { - /* miss address GPE, don't expect it anymore */ - pr_info(PREFIX "missing address confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); - } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { - /* miss write data GPE, don't expect it */ - pr_info(PREFIX "missing write data confirmation, " - "don't expect it any longer.\n"); - set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); - } else { - /* missing GPEs, switch back to poll mode */ - if (printk_ratelimit()) - pr_info(PREFIX "missing confirmations, " + /* missing GPEs, switch back to poll mode */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " "switch off interrupt mode.\n"); - clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - } - goto end; + ec_switch_to_poll_mode(ec); + ec_schedule_ec_poll(ec); + return 0; } } else { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) - goto end; + return 0; + udelay(ACPI_EC_UDELAY); } } - pr_err(PREFIX "acpi_ec_wait timeout," - " status = %d, expect_event = %d\n", - acpi_ec_read_status(ec), event); - ret = -ETIME; - end: - clear_bit(EC_FLAGS_ADDRESS, &ec->flags); - return ret; + pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", + acpi_ec_read_status(ec), + (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); + return -ETIME; } static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, @@ -245,8 +210,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, { int result = 0; set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); - acpi_ec_write_cmd(ec, command); pr_debug(PREFIX "transaction start\n"); + acpi_ec_write_cmd(ec, command); for (; wdata_len > 0; --wdata_len) { result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { @@ -254,15 +219,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, "write_cmd timeout, command = %d\n", command); goto end; } - /* mark the address byte written to EC */ - if (rdata_len + wdata_len > 1) - set_bit(EC_FLAGS_ADDRESS, &ec->flags); set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); acpi_ec_write_data(ec, *(wdata++)); } if (!rdata_len) { - set_bit(EC_FLAGS_WDATA, &ec->flags); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); if (result) { pr_err(PREFIX @@ -527,47 +488,51 @@ static u32 acpi_ec_gpe_handler(void *data) { acpi_status status = AE_OK; struct acpi_ec *ec = data; + u8 state = acpi_ec_read_status(ec); 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"); + ec_switch_to_poll_mode(ec); + goto end; + } clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) { + if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); - } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { + } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && + in_interrupt()) { /* this is non-query, must be confirmation */ if (printk_ratelimit()) pr_info(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); set_bit(EC_FLAGS_GPE_MODE, &ec->flags); + clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); } - +end: + ec_schedule_ec_poll(ec); return ACPI_SUCCESS(status) ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } +static void do_ec_poll(struct work_struct *work) +{ + struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); + atomic_set(&ec->irq_count, 0); + (void)acpi_ec_gpe_handler(ec); +} + /* -------------------------------------------------------------------------- Address Space Management -------------------------------------------------------------------------- */ static acpi_status -acpi_ec_space_setup(acpi_handle region_handle, - u32 function, void *handler_context, void **return_context) -{ - /* - * The EC object is in the handler context and is needed - * when calling the acpi_ec_space_handler. - */ - *return_context = (function != ACPI_REGION_DEACTIVATE) ? - handler_context : NULL; - - return AE_OK; -} - -static acpi_status acpi_ec_space_handler(u32 function, acpi_physical_address address, u32 bits, acpi_integer *value, void *handler_context, void *region_context) @@ -709,6 +674,8 @@ static struct acpi_ec *make_acpi_ec(void) mutex_init(&ec->lock); init_waitqueue_head(&ec->wait); INIT_LIST_HEAD(&ec->list); + INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); + atomic_set(&ec->irq_count, 0); return ec; } @@ -741,17 +708,21 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); if (ACPI_FAILURE(status)) return status; - /* Find and register all query methods */ - acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, - acpi_ec_register_query_methods, ec, NULL); /* Use the global lock for all EC transactions? */ acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); ec->handle = handle; return AE_CTRL_TERMINATE; } +static void ec_poll_stop(struct acpi_ec *ec) +{ + clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); + cancel_delayed_work(&ec->work); +} + static void ec_remove_handlers(struct acpi_ec *ec) { + ec_poll_stop(ec); if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) pr_err(PREFIX "failed to remove space handler\n"); @@ -771,31 +742,28 @@ static int acpi_ec_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_EC_CLASS); /* Check for boot EC */ - if (boot_ec) { - if (boot_ec->handle == device->handle) { - /* Pre-loaded EC from DSDT, just move pointer */ - ec = boot_ec; - boot_ec = NULL; - goto end; - } else if (boot_ec->handle == ACPI_ROOT_OBJECT) { - /* ECDT-based EC, time to shut it down */ - ec_remove_handlers(boot_ec); - kfree(boot_ec); - first_ec = boot_ec = NULL; + if (boot_ec && + (boot_ec->handle == device->handle || + boot_ec->handle == ACPI_ROOT_OBJECT)) { + ec = boot_ec; + boot_ec = NULL; + } else { + ec = make_acpi_ec(); + if (!ec) + return -ENOMEM; + if (ec_parse_device(device->handle, 0, ec, NULL) != + AE_CTRL_TERMINATE) { + kfree(ec); + return -EINVAL; } } - ec = make_acpi_ec(); - if (!ec) - return -ENOMEM; - - if (ec_parse_device(device->handle, 0, ec, NULL) != - AE_CTRL_TERMINATE) { - kfree(ec); - return -EINVAL; - } ec->handle = device->handle; - end: + + /* Find and register all query methods */ + acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, + acpi_ec_register_query_methods, ec, NULL); + if (!first_ec) first_ec = ec; acpi_driver_data(device) = ec; @@ -870,7 +838,7 @@ static int ec_install_handlers(struct acpi_ec *ec) status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, - &acpi_ec_space_setup, ec); + NULL, ec); if (ACPI_FAILURE(status)) { acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); return -ENODEV; @@ -897,6 +865,7 @@ static int acpi_ec_start(struct acpi_device *device) /* EC is fully operational, allow queries */ clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); + ec_schedule_ec_poll(ec); return ret; } @@ -924,6 +893,11 @@ int __init acpi_boot_ec_enable(void) return -EFAULT; } +static const struct acpi_device_id ec_device_ids[] = { + {"PNP0C09", 0}, + {"", 0}, +}; + int __init acpi_ec_ecdt_probe(void) { int ret; @@ -944,6 +918,7 @@ int __init acpi_ec_ecdt_probe(void) boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->gpe = ecdt_ptr->gpe; boot_ec->handle = ACPI_ROOT_OBJECT; + acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); } else { /* This workaround is needed only on some broken machines, * which require early EC, but fail to provide ECDT */ @@ -973,6 +948,39 @@ int __init acpi_ec_ecdt_probe(void) return -ENODEV; } +static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) +{ + struct acpi_ec *ec = acpi_driver_data(device); + /* Stop using GPE */ + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + return 0; +} + +static int acpi_ec_resume(struct acpi_device *device) +{ + struct acpi_ec *ec = acpi_driver_data(device); + /* Enable use of GPE back */ + clear_bit(EC_FLAGS_NO_GPE, &ec->flags); + acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + return 0; +} + +static struct acpi_driver acpi_ec_driver = { + .name = "ec", + .class = ACPI_EC_CLASS, + .ids = ec_device_ids, + .ops = { + .add = acpi_ec_add, + .remove = acpi_ec_remove, + .start = acpi_ec_start, + .stop = acpi_ec_stop, + .suspend = acpi_ec_suspend, + .resume = acpi_ec_resume, + }, +}; + static int __init acpi_ec_init(void) { int result = 0; diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index f55e1fd9e0b8..5354be44f876 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -248,10 +248,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) ACPI_FUNCTION_TRACE(ev_disable_gpe); - if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) { - return_ACPI_STATUS(AE_OK); - } - /* Make sure HW enable masks are updated */ status = diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index c8e3cba423ef..cf635cde836b 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -260,24 +260,23 @@ static int acpi_fan_add(struct acpi_device *device) result = PTR_ERR(cdev); goto end; } - if (cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, cdev->id); - - acpi_driver_data(device) = cdev; - result = sysfs_create_link(&device->dev.kobj, - &cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - - result = sysfs_create_link(&cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) - return result; - } + + printk(KERN_INFO PREFIX + "%s is registered as cooling_device%d\n", + device->dev.bus_id, cdev->id); + + acpi_driver_data(device) = cdev; + result = sysfs_create_link(&device->dev.kobj, + &cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + + result = sysfs_create_link(&cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); result = acpi_fan_add_fs(device); if (result) diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index eda0978b57c6..06f8634fe58b 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -142,6 +142,7 @@ EXPORT_SYMBOL(acpi_get_physical_device); static int acpi_bind_one(struct device *dev, acpi_handle handle) { + struct acpi_device *acpi_dev; acpi_status status; if (dev->archdata.acpi_handle) { @@ -157,6 +158,16 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) } dev->archdata.acpi_handle = handle; + status = acpi_bus_get_device(handle, &acpi_dev); + if (!ACPI_FAILURE(status)) { + int ret; + + ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, + "firmware_node"); + ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, + "physical_node"); + } + return 0; } @@ -165,8 +176,17 @@ static int acpi_unbind_one(struct device *dev) if (!dev->archdata.acpi_handle) return 0; if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { + struct acpi_device *acpi_dev; + /* acpi_get_physical_device increase refcnt by one */ put_device(dev); + + if (!acpi_bus_get_device(dev->archdata.acpi_handle, + &acpi_dev)) { + sysfs_remove_link(&dev->kobj, "firmware_node"); + sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); + } + acpi_detach_data(dev->archdata.acpi_handle, acpi_glue_data_handler); dev->archdata.acpi_handle = NULL; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index a697fb6cf050..235a1386888a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -4,6 +4,8 @@ * Copyright (C) 2000 Andrew Henroid * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> + * Copyright (c) 2008 Intel Corporation + * Author: Matthew Wilcox <willy@linux.intel.com> * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -37,15 +39,18 @@ #include <linux/workqueue.h> #include <linux/nmi.h> #include <linux/acpi.h> -#include <acpi/acpi.h> -#include <asm/io.h> -#include <acpi/acpi_bus.h> -#include <acpi/processor.h> -#include <asm/uaccess.h> - #include <linux/efi.h> #include <linux/ioport.h> #include <linux/list.h> +#include <linux/jiffies.h> +#include <linux/semaphore.h> + +#include <asm/io.h> +#include <asm/uaccess.h> + +#include <acpi/acpi.h> +#include <acpi/acpi_bus.h> +#include <acpi/processor.h> #define _COMPONENT ACPI_OS_SERVICES ACPI_MODULE_NAME("osl"); @@ -737,6 +742,7 @@ EXPORT_SYMBOL(acpi_os_execute); void acpi_os_wait_events_complete(void *context) { flush_workqueue(kacpid_wq); + flush_workqueue(kacpi_notify_wq); } EXPORT_SYMBOL(acpi_os_wait_events_complete); @@ -764,7 +770,6 @@ acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) { struct semaphore *sem = NULL; - sem = acpi_os_allocate(sizeof(struct semaphore)); if (!sem) return AE_NO_MEMORY; @@ -791,12 +796,12 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle) { struct semaphore *sem = (struct semaphore *)handle; - if (!sem) return AE_BAD_PARAMETER; ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle)); + BUG_ON(!list_empty(&sem->wait_list)); kfree(sem); sem = NULL; @@ -804,21 +809,15 @@ acpi_status acpi_os_delete_semaphore(acpi_handle handle) } /* - * TODO: The kernel doesn't have a 'down_timeout' function -- had to - * improvise. The process is to sleep for one scheduler quantum - * until the semaphore becomes available. Downside is that this - * may result in starvation for timeout-based waits when there's - * lots of semaphore activity. - * * TODO: Support for units > 1? */ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) { acpi_status status = AE_OK; struct semaphore *sem = (struct semaphore *)handle; + long jiffies; int ret = 0; - if (!sem || (units < 1)) return AE_BAD_PARAMETER; @@ -828,58 +827,14 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); - /* - * This can be called during resume with interrupts off. - * Like boot-time, we should be single threaded and will - * always get the lock if we try -- timeout or not. - * If this doesn't succeed, then we will oops courtesy of - * might_sleep() in down(). - */ - if (!down_trylock(sem)) - return AE_OK; - - switch (timeout) { - /* - * No Wait: - * -------- - * A zero timeout value indicates that we shouldn't wait - just - * acquire the semaphore if available otherwise return AE_TIME - * (a.k.a. 'would block'). - */ - case 0: - if (down_trylock(sem)) - status = AE_TIME; - break; - - /* - * Wait Indefinitely: - * ------------------ - */ - case ACPI_WAIT_FOREVER: - down(sem); - break; - - /* - * Wait w/ Timeout: - * ---------------- - */ - default: - // TODO: A better timeout algorithm? - { - int i = 0; - static const int quantum_ms = 1000 / HZ; - - ret = down_trylock(sem); - for (i = timeout; (i > 0 && ret != 0); i -= quantum_ms) { - schedule_timeout_interruptible(1); - ret = down_trylock(sem); - } - - if (ret != 0) - status = AE_TIME; - } - break; - } + if (timeout == ACPI_WAIT_FOREVER) + jiffies = MAX_SCHEDULE_TIMEOUT; + else + jiffies = msecs_to_jiffies(timeout); + + ret = down_timeout(sem, jiffies); + if (ret) + status = AE_TIME; if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, @@ -902,7 +857,6 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) { struct semaphore *sem = (struct semaphore *)handle; - if (!sem || (units < 1)) return AE_BAD_PARAMETER; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 76bf6d90c700..f2a76acecfcd 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -121,7 +121,7 @@ acpi_power_get_context(acpi_handle handle, } *resource = acpi_driver_data(device); - if (!resource) + if (!*resource) return -ENODEV; return 0; diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a825b431b64f..ea5f628dcc15 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -674,22 +674,21 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) result = PTR_ERR(pr->cdev); goto end; } - if (pr->cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, pr->cdev->id); - - result = sysfs_create_link(&device->dev.kobj, - &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - result = sysfs_create_link(&pr->cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) - return result; - } + + printk(KERN_INFO PREFIX + "%s is registered as cooling_device%d\n", + device->dev.bus_id, pr->cdev->id); + + result = sysfs_create_link(&device->dev.kobj, + &pr->cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&pr->cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); if (pr->flags.throttling) { printk(KERN_INFO PREFIX "%s [%s] (supports", diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 788da9781f80..55d69dce47c4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -418,13 +418,12 @@ static void acpi_processor_idle(void) cx = pr->power.state; if (!cx || acpi_idle_suspend) { - if (pm_idle_save) - pm_idle_save(); - else + if (pm_idle_save) { + pm_idle_save(); /* enables IRQs */ + } else { acpi_safe_halt(); - - if (irqs_disabled()) local_irq_enable(); + } return; } @@ -520,10 +519,12 @@ static void acpi_processor_idle(void) * Use the appropriate idle routine, the one that would * be used without acpi C-states. */ - if (pm_idle_save) - pm_idle_save(); - else + 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 @@ -534,8 +535,6 @@ static void acpi_processor_idle(void) * skew otherwise. */ sleep_ticks = 0xFFFFFFFF; - if (irqs_disabled()) - local_irq_enable(); break; @@ -848,6 +847,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) /* all processors need to support C1 */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; + pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; @@ -960,6 +960,9 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.address); } + if (cx.type == ACPI_STATE_C1) { + cx.valid = 1; + } obj = &(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) @@ -1295,6 +1298,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int result = 0; + if (boot_option_idle_override) + return 0; if (!pr) return -EINVAL; @@ -1734,6 +1739,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) { int ret; + if (boot_option_idle_override) + return 0; + if (!pr) return -EINVAL; @@ -1764,6 +1772,8 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, struct proc_dir_entry *entry = NULL; unsigned int i; + if (boot_option_idle_override) + return 0; if (!first_run) { dmi_check_system(processor_power_dmi_table); @@ -1799,7 +1809,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, * Note that we use previously set idle handler will be used on * platforms that only support C1. */ - if ((pr->flags.power) && (!boot_option_idle_override)) { + if (pr->flags.power) { #ifdef CONFIG_CPU_IDLE acpi_processor_setup_cpuidle(pr); pr->power.dev.cpu = pr->id; @@ -1839,8 +1849,11 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device) { + if (boot_option_idle_override) + return 0; + #ifdef CONFIG_CPU_IDLE - if ((pr->flags.power) && (!boot_option_idle_override)) + if (pr->flags.power) cpuidle_unregister_device(&pr->power.dev); #endif pr->flags.power_setup_done = 0; diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 9cb43f52f7b6..649ae99b9216 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -97,7 +97,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr) #define CPUFREQ_THERMAL_MIN_STEP 0 #define CPUFREQ_THERMAL_MAX_STEP 3 -static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS]; +static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); static unsigned int acpi_thermal_cpufreq_is_init = 0; static int cpu_has_cpufreq(unsigned int cpu) @@ -113,9 +113,9 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return -ENODEV; - if (cpufreq_thermal_reduction_pctg[cpu] < + if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) < CPUFREQ_THERMAL_MAX_STEP) { - cpufreq_thermal_reduction_pctg[cpu]++; + per_cpu(cpufreq_thermal_reduction_pctg, cpu)++; cpufreq_update_policy(cpu); return 0; } @@ -128,14 +128,14 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return -ENODEV; - if (cpufreq_thermal_reduction_pctg[cpu] > + if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) > (CPUFREQ_THERMAL_MIN_STEP + 1)) - cpufreq_thermal_reduction_pctg[cpu]--; + per_cpu(cpufreq_thermal_reduction_pctg, cpu)--; else - cpufreq_thermal_reduction_pctg[cpu] = 0; + per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0; cpufreq_update_policy(cpu); /* We reached max freq again and can leave passive mode */ - return !cpufreq_thermal_reduction_pctg[cpu]; + return !per_cpu(cpufreq_thermal_reduction_pctg, cpu); } static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, @@ -147,9 +147,10 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, if (event != CPUFREQ_ADJUST) goto out; - max_freq = - (policy->cpuinfo.max_freq * - (100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100; + max_freq = ( + policy->cpuinfo.max_freq * + (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) + ) / 100; cpufreq_verify_within_limits(policy, 0, max_freq); @@ -174,7 +175,7 @@ static int cpufreq_get_cur_state(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return 0; - return cpufreq_thermal_reduction_pctg[cpu]; + return per_cpu(cpufreq_thermal_reduction_pctg, cpu); } static int cpufreq_set_cur_state(unsigned int cpu, int state) @@ -182,7 +183,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) if (!cpu_has_cpufreq(cpu)) return 0; - cpufreq_thermal_reduction_pctg[cpu] = state; + per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; cpufreq_update_policy(cpu); return 0; } @@ -191,8 +192,9 @@ void acpi_thermal_cpufreq_init(void) { int i; - for (i = 0; i < NR_CPUS; i++) - cpufreq_thermal_reduction_pctg[i] = 0; + for (i = 0; i < nr_cpu_ids; i++) + if (cpu_present(i)) + per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER); diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 1b8e592a8241..0bba3a914e86 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -838,10 +838,10 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr) * Migrate task to the cpu pointed by pr. */ saved_mask = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(pr->id)); + set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id)); ret = pr->throttling.acpi_processor_get_throttling(pr); /* restore the previous state */ - set_cpus_allowed(current, saved_mask); + set_cpus_allowed_ptr(current, &saved_mask); return ret; } @@ -1025,7 +1025,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) * it can be called only for the cpu pointed by pr. */ if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { - set_cpus_allowed(current, cpumask_of_cpu(pr->id)); + set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id)); ret = p_throttling->acpi_processor_set_throttling(pr, t_state.target_state); } else { @@ -1056,7 +1056,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) continue; } t_state.cpu = i; - set_cpus_allowed(current, cpumask_of_cpu(i)); + set_cpus_allowed_ptr(current, &cpumask_of_cpu(i)); ret = match_pr->throttling. acpi_processor_set_throttling( match_pr, t_state.target_state); @@ -1074,7 +1074,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) &t_state); } /* restore the previous state */ - set_cpus_allowed(current, saved_mask); + set_cpus_allowed_ptr(current, &saved_mask); return ret; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 464ee6ea8c61..6d85289f1c12 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -691,6 +691,9 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *package = NULL; + union acpi_object in_arg[3]; + struct acpi_object_list arg_list = { 3, in_arg }; + acpi_status psw_status = AE_OK; struct acpi_device_id button_device_ids[] = { {"PNP0C0D", 0}, @@ -699,7 +702,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) {"", 0}, }; - /* _PRW */ status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -717,6 +719,45 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) kfree(buffer.pointer); device->wakeup.flags.valid = 1; + /* Call _PSW/_DSW object to disable its ability to wake the sleeping + * system for the ACPI device with the _PRW object. + * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. + * So it is necessary to call _DSW object first. Only when it is not + * present will the _PSW object used. + */ + /* + * Three agruments are needed for the _DSW object. + * Argument 0: enable/disable the wake capabilities + * When _DSW object is called to disable the wake capabilities, maybe + * the first argument is filled. The value of the other two agruments + * is meaningless. + */ + in_arg[0].type = ACPI_TYPE_INTEGER; + in_arg[0].integer.value = 0; + in_arg[1].type = ACPI_TYPE_INTEGER; + in_arg[1].integer.value = 0; + in_arg[2].type = ACPI_TYPE_INTEGER; + in_arg[2].integer.value = 0; + psw_status = acpi_evaluate_object(device->handle, "_DSW", + &arg_list, NULL); + if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n")); + /* + * When the _DSW object is not present, OSPM will call _PSW object. + */ + if (psw_status == AE_NOT_FOUND) { + /* + * Only one agruments is required for the _PSW object. + * agrument 0: enable/disable the wake capabilities + */ + arg_list.count = 1; + in_arg[0].integer.value = 0; + psw_status = acpi_evaluate_object(device->handle, "_PSW", + &arg_list, NULL); + if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in " + "evaluate _PSW\n")); + } /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; @@ -881,10 +922,7 @@ static void acpi_device_get_busid(struct acpi_device *device, static int acpi_video_bus_match(struct acpi_device *device) { - acpi_handle h_dummy1; - acpi_handle h_dummy2; - acpi_handle h_dummy3; - + acpi_handle h_dummy; if (!device) return -EINVAL; @@ -894,18 +932,18 @@ acpi_video_bus_match(struct acpi_device *device) */ /* Does this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2))) + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) return 0; /* Does this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1))) + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) return 0; /* Does this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3))) + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) return 0; return -ENODEV; diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 71183eea7906..c3b0cd88d09f 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -51,7 +51,7 @@ static int acpi_sleep_prepare(u32 acpi_state) } #ifdef CONFIG_SUSPEND -static struct platform_suspend_ops acpi_pm_ops; +static struct platform_suspend_ops acpi_suspend_ops; extern void do_suspend_lowlevel(void); @@ -65,11 +65,11 @@ static u32 acpi_suspend_states[] = { static int init_8259A_after_S1; /** - * acpi_pm_begin - Set the target system sleep state to the state + * acpi_suspend_begin - Set the target system sleep state to the state * associated with given @pm_state, if supported. */ -static int acpi_pm_begin(suspend_state_t pm_state) +static int acpi_suspend_begin(suspend_state_t pm_state) { u32 acpi_state = acpi_suspend_states[pm_state]; int error = 0; @@ -85,13 +85,13 @@ static int acpi_pm_begin(suspend_state_t pm_state) } /** - * acpi_pm_prepare - Do preliminary suspend work. + * acpi_suspend_prepare - Do preliminary suspend work. * * If necessary, set the firmware waking vector and do arch-specific * nastiness to get the wakeup code to the waking vector. */ -static int acpi_pm_prepare(void) +static int acpi_suspend_prepare(void) { int error = acpi_sleep_prepare(acpi_target_sleep_state); @@ -104,7 +104,7 @@ static int acpi_pm_prepare(void) } /** - * acpi_pm_enter - Actually enter a sleep state. + * acpi_suspend_enter - Actually enter a sleep state. * @pm_state: ignored * * Flush caches and go to sleep. For STR we have to call arch-specific @@ -112,7 +112,7 @@ static int acpi_pm_prepare(void) * It's unfortunate, but it works. Please fix if you're feeling frisky. */ -static int acpi_pm_enter(suspend_state_t pm_state) +static int acpi_suspend_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; unsigned long flags = 0; @@ -169,13 +169,13 @@ static int acpi_pm_enter(suspend_state_t pm_state) } /** - * acpi_pm_finish - Instruct the platform to leave a sleep state. + * acpi_suspend_finish - Instruct the platform to leave a sleep state. * * This is called after we wake back up (or if entering the sleep state * failed). */ -static void acpi_pm_finish(void) +static void acpi_suspend_finish(void) { u32 acpi_state = acpi_target_sleep_state; @@ -196,19 +196,19 @@ static void acpi_pm_finish(void) } /** - * acpi_pm_end - Finish up suspend sequence. + * acpi_suspend_end - Finish up suspend sequence. */ -static void acpi_pm_end(void) +static void acpi_suspend_end(void) { /* - * This is necessary in case acpi_pm_finish() is not called during a + * This is necessary in case acpi_suspend_finish() is not called during a * failing transition to a sleep state. */ acpi_target_sleep_state = ACPI_STATE_S0; } -static int acpi_pm_state_valid(suspend_state_t pm_state) +static int acpi_suspend_state_valid(suspend_state_t pm_state) { u32 acpi_state; @@ -224,13 +224,13 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) } } -static struct platform_suspend_ops acpi_pm_ops = { - .valid = acpi_pm_state_valid, - .begin = acpi_pm_begin, - .prepare = acpi_pm_prepare, - .enter = acpi_pm_enter, - .finish = acpi_pm_finish, - .end = acpi_pm_end, +static struct platform_suspend_ops acpi_suspend_ops = { + .valid = acpi_suspend_state_valid, + .begin = acpi_suspend_begin, + .prepare = acpi_suspend_prepare, + .enter = acpi_suspend_enter, + .finish = acpi_suspend_finish, + .end = acpi_suspend_end, }; /* @@ -492,7 +492,7 @@ int __init acpi_sleep_init(void) } } - suspend_set_ops(&acpi_pm_ops); + suspend_set_ops(&acpi_suspend_ops); #endif #ifdef CONFIG_HIBERNATION diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 1bcecc7dd2ca..782c2250443e 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -884,10 +884,15 @@ static void acpi_thermal_check(void *data) static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) { struct acpi_thermal *tz = thermal->devdata; + int result; if (!tz) return -EINVAL; + result = acpi_thermal_get_temperature(tz); + if (result) + return result; + return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature)); } @@ -1012,6 +1017,18 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, return -EINVAL; } +static int thermal_get_crit_temp(struct thermal_zone_device *thermal, + unsigned long *temperature) { + struct acpi_thermal *tz = thermal->devdata; + + if (tz->trips.critical.flags.valid) { + *temperature = KELVIN_TO_MILLICELSIUS( + tz->trips.critical.temperature); + return 0; + } else + return -EINVAL; +} + typedef int (*cb)(struct thermal_zone_device *, int, struct thermal_cooling_device *); static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, @@ -1103,6 +1120,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { .set_mode = thermal_set_mode, .get_trip_type = thermal_get_trip_type, .get_trip_temp = thermal_get_trip_temp, + .get_crit_temp = thermal_get_crit_temp, }; static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) @@ -1123,7 +1141,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++, trips++); - tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone", + tz->thermal_zone = thermal_zone_device_register("acpitz", trips, tz, &acpi_thermal_zone_ops); if (IS_ERR(tz->thermal_zone)) return -ENODEV; @@ -1710,7 +1728,6 @@ static int acpi_thermal_resume(struct acpi_device *device) return AE_OK; } -#ifdef CONFIG_DMI static int thermal_act(const struct dmi_system_id *d) { if (act == 0) { @@ -1785,7 +1802,6 @@ static struct dmi_system_id thermal_dmi_table[] __initdata = { }, {} }; -#endif /* CONFIG_DMI */ static int __init acpi_thermal_init(void) { diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index a92d91277ef9..f8bdadf3c32f 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c @@ -193,24 +193,6 @@ acpi_status acpi_enable_subsystem(u32 flags) } } - /* - * Complete the GPE initialization for the GPE blocks defined in the FADT - * (GPE block 0 and 1). - * - * Note1: This is where the _PRW methods are executed for the GPEs. These - * methods can only be executed after the SCI and Global Lock handlers are - * installed and initialized. - * - * Note2: Currently, there seems to be no need to run the _REG methods - * before execution of the _PRW methods and enabling of the GPEs. - */ - if (!(flags & ACPI_NO_EVENT_INIT)) { - status = acpi_ev_install_fadt_gpes(); - if (ACPI_FAILURE(status)) { - return (status); - } - } - return_ACPI_STATUS(status); } @@ -281,6 +263,23 @@ acpi_status acpi_initialize_objects(u32 flags) } /* + * Complete the GPE initialization for the GPE blocks defined in the FADT + * (GPE block 0 and 1). + * + * Note1: This is where the _PRW methods are executed for the GPEs. These + * methods can only be executed after the SCI and Global Lock handlers are + * installed and initialized. + * + * Note2: Currently, there seems to be no need to run the _REG methods + * before execution of the _PRW methods and enabling of the GPEs. + */ + if (!(flags & ACPI_NO_EVENT_INIT)) { + status = acpi_ev_install_fadt_gpes(); + if (ACPI_FAILURE(status)) + return (status); + } + + /* * Empty the caches (delete the cached objects) on the assumption that * the table load filled them up more than they will be at runtime -- * thus wasting non-paged memory. diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 980a74188781..33c502e56026 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -57,8 +57,6 @@ #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 -#define ACPI_VIDEO_HEAD_INVALID (~0u - 1) -#define ACPI_VIDEO_HEAD_END (~0u) #define MAX_NAME_LEN 20 #define ACPI_VIDEO_DISPLAY_CRT 1 @@ -734,21 +732,19 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (IS_ERR(device->cdev)) return; - if (device->cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev->dev.bus_id, device->cdev->id); - result = sysfs_create_link(&device->dev->dev.kobj, - &device->cdev->device.kobj, - "thermal_cooling"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - result = sysfs_create_link(&device->cdev->device.kobj, - &device->dev->dev.kobj, - "device"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - } + printk(KERN_INFO PREFIX + "%s is registered as cooling_device%d\n", + device->dev->dev.bus_id, device->cdev->id); + result = sysfs_create_link(&device->dev->dev.kobj, + &device->cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&device->cdev->device.kobj, + &device->dev->dev.kobj, "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + } if (device->cap._DCS && device->cap._DSS){ static int count = 0; @@ -1050,87 +1046,90 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) static int acpi_video_device_add_fs(struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; + struct proc_dir_entry *entry, *device_dir; struct acpi_video_device *vid_dev; - - if (!device) - return -ENODEV; - vid_dev = acpi_driver_data(device); if (!vid_dev) return -ENODEV; - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - vid_dev->video->dir); - if (!acpi_device_dir(device)) - return -ENODEV; - acpi_device_dir(device)->owner = THIS_MODULE; - } + device_dir = proc_mkdir(acpi_device_bid(device), + vid_dev->video->dir); + if (!device_dir) + return -ENOMEM; + + device_dir->owner = THIS_MODULE; /* 'info' [R] */ - entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("info", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_device_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_dir; + + entry->proc_fops = &acpi_video_device_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'state' [R/W] */ - entry = - create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device)); + entry = create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_device_state_fops.write = acpi_video_device_write_state; - entry->proc_fops = &acpi_video_device_state_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_info; + + acpi_video_device_state_fops.write = acpi_video_device_write_state; + entry->proc_fops = &acpi_video_device_state_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'brightness' [R/W] */ - entry = - create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device)); + entry = create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness; - entry->proc_fops = &acpi_video_device_brightness_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_state; + + acpi_video_device_brightness_fops.write = + acpi_video_device_write_brightness; + entry->proc_fops = &acpi_video_device_brightness_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'EDID' [R] */ - entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("EDID", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_device_EDID_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_brightness; + entry->proc_fops = &acpi_video_device_EDID_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + + acpi_device_dir(device) = device_dir; return 0; + + err_remove_brightness: + remove_proc_entry("brightness", device_dir); + err_remove_state: + remove_proc_entry("state", device_dir); + err_remove_info: + remove_proc_entry("info", device_dir); + err_remove_dir: + remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); + return -ENOMEM; } static int acpi_video_device_remove_fs(struct acpi_device *device) { struct acpi_video_device *vid_dev; + struct proc_dir_entry *device_dir; vid_dev = acpi_driver_data(device); if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) return -ENODEV; - if (acpi_device_dir(device)) { - remove_proc_entry("info", acpi_device_dir(device)); - remove_proc_entry("state", acpi_device_dir(device)); - remove_proc_entry("brightness", acpi_device_dir(device)); - remove_proc_entry("EDID", acpi_device_dir(device)); + device_dir = acpi_device_dir(device); + if (device_dir) { + remove_proc_entry("info", device_dir); + remove_proc_entry("state", device_dir); + remove_proc_entry("brightness", device_dir); + remove_proc_entry("EDID", device_dir); remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); acpi_device_dir(device) = NULL; } @@ -1337,94 +1336,91 @@ acpi_video_bus_write_DOS(struct file *file, static int acpi_video_bus_add_fs(struct acpi_device *device) { - struct proc_dir_entry *entry = NULL; - struct acpi_video_bus *video; - + struct acpi_video_bus *video = acpi_driver_data(device); + struct proc_dir_entry *device_dir; + struct proc_dir_entry *entry; - video = acpi_driver_data(device); + device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); + if (!device_dir) + return -ENOMEM; - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_video_dir); - if (!acpi_device_dir(device)) - return -ENODEV; - video->dir = acpi_device_dir(device); - acpi_device_dir(device)->owner = THIS_MODULE; - } + device_dir->owner = THIS_MODULE; /* 'info' [R] */ - entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("info", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_dir; + + entry->proc_fops = &acpi_video_bus_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'ROM' [R] */ - entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("ROM", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_ROM_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_info; + + entry->proc_fops = &acpi_video_bus_ROM_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'POST_info' [R] */ - entry = - create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device)); + entry = create_proc_entry("POST_info", S_IRUGO, device_dir); if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_video_bus_POST_info_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_rom; + + entry->proc_fops = &acpi_video_bus_POST_info_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'POST' [R/W] */ - entry = - create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR, - acpi_device_dir(device)); + entry = create_proc_entry("POST", S_IFREG | S_IRUGO | S_IWUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; - entry->proc_fops = &acpi_video_bus_POST_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_post_info; + + acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; + entry->proc_fops = &acpi_video_bus_POST_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; /* 'DOS' [R/W] */ - entry = - create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR, - acpi_device_dir(device)); + entry = create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IWUSR, + device_dir); if (!entry) - return -ENODEV; - else { - acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; - entry->proc_fops = &acpi_video_bus_DOS_fops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } + goto err_remove_post; + + acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; + entry->proc_fops = &acpi_video_bus_DOS_fops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + video->dir = acpi_device_dir(device) = device_dir; return 0; + + err_remove_post: + remove_proc_entry("POST", device_dir); + err_remove_post_info: + remove_proc_entry("POST_info", device_dir); + err_remove_rom: + remove_proc_entry("ROM", device_dir); + err_remove_info: + remove_proc_entry("info", device_dir); + err_remove_dir: + remove_proc_entry(acpi_device_bid(device), acpi_video_dir); + return -ENOMEM; } static int acpi_video_bus_remove_fs(struct acpi_device *device) { - struct acpi_video_bus *video; - - - video = acpi_driver_data(device); + struct proc_dir_entry *device_dir = acpi_device_dir(device); - if (acpi_device_dir(device)) { - remove_proc_entry("info", acpi_device_dir(device)); - remove_proc_entry("ROM", acpi_device_dir(device)); - remove_proc_entry("POST_info", acpi_device_dir(device)); - remove_proc_entry("POST", acpi_device_dir(device)); - remove_proc_entry("DOS", acpi_device_dir(device)); + if (device_dir) { + remove_proc_entry("info", device_dir); + remove_proc_entry("ROM", device_dir); + remove_proc_entry("POST_info", device_dir); + remove_proc_entry("POST", device_dir); + remove_proc_entry("DOS", device_dir); remove_proc_entry(acpi_device_bid(device), acpi_video_dir); acpi_device_dir(device) = NULL; } @@ -1440,11 +1436,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) static struct acpi_video_device_attrib* acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) { - int count; + struct acpi_video_enumerated_device *ids; + int i; + + for (i = 0; i < video->attached_count; i++) { + ids = &video->attached_array[i]; + if ((ids->value.int_val & 0xffff) == device_id) + return &ids->value.attrib; + } - for(count = 0; count < video->attached_count; count++) - if((video->attached_array[count].value.int_val & 0xffff) == device_id) - return &(video->attached_array[count].value.attrib); return NULL; } @@ -1571,20 +1571,16 @@ static void acpi_video_device_bind(struct acpi_video_bus *video, struct acpi_video_device *device) { + struct acpi_video_enumerated_device *ids; int i; -#define IDS_VAL(i) video->attached_array[i].value.int_val -#define IDS_BIND(i) video->attached_array[i].bind_info - - for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID && - i < video->attached_count; i++) { - if (device->device_id == (IDS_VAL(i) & 0xffff)) { - IDS_BIND(i) = device; + for (i = 0; i < video->attached_count; i++) { + ids = &video->attached_array[i]; + if (device->device_id == (ids->value.int_val & 0xffff)) { + ids->bind_info = device; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); } } -#undef IDS_VAL -#undef IDS_BIND } /* @@ -1603,7 +1599,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) int status; int count; int i; - struct acpi_video_enumerated_device *active_device_list; + struct acpi_video_enumerated_device *active_list; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *dod = NULL; union acpi_object *obj; @@ -1624,13 +1620,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", dod->package.count)); - active_device_list = kmalloc((1 + - dod->package.count) * - sizeof(struct - acpi_video_enumerated_device), - GFP_KERNEL); - - if (!active_device_list) { + active_list = kcalloc(1 + dod->package.count, + sizeof(struct acpi_video_enumerated_device), + GFP_KERNEL); + if (!active_list) { status = -ENOMEM; goto out; } @@ -1640,23 +1633,24 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) obj = &dod->package.elements[i]; if (obj->type != ACPI_TYPE_INTEGER) { - printk(KERN_ERR PREFIX "Invalid _DOD data\n"); - active_device_list[i].value.int_val = - ACPI_VIDEO_HEAD_INVALID; + printk(KERN_ERR PREFIX + "Invalid _DOD data in element %d\n", i); + continue; } - active_device_list[i].value.int_val = obj->integer.value; - active_device_list[i].bind_info = NULL; + + active_list[count].value.int_val = obj->integer.value; + active_list[count].bind_info = NULL; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, (int)obj->integer.value)); count++; } - active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END; kfree(video->attached_array); - video->attached_array = active_device_list; + video->attached_array = active_list; video->attached_count = count; - out: + + out: kfree(buffer.pointer); return status; } |