--- zzzz-none-000/linux-3.10.107/drivers/ata/libata-acpi.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/ata/libata-acpi.c 2021-02-04 17:41:59.000000000 +0000 @@ -20,8 +20,6 @@ #include #include "libata.h" -#include - unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT; module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644); MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM, 0x8=FPDMA non-zero offset, 0x10=FPDMA DMA Setup FIS auto-activate)"); @@ -34,62 +32,35 @@ 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; +struct ata_acpi_hotplug_context { + struct acpi_hotplug_context hp; + union { + struct ata_port *ap; + struct ata_device *dev; + } data; +}; - return ap->scsi_host ? - DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev) : NULL; -} -EXPORT_SYMBOL(ata_ap_acpi_handle); +#define ata_hotplug_data(context) (container_of((context), struct ata_acpi_hotplug_context, hp)->data) /** * 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,24 +127,21 @@ 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) +static int ata_acpi_dev_notify_dock(struct acpi_device *adev, u32 event) { - struct ata_device *dev = data; - + struct ata_device *dev = ata_hotplug_data(adev->hp).dev; ata_acpi_handle_hotplug(dev->link->ap, dev, event); + return 0; } -static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data) +static int ata_acpi_ap_notify_dock(struct acpi_device *adev, u32 event) { - struct ata_port *ap = data; - - ata_acpi_handle_hotplug(ap, NULL, event); + ata_acpi_handle_hotplug(ata_hotplug_data(adev->hp).ap, NULL, event); + return 0; } static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev, @@ -195,58 +163,85 @@ } } -static void ata_acpi_ap_uevent(acpi_handle handle, u32 event, void *data) +static void ata_acpi_ap_uevent(struct acpi_device *adev, u32 event) { - ata_acpi_uevent(data, NULL, event); + ata_acpi_uevent(ata_hotplug_data(adev->hp).ap, NULL, event); } -static void ata_acpi_dev_uevent(acpi_handle handle, u32 event, void *data) +static void ata_acpi_dev_uevent(struct acpi_device *adev, u32 event) { - struct ata_device *dev = data; + struct ata_device *dev = ata_hotplug_data(adev->hp).dev; ata_acpi_uevent(dev->link->ap, dev, event); } -static const struct acpi_dock_ops ata_acpi_dev_dock_ops = { - .handler = ata_acpi_dev_notify_dock, - .uevent = ata_acpi_dev_uevent, -}; +/* bind acpi handle to pata port */ +void ata_acpi_bind_port(struct ata_port *ap) +{ + struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); + struct acpi_device *adev; + struct ata_acpi_hotplug_context *context; -static const struct acpi_dock_ops ata_acpi_ap_dock_ops = { - .handler = ata_acpi_ap_notify_dock, - .uevent = ata_acpi_ap_uevent, -}; + if (libata_noacpi || ap->flags & ATA_FLAG_ACPI_SATA || !host_companion) + return; -void ata_acpi_hotplug_init(struct ata_host *host) -{ - int i; + acpi_preset_companion(&ap->tdev, host_companion, ap->port_no); - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - acpi_handle handle; - struct ata_device *dev; + if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) + ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; - if (!ap) - continue; + adev = ACPI_COMPANION(&ap->tdev); + if (!adev || adev->hp) + return; - 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); - } + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) + return; - ata_for_each_dev(dev, &ap->link, ALL) { - handle = ata_dev_acpi_handle(dev); - if (!handle) - continue; + context->data.ap = ap; + acpi_initialize_hp_context(adev, &context->hp, ata_acpi_ap_notify_dock, + ata_acpi_ap_uevent); +} - /* 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; + struct acpi_device *port_companion = ACPI_COMPANION(&ap->tdev); + struct acpi_device *host_companion = ACPI_COMPANION(ap->host->dev); + struct acpi_device *parent, *adev; + struct ata_acpi_hotplug_context *context; + u64 adr; + + /* + * For both sata/pata devices, host companion device is required. + * For pata device, port companion device is also required. + */ + if (libata_noacpi || !host_companion || + (!(ap->flags & ATA_FLAG_ACPI_SATA) && !port_companion)) + 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 = host_companion; + } else { + adr = dev->devno; + parent = port_companion; } + + acpi_preset_companion(&dev->tdev, parent, adr); + adev = ACPI_COMPANION(&dev->tdev); + if (!adev || adev->hp) + return; + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) + return; + + context->data.dev = dev; + acpi_initialize_hp_context(adev, &context->hp, ata_acpi_dev_notify_dock, + ata_acpi_dev_uevent); } /** @@ -270,18 +265,34 @@ 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 +328,6 @@ 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 +364,8 @@ 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 +840,7 @@ 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 */ @@ -863,6 +853,7 @@ ata_for_each_dev(dev, &ap->link, ALL) { ata_acpi_clear_gtf(dev); if (ata_dev_enabled(dev) && + ata_dev_acpi_handle(dev) && ata_dev_get_GTF(dev, NULL) >= 0) dev->flags |= ATA_DFLAG_ACPI_PENDING; } @@ -894,8 +885,7 @@ 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 +922,7 @@ 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; @@ -947,11 +937,11 @@ continue; acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ? - ACPI_STATE_D0 : ACPI_STATE_D3); + ACPI_STATE_D0 : ACPI_STATE_D3_COLD); } if (!(state.event & PM_EVENT_RESUME)) - acpi_bus_set_power(port_handle, ACPI_STATE_D3); + acpi_bus_set_power(port_handle, ACPI_STATE_D3_COLD); } /** @@ -1062,110 +1052,3 @@ { 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) -{ - return scsi_register_acpi_bus_type(&ata_acpi_bus); -} - -void ata_acpi_unregister(void) -{ - scsi_unregister_acpi_bus_type(&ata_acpi_bus); -}