aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2008-10-22 23:25:26 -0400
committerLen Brown <len.brown@intel.com>2008-10-22 23:25:26 -0400
commit47bf31adc541bef0c20de15e800e0011f1ae70c7 (patch)
tree28903879a8570eaefa57942ec3d475d365f5a465 /drivers/ata
parent4538fad56ee1c16bce0294b5647d2551f0e03164 (diff)
parent0a918a9432cc30aede10f904253b66ea6ab485ac (diff)
Merge branch 'dock' into test
Conflicts: drivers/acpi/osl.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-acpi.c135
1 files changed, 48 insertions, 87 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 9330b7922f62..c012307d0ba6 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -120,21 +120,6 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
120 ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; 120 ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
121} 121}
122 122
123static void ata_acpi_eject_device(acpi_handle handle)
124{
125 struct acpi_object_list arg_list;
126 union acpi_object arg;
127
128 arg_list.count = 1;
129 arg_list.pointer = &arg;
130 arg.type = ACPI_TYPE_INTEGER;
131 arg.integer.value = 1;
132
133 if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
134 &arg_list, NULL)))
135 printk(KERN_ERR "Failed to evaluate _EJ0!\n");
136}
137
138/* @ap and @dev are the same as ata_acpi_handle_hotplug() */ 123/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
139static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev) 124static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
140{ 125{
@@ -157,7 +142,6 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
157 * @ap: ATA port ACPI event occurred 142 * @ap: ATA port ACPI event occurred
158 * @dev: ATA device ACPI event occurred (can be NULL) 143 * @dev: ATA device ACPI event occurred (can be NULL)
159 * @event: ACPI event which occurred 144 * @event: ACPI event which occurred
160 * @is_dock_event: boolean indicating whether the event was a dock one
161 * 145 *
162 * All ACPI bay / device realted events end up in this function. If 146 * All ACPI bay / device realted events end up in this function. If
163 * the event is port-wide @dev is NULL. If the event is specific to a 147 * the event is port-wide @dev is NULL. If the event is specific to a
@@ -171,117 +155,100 @@ static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
171 * ACPI notify handler context. May sleep. 155 * ACPI notify handler context. May sleep.
172 */ 156 */
173static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev, 157static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
174 u32 event, int is_dock_event) 158 u32 event)
175{ 159{
176 char event_string[12];
177 char *envp[] = { event_string, NULL };
178 struct ata_eh_info *ehi = &ap->link.eh_info; 160 struct ata_eh_info *ehi = &ap->link.eh_info;
179 struct kobject *kobj = NULL;
180 int wait = 0; 161 int wait = 0;
181 unsigned long flags; 162 unsigned long flags;
182 acpi_handle handle, tmphandle; 163 acpi_handle handle;
183 unsigned long sta;
184 acpi_status status;
185 164
186 if (dev) { 165 if (dev)
187 if (dev->sdev)
188 kobj = &dev->sdev->sdev_gendev.kobj;
189 handle = dev->acpi_handle; 166 handle = dev->acpi_handle;
190 } else { 167 else
191 kobj = &ap->dev->kobj;
192 handle = ap->acpi_handle; 168 handle = ap->acpi_handle;
193 }
194
195 status = acpi_get_handle(handle, "_EJ0", &tmphandle);
196 if (ACPI_FAILURE(status))
197 /* This device does not support hotplug */
198 return;
199
200 if (event == ACPI_NOTIFY_BUS_CHECK ||
201 event == ACPI_NOTIFY_DEVICE_CHECK)
202 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
203 169
204 spin_lock_irqsave(ap->lock, flags); 170 spin_lock_irqsave(ap->lock, flags);
205 171 /*
172 * When dock driver calls into the routine, it will always use
173 * ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
174 * ACPI_NOTIFY_EJECT_REQUEST for remove
175 */
206 switch (event) { 176 switch (event) {
207 case ACPI_NOTIFY_BUS_CHECK: 177 case ACPI_NOTIFY_BUS_CHECK:
208 case ACPI_NOTIFY_DEVICE_CHECK: 178 case ACPI_NOTIFY_DEVICE_CHECK:
209 ata_ehi_push_desc(ehi, "ACPI event"); 179 ata_ehi_push_desc(ehi, "ACPI event");
210 180
211 if (ACPI_FAILURE(status)) { 181 ata_ehi_hotplugged(ehi);
212 ata_port_printk(ap, KERN_ERR, 182 ata_port_freeze(ap);
213 "acpi: failed to determine bay status (0x%x)\n",
214 status);
215 break;
216 }
217
218 if (sta) {
219 ata_ehi_hotplugged(ehi);
220 ata_port_freeze(ap);
221 } else {
222 /* The device has gone - unplug it */
223 ata_acpi_detach_device(ap, dev);
224 wait = 1;
225 }
226 break; 183 break;
227 case ACPI_NOTIFY_EJECT_REQUEST: 184 case ACPI_NOTIFY_EJECT_REQUEST:
228 ata_ehi_push_desc(ehi, "ACPI event"); 185 ata_ehi_push_desc(ehi, "ACPI event");
229 186
230 if (!is_dock_event)
231 break;
232
233 /* undock event - immediate unplug */
234 ata_acpi_detach_device(ap, dev); 187 ata_acpi_detach_device(ap, dev);
235 wait = 1; 188 wait = 1;
236 break; 189 break;
237 } 190 }
238 191
239 /* make sure kobj doesn't go away while ap->lock is released */
240 kobject_get(kobj);
241
242 spin_unlock_irqrestore(ap->lock, flags); 192 spin_unlock_irqrestore(ap->lock, flags);
243 193
244 if (wait) { 194 if (wait)
245 ata_port_wait_eh(ap); 195 ata_port_wait_eh(ap);
246 ata_acpi_eject_device(handle);
247 }
248
249 if (kobj && !is_dock_event) {
250 sprintf(event_string, "BAY_EVENT=%d", event);
251 kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
252 }
253
254 kobject_put(kobj);
255} 196}
256 197
257static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data) 198static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
258{ 199{
259 struct ata_device *dev = data; 200 struct ata_device *dev = data;
260 201
261 ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1); 202 ata_acpi_handle_hotplug(dev->link->ap, dev, event);
262} 203}
263 204
264static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) 205static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
265{ 206{
266 struct ata_port *ap = data; 207 struct ata_port *ap = data;
267 208
268 ata_acpi_handle_hotplug(ap, NULL, event, 1); 209 ata_acpi_handle_hotplug(ap, NULL, event);
269} 210}
270 211
271static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data) 212static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,
213 u32 event)
272{ 214{
273 struct ata_device *dev = data; 215 struct kobject *kobj = NULL;
216 char event_string[20];
217 char *envp[] = { event_string, NULL };
218
219 if (dev) {
220 if (dev->sdev)
221 kobj = &dev->sdev->sdev_gendev.kobj;
222 } else
223 kobj = &ap->dev->kobj;
274 224
275 ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0); 225 if (kobj) {
226 snprintf(event_string, 20, "BAY_EVENT=%d", event);
227 kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
228 }
276} 229}
277 230
278static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data) 231static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data)
279{ 232{
280 struct ata_port *ap = data; 233 ata_acpi_uevent(data, NULL, event);
234}
281 235
282 ata_acpi_handle_hotplug(ap, NULL, event, 0); 236static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data)
237{
238 struct ata_device *dev = data;
239 ata_acpi_uevent(dev->link->ap, dev, event);
283} 240}
284 241
242static struct acpi_dock_ops ata_acpi_dev_dock_ops = {
243 .handler = ata_acpi_dev_notify_dock,
244 .uevent = ata_acpi_dev_uevent,
245};
246
247static struct acpi_dock_ops ata_acpi_ap_dock_ops = {
248 .handler = ata_acpi_ap_notify_dock,
249 .uevent = ata_acpi_ap_uevent,
250};
251
285/** 252/**
286 * ata_acpi_associate - associate ATA host with ACPI objects 253 * ata_acpi_associate - associate ATA host with ACPI objects
287 * @host: target ATA host 254 * @host: target ATA host
@@ -315,24 +282,18 @@ void ata_acpi_associate(struct ata_host *host)
315 ata_acpi_associate_ide_port(ap); 282 ata_acpi_associate_ide_port(ap);
316 283
317 if (ap->acpi_handle) { 284 if (ap->acpi_handle) {
318 acpi_install_notify_handler(ap->acpi_handle,
319 ACPI_SYSTEM_NOTIFY,
320 ata_acpi_ap_notify, ap);
321 /* we might be on a docking station */ 285 /* we might be on a docking station */
322 register_hotplug_dock_device(ap->acpi_handle, 286 register_hotplug_dock_device(ap->acpi_handle,
323 ata_acpi_ap_notify_dock, ap); 287 &ata_acpi_ap_dock_ops, ap);
324 } 288 }
325 289
326 for (j = 0; j < ata_link_max_devices(&ap->link); j++) { 290 for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
327 struct ata_device *dev = &ap->link.device[j]; 291 struct ata_device *dev = &ap->link.device[j];
328 292
329 if (dev->acpi_handle) { 293 if (dev->acpi_handle) {
330 acpi_install_notify_handler(dev->acpi_handle,
331 ACPI_SYSTEM_NOTIFY,
332 ata_acpi_dev_notify, dev);
333 /* we might be on a docking station */ 294 /* we might be on a docking station */
334 register_hotplug_dock_device(dev->acpi_handle, 295 register_hotplug_dock_device(dev->acpi_handle,
335 ata_acpi_dev_notify_dock, dev); 296 &ata_acpi_dev_dock_ops, dev);
336 } 297 }
337 } 298 }
338 } 299 }