aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evgpe.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-06-08 04:49:08 -0400
committerLen Brown <len.brown@intel.com>2010-06-12 00:44:37 -0400
commitfd247447c1d94a79d5cfc647430784306b3a8323 (patch)
treed3a58bb5e50068f4d9245f0788e7f14ff56ac711 /drivers/acpi/acpica/evgpe.c
parente4e9a735991c80fb0fc1bd4a13a93681c3c17ce0 (diff)
ACPI / ACPICA: Fix low-level GPE manipulation code
ACPICA uses acpi_ev_enable_gpe() for enabling GPEs at the low level, which is incorrect, because this function only enables the GPE if the corresponding bit in its enable register's enable_for_run mask is set. This causes acpi_set_gpe() to work incorrectly if used for enabling GPEs that were not previously enabled with acpi_enable_gpe(). As a result, among other things, wakeup-only GPEs are never enabled by acpi_enable_wakeup_device(), so the devices that use them are unable to wake up the system. To fix this issue remove acpi_ev_enable_gpe() and its counterpart acpi_ev_disable_gpe() and replace acpi_hw_low_disable_gpe() with acpi_hw_low_set_gpe() that will be used instead to manipulate GPE enable bits at the low level. Make the users of acpi_ev_enable_gpe() and acpi_ev_disable_gpe() call acpi_hw_low_set_gpe() instead and make sure that GPE enable masks are only updated by acpi_enable_gpe() and acpi_disable_gpe() when GPE reference counters change from 0 to 1 and from 1 to 0, respectively. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/evgpe.c')
-rw-r--r--drivers/acpi/acpica/evgpe.c108
1 files changed, 2 insertions, 106 deletions
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 57eeb3bde41e..66cd03835d6e 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -99,106 +99,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
99 return_ACPI_STATUS(AE_OK); 99 return_ACPI_STATUS(AE_OK);
100} 100}
101 101
102/*******************************************************************************
103 *
104 * FUNCTION: acpi_ev_enable_gpe
105 *
106 * PARAMETERS: gpe_event_info - GPE to enable
107 *
108 * RETURN: Status
109 *
110 * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
111 * of type or number of references.
112 *
113 * Note: The GPE lock should be already acquired when this function is called.
114 *
115 ******************************************************************************/
116
117acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
118{
119 acpi_status status;
120
121
122 ACPI_FUNCTION_TRACE(ev_enable_gpe);
123
124
125 /*
126 * We will only allow a GPE to be enabled if it has either an
127 * associated method (_Lxx/_Exx) or a handler. Otherwise, the
128 * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
129 * first time it fires.
130 */
131 if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
132 return_ACPI_STATUS(AE_NO_HANDLER);
133 }
134
135 /* Ensure the HW enable masks are current */
136
137 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
138 if (ACPI_FAILURE(status)) {
139 return_ACPI_STATUS(status);
140 }
141
142 /* Clear the GPE (of stale events) */
143
144 status = acpi_hw_clear_gpe(gpe_event_info);
145 if (ACPI_FAILURE(status)) {
146 return_ACPI_STATUS(status);
147 }
148
149 /* Enable the requested GPE */
150
151 status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
152 return_ACPI_STATUS(status);
153}
154
155/*******************************************************************************
156 *
157 * FUNCTION: acpi_ev_disable_gpe
158 *
159 * PARAMETERS: gpe_event_info - GPE to disable
160 *
161 * RETURN: Status
162 *
163 * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
164 * regardless of the type or number of references.
165 *
166 * Note: The GPE lock should be already acquired when this function is called.
167 *
168 ******************************************************************************/
169
170acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
171{
172 acpi_status status;
173
174 ACPI_FUNCTION_TRACE(ev_disable_gpe);
175
176
177 /*
178 * Note: Always disable the GPE, even if we think that that it is already
179 * disabled. It is possible that the AML or some other code has enabled
180 * the GPE behind our back.
181 */
182
183 /* Ensure the HW enable masks are current */
184
185 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
186 if (ACPI_FAILURE(status)) {
187 return_ACPI_STATUS(status);
188 }
189
190 /*
191 * Always H/W disable this GPE, even if we don't know the GPE type.
192 * Simply clear the enable bit for this particular GPE, but do not
193 * write out the current GPE enable mask since this may inadvertently
194 * enable GPEs too early. An example is a rogue GPE that has arrived
195 * during ACPICA initialization - possibly because AML or other code
196 * has enabled the GPE.
197 */
198 status = acpi_hw_low_disable_gpe(gpe_event_info);
199 return_ACPI_STATUS(status);
200}
201
202 102
203/******************************************************************************* 103/*******************************************************************************
204 * 104 *
@@ -450,10 +350,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
450 return_VOID; 350 return_VOID;
451 } 351 }
452 352
453 /* Update the GPE register masks for return to enabled state */
454
455 (void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
456
457 /* 353 /*
458 * Take a snapshot of the GPE info for this level - we copy the info to 354 * Take a snapshot of the GPE info for this level - we copy the info to
459 * prevent a race condition with remove_handler/remove_block. 355 * prevent a race condition with remove_handler/remove_block.
@@ -606,7 +502,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
606 * Disable the GPE, so it doesn't keep firing before the method has a 502 * Disable the GPE, so it doesn't keep firing before the method has a
607 * chance to run (it runs asynchronously with interrupts enabled). 503 * chance to run (it runs asynchronously with interrupts enabled).
608 */ 504 */
609 status = acpi_ev_disable_gpe(gpe_event_info); 505 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
610 if (ACPI_FAILURE(status)) { 506 if (ACPI_FAILURE(status)) {
611 ACPI_EXCEPTION((AE_INFO, status, 507 ACPI_EXCEPTION((AE_INFO, status,
612 "Unable to disable GPE[0x%2X]", 508 "Unable to disable GPE[0x%2X]",
@@ -643,7 +539,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
643 * Disable the GPE. The GPE will remain disabled a handler 539 * Disable the GPE. The GPE will remain disabled a handler
644 * is installed or ACPICA is restarted. 540 * is installed or ACPICA is restarted.
645 */ 541 */
646 status = acpi_ev_disable_gpe(gpe_event_info); 542 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
647 if (ACPI_FAILURE(status)) { 543 if (ACPI_FAILURE(status)) {
648 ACPI_EXCEPTION((AE_INFO, status, 544 ACPI_EXCEPTION((AE_INFO, status,
649 "Unable to disable GPE[0x%2X]", 545 "Unable to disable GPE[0x%2X]",