diff options
author | Matthew Garrett <mjg@redhat.com> | 2012-06-25 04:13:03 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2012-06-29 11:38:10 -0400 |
commit | 6b66d95895c149cbc04d4fac5a2f5477c543a8ae (patch) | |
tree | fbf0349878339b7104338af89be86d0f78bfee1a /drivers/ata | |
parent | de50ada55b6b83b54b817911ec42dc590e1c1738 (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.c | 137 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 5 | ||||
-rw-r--r-- | drivers/ata/libata.h | 6 |
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 | ||
50 | static 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 | |||
68 | static 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 | |||
1055 | static 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 | |||
1072 | static 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 | |||
1086 | static 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 | |||
1104 | static int is_ata_port(const struct device *dev) | ||
1105 | { | ||
1106 | return dev->type == &ata_port_type; | ||
1107 | } | ||
1108 | |||
1109 | static 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 | |||
1119 | static 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 | |||
1139 | static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle) | ||
1140 | { | ||
1141 | return -ENODEV; | ||
1142 | } | ||
1143 | |||
1144 | static struct acpi_bus_type ata_acpi_bus = { | ||
1145 | .find_bridge = ata_acpi_find_dummy, | ||
1146 | .find_device = ata_acpi_find_device, | ||
1147 | }; | ||
1148 | |||
1149 | int ata_acpi_register(void) | ||
1150 | { | ||
1151 | return scsi_register_acpi_bus_type(&ata_acpi_bus); | ||
1152 | } | ||
1153 | |||
1154 | void 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 | |||
5293 | static int ata_port_suspend_common(struct device *dev, pm_message_t mesg) | 5291 | static 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); | |||
107 | extern int ata_port_probe(struct ata_port *ap); | 107 | extern int ata_port_probe(struct ata_port *ap); |
108 | extern void __ata_port_probe(struct ata_port *ap); | 108 | extern 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 |
112 | extern unsigned int ata_acpi_gtf_filter; | 114 | extern unsigned int ata_acpi_gtf_filter; |
@@ -119,6 +121,8 @@ extern void ata_acpi_on_resume(struct ata_port *ap); | |||
119 | extern int ata_acpi_on_devcfg(struct ata_device *dev); | 121 | extern int ata_acpi_on_devcfg(struct ata_device *dev); |
120 | extern void ata_acpi_on_disable(struct ata_device *dev); | 122 | extern void ata_acpi_on_disable(struct ata_device *dev); |
121 | extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state); | 123 | extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state); |
124 | extern int ata_acpi_register(void); | ||
125 | extern void ata_acpi_unregister(void); | ||
122 | #else | 126 | #else |
123 | static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { } | 127 | static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { } |
124 | static inline void ata_acpi_associate(struct ata_host *host) { } | 128 | static 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; } | |||
129 | static inline void ata_acpi_on_disable(struct ata_device *dev) { } | 133 | static inline void ata_acpi_on_disable(struct ata_device *dev) { } |
130 | static inline void ata_acpi_set_state(struct ata_port *ap, | 134 | static inline void ata_acpi_set_state(struct ata_port *ap, |
131 | pm_message_t state) { } | 135 | pm_message_t state) { } |
136 | static inline int ata_acpi_register(void) { return 0; } | ||
137 | static void ata_acpi_unregister(void) { } | ||
132 | #endif | 138 | #endif |
133 | 139 | ||
134 | /* libata-scsi.c */ | 140 | /* libata-scsi.c */ |