aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorKristen Carlson Accardi <kristen.c.accardi@intel.com>2006-09-28 14:29:12 -0400
committerJeff Garzik <jeff@garzik.org>2007-02-16 13:32:41 -0500
commit7ea1fbc2a2449bc034a3d255f36f2e5486d52fe8 (patch)
treeefa06ba55094924f27e7598b393a46b8c2753ec0 /drivers/ata
parent11ef697b37e3c85ce1ac21f7711babf1f5b12784 (diff)
[PATCH] libata: ACPI _SDD support
_SDD (Set Device Data) is an ACPI method that is used to tell the firmware what the identify data is of the device that is attached to the port. It is an optional method, and it's ok for it to be missing. Because of this, we always return success from the routine that calls this method, even if the execution fails. Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Jeff Garzik <jeff@garzik.org> (cherry picked from 39aa79e0a1f5f2e28aa341f035940746a98b45b1 commit)
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-acpi.c96
-rw-r--r--drivers/ata/libata-core.c8
-rw-r--r--drivers/ata/libata.h5
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 */
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
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
93extern int ata_acpi_exec_tfs(struct ata_port *ap); 93extern int ata_acpi_exec_tfs(struct ata_port *ap);
94extern int ata_acpi_push_id(struct ata_port *ap, unsigned int ix);
94#else 95#else
95static inline int ata_acpi_exec_tfs(struct ata_port *ap) 96static inline int ata_acpi_exec_tfs(struct ata_port *ap)
96{ 97{
97 return 0; 98 return 0;
98} 99}
100static 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 */