diff options
author | Luming Yu <luming.yu@intel.com> | 2005-08-10 01:40:00 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-08-11 17:30:51 -0400 |
commit | 716e084edb0230910b174000dc3490f9e91652e3 (patch) | |
tree | a3f5c00b87efa64a26127c9bc1c73d3a51d703cd /drivers | |
parent | cbfc1bae55bbd053308ef0fa6b6448cd1ddf3e67 (diff) |
[ACPI] Fix "ec_burst=1" mode latency issue
http://bugzilla.kernel.org/show_bug.cgi?id=3851
Signed-off-by: Luming Yu <luming.yu@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-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); |