Merge branches 'release', 'acpica', 'bugzilla-10224', 'bugzilla-9772', 'bugzilla-9916', 'ec', 'eeepc', 'idle', 'misc', 'pm-legacy', 'sysfs-links-2.6.26', 'thermal', 'thinkpad' and 'video' into release

This commit is contained in:
6071 changed files with 355435 additions and 267912 deletions

View file

@ -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

View file

@ -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},
};

View file

@ -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)
{

View file

@ -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 void ec_schedule_ec_poll(struct acpi_ec *ec)
{
if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags))
schedule_delayed_work(&ec->work,
msecs_to_jiffies(ACPI_EC_DELAY));
}
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)
{
int ret = 0;
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;
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,46 +488,50 @@ 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,
@ -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;

View file

@ -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 =

View file

@ -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;
printk(KERN_INFO PREFIX
"%s is registered as cooling_device%d\n",
device->dev.bus_id, cdev->id);
result = sysfs_create_link(&cdev->device.kobj,
&device->dev.kobj,
"device");
if (result)
return result;
}
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)

View file

@ -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;

View file

@ -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;

View file

@ -121,7 +121,7 @@ acpi_power_get_context(acpi_handle handle,
}
*resource = acpi_driver_data(device);
if (!resource)
if (!*resource)
return -ENODEV;
return 0;

View file

@ -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",

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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)
{

View file

@ -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);
}
@ -280,6 +262,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 --

View file

@ -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;
device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir);
if (!device_dir)
return -ENOMEM;
video = acpi_driver_data(device);
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;
struct proc_dir_entry *device_dir = acpi_device_dir(device);
video = acpi_driver_data(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;
}