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); |