diff options
Diffstat (limited to 'drivers/ata/libata-acpi.c')
-rw-r--r-- | drivers/ata/libata-acpi.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index e0dd132fd490..5932ae24ddc1 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -346,8 +346,8 @@ EXPORT_SYMBOL_GPL(ata_acpi_stm); | |||
346 | * EH context. | 346 | * EH context. |
347 | * | 347 | * |
348 | * RETURNS: | 348 | * RETURNS: |
349 | * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't | 349 | * Number of taskfiles on success, 0 if _GTF doesn't exist. -EINVAL |
350 | * contain valid data. | 350 | * if _GTF is invalid. |
351 | */ | 351 | */ |
352 | static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) | 352 | static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) |
353 | { | 353 | { |
@@ -380,6 +380,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) | |||
380 | ata_dev_printk(dev, KERN_WARNING, | 380 | ata_dev_printk(dev, KERN_WARNING, |
381 | "_GTF evaluation failed (AE 0x%x)\n", | 381 | "_GTF evaluation failed (AE 0x%x)\n", |
382 | status); | 382 | status); |
383 | rc = -EINVAL; | ||
383 | } | 384 | } |
384 | goto out_free; | 385 | goto out_free; |
385 | } | 386 | } |
@@ -391,6 +392,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) | |||
391 | __FUNCTION__, | 392 | __FUNCTION__, |
392 | (unsigned long long)output.length, | 393 | (unsigned long long)output.length, |
393 | output.pointer); | 394 | output.pointer); |
395 | rc = -EINVAL; | ||
394 | goto out_free; | 396 | goto out_free; |
395 | } | 397 | } |
396 | 398 | ||
@@ -398,6 +400,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) | |||
398 | ata_dev_printk(dev, KERN_WARNING, | 400 | ata_dev_printk(dev, KERN_WARNING, |
399 | "_GTF unexpected object type 0x%x\n", | 401 | "_GTF unexpected object type 0x%x\n", |
400 | out_obj->type); | 402 | out_obj->type); |
403 | rc = -EINVAL; | ||
401 | goto out_free; | 404 | goto out_free; |
402 | } | 405 | } |
403 | 406 | ||
@@ -405,6 +408,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) | |||
405 | ata_dev_printk(dev, KERN_WARNING, | 408 | ata_dev_printk(dev, KERN_WARNING, |
406 | "unexpected _GTF length (%d)\n", | 409 | "unexpected _GTF length (%d)\n", |
407 | out_obj->buffer.length); | 410 | out_obj->buffer.length); |
411 | rc = -EINVAL; | ||
408 | goto out_free; | 412 | goto out_free; |
409 | } | 413 | } |
410 | 414 | ||
@@ -531,6 +535,7 @@ static int taskfile_load_raw(struct ata_device *dev, | |||
531 | /** | 535 | /** |
532 | * ata_acpi_exec_tfs - get then write drive taskfile settings | 536 | * ata_acpi_exec_tfs - get then write drive taskfile settings |
533 | * @dev: target ATA device | 537 | * @dev: target ATA device |
538 | * @nr_executed: out paramter for the number of executed commands | ||
534 | * | 539 | * |
535 | * Evaluate _GTF and excute returned taskfiles. | 540 | * Evaluate _GTF and excute returned taskfiles. |
536 | * | 541 | * |
@@ -538,16 +543,19 @@ static int taskfile_load_raw(struct ata_device *dev, | |||
538 | * EH context. | 543 | * EH context. |
539 | * | 544 | * |
540 | * RETURNS: | 545 | * RETURNS: |
541 | * Number of executed taskfiles on success, 0 if _GTF doesn't exist or | 546 | * Number of executed taskfiles on success, 0 if _GTF doesn't exist. |
542 | * doesn't contain valid data. -errno on other errors. | 547 | * -errno on other errors. |
543 | */ | 548 | */ |
544 | static int ata_acpi_exec_tfs(struct ata_device *dev) | 549 | static int ata_acpi_exec_tfs(struct ata_device *dev, int *nr_executed) |
545 | { | 550 | { |
546 | struct ata_acpi_gtf *gtf = NULL; | 551 | struct ata_acpi_gtf *gtf = NULL; |
547 | int gtf_count, i, rc; | 552 | int gtf_count, i, rc; |
548 | 553 | ||
549 | /* get taskfiles */ | 554 | /* get taskfiles */ |
550 | gtf_count = ata_dev_get_GTF(dev, >f); | 555 | rc = ata_dev_get_GTF(dev, >f); |
556 | if (rc < 0) | ||
557 | return rc; | ||
558 | gtf_count = rc; | ||
551 | 559 | ||
552 | /* execute them */ | 560 | /* execute them */ |
553 | for (i = 0, rc = 0; i < gtf_count; i++) { | 561 | for (i = 0, rc = 0; i < gtf_count; i++) { |
@@ -559,12 +567,12 @@ static int ata_acpi_exec_tfs(struct ata_device *dev) | |||
559 | tmp = taskfile_load_raw(dev, gtf++); | 567 | tmp = taskfile_load_raw(dev, gtf++); |
560 | if (!rc) | 568 | if (!rc) |
561 | rc = tmp; | 569 | rc = tmp; |
570 | |||
571 | (*nr_executed)++; | ||
562 | } | 572 | } |
563 | 573 | ||
564 | ata_acpi_clear_gtf(dev); | 574 | ata_acpi_clear_gtf(dev); |
565 | 575 | ||
566 | if (rc == 0) | ||
567 | return gtf_count; | ||
568 | return rc; | 576 | return rc; |
569 | } | 577 | } |
570 | 578 | ||
@@ -700,6 +708,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev) | |||
700 | struct ata_port *ap = dev->link->ap; | 708 | struct ata_port *ap = dev->link->ap; |
701 | struct ata_eh_context *ehc = &ap->link.eh_context; | 709 | struct ata_eh_context *ehc = &ap->link.eh_context; |
702 | int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA; | 710 | int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA; |
711 | int nr_executed = 0; | ||
703 | int rc; | 712 | int rc; |
704 | 713 | ||
705 | if (!dev->acpi_handle) | 714 | if (!dev->acpi_handle) |
@@ -718,14 +727,14 @@ int ata_acpi_on_devcfg(struct ata_device *dev) | |||
718 | } | 727 | } |
719 | 728 | ||
720 | /* do _GTF */ | 729 | /* do _GTF */ |
721 | rc = ata_acpi_exec_tfs(dev); | 730 | rc = ata_acpi_exec_tfs(dev, &nr_executed); |
722 | if (rc < 0) | 731 | if (rc) |
723 | goto acpi_err; | 732 | goto acpi_err; |
724 | 733 | ||
725 | dev->flags &= ~ATA_DFLAG_ACPI_PENDING; | 734 | dev->flags &= ~ATA_DFLAG_ACPI_PENDING; |
726 | 735 | ||
727 | /* refresh IDENTIFY page if any _GTF command has been executed */ | 736 | /* refresh IDENTIFY page if any _GTF command has been executed */ |
728 | if (rc > 0) { | 737 | if (nr_executed) { |
729 | rc = ata_dev_reread_id(dev, 0); | 738 | rc = ata_dev_reread_id(dev, 0); |
730 | if (rc < 0) { | 739 | if (rc < 0) { |
731 | ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY " | 740 | ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY " |
@@ -737,18 +746,26 @@ int ata_acpi_on_devcfg(struct ata_device *dev) | |||
737 | return 0; | 746 | return 0; |
738 | 747 | ||
739 | acpi_err: | 748 | acpi_err: |
740 | /* let EH retry on the first failure, disable ACPI on the second */ | 749 | /* ignore evaluation failure if we can continue safely */ |
741 | if (dev->flags & ATA_DFLAG_ACPI_FAILED) { | 750 | if (rc == -EINVAL && !nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN)) |
742 | ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the " | 751 | return 0; |
743 | "second time, disabling (errno=%d)\n", rc); | ||
744 | |||
745 | dev->acpi_handle = NULL; | ||
746 | 752 | ||
747 | /* if port is working, request IDENTIFY reload and continue */ | 753 | /* fail and let EH retry once more for unknown IO errors */ |
748 | if (!(ap->pflags & ATA_PFLAG_FROZEN)) | 754 | if (!(dev->flags & ATA_DFLAG_ACPI_FAILED)) { |
749 | rc = 1; | 755 | dev->flags |= ATA_DFLAG_ACPI_FAILED; |
756 | return rc; | ||
750 | } | 757 | } |
751 | dev->flags |= ATA_DFLAG_ACPI_FAILED; | 758 | |
759 | ata_dev_printk(dev, KERN_WARNING, | ||
760 | "ACPI: failed the second time, disabled\n"); | ||
761 | dev->acpi_handle = NULL; | ||
762 | |||
763 | /* We can safely continue if no _GTF command has been executed | ||
764 | * and port is not frozen. | ||
765 | */ | ||
766 | if (!nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN)) | ||
767 | return 0; | ||
768 | |||
752 | return rc; | 769 | return rc; |
753 | } | 770 | } |
754 | 771 | ||