From 31a889617a91f24ffbbf4a166b592890f7eb76cb Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 24 Feb 2011 10:58:57 -0500 Subject: [PATCH] linux-2.6-acpi-fix-implicit-notify.patch: Fix implicit notify when there's more than one device per GPE --- kernel.spec | 8 +- linux-2.6-acpi-fix-implicit-notify.patch | 129 +++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 linux-2.6-acpi-fix-implicit-notify.patch diff --git a/kernel.spec b/kernel.spec index d5c04d6d5..187843eda 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -640,6 +640,7 @@ Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch Patch393: acpi-ec-add-delay-before-write.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch +Patch395: linux-2.6-acpi-fix-implicit-notify.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch @@ -1209,6 +1210,7 @@ ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch ApplyPatch acpi-ec-add-delay-before-write.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch +ApplyPatch linux-2.6-acpi-fix-implicit-notify.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-sizeof-structs.patch @@ -1951,6 +1953,10 @@ fi # and build. %changelog +* Thu Feb 24 2011 Matthew Garrett 2.6.38-0.rc6.git2.2 +- linux-2.6-acpi-fix-implicit-notify.patch: Fix implicit notify when there's + more than one device per GPE + * Wed Feb 23 2011 Chuck Ebbert 2.6.38-0.rc6.git2.1 - Linux 2.6.38-rc6-git2 diff --git a/linux-2.6-acpi-fix-implicit-notify.patch b/linux-2.6-acpi-fix-implicit-notify.patch new file mode 100644 index 000000000..7987be887 --- /dev/null +++ b/linux-2.6-acpi-fix-implicit-notify.patch @@ -0,0 +1,129 @@ +Index: linux-2.6/drivers/acpi/acpica/aclocal.h +=================================================================== +--- linux-2.6.orig/drivers/acpi/acpica/aclocal.h ++++ linux-2.6/drivers/acpi/acpica/aclocal.h +@@ -416,10 +416,15 @@ struct acpi_gpe_handler_info { + u8 originally_enabled; /* True if GPE was originally enabled */ + }; + ++struct acpi_gpe_notify_object { ++ struct acpi_namespace_node *node; ++ struct acpi_gpe_notify_object *next; ++}; ++ + union acpi_gpe_dispatch_info { + struct acpi_namespace_node *method_node; /* Method node for this GPE level */ + struct acpi_gpe_handler_info *handler; /* Installed GPE handler */ +- struct acpi_namespace_node *device_node; /* Parent _PRW device for implicit notify */ ++ struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */ + }; + + /* +Index: linux-2.6/drivers/acpi/acpica/evxfgpe.c +=================================================================== +--- linux-2.6.orig/drivers/acpi/acpica/evxfgpe.c ++++ linux-2.6/drivers/acpi/acpica/evxfgpe.c +@@ -198,7 +198,9 @@ acpi_setup_gpe_for_wake(acpi_handle wake + acpi_status status = AE_BAD_PARAMETER; + struct acpi_gpe_event_info *gpe_event_info; + struct acpi_namespace_node *device_node; ++ struct acpi_gpe_notify_object *notify_object; + acpi_cpu_flags flags; ++ u8 gpe_dispatch_mask; + + ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake); + +@@ -221,27 +223,49 @@ acpi_setup_gpe_for_wake(acpi_handle wake + goto unlock_and_exit; + } + ++ if (wake_device == ACPI_ROOT_OBJECT) { ++ goto out; ++ } ++ + /* + * If there is no method or handler for this GPE, then the + * wake_device will be notified whenever this GPE fires (aka + * "implicit notify") Note: The GPE is assumed to be + * level-triggered (for windows compatibility). + */ +- if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == +- ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) { ++ gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK; ++ if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE ++ && gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) { ++ goto out; ++ } + +- /* Validate wake_device is of type Device */ ++ /* Validate wake_device is of type Device */ + +- device_node = ACPI_CAST_PTR(struct acpi_namespace_node, +- wake_device); +- if (device_node->type != ACPI_TYPE_DEVICE) { +- goto unlock_and_exit; +- } ++ device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); ++ if (device_node->type != ACPI_TYPE_DEVICE) { ++ goto unlock_and_exit; ++ } ++ ++ if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) { + gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | + ACPI_GPE_LEVEL_TRIGGERED); +- gpe_event_info->dispatch.device_node = device_node; ++ gpe_event_info->dispatch.device.node = device_node; ++ gpe_event_info->dispatch.device.next = NULL; ++ } else { ++ /* There are multiple devices to notify implicitly. */ ++ ++ notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object)); ++ if (!notify_object) { ++ status = AE_NO_MEMORY; ++ goto unlock_and_exit; ++ } ++ ++ notify_object->node = device_node; ++ notify_object->next = gpe_event_info->dispatch.device.next; ++ gpe_event_info->dispatch.device.next = notify_object; + } + ++ out: + gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; + status = AE_OK; + +Index: linux-2.6/drivers/acpi/acpica/evgpe.c +=================================================================== +--- linux-2.6.orig/drivers/acpi/acpica/evgpe.c ++++ linux-2.6/drivers/acpi/acpica/evgpe.c +@@ -457,6 +457,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as + acpi_status status; + struct acpi_gpe_event_info *local_gpe_event_info; + struct acpi_evaluate_info *info; ++ struct acpi_gpe_notify_object *notify_object; + + ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method); + +@@ -508,10 +509,18 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as + * from this thread -- because handlers may in turn run other + * control methods. + */ +- status = +- acpi_ev_queue_notify_request(local_gpe_event_info->dispatch. +- device_node, +- ACPI_NOTIFY_DEVICE_WAKE); ++ status = acpi_ev_queue_notify_request( ++ local_gpe_event_info->dispatch.device.node, ++ ACPI_NOTIFY_DEVICE_WAKE); ++ ++ notify_object = local_gpe_event_info->dispatch.device.next; ++ while (ACPI_SUCCESS(status) && notify_object) { ++ status = acpi_ev_queue_notify_request( ++ notify_object->node, ++ ACPI_NOTIFY_DEVICE_WAKE); ++ notify_object = notify_object->next; ++ } ++ + break; + + case ACPI_GPE_DISPATCH_METHOD: