]> err.no Git - linux-2.6/blobdiff - drivers/ata/libata-acpi.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6] / drivers / ata / libata-acpi.c
index bf98a566adac67c2ec49dc7fc4318fbf15cad68d..dbf6ca781f66ff578a57ad6226c4dc921f5efca4 100644 (file)
@@ -77,7 +77,7 @@ void ata_acpi_associate_sata_port(struct ata_port *ap)
 {
        WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA));
 
-       if (!ap->nr_pmp_links) {
+       if (!sata_pmp_attached(ap)) {
                acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
 
                ap->link.device->acpi_handle =
@@ -118,8 +118,8 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
                ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
 }
 
-static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
-                                   u32 event)
+static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device
+                                   *dev, u32 event)
 {
        char event_string[12];
        char *envp[] = { event_string, NULL };
@@ -127,6 +127,9 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
        struct kobject *kobj = NULL;
        int wait = 0;
        unsigned long flags;
+       acpi_handle handle, tmphandle;
+       unsigned long sta;
+       acpi_status status;
 
        if (!ap)
                ap = dev->link->ap;
@@ -134,32 +137,57 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
 
        spin_lock_irqsave(ap->lock, flags);
 
+       if (dev)
+               handle = dev->acpi_handle;
+       else
+               handle = ap->acpi_handle;
+
+       status = acpi_get_handle(handle, "_EJ0", &tmphandle);
+       if (ACPI_FAILURE(status)) {
+               /* This device is not ejectable */
+               spin_unlock_irqrestore(ap->lock, flags);
+               return;
+       }
+
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+       if (ACPI_FAILURE(status)) {
+               printk ("Unable to determine bay status\n");
+               spin_unlock_irqrestore(ap->lock, flags);
+               return;
+       }
+
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
        case ACPI_NOTIFY_DEVICE_CHECK:
                ata_ehi_push_desc(ehi, "ACPI event");
-               ata_ehi_hotplugged(ehi);
-               ata_port_freeze(ap);
-               break;
-
-       case ACPI_NOTIFY_EJECT_REQUEST:
-               ata_ehi_push_desc(ehi, "ACPI event");
-               if (dev)
-                       dev->flags |= ATA_DFLAG_DETACH;
-               else {
-                       struct ata_link *tlink;
-                       struct ata_device *tdev;
-
-                       ata_port_for_each_link(tlink, ap)
-                               ata_link_for_each_dev(tdev, tlink)
-                                       tdev->flags |= ATA_DFLAG_DETACH;
+               if (!sta) {
+                /* Device has been unplugged */
+                       if (dev)
+                               dev->flags |= ATA_DFLAG_DETACH;
+                       else {
+                               struct ata_link *tlink;
+                               struct ata_device *tdev;
+
+                               ata_port_for_each_link(tlink, ap) {
+                                       ata_link_for_each_dev(tdev, tlink) {
+                                               tdev->flags |=
+                                                       ATA_DFLAG_DETACH;
+                                       }
+                               }
+                       }
+                       ata_port_schedule_eh(ap);
+                       wait = 1;
+               } else {
+                       ata_ehi_hotplugged(ehi);
+                       ata_port_freeze(ap);
                }
-
-               ata_port_schedule_eh(ap);
-               wait = 1;
-               break;
        }
 
+       spin_unlock_irqrestore(ap->lock, flags);
+
+       if (wait)
+               ata_port_wait_eh(ap);
+
        if (dev) {
                if (dev->sdev)
                        kobj = &dev->sdev->sdev_gendev.kobj;
@@ -170,11 +198,6 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
                sprintf(event_string, "BAY_EVENT=%d", event);
                kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
        }
-
-       spin_unlock_irqrestore(ap->lock, flags);
-
-       if (wait)
-               ata_port_wait_eh(ap);
 }
 
 static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
@@ -227,11 +250,9 @@ void ata_acpi_associate(struct ata_host *host)
                        acpi_install_notify_handler(ap->acpi_handle,
                                                    ACPI_SYSTEM_NOTIFY,
                                                    ata_acpi_ap_notify, ap);
-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
                        /* we might be on a docking station */
                        register_hotplug_dock_device(ap->acpi_handle,
                                                     ata_acpi_ap_notify, ap);
-#endif
                }
 
                for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
@@ -241,11 +262,9 @@ void ata_acpi_associate(struct ata_host *host)
                                acpi_install_notify_handler(dev->acpi_handle,
                                                ACPI_SYSTEM_NOTIFY,
                                                ata_acpi_dev_notify, dev);
-#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
                                /* we might be on a docking station */
                                register_hotplug_dock_device(dev->acpi_handle,
                                                ata_acpi_dev_notify, dev);
-#endif
                        }
                }
        }
@@ -839,7 +858,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
                 */
                ata_link_for_each_dev(dev, &ap->link) {
                        ata_acpi_clear_gtf(dev);
-                       if (ata_dev_get_GTF(dev, NULL) >= 0)
+                       if (ata_dev_enabled(dev) &&
+                           ata_dev_get_GTF(dev, NULL) >= 0)
                                dev->flags |= ATA_DFLAG_ACPI_PENDING;
                }
        } else {
@@ -849,7 +869,8 @@ void ata_acpi_on_resume(struct ata_port *ap)
                 */
                ata_link_for_each_dev(dev, &ap->link) {
                        ata_acpi_clear_gtf(dev);
-                       dev->flags |= ATA_DFLAG_ACPI_PENDING;
+                       if (ata_dev_enabled(dev))
+                               dev->flags |= ATA_DFLAG_ACPI_PENDING;
                }
        }
 }