aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evxfgpe.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-02-11 19:39:15 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2011-02-11 19:39:15 -0500
commit2d55951368faa32ff098398c56780ebb6405a3d9 (patch)
tree0e6290e8fa625c8c028ca06edb629549e6379240 /drivers/acpi/acpica/evxfgpe.c
parent100b33c8bd8a3235fd0b7948338d6cbb3db3c63d (diff)
ACPI / ACPICA: Avoid crashing if _PRW is defined for the root object
Some ACPI BIOSes define _PRW for the root object which causes acpi_setup_gpe_for_wake() to crash when trying to dereference the bogus device_node pointer. Avoid the crash by checking if wake_device is not the root object before attempting to set up the "implicit notify" mechanism for it. The problem was introduced by commit bba63a296ffab20e08d9e8252d2f0d99 (ACPICA: Implicit notify support) that added the wake_device argument to acpi_setup_gpe_for_wake(). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/acpi/acpica/evxfgpe.c')
-rw-r--r--drivers/acpi/acpica/evxfgpe.c49
1 files changed, 26 insertions, 23 deletions
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index e9562a7cb2f..3b20a3401b6 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -212,37 +212,40 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
212 return_ACPI_STATUS(AE_BAD_PARAMETER); 212 return_ACPI_STATUS(AE_BAD_PARAMETER);
213 } 213 }
214 214
215 /* Validate wake_device is of type Device */
216
217 device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
218 if (device_node->type != ACPI_TYPE_DEVICE) {
219 return_ACPI_STATUS(AE_BAD_PARAMETER);
220 }
221
222 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 215 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
223 216
224 /* Ensure that we have a valid GPE number */ 217 /* Ensure that we have a valid GPE number */
225 218
226 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 219 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
227 if (gpe_event_info) { 220 if (!gpe_event_info) {
228 /* 221 goto unlock_and_exit;
229 * If there is no method or handler for this GPE, then the 222 }
230 * wake_device will be notified whenever this GPE fires (aka 223
231 * "implicit notify") Note: The GPE is assumed to be 224 /*
232 * level-triggered (for windows compatibility). 225 * If there is no method or handler for this GPE, then the
233 */ 226 * wake_device will be notified whenever this GPE fires (aka
234 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 227 * "implicit notify") Note: The GPE is assumed to be
235 ACPI_GPE_DISPATCH_NONE) { 228 * level-triggered (for windows compatibility).
236 gpe_event_info->flags = 229 */
237 (ACPI_GPE_DISPATCH_NOTIFY | 230 if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
238 ACPI_GPE_LEVEL_TRIGGERED); 231 ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) {
239 gpe_event_info->dispatch.device_node = device_node;
240 }
241 232
242 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; 233 /* Validate wake_device is of type Device */
243 status = AE_OK; 234
235 device_node = ACPI_CAST_PTR(struct acpi_namespace_node,
236 wake_device);
237 if (device_node->type != ACPI_TYPE_DEVICE) {
238 goto unlock_and_exit;
239 }
240 gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
241 ACPI_GPE_LEVEL_TRIGGERED);
242 gpe_event_info->dispatch.device_node = device_node;
244 } 243 }
245 244
245 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
246 status = AE_OK;
247
248 unlock_and_exit:
246 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 249 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
247 return_ACPI_STATUS(status); 250 return_ACPI_STATUS(status);
248} 251}