aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-devices-power_resources_wakeup13
-rw-r--r--drivers/acpi/power.c58
2 files changed, 52 insertions, 19 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-power_resources_wakeup b/Documentation/ABI/testing/sysfs-devices-power_resources_wakeup
new file mode 100644
index 000000000000..e0588feeb6e1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-power_resources_wakeup
@@ -0,0 +1,13 @@
+What: /sys/devices/.../power_resources_wakeup/
+Date: April 2013
+Contact: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+ The /sys/devices/.../power_resources_wakeup/ directory is only
+ present for device objects representing ACPI device nodes that
+ require ACPI power resources for wakeup signaling.
+
+ If present, it contains symbolic links to device directories
+ representing ACPI power resources that need to be turned on for
+ the given device node to be able to signal wakeup. The names of
+ the links are the same as the names of the directories they
+ point to.
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 34f5ef11d427..0e3f57674fd1 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -459,57 +459,79 @@ static struct attribute_group attr_groups[] = {
},
};
-static void acpi_power_hide_list(struct acpi_device *adev, int state)
+static struct attribute_group wakeup_attr_group = {
+ .name = "power_resources_wakeup",
+ .attrs = attrs,
+};
+
+static void acpi_power_hide_list(struct acpi_device *adev,
+ struct list_head *resources,
+ struct attribute_group *attr_group)
{
- struct acpi_device_power_state *ps = &adev->power.states[state];
struct acpi_power_resource_entry *entry;
- if (list_empty(&ps->resources))
+ if (list_empty(resources))
return;
- list_for_each_entry_reverse(entry, &ps->resources, node) {
+ list_for_each_entry_reverse(entry, resources, node) {
struct acpi_device *res_dev = &entry->resource->device;
sysfs_remove_link_from_group(&adev->dev.kobj,
- attr_groups[state].name,
+ attr_group->name,
dev_name(&res_dev->dev));
}
- sysfs_remove_group(&adev->dev.kobj, &attr_groups[state]);
+ sysfs_remove_group(&adev->dev.kobj, attr_group);
}
-static void acpi_power_expose_list(struct acpi_device *adev, int state)
+static void acpi_power_expose_list(struct acpi_device *adev,
+ struct list_head *resources,
+ struct attribute_group *attr_group)
{
- struct acpi_device_power_state *ps = &adev->power.states[state];
struct acpi_power_resource_entry *entry;
int ret;
- if (list_empty(&ps->resources))
+ if (list_empty(resources))
return;
- ret = sysfs_create_group(&adev->dev.kobj, &attr_groups[state]);
+ ret = sysfs_create_group(&adev->dev.kobj, attr_group);
if (ret)
return;
- list_for_each_entry(entry, &ps->resources, node) {
+ list_for_each_entry(entry, resources, node) {
struct acpi_device *res_dev = &entry->resource->device;
ret = sysfs_add_link_to_group(&adev->dev.kobj,
- attr_groups[state].name,
+ attr_group->name,
&res_dev->dev.kobj,
dev_name(&res_dev->dev));
if (ret) {
- acpi_power_hide_list(adev, state);
+ acpi_power_hide_list(adev, resources, attr_group);
break;
}
}
}
+static void acpi_power_expose_hide(struct acpi_device *adev,
+ struct list_head *resources,
+ struct attribute_group *attr_group,
+ bool expose)
+{
+ if (expose)
+ acpi_power_expose_list(adev, resources, attr_group);
+ else
+ acpi_power_hide_list(adev, resources, attr_group);
+}
+
void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
{
struct acpi_device_power_state *ps;
struct acpi_power_resource_entry *entry;
int state;
+ if (adev->wakeup.flags.valid)
+ acpi_power_expose_hide(adev, &adev->wakeup.resources,
+ &wakeup_attr_group, add);
+
if (!adev->power.flags.power_resources)
return;
@@ -523,12 +545,10 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
acpi_power_remove_dependent(resource, adev);
}
- for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++) {
- if (add)
- acpi_power_expose_list(adev, state);
- else
- acpi_power_hide_list(adev, state);
- }
+ for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
+ acpi_power_expose_hide(adev,
+ &adev->power.states[state].resources,
+ &attr_groups[state], add);
}
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)