aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/acevents.h4
-rw-r--r--drivers/acpi/acpica/acglobal.h2
-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
-rw-r--r--drivers/acpi/acpica/utmutex.c5
7 files changed, 141 insertions, 83 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/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 18e796fe4295..1d192142c691 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -108,7 +108,7 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
108/* 108/*
109 * Optionally enable output from the AML Debug Object. 109 * Optionally enable output from the AML Debug Object.
110 */ 110 */
111u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE); 111u32 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
112 112
113/* 113/*
114 * Optionally copy the entire DSDT to local memory (instead of simply 114 * Optionally copy the entire DSDT to local memory (instead of simply
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 0ec900da5794..304825528d48 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -294,7 +294,7 @@ ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
294 ******************************************************************************/ 294 ******************************************************************************/
295acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) 295acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
296{ 296{
297 acpi_status status = AE_OK; 297 acpi_status status = AE_BAD_PARAMETER;
298 struct acpi_gpe_event_info *gpe_event_info; 298 struct acpi_gpe_event_info *gpe_event_info;
299 acpi_cpu_flags flags; 299 acpi_cpu_flags flags;
300 300
@@ -305,28 +305,10 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
305 /* Ensure that we have a valid GPE number */ 305 /* Ensure that we have a valid GPE number */
306 306
307 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 307 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
308 if (!gpe_event_info) { 308 if (gpe_event_info) {
309 status = AE_BAD_PARAMETER; 309 status = acpi_raw_enable_gpe(gpe_event_info);
310 goto unlock_and_exit;
311 } 310 }
312 311
313 if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
314 status = AE_LIMIT; /* Too many references */
315 goto unlock_and_exit;
316 }
317
318 gpe_event_info->runtime_count++;
319 if (gpe_event_info->runtime_count == 1) {
320 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
321 if (ACPI_SUCCESS(status)) {
322 status = acpi_ev_enable_gpe(gpe_event_info);
323 }
324 if (ACPI_FAILURE(status)) {
325 gpe_event_info->runtime_count--;
326 }
327 }
328
329unlock_and_exit:
330 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 312 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
331 return_ACPI_STATUS(status); 313 return_ACPI_STATUS(status);
332} 314}
@@ -348,7 +330,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
348 ******************************************************************************/ 330 ******************************************************************************/
349acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) 331acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
350{ 332{
351 acpi_status status = AE_OK; 333 acpi_status status = AE_BAD_PARAMETER;
352 struct acpi_gpe_event_info *gpe_event_info; 334 struct acpi_gpe_event_info *gpe_event_info;
353 acpi_cpu_flags flags; 335 acpi_cpu_flags flags;
354 336
@@ -359,32 +341,10 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
359 /* Ensure that we have a valid GPE number */ 341 /* Ensure that we have a valid GPE number */
360 342
361 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); 343 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
362 if (!gpe_event_info) { 344 if (gpe_event_info) {
363 status = AE_BAD_PARAMETER; 345 status = acpi_raw_disable_gpe(gpe_event_info) ;
364 goto unlock_and_exit;
365 }
366
367 /* Hardware-disable a runtime GPE on removal of the last reference */
368
369 if (!gpe_event_info->runtime_count) {
370 status = AE_LIMIT; /* There are no references to remove */
371 goto unlock_and_exit;
372 } 346 }
373 347
374 gpe_event_info->runtime_count--;
375 if (!gpe_event_info->runtime_count) {
376 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
377 if (ACPI_SUCCESS(status)) {
378 status =
379 acpi_hw_low_set_gpe(gpe_event_info,
380 ACPI_GPE_DISABLE);
381 }
382 if (ACPI_FAILURE(status)) {
383 gpe_event_info->runtime_count++;
384 }
385 }
386
387unlock_and_exit:
388 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 348 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
389 return_ACPI_STATUS(status); 349 return_ACPI_STATUS(status);
390} 350}
@@ -411,7 +371,6 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
411 acpi_status status = AE_OK; 371 acpi_status status = AE_OK;
412 struct acpi_gpe_event_info *gpe_event_info; 372 struct acpi_gpe_event_info *gpe_event_info;
413 acpi_cpu_flags flags; 373 acpi_cpu_flags flags;
414 u8 disable = 0;
415 374
416 ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); 375 ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
417 376
@@ -430,15 +389,12 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
430 } 389 }
431 390
432 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; 391 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
433 disable = (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) 392 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
434 && gpe_event_info->runtime_count; 393 (void)acpi_raw_disable_gpe(gpe_event_info);
394 }
435 395
436unlock_and_exit: 396unlock_and_exit:
437 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 397 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
438
439 if (disable)
440 status = acpi_disable_gpe(gpe_device, gpe_number);
441
442 return_ACPI_STATUS(status); 398 return_ACPI_STATUS(status);
443} 399}
444ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) 400ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 058b3df48271..f5cca3a1300c 100644
--- a/drivers/acpi/acpica/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -279,13 +279,10 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
279 279
280acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id) 280acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
281{ 281{
282 acpi_thread_id this_thread_id;
283
284 ACPI_FUNCTION_NAME(ut_release_mutex); 282 ACPI_FUNCTION_NAME(ut_release_mutex);
285 283
286 this_thread_id = acpi_os_get_thread_id();
287 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n", 284 ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n",
288 ACPI_CAST_PTR(void, this_thread_id), 285 ACPI_CAST_PTR(void, acpi_os_get_thread_id()),
289 acpi_ut_get_mutex_name(mutex_id))); 286 acpi_ut_get_mutex_name(mutex_id)));
290 287
291 if (mutex_id > ACPI_MAX_MUTEX) { 288 if (mutex_id > ACPI_MAX_MUTEX) {