]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/ata/libata-core.c
[libata] Shuffle DRV_xxx in core and SiS drivers, to kill warnings
[mirror_ubuntu-bionic-kernel.git] / drivers / ata / libata-core.c
index f8ec3896b793e21c14e5352c0589a11f22fa0c7b..ed11ee41673cd20d23d8071b8ecfe2297dce2556 100644 (file)
@@ -59,6 +59,9 @@
 
 #include "libata.h"
 
+#define DRV_VERSION    "2.10"  /* must be exactly four chars */
+
+
 /* debounce timing parameters in msecs { interval, duration, timeout } */
 const unsigned long sata_deb_timing_normal[]           = {   5,  100, 2000 };
 const unsigned long sata_deb_timing_hotplug[]          = {  25,  500, 2000 };
@@ -1037,7 +1040,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
                 * the PIO timing number for the maximum. Turn it into
                 * a mask.
                 */
-               u8 mode = id[ATA_ID_OLD_PIO_MODES] & 0xFF;
+               u8 mode = (id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF;
                if (mode < 5)   /* Valid PIO range */
                        pio_mask = (2 << mode) - 1;
                else
@@ -1081,7 +1084,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
  *     ata_port_queue_task - Queue port_task
  *     @ap: The ata_port to queue port_task for
  *     @fn: workqueue function to be scheduled
- *     @data: data value to pass to workqueue function
+ *     @data: data for @fn to use
  *     @delay: delay time for workqueue function
  *
  *     Schedule @fn(@data) for execution after @delay jiffies using
@@ -1096,7 +1099,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
  *     LOCKING:
  *     Inherited from caller.
  */
-void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
+void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
                         unsigned long delay)
 {
        int rc;
@@ -1104,12 +1107,10 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
        if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
                return;
 
-       PREPARE_WORK(&ap->port_task, fn, data);
+       PREPARE_DELAYED_WORK(&ap->port_task, fn);
+       ap->port_task_data = data;
 
-       if (!delay)
-               rc = queue_work(ata_wq, &ap->port_task);
-       else
-               rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
+       rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
 
        /* rc == 0 means that another user is using port task */
        WARN_ON(rc == 0);
@@ -1158,7 +1159,7 @@ void ata_port_flush_task(struct ata_port *ap)
                ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
 }
 
-void ata_qc_complete_internal(struct ata_queued_cmd *qc)
+static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
        struct completion *waiting = qc->private_data;
 
@@ -1251,7 +1252,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
                        buflen += sg[i].length;
 
                ata_sg_init(qc, sg, n_elem);
-               qc->nsect = buflen / ATA_SECT_SIZE;
+               qc->nbytes = buflen;
        }
 
        qc->private_data = &wait;
@@ -1293,7 +1294,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        if (ap->ops->post_internal_cmd)
                ap->ops->post_internal_cmd(qc);
 
-       if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) {
+       if ((qc->flags & ATA_QCFLAG_FAILED) && !qc->err_mask) {
                if (ata_msg_warn(ap))
                        ata_dev_printk(dev, KERN_WARNING,
                                "zero err_mask for failed "
@@ -1334,7 +1335,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
 }
 
 /**
- *     ata_exec_internal_sg - execute libata internal command
+ *     ata_exec_internal - execute libata internal command
  *     @dev: Device to which the command is sent
  *     @tf: Taskfile registers for the command and the result
  *     @cdb: CDB for packet command
@@ -1355,11 +1356,17 @@ unsigned ata_exec_internal(struct ata_device *dev,
                           struct ata_taskfile *tf, const u8 *cdb,
                           int dma_dir, void *buf, unsigned int buflen)
 {
-       struct scatterlist sg;
+       struct scatterlist *psg = NULL, sg;
+       unsigned int n_elem = 0;
 
-       sg_init_one(&sg, buf, buflen);
+       if (dma_dir != DMA_NONE) {
+               WARN_ON(!buf);
+               sg_init_one(&sg, buf, buflen);
+               psg = &sg;
+               n_elem++;
+       }
 
-       return ata_exec_internal_sg(dev, tf, cdb, dma_dir, &sg, 1);
+       return ata_exec_internal_sg(dev, tf, cdb, dma_dir, psg, n_elem);
 }
 
 /**
@@ -2305,7 +2312,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
         * DMA cycle timing is slower/equal than the fastest PIO timing.
         */
 
-       if (speed > XFER_PIO_4) {
+       if (speed > XFER_PIO_6) {
                ata_timing_compute(adev, adev->pio_mode, &p, T, UT);
                ata_timing_merge(&p, t, t, ATA_TIMING_ALL);
        }
@@ -2427,18 +2434,8 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
        int i, rc = 0, used_dma = 0, found = 0;
 
        /* has private set_mode? */
-       if (ap->ops->set_mode) {
-               /* FIXME: make ->set_mode handle no device case and
-                * return error code and failing device on failure.
-                */
-               for (i = 0; i < ATA_MAX_DEVICES; i++) {
-                       if (ata_dev_ready(&ap->device[i])) {
-                               ap->ops->set_mode(ap);
-                               break;
-                       }
-               }
-               return 0;
-       }
+       if (ap->ops->set_mode)
+               return ap->ops->set_mode(ap, r_failed_dev);
 
        /* step 1: calculate xfer_mask */
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
@@ -2498,7 +2495,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                dev = &ap->device[i];
 
-               /* don't udpate suspended devices' xfer mode */
+               /* don't update suspended devices' xfer mode */
                if (!ata_dev_ready(dev))
                        continue;
 
@@ -3192,7 +3189,8 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
                               const u16 *new_id)
 {
        const u16 *old_id = dev->id;
-       unsigned char model[2][41], serial[2][21];
+       unsigned char model[2][ATA_ID_PROD_LEN + 1];
+       unsigned char serial[2][ATA_ID_SERNO_LEN + 1];
        u64 new_n_sectors;
 
        if (dev->class != new_class) {
@@ -3201,10 +3199,10 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
                return 0;
        }
 
-       ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0]));
-       ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1]));
-       ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0]));
-       ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1]));
+       ata_id_c_string(old_id, model[0], ATA_ID_PROD, sizeof(model[0]));
+       ata_id_c_string(new_id, model[1], ATA_ID_PROD, sizeof(model[1]));
+       ata_id_c_string(old_id, serial[0], ATA_ID_SERNO, sizeof(serial[0]));
+       ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));
        new_n_sectors = ata_id_n_sectors(new_id);
 
        if (strcmp(model[0], model[1])) {
@@ -3329,37 +3327,20 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { }
 };
 
-static int ata_strim(char *s, size_t len)
-{
-       len = strnlen(s, len);
-
-       /* ATAPI specifies that empty space is blank-filled; remove blanks */
-       while ((len > 0) && (s[len - 1] == ' ')) {
-               len--;
-               s[len] = 0;
-       }
-       return len;
-}
-
 unsigned long ata_device_blacklisted(const struct ata_device *dev)
 {
-       unsigned char model_num[40];
-       unsigned char model_rev[16];
-       unsigned int nlen, rlen;
+       unsigned char model_num[ATA_ID_PROD_LEN + 1];
+       unsigned char model_rev[ATA_ID_FW_REV_LEN + 1];
        const struct ata_blacklist_entry *ad = ata_device_blacklist;
 
-       ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
-                         sizeof(model_num));
-       ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS,
-                         sizeof(model_rev));
-       nlen = ata_strim(model_num, sizeof(model_num));
-       rlen = ata_strim(model_rev, sizeof(model_rev));
+       ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
+       ata_id_c_string(dev->id, model_rev, ATA_ID_FW_REV, sizeof(model_rev));
 
        while (ad->model_num) {
-               if (!strncmp(ad->model_num, model_num, nlen)) {
+               if (!strcmp(ad->model_num, model_num)) {
                        if (ad->model_rev == NULL)
                                return ad->horkage;
-                       if (!strncmp(ad->model_rev, model_rev, rlen))
+                       if (!strcmp(ad->model_rev, model_rev))
                                return ad->horkage;
                }
                ad++;
@@ -4027,11 +4008,11 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
        unsigned int offset;
        unsigned char *buf;
 
-       if (qc->cursect == (qc->nsect - 1))
+       if (qc->curbytes == qc->nbytes - ATA_SECT_SIZE)
                ap->hsm_task_state = HSM_ST_LAST;
 
        page = sg[qc->cursg].page;
-       offset = sg[qc->cursg].offset + qc->cursg_ofs * ATA_SECT_SIZE;
+       offset = sg[qc->cursg].offset + qc->cursg_ofs;
 
        /* get the current page and offset */
        page = nth_page(page, (offset >> PAGE_SHIFT));
@@ -4056,10 +4037,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
                ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
        }
 
-       qc->cursect++;
-       qc->cursg_ofs++;
+       qc->curbytes += ATA_SECT_SIZE;
+       qc->cursg_ofs += ATA_SECT_SIZE;
 
-       if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) {
+       if (qc->cursg_ofs == (&sg[qc->cursg])->length) {
                qc->cursg++;
                qc->cursg_ofs = 0;
        }
@@ -4084,7 +4065,8 @@ static void ata_pio_sectors(struct ata_queued_cmd *qc)
 
                WARN_ON(qc->dev->multi_count == 0);
 
-               nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+               nsect = min((qc->nbytes - qc->curbytes) / ATA_SECT_SIZE,
+                           qc->dev->multi_count);
                while (nsect--)
                        ata_pio_sector(qc);
        } else
@@ -4588,10 +4570,11 @@ fsm_start:
        return poll_next;
 }
 
-static void ata_pio_task(void *_data)
+static void ata_pio_task(struct work_struct *work)
 {
-       struct ata_queued_cmd *qc = _data;
-       struct ata_port *ap = qc->ap;
+       struct ata_port *ap =
+               container_of(work, struct ata_port, port_task.work);
+       struct ata_queued_cmd *qc = ap->port_task_data;
        u8 status;
        int poll_next;
 
@@ -4961,6 +4944,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
        if (ap->flags & ATA_FLAG_PIO_POLLING) {
                switch (qc->tf.protocol) {
                case ATA_PROT_PIO:
+               case ATA_PROT_NODATA:
                case ATA_PROT_ATAPI:
                case ATA_PROT_ATAPI_NODATA:
                        qc->tf.flags |= ATA_TFLAG_POLLING;
@@ -5505,54 +5489,25 @@ void ata_host_resume(struct ata_host *host)
  *     LOCKING:
  *     Inherited from caller.
  */
-
-int ata_port_start (struct ata_port *ap)
+int ata_port_start(struct ata_port *ap)
 {
        struct device *dev = ap->dev;
        int rc;
 
-       ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
+       ap->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma,
+                                     GFP_KERNEL);
        if (!ap->prd)
                return -ENOMEM;
 
        rc = ata_pad_alloc(ap, dev);
-       if (rc) {
-               dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
+       if (rc)
                return rc;
-       }
-
-       DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
 
+       DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd,
+               (unsigned long long)ap->prd_dma);
        return 0;
 }
 
-
-/**
- *     ata_port_stop - Undo ata_port_start()
- *     @ap: Port to shut down
- *
- *     Frees the PRD table.
- *
- *     May be used as the port_stop() entry in ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-
-void ata_port_stop (struct ata_port *ap)
-{
-       struct device *dev = ap->dev;
-
-       dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
-       ata_pad_free(ap, dev);
-}
-
-void ata_host_stop (struct ata_host *host)
-{
-       if (host->mmio_base)
-               iounmap(host->mmio_base);
-}
-
 /**
  *     ata_dev_init - Initialize an ata_device structure
  *     @dev: Device structure to initialize
@@ -5635,9 +5590,9 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host,
        ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
 #endif
 
-       INIT_WORK(&ap->port_task, NULL, NULL);
-       INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap);
-       INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap);
+       INIT_DELAYED_WORK(&ap->port_task, NULL);
+       INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
+       INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
        INIT_LIST_HEAD(&ap->eh_done_q);
        init_waitqueue_head(&ap->eh_wait_q);
 
@@ -5726,6 +5681,27 @@ static struct ata_port * ata_port_add(const struct ata_probe_ent *ent,
        return ap;
 }
 
+static void ata_host_release(struct device *gendev, void *res)
+{
+       struct ata_host *host = dev_get_drvdata(gendev);
+       int i;
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap = host->ports[i];
+
+               if (!ap)
+                       continue;
+
+               if (ap->ops->port_stop)
+                       ap->ops->port_stop(ap);
+
+               scsi_host_put(ap->scsi_host);
+       }
+
+       if (host->ops->host_stop)
+               host->ops->host_stop(host);
+}
+
 /**
  *     ata_sas_host_init - Initialize a host struct
  *     @host:  host to initialize
@@ -5773,16 +5749,22 @@ int ata_device_add(const struct ata_probe_ent *ent)
        int rc;
 
        DPRINTK("ENTER\n");
-       
+
        if (ent->irq == 0) {
                dev_printk(KERN_ERR, dev, "is not available: No interrupt assigned.\n");
                return 0;
        }
+
+       if (!devres_open_group(dev, ata_device_add, GFP_KERNEL))
+               return 0;
+
        /* alloc a container for our list of ATA ports (buses) */
-       host = kzalloc(sizeof(struct ata_host) +
-                      (ent->n_ports * sizeof(void *)), GFP_KERNEL);
+       host = devres_alloc(ata_host_release, sizeof(struct ata_host) +
+                           (ent->n_ports * sizeof(void *)), GFP_KERNEL);
        if (!host)
-               return 0;
+               goto err_out;
+       devres_add(dev, host);
+       dev_set_drvdata(dev, host);
 
        ata_host_init(host, dev, ent->_host_flags, ent->port_ops);
        host->n_ports = ent->n_ports;
@@ -5840,8 +5822,8 @@ int ata_device_add(const struct ata_probe_ent *ent)
        }
 
        /* obtain irq, that may be shared between channels */
-       rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
-                        DRV_NAME, host);
+       rc = devm_request_irq(dev, ent->irq, ent->port_ops->irq_handler,
+                             ent->irq_flags, DRV_NAME, host);
        if (rc) {
                dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
                           ent->irq, rc);
@@ -5854,15 +5836,19 @@ int ata_device_add(const struct ata_probe_ent *ent)
                   so trap it now */
                BUG_ON(ent->irq == ent->irq2);
 
-               rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags,
-                        DRV_NAME, host);
+               rc = devm_request_irq(dev, ent->irq2,
+                               ent->port_ops->irq_handler, ent->irq_flags,
+                               DRV_NAME, host);
                if (rc) {
                        dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
                                   ent->irq2, rc);
-                       goto err_out_free_irq;
+                       goto err_out;
                }
        }
 
+       /* resource acquisition complete */
+       devres_remove_group(dev, ata_device_add);
+
        /* perform each probe synchronously */
        DPRINTK("probe begin\n");
        for (i = 0; i < host->n_ports; i++) {
@@ -5931,24 +5917,13 @@ int ata_device_add(const struct ata_probe_ent *ent)
                ata_scsi_scan_host(ap);
        }
 
-       dev_set_drvdata(dev, host);
-
        VPRINTK("EXIT, returning %u\n", ent->n_ports);
        return ent->n_ports; /* success */
 
-err_out_free_irq:
-       free_irq(ent->irq, host);
-err_out:
-       for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap = host->ports[i];
-               if (ap) {
-                       ap->ops->port_stop(ap);
-                       scsi_host_put(ap->scsi_host);
-               }
-       }
-
-       kfree(host);
-       VPRINTK("EXIT, returning 0\n");
+ err_out:
+       devres_release_group(dev, ata_device_add);
+       dev_set_drvdata(dev, NULL);
+       VPRINTK("EXIT, returning %d\n", rc);
        return 0;
 }
 
@@ -6011,76 +5986,20 @@ void ata_port_detach(struct ata_port *ap)
 }
 
 /**
- *     ata_host_remove - PCI layer callback for device removal
- *     @host: ATA host set that was removed
+ *     ata_host_detach - Detach all ports of an ATA host
+ *     @host: Host to detach
  *
- *     Unregister all objects associated with this host set. Free those
- *     objects.
+ *     Detach all ports of @host.
  *
  *     LOCKING:
- *     Inherited from calling layer (may sleep).
+ *     Kernel thread context (may sleep).
  */
-
-void ata_host_remove(struct ata_host *host)
+void ata_host_detach(struct ata_host *host)
 {
-       unsigned int i;
+       int i;
 
        for (i = 0; i < host->n_ports; i++)
                ata_port_detach(host->ports[i]);
-
-       free_irq(host->irq, host);
-       if (host->irq2)
-               free_irq(host->irq2, host);
-
-       for (i = 0; i < host->n_ports; i++) {
-               struct ata_port *ap = host->ports[i];
-
-               ata_scsi_release(ap->scsi_host);
-
-               if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
-                       struct ata_ioports *ioaddr = &ap->ioaddr;
-
-                       /* FIXME: Add -ac IDE pci mods to remove these special cases */
-                       if (ioaddr->cmd_addr == ATA_PRIMARY_CMD)
-                               release_region(ATA_PRIMARY_CMD, 8);
-                       else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD)
-                               release_region(ATA_SECONDARY_CMD, 8);
-               }
-
-               scsi_host_put(ap->scsi_host);
-       }
-
-       if (host->ops->host_stop)
-               host->ops->host_stop(host);
-
-       kfree(host);
-}
-
-/**
- *     ata_scsi_release - SCSI layer callback hook for host unload
- *     @shost: libata host to be unloaded
- *
- *     Performs all duties necessary to shut down a libata port...
- *     Kill port kthread, disable port, and release resources.
- *
- *     LOCKING:
- *     Inherited from SCSI layer.
- *
- *     RETURNS:
- *     One.
- */
-
-int ata_scsi_release(struct Scsi_Host *shost)
-{
-       struct ata_port *ap = ata_shost_to_port(shost);
-
-       DPRINTK("ENTER\n");
-
-       ap->ops->port_disable(ap);
-       ap->ops->port_stop(ap);
-
-       DPRINTK("EXIT\n");
-       return 1;
 }
 
 struct ata_probe_ent *
@@ -6088,7 +6007,11 @@ ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
 {
        struct ata_probe_ent *probe_ent;
 
-       probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
+       /* XXX - the following if can go away once all LLDs are managed */
+       if (!list_empty(&dev->devres_head))
+               probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL);
+       else
+               probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL);
        if (!probe_ent) {
                printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
                       kobject_name(&(dev->kobj)));
@@ -6138,37 +6061,23 @@ void ata_std_ports(struct ata_ioports *ioaddr)
 
 #ifdef CONFIG_PCI
 
-void ata_pci_host_stop (struct ata_host *host)
-{
-       struct pci_dev *pdev = to_pci_dev(host->dev);
-
-       pci_iounmap(pdev, host->mmio_base);
-}
-
 /**
  *     ata_pci_remove_one - PCI layer callback for device removal
  *     @pdev: PCI device that was removed
  *
- *     PCI layer indicates to libata via this hook that
- *     hot-unplug or module unload event has occurred.
- *     Handle this by unregistering all objects associated
- *     with this PCI device.  Free those objects.  Then finally
- *     release PCI resources and disable device.
+ *     PCI layer indicates to libata via this hook that hot-unplug or
+ *     module unload event has occurred.  Detach all ports.  Resource
+ *     release is handled via devres.
  *
  *     LOCKING:
  *     Inherited from PCI layer (may sleep).
  */
-
-void ata_pci_remove_one (struct pci_dev *pdev)
+void ata_pci_remove_one(struct pci_dev *pdev)
 {
        struct device *dev = pci_dev_to_dev(pdev);
        struct ata_host *host = dev_get_drvdata(dev);
 
-       ata_host_remove(host);
-
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       dev_set_drvdata(dev, NULL);
+       ata_host_detach(host);
 }
 
 /* move to PCI subsystem */
@@ -6215,12 +6124,22 @@ void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg)
        }
 }
 
-void ata_pci_device_do_resume(struct pci_dev *pdev)
+int ata_pci_device_do_resume(struct pci_dev *pdev)
 {
+       int rc;
+
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
-       pci_enable_device(pdev);
+
+       rc = pcim_enable_device(pdev);
+       if (rc) {
+               dev_printk(KERN_ERR, &pdev->dev,
+                          "failed to enable device after resume (%d)\n", rc);
+               return rc;
+       }
+
        pci_set_master(pdev);
+       return 0;
 }
 
 int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
@@ -6240,10 +6159,12 @@ int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
 int ata_pci_device_resume(struct pci_dev *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int rc;
 
-       ata_pci_device_do_resume(pdev);
-       ata_host_resume(host);
-       return 0;
+       rc = ata_pci_device_do_resume(pdev);
+       if (rc == 0)
+               ata_host_resume(host);
+       return rc;
 }
 #endif /* CONFIG_PCI */
 
@@ -6389,8 +6310,7 @@ EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_host_init);
 EXPORT_SYMBOL_GPL(ata_device_add);
-EXPORT_SYMBOL_GPL(ata_port_detach);
-EXPORT_SYMBOL_GPL(ata_host_remove);
+EXPORT_SYMBOL_GPL(ata_host_detach);
 EXPORT_SYMBOL_GPL(ata_sg_init);
 EXPORT_SYMBOL_GPL(ata_sg_init_one);
 EXPORT_SYMBOL_GPL(ata_hsm_move);
@@ -6407,8 +6327,6 @@ EXPORT_SYMBOL_GPL(ata_check_status);
 EXPORT_SYMBOL_GPL(ata_altstatus);
 EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
-EXPORT_SYMBOL_GPL(ata_port_stop);
-EXPORT_SYMBOL_GPL(ata_host_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_mmio_data_xfer);
 EXPORT_SYMBOL_GPL(ata_pio_data_xfer);
@@ -6449,7 +6367,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
 EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
-EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(sata_scr_valid);
 EXPORT_SYMBOL_GPL(sata_scr_read);
@@ -6470,7 +6387,6 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
-EXPORT_SYMBOL_GPL(ata_pci_host_stop);
 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);