diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2010-02-17 17:41:07 -0500 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2010-02-22 19:20:45 -0500 |
commit | 9630bdd9b15d2f489c646d8bc04b60e53eb5ec78 (patch) | |
tree | ed99f729cb9142492e0cdf2f7d19f2f33069a3f4 /drivers/acpi/wakeup.c | |
parent | c39fae1416d59fd565606793f090cebe3720d50d (diff) |
ACPI: Use GPE reference counting to support shared GPEs
ACPI GPEs may map to multiple devices. The current GPE interface
only provides a mechanism for enabling and disabling GPEs, making
it difficult to change the state of GPEs at runtime without extensive
cooperation between devices.
Add an API to allow devices to indicate whether or not they want
their device's GPE to be enabled for both runtime and wakeup events.
Remove the old GPE type handling entirely, which gets rid of various
quirks, like the implicit disabling with GPE type setting. This
requires a small amount of rework in order to ensure that non-wake
GPEs are enabled by default to preserve existing behaviour.
Based on patches from Matthew Garrett <mjg@redhat.com>.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/acpi/wakeup.c')
-rw-r--r-- | drivers/acpi/wakeup.c | 81 |
1 files changed, 27 insertions, 54 deletions
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index e0ee0c036f5a..6783986c7469 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c | |||
@@ -21,12 +21,12 @@ | |||
21 | ACPI_MODULE_NAME("wakeup_devices") | 21 | ACPI_MODULE_NAME("wakeup_devices") |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * acpi_enable_wakeup_device_prep - prepare wakeup devices | 24 | * acpi_enable_wakeup_device_prep - Prepare wake-up devices. |
25 | * @sleep_state: ACPI state | 25 | * @sleep_state: ACPI system sleep state. |
26 | * Enable all wakup devices power if the devices' wakeup level | 26 | * |
27 | * is higher than requested sleep level | 27 | * Enable all wake-up devices' power, unless the requested system sleep state is |
28 | * too deep. | ||
28 | */ | 29 | */ |
29 | |||
30 | void acpi_enable_wakeup_device_prep(u8 sleep_state) | 30 | void acpi_enable_wakeup_device_prep(u8 sleep_state) |
31 | { | 31 | { |
32 | struct list_head *node, *next; | 32 | struct list_head *node, *next; |
@@ -36,9 +36,8 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state) | |||
36 | struct acpi_device, | 36 | struct acpi_device, |
37 | wakeup_list); | 37 | wakeup_list); |
38 | 38 | ||
39 | if (!dev->wakeup.flags.valid || | 39 | if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled |
40 | !dev->wakeup.state.enabled || | 40 | || (sleep_state > (u32) dev->wakeup.sleep_state)) |
41 | (sleep_state > (u32) dev->wakeup.sleep_state)) | ||
42 | continue; | 41 | continue; |
43 | 42 | ||
44 | acpi_enable_wakeup_device_power(dev, sleep_state); | 43 | acpi_enable_wakeup_device_power(dev, sleep_state); |
@@ -46,9 +45,12 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state) | |||
46 | } | 45 | } |
47 | 46 | ||
48 | /** | 47 | /** |
49 | * acpi_enable_wakeup_device - enable wakeup devices | 48 | * acpi_enable_wakeup_device - Enable wake-up device GPEs. |
50 | * @sleep_state: ACPI state | 49 | * @sleep_state: ACPI system sleep state. |
51 | * Enable all wakup devices's GPE | 50 | * |
51 | * Enable all wake-up devices' GPEs, with the assumption that | ||
52 | * acpi_disable_all_gpes() was executed before, so we don't need to disable any | ||
53 | * GPEs here. | ||
52 | */ | 54 | */ |
53 | void acpi_enable_wakeup_device(u8 sleep_state) | 55 | void acpi_enable_wakeup_device(u8 sleep_state) |
54 | { | 56 | { |
@@ -65,29 +67,22 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
65 | if (!dev->wakeup.flags.valid) | 67 | if (!dev->wakeup.flags.valid) |
66 | continue; | 68 | continue; |
67 | 69 | ||
68 | /* If users want to disable run-wake GPE, | ||
69 | * we only disable it for wake and leave it for runtime | ||
70 | */ | ||
71 | if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) | 70 | if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) |
72 | || sleep_state > (u32) dev->wakeup.sleep_state) { | 71 | || sleep_state > (u32) dev->wakeup.sleep_state) |
73 | if (dev->wakeup.flags.run_wake) { | ||
74 | /* set_gpe_type will disable GPE, leave it like that */ | ||
75 | acpi_set_gpe_type(dev->wakeup.gpe_device, | ||
76 | dev->wakeup.gpe_number, | ||
77 | ACPI_GPE_TYPE_RUNTIME); | ||
78 | } | ||
79 | continue; | 72 | continue; |
80 | } | 73 | |
81 | if (!dev->wakeup.flags.run_wake) | 74 | /* The wake-up power should have been enabled already. */ |
82 | acpi_enable_gpe(dev->wakeup.gpe_device, | 75 | acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
83 | dev->wakeup.gpe_number); | 76 | ACPI_GPE_ENABLE); |
84 | } | 77 | } |
85 | } | 78 | } |
86 | 79 | ||
87 | /** | 80 | /** |
88 | * acpi_disable_wakeup_device - disable devices' wakeup capability | 81 | * acpi_disable_wakeup_device - Disable devices' wakeup capability. |
89 | * @sleep_state: ACPI state | 82 | * @sleep_state: ACPI system sleep state. |
90 | * Disable all wakup devices's GPE and wakeup capability | 83 | * |
84 | * This function only affects devices with wakeup.state.enabled set, which means | ||
85 | * that it reverses the changes made by acpi_enable_wakeup_device_prep(). | ||
91 | */ | 86 | */ |
92 | void acpi_disable_wakeup_device(u8 sleep_state) | 87 | void acpi_disable_wakeup_device(u8 sleep_state) |
93 | { | 88 | { |
@@ -97,30 +92,11 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
97 | struct acpi_device *dev = | 92 | struct acpi_device *dev = |
98 | container_of(node, struct acpi_device, wakeup_list); | 93 | container_of(node, struct acpi_device, wakeup_list); |
99 | 94 | ||
100 | if (!dev->wakeup.flags.valid) | 95 | if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled |
101 | continue; | 96 | || (sleep_state > (u32) dev->wakeup.sleep_state)) |
102 | |||
103 | if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count) | ||
104 | || sleep_state > (u32) dev->wakeup.sleep_state) { | ||
105 | if (dev->wakeup.flags.run_wake) { | ||
106 | acpi_set_gpe_type(dev->wakeup.gpe_device, | ||
107 | dev->wakeup.gpe_number, | ||
108 | ACPI_GPE_TYPE_WAKE_RUN); | ||
109 | /* Re-enable it, since set_gpe_type will disable it */ | ||
110 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
111 | dev->wakeup.gpe_number); | ||
112 | } | ||
113 | continue; | 97 | continue; |
114 | } | ||
115 | 98 | ||
116 | acpi_disable_wakeup_device_power(dev); | 99 | acpi_disable_wakeup_device_power(dev); |
117 | /* Never disable run-wake GPE */ | ||
118 | if (!dev->wakeup.flags.run_wake) { | ||
119 | acpi_disable_gpe(dev->wakeup.gpe_device, | ||
120 | dev->wakeup.gpe_number); | ||
121 | acpi_clear_gpe(dev->wakeup.gpe_device, | ||
122 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | ||
123 | } | ||
124 | } | 100 | } |
125 | } | 101 | } |
126 | 102 | ||
@@ -136,11 +112,8 @@ int __init acpi_wakeup_device_init(void) | |||
136 | /* In case user doesn't load button driver */ | 112 | /* In case user doesn't load button driver */ |
137 | if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled) | 113 | if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled) |
138 | continue; | 114 | continue; |
139 | acpi_set_gpe_type(dev->wakeup.gpe_device, | 115 | acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, |
140 | dev->wakeup.gpe_number, | 116 | ACPI_GPE_TYPE_WAKE); |
141 | ACPI_GPE_TYPE_WAKE_RUN); | ||
142 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
143 | dev->wakeup.gpe_number); | ||
144 | dev->wakeup.state.enabled = 1; | 117 | dev->wakeup.state.enabled = 1; |
145 | } | 118 | } |
146 | mutex_unlock(&acpi_device_lock); | 119 | mutex_unlock(&acpi_device_lock); |