]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/libata-core.c
[SCSI] qla2xxx: Correct issue where the rport's upcall was not being made after relogin.
[linux-2.6-omap-h63xx.git] / drivers / scsi / libata-core.c
index a0060cf31e0d8fd26180afbda64d1342510c2a94..46c4cdbaee86dc26114299c2a1ccfa45150b9c39 100644 (file)
@@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = {
        ATA_CMD_WRITE_MULTI,
        ATA_CMD_READ_MULTI_EXT,
        ATA_CMD_WRITE_MULTI_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_MULTI_FUA_EXT,
        /* pio */
        ATA_CMD_PIO_READ,
        ATA_CMD_PIO_WRITE,
        ATA_CMD_PIO_READ_EXT,
        ATA_CMD_PIO_WRITE_EXT,
+       0,
+       0,
+       0,
+       0,
        /* dma */
        ATA_CMD_READ,
        ATA_CMD_WRITE,
        ATA_CMD_READ_EXT,
-       ATA_CMD_WRITE_EXT
+       ATA_CMD_WRITE_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_FUA_EXT
 };
 
 /**
@@ -584,25 +596,36 @@ static const u8 ata_rw_cmds[] = {
  *     LOCKING:
  *     caller.
  */
-void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
+int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
 {
        struct ata_taskfile *tf = &qc->tf;
        struct ata_device *dev = qc->dev;
+       u8 cmd;
 
-       int index, lba48, write;
+       int index, fua, lba48, write;
  
+       fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
        lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
        write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
 
        if (dev->flags & ATA_DFLAG_PIO) {
+               tf->protocol = ATA_PROT_PIO;
+               index = dev->multi_count ? 0 : 8;
+       } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+               /* Unable to use DMA due to host limitation */
                tf->protocol = ATA_PROT_PIO;
                index = dev->multi_count ? 0 : 4;
        } else {
                tf->protocol = ATA_PROT_DMA;
-               index = 8;
+               index = 16;
        }
 
-       tf->command = ata_rw_cmds[index + lba48 + write];
+       cmd = ata_rw_cmds[index + fua + lba48 + write];
+       if (cmd) {
+               tf->command = cmd;
+               return 0;
+       }
+       return -1;
 }
 
 static const char * const xfer_mode_str[] = {
@@ -1032,42 +1055,154 @@ static unsigned int ata_pio_modes(const struct ata_device *adev)
 {
        u16 modes;
 
-       /* Usual case. Word 53 indicates word 88 is valid */
-       if (adev->id[ATA_ID_FIELD_VALID] & (1 << 2)) {
+       /* Usual case. Word 53 indicates word 64 is valid */
+       if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
                modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
                modes <<= 3;
                modes |= 0x7;
                return modes;
        }
 
-       /* If word 88 isn't valid then Word 51 holds the PIO timing number
-          for the maximum. Turn it into a mask and return it */
-       modes = (2 << (adev->id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+       /* If word 64 isn't valid then Word 51 high byte holds the PIO timing
+          number for the maximum. Turn it into a mask and return it */
+       modes = (2 << ((adev->id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF)) - 1 ;
        return modes;
+       /* But wait.. there's more. Design your standards by committee and
+          you too can get a free iordy field to process. However its the 
+          speeds not the modes that are supported... Note drivers using the
+          timing API will get this right anyway */
 }
 
-static int ata_qc_wait_err(struct ata_queued_cmd *qc,
-                          struct completion *wait)
+struct ata_exec_internal_arg {
+       unsigned int err_mask;
+       struct ata_taskfile *tf;
+       struct completion *waiting;
+};
+
+int ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
-       int rc = 0;
+       struct ata_exec_internal_arg *arg = qc->private_data;
+       struct completion *waiting = arg->waiting;
 
-       if (wait_for_completion_timeout(wait, 30 * HZ) < 1) {
-               /* timeout handling */
-               qc->err_mask |= ac_err_mask(ata_chk_status(qc->ap));
+       if (!(qc->err_mask & ~AC_ERR_DEV))
+               qc->ap->ops->tf_read(qc->ap, arg->tf);
+       arg->err_mask = qc->err_mask;
+       arg->waiting = NULL;
+       complete(waiting);
 
-               if (!qc->err_mask) {
-                       printk(KERN_WARNING "ata%u: slow completion (cmd %x)\n",
-                              qc->ap->id, qc->tf.command);
-               } else {
-                       printk(KERN_WARNING "ata%u: qc timeout (cmd %x)\n",
-                              qc->ap->id, qc->tf.command);
-                       rc = -EIO;
+       return 0;
+}
+
+/**
+ *     ata_exec_internal - execute libata internal command
+ *     @ap: Port to which the command is sent
+ *     @dev: Device to which the command is sent
+ *     @tf: Taskfile registers for the command and the result
+ *     @dma_dir: Data tranfer direction of the command
+ *     @buf: Data buffer of the command
+ *     @buflen: Length of data buffer
+ *
+ *     Executes libata internal command with timeout.  @tf contains
+ *     command on entry and result on return.  Timeout and error
+ *     conditions are reported via return value.  No recovery action
+ *     is taken after a command times out.  It's caller's duty to
+ *     clean up after timeout.
+ *
+ *     LOCKING:
+ *     None.  Should be called with kernel context, might sleep.
+ */
+
+static unsigned
+ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
+                 struct ata_taskfile *tf,
+                 int dma_dir, void *buf, unsigned int buflen)
+{
+       u8 command = tf->command;
+       struct ata_queued_cmd *qc;
+       DECLARE_COMPLETION(wait);
+       unsigned long flags;
+       struct ata_exec_internal_arg arg;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+
+       qc = ata_qc_new_init(ap, dev);
+       BUG_ON(qc == NULL);
+
+       qc->tf = *tf;
+       qc->dma_dir = dma_dir;
+       if (dma_dir != DMA_NONE) {
+               ata_sg_init_one(qc, buf, buflen);
+               qc->nsect = buflen / ATA_SECT_SIZE;
+       }
+
+       arg.waiting = &wait;
+       arg.tf = tf;
+       qc->private_data = &arg;
+       qc->complete_fn = ata_qc_complete_internal;
+
+       if (ata_qc_issue(qc))
+               goto issue_fail;
+
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
+               spin_lock_irqsave(&ap->host_set->lock, flags);
+
+               /* We're racing with irq here.  If we lose, the
+                * following test prevents us from completing the qc
+                * again.  If completion irq occurs after here but
+                * before the caller cleans up, it will result in a
+                * spurious interrupt.  We can live with that.
+                */
+               if (arg.waiting) {
+                       qc->err_mask = AC_ERR_OTHER;
+                       ata_qc_complete(qc);
+                       printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
+                              ap->id, command);
                }
 
-               ata_qc_complete(qc);
+               spin_unlock_irqrestore(&ap->host_set->lock, flags);
        }
 
-       return rc;
+       return arg.err_mask;
+
+ issue_fail:
+       ata_qc_free(qc);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       return AC_ERR_OTHER;
+}
+
+/**
+ *     ata_pio_need_iordy      -       check if iordy needed
+ *     @adev: ATA device
+ *
+ *     Check if the current speed of the device requires IORDY. Used
+ *     by various controllers for chip configuration.
+ */
+
+unsigned int ata_pio_need_iordy(const struct ata_device *adev)
+{
+       int pio;
+       int speed = adev->pio_mode - XFER_PIO_0;
+
+       if (speed < 2)
+               return 0;
+       if (speed > 2)
+               return 1;
+               
+       /* If we have no drive specific rule, then PIO 2 is non IORDY */
+
+       if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE */
+               pio = adev->id[ATA_ID_EIDE_PIO];
+               /* Is the speed faster than the drive allows non IORDY ? */
+               if (pio) {
+                       /* This is cycle times not frequency - watch the logic! */
+                       if (pio > 240)  /* PIO2 is 240nS per cycle */
+                               return 1;
+                       return 0;
+               }
+       }
+       return 0;
 }
 
 /**
@@ -1099,9 +1234,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
        u16 tmp;
        unsigned long xfer_modes;
        unsigned int using_edd;
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
+       struct ata_taskfile tf;
+       unsigned int err_mask;
        int rc;
 
        if (!ata_dev_present(dev)) {
@@ -1122,40 +1256,26 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 
        ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
-
-       ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-       qc->dma_dir = DMA_FROM_DEVICE;
-       qc->tf.protocol = ATA_PROT_PIO;
-       qc->nsect = 1;
-
 retry:
+       ata_tf_init(ap, &tf, device);
+
        if (dev->class == ATA_DEV_ATA) {
-               qc->tf.command = ATA_CMD_ID_ATA;
+               tf.command = ATA_CMD_ID_ATA;
                DPRINTK("do ATA identify\n");
        } else {
-               qc->tf.command = ATA_CMD_ID_ATAPI;
+               tf.command = ATA_CMD_ID_ATAPI;
                DPRINTK("do ATAPI identify\n");
        }
 
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
+       tf.protocol = ATA_PROT_PIO;
 
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       if (rc)
-               goto err_out;
-       else
-               ata_qc_wait_err(qc, &wait);
+       err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+                                    dev->id, sizeof(dev->id));
 
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       ap->ops->tf_read(ap, &qc->tf);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       if (err_mask) {
+               if (err_mask & ~AC_ERR_DEV)
+                       goto err_out;
 
-       if (qc->tf.command & ATA_ERR) {
                /*
                 * arg!  EDD works for all test cases, but seems to return
                 * the ATA signature for some ATAPI devices.  Until the
@@ -1168,14 +1288,9 @@ retry:
                 * to have this problem.
                 */
                if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
-                       u8 err = qc->tf.feature;
+                       u8 err = tf.feature;
                        if (err & ATA_ABORTED) {
                                dev->class = ATA_DEV_ATAPI;
-                               qc->cursg = 0;
-                               qc->cursg_ofs = 0;
-                               qc->cursect = 0;
-                               qc->nsect = 1;
-                               qc->err_mask = 0;
                                goto retry;
                        }
                }
@@ -1341,7 +1456,7 @@ void ata_dev_config(struct ata_port *ap, unsigned int i)
                ap->udma_mask &= ATA_UDMA5;
                ap->host->max_sectors = ATA_MAX_SECTORS;
                ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
-               ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+               ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
        }
 
        if (ap->ops->dev_config)
@@ -1673,7 +1788,7 @@ static const struct {
        { ATA_SHIFT_PIO,        XFER_PIO_0 },
 };
 
-static inline u8 base_from_shift(unsigned int shift)
+static u8 base_from_shift(unsigned int shift)
 {
        int i;
 
@@ -2279,34 +2394,23 @@ static int ata_choose_xfer_mode(const struct ata_port *ap,
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 {
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       int rc;
-       unsigned long flags;
+       struct ata_taskfile tf;
 
        /* set up set-features taskfile */
        DPRINTK("set features - xfer mode\n");
 
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
-
-       qc->tf.command = ATA_CMD_SET_FEATURES;
-       qc->tf.feature = SETFEATURES_XFER;
-       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       qc->tf.protocol = ATA_PROT_NODATA;
-       qc->tf.nsect = dev->xfer_mode;
-
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       ata_tf_init(ap, &tf, dev->devno);
+       tf.command = ATA_CMD_SET_FEATURES;
+       tf.feature = SETFEATURES_XFER;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+       tf.nsect = dev->xfer_mode;
 
-       if (rc)
+       if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+               printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n",
+                      ap->id);
                ata_port_disable(ap);
-       else
-               ata_qc_wait_err(qc, &wait);
+       }
 
        DPRINTK("EXIT\n");
 }
@@ -2321,41 +2425,25 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 
 static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 {
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
-       int rc;
-
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
+       struct ata_taskfile tf;
 
-       ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-       qc->dma_dir = DMA_FROM_DEVICE;
+       ata_tf_init(ap, &tf, dev->devno);
 
        if (dev->class == ATA_DEV_ATA) {
-               qc->tf.command = ATA_CMD_ID_ATA;
+               tf.command = ATA_CMD_ID_ATA;
                DPRINTK("do ATA identify\n");
        } else {
-               qc->tf.command = ATA_CMD_ID_ATAPI;
+               tf.command = ATA_CMD_ID_ATAPI;
                DPRINTK("do ATAPI identify\n");
        }
 
-       qc->tf.flags |= ATA_TFLAG_DEVICE;
-       qc->tf.protocol = ATA_PROT_PIO;
-       qc->nsect = 1;
-
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
+       tf.flags |= ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_PIO;
 
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       if (rc)
+       if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+                             dev->id, sizeof(dev->id)))
                goto err_out;
 
-       ata_qc_wait_err(qc, &wait);
-
        swap_buf_le16(dev->id, ATA_ID_WORDS);
 
        ata_dump_id(dev);
@@ -2364,6 +2452,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 
        return;
 err_out:
+       printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
        ata_port_disable(ap);
 }
 
@@ -2377,10 +2466,7 @@ err_out:
 
 static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
 {
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       int rc;
-       unsigned long flags;
+       struct ata_taskfile tf;
        u16 sectors = dev->id[6];
        u16 heads   = dev->id[3];
 
@@ -2391,26 +2477,18 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
        /* set up init dev params taskfile */
        DPRINTK("init dev params \n");
 
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
-
-       qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
-       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       qc->tf.protocol = ATA_PROT_NODATA;
-       qc->tf.nsect = sectors;
-       qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
-
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       ata_tf_init(ap, &tf, dev->devno);
+       tf.command = ATA_CMD_INIT_DEV_PARAMS;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+       tf.nsect = sectors;
+       tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
 
-       if (rc)
+       if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+               printk(KERN_ERR "ata%u: failed to init parameters, disabled\n",
+                      ap->id);
                ata_port_disable(ap);
-       else
-               ata_qc_wait_err(qc, &wait);
+       }
 
        DPRINTK("EXIT\n");
 }
@@ -3019,10 +3097,21 @@ static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
 static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
                          unsigned int buflen, int do_write)
 {
-       if (ap->flags & ATA_FLAG_MMIO)
-               ata_mmio_data_xfer(ap, buf, buflen, do_write);
-       else
-               ata_pio_data_xfer(ap, buf, buflen, do_write);
+       /* Make the crap hardware pay the costs not the good stuff */
+       if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) {
+               unsigned long flags;
+               local_irq_save(flags);
+               if (ap->flags & ATA_FLAG_MMIO)
+                       ata_mmio_data_xfer(ap, buf, buflen, do_write);
+               else
+                       ata_pio_data_xfer(ap, buf, buflen, do_write);
+               local_irq_restore(flags);
+       } else {
+               if (ap->flags & ATA_FLAG_MMIO)
+                       ata_mmio_data_xfer(ap, buf, buflen, do_write);
+               else
+                       ata_pio_data_xfer(ap, buf, buflen, do_write);
+       }
 }
 
 /**
@@ -3482,15 +3571,10 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
        return qc;
 }
 
-int ata_qc_complete_noop(struct ata_queued_cmd *qc)
-{
-       return 0;
-}
-
 static void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       unsigned int tag, do_clear = 0;
+       unsigned int tag;
 
        qc->flags = 0;
        tag = qc->tag;
@@ -3498,17 +3582,8 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
                if (tag == ap->active_tag)
                        ap->active_tag = ATA_TAG_POISON;
                qc->tag = ATA_TAG_POISON;
-               do_clear = 1;
-       }
-
-       if (qc->waiting) {
-               struct completion *waiting = qc->waiting;
-               qc->waiting = NULL;
-               complete(waiting);
-       }
-
-       if (likely(do_clear))
                clear_bit(tag, &ap->qactive);
+       }
 }
 
 /**
@@ -3524,7 +3599,6 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
 void ata_qc_free(struct ata_queued_cmd *qc)
 {
        assert(qc != NULL);     /* ata_qc_from_tag _might_ return NULL */
-       assert(qc->waiting == NULL);    /* nothing should be waiting */
 
        __ata_qc_complete(qc);
 }
@@ -4151,6 +4225,96 @@ err_out:
  *     Inherited from caller.
  */
 
+/*
+ * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
+ * without filling any other registers
+ */
+static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
+                            u8 cmd)
+{
+       struct ata_taskfile tf;
+       int err;
+
+       ata_tf_init(ap, &tf, dev->devno);
+
+       tf.command = cmd;
+       tf.flags |= ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+
+       err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
+       if (err)
+               printk(KERN_ERR "%s: ata command failed: %d\n",
+                               __FUNCTION__, err);
+
+       return err;
+}
+
+static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
+{
+       u8 cmd;
+
+       if (!ata_try_flush_cache(dev))
+               return 0;
+
+       if (ata_id_has_flush_ext(dev->id))
+               cmd = ATA_CMD_FLUSH_EXT;
+       else
+               cmd = ATA_CMD_FLUSH;
+
+       return ata_do_simple_cmd(ap, dev, cmd);
+}
+
+static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
+{
+       return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
+}
+
+static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
+{
+       return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
+}
+
+/**
+ *     ata_device_resume - wakeup a previously suspended devices
+ *
+ *     Kick the drive back into action, by sending it an idle immediate
+ *     command and making sure its transfer mode matches between drive
+ *     and host.
+ *
+ */
+int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
+{
+       if (ap->flags & ATA_FLAG_SUSPENDED) {
+               ap->flags &= ~ATA_FLAG_SUSPENDED;
+               ata_set_mode(ap);
+       }
+       if (!ata_dev_present(dev))
+               return 0;
+       if (dev->class == ATA_DEV_ATA)
+               ata_start_drive(ap, dev);
+
+       return 0;
+}
+
+/**
+ *     ata_device_suspend - prepare a device for suspend
+ *
+ *     Flush the cache on the drive, if appropriate, then issue a
+ *     standbynow command.
+ *
+ */
+int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
+{
+       if (!ata_dev_present(dev))
+               return 0;
+       if (dev->class == ATA_DEV_ATA)
+               ata_flush_cache(ap, dev);
+
+       ata_standby_drive(ap, dev);
+       ap->flags |= ATA_FLAG_SUSPENDED;
+       return 0;
+}
+
 int ata_port_start (struct ata_port *ap)
 {
        struct device *dev = ap->host_set->dev;
@@ -4899,6 +5063,23 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
 
        return (tmp == bits->val) ? 1 : 0;
 }
+
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+       return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_device(pdev);
+       pci_set_master(pdev);
+       return 0;
+}
 #endif /* CONFIG_PCI */
 
 
@@ -4993,6 +5174,7 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
 EXPORT_SYMBOL_GPL(ata_dev_config);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
+EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
 EXPORT_SYMBOL_GPL(ata_timing_compute);
 EXPORT_SYMBOL_GPL(ata_timing_merge);
 
@@ -5002,4 +5184,11 @@ 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);
+EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_resume);
 #endif /* CONFIG_PCI */
+
+EXPORT_SYMBOL_GPL(ata_device_suspend);
+EXPORT_SYMBOL_GPL(ata_device_resume);
+EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
+EXPORT_SYMBOL_GPL(ata_scsi_device_resume);