diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-acpi.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 9e69a5308693..acb95dffdb6a 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -38,6 +38,16 @@ static void ata_acpi_clear_gtf(struct ata_device *dev) | |||
38 | dev->gtf_cache = NULL; | 38 | dev->gtf_cache = NULL; |
39 | } | 39 | } |
40 | 40 | ||
41 | struct ata_acpi_hotplug_context { | ||
42 | struct acpi_hotplug_context hp; | ||
43 | union { | ||
44 | struct ata_port *ap; | ||
45 | struct ata_device *dev; | ||
46 | } data; | ||
47 | }; | ||
48 | |||
49 | #define ata_hotplug_data(context) (container_of((context), struct ata_acpi_hotplug_context, hp)->data) | ||
50 | |||
41 | /** | 51 | /** |
42 | * ata_dev_acpi_handle - provide the acpi_handle for an ata_device | 52 | * ata_dev_acpi_handle - provide the acpi_handle for an ata_device |
43 | * @dev: the acpi_handle returned will correspond to this device | 53 | * @dev: the acpi_handle returned will correspond to this device |
@@ -121,18 +131,17 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, | |||
121 | ata_port_wait_eh(ap); | 131 | ata_port_wait_eh(ap); |
122 | } | 132 | } |
123 | 133 | ||
124 | static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) | 134 | static int ata_acpi_dev_notify_dock(struct acpi_device *adev, u32 event) |
125 | { | 135 | { |
126 | struct ata_device *dev = data; | 136 | struct ata_device *dev = ata_hotplug_data(adev->hp).dev; |
127 | |||
128 | ata_acpi_handle_hotplug(dev->link->ap, dev, event); | 137 | ata_acpi_handle_hotplug(dev->link->ap, dev, event); |
138 | return 0; | ||
129 | } | 139 | } |
130 | 140 | ||
131 | static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) | 141 | static int ata_acpi_ap_notify_dock(struct acpi_device *adev, u32 event) |
132 | { | 142 | { |
133 | struct ata_port *ap = data; | 143 | ata_acpi_handle_hotplug(ata_hotplug_data(adev->hp).ap, NULL, event); |
134 | 144 | return 0; | |
135 | ata_acpi_handle_hotplug(ap, NULL, event); | ||
136 | } | 145 | } |
137 | 146 | ||
138 | static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, | 147 | static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, |
@@ -154,31 +163,23 @@ static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, | |||
154 | } | 163 | } |
155 | } | 164 | } |
156 | 165 | ||
157 | static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data) | 166 | static void ata_acpi_ap_uevent(struct acpi_device *adev, u32 event) |
158 | { | 167 | { |
159 | ata_acpi_uevent(data, NULL, event); | 168 | ata_acpi_uevent(ata_hotplug_data(adev->hp).ap, NULL, event); |
160 | } | 169 | } |
161 | 170 | ||
162 | static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data) | 171 | static void ata_acpi_dev_uevent(struct acpi_device *adev, u32 event) |
163 | { | 172 | { |
164 | struct ata_device *dev = data; | 173 | struct ata_device *dev = ata_hotplug_data(adev->hp).dev; |
165 | ata_acpi_uevent(dev->link->ap, dev, event); | 174 | ata_acpi_uevent(dev->link->ap, dev, event); |
166 | } | 175 | } |
167 | 176 | ||
168 | static const struct acpi_dock_ops ata_acpi_dev_dock_ops = { | ||
169 | .handler = ata_acpi_dev_notify_dock, | ||
170 | .uevent = ata_acpi_dev_uevent, | ||
171 | }; | ||
172 | |||
173 | static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { | ||
174 | .handler = ata_acpi_ap_notify_dock, | ||
175 | .uevent = ata_acpi_ap_uevent, | ||
176 | }; | ||
177 | |||
178 | /* bind acpi handle to pata port */ | 177 | /* bind acpi handle to pata port */ |
179 | void ata_acpi_bind_port(struct ata_port *ap) | 178 | void ata_acpi_bind_port(struct ata_port *ap) |
180 | { | 179 | { |
181 | struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); | 180 | struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); |
181 | struct acpi_device *adev; | ||
182 | struct ata_acpi_hotplug_context *context; | ||
182 | 183 | ||
183 | if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion) | 184 | if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion) |
184 | return; | 185 | return; |
@@ -188,9 +189,17 @@ void ata_acpi_bind_port(struct ata_port *ap) | |||
188 | if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) | 189 | if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) |
189 | ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; | 190 | ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; |
190 | 191 | ||
191 | /* we might be on a docking station */ | 192 | adev = ACPI_COMPANION(&ap->tdev); |
192 | register_hotplug_dock_device(ACPI_HANDLE(&ap->tdev), | 193 | if (!adev || adev->hp) |
193 | &ata_acpi_ap_dock_ops, ap, NULL, NULL); | 194 | return; |
195 | |||
196 | context = kzalloc(sizeof(*context), GFP_KERNEL); | ||
197 | if (!context) | ||
198 | return; | ||
199 | |||
200 | context->data.ap = ap; | ||
201 | acpi_initialize_hp_context(adev, &context->hp, ata_acpi_ap_notify_dock, | ||
202 | ata_acpi_ap_uevent); | ||
194 | } | 203 | } |
195 | 204 | ||
196 | void ata_acpi_bind_dev(struct ata_device *dev) | 205 | void ata_acpi_bind_dev(struct ata_device *dev) |
@@ -198,7 +207,8 @@ void ata_acpi_bind_dev(struct ata_device *dev) | |||
198 | struct ata_port *ap = dev->link->ap; | 207 | struct ata_port *ap = dev->link->ap; |
199 | struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev); | 208 | struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev); |
200 | struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); | 209 | struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); |
201 | struct acpi_device *parent; | 210 | struct acpi_device *parent, *adev; |
211 | struct ata_acpi_hotplug_context *context; | ||
202 | u64 adr; | 212 | u64 adr; |
203 | 213 | ||
204 | /* | 214 | /* |
@@ -221,9 +231,17 @@ void ata_acpi_bind_dev(struct ata_device *dev) | |||
221 | } | 231 | } |
222 | 232 | ||
223 | acpi_preset_companion(&dev->tdev, parent, adr); | 233 | acpi_preset_companion(&dev->tdev, parent, adr); |
234 | adev = ACPI_COMPANION(&dev->tdev); | ||
235 | if (!adev || adev->hp) | ||
236 | return; | ||
237 | |||
238 | context = kzalloc(sizeof(*context), GFP_KERNEL); | ||
239 | if (!context) | ||
240 | return; | ||
224 | 241 | ||
225 | register_hotplug_dock_device(ata_dev_acpi_handle(dev), | 242 | context->data.dev = dev; |
226 | &ata_acpi_dev_dock_ops, dev, NULL, NULL); | 243 | acpi_initialize_hp_context(adev, &context->hp, ata_acpi_dev_notify_dock, |
244 | ata_acpi_dev_uevent); | ||
227 | } | 245 | } |
228 | 246 | ||
229 | /** | 247 | /** |