aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2012-06-25 04:13:03 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-06-29 11:38:10 -0400
commit6b66d95895c149cbc04d4fac5a2f5477c543a8ae (patch)
treefbf0349878339b7104338af89be86d0f78bfee1a /drivers/ata
parentde50ada55b6b83b54b817911ec42dc590e1c1738 (diff)
libata: bind the Linux device tree to the ACPI device tree
Associate the ACPI device tree and libata devices. This patch uses the generic ACPI glue framework to do so. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Holger Macht <holger@homac.de> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-acpi.c137
-rw-r--r--drivers/ata/libata-core.c5
-rw-r--r--drivers/ata/libata.h6
3 files changed, 146 insertions, 2 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index bb7c5f1085cc..b3025a7d71e3 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -47,6 +47,39 @@ static void ata_acpi_clear_gtf(struct ata_device *dev)
47 dev->gtf_cache = NULL; 47 dev->gtf_cache = NULL;
48} 48}
49 49
50static acpi_handle ap_acpi_handle(struct ata_port *ap)
51{
52 if (ap->flags & ATA_FLAG_ACPI_SATA)
53 return NULL;
54
55 /*
56 * If acpi bind operation has already happened, we can get the handle
57 * for the port by checking the corresponding scsi_host device's
58 * firmware node, otherwise we will need to find out the handle from
59 * its parent's acpi node.
60 */
61 if (ap->scsi_host)
62 return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
63 else
64 return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev),
65 ap->port_no);
66}
67
68static acpi_handle dev_acpi_handle(struct ata_device *dev)
69{
70 acpi_integer adr;
71 struct ata_port *ap = dev->link->ap;
72
73 if (ap->flags & ATA_FLAG_ACPI_SATA) {
74 if (!sata_pmp_attached(ap))
75 adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
76 else
77 adr = SATA_ADR(ap->port_no, dev->link->pmp);
78 return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), adr);
79 } else
80 return acpi_get_child(ap_acpi_handle(ap), dev->devno);
81}
82
50/** 83/**
51 * ata_acpi_associate_sata_port - associate SATA port with ACPI objects 84 * ata_acpi_associate_sata_port - associate SATA port with ACPI objects
52 * @ap: target SATA port 85 * @ap: target SATA port
@@ -1018,3 +1051,107 @@ void ata_acpi_on_disable(struct ata_device *dev)
1018{ 1051{
1019 ata_acpi_clear_gtf(dev); 1052 ata_acpi_clear_gtf(dev);
1020} 1053}
1054
1055static int compat_pci_ata(struct ata_port *ap)
1056{
1057 struct device *dev = ap->tdev.parent;
1058 struct pci_dev *pdev;
1059
1060 if (!is_pci_dev(dev))
1061 return 0;
1062
1063 pdev = to_pci_dev(dev);
1064
1065 if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
1066 (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
1067 return 0;
1068
1069 return 1;
1070}
1071
1072static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle)
1073{
1074 if (ap->flags & ATA_FLAG_ACPI_SATA)
1075 return -ENODEV;
1076
1077 *handle = acpi_get_child(DEVICE_ACPI_HANDLE(ap->tdev.parent),
1078 ap->port_no);
1079
1080 if (!*handle)
1081 return -ENODEV;
1082
1083 return 0;
1084}
1085
1086static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
1087 acpi_handle *handle)
1088{
1089 struct ata_device *ata_dev;
1090
1091 if (ap->flags & ATA_FLAG_ACPI_SATA)
1092 ata_dev = &ap->link.device[sdev->channel];
1093 else
1094 ata_dev = &ap->link.device[sdev->id];
1095
1096 *handle = dev_acpi_handle(ata_dev);
1097
1098 if (!*handle)
1099 return -ENODEV;
1100
1101 return 0;
1102}
1103
1104static int is_ata_port(const struct device *dev)
1105{
1106 return dev->type == &ata_port_type;
1107}
1108
1109static struct ata_port *dev_to_ata_port(struct device *dev)
1110{
1111 while (!is_ata_port(dev)) {
1112 if (!dev->parent)
1113 return NULL;
1114 dev = dev->parent;
1115 }
1116 return to_ata_port(dev);
1117}
1118
1119static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
1120{
1121 struct ata_port *ap = dev_to_ata_port(dev);
1122
1123 if (!ap)
1124 return -ENODEV;
1125
1126 if (!compat_pci_ata(ap))
1127 return -ENODEV;
1128
1129 if (scsi_is_host_device(dev))
1130 return ata_acpi_bind_host(ap, handle);
1131 else if (scsi_is_sdev_device(dev)) {
1132 struct scsi_device *sdev = to_scsi_device(dev);
1133
1134 return ata_acpi_bind_device(ap, sdev, handle);
1135 } else
1136 return -ENODEV;
1137}
1138
1139static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle)
1140{
1141 return -ENODEV;
1142}
1143
1144static struct acpi_bus_type ata_acpi_bus = {
1145 .find_bridge = ata_acpi_find_dummy,
1146 .find_device = ata_acpi_find_device,
1147};
1148
1149int ata_acpi_register(void)
1150{
1151 return scsi_register_acpi_bus_type(&ata_acpi_bus);
1152}
1153
1154void ata_acpi_unregister(void)
1155{
1156 scsi_unregister_acpi_bus_type(&ata_acpi_bus);
1157}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index cece3a4d11ea..bd33b4a7ac13 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5288,8 +5288,6 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
5288 return rc; 5288 return rc;
5289} 5289}
5290 5290
5291#define to_ata_port(d) container_of(d, struct ata_port, tdev)
5292
5293static int ata_port_suspend_common(struct device *dev, pm_message_t mesg) 5291static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
5294{ 5292{
5295 struct ata_port *ap = to_ata_port(dev); 5293 struct ata_port *ap = to_ata_port(dev);
@@ -6513,6 +6511,8 @@ static int __init ata_init(void)
6513 6511
6514 ata_parse_force_param(); 6512 ata_parse_force_param();
6515 6513
6514 ata_acpi_register();
6515
6516 rc = ata_sff_init(); 6516 rc = ata_sff_init();
6517 if (rc) { 6517 if (rc) {
6518 kfree(ata_force_tbl); 6518 kfree(ata_force_tbl);
@@ -6539,6 +6539,7 @@ static void __exit ata_exit(void)
6539 ata_release_transport(ata_scsi_transport_template); 6539 ata_release_transport(ata_scsi_transport_template);
6540 libata_transport_exit(); 6540 libata_transport_exit();
6541 ata_sff_exit(); 6541 ata_sff_exit();
6542 ata_acpi_unregister();
6542 kfree(ata_force_tbl); 6543 kfree(ata_force_tbl);
6543} 6544}
6544 6545
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 9d0fd0b71852..7f48b602b01b 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -107,6 +107,8 @@ extern const char *sata_spd_string(unsigned int spd);
107extern int ata_port_probe(struct ata_port *ap); 107extern int ata_port_probe(struct ata_port *ap);
108extern void __ata_port_probe(struct ata_port *ap); 108extern void __ata_port_probe(struct ata_port *ap);
109 109
110#define to_ata_port(d) container_of(d, struct ata_port, tdev)
111
110/* libata-acpi.c */ 112/* libata-acpi.c */
111#ifdef CONFIG_ATA_ACPI 113#ifdef CONFIG_ATA_ACPI
112extern unsigned int ata_acpi_gtf_filter; 114extern unsigned int ata_acpi_gtf_filter;
@@ -119,6 +121,8 @@ extern void ata_acpi_on_resume(struct ata_port *ap);
119extern int ata_acpi_on_devcfg(struct ata_device *dev); 121extern int ata_acpi_on_devcfg(struct ata_device *dev);
120extern void ata_acpi_on_disable(struct ata_device *dev); 122extern void ata_acpi_on_disable(struct ata_device *dev);
121extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state); 123extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
124extern int ata_acpi_register(void);
125extern void ata_acpi_unregister(void);
122#else 126#else
123static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { } 127static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
124static inline void ata_acpi_associate(struct ata_host *host) { } 128static inline void ata_acpi_associate(struct ata_host *host) { }
@@ -129,6 +133,8 @@ static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
129static inline void ata_acpi_on_disable(struct ata_device *dev) { } 133static inline void ata_acpi_on_disable(struct ata_device *dev) { }
130static inline void ata_acpi_set_state(struct ata_port *ap, 134static inline void ata_acpi_set_state(struct ata_port *ap,
131 pm_message_t state) { } 135 pm_message_t state) { }
136static inline int ata_acpi_register(void) { return 0; }
137static void ata_acpi_unregister(void) { }
132#endif 138#endif
133 139
134/* libata-scsi.c */ 140/* libata-scsi.c */