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