diff options
Diffstat (limited to 'drivers/acpi/acpica/evxfgpe.c')
| -rw-r--r-- | drivers/acpi/acpica/evxfgpe.c | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index e9562a7cb2f9..52aaff3df562 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
| @@ -198,7 +198,9 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, | |||
| 198 | acpi_status status = AE_BAD_PARAMETER; | 198 | acpi_status status = AE_BAD_PARAMETER; |
| 199 | struct acpi_gpe_event_info *gpe_event_info; | 199 | struct acpi_gpe_event_info *gpe_event_info; |
| 200 | struct acpi_namespace_node *device_node; | 200 | struct acpi_namespace_node *device_node; |
| 201 | struct acpi_gpe_notify_object *notify_object; | ||
| 201 | acpi_cpu_flags flags; | 202 | acpi_cpu_flags flags; |
| 203 | u8 gpe_dispatch_mask; | ||
| 202 | 204 | ||
| 203 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); | 205 | ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); |
| 204 | 206 | ||
| @@ -212,37 +214,62 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, | |||
| 212 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 214 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
| 213 | } | 215 | } |
| 214 | 216 | ||
| 217 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
| 218 | |||
| 219 | /* Ensure that we have a valid GPE number */ | ||
| 220 | |||
| 221 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
| 222 | if (!gpe_event_info) { | ||
| 223 | goto unlock_and_exit; | ||
| 224 | } | ||
| 225 | |||
| 226 | if (wake_device == ACPI_ROOT_OBJECT) { | ||
| 227 | goto out; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* | ||
| 231 | * If there is no method or handler for this GPE, then the | ||
| 232 | * wake_device will be notified whenever this GPE fires (aka | ||
| 233 | * "implicit notify") Note: The GPE is assumed to be | ||
| 234 | * level-triggered (for windows compatibility). | ||
| 235 | */ | ||
| 236 | gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK; | ||
| 237 | if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE | ||
| 238 | && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) { | ||
| 239 | goto out; | ||
| 240 | } | ||
| 241 | |||
| 215 | /* Validate wake_device is of type Device */ | 242 | /* Validate wake_device is of type Device */ |
| 216 | 243 | ||
| 217 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); | 244 | device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); |
| 218 | if (device_node->type != ACPI_TYPE_DEVICE) { | 245 | if (device_node->type != ACPI_TYPE_DEVICE) { |
| 219 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 246 | goto unlock_and_exit; |
| 220 | } | 247 | } |
| 221 | 248 | ||
| 222 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 249 | if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) { |
| 250 | gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | | ||
| 251 | ACPI_GPE_LEVEL_TRIGGERED); | ||
| 252 | gpe_event_info->dispatch.device.node = device_node; | ||
| 253 | gpe_event_info->dispatch.device.next = NULL; | ||
| 254 | } else { | ||
| 255 | /* There are multiple devices to notify implicitly. */ | ||
| 223 | 256 | ||
| 224 | /* Ensure that we have a valid GPE number */ | 257 | notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object)); |
| 225 | 258 | if (!notify_object) { | |
| 226 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 259 | status = AE_NO_MEMORY; |
| 227 | if (gpe_event_info) { | 260 | goto unlock_and_exit; |
| 228 | /* | ||
| 229 | * If there is no method or handler for this GPE, then the | ||
| 230 | * wake_device will be notified whenever this GPE fires (aka | ||
| 231 | * "implicit notify") Note: The GPE is assumed to be | ||
| 232 | * level-triggered (for windows compatibility). | ||
| 233 | */ | ||
| 234 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | ||
| 235 | ACPI_GPE_DISPATCH_NONE) { | ||
| 236 | gpe_event_info->flags = | ||
| 237 | (ACPI_GPE_DISPATCH_NOTIFY | | ||
| 238 | ACPI_GPE_LEVEL_TRIGGERED); | ||
| 239 | gpe_event_info->dispatch.device_node = device_node; | ||
| 240 | } | 261 | } |
| 241 | 262 | ||
| 242 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | 263 | notify_object->node = device_node; |
| 243 | status = AE_OK; | 264 | notify_object->next = gpe_event_info->dispatch.device.next; |
| 265 | gpe_event_info->dispatch.device.next = notify_object; | ||
| 244 | } | 266 | } |
| 245 | 267 | ||
| 268 | out: | ||
| 269 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | ||
| 270 | status = AE_OK; | ||
| 271 | |||
| 272 | unlock_and_exit: | ||
| 246 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 273 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
| 247 | return_ACPI_STATUS(status); | 274 | return_ACPI_STATUS(status); |
| 248 | } | 275 | } |
