diff options
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r-- | drivers/acpi/ec.c | 107 |
1 files changed, 12 insertions, 95 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 9c7fce6a42e8..0f232e719daf 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -112,11 +112,6 @@ static struct acpi_ec *ec_ecdt; | |||
112 | static struct acpi_device *first_ec; | 112 | static struct acpi_device *first_ec; |
113 | static int acpi_ec_mode = EC_INTR; | 113 | static int acpi_ec_mode = EC_INTR; |
114 | 114 | ||
115 | static void acpi_ec_gpe_poll_query(void *ec_cxt); | ||
116 | static void acpi_ec_gpe_intr_query(void *ec_cxt); | ||
117 | static u32 acpi_ec_gpe_poll_handler(void *data); | ||
118 | static u32 acpi_ec_gpe_intr_handler(void *data); | ||
119 | |||
120 | /* -------------------------------------------------------------------------- | 115 | /* -------------------------------------------------------------------------- |
121 | Transaction Management | 116 | Transaction Management |
122 | -------------------------------------------------------------------------- */ | 117 | -------------------------------------------------------------------------- */ |
@@ -428,21 +423,13 @@ static int acpi_ec_query(struct acpi_ec *ec, u32 * data) | |||
428 | Event Management | 423 | Event Management |
429 | -------------------------------------------------------------------------- */ | 424 | -------------------------------------------------------------------------- */ |
430 | 425 | ||
431 | union acpi_ec_query_data { | 426 | struct acpi_ec_query_data { |
432 | acpi_handle handle; | 427 | acpi_handle handle; |
433 | u8 data; | 428 | u8 data; |
434 | }; | 429 | }; |
435 | 430 | ||
436 | static void acpi_ec_gpe_query(void *ec_cxt) | 431 | static void acpi_ec_gpe_query(void *ec_cxt) |
437 | { | 432 | { |
438 | if (acpi_ec_mode == EC_POLL) | ||
439 | acpi_ec_gpe_poll_query(ec_cxt); | ||
440 | else | ||
441 | acpi_ec_gpe_intr_query(ec_cxt); | ||
442 | } | ||
443 | |||
444 | static void acpi_ec_gpe_poll_query(void *ec_cxt) | ||
445 | { | ||
446 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; | 433 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; |
447 | u32 value = 0; | 434 | u32 value = 0; |
448 | static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; | 435 | static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; |
@@ -454,18 +441,8 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt) | |||
454 | if (!ec_cxt) | 441 | if (!ec_cxt) |
455 | goto end; | 442 | goto end; |
456 | 443 | ||
457 | if (down_interruptible (&ec->sem)) { | ||
458 | return; | ||
459 | } | ||
460 | value = acpi_ec_read_status(ec); | 444 | value = acpi_ec_read_status(ec); |
461 | up(&ec->sem); | ||
462 | 445 | ||
463 | /* TBD: Implement asynch events! | ||
464 | * NOTE: All we care about are EC-SCI's. Other EC events are | ||
465 | * handled via polling (yuck!). This is because some systems | ||
466 | * treat EC-SCIs as level (versus EDGE!) triggered, preventing | ||
467 | * a purely interrupt-driven approach (grumble, grumble). | ||
468 | */ | ||
469 | if (!(value & ACPI_EC_FLAG_SCI)) | 446 | if (!(value & ACPI_EC_FLAG_SCI)) |
470 | goto end; | 447 | goto end; |
471 | 448 | ||
@@ -475,96 +452,36 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt) | |||
475 | object_name[2] = hex[((value >> 4) & 0x0F)]; | 452 | object_name[2] = hex[((value >> 4) & 0x0F)]; |
476 | object_name[3] = hex[(value & 0x0F)]; | 453 | object_name[3] = hex[(value & 0x0F)]; |
477 | 454 | ||
478 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); | 455 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); |
479 | 456 | ||
480 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | 457 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); |
481 | 458 | ||
482 | end: | 459 | end: |
483 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 460 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); |
484 | } | 461 | } |
485 | static void acpi_ec_gpe_intr_query(void *ec_cxt) | ||
486 | { | ||
487 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; | ||
488 | u32 value; | ||
489 | int result = -ENODATA; | ||
490 | static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; | ||
491 | const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', | ||
492 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
493 | }; | ||
494 | |||
495 | |||
496 | if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) | ||
497 | result = acpi_ec_query(ec, &value); | ||
498 | |||
499 | if (result) | ||
500 | goto end; | ||
501 | |||
502 | object_name[2] = hex[((value >> 4) & 0x0F)]; | ||
503 | object_name[3] = hex[(value & 0x0F)]; | ||
504 | |||
505 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); | ||
506 | |||
507 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | ||
508 | end: | ||
509 | return; | ||
510 | } | ||
511 | 462 | ||
512 | static u32 acpi_ec_gpe_handler(void *data) | 463 | static u32 acpi_ec_gpe_handler(void *data) |
513 | { | 464 | { |
514 | if (acpi_ec_mode == EC_POLL) | ||
515 | return acpi_ec_gpe_poll_handler(data); | ||
516 | else | ||
517 | return acpi_ec_gpe_intr_handler(data); | ||
518 | } | ||
519 | static u32 acpi_ec_gpe_poll_handler(void *data) | ||
520 | { | ||
521 | acpi_status status = AE_OK; | ||
522 | struct acpi_ec *ec = (struct acpi_ec *)data; | ||
523 | |||
524 | if (!ec) | ||
525 | return ACPI_INTERRUPT_NOT_HANDLED; | ||
526 | |||
527 | acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR); | ||
528 | |||
529 | status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec); | ||
530 | |||
531 | if (status == AE_OK) | ||
532 | return ACPI_INTERRUPT_HANDLED; | ||
533 | else | ||
534 | return ACPI_INTERRUPT_NOT_HANDLED; | ||
535 | } | ||
536 | static u32 acpi_ec_gpe_intr_handler(void *data) | ||
537 | { | ||
538 | acpi_status status = AE_OK; | 465 | acpi_status status = AE_OK; |
539 | u32 value; | 466 | u32 value; |
467 | u8 exec_mode; | ||
540 | struct acpi_ec *ec = (struct acpi_ec *)data; | 468 | struct acpi_ec *ec = (struct acpi_ec *)data; |
541 | 469 | ||
542 | if (!ec) | ||
543 | return ACPI_INTERRUPT_NOT_HANDLED; | ||
544 | |||
545 | acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 470 | acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); |
546 | value = acpi_ec_read_status(ec); | 471 | value = acpi_ec_read_status(ec); |
547 | 472 | ||
548 | switch (ec->expect_event) { | 473 | if (acpi_ec_mode == EC_INTR) { |
549 | case ACPI_EC_EVENT_OBF_1: | 474 | if (acpi_ec_check_status(value, ec->expect_event)) { |
550 | if (!(value & ACPI_EC_FLAG_OBF)) | 475 | ec->expect_event = 0; |
551 | break; | 476 | wake_up(&ec->wait); |
552 | ec->expect_event = 0; | 477 | } |
553 | wake_up(&ec->wait); | 478 | exec_mode = OSL_EC_BURST_HANDLER; |
554 | break; | 479 | } else { |
555 | case ACPI_EC_EVENT_IBF_0: | 480 | exec_mode = OSL_EC_POLL_HANDLER; |
556 | if ((value & ACPI_EC_FLAG_IBF)) | ||
557 | break; | ||
558 | ec->expect_event = 0; | ||
559 | wake_up(&ec->wait); | ||
560 | break; | ||
561 | default: | ||
562 | break; | ||
563 | } | 481 | } |
564 | 482 | ||
565 | if (value & ACPI_EC_FLAG_SCI) { | 483 | if (value & ACPI_EC_FLAG_SCI) { |
566 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, | 484 | status = acpi_os_execute(exec_mode, acpi_ec_gpe_query, ec); |
567 | acpi_ec_gpe_query, ec); | ||
568 | return status == AE_OK ? | 485 | return status == AE_OK ? |
569 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 486 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
570 | } | 487 | } |