aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/acevents.h4
-rw-r--r--drivers/acpi/acpica/aclocal.h1
-rw-r--r--drivers/acpi/acpica/evgpe.c73
-rw-r--r--drivers/acpi/acpica/evxface.c77
-rw-r--r--drivers/acpi/acpica/evxfevnt.c62
5 files changed, 139 insertions, 78 deletions
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index e0e6affb0d80..36867cd70eac 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -82,6 +82,10 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info);
82 82
83acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info); 83acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
84 84
85acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
86
87acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
88
85struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, 89struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
86 u32 gpe_number); 90 u32 gpe_number);
87 91
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 1ee0bcf399aa..df85b53a674f 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -412,6 +412,7 @@ struct acpi_handler_info {
412 acpi_event_handler address; /* Address of handler, if any */ 412 acpi_event_handler address; /* Address of handler, if any */
413 void *context; /* Context to be passed to handler */ 413 void *context; /* Context to be passed to handler */
414 struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */ 414 struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
415 u8 orig_flags; /* Original misc info about this GPE */
415}; 416};
416 417
417union acpi_gpe_dispatch_info { 418union acpi_gpe_dispatch_info {
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index 7a6a3e6f4be0..f226eac314db 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -137,6 +137,79 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
137 137
138/******************************************************************************* 138/*******************************************************************************
139 * 139 *
140 * FUNCTION: acpi_raw_enable_gpe
141 *
142 * PARAMETERS: gpe_event_info - GPE to enable
143 *
144 * RETURN: Status
145 *
146 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
147 * hardware-enabled.
148 *
149 ******************************************************************************/
150
151acpi_status acpi_raw_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
152{
153 acpi_status status = AE_OK;
154
155 if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
156 return_ACPI_STATUS(AE_LIMIT);
157 }
158
159 gpe_event_info->runtime_count++;
160 if (gpe_event_info->runtime_count == 1) {
161 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
162 if (ACPI_SUCCESS(status)) {
163 status = acpi_ev_enable_gpe(gpe_event_info);
164 }
165
166 if (ACPI_FAILURE(status)) {
167 gpe_event_info->runtime_count--;
168 }
169 }
170
171 return_ACPI_STATUS(status);
172}
173
174/*******************************************************************************
175 *
176 * FUNCTION: acpi_raw_disable_gpe
177 *
178 * PARAMETERS: gpe_event_info - GPE to disable
179 *
180 * RETURN: Status
181 *
182 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
183 * removed, the GPE is hardware-disabled.
184 *
185 ******************************************************************************/
186
187acpi_status acpi_raw_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
188{
189 acpi_status status = AE_OK;
190
191 if (!gpe_event_info->runtime_count) {
192 return_ACPI_STATUS(AE_LIMIT);
193 }
194
195 gpe_event_info->runtime_count--;
196 if (!gpe_event_info->runtime_count) {
197 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
198 if (ACPI_SUCCESS(status)) {
199 status = acpi_hw_low_set_gpe(gpe_event_info,
200 ACPI_GPE_DISABLE);
201 }
202
203 if (ACPI_FAILURE(status)) {
204 gpe_event_info->runtime_count++;
205 }
206 }
207
208 return_ACPI_STATUS(status);
209}
210
211/*******************************************************************************
212 *
140 * FUNCTION: acpi_ev_low_get_gpe_info 213 * FUNCTION: acpi_ev_low_get_gpe_info
141 * 214 *
142 * PARAMETERS: gpe_number - Raw GPE number 215 * PARAMETERS: gpe_number - Raw GPE number
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 4a531cdf7942..14e48add32fa 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -691,12 +691,22 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
691 return_ACPI_STATUS(status); 691 return_ACPI_STATUS(status);
692 } 692 }
693 693
694 /* Allocate memory for the handler object */
695
696 handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info));
697 if (!handler) {
698 status = AE_NO_MEMORY;
699 goto unlock_and_exit;
700 }
701
702 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
703
694 /* Ensure that we have a valid GPE number */ 704 /* Ensure that we have a valid GPE number */
695 705
696 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 706 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
697 if (!gpe_event_info) { 707 if (!gpe_event_info) {
698 status = AE_BAD_PARAMETER; 708 status = AE_BAD_PARAMETER;
699 goto unlock_and_exit; 709 goto free_and_exit;
700 } 710 }
701 711
702 /* Make sure that there isn't a handler there already */ 712 /* Make sure that there isn't a handler there already */
@@ -704,24 +714,30 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
704 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == 714 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
705 ACPI_GPE_DISPATCH_HANDLER) { 715 ACPI_GPE_DISPATCH_HANDLER) {
706 status = AE_ALREADY_EXISTS; 716 status = AE_ALREADY_EXISTS;
707 goto unlock_and_exit; 717 goto free_and_exit;
708 } 718 }
709 719
710 /* Allocate and init handler object */ 720 /* Allocate and init handler object */
711 721
712 handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info));
713 if (!handler) {
714 status = AE_NO_MEMORY;
715 goto unlock_and_exit;
716 }
717
718 handler->address = address; 722 handler->address = address;
719 handler->context = context; 723 handler->context = context;
720 handler->method_node = gpe_event_info->dispatch.method_node; 724 handler->method_node = gpe_event_info->dispatch.method_node;
725 handler->orig_flags = gpe_event_info->flags &
726 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
727
728 /*
729 * If the GPE is associated with a method and it cannot wake up the
730 * system from sleep states, it was enabled automatically during
731 * initialization, so it has to be disabled now to avoid spurious
732 * execution of the handler.
733 */
734
735 if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
736 && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
737 (void)acpi_raw_disable_gpe(gpe_event_info);
721 738
722 /* Install the handler */ 739 /* Install the handler */
723 740
724 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
725 gpe_event_info->dispatch.handler = handler; 741 gpe_event_info->dispatch.handler = handler;
726 742
727 /* Setup up dispatch flags to indicate handler (vs. method) */ 743 /* Setup up dispatch flags to indicate handler (vs. method) */
@@ -735,6 +751,11 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
735unlock_and_exit: 751unlock_and_exit:
736 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 752 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
737 return_ACPI_STATUS(status); 753 return_ACPI_STATUS(status);
754
755free_and_exit:
756 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
757 ACPI_FREE(handler);
758 goto unlock_and_exit;
738} 759}
739 760
740ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) 761ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
@@ -770,11 +791,17 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
770 return_ACPI_STATUS(AE_BAD_PARAMETER); 791 return_ACPI_STATUS(AE_BAD_PARAMETER);
771 } 792 }
772 793
794 /* Make sure all deferred tasks are completed */
795
796 acpi_os_wait_events_complete(NULL);
797
773 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); 798 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
774 if (ACPI_FAILURE(status)) { 799 if (ACPI_FAILURE(status)) {
775 return_ACPI_STATUS(status); 800 return_ACPI_STATUS(status);
776 } 801 }
777 802
803 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
804
778 /* Ensure that we have a valid GPE number */ 805 /* Ensure that we have a valid GPE number */
779 806
780 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 807 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
@@ -798,34 +825,34 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
798 goto unlock_and_exit; 825 goto unlock_and_exit;
799 } 826 }
800 827
801 /* Make sure all deferred tasks are completed */
802
803 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
804 acpi_os_wait_events_complete(NULL);
805 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
806 if (ACPI_FAILURE(status)) {
807 return_ACPI_STATUS(status);
808 }
809
810 /* Remove the handler */ 828 /* Remove the handler */
811 829
812 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
813 handler = gpe_event_info->dispatch.handler; 830 handler = gpe_event_info->dispatch.handler;
814 831
815 /* Restore Method node (if any), set dispatch flags */ 832 /* Restore Method node (if any), set dispatch flags */
816 833
817 gpe_event_info->dispatch.method_node = handler->method_node; 834 gpe_event_info->dispatch.method_node = handler->method_node;
818 gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ 835 gpe_event_info->flags &=
819 if (handler->method_node) { 836 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
820 gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD; 837 gpe_event_info->flags |= handler->orig_flags;
821 } 838
822 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 839 /*
840 * If the GPE was previously associated with a method and it cannot wake
841 * up the system from sleep states, it should be enabled at this point
842 * to restore the post-initialization configuration.
843 */
844
845 if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
846 && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
847 (void)acpi_raw_enable_gpe(gpe_event_info);
823 848
824 /* Now we can free the handler object */ 849 /* Now we can free the handler object */
825 850
826 ACPI_FREE(handler); 851 ACPI_FREE(handler);
827 852
828 unlock_and_exit: 853unlock_and_exit:
854 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
855
829 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 856 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
830 return_ACPI_STATUS(status); 857 return_ACPI_STATUS(status);
831} 858}
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 53d591a11138..0fb9e94878d9 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -291,7 +291,7 @@ ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
291 ******************************************************************************/ 291 ******************************************************************************/
292acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) 292acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
293{ 293{
294 acpi_status status = AE_OK; 294 acpi_status status = AE_BAD_PARAMETER;
295 struct acpi_gpe_event_info *gpe_event_info; 295 struct acpi_gpe_event_info *gpe_event_info;
296 acpi_cpu_flags flags; 296 acpi_cpu_flags flags;
297 297
@@ -302,28 +302,10 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
302 /* Ensure that we have a valid GPE number */ 302 /* Ensure that we have a valid GPE number */
303 303
304 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 304 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
305 if (!gpe_event_info) { 305 if (gpe_event_info) {
306 status = AE_BAD_PARAMETER; 306 status = acpi_raw_enable_gpe(gpe_event_info);
307 goto unlock_and_exit;
308 } 307 }
309 308
310 if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
311 status = AE_LIMIT; /* Too many references */
312 goto unlock_and_exit;
313 }
314
315 gpe_event_info->runtime_count++;
316 if (gpe_event_info->runtime_count == 1) {
317 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
318 if (ACPI_SUCCESS(status)) {
319 status = acpi_ev_enable_gpe(gpe_event_info);
320 }
321 if (ACPI_FAILURE(status)) {
322 gpe_event_info->runtime_count--;
323 }
324 }
325
326unlock_and_exit:
327 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 309 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
328 return_ACPI_STATUS(status); 310 return_ACPI_STATUS(status);
329} 311}
@@ -345,7 +327,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
345 ******************************************************************************/ 327 ******************************************************************************/
346acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) 328acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
347{ 329{
348 acpi_status status = AE_OK; 330 acpi_status status = AE_BAD_PARAMETER;
349 struct acpi_gpe_event_info *gpe_event_info; 331 struct acpi_gpe_event_info *gpe_event_info;
350 acpi_cpu_flags flags; 332 acpi_cpu_flags flags;
351 333
@@ -356,32 +338,10 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
356 /* Ensure that we have a valid GPE number */ 338 /* Ensure that we have a valid GPE number */
357 339
358 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 340 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
359 if (!gpe_event_info) { 341 if (gpe_event_info) {
360 status = AE_BAD_PARAMETER; 342 status = acpi_raw_disable_gpe(gpe_event_info) ;
361 goto unlock_and_exit;
362 }
363
364 /* Hardware-disable a runtime GPE on removal of the last reference */
365
366 if (!gpe_event_info->runtime_count) {
367 status = AE_LIMIT; /* There are no references to remove */
368 goto unlock_and_exit;
369 } 343 }
370 344
371 gpe_event_info->runtime_count--;
372 if (!gpe_event_info->runtime_count) {
373 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
374 if (ACPI_SUCCESS(status)) {
375 status =
376 acpi_hw_low_set_gpe(gpe_event_info,
377 ACPI_GPE_DISABLE);
378 }
379 if (ACPI_FAILURE(status)) {
380 gpe_event_info->runtime_count++;
381 }
382 }
383
384unlock_and_exit:
385 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 345 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
386 return_ACPI_STATUS(status); 346 return_ACPI_STATUS(status);
387} 347}
@@ -408,7 +368,6 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
408 acpi_status status = AE_OK; 368 acpi_status status = AE_OK;
409 struct acpi_gpe_event_info *gpe_event_info; 369 struct acpi_gpe_event_info *gpe_event_info;
410 acpi_cpu_flags flags; 370 acpi_cpu_flags flags;
411 u8 disable = 0;
412 371
413 ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); 372 ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
414 373
@@ -427,15 +386,12 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
427 } 386 }
428 387
429 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; 388 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
430 disable = (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) 389 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
431 && gpe_event_info->runtime_count; 390 (void)acpi_raw_disable_gpe(gpe_event_info);
391 }
432 392
433unlock_and_exit: 393unlock_and_exit:
434 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 394 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
435
436 if (disable)
437 status = acpi_disable_gpe(gpe_device, gpe_number);
438
439 return_ACPI_STATUS(status); 395 return_ACPI_STATUS(status);
440} 396}
441ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) 397ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)