diff options
| -rw-r--r-- | drivers/acpi/ec.c | 171 |
1 files changed, 59 insertions, 112 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b15f5ec81d05..7e1a445955bc 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -212,19 +212,29 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) | |||
| 212 | ec->burst.expect_event = event; | 212 | ec->burst.expect_event = event; |
| 213 | smp_mb(); | 213 | smp_mb(); |
| 214 | 214 | ||
| 215 | result = wait_event_interruptible_timeout(ec->burst.wait, | 215 | switch (event) { |
| 216 | !ec->burst.expect_event, | 216 | case ACPI_EC_EVENT_OBF: |
| 217 | msecs_to_jiffies | 217 | if (acpi_ec_read_status(ec) & event) { |
| 218 | (ACPI_EC_DELAY)); | 218 | ec->burst.expect_event = 0; |
| 219 | return_VALUE(0); | ||
| 220 | } | ||
| 221 | break; | ||
| 222 | |||
| 223 | case ACPI_EC_EVENT_IBE: | ||
| 224 | if (~acpi_ec_read_status(ec) & event) { | ||
| 225 | ec->burst.expect_event = 0; | ||
| 226 | return_VALUE(0); | ||
| 227 | } | ||
| 228 | break; | ||
| 229 | } | ||
| 230 | |||
| 231 | result = wait_event_timeout(ec->burst.wait, | ||
| 232 | !ec->burst.expect_event, | ||
| 233 | msecs_to_jiffies(ACPI_EC_DELAY)); | ||
| 219 | 234 | ||
| 220 | ec->burst.expect_event = 0; | 235 | ec->burst.expect_event = 0; |
| 221 | smp_mb(); | 236 | smp_mb(); |
| 222 | 237 | ||
| 223 | if (result < 0) { | ||
| 224 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, " result = %d ", result)); | ||
| 225 | return_VALUE(result); | ||
| 226 | } | ||
| 227 | |||
| 228 | /* | 238 | /* |
| 229 | * Verify that the event in question has actually happened by | 239 | * Verify that the event in question has actually happened by |
| 230 | * querying EC status. Do the check even if operation timed-out | 240 | * querying EC status. Do the check even if operation timed-out |
| @@ -254,15 +264,15 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec) | |||
| 254 | 264 | ||
| 255 | status = acpi_ec_read_status(ec); | 265 | status = acpi_ec_read_status(ec); |
| 256 | if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { | 266 | if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { |
| 267 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 268 | if (status) | ||
| 269 | goto end; | ||
| 257 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, | 270 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, |
| 258 | &ec->common.command_addr); | 271 | &ec->common.command_addr); |
| 259 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 272 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 260 | if (status) { | 273 | if (status) |
| 261 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 262 | return_VALUE(-EINVAL); | 274 | return_VALUE(-EINVAL); |
| 263 | } | ||
| 264 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); | 275 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); |
| 265 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 266 | if (tmp != 0x90) { /* Burst ACK byte */ | 276 | if (tmp != 0x90) { /* Burst ACK byte */ |
| 267 | return_VALUE(-EINVAL); | 277 | return_VALUE(-EINVAL); |
| 268 | } | 278 | } |
| @@ -270,30 +280,17 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec) | |||
| 270 | 280 | ||
| 271 | atomic_set(&ec->burst.leaving_burst, 0); | 281 | atomic_set(&ec->burst.leaving_burst, 0); |
| 272 | return_VALUE(0); | 282 | return_VALUE(0); |
| 283 | end: | ||
| 284 | printk("Error in acpi_ec_wait\n"); | ||
| 285 | return_VALUE(-1); | ||
| 273 | } | 286 | } |
| 274 | 287 | ||
| 275 | static int acpi_ec_leave_burst_mode(union acpi_ec *ec) | 288 | static int acpi_ec_leave_burst_mode(union acpi_ec *ec) |
| 276 | { | 289 | { |
| 277 | int status = 0; | ||
| 278 | 290 | ||
| 279 | ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); | 291 | ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); |
| 280 | 292 | ||
| 281 | atomic_set(&ec->burst.leaving_burst, 1); | 293 | atomic_set(&ec->burst.leaving_burst, 1); |
| 282 | status = acpi_ec_read_status(ec); | ||
| 283 | if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)) { | ||
| 284 | acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, | ||
| 285 | &ec->common.command_addr); | ||
| 286 | status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); | ||
| 287 | if (status) { | ||
| 288 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 289 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
| 290 | "------->wait fail\n")); | ||
| 291 | return_VALUE(-EINVAL); | ||
| 292 | } | ||
| 293 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 294 | status = acpi_ec_read_status(ec); | ||
| 295 | } | ||
| 296 | |||
| 297 | return_VALUE(0); | 294 | return_VALUE(0); |
| 298 | } | 295 | } |
| 299 | 296 | ||
| @@ -416,7 +413,6 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) | |||
| 416 | if (!ec || !data) | 413 | if (!ec || !data) |
| 417 | return_VALUE(-EINVAL); | 414 | return_VALUE(-EINVAL); |
| 418 | 415 | ||
| 419 | retry: | ||
| 420 | *data = 0; | 416 | *data = 0; |
| 421 | 417 | ||
| 422 | if (ec->common.global_lock) { | 418 | if (ec->common.global_lock) { |
| @@ -428,27 +424,26 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) | |||
| 428 | WARN_ON(in_interrupt()); | 424 | WARN_ON(in_interrupt()); |
| 429 | down(&ec->burst.sem); | 425 | down(&ec->burst.sem); |
| 430 | 426 | ||
| 431 | if (acpi_ec_enter_burst_mode(ec)) | 427 | acpi_ec_enter_burst_mode(ec); |
| 428 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 429 | if (status) { | ||
| 430 | printk("read EC, IB not empty\n"); | ||
| 432 | goto end; | 431 | goto end; |
| 433 | 432 | } | |
| 434 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, | 433 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, |
| 435 | &ec->common.command_addr); | 434 | &ec->common.command_addr); |
| 436 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 435 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 437 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 438 | if (status) { | 436 | if (status) { |
| 439 | goto end; | 437 | printk("read EC, IB not empty\n"); |
| 440 | } | 438 | } |
| 441 | 439 | ||
| 442 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | 440 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
| 443 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 441 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 444 | if (status) { | 442 | if (status) { |
| 445 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | 443 | printk("read EC, OB not full\n"); |
| 446 | goto end; | 444 | goto end; |
| 447 | } | 445 | } |
| 448 | |||
| 449 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | 446 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); |
| 450 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 451 | |||
| 452 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", | 447 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", |
| 453 | *data, address)); | 448 | *data, address)); |
| 454 | 449 | ||
| @@ -459,15 +454,6 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data) | |||
| 459 | if (ec->common.global_lock) | 454 | if (ec->common.global_lock) |
| 460 | acpi_release_global_lock(glk); | 455 | acpi_release_global_lock(glk); |
| 461 | 456 | ||
| 462 | if (atomic_read(&ec->burst.leaving_burst) == 2) { | ||
| 463 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aborted, retry ...\n")); | ||
| 464 | while (atomic_read(&ec->burst.pending_gpe)) { | ||
| 465 | msleep(1); | ||
| 466 | } | ||
| 467 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 468 | goto retry; | ||
| 469 | } | ||
| 470 | |||
| 471 | return_VALUE(status); | 457 | return_VALUE(status); |
| 472 | } | 458 | } |
| 473 | 459 | ||
| @@ -475,13 +461,12 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data) | |||
| 475 | { | 461 | { |
| 476 | int status = 0; | 462 | int status = 0; |
| 477 | u32 glk; | 463 | u32 glk; |
| 478 | u32 tmp; | ||
| 479 | 464 | ||
| 480 | ACPI_FUNCTION_TRACE("acpi_ec_write"); | 465 | ACPI_FUNCTION_TRACE("acpi_ec_write"); |
| 481 | 466 | ||
| 482 | if (!ec) | 467 | if (!ec) |
| 483 | return_VALUE(-EINVAL); | 468 | return_VALUE(-EINVAL); |
| 484 | retry: | 469 | |
| 485 | if (ec->common.global_lock) { | 470 | if (ec->common.global_lock) { |
| 486 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 471 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
| 487 | if (ACPI_FAILURE(status)) | 472 | if (ACPI_FAILURE(status)) |
| @@ -491,62 +476,36 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data) | |||
| 491 | WARN_ON(in_interrupt()); | 476 | WARN_ON(in_interrupt()); |
| 492 | down(&ec->burst.sem); | 477 | down(&ec->burst.sem); |
| 493 | 478 | ||
| 494 | if (acpi_ec_enter_burst_mode(ec)) | 479 | acpi_ec_enter_burst_mode(ec); |
| 495 | goto end; | ||
| 496 | 480 | ||
| 497 | status = acpi_ec_read_status(ec); | 481 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 498 | if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { | 482 | if (status) { |
| 499 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, | 483 | printk("write EC, IB not empty\n"); |
| 500 | &ec->common.command_addr); | ||
| 501 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
| 502 | if (status) | ||
| 503 | goto end; | ||
| 504 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); | ||
| 505 | if (tmp != 0x90) /* Burst ACK byte */ | ||
| 506 | goto end; | ||
| 507 | } | 484 | } |
| 508 | /*Now we are in burst mode */ | ||
| 509 | |||
| 510 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, | 485 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, |
| 511 | &ec->common.command_addr); | 486 | &ec->common.command_addr); |
| 512 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 487 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 513 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 514 | if (status) { | 488 | if (status) { |
| 515 | goto end; | 489 | printk("write EC, IB not empty\n"); |
| 516 | } | 490 | } |
| 517 | 491 | ||
| 518 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | 492 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
| 519 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 493 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 520 | if (status) { | 494 | if (status) { |
| 521 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | 495 | printk("write EC, IB not empty\n"); |
| 522 | goto end; | ||
| 523 | } | 496 | } |
| 524 | 497 | ||
| 525 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); | 498 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); |
| 526 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 527 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 528 | if (status) | ||
| 529 | goto end; | ||
| 530 | 499 | ||
| 531 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", | 500 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", |
| 532 | data, address)); | 501 | data, address)); |
| 533 | 502 | ||
| 534 | end: | ||
| 535 | acpi_ec_leave_burst_mode(ec); | 503 | acpi_ec_leave_burst_mode(ec); |
| 536 | up(&ec->burst.sem); | 504 | up(&ec->burst.sem); |
| 537 | 505 | ||
| 538 | if (ec->common.global_lock) | 506 | if (ec->common.global_lock) |
| 539 | acpi_release_global_lock(glk); | 507 | acpi_release_global_lock(glk); |
| 540 | 508 | ||
| 541 | if (atomic_read(&ec->burst.leaving_burst) == 2) { | ||
| 542 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aborted, retry ...\n")); | ||
| 543 | while (atomic_read(&ec->burst.pending_gpe)) { | ||
| 544 | msleep(1); | ||
| 545 | } | ||
| 546 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 547 | goto retry; | ||
| 548 | } | ||
| 549 | |||
| 550 | return_VALUE(status); | 509 | return_VALUE(status); |
| 551 | } | 510 | } |
| 552 | 511 | ||
| @@ -662,8 +621,12 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) | |||
| 662 | } | 621 | } |
| 663 | 622 | ||
| 664 | down(&ec->burst.sem); | 623 | down(&ec->burst.sem); |
| 665 | if (acpi_ec_enter_burst_mode(ec)) | 624 | |
| 625 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 626 | if (status) { | ||
| 627 | printk("query EC, IB not empty\n"); | ||
| 666 | goto end; | 628 | goto end; |
| 629 | } | ||
| 667 | /* | 630 | /* |
| 668 | * Query the EC to find out which _Qxx method we need to evaluate. | 631 | * Query the EC to find out which _Qxx method we need to evaluate. |
| 669 | * Note that successful completion of the query causes the ACPI_EC_SCI | 632 | * Note that successful completion of the query causes the ACPI_EC_SCI |
| @@ -673,27 +636,20 @@ static int acpi_ec_burst_query(union acpi_ec *ec, u32 * data) | |||
| 673 | &ec->common.command_addr); | 636 | &ec->common.command_addr); |
| 674 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 637 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 675 | if (status) { | 638 | if (status) { |
| 676 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | 639 | printk("query EC, OB not full\n"); |
| 677 | goto end; | 640 | goto end; |
| 678 | } | 641 | } |
| 679 | 642 | ||
| 680 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | 643 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); |
| 681 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 682 | if (!*data) | 644 | if (!*data) |
| 683 | status = -ENODATA; | 645 | status = -ENODATA; |
| 684 | 646 | ||
| 685 | end: | 647 | end: |
| 686 | acpi_ec_leave_burst_mode(ec); | ||
| 687 | up(&ec->burst.sem); | 648 | up(&ec->burst.sem); |
| 688 | 649 | ||
| 689 | if (ec->common.global_lock) | 650 | if (ec->common.global_lock) |
| 690 | acpi_release_global_lock(glk); | 651 | acpi_release_global_lock(glk); |
| 691 | 652 | ||
| 692 | if (atomic_read(&ec->burst.leaving_burst) == 2) { | ||
| 693 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aborted, retry ...\n")); | ||
| 694 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 695 | status = -ENODATA; | ||
| 696 | } | ||
| 697 | return_VALUE(status); | 653 | return_VALUE(status); |
| 698 | } | 654 | } |
| 699 | 655 | ||
| @@ -818,31 +774,21 @@ static u32 acpi_ec_gpe_burst_handler(void *data) | |||
| 818 | if (!ec) | 774 | if (!ec) |
| 819 | return ACPI_INTERRUPT_NOT_HANDLED; | 775 | return ACPI_INTERRUPT_NOT_HANDLED; |
| 820 | 776 | ||
| 821 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); | 777 | acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); |
| 822 | |||
| 823 | value = acpi_ec_read_status(ec); | 778 | value = acpi_ec_read_status(ec); |
| 824 | 779 | ||
| 825 | if ((value & ACPI_EC_FLAG_IBF) && | 780 | switch (ec->burst.expect_event) { |
| 826 | !(value & ACPI_EC_FLAG_BURST) && | 781 | case ACPI_EC_EVENT_OBF: |
| 827 | (atomic_read(&ec->burst.leaving_burst) == 0)) { | 782 | if (!(value & ACPI_EC_FLAG_OBF)) |
| 828 | /* | 783 | break; |
| 829 | * the embedded controller disables | 784 | case ACPI_EC_EVENT_IBE: |
| 830 | * burst mode for any reason other | 785 | if ((value & ACPI_EC_FLAG_IBF)) |
| 831 | * than the burst disable command | 786 | break; |
| 832 | * to process critical event. | 787 | ec->burst.expect_event = 0; |
| 833 | */ | ||
| 834 | atomic_set(&ec->burst.leaving_burst, 2); /* block current pending transaction | ||
| 835 | and retry */ | ||
| 836 | wake_up(&ec->burst.wait); | 788 | wake_up(&ec->burst.wait); |
| 837 | } else { | 789 | return ACPI_INTERRUPT_HANDLED; |
| 838 | if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && | 790 | default: |
| 839 | (value & ACPI_EC_FLAG_OBF)) || | 791 | break; |
| 840 | (ec->burst.expect_event == ACPI_EC_EVENT_IBE && | ||
| 841 | !(value & ACPI_EC_FLAG_IBF))) { | ||
| 842 | ec->burst.expect_event = 0; | ||
| 843 | wake_up(&ec->burst.wait); | ||
| 844 | return ACPI_INTERRUPT_HANDLED; | ||
| 845 | } | ||
| 846 | } | 792 | } |
| 847 | 793 | ||
| 848 | if (value & ACPI_EC_FLAG_SCI) { | 794 | if (value & ACPI_EC_FLAG_SCI) { |
| @@ -1166,6 +1112,7 @@ static int acpi_ec_burst_add(struct acpi_device *device) | |||
| 1166 | if (result) | 1112 | if (result) |
| 1167 | goto end; | 1113 | goto end; |
| 1168 | 1114 | ||
| 1115 | printk("burst-mode-ec-10-Aug\n"); | ||
| 1169 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", | 1116 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", |
| 1170 | acpi_device_name(device), acpi_device_bid(device), | 1117 | acpi_device_name(device), acpi_device_bid(device), |
| 1171 | (u32) ec->common.gpe_bit); | 1118 | (u32) ec->common.gpe_bit); |
