aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/acpica/acdebug.h3
-rw-r--r--drivers/acpi/acpica/acevents.h6
-rw-r--r--drivers/acpi/acpica/acglobal.h1
-rw-r--r--drivers/acpi/acpica/aclocal.h8
-rw-r--r--drivers/acpi/acpica/evgpeutil.c2
-rw-r--r--drivers/acpi/acpica/evmisc.c14
-rw-r--r--drivers/acpi/acpica/evsci.c80
-rw-r--r--drivers/acpi/acpica/evxface.c139
-rw-r--r--drivers/acpi/acpica/utglobal.c3
-rw-r--r--include/acpi/acpixf.h13
-rw-r--r--include/acpi/actypes.h3
11 files changed, 249 insertions, 23 deletions
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 9feba08c29fe..30c2d6911386 100644
--- a/drivers/acpi/acpica/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
@@ -113,11 +113,12 @@ void acpi_db_display_handlers(void);
113ACPI_HW_DEPENDENT_RETURN_VOID(void 113ACPI_HW_DEPENDENT_RETURN_VOID(void
114 acpi_db_generate_gpe(char *gpe_arg, 114 acpi_db_generate_gpe(char *gpe_arg,
115 char *block_arg)) 115 char *block_arg))
116 ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void))
116 117
117/* 118/*
118 * dbconvert - miscellaneous conversion routines 119 * dbconvert - miscellaneous conversion routines
119 */ 120 */
120 acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value); 121acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
121 122
122acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object); 123acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object);
123 124
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index ab0e97710381..3ae5fd02ae64 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -242,11 +242,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
242 */ 242 */
243u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context); 243u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context);
244 244
245u32 acpi_ev_install_sci_handler(void); 245u32 acpi_ev_sci_dispatch(void);
246 246
247acpi_status acpi_ev_remove_sci_handler(void); 247u32 acpi_ev_install_sci_handler(void);
248 248
249u32 acpi_ev_initialize_SCI(u32 program_SCI); 249acpi_status acpi_ev_remove_all_sci_handlers(void);
250 250
251ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void)) 251ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void))
252#endif /* __ACEVENTS_H__ */ 252#endif /* __ACEVENTS_H__ */
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index c9ad2e1f1ee1..0fba431f4fcb 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -269,6 +269,7 @@ ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler;
269ACPI_EXTERN void *acpi_gbl_table_handler_context; 269ACPI_EXTERN void *acpi_gbl_table_handler_context;
270ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; 270ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
271ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler; 271ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
272ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list;
272 273
273/* Owner ID support */ 274/* Owner ID support */
274 275
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 0ed00669cd21..be9e30ee6048 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -398,6 +398,14 @@ struct acpi_simple_repair_info {
398 * 398 *
399 ****************************************************************************/ 399 ****************************************************************************/
400 400
401/* Dispatch info for each host-installed SCI handler */
402
403struct acpi_sci_handler_info {
404 struct acpi_sci_handler_info *next;
405 acpi_sci_handler address; /* Address of handler */
406 void *context; /* Context to be passed to handler */
407};
408
401/* Dispatch info for each GPE -- either a method or handler, cannot be both */ 409/* Dispatch info for each GPE -- either a method or handler, cannot be both */
402 410
403struct acpi_gpe_handler_info { 411struct acpi_gpe_handler_info {
diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c
index b24dbb80fab8..d52339090b60 100644
--- a/drivers/acpi/acpica/evgpeutil.c
+++ b/drivers/acpi/acpica/evgpeutil.c
@@ -196,7 +196,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
196 * 196 *
197 * FUNCTION: acpi_ev_get_gpe_xrupt_block 197 * FUNCTION: acpi_ev_get_gpe_xrupt_block
198 * 198 *
199 * PARAMETERS: interrupt_number - Interrupt for a GPE block 199 * PARAMETERS: interrupt_number - Interrupt for a GPE block
200 * 200 *
201 * RETURN: A GPE interrupt block 201 * RETURN: A GPE interrupt block
202 * 202 *
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c
index 1b111ef74903..a5687540e9a6 100644
--- a/drivers/acpi/acpica/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -264,13 +264,6 @@ void acpi_ev_terminate(void)
264 264
265 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); 265 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
266 266
267 /* Remove SCI handler */
268
269 status = acpi_ev_remove_sci_handler();
270 if (ACPI_FAILURE(status)) {
271 ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
272 }
273
274 status = acpi_ev_remove_global_lock_handler(); 267 status = acpi_ev_remove_global_lock_handler();
275 if (ACPI_FAILURE(status)) { 268 if (ACPI_FAILURE(status)) {
276 ACPI_ERROR((AE_INFO, 269 ACPI_ERROR((AE_INFO,
@@ -280,6 +273,13 @@ void acpi_ev_terminate(void)
280 acpi_gbl_events_initialized = FALSE; 273 acpi_gbl_events_initialized = FALSE;
281 } 274 }
282 275
276 /* Remove SCI handlers */
277
278 status = acpi_ev_remove_all_sci_handlers();
279 if (ACPI_FAILURE(status)) {
280 ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
281 }
282
283 /* Deallocate all handler objects installed within GPE info structs */ 283 /* Deallocate all handler objects installed within GPE info structs */
284 284
285 status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL); 285 status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c
index b905acf7aacd..b2f0fb2f57b4 100644
--- a/drivers/acpi/acpica/evsci.c
+++ b/drivers/acpi/acpica/evsci.c
@@ -54,6 +54,52 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
54 54
55/******************************************************************************* 55/*******************************************************************************
56 * 56 *
57 * FUNCTION: acpi_ev_sci_dispatch
58 *
59 * PARAMETERS: None
60 *
61 * RETURN: Status code indicates whether interrupt was handled.
62 *
63 * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
64 *
65 ******************************************************************************/
66
67u32 acpi_ev_sci_dispatch(void)
68{
69 struct acpi_sci_handler_info *sci_handler;
70 acpi_cpu_flags flags;
71 u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
72
73 ACPI_FUNCTION_NAME(ev_sci_dispatch);
74
75 /* Are there any host-installed SCI handlers? */
76
77 if (!acpi_gbl_sci_handler_list) {
78 return (int_status);
79 }
80
81 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
82
83 /* Invoke all host-installed SCI handlers */
84
85 sci_handler = acpi_gbl_sci_handler_list;
86 while (sci_handler) {
87
88 /* Invoke the installed handler (at interrupt level) */
89
90 int_status |= sci_handler->address((u32)acpi_gbl_FADT.
91 sci_interrupt,
92 sci_handler->context);
93
94 sci_handler = sci_handler->next;
95 }
96
97 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
98 return (int_status);
99}
100
101/*******************************************************************************
102 *
57 * FUNCTION: acpi_ev_sci_xrupt_handler 103 * FUNCTION: acpi_ev_sci_xrupt_handler
58 * 104 *
59 * PARAMETERS: context - Calling Context 105 * PARAMETERS: context - Calling Context
@@ -89,6 +135,10 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
89 */ 135 */
90 interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); 136 interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
91 137
138 /* Invoke all host-installed SCI handlers */
139
140 interrupt_handled |= acpi_ev_sci_dispatch();
141
92 return_UINT32(interrupt_handled); 142 return_UINT32(interrupt_handled);
93} 143}
94 144
@@ -112,14 +162,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
112 ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler); 162 ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
113 163
114 /* 164 /*
115 * We are guaranteed by the ACPI CA initialization/shutdown code that 165 * We are guaranteed by the ACPICA initialization/shutdown code that
116 * if this interrupt handler is installed, ACPI is enabled. 166 * if this interrupt handler is installed, ACPI is enabled.
117 */ 167 */
118 168
119 /* GPEs: Check for and dispatch any GPEs that have occurred */ 169 /* GPEs: Check for and dispatch any GPEs that have occurred */
120 170
121 interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list); 171 interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
122
123 return_UINT32(interrupt_handled); 172 return_UINT32(interrupt_handled);
124} 173}
125 174
@@ -150,15 +199,15 @@ u32 acpi_ev_install_sci_handler(void)
150 199
151/****************************************************************************** 200/******************************************************************************
152 * 201 *
153 * FUNCTION: acpi_ev_remove_sci_handler 202 * FUNCTION: acpi_ev_remove_all_sci_handlers
154 * 203 *
155 * PARAMETERS: none 204 * PARAMETERS: none
156 * 205 *
157 * RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not 206 * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not
158 * installed to begin with 207 * installed to begin with
159 * 208 *
160 * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be 209 * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
161 * taken. 210 * taken. Remove all host-installed SCI handlers.
162 * 211 *
163 * Note: It doesn't seem important to disable all events or set the event 212 * Note: It doesn't seem important to disable all events or set the event
164 * enable registers to their original values. The OS should disable 213 * enable registers to their original values. The OS should disable
@@ -167,11 +216,13 @@ u32 acpi_ev_install_sci_handler(void)
167 * 216 *
168 ******************************************************************************/ 217 ******************************************************************************/
169 218
170acpi_status acpi_ev_remove_sci_handler(void) 219acpi_status acpi_ev_remove_all_sci_handlers(void)
171{ 220{
221 struct acpi_sci_handler_info *sci_handler;
222 acpi_cpu_flags flags;
172 acpi_status status; 223 acpi_status status;
173 224
174 ACPI_FUNCTION_TRACE(ev_remove_sci_handler); 225 ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
175 226
176 /* Just let the OS remove the handler and disable the level */ 227 /* Just let the OS remove the handler and disable the level */
177 228
@@ -179,6 +230,21 @@ acpi_status acpi_ev_remove_sci_handler(void)
179 acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt, 230 acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
180 acpi_ev_sci_xrupt_handler); 231 acpi_ev_sci_xrupt_handler);
181 232
233 if (!acpi_gbl_sci_handler_list) {
234 return (status);
235 }
236
237 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
238
239 /* Free all host-installed SCI handlers */
240
241 while (acpi_gbl_sci_handler_list) {
242 sci_handler = acpi_gbl_sci_handler_list;
243 acpi_gbl_sci_handler_list = sci_handler->next;
244 ACPI_FREE(sci_handler);
245 }
246
247 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
182 return_ACPI_STATUS(status); 248 return_ACPI_STATUS(status);
183} 249}
184 250
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index ca5fba99c33b..6f56146a6f88 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -385,6 +385,144 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
385#if (!ACPI_REDUCED_HARDWARE) 385#if (!ACPI_REDUCED_HARDWARE)
386/******************************************************************************* 386/*******************************************************************************
387 * 387 *
388 * FUNCTION: acpi_install_sci_handler
389 *
390 * PARAMETERS: address - Address of the handler
391 * context - Value passed to the handler on each SCI
392 *
393 * RETURN: Status
394 *
395 * DESCRIPTION: Install a handler for a System Control Interrupt.
396 *
397 ******************************************************************************/
398acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
399{
400 struct acpi_sci_handler_info *new_sci_handler;
401 struct acpi_sci_handler_info *sci_handler;
402 acpi_cpu_flags flags;
403 acpi_status status;
404
405 ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
406
407 if (!address) {
408 return_ACPI_STATUS(AE_BAD_PARAMETER);
409 }
410
411 /* Allocate and init a handler object */
412
413 new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
414 if (!new_sci_handler) {
415 return_ACPI_STATUS(AE_NO_MEMORY);
416 }
417
418 new_sci_handler->address = address;
419 new_sci_handler->context = context;
420
421 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
422 if (ACPI_FAILURE(status)) {
423 goto exit;
424 }
425
426 /* Lock list during installation */
427
428 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
429 sci_handler = acpi_gbl_sci_handler_list;
430
431 /* Ensure handler does not already exist */
432
433 while (sci_handler) {
434 if (address == sci_handler->address) {
435 status = AE_ALREADY_EXISTS;
436 goto unlock_and_exit;
437 }
438
439 sci_handler = sci_handler->next;
440 }
441
442 /* Install the new handler into the global list (at head) */
443
444 new_sci_handler->next = acpi_gbl_sci_handler_list;
445 acpi_gbl_sci_handler_list = new_sci_handler;
446
447 unlock_and_exit:
448
449 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
450 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
451
452 exit:
453 if (ACPI_FAILURE(status)) {
454 ACPI_FREE(new_sci_handler);
455 }
456 return_ACPI_STATUS(status);
457}
458
459/*******************************************************************************
460 *
461 * FUNCTION: acpi_remove_sci_handler
462 *
463 * PARAMETERS: address - Address of the handler
464 *
465 * RETURN: Status
466 *
467 * DESCRIPTION: Remove a handler for a System Control Interrupt.
468 *
469 ******************************************************************************/
470
471acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
472{
473 struct acpi_sci_handler_info *prev_sci_handler;
474 struct acpi_sci_handler_info *next_sci_handler;
475 acpi_cpu_flags flags;
476 acpi_status status;
477
478 ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
479
480 if (!address) {
481 return_ACPI_STATUS(AE_BAD_PARAMETER);
482 }
483
484 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
485 if (ACPI_FAILURE(status)) {
486 return_ACPI_STATUS(status);
487 }
488
489 /* Remove the SCI handler with lock */
490
491 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
492
493 prev_sci_handler = NULL;
494 next_sci_handler = acpi_gbl_sci_handler_list;
495 while (next_sci_handler) {
496 if (next_sci_handler->address == address) {
497
498 /* Unlink and free the SCI handler info block */
499
500 if (prev_sci_handler) {
501 prev_sci_handler->next = next_sci_handler->next;
502 } else {
503 acpi_gbl_sci_handler_list =
504 next_sci_handler->next;
505 }
506
507 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
508 ACPI_FREE(next_sci_handler);
509 goto unlock_and_exit;
510 }
511
512 prev_sci_handler = next_sci_handler;
513 next_sci_handler = next_sci_handler->next;
514 }
515
516 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
517 status = AE_NOT_EXIST;
518
519 unlock_and_exit:
520 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
521 return_ACPI_STATUS(status);
522}
523
524/*******************************************************************************
525 *
388 * FUNCTION: acpi_install_global_event_handler 526 * FUNCTION: acpi_install_global_event_handler
389 * 527 *
390 * PARAMETERS: handler - Pointer to the global event handler function 528 * PARAMETERS: handler - Pointer to the global event handler function
@@ -398,6 +536,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
398 * Can be used to update event counters, etc. 536 * Can be used to update event counters, etc.
399 * 537 *
400 ******************************************************************************/ 538 ******************************************************************************/
539
401acpi_status 540acpi_status
402acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context) 541acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
403{ 542{
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index d6f26bf8a062..046d5b059c07 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -291,7 +291,7 @@ acpi_status acpi_ut_init_globals(void)
291 291
292#if (!ACPI_REDUCED_HARDWARE) 292#if (!ACPI_REDUCED_HARDWARE)
293 293
294 /* GPE support */ 294 /* GPE/SCI support */
295 295
296 acpi_gbl_all_gpes_initialized = FALSE; 296 acpi_gbl_all_gpes_initialized = FALSE;
297 acpi_gbl_gpe_xrupt_list_head = NULL; 297 acpi_gbl_gpe_xrupt_list_head = NULL;
@@ -300,6 +300,7 @@ acpi_status acpi_ut_init_globals(void)
300 acpi_current_gpe_count = 0; 300 acpi_current_gpe_count = 0;
301 301
302 acpi_gbl_global_event_handler = NULL; 302 acpi_gbl_global_event_handler = NULL;
303 acpi_gbl_sci_handler_list = NULL;
303 304
304#endif /* !ACPI_REDUCED_HARDWARE */ 305#endif /* !ACPI_REDUCED_HARDWARE */
305 306
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 85bfdbe17805..55a4d3ae1477 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -280,9 +280,16 @@ acpi_status
280acpi_install_initialization_handler(acpi_init_handler handler, u32 function); 280acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
281 281
282ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status 282ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
283 acpi_install_global_event_handler 283 acpi_install_sci_handler(acpi_sci_handler
284 (acpi_gbl_event_handler handler, void *context)) 284 address,
285 285 void *context))
286ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
287 acpi_remove_sci_handler(acpi_sci_handler
288 address))
289ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
290 acpi_install_global_event_handler
291 (acpi_gbl_event_handler handler,
292 void *context))
286ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status 293ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
287 acpi_install_fixed_event_handler(u32 294 acpi_install_fixed_event_handler(u32
288 acpi_event, 295 acpi_event,
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index b748aefce929..850f75027fb6 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -946,6 +946,9 @@ typedef void
946 * Various handlers and callback procedures 946 * Various handlers and callback procedures
947 */ 947 */
948typedef 948typedef
949u32 (*acpi_sci_handler) (u32 interrupt_number, void *context);
950
951typedef
949void (*acpi_gbl_event_handler) (u32 event_type, 952void (*acpi_gbl_event_handler) (u32 event_type,
950 acpi_handle device, 953 acpi_handle device,
951 u32 event_number, void *context); 954 u32 event_number, void *context);