aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/wakeup.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-02-17 17:41:07 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-22 19:20:45 -0500
commit9630bdd9b15d2f489c646d8bc04b60e53eb5ec78 (patch)
treeed99f729cb9142492e0cdf2f7d19f2f33069a3f4 /drivers/acpi/wakeup.c
parentc39fae1416d59fd565606793f090cebe3720d50d (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.c81
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 @@
21ACPI_MODULE_NAME("wakeup_devices") 21ACPI_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
30void acpi_enable_wakeup_device_prep(u8 sleep_state) 30void 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 */
53void acpi_enable_wakeup_device(u8 sleep_state) 55void 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 */
92void acpi_disable_wakeup_device(u8 sleep_state) 87void 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);