]> Pileus Git - ~andy/linux/blobdiff - drivers/ata/libata-acpi.c
Merge branch 'for-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata
[~andy/linux] / drivers / ata / libata-acpi.c
index da8170dfc90f142d8924de9c10be76444acbb250..4ba8b04055728d49a0ac147a608d1ad27391d62a 100644 (file)
@@ -34,62 +34,25 @@ struct ata_acpi_gtf {
        u8      tf[REGS_PER_GTF];       /* regs. 0x1f1 - 0x1f7 */
 } __packed;
 
-/*
- *     Helper - belongs in the PCI layer somewhere eventually
- */
-static int is_pci_dev(struct device *dev)
-{
-       return (dev->bus == &pci_bus_type);
-}
-
 static void ata_acpi_clear_gtf(struct ata_device *dev)
 {
        kfree(dev->gtf_cache);
        dev->gtf_cache = NULL;
 }
 
-/**
- * ata_ap_acpi_handle - provide the acpi_handle for an ata_port
- * @ap: the acpi_handle returned will correspond to this port
- *
- * Returns the acpi_handle for the ACPI namespace object corresponding to
- * the ata_port passed into the function, or NULL if no such object exists
- */
-acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
-{
-       if (ap->flags & ATA_FLAG_ACPI_SATA)
-               return NULL;
-
-       return ap->scsi_host ?
-               DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev) : NULL;
-}
-EXPORT_SYMBOL(ata_ap_acpi_handle);
-
 /**
  * ata_dev_acpi_handle - provide the acpi_handle for an ata_device
- * @dev: the acpi_device returned will correspond to this port
+ * @dev: the acpi_handle returned will correspond to this device
  *
  * Returns the acpi_handle for the ACPI namespace object corresponding to
  * the ata_device passed into the function, or NULL if no such object exists
+ * or ACPI is disabled for this device due to consecutive errors.
  */
 acpi_handle ata_dev_acpi_handle(struct ata_device *dev)
 {
-       acpi_integer adr;
-       struct ata_port *ap = dev->link->ap;
-
-       if (libata_noacpi || dev->flags & ATA_DFLAG_ACPI_DISABLED)
-               return NULL;
-
-       if (ap->flags & ATA_FLAG_ACPI_SATA) {
-               if (!sata_pmp_attached(ap))
-                       adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
-               else
-                       adr = SATA_ADR(ap->port_no, dev->link->pmp);
-               return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), adr);
-       } else
-               return acpi_get_child(ata_ap_acpi_handle(ap), dev->devno);
+       return dev->flags & ATA_DFLAG_ACPI_DISABLED ?
+                       NULL : ACPI_HANDLE(&dev->tdev);
 }
-EXPORT_SYMBOL(ata_dev_acpi_handle);
 
 /* @ap and @dev are the same as ata_acpi_handle_hotplug() */
 static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
@@ -156,10 +119,8 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
 
        spin_unlock_irqrestore(ap->lock, flags);
 
-       if (wait) {
+       if (wait)
                ata_port_wait_eh(ap);
-               flush_work(&ap->hotplug_task.work);
-       }
 }
 
 static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
@@ -216,37 +177,55 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
        .uevent = ata_acpi_ap_uevent,
 };
 
-void ata_acpi_hotplug_init(struct ata_host *host)
+/* bind acpi handle to pata port */
+void ata_acpi_bind_port(struct ata_port *ap)
 {
-       int i;
+       acpi_handle host_handle = ACPI_HANDLE(ap->host->dev);
 
-       for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap = host->ports[i];
-               acpi_handle handle;
-               struct ata_device *dev;
+       if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_handle)
+               return;
 
-               if (!ap)
-                       continue;
+       ACPI_HANDLE_SET(&ap->tdev, acpi_get_child(host_handle, ap->port_no));
 
-               handle = ata_ap_acpi_handle(ap);
-               if (handle) {
-                       /* we might be on a docking station */
-                       register_hotplug_dock_device(handle,
-                                                    &ata_acpi_ap_dock_ops, ap,
-                                                    NULL, NULL);
-               }
+       if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
+               ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
 
-               ata_for_each_dev(dev, &ap->link, ALL) {
-                       handle = ata_dev_acpi_handle(dev);
-                       if (!handle)
-                               continue;
+       /* we might be on a docking station */
+       register_hotplug_dock_device(ACPI_HANDLE(&ap->tdev),
+                                    &ata_acpi_ap_dock_ops, ap, NULL, NULL);
+}
 
-                       /* we might be on a docking station */
-                       register_hotplug_dock_device(handle,
-                                                    &ata_acpi_dev_dock_ops,
-                                                    dev, NULL, NULL);
-               }
+void ata_acpi_bind_dev(struct ata_device *dev)
+{
+       struct ata_port *ap = dev->link->ap;
+       acpi_handle port_handle = ACPI_HANDLE(&ap->tdev);
+       acpi_handle host_handle = ACPI_HANDLE(ap->host->dev);
+       acpi_handle parent_handle;
+       u64 adr;
+
+       /*
+        * For both sata/pata devices, host handle is required.
+        * For pata device, port handle is also required.
+        */
+       if (libata_noacpi || !host_handle ||
+                       (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_handle))
+               return;
+
+       if (ap->flags & ATA_FLAG_ACPI_SATA) {
+               if (!sata_pmp_attached(ap))
+                       adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
+               else
+                       adr = SATA_ADR(ap->port_no, dev->link->pmp);
+               parent_handle = host_handle;
+       } else {
+               adr = dev->devno;
+               parent_handle = port_handle;
        }
+
+       ACPI_HANDLE_SET(&dev->tdev, acpi_get_child(parent_handle, adr));
+
+       register_hotplug_dock_device(ata_dev_acpi_handle(dev),
+                                    &ata_acpi_dev_dock_ops, dev, NULL, NULL);
 }
 
 /**
@@ -270,18 +249,34 @@ void ata_acpi_dissociate(struct ata_host *host)
                struct ata_port *ap = host->ports[i];
                const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
 
-               if (ata_ap_acpi_handle(ap) && gtm)
+               if (ACPI_HANDLE(&ap->tdev) && gtm)
                        ata_acpi_stm(ap, gtm);
        }
 }
 
-static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle,
-                         struct ata_acpi_gtm *gtm)
+/**
+ * ata_acpi_gtm - execute _GTM
+ * @ap: target ATA port
+ * @gtm: out parameter for _GTM result
+ *
+ * Evaluate _GTM and store the result in @gtm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
+ */
+int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
 {
        struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
        union acpi_object *out_obj;
        acpi_status status;
        int rc = 0;
+       acpi_handle handle = ACPI_HANDLE(&ap->tdev);
+
+       if (!handle)
+               return -EINVAL;
 
        status = acpi_evaluate_object(handle, "_GTM", NULL, &output);
 
@@ -317,27 +312,6 @@ static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle,
        return rc;
 }
 
-/**
- * ata_acpi_gtm - execute _GTM
- * @ap: target ATA port
- * @gtm: out parameter for _GTM result
- *
- * Evaluate _GTM and store the result in @gtm.
- *
- * LOCKING:
- * EH context.
- *
- * RETURNS:
- * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
- */
-int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
-{
-       if (ata_ap_acpi_handle(ap))
-               return __ata_acpi_gtm(ap, ata_ap_acpi_handle(ap), gtm);
-       else
-               return -EINVAL;
-}
-
 EXPORT_SYMBOL_GPL(ata_acpi_gtm);
 
 /**
@@ -374,8 +348,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm)
        input.count = 3;
        input.pointer = in_params;
 
-       status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_STM", &input,
-                                     NULL);
+       status = acpi_evaluate_object(ACPI_HANDLE(&ap->tdev), "_STM",
+                                     &input, NULL);
 
        if (status == AE_NOT_FOUND)
                return -ENOENT;
@@ -850,7 +824,7 @@ void ata_acpi_on_resume(struct ata_port *ap)
        const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
        struct ata_device *dev;
 
-       if (ata_ap_acpi_handle(ap) && gtm) {
+       if (ACPI_HANDLE(&ap->tdev) && gtm) {
                /* _GTM valid */
 
                /* restore timing parameters */
@@ -894,8 +868,7 @@ static int ata_acpi_choose_suspend_state(struct ata_device *dev, bool runtime)
                d_max_in = ACPI_STATE_D3_HOT;
 
 out:
-       return acpi_pm_device_sleep_state(&dev->sdev->sdev_gendev,
-                                         NULL, d_max_in);
+       return acpi_pm_device_sleep_state(&dev->tdev, NULL, d_max_in);
 }
 
 static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state)
@@ -932,7 +905,7 @@ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state)
        struct ata_device *dev;
        acpi_handle port_handle;
 
-       port_handle = ata_ap_acpi_handle(ap);
+       port_handle = ACPI_HANDLE(&ap->tdev);
        if (!port_handle)
                return;
 
@@ -1063,109 +1036,16 @@ void ata_acpi_on_disable(struct ata_device *dev)
        ata_acpi_clear_gtf(dev);
 }
 
-static int compat_pci_ata(struct ata_port *ap)
-{
-       struct device *dev = ap->tdev.parent;
-       struct pci_dev *pdev;
-
-       if (!is_pci_dev(dev))
-               return 0;
-
-       pdev = to_pci_dev(dev);
-
-       if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
-           (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
-               return 0;
-
-       return 1;
-}
-
-static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle)
-{
-       if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA)
-               return -ENODEV;
-
-       *handle = acpi_get_child(DEVICE_ACPI_HANDLE(ap->tdev.parent),
-                       ap->port_no);
-
-       if (!*handle)
-               return -ENODEV;
-
-       if (__ata_acpi_gtm(ap, *handle, &ap->__acpi_init_gtm) == 0)
-               ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
-
-       return 0;
-}
-
-static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
-                               acpi_handle *handle)
-{
-       struct ata_device *ata_dev;
-
-       if (ap->flags & ATA_FLAG_ACPI_SATA) {
-               if (!sata_pmp_attached(ap))
-                       ata_dev = &ap->link.device[sdev->id];
-               else
-                       ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
-       }
-       else {
-               ata_dev = &ap->link.device[sdev->id];
-       }
-
-       *handle = ata_dev_acpi_handle(ata_dev);
-
-       if (!*handle)
-               return -ENODEV;
-
-       return 0;
-}
-
-static int is_ata_port(const struct device *dev)
-{
-       return dev->type == &ata_port_type;
-}
-
-static struct ata_port *dev_to_ata_port(struct device *dev)
-{
-       while (!is_ata_port(dev)) {
-               if (!dev->parent)
-                       return NULL;
-               dev = dev->parent;
-       }
-       return to_ata_port(dev);
-}
-
-static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
-{
-       struct ata_port *ap = dev_to_ata_port(dev);
-
-       if (!ap)
-               return -ENODEV;
-
-       if (!compat_pci_ata(ap))
-               return -ENODEV;
-
-       if (scsi_is_host_device(dev))
-               return ata_acpi_bind_host(ap, handle);
-       else if (scsi_is_sdev_device(dev)) {
-               struct scsi_device *sdev = to_scsi_device(dev);
-
-               return ata_acpi_bind_device(ap, sdev, handle);
-       } else
-               return -ENODEV;
-}
-
-static struct acpi_bus_type ata_acpi_bus = {
-       .name = "ATA",
-       .find_device = ata_acpi_find_device,
-};
-
-int ata_acpi_register(void)
+void ata_scsi_acpi_bind(struct ata_device *dev)
 {
-       return scsi_register_acpi_bus_type(&ata_acpi_bus);
+       acpi_handle handle = ata_dev_acpi_handle(dev);
+       if (handle)
+               acpi_dev_pm_add_dependent(handle, &dev->sdev->sdev_gendev);
 }
 
-void ata_acpi_unregister(void)
+void ata_scsi_acpi_unbind(struct ata_device *dev)
 {
-       scsi_unregister_acpi_bus_type(&ata_acpi_bus);
+       acpi_handle handle = ata_dev_acpi_handle(dev);
+       if (handle)
+               acpi_dev_pm_remove_dependent(handle, &dev->sdev->sdev_gendev);
 }