aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-acpi.c')
-rw-r--r--drivers/ata/libata-acpi.c96
1 files changed, 96 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 */
614int 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 */
694out:
695 return 0;
696}
697
698