Skip to content

Commit

Permalink
ACPI / PM: Use device wakeup flags for handling ACPI wakeup devices
Browse files Browse the repository at this point in the history
There are ACPI devices (buttons and the laptop lid) that can wake up
the system from sleep states and have no "physical" companion
devices.  The ACPI subsystem uses two flags, wakeup.state.enabled and
wakeup.flags.always_enabled, for handling those devices, but they
are not accessible through the standard device wakeup infrastructure.
User space can only control them via the /proc/acpi/wakeup interface
that is not really convenient (e.g. the way in which devices are
enabled to wake up the system is not portable between different
systems, because it requires one to know the devices' "names" used in
the system's ACPI tables).

To address this problem, use standard device wakeup flags instead of
the special ACPI flags for handling those devices.  In particular,
use device_set_wakeup_capable() to mark the ACPI wakeup devices
during initialization and use device_set_wakeup_enable() to allow
or disallow them to wake up the system from sleep states.  Rework
the /proc/acpi/wakeup interface to take these changes into account.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Len Brown <len.brown@intel.com>
  • Loading branch information
Rafael J. Wysocki authored and Len Brown committed Jan 7, 2011
1 parent b014f4f commit f2b56bc
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 17 deletions.
4 changes: 2 additions & 2 deletions drivers/acpi/button.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ static int acpi_button_add(struct acpi_device *device)
acpi_enable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number);
device->wakeup.run_wake_count++;
device->wakeup.state.enabled = 1;
device_set_wakeup_enable(&device->dev, true);
}

printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
Expand All @@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
acpi_disable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number);
device->wakeup.run_wake_count--;
device->wakeup.state.enabled = 0;
device_set_wakeup_enable(&device->dev, false);
}

acpi_button_remove_fs(device);
Expand Down
19 changes: 13 additions & 6 deletions drivers/acpi/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,9 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
dev->pnp.bus_id,
(u32) dev->wakeup.sleep_state,
dev->wakeup.flags.run_wake ? '*' : ' ',
dev->wakeup.state.enabled ? "enabled" : "disabled");
(device_may_wakeup(&dev->dev)
|| (ldev && device_may_wakeup(ldev))) ?
"enabled" : "disabled");
if (ldev)
seq_printf(seq, "%s:%s",
ldev->bus ? ldev->bus->name : "no-bus",
Expand All @@ -328,8 +330,10 @@ static void physical_device_enable_wakeup(struct acpi_device *adev)
{
struct device *dev = acpi_get_physical_device(adev->handle);

if (dev && device_can_wakeup(dev))
device_set_wakeup_enable(dev, adev->wakeup.state.enabled);
if (dev && device_can_wakeup(dev)) {
bool enable = !device_may_wakeup(dev);
device_set_wakeup_enable(dev, enable);
}
}

static ssize_t
Expand Down Expand Up @@ -360,9 +364,12 @@ acpi_system_write_wakeup_device(struct file *file,
continue;

if (!strncmp(dev->pnp.bus_id, str, 4)) {
dev->wakeup.state.enabled =
dev->wakeup.state.enabled ? 0 : 1;
physical_device_enable_wakeup(dev);
if (device_can_wakeup(&dev->dev)) {
bool enable = !device_may_wakeup(&dev->dev);
device_set_wakeup_enable(&dev->dev, enable);
} else {
physical_device_enable_wakeup(dev);
}
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
/* Power button, Lid switch always enable wakeup */
if (!acpi_match_device_ids(device, button_device_ids)) {
device->wakeup.flags.run_wake = 1;
device->wakeup.flags.always_enabled = 1;
device_set_wakeup_capable(&device->dev, true);
return;
}

Expand Down
18 changes: 10 additions & 8 deletions drivers/acpi/wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ void acpi_enable_wakeup_devices(u8 sleep_state)
container_of(node, struct acpi_device, wakeup_list);

if (!dev->wakeup.flags.valid
|| !(dev->wakeup.state.enabled || dev->wakeup.prepare_count)
|| sleep_state > (u32) dev->wakeup.sleep_state)
|| sleep_state > (u32) dev->wakeup.sleep_state
|| !(device_may_wakeup(&dev->dev)
|| dev->wakeup.prepare_count))
continue;

if (dev->wakeup.state.enabled)
if (device_may_wakeup(&dev->dev))
acpi_enable_wakeup_device_power(dev, sleep_state);

/* The wake-up power should have been enabled already. */
Expand All @@ -63,14 +64,15 @@ void acpi_disable_wakeup_devices(u8 sleep_state)
container_of(node, struct acpi_device, wakeup_list);

if (!dev->wakeup.flags.valid
|| !(dev->wakeup.state.enabled || dev->wakeup.prepare_count)
|| (sleep_state > (u32) dev->wakeup.sleep_state))
|| sleep_state > (u32) dev->wakeup.sleep_state
|| !(device_may_wakeup(&dev->dev)
|| dev->wakeup.prepare_count))
continue;

acpi_gpe_wakeup(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
ACPI_GPE_DISABLE);

if (dev->wakeup.state.enabled)
if (device_may_wakeup(&dev->dev))
acpi_disable_wakeup_device_power(dev);
}
}
Expand All @@ -84,8 +86,8 @@ int __init acpi_wakeup_device_init(void)
struct acpi_device *dev = container_of(node,
struct acpi_device,
wakeup_list);
if (dev->wakeup.flags.always_enabled)
dev->wakeup.state.enabled = 1;
if (device_can_wakeup(&dev->dev))
device_set_wakeup_enable(&dev->dev, true);
}
mutex_unlock(&acpi_device_lock);
return 0;
Expand Down

0 comments on commit f2b56bc

Please sign in to comment.