diff options
Diffstat (limited to 'drivers/acpi')
| -rw-r--r-- | drivers/acpi/ec.c | 169 |
1 files changed, 59 insertions, 110 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 1ac5731d45e5..31067a0a3671 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -234,18 +234,29 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event) | |||
| 234 | ec->burst.expect_event = event; | 234 | ec->burst.expect_event = event; |
| 235 | smp_mb(); | 235 | smp_mb(); |
| 236 | 236 | ||
| 237 | result = wait_event_interruptible_timeout(ec->burst.wait, | 237 | switch (event) { |
| 238 | case ACPI_EC_EVENT_OBF: | ||
| 239 | if (acpi_ec_read_status(ec) & event) { | ||
| 240 | ec->burst.expect_event = 0; | ||
| 241 | return_VALUE(0); | ||
| 242 | } | ||
| 243 | break; | ||
| 244 | |||
| 245 | case ACPI_EC_EVENT_IBE: | ||
| 246 | if (~acpi_ec_read_status(ec) & event) { | ||
| 247 | ec->burst.expect_event = 0; | ||
| 248 | return_VALUE(0); | ||
| 249 | } | ||
| 250 | break; | ||
| 251 | } | ||
| 252 | |||
| 253 | result = wait_event_timeout(ec->burst.wait, | ||
| 238 | !ec->burst.expect_event, | 254 | !ec->burst.expect_event, |
| 239 | msecs_to_jiffies(ACPI_EC_DELAY)); | 255 | msecs_to_jiffies(ACPI_EC_DELAY)); |
| 240 | 256 | ||
| 241 | ec->burst.expect_event = 0; | 257 | ec->burst.expect_event = 0; |
| 242 | smp_mb(); | 258 | smp_mb(); |
| 243 | 259 | ||
| 244 | if (result < 0){ | ||
| 245 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR," result = %d ", result)); | ||
| 246 | return_VALUE(result); | ||
| 247 | } | ||
| 248 | |||
| 249 | /* | 260 | /* |
| 250 | * Verify that the event in question has actually happened by | 261 | * Verify that the event in question has actually happened by |
| 251 | * querying EC status. Do the check even if operation timed-out | 262 | * querying EC status. Do the check even if operation timed-out |
| @@ -280,14 +291,14 @@ acpi_ec_enter_burst_mode ( | |||
| 280 | status = acpi_ec_read_status(ec); | 291 | status = acpi_ec_read_status(ec); |
| 281 | if (status != -EINVAL && | 292 | if (status != -EINVAL && |
| 282 | !(status & ACPI_EC_FLAG_BURST)){ | 293 | !(status & ACPI_EC_FLAG_BURST)){ |
| 294 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 295 | if(status) | ||
| 296 | goto end; | ||
| 283 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); | 297 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); |
| 284 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 298 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 285 | if (status){ | 299 | if (status) |
| 286 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 287 | return_VALUE(-EINVAL); | 300 | return_VALUE(-EINVAL); |
| 288 | } | ||
| 289 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); | 301 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); |
| 290 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 291 | if(tmp != 0x90 ) {/* Burst ACK byte*/ | 302 | if(tmp != 0x90 ) {/* Burst ACK byte*/ |
| 292 | return_VALUE(-EINVAL); | 303 | return_VALUE(-EINVAL); |
| 293 | } | 304 | } |
| @@ -295,31 +306,19 @@ acpi_ec_enter_burst_mode ( | |||
| 295 | 306 | ||
| 296 | atomic_set(&ec->burst.leaving_burst , 0); | 307 | atomic_set(&ec->burst.leaving_burst , 0); |
| 297 | return_VALUE(0); | 308 | return_VALUE(0); |
| 309 | end: | ||
| 310 | printk("Error in acpi_ec_wait\n"); | ||
| 311 | return_VALUE(-1); | ||
| 298 | } | 312 | } |
| 299 | 313 | ||
| 300 | static int | 314 | static int |
| 301 | acpi_ec_leave_burst_mode ( | 315 | acpi_ec_leave_burst_mode ( |
| 302 | union acpi_ec *ec) | 316 | union acpi_ec *ec) |
| 303 | { | 317 | { |
| 304 | int status =0; | ||
| 305 | 318 | ||
| 306 | ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); | 319 | ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode"); |
| 307 | 320 | ||
| 308 | atomic_set(&ec->burst.leaving_burst , 1); | 321 | atomic_set(&ec->burst.leaving_burst, 1); |
| 309 | status = acpi_ec_read_status(ec); | ||
| 310 | if (status != -EINVAL && | ||
| 311 | (status & ACPI_EC_FLAG_BURST)){ | ||
| 312 | acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); | ||
| 313 | status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); | ||
| 314 | if (status){ | ||
| 315 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 316 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"------->wait fail\n")); | ||
| 317 | return_VALUE(-EINVAL); | ||
| 318 | } | ||
| 319 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 320 | status = acpi_ec_read_status(ec); | ||
| 321 | } | ||
| 322 | |||
| 323 | return_VALUE(0); | 322 | return_VALUE(0); |
| 324 | } | 323 | } |
| 325 | 324 | ||
| @@ -461,7 +460,6 @@ acpi_ec_burst_read ( | |||
| 461 | if (!ec || !data) | 460 | if (!ec || !data) |
| 462 | return_VALUE(-EINVAL); | 461 | return_VALUE(-EINVAL); |
| 463 | 462 | ||
| 464 | retry: | ||
| 465 | *data = 0; | 463 | *data = 0; |
| 466 | 464 | ||
| 467 | if (ec->common.global_lock) { | 465 | if (ec->common.global_lock) { |
| @@ -473,26 +471,25 @@ retry: | |||
| 473 | WARN_ON(in_interrupt()); | 471 | WARN_ON(in_interrupt()); |
| 474 | down(&ec->burst.sem); | 472 | down(&ec->burst.sem); |
| 475 | 473 | ||
| 476 | if(acpi_ec_enter_burst_mode(ec)) | 474 | acpi_ec_enter_burst_mode(ec); |
| 475 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 476 | if (status) { | ||
| 477 | printk("read EC, IB not empty\n"); | ||
| 477 | goto end; | 478 | goto end; |
| 478 | 479 | } | |
| 479 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); | 480 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->common.command_addr); |
| 480 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 481 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 481 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 482 | if (status) { | 482 | if (status) { |
| 483 | goto end; | 483 | printk("read EC, IB not empty\n"); |
| 484 | } | 484 | } |
| 485 | 485 | ||
| 486 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | 486 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
| 487 | status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 487 | status= acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 488 | if (status){ | 488 | if (status){ |
| 489 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | 489 | printk("read EC, OB not full\n"); |
| 490 | goto end; | 490 | goto end; |
| 491 | } | 491 | } |
| 492 | |||
| 493 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | 492 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); |
| 494 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 495 | |||
| 496 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", | 493 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", |
| 497 | *data, address)); | 494 | *data, address)); |
| 498 | 495 | ||
| @@ -503,15 +500,6 @@ end: | |||
| 503 | if (ec->common.global_lock) | 500 | if (ec->common.global_lock) |
| 504 | acpi_release_global_lock(glk); | 501 | acpi_release_global_lock(glk); |
| 505 | 502 | ||
| 506 | if(atomic_read(&ec->burst.leaving_burst) == 2){ | ||
| 507 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | ||
| 508 | while(atomic_read(&ec->burst.pending_gpe)){ | ||
| 509 | msleep(1); | ||
| 510 | } | ||
| 511 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 512 | goto retry; | ||
| 513 | } | ||
| 514 | |||
| 515 | return_VALUE(status); | 503 | return_VALUE(status); |
| 516 | } | 504 | } |
| 517 | 505 | ||
| @@ -524,13 +512,12 @@ acpi_ec_burst_write ( | |||
| 524 | { | 512 | { |
| 525 | int status = 0; | 513 | int status = 0; |
| 526 | u32 glk; | 514 | u32 glk; |
| 527 | u32 tmp; | ||
| 528 | 515 | ||
| 529 | ACPI_FUNCTION_TRACE("acpi_ec_write"); | 516 | ACPI_FUNCTION_TRACE("acpi_ec_write"); |
| 530 | 517 | ||
| 531 | if (!ec) | 518 | if (!ec) |
| 532 | return_VALUE(-EINVAL); | 519 | return_VALUE(-EINVAL); |
| 533 | retry: | 520 | |
| 534 | if (ec->common.global_lock) { | 521 | if (ec->common.global_lock) { |
| 535 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); | 522 | status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); |
| 536 | if (ACPI_FAILURE(status)) | 523 | if (ACPI_FAILURE(status)) |
| @@ -540,61 +527,35 @@ retry: | |||
| 540 | WARN_ON(in_interrupt()); | 527 | WARN_ON(in_interrupt()); |
| 541 | down(&ec->burst.sem); | 528 | down(&ec->burst.sem); |
| 542 | 529 | ||
| 543 | if(acpi_ec_enter_burst_mode(ec)) | 530 | acpi_ec_enter_burst_mode(ec); |
| 544 | goto end; | ||
| 545 | 531 | ||
| 546 | status = acpi_ec_read_status(ec); | 532 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 547 | if (status != -EINVAL && | 533 | if ( status) { |
| 548 | !(status & ACPI_EC_FLAG_BURST)){ | 534 | printk("write EC, IB not empty\n"); |
| 549 | acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, &ec->common.command_addr); | ||
| 550 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | ||
| 551 | if (status) | ||
| 552 | goto end; | ||
| 553 | acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); | ||
| 554 | if(tmp != 0x90 ) /* Burst ACK byte*/ | ||
| 555 | goto end; | ||
| 556 | } | 535 | } |
| 557 | /*Now we are in burst mode*/ | ||
| 558 | |||
| 559 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); | 536 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->common.command_addr); |
| 560 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 537 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 561 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | 538 | if (status) { |
| 562 | if (status){ | 539 | printk ("write EC, IB not empty\n"); |
| 563 | goto end; | ||
| 564 | } | 540 | } |
| 565 | 541 | ||
| 566 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); | 542 | acpi_hw_low_level_write(8, address, &ec->common.data_addr); |
| 567 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | 543 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); |
| 568 | if (status){ | 544 | if (status){ |
| 569 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | 545 | printk("write EC, IB not empty\n"); |
| 570 | goto end; | ||
| 571 | } | 546 | } |
| 572 | 547 | ||
| 573 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); | 548 | acpi_hw_low_level_write(8, data, &ec->common.data_addr); |
| 574 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 575 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 576 | if (status) | ||
| 577 | goto end; | ||
| 578 | 549 | ||
| 579 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", | 550 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", |
| 580 | data, address)); | 551 | data, address)); |
| 581 | 552 | ||
| 582 | end: | ||
| 583 | acpi_ec_leave_burst_mode(ec); | 553 | acpi_ec_leave_burst_mode(ec); |
| 584 | up(&ec->burst.sem); | 554 | up(&ec->burst.sem); |
| 585 | 555 | ||
| 586 | if (ec->common.global_lock) | 556 | if (ec->common.global_lock) |
| 587 | acpi_release_global_lock(glk); | 557 | acpi_release_global_lock(glk); |
| 588 | 558 | ||
| 589 | if(atomic_read(&ec->burst.leaving_burst) == 2){ | ||
| 590 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | ||
| 591 | while(atomic_read(&ec->burst.pending_gpe)){ | ||
| 592 | msleep(1); | ||
| 593 | } | ||
| 594 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 595 | goto retry; | ||
| 596 | } | ||
| 597 | |||
| 598 | return_VALUE(status); | 559 | return_VALUE(status); |
| 599 | } | 560 | } |
| 600 | 561 | ||
| @@ -719,8 +680,12 @@ acpi_ec_burst_query ( | |||
| 719 | } | 680 | } |
| 720 | 681 | ||
| 721 | down(&ec->burst.sem); | 682 | down(&ec->burst.sem); |
| 722 | if(acpi_ec_enter_burst_mode(ec)) | 683 | |
| 684 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); | ||
| 685 | if (status) { | ||
| 686 | printk("query EC, IB not empty\n"); | ||
| 723 | goto end; | 687 | goto end; |
| 688 | } | ||
| 724 | /* | 689 | /* |
| 725 | * Query the EC to find out which _Qxx method we need to evaluate. | 690 | * Query the EC to find out which _Qxx method we need to evaluate. |
| 726 | * Note that successful completion of the query causes the ACPI_EC_SCI | 691 | * Note that successful completion of the query causes the ACPI_EC_SCI |
| @@ -729,27 +694,20 @@ acpi_ec_burst_query ( | |||
| 729 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); | 694 | acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->common.command_addr); |
| 730 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); | 695 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); |
| 731 | if (status){ | 696 | if (status){ |
| 732 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | 697 | printk("query EC, OB not full\n"); |
| 733 | goto end; | 698 | goto end; |
| 734 | } | 699 | } |
| 735 | 700 | ||
| 736 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); | 701 | acpi_hw_low_level_read(8, data, &ec->common.data_addr); |
| 737 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 738 | if (!*data) | 702 | if (!*data) |
| 739 | status = -ENODATA; | 703 | status = -ENODATA; |
| 740 | 704 | ||
| 741 | end: | 705 | end: |
| 742 | acpi_ec_leave_burst_mode(ec); | ||
| 743 | up(&ec->burst.sem); | 706 | up(&ec->burst.sem); |
| 744 | 707 | ||
| 745 | if (ec->common.global_lock) | 708 | if (ec->common.global_lock) |
| 746 | acpi_release_global_lock(glk); | 709 | acpi_release_global_lock(glk); |
| 747 | 710 | ||
| 748 | if(atomic_read(&ec->burst.leaving_burst) == 2){ | ||
| 749 | ACPI_DEBUG_PRINT((ACPI_DB_INFO,"aborted, retry ...\n")); | ||
| 750 | acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); | ||
| 751 | status = -ENODATA; | ||
| 752 | } | ||
| 753 | return_VALUE(status); | 711 | return_VALUE(status); |
| 754 | } | 712 | } |
| 755 | 713 | ||
| @@ -885,31 +843,21 @@ acpi_ec_gpe_burst_handler ( | |||
| 885 | if (!ec) | 843 | if (!ec) |
| 886 | return ACPI_INTERRUPT_NOT_HANDLED; | 844 | return ACPI_INTERRUPT_NOT_HANDLED; |
| 887 | 845 | ||
| 888 | acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); | 846 | acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); |
| 889 | |||
| 890 | value = acpi_ec_read_status(ec); | 847 | value = acpi_ec_read_status(ec); |
| 891 | 848 | ||
| 892 | if((value & ACPI_EC_FLAG_IBF) && | 849 | switch ( ec->burst.expect_event) { |
| 893 | !(value & ACPI_EC_FLAG_BURST) && | 850 | case ACPI_EC_EVENT_OBF: |
| 894 | (atomic_read(&ec->burst.leaving_burst) == 0)) { | 851 | if (!(value & ACPI_EC_FLAG_OBF)) |
| 895 | /* | 852 | break; |
| 896 | * the embedded controller disables | 853 | case ACPI_EC_EVENT_IBE: |
| 897 | * burst mode for any reason other | 854 | if ((value & ACPI_EC_FLAG_IBF)) |
| 898 | * than the burst disable command | 855 | break; |
| 899 | * to process critical event. | 856 | ec->burst.expect_event = 0; |
| 900 | */ | ||
| 901 | atomic_set(&ec->burst.leaving_burst , 2); /* block current pending transaction | ||
| 902 | and retry */ | ||
| 903 | wake_up(&ec->burst.wait); | 857 | wake_up(&ec->burst.wait); |
| 904 | }else { | 858 | return ACPI_INTERRUPT_HANDLED; |
| 905 | if ((ec->burst.expect_event == ACPI_EC_EVENT_OBF && | 859 | default: |
| 906 | (value & ACPI_EC_FLAG_OBF)) || | 860 | break; |
| 907 | (ec->burst.expect_event == ACPI_EC_EVENT_IBE && | ||
| 908 | !(value & ACPI_EC_FLAG_IBF))) { | ||
| 909 | ec->burst.expect_event = 0; | ||
| 910 | wake_up(&ec->burst.wait); | ||
| 911 | return ACPI_INTERRUPT_HANDLED; | ||
| 912 | } | ||
| 913 | } | 861 | } |
| 914 | 862 | ||
| 915 | if (value & ACPI_EC_FLAG_SCI){ | 863 | if (value & ACPI_EC_FLAG_SCI){ |
| @@ -1242,6 +1190,7 @@ acpi_ec_burst_add ( | |||
| 1242 | if (result) | 1190 | if (result) |
| 1243 | goto end; | 1191 | goto end; |
| 1244 | 1192 | ||
| 1193 | printk("burst-mode-ec-10-Aug\n"); | ||
| 1245 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", | 1194 | printk(KERN_INFO PREFIX "%s [%s] (gpe %d)\n", |
| 1246 | acpi_device_name(device), acpi_device_bid(device), | 1195 | acpi_device_name(device), acpi_device_bid(device), |
| 1247 | (u32) ec->common.gpe_bit); | 1196 | (u32) ec->common.gpe_bit); |
