mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
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:
parent
75a44ce00b
729b2bdbfa
2f67a0695d
51ae796f7f
ce52ddf58c
e1faa9da28
36a9135865
9448b0d43e
99bda83e8b
1071695f17
7aa0f1a8b1
68f12ae5d7
66fb9d120e
commit
96916090f4
6071 changed files with 355435 additions and 267912 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ acpi_power_get_context(acpi_handle handle,
|
|||
}
|
||||
|
||||
*resource = acpi_driver_data(device);
|
||||
if (!resource)
|
||||
if (!*resource)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 --
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue