diff options
Diffstat (limited to 'drivers/ata/libata-acpi.c')
-rw-r--r-- | drivers/ata/libata-acpi.c | 408 |
1 files changed, 292 insertions, 116 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index bb7c5f1085cc..902b5a457170 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/libata.h> | 16 | #include <linux/libata.h> |
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/pm_runtime.h> | ||
19 | #include <scsi/scsi_device.h> | 20 | #include <scsi/scsi_device.h> |
20 | #include "libata.h" | 21 | #include "libata.h" |
21 | 22 | ||
@@ -48,62 +49,53 @@ static void ata_acpi_clear_gtf(struct ata_device *dev) | |||
48 | } | 49 | } |
49 | 50 | ||
50 | /** | 51 | /** |
51 | * ata_acpi_associate_sata_port - associate SATA port with ACPI objects | 52 | * ata_ap_acpi_handle - provide the acpi_handle for an ata_port |
52 | * @ap: target SATA port | 53 | * @ap: the acpi_handle returned will correspond to this port |
53 | * | 54 | * |
54 | * Look up ACPI objects associated with @ap and initialize acpi_handle | 55 | * Returns the acpi_handle for the ACPI namespace object corresponding to |
55 | * fields of @ap, the port and devices accordingly. | 56 | * the ata_port passed into the function, or NULL if no such object exists |
56 | * | ||
57 | * LOCKING: | ||
58 | * EH context. | ||
59 | * | ||
60 | * RETURNS: | ||
61 | * 0 on success, -errno on failure. | ||
62 | */ | 57 | */ |
63 | void ata_acpi_associate_sata_port(struct ata_port *ap) | 58 | acpi_handle ata_ap_acpi_handle(struct ata_port *ap) |
64 | { | 59 | { |
65 | WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA)); | 60 | if (ap->flags & ATA_FLAG_ACPI_SATA) |
66 | 61 | return NULL; | |
67 | if (!sata_pmp_attached(ap)) { | ||
68 | u64 adr = SATA_ADR(ap->port_no, NO_PORT_MULT); | ||
69 | |||
70 | ap->link.device->acpi_handle = | ||
71 | acpi_get_child(ap->host->acpi_handle, adr); | ||
72 | } else { | ||
73 | struct ata_link *link; | ||
74 | |||
75 | ap->link.device->acpi_handle = NULL; | ||
76 | |||
77 | ata_for_each_link(link, ap, EDGE) { | ||
78 | u64 adr = SATA_ADR(ap->port_no, link->pmp); | ||
79 | 62 | ||
80 | link->device->acpi_handle = | 63 | /* |
81 | acpi_get_child(ap->host->acpi_handle, adr); | 64 | * If acpi bind operation has already happened, we can get the handle |
82 | } | 65 | * for the port by checking the corresponding scsi_host device's |
83 | } | 66 | * firmware node, otherwise we will need to find out the handle from |
67 | * its parent's acpi node. | ||
68 | */ | ||
69 | if (ap->scsi_host) | ||
70 | return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev); | ||
71 | else | ||
72 | return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), | ||
73 | ap->port_no); | ||
84 | } | 74 | } |
75 | EXPORT_SYMBOL(ata_ap_acpi_handle); | ||
85 | 76 | ||
86 | static void ata_acpi_associate_ide_port(struct ata_port *ap) | 77 | /** |
78 | * ata_dev_acpi_handle - provide the acpi_handle for an ata_device | ||
79 | * @dev: the acpi_device returned will correspond to this port | ||
80 | * | ||
81 | * Returns the acpi_handle for the ACPI namespace object corresponding to | ||
82 | * the ata_device passed into the function, or NULL if no such object exists | ||
83 | */ | ||
84 | acpi_handle ata_dev_acpi_handle(struct ata_device *dev) | ||
87 | { | 85 | { |
88 | int max_devices, i; | 86 | acpi_integer adr; |
89 | 87 | struct ata_port *ap = dev->link->ap; | |
90 | ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no); | ||
91 | if (!ap->acpi_handle) | ||
92 | return; | ||
93 | |||
94 | max_devices = 1; | ||
95 | if (ap->flags & ATA_FLAG_SLAVE_POSS) | ||
96 | max_devices++; | ||
97 | |||
98 | for (i = 0; i < max_devices; i++) { | ||
99 | struct ata_device *dev = &ap->link.device[i]; | ||
100 | |||
101 | dev->acpi_handle = acpi_get_child(ap->acpi_handle, i); | ||
102 | } | ||
103 | 88 | ||
104 | if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) | 89 | if (ap->flags & ATA_FLAG_ACPI_SATA) { |
105 | ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; | 90 | if (!sata_pmp_attached(ap)) |
91 | adr = SATA_ADR(ap->port_no, NO_PORT_MULT); | ||
92 | else | ||
93 | adr = SATA_ADR(ap->port_no, dev->link->pmp); | ||
94 | return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), adr); | ||
95 | } else | ||
96 | return acpi_get_child(ata_ap_acpi_handle(ap), dev->devno); | ||
106 | } | 97 | } |
98 | EXPORT_SYMBOL(ata_dev_acpi_handle); | ||
107 | 99 | ||
108 | /* @ap and @dev are the same as ata_acpi_handle_hotplug() */ | 100 | /* @ap and @dev are the same as ata_acpi_handle_hotplug() */ |
109 | static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) | 101 | static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) |
@@ -229,56 +221,6 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { | |||
229 | }; | 221 | }; |
230 | 222 | ||
231 | /** | 223 | /** |
232 | * ata_acpi_associate - associate ATA host with ACPI objects | ||
233 | * @host: target ATA host | ||
234 | * | ||
235 | * Look up ACPI objects associated with @host and initialize | ||
236 | * acpi_handle fields of @host, its ports and devices accordingly. | ||
237 | * | ||
238 | * LOCKING: | ||
239 | * EH context. | ||
240 | * | ||
241 | * RETURNS: | ||
242 | * 0 on success, -errno on failure. | ||
243 | */ | ||
244 | void ata_acpi_associate(struct ata_host *host) | ||
245 | { | ||
246 | int i, j; | ||
247 | |||
248 | if (!is_pci_dev(host->dev) || libata_noacpi) | ||
249 | return; | ||
250 | |||
251 | host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev); | ||
252 | if (!host->acpi_handle) | ||
253 | return; | ||
254 | |||
255 | for (i = 0; i < host->n_ports; i++) { | ||
256 | struct ata_port *ap = host->ports[i]; | ||
257 | |||
258 | if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA) | ||
259 | ata_acpi_associate_sata_port(ap); | ||
260 | else | ||
261 | ata_acpi_associate_ide_port(ap); | ||
262 | |||
263 | if (ap->acpi_handle) { | ||
264 | /* we might be on a docking station */ | ||
265 | register_hotplug_dock_device(ap->acpi_handle, | ||
266 | &ata_acpi_ap_dock_ops, ap); | ||
267 | } | ||
268 | |||
269 | for (j = 0; j < ata_link_max_devices(&ap->link); j++) { | ||
270 | struct ata_device *dev = &ap->link.device[j]; | ||
271 | |||
272 | if (dev->acpi_handle) { | ||
273 | /* we might be on a docking station */ | ||
274 | register_hotplug_dock_device(dev->acpi_handle, | ||
275 | &ata_acpi_dev_dock_ops, dev); | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /** | ||
282 | * ata_acpi_dissociate - dissociate ATA host from ACPI objects | 224 | * ata_acpi_dissociate - dissociate ATA host from ACPI objects |
283 | * @host: target ATA host | 225 | * @host: target ATA host |
284 | * | 226 | * |
@@ -299,7 +241,7 @@ void ata_acpi_dissociate(struct ata_host *host) | |||
299 | struct ata_port *ap = host->ports[i]; | 241 | struct ata_port *ap = host->ports[i]; |
300 | const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); | 242 | const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); |
301 | 243 | ||
302 | if (ap->acpi_handle && gtm) | 244 | if (ata_ap_acpi_handle(ap) && gtm) |
303 | ata_acpi_stm(ap, gtm); | 245 | ata_acpi_stm(ap, gtm); |
304 | } | 246 | } |
305 | } | 247 | } |
@@ -324,7 +266,8 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm) | |||
324 | acpi_status status; | 266 | acpi_status status; |
325 | int rc = 0; | 267 | int rc = 0; |
326 | 268 | ||
327 | status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output); | 269 | status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_GTM", NULL, |
270 | &output); | ||
328 | 271 | ||
329 | rc = -ENOENT; | 272 | rc = -ENOENT; |
330 | if (status == AE_NOT_FOUND) | 273 | if (status == AE_NOT_FOUND) |
@@ -394,7 +337,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm) | |||
394 | input.count = 3; | 337 | input.count = 3; |
395 | input.pointer = in_params; | 338 | input.pointer = in_params; |
396 | 339 | ||
397 | status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL); | 340 | status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_STM", &input, |
341 | NULL); | ||
398 | 342 | ||
399 | if (status == AE_NOT_FOUND) | 343 | if (status == AE_NOT_FOUND) |
400 | return -ENOENT; | 344 | return -ENOENT; |
@@ -451,7 +395,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf) | |||
451 | __func__, ap->port_no); | 395 | __func__, ap->port_no); |
452 | 396 | ||
453 | /* _GTF has no input parameters */ | 397 | /* _GTF has no input parameters */ |
454 | status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output); | 398 | status = acpi_evaluate_object(ata_dev_acpi_handle(dev), "_GTF", NULL, |
399 | &output); | ||
455 | out_obj = dev->gtf_cache = output.pointer; | 400 | out_obj = dev->gtf_cache = output.pointer; |
456 | 401 | ||
457 | if (ACPI_FAILURE(status)) { | 402 | if (ACPI_FAILURE(status)) { |
@@ -817,7 +762,8 @@ static int ata_acpi_push_id(struct ata_device *dev) | |||
817 | 762 | ||
818 | /* It's OK for _SDD to be missing too. */ | 763 | /* It's OK for _SDD to be missing too. */ |
819 | swap_buf_le16(dev->id, ATA_ID_WORDS); | 764 | swap_buf_le16(dev->id, ATA_ID_WORDS); |
820 | status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL); | 765 | status = acpi_evaluate_object(ata_dev_acpi_handle(dev), "_SDD", &input, |
766 | NULL); | ||
821 | swap_buf_le16(dev->id, ATA_ID_WORDS); | 767 | swap_buf_le16(dev->id, ATA_ID_WORDS); |
822 | 768 | ||
823 | if (status == AE_NOT_FOUND) | 769 | if (status == AE_NOT_FOUND) |
@@ -867,7 +813,7 @@ void ata_acpi_on_resume(struct ata_port *ap) | |||
867 | const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); | 813 | const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); |
868 | struct ata_device *dev; | 814 | struct ata_device *dev; |
869 | 815 | ||
870 | if (ap->acpi_handle && gtm) { | 816 | if (ata_ap_acpi_handle(ap) && gtm) { |
871 | /* _GTM valid */ | 817 | /* _GTM valid */ |
872 | 818 | ||
873 | /* restore timing parameters */ | 819 | /* restore timing parameters */ |
@@ -907,23 +853,39 @@ void ata_acpi_on_resume(struct ata_port *ap) | |||
907 | void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) | 853 | void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) |
908 | { | 854 | { |
909 | struct ata_device *dev; | 855 | struct ata_device *dev; |
910 | 856 | acpi_handle handle; | |
911 | if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA)) | 857 | int acpi_state; |
912 | return; | ||
913 | 858 | ||
914 | /* channel first and then drives for power on and vica versa | 859 | /* channel first and then drives for power on and vica versa |
915 | for power off */ | 860 | for power off */ |
916 | if (state.event == PM_EVENT_ON) | 861 | handle = ata_ap_acpi_handle(ap); |
917 | acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0); | 862 | if (handle && state.event == PM_EVENT_ON) |
863 | acpi_bus_set_power(handle, ACPI_STATE_D0); | ||
918 | 864 | ||
919 | ata_for_each_dev(dev, &ap->link, ENABLED) { | 865 | ata_for_each_dev(dev, &ap->link, ENABLED) { |
920 | if (dev->acpi_handle) | 866 | handle = ata_dev_acpi_handle(dev); |
921 | acpi_bus_set_power(dev->acpi_handle, | 867 | if (!handle) |
922 | state.event == PM_EVENT_ON ? | 868 | continue; |
923 | ACPI_STATE_D0 : ACPI_STATE_D3); | 869 | |
870 | if (state.event != PM_EVENT_ON) { | ||
871 | acpi_state = acpi_pm_device_sleep_state( | ||
872 | &dev->sdev->sdev_gendev, NULL, ACPI_STATE_D3); | ||
873 | if (acpi_state > 0) | ||
874 | acpi_bus_set_power(handle, acpi_state); | ||
875 | /* TBD: need to check if it's runtime pm request */ | ||
876 | acpi_pm_device_run_wake( | ||
877 | &dev->sdev->sdev_gendev, true); | ||
878 | } else { | ||
879 | /* Ditto */ | ||
880 | acpi_pm_device_run_wake( | ||
881 | &dev->sdev->sdev_gendev, false); | ||
882 | acpi_bus_set_power(handle, ACPI_STATE_D0); | ||
883 | } | ||
924 | } | 884 | } |
925 | if (state.event != PM_EVENT_ON) | 885 | |
926 | acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3); | 886 | handle = ata_ap_acpi_handle(ap); |
887 | if (handle && state.event != PM_EVENT_ON) | ||
888 | acpi_bus_set_power(handle, ACPI_STATE_D3); | ||
927 | } | 889 | } |
928 | 890 | ||
929 | /** | 891 | /** |
@@ -948,7 +910,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev) | |||
948 | int nr_executed = 0; | 910 | int nr_executed = 0; |
949 | int rc; | 911 | int rc; |
950 | 912 | ||
951 | if (!dev->acpi_handle) | 913 | if (!ata_dev_acpi_handle(dev)) |
952 | return 0; | 914 | return 0; |
953 | 915 | ||
954 | /* do we need to do _GTF? */ | 916 | /* do we need to do _GTF? */ |
@@ -994,7 +956,6 @@ int ata_acpi_on_devcfg(struct ata_device *dev) | |||
994 | } | 956 | } |
995 | 957 | ||
996 | ata_dev_warn(dev, "ACPI: failed the second time, disabled\n"); | 958 | ata_dev_warn(dev, "ACPI: failed the second time, disabled\n"); |
997 | dev->acpi_handle = NULL; | ||
998 | 959 | ||
999 | /* We can safely continue if no _GTF command has been executed | 960 | /* We can safely continue if no _GTF command has been executed |
1000 | * and port is not frozen. | 961 | * and port is not frozen. |
@@ -1018,3 +979,218 @@ void ata_acpi_on_disable(struct ata_device *dev) | |||
1018 | { | 979 | { |
1019 | ata_acpi_clear_gtf(dev); | 980 | ata_acpi_clear_gtf(dev); |
1020 | } | 981 | } |
982 | |||
983 | static void ata_acpi_wake_dev(acpi_handle handle, u32 event, void *context) | ||
984 | { | ||
985 | struct ata_device *ata_dev = context; | ||
986 | |||
987 | if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev && | ||
988 | pm_runtime_suspended(&ata_dev->sdev->sdev_gendev)) | ||
989 | scsi_autopm_get_device(ata_dev->sdev); | ||
990 | } | ||
991 | |||
992 | static void ata_acpi_add_pm_notifier(struct ata_device *dev) | ||
993 | { | ||
994 | struct acpi_device *acpi_dev; | ||
995 | acpi_handle handle; | ||
996 | acpi_status status; | ||
997 | |||
998 | handle = ata_dev_acpi_handle(dev); | ||
999 | if (!handle) | ||
1000 | return; | ||
1001 | |||
1002 | status = acpi_bus_get_device(handle, &acpi_dev); | ||
1003 | if (ACPI_FAILURE(status)) | ||
1004 | return; | ||
1005 | |||
1006 | if (dev->sdev->can_power_off) { | ||
1007 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
1008 | ata_acpi_wake_dev, dev); | ||
1009 | device_set_run_wake(&dev->sdev->sdev_gendev, true); | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | static void ata_acpi_remove_pm_notifier(struct ata_device *dev) | ||
1014 | { | ||
1015 | struct acpi_device *acpi_dev; | ||
1016 | acpi_handle handle; | ||
1017 | acpi_status status; | ||
1018 | |||
1019 | handle = ata_dev_acpi_handle(dev); | ||
1020 | if (!handle) | ||
1021 | return; | ||
1022 | |||
1023 | status = acpi_bus_get_device(handle, &acpi_dev); | ||
1024 | if (ACPI_FAILURE(status)) | ||
1025 | return; | ||
1026 | |||
1027 | if (dev->sdev->can_power_off) { | ||
1028 | device_set_run_wake(&dev->sdev->sdev_gendev, false); | ||
1029 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
1030 | ata_acpi_wake_dev); | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | static void ata_acpi_register_power_resource(struct ata_device *dev) | ||
1035 | { | ||
1036 | struct scsi_device *sdev = dev->sdev; | ||
1037 | acpi_handle handle; | ||
1038 | struct device *device; | ||
1039 | |||
1040 | handle = ata_dev_acpi_handle(dev); | ||
1041 | if (!handle) | ||
1042 | return; | ||
1043 | |||
1044 | device = &sdev->sdev_gendev; | ||
1045 | |||
1046 | acpi_power_resource_register_device(device, handle); | ||
1047 | } | ||
1048 | |||
1049 | static void ata_acpi_unregister_power_resource(struct ata_device *dev) | ||
1050 | { | ||
1051 | struct scsi_device *sdev = dev->sdev; | ||
1052 | acpi_handle handle; | ||
1053 | struct device *device; | ||
1054 | |||
1055 | handle = ata_dev_acpi_handle(dev); | ||
1056 | if (!handle) | ||
1057 | return; | ||
1058 | |||
1059 | device = &sdev->sdev_gendev; | ||
1060 | |||
1061 | acpi_power_resource_unregister_device(device, handle); | ||
1062 | } | ||
1063 | |||
1064 | void ata_acpi_bind(struct ata_device *dev) | ||
1065 | { | ||
1066 | ata_acpi_add_pm_notifier(dev); | ||
1067 | ata_acpi_register_power_resource(dev); | ||
1068 | } | ||
1069 | |||
1070 | void ata_acpi_unbind(struct ata_device *dev) | ||
1071 | { | ||
1072 | ata_acpi_remove_pm_notifier(dev); | ||
1073 | ata_acpi_unregister_power_resource(dev); | ||
1074 | } | ||
1075 | |||
1076 | static int compat_pci_ata(struct ata_port *ap) | ||
1077 | { | ||
1078 | struct device *dev = ap->tdev.parent; | ||
1079 | struct pci_dev *pdev; | ||
1080 | |||
1081 | if (!is_pci_dev(dev)) | ||
1082 | return 0; | ||
1083 | |||
1084 | pdev = to_pci_dev(dev); | ||
1085 | |||
1086 | if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA && | ||
1087 | (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE) | ||
1088 | return 0; | ||
1089 | |||
1090 | return 1; | ||
1091 | } | ||
1092 | |||
1093 | static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle) | ||
1094 | { | ||
1095 | if (ap->flags & ATA_FLAG_ACPI_SATA) | ||
1096 | return -ENODEV; | ||
1097 | |||
1098 | *handle = acpi_get_child(DEVICE_ACPI_HANDLE(ap->tdev.parent), | ||
1099 | ap->port_no); | ||
1100 | |||
1101 | if (!*handle) | ||
1102 | return -ENODEV; | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1107 | static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, | ||
1108 | acpi_handle *handle) | ||
1109 | { | ||
1110 | struct ata_device *ata_dev; | ||
1111 | acpi_status status; | ||
1112 | struct acpi_device *acpi_dev; | ||
1113 | struct acpi_device_power_state *states; | ||
1114 | |||
1115 | if (ap->flags & ATA_FLAG_ACPI_SATA) | ||
1116 | ata_dev = &ap->link.device[sdev->channel]; | ||
1117 | else | ||
1118 | ata_dev = &ap->link.device[sdev->id]; | ||
1119 | |||
1120 | *handle = ata_dev_acpi_handle(ata_dev); | ||
1121 | |||
1122 | if (!*handle) | ||
1123 | return -ENODEV; | ||
1124 | |||
1125 | status = acpi_bus_get_device(*handle, &acpi_dev); | ||
1126 | if (ACPI_FAILURE(status)) | ||
1127 | return 0; | ||
1128 | |||
1129 | /* | ||
1130 | * If firmware has _PS3 or _PR3 for this device, | ||
1131 | * and this ata ODD device support device attention, | ||
1132 | * it means this device can be powered off | ||
1133 | */ | ||
1134 | states = acpi_dev->power.states; | ||
1135 | if ((states[ACPI_STATE_D3_HOT].flags.valid || | ||
1136 | states[ACPI_STATE_D3_COLD].flags.explicit_set) && | ||
1137 | ata_dev->flags & ATA_DFLAG_DA) | ||
1138 | sdev->can_power_off = 1; | ||
1139 | |||
1140 | return 0; | ||
1141 | } | ||
1142 | |||
1143 | static int is_ata_port(const struct device *dev) | ||
1144 | { | ||
1145 | return dev->type == &ata_port_type; | ||
1146 | } | ||
1147 | |||
1148 | static struct ata_port *dev_to_ata_port(struct device *dev) | ||
1149 | { | ||
1150 | while (!is_ata_port(dev)) { | ||
1151 | if (!dev->parent) | ||
1152 | return NULL; | ||
1153 | dev = dev->parent; | ||
1154 | } | ||
1155 | return to_ata_port(dev); | ||
1156 | } | ||
1157 | |||
1158 | static int ata_acpi_find_device(struct device *dev, acpi_handle *handle) | ||
1159 | { | ||
1160 | struct ata_port *ap = dev_to_ata_port(dev); | ||
1161 | |||
1162 | if (!ap) | ||
1163 | return -ENODEV; | ||
1164 | |||
1165 | if (!compat_pci_ata(ap)) | ||
1166 | return -ENODEV; | ||
1167 | |||
1168 | if (scsi_is_host_device(dev)) | ||
1169 | return ata_acpi_bind_host(ap, handle); | ||
1170 | else if (scsi_is_sdev_device(dev)) { | ||
1171 | struct scsi_device *sdev = to_scsi_device(dev); | ||
1172 | |||
1173 | return ata_acpi_bind_device(ap, sdev, handle); | ||
1174 | } else | ||
1175 | return -ENODEV; | ||
1176 | } | ||
1177 | |||
1178 | static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle) | ||
1179 | { | ||
1180 | return -ENODEV; | ||
1181 | } | ||
1182 | |||
1183 | static struct acpi_bus_type ata_acpi_bus = { | ||
1184 | .find_bridge = ata_acpi_find_dummy, | ||
1185 | .find_device = ata_acpi_find_device, | ||
1186 | }; | ||
1187 | |||
1188 | int ata_acpi_register(void) | ||
1189 | { | ||
1190 | return scsi_register_acpi_bus_type(&ata_acpi_bus); | ||
1191 | } | ||
1192 | |||
1193 | void ata_acpi_unregister(void) | ||
1194 | { | ||
1195 | scsi_unregister_acpi_bus_type(&ata_acpi_bus); | ||
1196 | } | ||