diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/libata-acpi.c | 96 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 8 | ||||
-rw-r--r-- | drivers/ata/libata.h | 5 |
3 files changed, 109 insertions, 0 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 7b740fe1721b..f2fd0dda70f2 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -600,3 +600,99 @@ int ata_acpi_exec_tfs(struct ata_port *ap) | |||
600 | return ret; | 600 | return ret; |
601 | } | 601 | } |
602 | 602 | ||
603 | /** | ||
604 | * ata_acpi_push_id - send Identify data to drive | ||
605 | * @ap: the ata_port for the drive | ||
606 | * @ix: drive index | ||
607 | * | ||
608 | * _SDD ACPI object: for SATA mode only | ||
609 | * Must be after Identify (Packet) Device -- uses its data | ||
610 | * ATM this function never returns a failure. It is an optional | ||
611 | * method and if it fails for whatever reason, we should still | ||
612 | * just keep going. | ||
613 | */ | ||
614 | int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) | ||
615 | { | ||
616 | acpi_handle handle; | ||
617 | acpi_integer pcidevfn; | ||
618 | int err; | ||
619 | struct device *dev = ap->host->dev; | ||
620 | struct ata_device *atadev = &ap->device[ix]; | ||
621 | u32 dev_adr; | ||
622 | acpi_status status; | ||
623 | struct acpi_object_list input; | ||
624 | union acpi_object in_params[1]; | ||
625 | |||
626 | if (noacpi) | ||
627 | return 0; | ||
628 | |||
629 | if (ata_msg_probe(ap)) | ||
630 | ata_dev_printk(atadev, KERN_DEBUG, | ||
631 | "%s: ap->id: %d, ix = %d, port#: %d\n", | ||
632 | __FUNCTION__, ap->id, ix, ap->port_no); | ||
633 | |||
634 | /* Don't continue if not a SATA device. */ | ||
635 | if (!(ap->cbl == ATA_CBL_SATA)) { | ||
636 | if (ata_msg_probe(ap)) | ||
637 | ata_dev_printk(atadev, KERN_DEBUG, | ||
638 | "%s: Not a SATA device\n", __FUNCTION__); | ||
639 | goto out; | ||
640 | } | ||
641 | |||
642 | /* Don't continue if device has no _ADR method. | ||
643 | * _SDD is intended for known motherboard devices. */ | ||
644 | err = sata_get_dev_handle(dev, &handle, &pcidevfn); | ||
645 | if (err < 0) { | ||
646 | if (ata_msg_probe(ap)) | ||
647 | ata_dev_printk(atadev, KERN_DEBUG, | ||
648 | "%s: sata_get_dev_handle failed (%d\n", | ||
649 | __FUNCTION__, err); | ||
650 | goto out; | ||
651 | } | ||
652 | |||
653 | /* Get this drive's _ADR info, if not already known */ | ||
654 | if (!atadev->obj_handle) { | ||
655 | dev_adr = SATA_ADR_RSVD; | ||
656 | err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev, | ||
657 | &dev_adr); | ||
658 | if (err < 0 || dev_adr == SATA_ADR_RSVD || | ||
659 | !atadev->obj_handle) { | ||
660 | if (ata_msg_probe(ap)) | ||
661 | ata_dev_printk(atadev, KERN_DEBUG, | ||
662 | "%s: get_sata_adr failed: " | ||
663 | "err=%d, dev_adr=%u, obj_handle=0x%p\n", | ||
664 | __FUNCTION__, err, dev_adr, | ||
665 | atadev->obj_handle); | ||
666 | goto out; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | /* Give the drive Identify data to the drive via the _SDD method */ | ||
671 | /* _SDD: set up input parameters */ | ||
672 | input.count = 1; | ||
673 | input.pointer = in_params; | ||
674 | in_params[0].type = ACPI_TYPE_BUFFER; | ||
675 | in_params[0].buffer.length = sizeof(atadev->id[0] * ATA_ID_WORDS); | ||
676 | in_params[0].buffer.pointer = (u8 *)atadev->id; | ||
677 | /* Output buffer: _SDD has no output */ | ||
678 | |||
679 | /* It's OK for _SDD to be missing too. */ | ||
680 | swap_buf_le16(atadev->id, ATA_ID_WORDS); | ||
681 | status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL); | ||
682 | swap_buf_le16(atadev->id, ATA_ID_WORDS); | ||
683 | |||
684 | err = ACPI_FAILURE(status) ? -EIO : 0; | ||
685 | if (err < 0) { | ||
686 | if (ata_msg_probe(ap)) | ||
687 | ata_dev_printk(atadev, KERN_DEBUG, | ||
688 | "ata%u(%u): %s _SDD error: status = 0x%x\n", | ||
689 | ap->id, ap->device->devno, | ||
690 | __FUNCTION__, status); | ||
691 | } | ||
692 | |||
693 | /* always return success */ | ||
694 | out: | ||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | |||
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 785bf50488e9..90081e5ea80e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -1737,6 +1737,14 @@ int ata_dev_configure(struct ata_device *dev) | |||
1737 | if (ap->ops->dev_config) | 1737 | if (ap->ops->dev_config) |
1738 | ap->ops->dev_config(ap, dev); | 1738 | ap->ops->dev_config(ap, dev); |
1739 | 1739 | ||
1740 | /* set _SDD */ | ||
1741 | rc = ata_acpi_push_id(ap, dev->devno); | ||
1742 | if (rc) { | ||
1743 | ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n", | ||
1744 | rc); | ||
1745 | goto err_out_nosup; | ||
1746 | } | ||
1747 | |||
1740 | if (ata_msg_probe(ap)) | 1748 | if (ata_msg_probe(ap)) |
1741 | ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", | 1749 | ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n", |
1742 | __FUNCTION__, ata_chk_status(ap)); | 1750 | __FUNCTION__, ata_chk_status(ap)); |
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index ea02903e8503..0ad7781d72a3 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -91,11 +91,16 @@ extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev, | |||
91 | /* libata-acpi.c */ | 91 | /* libata-acpi.c */ |
92 | #ifdef CONFIG_SATA_ACPI | 92 | #ifdef CONFIG_SATA_ACPI |
93 | extern int ata_acpi_exec_tfs(struct ata_port *ap); | 93 | extern int ata_acpi_exec_tfs(struct ata_port *ap); |
94 | extern int ata_acpi_push_id(struct ata_port *ap, unsigned int ix); | ||
94 | #else | 95 | #else |
95 | static inline int ata_acpi_exec_tfs(struct ata_port *ap) | 96 | static inline int ata_acpi_exec_tfs(struct ata_port *ap) |
96 | { | 97 | { |
97 | return 0; | 98 | return 0; |
98 | } | 99 | } |
100 | static inline int ata_acpi_push_id(struct ata_port *ap, unsigned int ix) | ||
101 | { | ||
102 | return 0; | ||
103 | } | ||
99 | #endif | 104 | #endif |
100 | 105 | ||
101 | /* libata-scsi.c */ | 106 | /* libata-scsi.c */ |