Commit 14f7d720 authored by Len Brown's avatar Len Brown

Pull alexey-fixes into release branch

parents 6a22c57b 5527c8be
......@@ -586,11 +586,6 @@ and is between 256 and 4096 characters. It is defined in the file
eata= [HW,SCSI]
ec_intr= [HW,ACPI] ACPI Embedded Controller interrupt mode
Format: <int>
0: polling mode
non-0: interrupt mode (default)
edd= [EDD]
Format: {"of[f]" | "sk[ipmbr]"}
See comment in arch/i386/boot/edd.S
......
......@@ -88,7 +88,8 @@ config ACPI_PROC_EVENT
config ACPI_AC
tristate "AC Adapter"
depends on X86 && POWER_SUPPLY
depends on X86
select POWER_SUPPLY
default y
help
This driver adds support for the AC Adapter object, which indicates
......@@ -97,7 +98,8 @@ config ACPI_AC
config ACPI_BATTERY
tristate "Battery"
depends on X86 && POWER_SUPPLY
depends on X86
select POWER_SUPPLY
default y
help
This driver adds support for battery information through
......@@ -352,7 +354,7 @@ config ACPI_HOTPLUG_MEMORY
config ACPI_SBS
tristate "Smart Battery System"
depends on X86
depends on POWER_SUPPLY
select POWER_SUPPLY
help
This driver adds support for the Smart Battery System, another
type of access to battery information, found on some laptops.
......
......@@ -125,11 +125,15 @@ static int acpi_battery_technology(struct acpi_battery *battery)
return POWER_SUPPLY_TECHNOLOGY_NiMH;
if (!strcasecmp("LION", battery->type))
return POWER_SUPPLY_TECHNOLOGY_LION;
if (!strcasecmp("LI-ION", battery->type))
return POWER_SUPPLY_TECHNOLOGY_LION;
if (!strcasecmp("LiP", battery->type))
return POWER_SUPPLY_TECHNOLOGY_LIPO;
return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
}
static int acpi_battery_update(struct acpi_battery *battery);
static int acpi_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
......@@ -139,6 +143,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
if ((!acpi_battery_present(battery)) &&
psp != POWER_SUPPLY_PROP_PRESENT)
return -ENODEV;
acpi_battery_update(battery);
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
if (battery->state & 0x01)
......@@ -257,7 +262,7 @@ static int extract_package(struct acpi_battery *battery,
union acpi_object *package,
struct acpi_offsets *offsets, int num)
{
int i, *x;
int i;
union acpi_object *element;
if (package->type != ACPI_TYPE_PACKAGE)
return -EFAULT;
......@@ -266,16 +271,21 @@ static int extract_package(struct acpi_battery *battery,
return -EFAULT;
element = &package->package.elements[i];
if (offsets[i].mode) {
if (element->type != ACPI_TYPE_STRING &&
element->type != ACPI_TYPE_BUFFER)
return -EFAULT;
strncpy((u8 *)battery + offsets[i].offset,
element->string.pointer, 32);
u8 *ptr = (u8 *)battery + offsets[i].offset;
if (element->type == ACPI_TYPE_STRING ||
element->type == ACPI_TYPE_BUFFER)
strncpy(ptr, element->string.pointer, 32);
else if (element->type == ACPI_TYPE_INTEGER) {
strncpy(ptr, (u8 *)&element->integer.value,
sizeof(acpi_integer));
ptr[sizeof(acpi_integer)] = 0;
} else return -EFAULT;
} else {
if (element->type != ACPI_TYPE_INTEGER)
return -EFAULT;
x = (int *)((u8 *)battery + offsets[i].offset);
if (element->type == ACPI_TYPE_INTEGER) {
int *x = (int *)((u8 *)battery +
offsets[i].offset);
*x = element->integer.value;
} else return -EFAULT;
}
}
return 0;
......@@ -385,16 +395,40 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
return acpi_battery_set_alarm(battery);
}
static int acpi_battery_update(struct acpi_battery *battery)
static ssize_t acpi_battery_alarm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int saved_present = acpi_battery_present(battery);
int result = acpi_battery_get_status(battery);
if (result || !acpi_battery_present(battery))
return result;
if (saved_present != acpi_battery_present(battery) ||
!battery->update_time) {
struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
return sprintf(buf, "%d\n", battery->alarm * 1000);
}
static ssize_t acpi_battery_alarm_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long x;
struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
if (sscanf(buf, "%ld\n", &x) == 1)
battery->alarm = x/1000;
if (acpi_battery_present(battery))
acpi_battery_set_alarm(battery);
return count;
}
static struct device_attribute alarm_attr = {
.attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
.show = acpi_battery_alarm_show,
.store = acpi_battery_alarm_store,
};
static int sysfs_add_battery(struct acpi_battery *battery)
{
int result;
battery->update_time = 0;
result = acpi_battery_get_info(battery);
acpi_battery_init_alarm(battery);
if (result)
return result;
if (battery->power_unit) {
......@@ -406,8 +440,36 @@ static int acpi_battery_update(struct acpi_battery *battery)
battery->bat.num_properties =
ARRAY_SIZE(energy_battery_props);
}
acpi_battery_init_alarm(battery);
battery->bat.name = acpi_device_bid(battery->device);
battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat.get_property = acpi_battery_get_property;
result = power_supply_register(&battery->device->dev, &battery->bat);
if (result)
return result;
return device_create_file(battery->bat.dev, &alarm_attr);
}
static void sysfs_remove_battery(struct acpi_battery *battery)
{
if (!battery->bat.dev)
return;
device_remove_file(battery->bat.dev, &alarm_attr);
power_supply_unregister(&battery->bat);
}
static int acpi_battery_update(struct acpi_battery *battery)
{
int result = acpi_battery_get_status(battery);
if (result)
return result;
if (!acpi_battery_present(battery)) {
sysfs_remove_battery(battery);
return 0;
}
if (!battery->bat.dev)
sysfs_add_battery(battery);
return acpi_battery_get_state(battery);
}
......@@ -554,10 +616,6 @@ static ssize_t acpi_battery_write_alarm(struct file *file,
if (!battery || (count > sizeof(alarm_string) - 1))
return -EINVAL;
if (result) {
result = -ENODEV;
goto end;
}
if (!acpi_battery_present(battery)) {
result = -ENODEV;
goto end;
......@@ -688,33 +746,6 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
#endif
static ssize_t acpi_battery_alarm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
return sprintf(buf, "%d\n", battery->alarm * 1000);
}
static ssize_t acpi_battery_alarm_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned long x;
struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
if (sscanf(buf, "%ld\n", &x) == 1)
battery->alarm = x/1000;
if (acpi_battery_present(battery))
acpi_battery_set_alarm(battery);
return count;
}
static struct device_attribute alarm_attr = {
.attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
.show = acpi_battery_alarm_show,
.store = acpi_battery_alarm_store,
};
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
......@@ -732,6 +763,8 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
acpi_bus_generate_netlink_event(device->pnp.device_class,
device->dev.bus_id, event,
acpi_battery_present(battery));
/* acpi_batter_update could remove power_supply object */
if (battery->bat.dev)
kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE);
}
......@@ -756,11 +789,6 @@ static int acpi_battery_add(struct acpi_device *device)
if (result)
goto end;
#endif
battery->bat.name = acpi_device_bid(device);
battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
battery->bat.get_property = acpi_battery_get_property;
result = power_supply_register(&battery->device->dev, &battery->bat);
result = device_create_file(battery->bat.dev, &alarm_attr);
status = acpi_install_notify_handler(device->handle,
ACPI_ALL_NOTIFY,
acpi_battery_notify, battery);
......@@ -796,10 +824,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
#ifdef CONFIG_ACPI_PROCFS
acpi_battery_remove_fs(device);
#endif
if (battery->bat.dev) {
device_remove_file(battery->bat.dev, &alarm_attr);
power_supply_unregister(&battery->bat);
}
sysfs_remove_battery(battery);
mutex_destroy(&battery->lock);
kfree(battery);
return 0;
......@@ -813,6 +838,7 @@ static int acpi_battery_resume(struct acpi_device *device)
return -EINVAL;
battery = acpi_driver_data(device);
battery->update_time = 0;
acpi_battery_update(battery);
return 0;
}
......
......@@ -198,12 +198,10 @@ int acpi_bus_set_power(acpi_handle handle, int state)
return -ENODEV;
}
/*
* Get device's current power state if it's unknown
* This means device power state isn't initialized or previous setting failed
* Get device's current power state
*/
if ((device->power.state == ACPI_STATE_UNKNOWN) || device->flags.force_power_state)
acpi_bus_get_power(device->handle, &device->power.state);
if ((state == device->power.state) && !device->flags.force_power_state) {
if (state == device->power.state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
state));
return 0;
......
......@@ -78,6 +78,7 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids);
static int acpi_button_add(struct acpi_device *device);
static int acpi_button_remove(struct acpi_device *device, int type);
static int acpi_button_resume(struct acpi_device *device);
static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
......@@ -87,6 +88,7 @@ static struct acpi_driver acpi_button_driver = {
.ids = button_device_ids,
.ops = {
.add = acpi_button_add,
.resume = acpi_button_resume,
.remove = acpi_button_remove,
},
};
......@@ -253,6 +255,19 @@ static int acpi_button_remove_fs(struct acpi_device *device)
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
static int acpi_lid_send_state(struct acpi_button *button)
{
unsigned long state;
acpi_status status;
status = acpi_evaluate_integer(button->device->handle, "_LID", NULL,
&state);
if (ACPI_FAILURE(status))
return -ENODEV;
/* input layer checks if event is redundant */
input_report_switch(button->input, SW_LID, !state);
return 0;
}
static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
{
......@@ -265,15 +280,8 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
switch (event) {
case ACPI_BUTTON_NOTIFY_STATUS:
input = button->input;
if (button->type == ACPI_BUTTON_TYPE_LID) {
struct acpi_handle *handle = button->device->handle;
unsigned long state;
if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID",
NULL, &state)))
input_report_switch(input, SW_LID, !state);
acpi_lid_send_state(button);
} else {
int keycode = test_bit(KEY_SLEEP, input->keybit) ?
KEY_SLEEP : KEY_POWER;
......@@ -336,6 +344,17 @@ static int acpi_button_install_notify_handlers(struct acpi_button *button)
return ACPI_FAILURE(status) ? -ENODEV : 0;
}
static int acpi_button_resume(struct acpi_device *device)
{
struct acpi_button *button;
if (!device)
return -EINVAL;
button = acpi_driver_data(device);
if (button && button->type == ACPI_BUTTON_TYPE_LID)
return acpi_lid_send_state(button);
return 0;
}
static void acpi_button_remove_notify_handlers(struct acpi_button *button)
{
switch (button->type) {
......@@ -453,6 +472,8 @@ static int acpi_button_add(struct acpi_device *device)
error = input_register_device(input);
if (error)
goto err_remove_handlers;
if (button->type == ACPI_BUTTON_TYPE_LID)
acpi_lid_send_state(button);
if (device->wakeup.flags.valid) {
/* Button's GPE is run-wake GPE */
......
......@@ -71,10 +71,12 @@ 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 */
static enum ec_mode {
EC_INTR = 1, /* Output buffer full */
EC_POLL, /* Input buffer empty */
} acpi_ec_mode = EC_INTR;
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_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */
};
static int acpi_ec_remove(struct acpi_device *device, int type);
static int acpi_ec_start(struct acpi_device *device);
......@@ -116,9 +118,8 @@ static struct acpi_ec {
unsigned long command_addr;
unsigned long data_addr;
unsigned long global_lock;
unsigned long flags;
struct mutex lock;
atomic_t query_pending;
atomic_t event_count;
wait_queue_head_t wait;
struct list_head list;
u8 handlers_installed;
......@@ -148,45 +149,54 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
outb(data, ec->data_addr);
}
static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event,
unsigned old_count)
static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
{
u8 status = acpi_ec_read_status(ec);
if (old_count == atomic_read(&ec->event_count))
if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags))
return 0;
if (event == ACPI_EC_EVENT_OBF_1) {
if (status & ACPI_EC_FLAG_OBF)
if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF)
return 1;
} else if (event == ACPI_EC_EVENT_IBF_0) {
if (!(status & ACPI_EC_FLAG_IBF))
if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF))
return 1;
}
return 0;
}
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event,
unsigned count, int force_poll)
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
{
if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) {
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
while (time_before(jiffies, delay)) {
if (acpi_ec_check_status(ec, event, 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)))
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 anymore */
printk(KERN_INFO PREFIX "missing OBF_1 confirmation,"
"switching to degraded mode.\n");
set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags);
} else {
if (wait_event_timeout(ec->wait,
acpi_ec_check_status(ec, event, count),
msecs_to_jiffies(ACPI_EC_DELAY)) ||
acpi_ec_check_status(ec, event, 0)) {
/* missing GPEs, switch back to poll mode */
printk(KERN_INFO PREFIX "missing IBF_1 confirmations,"
"switch off interrupt mode.\n");
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
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))
return 0;
}
}
printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
" status = %d, expect_event = %d\n",
acpi_ec_read_status(ec), event);
}
}
return -ETIME;
}
......@@ -196,39 +206,42 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
int force_poll)
{
int result = 0;
unsigned count = atomic_read(&ec->event_count);
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_cmd(ec, command);
for (; wdata_len > 0; --wdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
printk(KERN_ERR PREFIX
"write_cmd timeout, command = %d\n", command);
goto end;
}
count = atomic_read(&ec->event_count);
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_data(ec, *(wdata++));
}
if (!rdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) {
printk(KERN_ERR PREFIX
"finish-write timeout, command = %d\n", command);
goto end;
}
} else if (command == ACPI_EC_COMMAND_QUERY) {
atomic_set(&ec->query_pending, 0);
}
} else if (command == ACPI_EC_COMMAND_QUERY)
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
for (; rdata_len > 0; --rdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll);
if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags))
force_poll = 1;
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
if (result) {
printk(KERN_ERR PREFIX "read timeout, command = %d\n",
command);
goto end;
}
count = atomic_read(&ec->event_count);
/* Don't expect GPE after last read */
if (rdata_len > 1)
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
*(rdata++) = acpi_ec_read_data(ec);
}
end:
......@@ -258,10 +271,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
}
}
/* Make sure GPE is enabled before doing transaction */
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
if (status) {
printk(KERN_ERR PREFIX
"input buffer is not empty, aborting transaction\n");
......@@ -435,9 +445,9 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
{
struct acpi_ec_query_handler *handler;
struct acpi_ec_query_handler *handler, *tmp;
mutex_lock(&ec->lock);
list_for_each_entry(handler, &ec->list, node) {
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
if (query_bit == handler->query_bit) {
list_del(&handler->node);
kfree(handler);
......@@ -476,23 +486,24 @@ static void acpi_ec_gpe_query(void *ec_cxt)
static u32 acpi_ec_gpe_handler(void *data)
{
acpi_status status = AE_OK;
u8 value;
struct acpi_ec *ec = data;
atomic_inc(&ec->event_count);
if (acpi_ec_mode == EC_INTR) {
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
wake_up(&ec->wait);
}
value = acpi_ec_read_status(ec);
if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
atomic_set(&ec->query_pending, 1);
status =
acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
if (acpi_ec_read_status(ec) & 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))) {
/* this is non-query, must be confirmation */
printk(KERN_INFO PREFIX "non-query interrupt received,"
" switching to interrupt mode\n");
set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
}
return status == AE_OK ?
return ACPI_SUCCESS(status) ?
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
}
......@@ -641,13 +652,10 @@ static struct acpi_ec *make_acpi_ec(void)
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
if (!ec)
return NULL;
atomic_set(&ec->query_pending, 1);
atomic_set(&ec->event_count, 1);
ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
mutex_init(&ec->lock);
init_waitqueue_head(&ec->wait);
INIT_LIST_HEAD(&ec->list);
return ec;
}
......@@ -741,6 +749,8 @@ static int acpi_ec_add(struct acpi_device *device)
acpi_ec_add_fs(device);
printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);
printk(KERN_INFO PREFIX "driver started in %s mode\n",
(test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll");
return 0;
}
......@@ -833,7 +843,7 @@ static int acpi_ec_start(struct acpi_device *device)
ret = ec_install_handlers(ec);
/* EC is fully operational, allow queries */
atomic_set(&ec->query_pending, 0);
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
return ret;
}
......@@ -925,19 +935,3 @@ static void __exit acpi_ec_exit(void)
return;
}
#endif /* 0 */
static int __init acpi_ec_set_intr_mode(char *str)
{
int intr;
if (!get_option(&str, &intr))
return 0;
acpi_ec_mode = (intr) ? EC_INTR : EC_POLL;
printk(KERN_NOTICE PREFIX "%s mode.\n", intr ? "interrupt" : "polling");
return 1;
}
__setup("ec_intr=", acpi_ec_set_intr_mode);
......@@ -47,8 +47,6 @@ MODULE_LICENSE("GPL");
static int acpi_fan_add(struct acpi_device *device);
static int acpi_fan_remove(struct acpi_device *device, int type);
static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
static int acpi_fan_resume(struct acpi_device *device);
static const struct acpi_device_id fan_device_ids[] = {
{"PNP0C0B", 0},
......@@ -63,15 +61,9 @@ static struct acpi_driver acpi_fan_driver = {
.ops = {
.add = acpi_fan_add,
.remove = acpi_fan_remove,
.suspend = acpi_fan_suspend,
.resume = acpi_fan_resume,
},
};
struct acpi_fan {
struct acpi_device * device;
};
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
......@@ -80,12 +72,12 @@ static struct proc_dir_entry *acpi_fan_dir;
static int acpi_fan_read_state(struct seq_file *seq, void *offset)
{
struct acpi_fan *fan = seq->private;
struct acpi_device *device = seq->private;
int state = 0;
if (fan) {
if (acpi_bus_get_power(fan->device->handle, &state))
if (device) {
if (acpi_bus_get_power(device->handle, &state))
seq_printf(seq, "status: ERROR\n");
else
seq_printf(seq, "status: %s\n",
......@@ -105,11 +97,10 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
{
int result = 0;
struct seq_file *m = file->private_data;
struct acpi_fan *fan = m->private;
struct acpi_device *device = m->private;
char state_string[12] = { '\0' };
if (!fan || (count > sizeof(state_string) - 1))
if (count > sizeof(state_string) - 1)
return -EINVAL;
if (copy_from_user(state_string, buffer, count))
......@@ -117,7 +108,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
state_string[count] = '\0';
result = acpi_bus_set_power(fan->device->handle,
result = acpi_bus_set_power(device->handle,
simple_strtoul(state_string, NULL, 0));
if (result)
return result;
......@@ -158,7 +149,7 @@ static int acpi_fan_add_fs(struct acpi_device *device)
return -ENODEV;
else {
entry->proc_fops = &acpi_fan_state_ops;
entry->data = acpi_driver_data(device);
entry->data = device;
entry->owner = THIS_MODULE;
}
......@@ -191,14 +182,8 @@ static int acpi_fan_add(struct acpi_device *device)
if (!device)
return -EINVAL;
fan = kzalloc(sizeof(struct acpi_fan), GFP_KERNEL);
if (!fan)
return -ENOMEM;
fan->device = device;
strcpy(acpi_device_name(device), "Fan");
strcpy(acpi_device_class(device), ACPI_FAN_CLASS);
acpi_driver_data(device) = fan;
result = acpi_bus_get_power(device->handle, &state);
if (result) {
......@@ -206,10 +191,6 @@ static int acpi_fan_add(struct acpi_device *device)
goto end;
}
device->flags.force_power_state = 1;
acpi_bus_set_power(device->handle, state);
device->flags.force_power_state = 0;
result = acpi_fan_add_fs(device);
if (result)
goto end;
......@@ -227,53 +208,14 @@ static int acpi_fan_add(struct acpi_device *device)
static int acpi_fan_remove(struct acpi_device *device, int type)
{
struct acpi_fan *fan = NULL;
if (!device || !acpi_driver_data(device))
return -EINVAL;
fan = acpi_driver_data(device);
acpi_fan_remove_fs(device);
kfree(fan);
return 0;
}
static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state)
{
if (!device)
return -EINVAL;
acpi_bus_set_power(device->handle, ACPI_STATE_D0);
return AE_OK;
}
static int acpi_fan_resume(struct acpi_device *device)
{
int result = 0;
int power_state = 0;
if (!device)
return -EINVAL;
result = acpi_bus_get_power(device->handle, &power_state);
if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error reading fan power state\n"));
return result;
}
device->flags.force_power_state = 1;
acpi_bus_set_power(device->handle, power_state);
device->flags.force_power_state = 0;
return result;
}
static int __init acpi_fan_init(void)
{
int result = 0;
......
......@@ -86,7 +86,6 @@ struct acpi_power_resource {
acpi_bus_id name;
u32 system_level;
u32 order;
int state;
struct mutex resource_lock;
struct list_head reference;
};
......@@ -128,33 +127,31 @@ acpi_power_get_context(acpi_handle handle,
return 0;
}
static int acpi_power_get_state(struct acpi_power_resource *resource)
static int acpi_power_get_state(struct acpi_power_resource *resource, int *state)
{
acpi_status status = AE_OK;
unsigned long sta = 0;
if (!resource)
if (!resource || !state)
return -EINVAL;
status = acpi_evaluate_integer(resource->device->handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status))
return -ENODEV;
if (sta & 0x01)
resource->state = ACPI_POWER_RESOURCE_STATE_ON;
else
resource->state = ACPI_POWER_RESOURCE_STATE_OFF;
*state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
ACPI_POWER_RESOURCE_STATE_OFF;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
resource->name, resource->state ? "on" : "off"));
resource->name, state ? "on" : "off"));
return 0;
}
static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
{
int result = 0;
int result = 0, state1;
struct acpi_power_resource *resource = NULL;
u32 i = 0;
......@@ -168,11 +165,11 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
result = acpi_power_get_context(list->handles[i], &resource);
if (result)
return result;
result = acpi_power_get_state(resource);
result = acpi_power_get_state(resource, &state1);
if (result)
return result;
*state = resource->state;
*state = state1;
if (*state != ACPI_POWER_RESOURCE_STATE_ON)
break;
......@@ -186,7 +183,7 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
{
int result = 0;
int result = 0, state;
int found = 0;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
......@@ -224,20 +221,14 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
}
mutex_unlock(&resource->resource_lock);
if (resource->state == ACPI_POWER_RESOURCE_STATE_ON) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already on\n",
resource->name));
return 0;
}
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
result = acpi_power_get_state(resource);
result = acpi_power_get_state(resource, &state);
if (result)
return result;
if (resource->state != ACPI_POWER_RESOURCE_STATE_ON)
if (state != ACPI_POWER_RESOURCE_STATE_ON)
return -ENOEXEC;
/* Update the power resource's _device_ power state */
......@@ -250,7 +241,7 @@ static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
{
int result = 0;
int result = 0, state;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
......@@ -281,20 +272,14 @@ static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
}
mutex_unlock(&resource->resource_lock);
if (resource->state == ACPI_POWER_RESOURCE_STATE_OFF) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] already off\n",
resource->name));
return 0;
}
status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
result = acpi_power_get_state(resource);
result = acpi_power_get_state(resource, &state);
if (result)
return result;
if (resource->state != ACPI_POWER_RESOURCE_STATE_OFF)
if (state != ACPI_POWER_RESOURCE_STATE_OFF)
return -ENOEXEC;
/* Update the power resource's _device_ power state */
......@@ -494,7 +479,7 @@ static struct proc_dir_entry *acpi_power_dir;
static int acpi_power_seq_show(struct seq_file *seq, void *offset)
{
int count = 0;
int result = 0;
int result = 0, state;
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
struct acpi_power_reference *ref;
......@@ -505,12 +490,12 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
if (!resource)
goto end;
result = acpi_power_get_state(resource);
result = acpi_power_get_state(resource, &state);
if (result)
goto end;
seq_puts(seq, "state: ");
switch (resource->state) {
switch (state) {
case ACPI_POWER_RESOURCE_STATE_ON:
seq_puts(seq, "on\n");
break;
......@@ -591,7 +576,7 @@ static int acpi_power_remove_fs(struct acpi_device *device)
static int acpi_power_add(struct acpi_device *device)
{
int result = 0;
int result = 0, state;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
union acpi_object acpi_object;
......@@ -622,11 +607,11 @@ static int acpi_power_add(struct acpi_device *device)
resource->system_level = acpi_object.power_resource.system_level;
resource->order = acpi_object.power_resource.resource_order;
result = acpi_power_get_state(resource);
result = acpi_power_get_state(resource, &state);
if (result)
goto end;
switch (resource->state) {
switch (state) {
case ACPI_POWER_RESOURCE_STATE_ON:
device->power.state = ACPI_STATE_D0;
break;
......@@ -643,7 +628,7 @@ static int acpi_power_add(struct acpi_device *device)
goto end;
printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device),
acpi_device_bid(device), resource->state ? "on" : "off");
acpi_device_bid(device), state ? "on" : "off");
end:
if (result)
......@@ -680,7 +665,7 @@ static int acpi_power_remove(struct acpi_device *device, int type)
static int acpi_power_resume(struct acpi_device *device)
{
int result = 0;
int result = 0, state;
struct acpi_power_resource *resource = NULL;
struct acpi_power_reference *ref;
......@@ -689,12 +674,12 @@ static int acpi_power_resume(struct acpi_device *device)
resource = (struct acpi_power_resource *)acpi_driver_data(device);
result = acpi_power_get_state(resource);
result = acpi_power_get_state(resource, &state);
if (result)
return result;
mutex_lock(&resource->resource_lock);
if ((resource->state == ACPI_POWER_RESOURCE_STATE_OFF) &&
if (state == ACPI_POWER_RESOURCE_STATE_OFF &&
!list_empty(&resource->reference)) {
ref = container_of(resource->reference.next, struct acpi_power_reference, node);
mutex_unlock(&resource->resource_lock);
......
......@@ -167,8 +167,8 @@ static void acpi_pm_finish(void)
{
u32 acpi_state = acpi_target_sleep_state;
acpi_leave_sleep_state(acpi_state);
acpi_disable_wakeup_device(acpi_state);
acpi_leave_sleep_state(acpi_state);
/* reset firmware waking vector */
acpi_set_firmware_waking_vector((acpi_physical_address) 0);
......@@ -272,8 +272,8 @@ static void acpi_hibernation_finish(void)
* enable it here.
*/
acpi_enable();
acpi_leave_sleep_state(ACPI_STATE_S4);
acpi_disable_wakeup_device(ACPI_STATE_S4);
acpi_leave_sleep_state(ACPI_STATE_S4);
/* reset firmware waking vector */
acpi_set_firmware_waking_vector((acpi_physical_address) 0);
......@@ -410,6 +410,7 @@ static void acpi_power_off(void)
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
printk("%s called\n", __FUNCTION__);
local_irq_disable();
acpi_enable_wakeup_device(ACPI_STATE_S5);
acpi_enter_sleep_state(ACPI_STATE_S5);
}
......
......@@ -168,8 +168,7 @@ struct acpi_device_flags {
u32 power_manageable:1;
u32 performance_manageable:1;
u32 wake_capable:1; /* Wakeup(_PRW) supported? */
u32 force_power_state:1;
u32 reserved:19;
u32 reserved:20;
};
/* File System */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment