aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2013-09-22 21:52:05 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-09-23 19:46:24 -0400
commita2fd4b4b4e2884405c54a91514b0fad3853aea01 (patch)
tree8cc50104af68c2115dc5d0829941d304c156c71d /drivers/acpi
parentd53d820741806a5488d0f002b61765deb58371f3 (diff)
ACPICA: Add support for host-installed SCI handlers.
This change adds support to allow hosts to install System Control Interrupt handlers. Certain ACPI functionality requires the host to handle raw SCIs. For example, the "SCI Doorbell" that is defined for memory power state support requires the host device driver to handle SCIs to examine if the doorbell has been activated. Multiple SCI handlers can be installed to allow for future expansion. Debugger support is included. Lv Zheng, Bob Moore. ACPICA BZ 1032. Bug summary: It is reported when the PCC (Platform Communication Channel, via MPST table, defined in ACPI specification 5.0) subchannel responds to the host, it issues an SCI and the host must probe the subchannel for channel status. Buglink: http://bugs.acpica.org/show_bug.cgi?id=1032 Signed-off-by: Lv Zheng <lv.zheng@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Reviewed-by: Len Brown <len.brown@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-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
9 files changed, 236 insertions, 20 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