]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'irq-pio'
authorTejun Heo <htejun@gmail.com>
Mon, 15 May 2006 11:59:15 +0000 (20:59 +0900)
committerTejun Heo <htejun@gmail.com>
Mon, 15 May 2006 11:59:15 +0000 (20:59 +0900)
Conflicts:

drivers/scsi/libata-core.c
include/linux/libata.h

1  2 
drivers/scsi/libata-core.c
drivers/scsi/libata-eh.c
drivers/scsi/sata_mv.c
drivers/scsi/sata_promise.c
drivers/scsi/sata_sx4.c
include/linux/ata.h
include/linux/libata.h

index 2969599ec0b9ad7163dbd38911a5d355a7c3a47b,5d38a6cc5736ae6a62de85e5d4ed6f28ee4c8d10..c859b96b891a8ed5ca7070dc255dad9e61504a6f
  
  #include "libata.h"
  
 -static unsigned int ata_dev_init_params(struct ata_port *ap,
 -                                      struct ata_device *dev,
 -                                      u16 heads,
 -                                      u16 sectors);
 -static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
 -                                       struct ata_device *dev);
 -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev);
 +static unsigned int ata_dev_init_params(struct ata_device *dev,
 +                                      u16 heads, u16 sectors);
 +static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
 +static void ata_dev_xfermask(struct ata_device *dev);
  
  static unsigned int ata_unique_id = 1;
  static struct workqueue_struct *ata_wq;
@@@ -409,10 -412,11 +409,10 @@@ static const char *sata_spd_string(unsi
        return spd_str[spd - 1];
  }
  
 -void ata_dev_disable(struct ata_port *ap, struct ata_device *dev)
 +void ata_dev_disable(struct ata_device *dev)
  {
        if (ata_dev_enabled(dev)) {
 -              printk(KERN_WARNING "ata%u: dev %u disabled\n",
 -                     ap->id, dev->devno);
 +              ata_dev_printk(dev, KERN_WARNING, "disabled\n");
                dev->class++;
        }
  }
@@@ -951,11 -955,13 +951,11 @@@ void ata_qc_complete_internal(struct at
  {
        struct completion *waiting = qc->private_data;
  
 -      qc->ap->ops->tf_read(qc->ap, &qc->tf);
        complete(waiting);
  }
  
  /**
   *    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
   *    @cdb: CDB for packet command
   *    None.  Should be called with kernel context, might sleep.
   */
  
 -unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
 +unsigned ata_exec_internal(struct ata_device *dev,
                           struct ata_taskfile *tf, const u8 *cdb,
                           int dma_dir, void *buf, unsigned int buflen)
  {
 +      struct ata_port *ap = dev->ap;
        u8 command = tf->command;
        struct ata_queued_cmd *qc;
 +      unsigned int tag, preempted_tag;
        DECLARE_COMPLETION(wait);
        unsigned long flags;
        unsigned int err_mask;
 +      int rc;
  
        spin_lock_irqsave(&ap->host_set->lock, flags);
  
 -      qc = ata_qc_new_init(ap, dev);
 -      BUG_ON(qc == NULL);
 +      /* no internal command while frozen */
 +      if (ap->flags & ATA_FLAG_FROZEN) {
 +              spin_unlock_irqrestore(&ap->host_set->lock, flags);
 +              return AC_ERR_SYSTEM;
 +      }
 +
 +      /* initialize internal qc */
 +
 +      /* XXX: Tag 0 is used for drivers with legacy EH as some
 +       * drivers choke if any other tag is given.  This breaks
 +       * ata_tag_internal() test for those drivers.  Don't use new
 +       * EH stuff without converting to it.
 +       */
 +      if (ap->ops->error_handler)
 +              tag = ATA_TAG_INTERNAL;
 +      else
 +              tag = 0;
 +
 +      if (test_and_set_bit(tag, &ap->qactive))
 +              BUG();
 +      qc = __ata_qc_from_tag(ap, tag);
 +
 +      qc->tag = tag;
 +      qc->scsicmd = NULL;
 +      qc->ap = ap;
 +      qc->dev = dev;
 +      ata_qc_reinit(qc);
  
 +      preempted_tag = ap->active_tag;
 +      ap->active_tag = ATA_TAG_POISON;
 +
 +      /* prepare & issue qc */
        qc->tf = *tf;
        if (cdb)
                memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
 +      qc->flags |= ATA_QCFLAG_RESULT_TF;
        qc->dma_dir = dma_dir;
        if (dma_dir != DMA_NONE) {
                ata_sg_init_one(qc, buf, buflen);
  
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
  
 -      if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
 -              ata_port_flush_task(ap);
 +      rc = wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL);
 +
 +      ata_port_flush_task(ap);
  
 +      if (!rc) {
                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.
 +               * twice.  If we win, the port is frozen and will be
 +               * cleaned up by ->post_internal_cmd().
                 */
                if (qc->flags & ATA_QCFLAG_ACTIVE) {
 -                      qc->err_mask = AC_ERR_TIMEOUT;
 -                      ata_qc_complete(qc);
 -                      printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
 -                             ap->id, command);
 +                      qc->err_mask |= AC_ERR_TIMEOUT;
 +
 +                      if (ap->ops->error_handler)
 +                              ata_port_freeze(ap);
 +                      else
 +                              ata_qc_complete(qc);
 +
 +                      ata_dev_printk(dev, KERN_WARNING,
 +                                     "qc timeout (cmd 0x%x)\n", command);
                }
  
                spin_unlock_irqrestore(&ap->host_set->lock, flags);
        }
  
 -      *tf = qc->tf;
 +      /* do post_internal_cmd */
 +      if (ap->ops->post_internal_cmd)
 +              ap->ops->post_internal_cmd(qc);
 +
 +      if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) {
 +              ata_dev_printk(dev, KERN_WARNING, "zero err_mask for failed "
 +                             "internal command, assuming AC_ERR_OTHER\n");
 +              qc->err_mask |= AC_ERR_OTHER;
 +      }
 +
 +      /* finish up */
 +      spin_lock_irqsave(&ap->host_set->lock, flags);
 +
 +      *tf = qc->result_tf;
        err_mask = qc->err_mask;
  
        ata_qc_free(qc);
 +      ap->active_tag = preempted_tag;
  
        /* XXX - Some LLDDs (sata_mv) disable port on command failure.
         * Until those drivers are fixed, we detect the condition
                ata_port_probe(ap);
        }
  
 +      spin_unlock_irqrestore(&ap->host_set->lock, flags);
 +
        return err_mask;
  }
  
@@@ -1139,10 -1090,11 +1139,10 @@@ unsigned int ata_pio_need_iordy(const s
  
  /**
   *    ata_dev_read_id - Read ID data from the specified device
 - *    @ap: port on which target device resides
   *    @dev: target device
   *    @p_class: pointer to class of the target device (may be changed)
   *    @post_reset: is this read ID post-reset?
 - *    @p_id: read IDENTIFY page (newly allocated)
 + *    @id: buffer to read IDENTIFY data into
   *
   *    Read ID data from the specified device.  ATA_CMD_ID_ATA is
   *    performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
   *    RETURNS:
   *    0 on success, -errno otherwise.
   */
 -static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
 -                         unsigned int *p_class, int post_reset, u16 **p_id)
 +static int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
 +                         int post_reset, u16 *id)
  {
 +      struct ata_port *ap = dev->ap;
        unsigned int class = *p_class;
        struct ata_taskfile tf;
        unsigned int err_mask = 0;
 -      u16 *id;
        const char *reason;
        int rc;
  
  
        ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
  
 -      id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
 -      if (id == NULL) {
 -              rc = -ENOMEM;
 -              reason = "out of memory";
 -              goto err_out;
 -      }
 -
   retry:
 -      ata_tf_init(ap, &tf, dev->devno);
 +      ata_tf_init(dev, &tf);
  
        switch (class) {
        case ATA_DEV_ATA:
  
        tf.protocol = ATA_PROT_PIO;
  
 -      err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_FROM_DEVICE,
 +      err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
                                     id, sizeof(id[0]) * ATA_ID_WORDS);
        if (err_mask) {
                rc = -EIO;
                 * Some drives were very specific about that exact sequence.
                 */
                if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
 -                      err_mask = ata_dev_init_params(ap, dev, id[3], id[6]);
 +                      err_mask = ata_dev_init_params(dev, id[3], id[6]);
                        if (err_mask) {
                                rc = -EIO;
                                reason = "INIT_DEV_PARAMS failed";
        }
  
        *p_class = class;
 -      *p_id = id;
 +
        return 0;
  
   err_out:
 -      printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n",
 -             ap->id, dev->devno, reason);
 -      kfree(id);
 +      ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY "
 +                     "(%s, err_mask=0x%x)\n", reason, err_mask);
        return rc;
  }
  
 -static inline u8 ata_dev_knobble(const struct ata_port *ap,
 -                               struct ata_device *dev)
 +static inline u8 ata_dev_knobble(struct ata_device *dev)
  {
 -      return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
 +      return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
  }
  
  /**
   *    ata_dev_configure - Configure the specified ATA/ATAPI device
 - *    @ap: Port on which target device resides
   *    @dev: Target device to configure
   *    @print_info: Enable device info printout
   *
   *    RETURNS:
   *    0 on success, -errno otherwise
   */
 -static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
 -                           int print_info)
 +static int ata_dev_configure(struct ata_device *dev, int print_info)
  {
 +      struct ata_port *ap = dev->ap;
        const u16 *id = dev->id;
        unsigned int xfer_mask;
        int i, rc;
  
        /* print device capabilities */
        if (print_info)
 -              printk(KERN_DEBUG "ata%u: dev %u cfg 49:%04x 82:%04x 83:%04x "
 -                     "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
 -                     ap->id, dev->devno, id[49], id[82], id[83],
 -                     id[84], id[85], id[86], id[87], id[88]);
 +              ata_dev_printk(dev, KERN_DEBUG, "cfg 49:%04x 82:%04x 83:%04x "
 +                             "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
 +                             id[49], id[82], id[83], id[84],
 +                             id[85], id[86], id[87], id[88]);
  
        /* initialize to-be-configured parameters */
        dev->flags &= ~ATA_DFLAG_CFG_MASK;
  
                        /* print device info to dmesg */
                        if (print_info)
 -                              printk(KERN_INFO "ata%u: dev %u ATA-%d, "
 -                                     "max %s, %Lu sectors: %s\n",
 -                                     ap->id, dev->devno,
 -                                     ata_id_major_version(id),
 -                                     ata_mode_string(xfer_mask),
 -                                     (unsigned long long)dev->n_sectors,
 -                                     lba_desc);
 +                              ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
 +                                      "max %s, %Lu sectors: %s\n",
 +                                      ata_id_major_version(id),
 +                                      ata_mode_string(xfer_mask),
 +                                      (unsigned long long)dev->n_sectors,
 +                                      lba_desc);
                } else {
                        /* CHS */
  
  
                        /* print device info to dmesg */
                        if (print_info)
 -                              printk(KERN_INFO "ata%u: dev %u ATA-%d, "
 -                                     "max %s, %Lu sectors: CHS %u/%u/%u\n",
 -                                     ap->id, dev->devno,
 -                                     ata_id_major_version(id),
 -                                     ata_mode_string(xfer_mask),
 -                                     (unsigned long long)dev->n_sectors,
 -                                     dev->cylinders, dev->heads, dev->sectors);
 +                              ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
 +                                      "max %s, %Lu sectors: CHS %u/%u/%u\n",
 +                                      ata_id_major_version(id),
 +                                      ata_mode_string(xfer_mask),
 +                                      (unsigned long long)dev->n_sectors,
 +                                      dev->cylinders, dev->heads, dev->sectors);
                }
  
+               if (dev->id[59] & 0x100) {
+                       dev->multi_count = dev->id[59] & 0xff;
+                       DPRINTK("ata%u: dev %u multi count %u\n",
+                               ap->id, dev->devno, dev->multi_count);
+               }
                dev->cdb_len = 16;
        }
  
        /* ATAPI-specific feature tests */
        else if (dev->class == ATA_DEV_ATAPI) {
+               char *cdb_intr_string = "";
                rc = atapi_cdb_len(id);
                if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
 -                      printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
 +                      ata_dev_printk(dev, KERN_WARNING,
 +                                     "unsupported CDB len\n");
                        rc = -EINVAL;
                        goto err_out_nosup;
                }
                dev->cdb_len = (unsigned int) rc;
  
+               if (ata_id_cdb_intr(dev->id)) {
+                       dev->flags |= ATA_DFLAG_CDB_INTR;
+                       cdb_intr_string = ", CDB intr";
+               }
                /* print device info to dmesg */
                if (print_info)
-                       ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s\n",
-                                      ata_mode_string(xfer_mask));
 -                      printk(KERN_INFO "ata%u: dev %u ATAPI, max %s%s\n",
 -                             ap->id, dev->devno, ata_mode_string(xfer_mask),
 -                             cdb_intr_string);
++                      ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
++                                     ata_mode_string(xfer_mask),
++                                     cdb_intr_string);
        }
  
        ap->host->max_cmd_len = 0;
                                              ap->device[i].cdb_len);
  
        /* limit bridge transfers to udma5, 200 sectors */
 -      if (ata_dev_knobble(ap, dev)) {
 +      if (ata_dev_knobble(dev)) {
                if (print_info)
 -                      printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
 -                             ap->id, dev->devno);
 +                      ata_dev_printk(dev, KERN_INFO,
 +                                     "applying bridge limits\n");
                dev->udma_mask &= ATA_UDMA5;
                dev->max_sectors = ATA_MAX_SECTORS;
        }
@@@ -1428,18 -1405,15 +1442,18 @@@ static int ata_bus_probe(struct ata_por
        if (ap->ops->probe_reset) {
                rc = ap->ops->probe_reset(ap, classes);
                if (rc) {
 -                      printk("ata%u: reset failed (errno=%d)\n", ap->id, rc);
 +                      ata_port_printk(ap, KERN_ERR,
 +                                      "reset failed (errno=%d)\n", rc);
                        return rc;
                }
        } else {
                ap->ops->phy_reset(ap);
  
 -              if (!(ap->flags & ATA_FLAG_DISABLED))
 -                      for (i = 0; i < ATA_MAX_DEVICES; i++)
 +              for (i = 0; i < ATA_MAX_DEVICES; i++) {
 +                      if (!(ap->flags & ATA_FLAG_DISABLED))
                                classes[i] = ap->device[i].class;
 +                      ap->device[i].class = ATA_DEV_UNKNOWN;
 +              }
  
                ata_port_probe(ap);
        }
                if (!ata_dev_enabled(dev))
                        continue;
  
 -              kfree(dev->id);
 -              dev->id = NULL;
 -              rc = ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id);
 +              rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
                if (rc)
                        goto fail;
  
 -              rc = ata_dev_configure(ap, dev, 1);
 +              rc = ata_dev_configure(dev, 1);
                if (rc)
                        goto fail;
        }
  
        /* configure transfer mode */
 -      if (ap->ops->set_mode) {
 -              /* FIXME: make ->set_mode handle no device case and
 -               * return error code and failing device on failure as
 -               * ata_set_mode() does.
 -               */
 -              for (i = 0; i < ATA_MAX_DEVICES; i++)
 -                      if (ata_dev_enabled(&ap->device[i])) {
 -                              ap->ops->set_mode(ap);
 -                              break;
 -                      }
 -              rc = 0;
 -      } else
 -              rc = ata_set_mode(ap, &dev);
 -
 +      rc = ata_set_mode(ap, &dev);
        if (rc) {
                down_xfermask = 1;
                goto fail;
                tries[dev->devno] = 0;
                break;
        case -EIO:
 -              ata_down_sata_spd_limit(ap);
 +              sata_down_spd_limit(ap);
                /* fall through */
        default:
                tries[dev->devno]--;
                if (down_xfermask &&
 -                  ata_down_xfermask_limit(ap, dev, tries[dev->devno] == 1))
 +                  ata_down_xfermask_limit(dev, tries[dev->devno] == 1))
                        tries[dev->devno] = 0;
        }
  
        if (!tries[dev->devno]) {
 -              ata_down_xfermask_limit(ap, dev, 1);
 -              ata_dev_disable(ap, dev);
 +              ata_down_xfermask_limit(dev, 1);
 +              ata_dev_disable(dev);
        }
  
        goto retry;
@@@ -1536,19 -1525,21 +1550,19 @@@ static void sata_print_link_status(stru
  {
        u32 sstatus, scontrol, tmp;
  
 -      if (!ap->ops->scr_read)
 +      if (sata_scr_read(ap, SCR_STATUS, &sstatus))
                return;
 +      sata_scr_read(ap, SCR_CONTROL, &scontrol);
  
 -      sstatus = scr_read(ap, SCR_STATUS);
 -      scontrol = scr_read(ap, SCR_CONTROL);
 -
 -      if (sata_dev_present(ap)) {
 +      if (ata_port_online(ap)) {
                tmp = (sstatus >> 4) & 0xf;
 -              printk(KERN_INFO
 -                     "ata%u: SATA link up %s (SStatus %X SControl %X)\n",
 -                     ap->id, sata_spd_string(tmp), sstatus, scontrol);
 +              ata_port_printk(ap, KERN_INFO,
 +                              "SATA link up %s (SStatus %X SControl %X)\n",
 +                              sata_spd_string(tmp), sstatus, scontrol);
        } else {
 -              printk(KERN_INFO
 -                     "ata%u: SATA link down (SStatus %X SControl %X)\n",
 -                     ap->id, sstatus, scontrol);
 +              ata_port_printk(ap, KERN_INFO,
 +                              "SATA link down (SStatus %X SControl %X)\n",
 +                              sstatus, scontrol);
        }
  }
  
@@@ -1571,18 -1562,17 +1585,18 @@@ void __sata_phy_reset(struct ata_port *
  
        if (ap->flags & ATA_FLAG_SATA_RESET) {
                /* issue phy wake/reset */
 -              scr_write_flush(ap, SCR_CONTROL, 0x301);
 +              sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
                /* Couldn't find anything in SATA I/II specs, but
                 * AHCI-1.1 10.4.2 says at least 1 ms. */
                mdelay(1);
        }
 -      scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
 +      /* phy wake/clear reset */
 +      sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
  
        /* wait for phy to become ready, if necessary */
        do {
                msleep(200);
 -              sstatus = scr_read(ap, SCR_STATUS);
 +              sata_scr_read(ap, SCR_STATUS, &sstatus);
                if ((sstatus & 0xf) != 1)
                        break;
        } while (time_before(jiffies, timeout));
        sata_print_link_status(ap);
  
        /* TODO: phy layer with polling, timeouts, etc. */
 -      if (sata_dev_present(ap))
 +      if (!ata_port_offline(ap))
                ata_port_probe(ap);
        else
                ata_port_disable(ap);
@@@ -1628,15 -1618,15 +1642,15 @@@ void sata_phy_reset(struct ata_port *ap
  
  /**
   *    ata_dev_pair            -       return other device on cable
 - *    @ap: port
   *    @adev: device
   *
   *    Obtain the other device on the same cable, or if none is
   *    present NULL is returned
   */
  
 -struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev)
 +struct ata_device *ata_dev_pair(struct ata_device *adev)
  {
 +      struct ata_port *ap = adev->ap;
        struct ata_device *pair = &ap->device[1 - adev->devno];
        if (!ata_dev_enabled(pair))
                return NULL;
@@@ -1664,12 -1654,12 +1678,12 @@@ void ata_port_disable(struct ata_port *
  }
  
  /**
 - *    ata_down_sata_spd_limit - adjust SATA spd limit downward
 + *    sata_down_spd_limit - adjust SATA spd limit downward
   *    @ap: Port to adjust SATA spd limit for
   *
   *    Adjust SATA spd limit of @ap downward.  Note that this
   *    function only adjusts the limit.  The change must be applied
 - *    using ata_set_sata_spd().
 + *    using sata_set_spd().
   *
   *    LOCKING:
   *    Inherited from caller.
   *    RETURNS:
   *    0 on success, negative errno on failure
   */
 -int ata_down_sata_spd_limit(struct ata_port *ap)
 +int sata_down_spd_limit(struct ata_port *ap)
  {
 -      u32 spd, mask;
 -      int highbit;
 +      u32 sstatus, spd, mask;
 +      int rc, highbit;
  
 -      if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read)
 -              return -EOPNOTSUPP;
 +      rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
 +      if (rc)
 +              return rc;
  
        mask = ap->sata_spd_limit;
        if (mask <= 1)
        highbit = fls(mask) - 1;
        mask &= ~(1 << highbit);
  
 -      spd = (scr_read(ap, SCR_STATUS) >> 4) & 0xf;
 +      spd = (sstatus >> 4) & 0xf;
        if (spd <= 1)
                return -EINVAL;
        spd--;
  
        ap->sata_spd_limit = mask;
  
 -      printk(KERN_WARNING "ata%u: limiting SATA link speed to %s\n",
 -             ap->id, sata_spd_string(fls(mask)));
 +      ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n",
 +                      sata_spd_string(fls(mask)));
  
        return 0;
  }
  
 -static int __ata_set_sata_spd_needed(struct ata_port *ap, u32 *scontrol)
 +static int __sata_set_spd_needed(struct ata_port *ap, u32 *scontrol)
  {
        u32 spd, limit;
  
  }
  
  /**
 - *    ata_set_sata_spd_needed - is SATA spd configuration needed
 + *    sata_set_spd_needed - is SATA spd configuration needed
   *    @ap: Port in question
   *
   *    Test whether the spd limit in SControl matches
   *    RETURNS:
   *    1 if SATA spd configuration is needed, 0 otherwise.
   */
 -int ata_set_sata_spd_needed(struct ata_port *ap)
 +int sata_set_spd_needed(struct ata_port *ap)
  {
        u32 scontrol;
  
 -      if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read)
 +      if (sata_scr_read(ap, SCR_CONTROL, &scontrol))
                return 0;
  
 -      scontrol = scr_read(ap, SCR_CONTROL);
 -
 -      return __ata_set_sata_spd_needed(ap, &scontrol);
 +      return __sata_set_spd_needed(ap, &scontrol);
  }
  
  /**
 - *    ata_set_sata_spd - set SATA spd according to spd limit
 + *    sata_set_spd - set SATA spd according to spd limit
   *    @ap: Port to set SATA spd for
   *
   *    Set SATA spd of @ap according to sata_spd_limit.
   *
   *    RETURNS:
   *    0 if spd doesn't need to be changed, 1 if spd has been
 - *    changed.  -EOPNOTSUPP if SCR registers are inaccessible.
 + *    changed.  Negative errno if SCR registers are inaccessible.
   */
 -int ata_set_sata_spd(struct ata_port *ap)
 +int sata_set_spd(struct ata_port *ap)
  {
        u32 scontrol;
 +      int rc;
  
 -      if (ap->cbl != ATA_CBL_SATA || !ap->ops->scr_read)
 -              return -EOPNOTSUPP;
 +      if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
 +              return rc;
  
 -      scontrol = scr_read(ap, SCR_CONTROL);
 -      if (!__ata_set_sata_spd_needed(ap, &scontrol))
 +      if (!__sata_set_spd_needed(ap, &scontrol))
                return 0;
  
 -      scr_write(ap, SCR_CONTROL, scontrol);
 +      if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
 +              return rc;
 +
        return 1;
  }
  
@@@ -1928,6 -1917,7 +1942,6 @@@ int ata_timing_compute(struct ata_devic
  
  /**
   *    ata_down_xfermask_limit - adjust dev xfer masks downward
 - *    @ap: Port associated with device @dev
   *    @dev: Device to adjust xfer masks
   *    @force_pio0: Force PIO0
   *
   *    RETURNS:
   *    0 on success, negative errno on failure
   */
 -int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev,
 -                          int force_pio0)
 +int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
  {
        unsigned long xfer_mask;
        int highbit;
        ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
                            &dev->udma_mask);
  
 -      printk(KERN_WARNING "ata%u: dev %u limiting speed to %s\n",
 -             ap->id, dev->devno, ata_mode_string(xfer_mask));
 +      ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n",
 +                     ata_mode_string(xfer_mask));
  
        return 0;
  
        return -EINVAL;
  }
  
 -static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
 +static int ata_dev_set_mode(struct ata_device *dev)
  {
        unsigned int err_mask;
        int rc;
        if (dev->xfer_shift == ATA_SHIFT_PIO)
                dev->flags |= ATA_DFLAG_PIO;
  
 -      err_mask = ata_dev_set_xfermode(ap, dev);
 +      err_mask = ata_dev_set_xfermode(dev);
        if (err_mask) {
 -              printk(KERN_ERR
 -                     "ata%u: failed to set xfermode (err_mask=0x%x)\n",
 -                     ap->id, err_mask);
 +              ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
 +                             "(err_mask=0x%x)\n", err_mask);
                return -EIO;
        }
  
 -      rc = ata_dev_revalidate(ap, dev, 0);
 +      rc = ata_dev_revalidate(dev, 0);
        if (rc)
                return rc;
  
        DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
                dev->xfer_shift, (int)dev->xfer_mode);
  
 -      printk(KERN_INFO "ata%u: dev %u configured for %s\n",
 -             ap->id, dev->devno,
 -             ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
 +      ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
 +                     ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
        return 0;
  }
  
@@@ -2022,20 -2015,6 +2036,20 @@@ int ata_set_mode(struct ata_port *ap, s
        struct ata_device *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_enabled(&ap->device[i])) {
 +                              ap->ops->set_mode(ap);
 +                              break;
 +                      }
 +              }
 +              return 0;
 +      }
 +
        /* step 1: calculate xfer_mask */
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                unsigned int pio_mask, dma_mask;
                if (!ata_dev_enabled(dev))
                        continue;
  
 -              ata_dev_xfermask(ap, dev);
 +              ata_dev_xfermask(dev);
  
                pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
                dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
                        continue;
  
                if (!dev->pio_mode) {
 -                      printk(KERN_WARNING "ata%u: dev %u no PIO support\n",
 -                             ap->id, dev->devno);
 +                      ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
                        rc = -EINVAL;
                        goto out;
                }
                if (!ata_dev_enabled(dev))
                        continue;
  
 -              rc = ata_dev_set_mode(ap, dev);
 +              rc = ata_dev_set_mode(dev);
                if (rc)
                        goto out;
        }
@@@ -2165,8 -2145,8 +2179,8 @@@ unsigned int ata_busy_sleep (struct ata
        }
  
        if (status & ATA_BUSY)
 -              printk(KERN_WARNING "ata%u is slow to respond, "
 -                     "please be patient\n", ap->id);
 +              ata_port_printk(ap, KERN_WARNING,
 +                              "port is slow to respond, please be patient\n");
  
        timeout = timer_start + tmout;
        while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
        }
  
        if (status & ATA_BUSY) {
 -              printk(KERN_ERR "ata%u failed to respond (%lu secs)\n",
 -                     ap->id, tmout / HZ);
 +              ata_port_printk(ap, KERN_ERR, "port failed to respond "
 +                              "(%lu secs)\n", tmout / HZ);
                return 1;
        }
  
@@@ -2269,7 -2249,7 +2283,7 @@@ static unsigned int ata_bus_softreset(s
         * pulldown resistor.
         */
        if (ata_check_status(ap) == 0xFF) {
 -              printk(KERN_ERR "ata%u: SRST failed (status 0xFF)\n", ap->id);
 +              ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
                return AC_ERR_OTHER;
        }
  
@@@ -2363,7 -2343,7 +2377,7 @@@ void ata_bus_reset(struct ata_port *ap
        return;
  
  err_out:
 -      printk(KERN_ERR "ata%u: disabling port\n", ap->id);
 +      ata_port_printk(ap, KERN_ERR, "disabling port\n");
        ap->ops->port_disable(ap);
  
        DPRINTK("EXIT\n");
@@@ -2373,26 -2353,20 +2387,26 @@@ static int sata_phy_resume(struct ata_p
  {
        unsigned long timeout = jiffies + (HZ * 5);
        u32 scontrol, sstatus;
 +      int rc;
 +
 +      if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
 +              return rc;
  
 -      scontrol = scr_read(ap, SCR_CONTROL);
        scontrol = (scontrol & 0x0f0) | 0x300;
 -      scr_write_flush(ap, SCR_CONTROL, scontrol);
 +
 +      if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
 +              return rc;
  
        /* Wait for phy to become ready, if necessary. */
        do {
                msleep(200);
 -              sstatus = scr_read(ap, SCR_STATUS);
 +              if ((rc = sata_scr_read(ap, SCR_STATUS, &sstatus)))
 +                      return rc;
                if ((sstatus & 0xf) != 1)
                        return 0;
        } while (time_before(jiffies, timeout));
  
 -      return -1;
 +      return -EBUSY;
  }
  
  /**
   */
  void ata_std_probeinit(struct ata_port *ap)
  {
 -      if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) {
 -              u32 spd;
 -
 -              /* set cable type and resume link */
 -              ap->cbl = ATA_CBL_SATA;
 -              sata_phy_resume(ap);
 +      u32 scontrol;
  
 -              /* init sata_spd_limit to the current value */
 -              spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4;
 -              if (spd)
 -                      ap->sata_spd_limit &= (1 << spd) - 1;
 +      /* resume link */
 +      sata_phy_resume(ap);
  
 -              /* wait for device */
 -              if (sata_dev_present(ap))
 -                      ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
 +      /* init sata_spd_limit to the current value */
 +      if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
 +              int spd = (scontrol >> 4) & 0xf;
 +              ap->sata_spd_limit &= (1 << spd) - 1;
        }
 +
 +      /* wait for device */
 +      if (ata_port_online(ap))
 +              ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
  }
  
  /**
@@@ -2448,7 -2424,7 +2462,7 @@@ int ata_std_softreset(struct ata_port *
  
        DPRINTK("ENTER\n");
  
 -      if (ap->ops->scr_read && !sata_dev_present(ap)) {
 +      if (ata_port_offline(ap)) {
                classes[0] = ATA_DEV_NONE;
                goto out;
        }
        DPRINTK("about to softreset, devmask=%x\n", devmask);
        err_mask = ata_bus_softreset(ap, devmask);
        if (err_mask) {
 -              printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n",
 -                     ap->id, err_mask);
 +              ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
 +                              err_mask);
                return -EIO;
        }
  
  int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
  {
        u32 scontrol;
 +      int rc;
  
        DPRINTK("ENTER\n");
  
 -      if (ata_set_sata_spd_needed(ap)) {
 +      if (sata_set_spd_needed(ap)) {
                /* SATA spec says nothing about how to reconfigure
                 * spd.  To be on the safe side, turn off phy during
                 * reconfiguration.  This works for at least ICH7 AHCI
                 * and Sil3124.
                 */
 -              scontrol = scr_read(ap, SCR_CONTROL);
 +              if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
 +                      return rc;
 +
                scontrol = (scontrol & 0x0f0) | 0x302;
 -              scr_write_flush(ap, SCR_CONTROL, scontrol);
  
 -              ata_set_sata_spd(ap);
 +              if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
 +                      return rc;
 +
 +              sata_set_spd(ap);
        }
  
        /* issue phy wake/reset */
 -      scontrol = scr_read(ap, SCR_CONTROL);
 +      if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
 +              return rc;
 +
        scontrol = (scontrol & 0x0f0) | 0x301;
 -      scr_write_flush(ap, SCR_CONTROL, scontrol);
 +
 +      if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
 +              return rc;
  
        /* Couldn't find anything in SATA I/II specs, but AHCI-1.1
         * 10.4.2 says at least 1 ms.
        sata_phy_resume(ap);
  
        /* TODO: phy layer with polling, timeouts, etc. */
 -      if (!sata_dev_present(ap)) {
 +      if (ata_port_offline(ap)) {
                *class = ATA_DEV_NONE;
                DPRINTK("EXIT, link offline\n");
                return 0;
        }
  
        if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
 -              printk(KERN_ERR
 -                     "ata%u: COMRESET failed (device not ready)\n", ap->id);
 +              ata_port_printk(ap, KERN_ERR,
 +                              "COMRESET failed (device not ready)\n");
                return -EIO;
        }
  
   */
  void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
  {
 +      u32 serror;
 +
        DPRINTK("ENTER\n");
  
        /* print link status */
 -      if (ap->cbl == ATA_CBL_SATA)
 -              sata_print_link_status(ap);
 +      sata_print_link_status(ap);
 +
 +      /* clear SError */
 +      if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
 +              sata_scr_write(ap, SCR_ERROR, serror);
  
        /* re-enable interrupts */
 -      if (ap->ioaddr.ctl_addr)        /* FIXME: hack. create a hook instead */
 -              ata_irq_on(ap);
 +      if (!ap->ops->error_handler) {
 +              /* FIXME: hack. create a hook instead */
 +              if (ap->ioaddr.ctl_addr)
 +                      ata_irq_on(ap);
 +      }
  
        /* is double-select really necessary? */
        if (classes[0] != ATA_DEV_NONE)
@@@ -2634,7 -2593,7 +2648,7 @@@ int ata_std_probe_reset(struct ata_por
        ata_reset_fn_t hardreset;
  
        hardreset = NULL;
 -      if (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read)
 +      if (sata_scr_valid(ap))
                hardreset = sata_std_hardreset;
  
        return ata_drive_probe_reset(ap, ata_std_probeinit,
  }
  
  int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
 -               ata_postreset_fn_t postreset, unsigned int *classes)
 +               unsigned int *classes)
  {
        int i, rc;
  
                        if (classes[i] == ATA_DEV_UNKNOWN)
                                classes[i] = ATA_DEV_NONE;
  
 -      if (postreset)
 -              postreset(ap, classes);
 -
        return 0;
  }
  
@@@ -2706,17 -2668,15 +2720,17 @@@ int ata_drive_probe_reset(struct ata_po
  {
        int rc = -EINVAL;
  
 +      ata_eh_freeze_port(ap);
 +
        if (probeinit)
                probeinit(ap);
  
 -      if (softreset && !ata_set_sata_spd_needed(ap)) {
 -              rc = ata_do_reset(ap, softreset, postreset, classes);
 +      if (softreset && !sata_set_spd_needed(ap)) {
 +              rc = ata_do_reset(ap, softreset, classes);
                if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN)
                        goto done;
 -              printk(KERN_INFO "ata%u: softreset failed, will try "
 -                     "hardreset in 5 secs\n", ap->id);
 +              ata_port_printk(ap, KERN_INFO, "softreset failed, "
 +                              "will try hardreset in 5 secs\n");
                ssleep(5);
        }
  
                goto done;
  
        while (1) {
 -              rc = ata_do_reset(ap, hardreset, postreset, classes);
 +              rc = ata_do_reset(ap, hardreset, classes);
                if (rc == 0) {
                        if (classes[0] != ATA_DEV_UNKNOWN)
                                goto done;
                        break;
                }
  
 -              if (ata_down_sata_spd_limit(ap))
 +              if (sata_down_spd_limit(ap))
                        goto done;
  
 -              printk(KERN_INFO "ata%u: hardreset failed, will retry "
 -                     "in 5 secs\n", ap->id);
 +              ata_port_printk(ap, KERN_INFO, "hardreset failed, "
 +                              "will retry in 5 secs\n");
                ssleep(5);
        }
  
        if (softreset) {
 -              printk(KERN_INFO "ata%u: hardreset succeeded without "
 -                     "classification, will retry softreset in 5 secs\n",
 -                     ap->id);
 +              ata_port_printk(ap, KERN_INFO,
 +                              "hardreset succeeded without classification, "
 +                              "will retry softreset in 5 secs\n");
                ssleep(5);
  
 -              rc = ata_do_reset(ap, softreset, postreset, classes);
 +              rc = ata_do_reset(ap, softreset, classes);
        }
  
   done:
 -      if (rc == 0 && classes[0] == ATA_DEV_UNKNOWN)
 -              rc = -ENODEV;
 +      if (rc == 0) {
 +              if (postreset)
 +                      postreset(ap, classes);
 +
 +              ata_eh_thaw_port(ap);
 +
 +              if (classes[0] == ATA_DEV_UNKNOWN)
 +                      rc = -ENODEV;
 +      }
        return rc;
  }
  
  /**
   *    ata_dev_same_device - Determine whether new ID matches configured device
 - *    @ap: port on which the device to compare against resides
   *    @dev: device to compare against
   *    @new_class: class of the new device
   *    @new_id: IDENTIFY page of the new device
   *    RETURNS:
   *    1 if @dev matches @new_class and @new_id, 0 otherwise.
   */
 -static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev,
 -                             unsigned int new_class, const u16 *new_id)
 +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];
        u64 new_n_sectors;
  
        if (dev->class != new_class) {
 -              printk(KERN_INFO
 -                     "ata%u: dev %u class mismatch %d != %d\n",
 -                     ap->id, dev->devno, dev->class, new_class);
 +              ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
 +                             dev->class, new_class);
                return 0;
        }
  
        new_n_sectors = ata_id_n_sectors(new_id);
  
        if (strcmp(model[0], model[1])) {
 -              printk(KERN_INFO
 -                     "ata%u: dev %u model number mismatch '%s' != '%s'\n",
 -                     ap->id, dev->devno, model[0], model[1]);
 +              ata_dev_printk(dev, KERN_INFO, "model number mismatch "
 +                             "'%s' != '%s'\n", model[0], model[1]);
                return 0;
        }
  
        if (strcmp(serial[0], serial[1])) {
 -              printk(KERN_INFO
 -                     "ata%u: dev %u serial number mismatch '%s' != '%s'\n",
 -                     ap->id, dev->devno, serial[0], serial[1]);
 +              ata_dev_printk(dev, KERN_INFO, "serial number mismatch "
 +                             "'%s' != '%s'\n", serial[0], serial[1]);
                return 0;
        }
  
        if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
 -              printk(KERN_INFO
 -                     "ata%u: dev %u n_sectors mismatch %llu != %llu\n",
 -                     ap->id, dev->devno, (unsigned long long)dev->n_sectors,
 -                     (unsigned long long)new_n_sectors);
 +              ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
 +                             "%llu != %llu\n",
 +                             (unsigned long long)dev->n_sectors,
 +                             (unsigned long long)new_n_sectors);
                return 0;
        }
  
  
  /**
   *    ata_dev_revalidate - Revalidate ATA device
 - *    @ap: port on which the device to revalidate resides
   *    @dev: device to revalidate
   *    @post_reset: is this revalidation after reset?
   *
   *    RETURNS:
   *    0 on success, negative errno otherwise
   */
 -int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
 -                     int post_reset)
 +int ata_dev_revalidate(struct ata_device *dev, int post_reset)
  {
        unsigned int class = dev->class;
 -      u16 *id = NULL;
 +      u16 *id = (void *)dev->ap->sector_buf;
        int rc;
  
        if (!ata_dev_enabled(dev)) {
                goto fail;
        }
  
 -      /* allocate & read ID data */
 -      rc = ata_dev_read_id(ap, dev, &class, post_reset, &id);
 +      /* read ID data */
 +      rc = ata_dev_read_id(dev, &class, post_reset, id);
        if (rc)
                goto fail;
  
        /* is the device still there? */
 -      if (!ata_dev_same_device(ap, dev, class, id)) {
 +      if (!ata_dev_same_device(dev, class, id)) {
                rc = -ENODEV;
                goto fail;
        }
  
 -      kfree(dev->id);
 -      dev->id = id;
 +      memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
  
        /* configure device according to the new ID */
 -      rc = ata_dev_configure(ap, dev, 0);
 +      rc = ata_dev_configure(dev, 0);
        if (rc == 0)
                return 0;
  
   fail:
 -      printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n",
 -             ap->id, dev->devno, rc);
 -      kfree(id);
 +      ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
        return rc;
  }
  
@@@ -2939,6 -2901,7 +2953,6 @@@ static int ata_dma_blacklisted(const st
  
  /**
   *    ata_dev_xfermask - Compute supported xfermask of the given device
 - *    @ap: Port on which the device to compute xfermask for resides
   *    @dev: Device to compute xfermask for
   *
   *    Compute supported xfermask of @dev and store it in
   *    LOCKING:
   *    None.
   */
 -static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
 +static void ata_dev_xfermask(struct ata_device *dev)
  {
 +      struct ata_port *ap = dev->ap;
        struct ata_host_set *hs = ap->host_set;
        unsigned long xfer_mask;
        int i;
        }
  
        if (ata_dma_blacklisted(dev))
 -              printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, "
 -                     "disabling DMA\n", ap->id, dev->devno);
 +              ata_dev_printk(dev, KERN_WARNING,
 +                             "device is on DMA blacklist, disabling DMA\n");
  
        if (hs->flags & ATA_HOST_SIMPLEX) {
                if (hs->simplex_claimed)
  
  /**
   *    ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command
 - *    @ap: Port associated with device @dev
   *    @dev: Device to which command will be sent
   *
   *    Issue SET FEATURES - XFER MODE command to device @dev
   *    0 on success, AC_ERR_* mask otherwise.
   */
  
 -static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
 -                                       struct ata_device *dev)
 +static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
  {
        struct ata_taskfile tf;
        unsigned int err_mask;
        /* set up set-features taskfile */
        DPRINTK("set features - xfer mode\n");
  
 -      ata_tf_init(ap, &tf, dev->devno);
 +      ata_tf_init(dev, &tf);
        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;
  
 -      err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0);
 +      err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
  
        DPRINTK("EXIT, err_mask=%x\n", err_mask);
        return err_mask;
  
  /**
   *    ata_dev_init_params - Issue INIT DEV PARAMS command
 - *    @ap: Port associated with device @dev
   *    @dev: Device to which command will be sent
 + *    @heads: Number of heads
 + *    @sectors: Number of sectors
   *
   *    LOCKING:
   *    Kernel thread context (may sleep)
   *    RETURNS:
   *    0 on success, AC_ERR_* mask otherwise.
   */
 -
 -static unsigned int ata_dev_init_params(struct ata_port *ap,
 -                                      struct ata_device *dev,
 -                                      u16 heads,
 -                                      u16 sectors)
 +static unsigned int ata_dev_init_params(struct ata_device *dev,
 +                                      u16 heads, u16 sectors)
  {
        struct ata_taskfile tf;
        unsigned int err_mask;
        /* set up init dev params taskfile */
        DPRINTK("init dev params \n");
  
 -      ata_tf_init(ap, &tf, dev->devno);
 +      ata_tf_init(dev, &tf);
        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 */
  
 -      err_mask = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0);
 +      err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
  
        DPRINTK("EXIT, err_mask=%x\n", err_mask);
        return err_mask;
@@@ -3211,6 -3177,15 +3225,15 @@@ int ata_check_atapi_dma(struct ata_queu
        if (ap->ops->check_atapi_dma)
                rc = ap->ops->check_atapi_dma(qc);
  
+       /* We don't support polling DMA.
+        * Use PIO if the LLDD handles only interrupts in
+        * the HSM_ST_LAST state and the ATAPI device
+        * generates CDB interrupts.
+        */
+       if ((ap->flags & ATA_FLAG_PIO_POLLING) &&
+           (qc->dev->flags & ATA_DFLAG_CDB_INTR))
+               rc = 1;
        return rc;
  }
  /**
@@@ -3446,133 -3421,18 +3469,32 @@@ skip_map
   *    LOCKING:
   *    None.  (grabs host lock)
   */
 -
  void ata_poll_qc_complete(struct ata_queued_cmd *qc)
  {
        struct ata_port *ap = qc->ap;
        unsigned long flags;
  
        spin_lock_irqsave(&ap->host_set->lock, flags);
 -      ata_irq_on(ap);
 -      ata_qc_complete(qc);
 +
 +      if (ap->ops->error_handler) {
 +              /* EH might have kicked in while host_set lock is released */
 +              qc = ata_qc_from_tag(ap, qc->tag);
 +              if (qc) {
 +                      if (!(qc->err_mask & AC_ERR_HSM)) {
-                               ap->flags &= ~ATA_FLAG_NOINTR;
 +                              ata_irq_on(ap);
 +                              ata_qc_complete(qc);
 +                      } else
 +                              ata_port_freeze(ap);
 +              }
 +      } else {
 +              /* old EH */
-               ap->flags &= ~ATA_FLAG_NOINTR;
 +              ata_irq_on(ap);
 +              ata_qc_complete(qc);
 +      }
 +
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
  }
  
- /**
-  *    ata_pio_poll - poll using PIO, depending on current state
-  *    @qc: qc in progress
-  *
-  *    LOCKING:
-  *    None.  (executing in kernel thread context)
-  *
-  *    RETURNS:
-  *    timeout value to use
-  */
- static unsigned long ata_pio_poll(struct ata_queued_cmd *qc)
- {
-       struct ata_port *ap = qc->ap;
-       u8 status;
-       unsigned int poll_state = HSM_ST_UNKNOWN;
-       unsigned int reg_state = HSM_ST_UNKNOWN;
-       switch (ap->hsm_task_state) {
-       case HSM_ST:
-       case HSM_ST_POLL:
-               poll_state = HSM_ST_POLL;
-               reg_state = HSM_ST;
-               break;
-       case HSM_ST_LAST:
-       case HSM_ST_LAST_POLL:
-               poll_state = HSM_ST_LAST_POLL;
-               reg_state = HSM_ST_LAST;
-               break;
-       default:
-               BUG();
-               break;
-       }
-       status = ata_chk_status(ap);
-       if (status & ATA_BUSY) {
-               if (time_after(jiffies, ap->pio_task_timeout)) {
-                       qc->err_mask |= AC_ERR_TIMEOUT;
-                       ap->hsm_task_state = HSM_ST_TMOUT;
-                       return 0;
-               }
-               ap->hsm_task_state = poll_state;
-               return ATA_SHORT_PAUSE;
-       }
-       ap->hsm_task_state = reg_state;
-       return 0;
- }
- /**
-  *    ata_pio_complete - check if drive is busy or idle
-  *    @qc: qc to complete
-  *
-  *    LOCKING:
-  *    None.  (executing in kernel thread context)
-  *
-  *    RETURNS:
-  *    Non-zero if qc completed, zero otherwise.
-  */
- static int ata_pio_complete(struct ata_queued_cmd *qc)
- {
-       struct ata_port *ap = qc->ap;
-       u8 drv_stat;
-       /*
-        * This is purely heuristic.  This is a fast path.  Sometimes when
-        * we enter, BSY will be cleared in a chk-status or two.  If not,
-        * the drive is probably seeking or something.  Snooze for a couple
-        * msecs, then chk-status again.  If still busy, fall back to
-        * HSM_ST_POLL state.
-        */
-       drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
-       if (drv_stat & ATA_BUSY) {
-               msleep(2);
-               drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
-               if (drv_stat & ATA_BUSY) {
-                       ap->hsm_task_state = HSM_ST_LAST_POLL;
-                       ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
-                       return 0;
-               }
-       }
-       drv_stat = ata_wait_idle(ap);
-       if (!ata_ok(drv_stat)) {
-               qc->err_mask |= __ac_err_mask(drv_stat);
-               ap->hsm_task_state = HSM_ST_ERR;
-               return 0;
-       }
-       ap->hsm_task_state = HSM_ST_IDLE;
-       WARN_ON(qc->err_mask);
-       ata_poll_qc_complete(qc);
-       /* another command may start at this point */
-       return 1;
- }
  /**
   *    swap_buf_le16 - swap halves of 16-bit words in place
   *    @buf:  Buffer to swap
@@@ -3741,7 -3601,23 +3663,23 @@@ static void ata_pio_sector(struct ata_q
        page = nth_page(page, (offset >> PAGE_SHIFT));
        offset %= PAGE_SIZE;
  
-       buf = kmap(page) + offset;
+       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+       if (PageHighMem(page)) {
+               unsigned long flags;
+               local_irq_save(flags);
+               buf = kmap_atomic(page, KM_IRQ0);
+               /* do the actual data transfer */
+               ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write);
+               kunmap_atomic(buf, KM_IRQ0);
+               local_irq_restore(flags);
+       } else {
+               buf = page_address(page);
+               ata_data_xfer(ap, buf + offset, ATA_SECT_SIZE, do_write);
+       }
  
        qc->cursect++;
        qc->cursg_ofs++;
                qc->cursg++;
                qc->cursg_ofs = 0;
        }
+ }
  
-       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+ /**
+  *    ata_pio_sectors - Transfer one or many 512-byte sectors.
+  *    @qc: Command on going
+  *
+  *    Transfer one or many ATA_SECT_SIZE of data from/to the 
+  *    ATA device for the DRQ request.
+  *
+  *    LOCKING:
+  *    Inherited from caller.
+  */
  
-       /* do the actual data transfer */
-       do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
-       ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write);
+ static void ata_pio_sectors(struct ata_queued_cmd *qc)
+ {
+       if (is_multi_taskfile(&qc->tf)) {
+               /* READ/WRITE MULTIPLE */
+               unsigned int nsect;
+               WARN_ON(qc->dev->multi_count == 0);
  
-       kunmap(page);
+               nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+               while (nsect--)
+                       ata_pio_sector(qc);
+       } else
+               ata_pio_sector(qc);
+ }
+ /**
+  *    atapi_send_cdb - Write CDB bytes to hardware
+  *    @ap: Port to which ATAPI device is attached.
+  *    @qc: Taskfile currently active
+  *
+  *    When device has indicated its readiness to accept
+  *    a CDB, this function is called.  Send the CDB.
+  *
+  *    LOCKING:
+  *    caller.
+  */
+ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+ {
+       /* send SCSI cdb */
+       DPRINTK("send cdb\n");
+       WARN_ON(qc->dev->cdb_len < 12);
+       ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+       ata_altstatus(ap); /* flush */
+       switch (qc->tf.protocol) {
+       case ATA_PROT_ATAPI:
+               ap->hsm_task_state = HSM_ST;
+               break;
+       case ATA_PROT_ATAPI_NODATA:
+               ap->hsm_task_state = HSM_ST_LAST;
+               break;
+       case ATA_PROT_ATAPI_DMA:
+               ap->hsm_task_state = HSM_ST_LAST;
+               /* initiate bmdma */
+               ap->ops->bmdma_start(qc);
+               break;
+       }
  }
  
  /**
@@@ -3798,8 -3728,8 +3790,8 @@@ next_sg
                unsigned int i;
  
                if (words) /* warning if bytes > 1 */
 -                      printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
 -                             ap->id, bytes);
 +                      ata_dev_printk(qc->dev, KERN_WARNING,
 +                                     "%u bytes trailing data\n", bytes);
  
                for (i = 0; i < words; i++)
                        ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
        /* don't cross page boundaries */
        count = min(count, (unsigned int)PAGE_SIZE - offset);
  
-       buf = kmap(page) + offset;
+       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+       if (PageHighMem(page)) {
+               unsigned long flags;
+               local_irq_save(flags);
+               buf = kmap_atomic(page, KM_IRQ0);
+               /* do the actual data transfer */
+               ata_data_xfer(ap, buf + offset, count, do_write);
+               kunmap_atomic(buf, KM_IRQ0);
+               local_irq_restore(flags);
+       } else {
+               buf = page_address(page);
+               ata_data_xfer(ap, buf + offset, count, do_write);
+       }
  
        bytes -= count;
        qc->curbytes += count;
                qc->cursg_ofs = 0;
        }
  
-       DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-       /* do the actual data transfer */
-       ata_data_xfer(ap, buf, count, do_write);
-       kunmap(page);
        if (bytes)
                goto next_sg;
  }
@@@ -3877,197 -3816,308 +3878,307 @@@ static void atapi_pio_bytes(struct ata_
        if (do_write != i_write)
                goto err_out;
  
+       VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes);
        __atapi_pio_bytes(qc, bytes);
  
        return;
  
  err_out:
 -      printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
 -            ap->id, dev->devno);
 +      ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n");
        qc->err_mask |= AC_ERR_HSM;
        ap->hsm_task_state = HSM_ST_ERR;
  }
  
  /**
-  *    ata_pio_block - start PIO on a block
-  *    @qc: qc to transfer block for
+  *    ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
+  *    @ap: the target ata_port
+  *    @qc: qc on going
   *
-  *    LOCKING:
-  *    None.  (executing in kernel thread context)
+  *    RETURNS:
+  *    1 if ok in workqueue, 0 otherwise.
   */
- static void ata_pio_block(struct ata_queued_cmd *qc)
+ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
  {
-       struct ata_port *ap = qc->ap;
-       u8 status;
+       if (qc->tf.flags & ATA_TFLAG_POLLING)
+               return 1;
  
-       /*
-        * This is purely heuristic.  This is a fast path.
-        * Sometimes when we enter, BSY will be cleared in
-        * a chk-status or two.  If not, the drive is probably seeking
-        * or something.  Snooze for a couple msecs, then
-        * chk-status again.  If still busy, fall back to
-        * HSM_ST_POLL state.
-        */
-       status = ata_busy_wait(ap, ATA_BUSY, 5);
-       if (status & ATA_BUSY) {
-               msleep(2);
-               status = ata_busy_wait(ap, ATA_BUSY, 10);
-               if (status & ATA_BUSY) {
-                       ap->hsm_task_state = HSM_ST_POLL;
-                       ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
-                       return;
-               }
-       }
+       if (ap->hsm_task_state == HSM_ST_FIRST) {
+               if (qc->tf.protocol == ATA_PROT_PIO &&
+                   (qc->tf.flags & ATA_TFLAG_WRITE))
+                   return 1;
  
-       /* check error */
-       if (status & (ATA_ERR | ATA_DF)) {
-               qc->err_mask |= AC_ERR_DEV;
-               ap->hsm_task_state = HSM_ST_ERR;
-               return;
+               if (is_atapi_taskfile(&qc->tf) &&
+                   !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       return 1;
        }
  
-       /* transfer data if any */
-       if (is_atapi_taskfile(&qc->tf)) {
-               /* DRQ=0 means no more data to transfer */
-               if ((status & ATA_DRQ) == 0) {
-                       ap->hsm_task_state = HSM_ST_LAST;
-                       return;
-               }
+       return 0;
+ }
  
-               atapi_pio_bytes(qc);
-       } else {
-               /* handle BSY=0, DRQ=0 as error */
-               if ((status & ATA_DRQ) == 0) {
+ /**
+  *    ata_hsm_move - move the HSM to the next state.
+  *    @ap: the target ata_port
+  *    @qc: qc on going
+  *    @status: current device status
+  *    @in_wq: 1 if called from workqueue, 0 otherwise
+  *
+  *    RETURNS:
+  *    1 when poll next status needed, 0 otherwise.
+  */
+ static int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+                        u8 status, int in_wq)
+ {
+       unsigned long flags = 0;
+       int poll_next;
+       WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+       /* Make sure ata_qc_issue_prot() does not throw things
+        * like DMA polling into the workqueue. Notice that
+        * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
+        */
+       WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
+ fsm_start:
+       DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
+               ap->id, qc->tf.protocol, ap->hsm_task_state, status);
+       switch (ap->hsm_task_state) {
+       case HSM_ST_FIRST:
+               /* Send first data block or PACKET CDB */
+               /* If polling, we will stay in the work queue after
+                * sending the data. Otherwise, interrupt handler
+                * takes over after sending the data.
+                */
+               poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+               /* check device status */
+               if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
+                       /* Wrong status. Let EH handle this */
                        qc->err_mask |= AC_ERR_HSM;
                        ap->hsm_task_state = HSM_ST_ERR;
-                       return;
+                       goto fsm_start;
                }
  
-               ata_pio_sector(qc);
-       }
- }
+               /* Device should not ask for data transfer (DRQ=1)
+                * when it finds something wrong.
+                * We ignore DRQ here and stop the HSM by
+                * changing hsm_task_state to HSM_ST_ERR and
+                * let the EH abort the command or reset the device.
+                */
+               if (unlikely(status & (ATA_ERR | ATA_DF))) {
+                       printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
+                              ap->id, status);
+                       qc->err_mask |= AC_ERR_DEV;
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
  
- static void ata_pio_error(struct ata_queued_cmd *qc)
- {
-       struct ata_port *ap = qc->ap;
+               /* Send the CDB (atapi) or the first data block (ata pio out).
+                * During the state transition, interrupt handler shouldn't
+                * be invoked before the data transfer is complete and
+                * hsm_task_state is changed. Hence, the following locking.
+                */
+               if (in_wq)
+                       spin_lock_irqsave(&ap->host_set->lock, flags);
  
-       if (qc->tf.command != ATA_CMD_PACKET)
-               ata_dev_printk(qc->dev, KERN_WARNING, "PIO error\n");
+               if (qc->tf.protocol == ATA_PROT_PIO) {
+                       /* PIO data out protocol.
+                        * send first data block.
+                        */
  
-       /* make sure qc->err_mask is available to
-        * know what's wrong and recover
-        */
-       WARN_ON(qc->err_mask == 0);
+                       /* ata_pio_sectors() might change the state
+                        * to HSM_ST_LAST. so, the state is changed here
+                        * before ata_pio_sectors().
+                        */
+                       ap->hsm_task_state = HSM_ST;
+                       ata_pio_sectors(qc);
+                       ata_altstatus(ap); /* flush */
+               } else
+                       /* send CDB */
+                       atapi_send_cdb(ap, qc);
+               if (in_wq)
+                       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+               /* if polling, ata_pio_task() handles the rest.
+                * otherwise, interrupt handler takes over from here.
+                */
+               break;
  
-       ap->hsm_task_state = HSM_ST_IDLE;
+       case HSM_ST:
+               /* complete command or read/write the data register */
+               if (qc->tf.protocol == ATA_PROT_ATAPI) {
+                       /* ATAPI PIO protocol */
+                       if ((status & ATA_DRQ) == 0) {
+                               /* no more data to transfer */
+                               ap->hsm_task_state = HSM_ST_LAST;
+                               goto fsm_start;
+                       }
  
-       ata_poll_qc_complete(qc);
- }
+                       /* Device should not ask for data transfer (DRQ=1)
+                        * when it finds something wrong.
+                        * We ignore DRQ here and stop the HSM by
+                        * changing hsm_task_state to HSM_ST_ERR and
+                        * let the EH abort the command or reset the device.
+                        */
+                       if (unlikely(status & (ATA_ERR | ATA_DF))) {
+                               printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
+                                      ap->id, status);
+                               qc->err_mask |= AC_ERR_DEV;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
  
- static void ata_pio_task(void *_data)
- {
-       struct ata_queued_cmd *qc = _data;
-       struct ata_port *ap = qc->ap;
-       unsigned long timeout;
-       int qc_completed;
+                       atapi_pio_bytes(qc);
  
- fsm_start:
-       timeout = 0;
-       qc_completed = 0;
+                       if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
+                               /* bad ireason reported by device */
+                               goto fsm_start;
  
-       switch (ap->hsm_task_state) {
-       case HSM_ST_IDLE:
-               return;
+               } else {
+                       /* ATA PIO protocol */
+                       if (unlikely((status & ATA_DRQ) == 0)) {
+                               /* handle BSY=0, DRQ=0 as error */
+                               qc->err_mask |= AC_ERR_HSM;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
  
-       case HSM_ST:
-               ata_pio_block(qc);
+                       /* For PIO reads, some devices may ask for
+                        * data transfer (DRQ=1) alone with ERR=1.
+                        * We respect DRQ here and transfer one
+                        * block of junk data before changing the
+                        * hsm_task_state to HSM_ST_ERR.
+                        *
+                        * For PIO writes, ERR=1 DRQ=1 doesn't make
+                        * sense since the data block has been
+                        * transferred to the device.
+                        */
+                       if (unlikely(status & (ATA_ERR | ATA_DF))) {
+                               /* data might be corrputed */
+                               qc->err_mask |= AC_ERR_DEV;
+                               if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+                                       ata_pio_sectors(qc);
+                                       ata_altstatus(ap);
+                                       status = ata_wait_idle(ap);
+                               }
+                               /* ata_pio_sectors() might change the
+                                * state to HSM_ST_LAST. so, the state
+                                * is changed after ata_pio_sectors().
+                                */
+                               ap->hsm_task_state = HSM_ST_ERR;
+                               goto fsm_start;
+                       }
+                       ata_pio_sectors(qc);
+                       if (ap->hsm_task_state == HSM_ST_LAST &&
+                           (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+                               /* all data read */
+                               ata_altstatus(ap);
+                               status = ata_wait_idle(ap);
+                               goto fsm_start;
+                       }
+               }
+               ata_altstatus(ap); /* flush */
+               poll_next = 1;
                break;
  
        case HSM_ST_LAST:
-               qc_completed = ata_pio_complete(qc);
-               break;
+               if (unlikely(!ata_ok(status))) {
+                       qc->err_mask |= __ac_err_mask(status);
+                       ap->hsm_task_state = HSM_ST_ERR;
+                       goto fsm_start;
+               }
+               /* no more data to transfer */
+               DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
+                       ap->id, qc->dev->devno, status);
+               WARN_ON(qc->err_mask);
+               ap->hsm_task_state = HSM_ST_IDLE;
  
-       case HSM_ST_POLL:
-       case HSM_ST_LAST_POLL:
-               timeout = ata_pio_poll(qc);
+               /* complete taskfile transaction */
+               if (in_wq)
+                       ata_poll_qc_complete(qc);
+               else
+                       ata_qc_complete(qc);
+               poll_next = 0;
                break;
  
-       case HSM_ST_TMOUT:
        case HSM_ST_ERR:
-               ata_pio_error(qc);
-               return;
+               if (qc->tf.command != ATA_CMD_PACKET)
+                       printk(KERN_ERR "ata%u: dev %u command error, drv_stat 0x%x\n",
+                              ap->id, qc->dev->devno, status);
+               /* make sure qc->err_mask is available to
+                * know what's wrong and recover
+                */
+               WARN_ON(qc->err_mask == 0);
+               ap->hsm_task_state = HSM_ST_IDLE;
+               /* complete taskfile transaction */
+               if (in_wq)
+                       ata_poll_qc_complete(qc);
+               else
+                       ata_qc_complete(qc);
+               poll_next = 0;
+               break;
+       default:
+               poll_next = 0;
+               BUG();
        }
  
-       if (timeout)
-               ata_port_queue_task(ap, ata_pio_task, qc, timeout);
-       else if (!qc_completed)
-               goto fsm_start;
+       return poll_next;
  }
  
- /**
-  *    atapi_packet_task - Write CDB bytes to hardware
-  *    @_data: qc in progress
-  *
-  *    When device has indicated its readiness to accept
-  *    a CDB, this function is called.  Send the CDB.
-  *    If DMA is to be performed, exit immediately.
-  *    Otherwise, we are in polling mode, so poll
-  *    status under operation succeeds or fails.
-  *
-  *    LOCKING:
-  *    Kernel thread context (may sleep)
-  */
- static void atapi_packet_task(void *_data)
+ static void ata_pio_task(void *_data)
  {
        struct ata_queued_cmd *qc = _data;
        struct ata_port *ap = qc->ap;
        u8 status;
+       int poll_next;
  
-       /* sleep-wait for BSY to clear */
-       DPRINTK("busy wait\n");
-       if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
-               qc->err_mask |= AC_ERR_TIMEOUT;
-               goto err_out;
-       }
-       /* make sure DRQ is set */
-       status = ata_chk_status(ap);
-       if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
-               qc->err_mask |= AC_ERR_HSM;
-               goto err_out;
-       }
-       /* send SCSI cdb */
-       DPRINTK("send cdb\n");
-       WARN_ON(qc->dev->cdb_len < 12);
-       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
-           qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
-               unsigned long flags;
-               /* Once we're done issuing command and kicking bmdma,
-                * irq handler takes over.  To not lose irq, we need
-                * to clear NOINTR flag before sending cdb, but
-                * interrupt handler shouldn't be invoked before we're
-                * finished.  Hence, the following locking.
-                */
-               spin_lock_irqsave(&ap->host_set->lock, flags);
-               ap->flags &= ~ATA_FLAG_NOINTR;
-               ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
-               if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
-                       ap->ops->bmdma_start(qc);       /* initiate bmdma */
-               spin_unlock_irqrestore(&ap->host_set->lock, flags);
-       } else {
-               ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
+ fsm_start:
+       WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
  
-               /* PIO commands are handled by polling */
-               ap->hsm_task_state = HSM_ST;
-               ata_port_queue_task(ap, ata_pio_task, qc, 0);
+       /*
+        * This is purely heuristic.  This is a fast path.
+        * Sometimes when we enter, BSY will be cleared in
+        * a chk-status or two.  If not, the drive is probably seeking
+        * or something.  Snooze for a couple msecs, then
+        * chk-status again.  If still busy, queue delayed work.
+        */
+       status = ata_busy_wait(ap, ATA_BUSY, 5);
+       if (status & ATA_BUSY) {
+               msleep(2);
+               status = ata_busy_wait(ap, ATA_BUSY, 10);
+               if (status & ATA_BUSY) {
+                       ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE);
+                       return;
+               }
        }
  
-       return;
+       /* move the HSM */
+       poll_next = ata_hsm_move(ap, qc, status, 1);
  
- err_out:
-       ata_poll_qc_complete(qc);
+       /* another command or interrupt handler
+        * may be running at this point.
+        */
+       if (poll_next)
+               goto fsm_start;
  }
  
  /**
@@@ -4084,14 -4134,9 +4195,14 @@@ static struct ata_queued_cmd *ata_qc_ne
        struct ata_queued_cmd *qc = NULL;
        unsigned int i;
  
 -      for (i = 0; i < ATA_MAX_QUEUE; i++)
 +      /* no command while frozen */
 +      if (unlikely(ap->flags & ATA_FLAG_FROZEN))
 +              return NULL;
 +
 +      /* the last tag is reserved for internal command. */
 +      for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
                if (!test_and_set_bit(i, &ap->qactive)) {
 -                      qc = ata_qc_from_tag(ap, i);
 +                      qc = __ata_qc_from_tag(ap, i);
                        break;
                }
  
  
  /**
   *    ata_qc_new_init - Request an available ATA command, and initialize it
 - *    @ap: Port associated with device @dev
   *    @dev: Device from whom we request an available command structure
   *
   *    LOCKING:
   *    None.
   */
  
 -struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 -                                    struct ata_device *dev)
 +struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
  {
 +      struct ata_port *ap = dev->ap;
        struct ata_queued_cmd *qc;
  
        qc = ata_qc_new(ap);
@@@ -4146,6 -4192,8 +4257,6 @@@ void ata_qc_free(struct ata_queued_cmd 
        qc->flags = 0;
        tag = qc->tag;
        if (likely(ata_tag_valid(tag))) {
 -              if (tag == ap->active_tag)
 -                      ap->active_tag = ATA_TAG_POISON;
                qc->tag = ATA_TAG_POISON;
                clear_bit(tag, &ap->qactive);
        }
@@@ -4159,9 -4207,6 +4270,9 @@@ void __ata_qc_complete(struct ata_queue
        if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
                ata_sg_clean(qc);
  
 +      /* command should be marked inactive atomically with qc completion */
 +      qc->ap->active_tag = ATA_TAG_POISON;
 +
        /* atapi: mark qc as inactive to prevent the interrupt handler
         * from completing the command twice later, before the error handler
         * is called. (when rc != 0 and atapi request sense is needed)
        qc->complete_fn(qc);
  }
  
 +/**
 + *    ata_qc_complete - Complete an active ATA command
 + *    @qc: Command to complete
 + *    @err_mask: ATA Status register contents
 + *
 + *    Indicate to the mid and upper layers that an ATA
 + *    command has completed, with either an ok or not-ok status.
 + *
 + *    LOCKING:
 + *    spin_lock_irqsave(host_set lock)
 + */
 +void ata_qc_complete(struct ata_queued_cmd *qc)
 +{
 +      struct ata_port *ap = qc->ap;
 +
 +      /* XXX: New EH and old EH use different mechanisms to
 +       * synchronize EH with regular execution path.
 +       *
 +       * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED.
 +       * Normal execution path is responsible for not accessing a
 +       * failed qc.  libata core enforces the rule by returning NULL
 +       * from ata_qc_from_tag() for failed qcs.
 +       *
 +       * Old EH depends on ata_qc_complete() nullifying completion
 +       * requests if ATA_QCFLAG_EH_SCHEDULED is set.  Old EH does
 +       * not synchronize with interrupt handler.  Only PIO task is
 +       * taken care of.
 +       */
 +      if (ap->ops->error_handler) {
 +              WARN_ON(ap->flags & ATA_FLAG_FROZEN);
 +
 +              if (unlikely(qc->err_mask))
 +                      qc->flags |= ATA_QCFLAG_FAILED;
 +
 +              if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
 +                      if (!ata_tag_internal(qc->tag)) {
 +                              /* always fill result TF for failed qc */
 +                              ap->ops->tf_read(ap, &qc->result_tf);
 +                              ata_qc_schedule_eh(qc);
 +                              return;
 +                      }
 +              }
 +
 +              /* read result TF if requested */
 +              if (qc->flags & ATA_QCFLAG_RESULT_TF)
 +                      ap->ops->tf_read(ap, &qc->result_tf);
 +
 +              __ata_qc_complete(qc);
 +      } else {
 +              if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
 +                      return;
 +
 +              /* read result TF if failed or requested */
 +              if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
 +                      ap->ops->tf_read(ap, &qc->result_tf);
 +
 +              __ata_qc_complete(qc);
 +      }
 +}
 +
  static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
  {
        struct ata_port *ap = qc->ap;
@@@ -4322,43 -4307,105 +4433,105 @@@ unsigned int ata_qc_issue_prot(struct a
  {
        struct ata_port *ap = qc->ap;
  
+       /* Use polling pio if the LLD doesn't handle
+        * interrupt driven pio and atapi CDB interrupt.
+        */
+       if (ap->flags & ATA_FLAG_PIO_POLLING) {
+               switch (qc->tf.protocol) {
+               case ATA_PROT_PIO:
+               case ATA_PROT_ATAPI:
+               case ATA_PROT_ATAPI_NODATA:
+                       qc->tf.flags |= ATA_TFLAG_POLLING;
+                       break;
+               case ATA_PROT_ATAPI_DMA:
+                       if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+                               /* see ata_check_atapi_dma() */
+                               BUG();
+                       break;
+               default:
+                       break;
+               }
+       }
+       /* select the device */
        ata_dev_select(ap, qc->dev->devno, 1, 0);
  
+       /* start the command */
        switch (qc->tf.protocol) {
        case ATA_PROT_NODATA:
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_qc_set_polling(qc);
                ata_tf_to_host(ap, &qc->tf);
+               ap->hsm_task_state = HSM_ST_LAST;
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
                break;
  
        case ATA_PROT_DMA:
+               WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
                ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
                ap->ops->bmdma_setup(qc);           /* set up bmdma */
                ap->ops->bmdma_start(qc);           /* initiate bmdma */
+               ap->hsm_task_state = HSM_ST_LAST;
                break;
  
-       case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
-               ata_qc_set_polling(qc);
-               ata_tf_to_host(ap, &qc->tf);
-               ap->hsm_task_state = HSM_ST;
-               ata_port_queue_task(ap, ata_pio_task, qc, 0);
-               break;
+       case ATA_PROT_PIO:
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_qc_set_polling(qc);
  
-       case ATA_PROT_ATAPI:
-               ata_qc_set_polling(qc);
                ata_tf_to_host(ap, &qc->tf);
-               ata_port_queue_task(ap, atapi_packet_task, qc, 0);
+               if (qc->tf.flags & ATA_TFLAG_WRITE) {
+                       /* PIO data out protocol */
+                       ap->hsm_task_state = HSM_ST_FIRST;
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
+                       /* always send first data block using
+                        * the ata_pio_task() codepath.
+                        */
+               } else {
+                       /* PIO data in protocol */
+                       ap->hsm_task_state = HSM_ST;
+                       if (qc->tf.flags & ATA_TFLAG_POLLING)
+                               ata_port_queue_task(ap, ata_pio_task, qc, 0);
+                       /* if polling, ata_pio_task() handles the rest.
+                        * otherwise, interrupt handler takes over from here.
+                        */
+               }
                break;
  
+       case ATA_PROT_ATAPI:
        case ATA_PROT_ATAPI_NODATA:
-               ap->flags |= ATA_FLAG_NOINTR;
+               if (qc->tf.flags & ATA_TFLAG_POLLING)
+                       ata_qc_set_polling(qc);
                ata_tf_to_host(ap, &qc->tf);
-               ata_port_queue_task(ap, atapi_packet_task, qc, 0);
+               ap->hsm_task_state = HSM_ST_FIRST;
+               /* send cdb by polling if no cdb interrupt */
+               if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
+                   (qc->tf.flags & ATA_TFLAG_POLLING))
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
                break;
  
        case ATA_PROT_ATAPI_DMA:
-               ap->flags |= ATA_FLAG_NOINTR;
+               WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
                ap->ops->tf_load(ap, &qc->tf);   /* load tf registers */
                ap->ops->bmdma_setup(qc);           /* set up bmdma */
-               ata_port_queue_task(ap, atapi_packet_task, qc, 0);
+               ap->hsm_task_state = HSM_ST_FIRST;
+               /* send cdb by polling if no cdb interrupt */
+               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       ata_port_queue_task(ap, ata_pio_task, qc, 0);
                break;
  
        default:
  inline unsigned int ata_host_intr (struct ata_port *ap,
                                   struct ata_queued_cmd *qc)
  {
-       u8 status, host_stat;
-       switch (qc->tf.protocol) {
-       case ATA_PROT_DMA:
-       case ATA_PROT_ATAPI_DMA:
-       case ATA_PROT_ATAPI:
-               /* check status of DMA engine */
-               host_stat = ap->ops->bmdma_status(ap);
-               VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
+       u8 status, host_stat = 0;
  
-               /* if it's not our irq... */
-               if (!(host_stat & ATA_DMA_INTR))
-                       goto idle_irq;
-               /* before we do anything else, clear DMA-Start bit */
-               ap->ops->bmdma_stop(qc);
+       VPRINTK("ata%u: protocol %d task_state %d\n",
+               ap->id, qc->tf.protocol, ap->hsm_task_state);
  
-               /* fall through */
-       case ATA_PROT_ATAPI_NODATA:
-       case ATA_PROT_NODATA:
-               /* check altstatus */
-               status = ata_altstatus(ap);
-               if (status & ATA_BUSY)
-                       goto idle_irq;
+       /* Check whether we are expecting interrupt in this state */
+       switch (ap->hsm_task_state) {
+       case HSM_ST_FIRST:
+               /* Some pre-ATAPI-4 devices assert INTRQ
+                * at this state when ready to receive CDB.
+                */
  
-               /* check main status, clearing INTRQ */
-               status = ata_chk_status(ap);
-               if (unlikely(status & ATA_BUSY))
+               /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+                * The flag was turned on only for atapi devices.
+                * No need to check is_atapi_taskfile(&qc->tf) again.
+                */
+               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
                        goto idle_irq;
-               DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-                       ap->id, qc->tf.protocol, status);
-               /* ack bmdma irq events */
-               ap->ops->irq_clear(ap);
-               /* complete taskfile transaction */
-               qc->err_mask |= ac_err_mask(status);
-               ata_qc_complete(qc);
                break;
+       case HSM_ST_LAST:
+               if (qc->tf.protocol == ATA_PROT_DMA ||
+                   qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+                       /* check status of DMA engine */
+                       host_stat = ap->ops->bmdma_status(ap);
+                       VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
+                       /* if it's not our irq... */
+                       if (!(host_stat & ATA_DMA_INTR))
+                               goto idle_irq;
+                       /* before we do anything else, clear DMA-Start bit */
+                       ap->ops->bmdma_stop(qc);
+                       if (unlikely(host_stat & ATA_DMA_ERR)) {
+                               /* error when transfering data to/from memory */
+                               qc->err_mask |= AC_ERR_HOST_BUS;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                       }
+               }
+               break;
+       case HSM_ST:
+               break;
        default:
                goto idle_irq;
        }
  
+       /* check altstatus */
+       status = ata_altstatus(ap);
+       if (status & ATA_BUSY)
+               goto idle_irq;
+       /* check main status, clearing INTRQ */
+       status = ata_chk_status(ap);
+       if (unlikely(status & ATA_BUSY))
+               goto idle_irq;
+       /* ack bmdma irq events */
+       ap->ops->irq_clear(ap);
+       ata_hsm_move(ap, qc, status, 0);
        return 1;       /* irq handled */
  
  idle_irq:
  #ifdef ATA_IRQ_TRAP
        if ((ap->stats.idle_irq % 1000) == 0) {
                ata_irq_ack(ap, 0); /* debug trap */
 -              printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
 +              ata_port_printk(ap, KERN_WARNING, "irq trap\n");
                return 1;
        }
  #endif
@@@ -4480,11 -4541,11 +4667,11 @@@ irqreturn_t ata_interrupt (int irq, voi
  
                ap = host_set->ports[i];
                if (ap &&
-                   !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) {
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
                        struct ata_queued_cmd *qc;
  
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.ctl & ATA_NIEN)) &&
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
                            (qc->flags & ATA_QCFLAG_ACTIVE))
                                handled |= ata_host_intr(ap, qc);
                }
        return IRQ_RETVAL(handled);
  }
  
 +/**
 + *    sata_scr_valid - test whether SCRs are accessible
 + *    @ap: ATA port to test SCR accessibility for
 + *
 + *    Test whether SCRs are accessible for @ap.
 + *
 + *    LOCKING:
 + *    None.
 + *
 + *    RETURNS:
 + *    1 if SCRs are accessible, 0 otherwise.
 + */
 +int sata_scr_valid(struct ata_port *ap)
 +{
 +      return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
 +}
 +
 +/**
 + *    sata_scr_read - read SCR register of the specified port
 + *    @ap: ATA port to read SCR for
 + *    @reg: SCR to read
 + *    @val: Place to store read value
 + *
 + *    Read SCR register @reg of @ap into *@val.  This function is
 + *    guaranteed to succeed if the cable type of the port is SATA
 + *    and the port implements ->scr_read.
 + *
 + *    LOCKING:
 + *    None.
 + *
 + *    RETURNS:
 + *    0 on success, negative errno on failure.
 + */
 +int sata_scr_read(struct ata_port *ap, int reg, u32 *val)
 +{
 +      if (sata_scr_valid(ap)) {
 +              *val = ap->ops->scr_read(ap, reg);
 +              return 0;
 +      }
 +      return -EOPNOTSUPP;
 +}
 +
 +/**
 + *    sata_scr_write - write SCR register of the specified port
 + *    @ap: ATA port to write SCR for
 + *    @reg: SCR to write
 + *    @val: value to write
 + *
 + *    Write @val to SCR register @reg of @ap.  This function is
 + *    guaranteed to succeed if the cable type of the port is SATA
 + *    and the port implements ->scr_read.
 + *
 + *    LOCKING:
 + *    None.
 + *
 + *    RETURNS:
 + *    0 on success, negative errno on failure.
 + */
 +int sata_scr_write(struct ata_port *ap, int reg, u32 val)
 +{
 +      if (sata_scr_valid(ap)) {
 +              ap->ops->scr_write(ap, reg, val);
 +              return 0;
 +      }
 +      return -EOPNOTSUPP;
 +}
 +
 +/**
 + *    sata_scr_write_flush - write SCR register of the specified port and flush
 + *    @ap: ATA port to write SCR for
 + *    @reg: SCR to write
 + *    @val: value to write
 + *
 + *    This function is identical to sata_scr_write() except that this
 + *    function performs flush after writing to the register.
 + *
 + *    LOCKING:
 + *    None.
 + *
 + *    RETURNS:
 + *    0 on success, negative errno on failure.
 + */
 +int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val)
 +{
 +      if (sata_scr_valid(ap)) {
 +              ap->ops->scr_write(ap, reg, val);
 +              ap->ops->scr_read(ap, reg);
 +              return 0;
 +      }
 +      return -EOPNOTSUPP;
 +}
 +
 +/**
 + *    ata_port_online - test whether the given port is online
 + *    @ap: ATA port to test
 + *
 + *    Test whether @ap is online.  Note that this function returns 0
 + *    if online status of @ap cannot be obtained, so
 + *    ata_port_online(ap) != !ata_port_offline(ap).
 + *
 + *    LOCKING:
 + *    None.
 + *
 + *    RETURNS:
 + *    1 if the port online status is available and online.
 + */
 +int ata_port_online(struct ata_port *ap)
 +{
 +      u32 sstatus;
 +
 +      if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3)
 +              return 1;
 +      return 0;
 +}
 +
 +/**
 + *    ata_port_offline - test whether the given port is offline
 + *    @ap: ATA port to test
 + *
 + *    Test whether @ap is offline.  Note that this function returns
 + *    0 if offline status of @ap cannot be obtained, so
 + *    ata_port_online(ap) != !ata_port_offline(ap).
 + *
 + *    LOCKING:
 + *    None.
 + *
 + *    RETURNS:
 + *    1 if the port offline status is available and offline.
 + */
 +int ata_port_offline(struct ata_port *ap)
 +{
 +      u32 sstatus;
 +
 +      if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3)
 +              return 1;
 +      return 0;
 +}
  
  /*
   * 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)
 +static int ata_do_simple_cmd(struct ata_device *dev, u8 cmd)
  {
        struct ata_taskfile tf;
        int err;
  
 -      ata_tf_init(ap, &tf, dev->devno);
 +      ata_tf_init(dev, &tf);
  
        tf.command = cmd;
        tf.flags |= ATA_TFLAG_DEVICE;
        tf.protocol = ATA_PROT_NODATA;
  
 -      err = ata_exec_internal(ap, dev, &tf, NULL, DMA_NONE, NULL, 0);
 +      err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
        if (err)
 -              printk(KERN_ERR "%s: ata command failed: %d\n",
 -                              __FUNCTION__, err);
 +              ata_dev_printk(dev, 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)
 +static int ata_flush_cache(struct ata_device *dev)
  {
        u8 cmd;
  
        else
                cmd = ATA_CMD_FLUSH;
  
 -      return ata_do_simple_cmd(ap, dev, cmd);
 +      return ata_do_simple_cmd(dev, cmd);
  }
  
 -static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
 +static int ata_standby_drive(struct ata_device *dev)
  {
 -      return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
 +      return ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
  }
  
 -static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
 +static int ata_start_drive(struct ata_device *dev)
  {
 -      return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
 +      return ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE);
  }
  
  /**
   *    ata_device_resume - wakeup a previously suspended devices
 - *    @ap: port the device is connected to
   *    @dev: the device to resume
   *
   *    Kick the drive back into action, by sending it an idle immediate
   *    and host.
   *
   */
 -int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
 +int ata_device_resume(struct ata_device *dev)
  {
 +      struct ata_port *ap = dev->ap;
 +
        if (ap->flags & ATA_FLAG_SUSPENDED) {
                struct ata_device *failed_dev;
                ap->flags &= ~ATA_FLAG_SUSPENDED;
                while (ata_set_mode(ap, &failed_dev))
 -                      ata_dev_disable(ap, failed_dev);
 +                      ata_dev_disable(failed_dev);
        }
        if (!ata_dev_enabled(dev))
                return 0;
        if (dev->class == ATA_DEV_ATA)
 -              ata_start_drive(ap, dev);
 +              ata_start_drive(dev);
  
        return 0;
  }
  
  /**
   *    ata_device_suspend - prepare a device for suspend
 - *    @ap: port the device is connected to
   *    @dev: the device to 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, pm_message_t state)
 +int ata_device_suspend(struct ata_device *dev, pm_message_t state)
  {
 +      struct ata_port *ap = dev->ap;
 +
        if (!ata_dev_enabled(dev))
                return 0;
        if (dev->class == ATA_DEV_ATA)
 -              ata_flush_cache(ap, dev);
 +              ata_flush_cache(dev);
  
        if (state.event != PM_EVENT_FREEZE)
 -              ata_standby_drive(ap, dev);
 +              ata_standby_drive(dev);
        ap->flags |= ATA_FLAG_SUSPENDED;
        return 0;
  }
@@@ -4853,6 -4776,7 +5040,6 @@@ static void ata_host_init(struct ata_po
        ap->udma_mask = ent->udma_mask;
        ap->flags |= ent->host_flags;
        ap->ops = ent->port_ops;
 -      ap->cbl = ATA_CBL_NONE;
        ap->sata_spd_limit = UINT_MAX;
        ap->active_tag = ATA_TAG_POISON;
        ap->last_ctl = 0xFF;
        INIT_WORK(&ap->port_task, NULL, NULL);
        INIT_LIST_HEAD(&ap->eh_done_q);
  
 +      /* set cable type */
 +      ap->cbl = ATA_CBL_NONE;
 +      if (ap->flags & ATA_FLAG_SATA)
 +              ap->cbl = ATA_CBL_SATA;
 +
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                struct ata_device *dev = &ap->device[i];
 +              dev->ap = ap;
                dev->devno = i;
                dev->pio_mask = UINT_MAX;
                dev->mwdma_mask = UINT_MAX;
@@@ -4991,18 -4909,18 +5178,18 @@@ int ata_device_add(const struct ata_pro
                                (ap->pio_mask << ATA_SHIFT_PIO);
  
                /* print per-port info to dmesg */
 -              printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX "
 -                               "bmdma 0x%lX irq %lu\n",
 -                      ap->id,
 -                      ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
 -                      ata_mode_string(xfer_mode_mask),
 -                      ap->ioaddr.cmd_addr,
 -                      ap->ioaddr.ctl_addr,
 -                      ap->ioaddr.bmdma_addr,
 -                      ent->irq);
 +              ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
 +                              "ctl 0x%lX bmdma 0x%lX irq %lu\n",
 +                              ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
 +                              ata_mode_string(xfer_mode_mask),
 +                              ap->ioaddr.cmd_addr,
 +                              ap->ioaddr.ctl_addr,
 +                              ap->ioaddr.bmdma_addr,
 +                              ent->irq);
  
                ata_chk_status(ap);
                host_set->ops->irq_clear(ap);
 +              ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */
                count++;
        }
  
  
                rc = scsi_add_host(ap->host, dev);
                if (rc) {
 -                      printk(KERN_ERR "ata%u: scsi_add_host failed\n",
 -                             ap->id);
 +                      ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n");
                        /* FIXME: do something useful here */
                        /* FIXME: handle unconditional calls to
                         * scsi_scan_host and ata_host_remove, below,
@@@ -5133,11 -5052,14 +5320,11 @@@ void ata_host_set_remove(struct ata_hos
  int ata_scsi_release(struct Scsi_Host *host)
  {
        struct ata_port *ap = ata_shost_to_port(host);
 -      int i;
  
        DPRINTK("ENTER\n");
  
        ap->ops->port_disable(ap);
        ata_host_remove(ap, 0);
 -      for (i = 0; i < ATA_MAX_DEVICES; i++)
 -              kfree(ap->device[i].id);
  
        DPRINTK("EXIT\n");
        return 1;
@@@ -5355,7 -5277,7 +5542,7 @@@ EXPORT_SYMBOL_GPL(ata_device_add)
  EXPORT_SYMBOL_GPL(ata_host_set_remove);
  EXPORT_SYMBOL_GPL(ata_sg_init);
  EXPORT_SYMBOL_GPL(ata_sg_init_one);
 -EXPORT_SYMBOL_GPL(__ata_qc_complete);
 +EXPORT_SYMBOL_GPL(ata_qc_complete);
  EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
  EXPORT_SYMBOL_GPL(ata_tf_load);
  EXPORT_SYMBOL_GPL(ata_tf_read);
@@@ -5377,13 -5299,8 +5564,13 @@@ EXPORT_SYMBOL_GPL(ata_bmdma_start)
  EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
  EXPORT_SYMBOL_GPL(ata_bmdma_status);
  EXPORT_SYMBOL_GPL(ata_bmdma_stop);
 +EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
 +EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
 +EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
 +EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
 +EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
  EXPORT_SYMBOL_GPL(ata_port_probe);
 -EXPORT_SYMBOL_GPL(ata_set_sata_spd);
 +EXPORT_SYMBOL_GPL(sata_set_spd);
  EXPORT_SYMBOL_GPL(sata_phy_reset);
  EXPORT_SYMBOL_GPL(__sata_phy_reset);
  EXPORT_SYMBOL_GPL(ata_bus_reset);
@@@ -5406,12 -5323,6 +5593,12 @@@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd)
  EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
  EXPORT_SYMBOL_GPL(ata_scsi_release);
  EXPORT_SYMBOL_GPL(ata_host_intr);
 +EXPORT_SYMBOL_GPL(sata_scr_valid);
 +EXPORT_SYMBOL_GPL(sata_scr_read);
 +EXPORT_SYMBOL_GPL(sata_scr_write);
 +EXPORT_SYMBOL_GPL(sata_scr_write_flush);
 +EXPORT_SYMBOL_GPL(ata_port_online);
 +EXPORT_SYMBOL_GPL(ata_port_offline);
  EXPORT_SYMBOL_GPL(ata_id_string);
  EXPORT_SYMBOL_GPL(ata_id_c_string);
  EXPORT_SYMBOL_GPL(ata_scsi_simulate);
@@@ -5437,12 -5348,7 +5624,12 @@@ EXPORT_SYMBOL_GPL(ata_device_resume)
  EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
  EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
  
 -EXPORT_SYMBOL_GPL(ata_scsi_error);
  EXPORT_SYMBOL_GPL(ata_eng_timeout);
 +EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
 +EXPORT_SYMBOL_GPL(ata_port_abort);
 +EXPORT_SYMBOL_GPL(ata_port_freeze);
 +EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
 +EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
  EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
  EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 +EXPORT_SYMBOL_GPL(ata_do_eh);
diff --combined drivers/scsi/libata-eh.c
index cd133f83e59511c3eda3772251532cc14bfae006,16db62211716d3b9ba5be30687fd80b99d6b8483..e401f353f84815d5a829d55a37b86bf4df38d6be
  
  #include "libata.h"
  
 +static void __ata_port_freeze(struct ata_port *ap);
 +
 +static void ata_ering_record(struct ata_ering *ering, int is_io,
 +                           unsigned int err_mask)
 +{
 +      struct ata_ering_entry *ent;
 +
 +      WARN_ON(!err_mask);
 +
 +      ering->cursor++;
 +      ering->cursor %= ATA_ERING_SIZE;
 +
 +      ent = &ering->ring[ering->cursor];
 +      ent->is_io = is_io;
 +      ent->err_mask = err_mask;
 +      ent->timestamp = get_jiffies_64();
 +}
 +
 +static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
 +{
 +      struct ata_ering_entry *ent = &ering->ring[ering->cursor];
 +      if (!ent->err_mask)
 +              return NULL;
 +      return ent;
 +}
 +
 +static int ata_ering_map(struct ata_ering *ering,
 +                       int (*map_fn)(struct ata_ering_entry *, void *),
 +                       void *arg)
 +{
 +      int idx, rc = 0;
 +      struct ata_ering_entry *ent;
 +
 +      idx = ering->cursor;
 +      do {
 +              ent = &ering->ring[idx];
 +              if (!ent->err_mask)
 +                      break;
 +              rc = map_fn(ent, arg);
 +              if (rc)
 +                      break;
 +              idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
 +      } while (idx != ering->cursor);
 +
 +      return rc;
 +}
 +
  /**
   *    ata_scsi_timed_out - SCSI layer time out callback
   *    @cmd: timed out SCSI command
   *    from finishing it by setting EH_SCHEDULED and return
   *    EH_NOT_HANDLED.
   *
 + *    TODO: kill this function once old EH is gone.
 + *
   *    LOCKING:
   *    Called from timer context
   *
@@@ -116,16 -67,10 +116,16 @@@ enum scsi_eh_timer_return ata_scsi_time
        struct ata_port *ap = ata_shost_to_port(host);
        unsigned long flags;
        struct ata_queued_cmd *qc;
 -      enum scsi_eh_timer_return ret = EH_HANDLED;
 +      enum scsi_eh_timer_return ret;
  
        DPRINTK("ENTER\n");
  
 +      if (ap->ops->error_handler) {
 +              ret = EH_NOT_HANDLED;
 +              goto out;
 +      }
 +
 +      ret = EH_HANDLED;
        spin_lock_irqsave(&ap->host_set->lock, flags);
        qc = ata_qc_from_tag(ap, ap->active_tag);
        if (qc) {
        }
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
  
 + out:
        DPRINTK("EXIT, ret=%d\n", ret);
        return ret;
  }
  void ata_scsi_error(struct Scsi_Host *host)
  {
        struct ata_port *ap = ata_shost_to_port(host);
 +      spinlock_t *hs_lock = &ap->host_set->lock;
 +      int i, repeat_cnt = ATA_EH_MAX_REPEAT;
 +      unsigned long flags;
  
        DPRINTK("ENTER\n");
  
 -      /* synchronize with IRQ handler and port task */
 -      spin_unlock_wait(&ap->host_set->lock);
 +      /* synchronize with port task */
        ata_port_flush_task(ap);
  
 -      WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
 +      /* synchronize with host_set lock and sort out timeouts */
 +
 +      /* For new EH, all qcs are finished in one of three ways -
 +       * normal completion, error completion, and SCSI timeout.
 +       * Both cmpletions can race against SCSI timeout.  When normal
 +       * completion wins, the qc never reaches EH.  When error
 +       * completion wins, the qc has ATA_QCFLAG_FAILED set.
 +       *
 +       * When SCSI timeout wins, things are a bit more complex.
 +       * Normal or error completion can occur after the timeout but
 +       * before this point.  In such cases, both types of
 +       * completions are honored.  A scmd is determined to have
 +       * timed out iff its associated qc is active and not failed.
 +       */
 +      if (ap->ops->error_handler) {
 +              struct scsi_cmnd *scmd, *tmp;
 +              int nr_timedout = 0;
 +
 +              spin_lock_irqsave(hs_lock, flags);
 +
 +              list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
 +                      struct ata_queued_cmd *qc;
 +
 +                      for (i = 0; i < ATA_MAX_QUEUE; i++) {
 +                              qc = __ata_qc_from_tag(ap, i);
 +                              if (qc->flags & ATA_QCFLAG_ACTIVE &&
 +                                  qc->scsicmd == scmd)
 +                                      break;
 +                      }
 +
 +                      if (i < ATA_MAX_QUEUE) {
 +                              /* the scmd has an associated qc */
 +                              if (!(qc->flags & ATA_QCFLAG_FAILED)) {
 +                                      /* which hasn't failed yet, timeout */
 +                                      qc->err_mask |= AC_ERR_TIMEOUT;
 +                                      qc->flags |= ATA_QCFLAG_FAILED;
 +                                      nr_timedout++;
 +                              }
 +                      } else {
 +                              /* Normal completion occurred after
 +                               * SCSI timeout but before this point.
 +                               * Successfully complete it.
 +                               */
 +                              scmd->retries = scmd->allowed;
 +                              scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
 +                      }
 +              }
  
 -      ap->ops->eng_timeout(ap);
 +              /* If we have timed out qcs.  They belong to EH from
 +               * this point but the state of the controller is
 +               * unknown.  Freeze the port to make sure the IRQ
 +               * handler doesn't diddle with those qcs.  This must
 +               * be done atomically w.r.t. setting QCFLAG_FAILED.
 +               */
 +              if (nr_timedout)
 +                      __ata_port_freeze(ap);
  
 +              spin_unlock_irqrestore(hs_lock, flags);
 +      } else
 +              spin_unlock_wait(hs_lock);
 +
 + repeat:
 +      /* invoke error handler */
 +      if (ap->ops->error_handler) {
 +              /* fetch & clear EH info */
 +              spin_lock_irqsave(hs_lock, flags);
 +
 +              memset(&ap->eh_context, 0, sizeof(ap->eh_context));
 +              ap->eh_context.i = ap->eh_info;
 +              memset(&ap->eh_info, 0, sizeof(ap->eh_info));
 +
 +              ap->flags &= ~ATA_FLAG_EH_PENDING;
 +
 +              spin_unlock_irqrestore(hs_lock, flags);
 +
 +              /* invoke EH */
 +              ap->ops->error_handler(ap);
 +
 +              /* Exception might have happend after ->error_handler
 +               * recovered the port but before this point.  Repeat
 +               * EH in such case.
 +               */
 +              spin_lock_irqsave(hs_lock, flags);
 +
 +              if (ap->flags & ATA_FLAG_EH_PENDING) {
 +                      if (--repeat_cnt) {
 +                              ata_port_printk(ap, KERN_INFO,
 +                                      "EH pending after completion, "
 +                                      "repeating EH (cnt=%d)\n", repeat_cnt);
 +                              spin_unlock_irqrestore(hs_lock, flags);
 +                              goto repeat;
 +                      }
 +                      ata_port_printk(ap, KERN_ERR, "EH pending after %d "
 +                                      "tries, giving up\n", ATA_EH_MAX_REPEAT);
 +              }
 +
 +              /* this run is complete, make sure EH info is clear */
 +              memset(&ap->eh_info, 0, sizeof(ap->eh_info));
 +
 +              /* Clear host_eh_scheduled while holding hs_lock such
 +               * that if exception occurs after this point but
 +               * before EH completion, SCSI midlayer will
 +               * re-initiate EH.
 +               */
 +              host->host_eh_scheduled = 0;
 +
 +              spin_unlock_irqrestore(hs_lock, flags);
 +      } else {
 +              WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
 +              ap->ops->eng_timeout(ap);
 +      }
 +
 +      /* finish or retry handled scmd's and clean up */
        WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
  
        scsi_eh_flush_done_q(&ap->eh_done_q);
  
 +      /* clean up */
 +      spin_lock_irqsave(hs_lock, flags);
 +
 +      if (ap->flags & ATA_FLAG_RECOVERED)
 +              ata_port_printk(ap, KERN_INFO, "EH complete\n");
 +      ap->flags &= ~ATA_FLAG_RECOVERED;
 +
 +      spin_unlock_irqrestore(hs_lock, flags);
 +
        DPRINTK("EXIT\n");
  }
  
   *    an interrupt was not delivered to the driver, even though the
   *    transaction completed successfully.
   *
 + *    TODO: kill this function once old EH is gone.
 + *
   *    LOCKING:
   *    Inherited from SCSI layer (none, can sleep)
   */
@@@ -345,12 -167,11 +345,12 @@@ static void ata_qc_timeout(struct ata_q
                /* ack bmdma irq events */
                ap->ops->irq_clear(ap);
  
 -              printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
 -                     ap->id, qc->tf.command, drv_stat, host_stat);
 +              ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, "
 +                             "stat 0x%x host_stat 0x%x\n",
 +                             qc->tf.command, drv_stat, host_stat);
  
                /* complete taskfile transaction */
-               qc->err_mask |= ac_err_mask(drv_stat);
+               qc->err_mask |= AC_ERR_TIMEOUT;
                break;
        }
  
   *    an interrupt was not delivered to the driver, even though the
   *    transaction completed successfully.
   *
 + *    TODO: kill this function once old EH is gone.
 + *
   *    LOCKING:
   *    Inherited from SCSI layer (none, can sleep)
   */
@@@ -390,190 -209,6 +390,190 @@@ void ata_eng_timeout(struct ata_port *a
        DPRINTK("EXIT\n");
  }
  
 +/**
 + *    ata_qc_schedule_eh - schedule qc for error handling
 + *    @qc: command to schedule error handling for
 + *
 + *    Schedule error handling for @qc.  EH will kick in as soon as
 + *    other commands are drained.
 + *
 + *    LOCKING:
 + *    spin_lock_irqsave(host_set lock)
 + */
 +void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
 +{
 +      struct ata_port *ap = qc->ap;
 +
 +      WARN_ON(!ap->ops->error_handler);
 +
 +      qc->flags |= ATA_QCFLAG_FAILED;
 +      qc->ap->flags |= ATA_FLAG_EH_PENDING;
 +
 +      /* The following will fail if timeout has already expired.
 +       * ata_scsi_error() takes care of such scmds on EH entry.
 +       * Note that ATA_QCFLAG_FAILED is unconditionally set after
 +       * this function completes.
 +       */
 +      scsi_req_abort_cmd(qc->scsicmd);
 +}
 +
 +/**
 + *    ata_port_schedule_eh - schedule error handling without a qc
 + *    @ap: ATA port to schedule EH for
 + *
 + *    Schedule error handling for @ap.  EH will kick in as soon as
 + *    all commands are drained.
 + *
 + *    LOCKING:
 + *    spin_lock_irqsave(host_set lock)
 + */
 +void ata_port_schedule_eh(struct ata_port *ap)
 +{
 +      WARN_ON(!ap->ops->error_handler);
 +
 +      ap->flags |= ATA_FLAG_EH_PENDING;
 +      ata_schedule_scsi_eh(ap->host);
 +
 +      DPRINTK("port EH scheduled\n");
 +}
 +
 +/**
 + *    ata_port_abort - abort all qc's on the port
 + *    @ap: ATA port to abort qc's for
 + *
 + *    Abort all active qc's of @ap and schedule EH.
 + *
 + *    LOCKING:
 + *    spin_lock_irqsave(host_set lock)
 + *
 + *    RETURNS:
 + *    Number of aborted qc's.
 + */
 +int ata_port_abort(struct ata_port *ap)
 +{
 +      int tag, nr_aborted = 0;
 +
 +      WARN_ON(!ap->ops->error_handler);
 +
 +      for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
 +              struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
 +
 +              if (qc) {
 +                      qc->flags |= ATA_QCFLAG_FAILED;
 +                      ata_qc_complete(qc);
 +                      nr_aborted++;
 +              }
 +      }
 +
 +      if (!nr_aborted)
 +              ata_port_schedule_eh(ap);
 +
 +      return nr_aborted;
 +}
 +
 +/**
 + *    __ata_port_freeze - freeze port
 + *    @ap: ATA port to freeze
 + *
 + *    This function is called when HSM violation or some other
 + *    condition disrupts normal operation of the port.  Frozen port
 + *    is not allowed to perform any operation until the port is
 + *    thawed, which usually follows a successful reset.
 + *
 + *    ap->ops->freeze() callback can be used for freezing the port
 + *    hardware-wise (e.g. mask interrupt and stop DMA engine).  If a
 + *    port cannot be frozen hardware-wise, the interrupt handler
 + *    must ack and clear interrupts unconditionally while the port
 + *    is frozen.
 + *
 + *    LOCKING:
 + *    spin_lock_irqsave(host_set lock)
 + */
 +static void __ata_port_freeze(struct ata_port *ap)
 +{
 +      WARN_ON(!ap->ops->error_handler);
 +
 +      if (ap->ops->freeze)
 +              ap->ops->freeze(ap);
 +
 +      ap->flags |= ATA_FLAG_FROZEN;
 +
 +      DPRINTK("ata%u port frozen\n", ap->id);
 +}
 +
 +/**
 + *    ata_port_freeze - abort & freeze port
 + *    @ap: ATA port to freeze
 + *
 + *    Abort and freeze @ap.
 + *
 + *    LOCKING:
 + *    spin_lock_irqsave(host_set lock)
 + *
 + *    RETURNS:
 + *    Number of aborted commands.
 + */
 +int ata_port_freeze(struct ata_port *ap)
 +{
 +      int nr_aborted;
 +
 +      WARN_ON(!ap->ops->error_handler);
 +
 +      nr_aborted = ata_port_abort(ap);
 +      __ata_port_freeze(ap);
 +
 +      return nr_aborted;
 +}
 +
 +/**
 + *    ata_eh_freeze_port - EH helper to freeze port
 + *    @ap: ATA port to freeze
 + *
 + *    Freeze @ap.
 + *
 + *    LOCKING:
 + *    None.
 + */
 +void ata_eh_freeze_port(struct ata_port *ap)
 +{
 +      unsigned long flags;
 +
 +      if (!ap->ops->error_handler)
 +              return;
 +
 +      spin_lock_irqsave(&ap->host_set->lock, flags);
 +      __ata_port_freeze(ap);
 +      spin_unlock_irqrestore(&ap->host_set->lock, flags);
 +}
 +
 +/**
 + *    ata_port_thaw_port - EH helper to thaw port
 + *    @ap: ATA port to thaw
 + *
 + *    Thaw frozen port @ap.
 + *
 + *    LOCKING:
 + *    None.
 + */
 +void ata_eh_thaw_port(struct ata_port *ap)
 +{
 +      unsigned long flags;
 +
 +      if (!ap->ops->error_handler)
 +              return;
 +
 +      spin_lock_irqsave(&ap->host_set->lock, flags);
 +
 +      ap->flags &= ~ATA_FLAG_FROZEN;
 +
 +      if (ap->ops->thaw)
 +              ap->ops->thaw(ap);
 +
 +      spin_unlock_irqrestore(&ap->host_set->lock, flags);
 +
 +      DPRINTK("ata%u port thawed\n", ap->id);
 +}
 +
  static void ata_eh_scsidone(struct scsi_cmnd *scmd)
  {
        /* nada */
@@@ -626,778 -261,3 +626,778 @@@ void ata_eh_qc_retry(struct ata_queued_
                scmd->retries--;
        __ata_eh_qc_complete(qc);
  }
 +
 +/**
 + *    ata_eh_about_to_do - about to perform eh_action
 + *    @ap: target ATA port
 + *    @action: action about to be performed
 + *
 + *    Called just before performing EH actions to clear related bits
 + *    in @ap->eh_info such that eh actions are not unnecessarily
 + *    repeated.
 + *
 + *    LOCKING:
 + *    None.
 + */
 +static void ata_eh_about_to_do(struct ata_port *ap, unsigned int action)
 +{
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&ap->host_set->lock, flags);
 +      ap->eh_info.action &= ~action;
 +      ap->flags |= ATA_FLAG_RECOVERED;
 +      spin_unlock_irqrestore(&ap->host_set->lock, flags);
 +}
 +
 +/**
 + *    ata_err_string - convert err_mask to descriptive string
 + *    @err_mask: error mask to convert to string
 + *
 + *    Convert @err_mask to descriptive string.  Errors are
 + *    prioritized according to severity and only the most severe
 + *    error is reported.
 + *
 + *    LOCKING:
 + *    None.
 + *
 + *    RETURNS:
 + *    Descriptive string for @err_mask
 + */
 +static const char * ata_err_string(unsigned int err_mask)
 +{
 +      if (err_mask & AC_ERR_HOST_BUS)
 +              return "host bus error";
 +      if (err_mask & AC_ERR_ATA_BUS)
 +              return "ATA bus error";
 +      if (err_mask & AC_ERR_TIMEOUT)
 +              return "timeout";
 +      if (err_mask & AC_ERR_HSM)
 +              return "HSM violation";
 +      if (err_mask & AC_ERR_SYSTEM)
 +              return "internal error";
 +      if (err_mask & AC_ERR_MEDIA)
 +              return "media error";
 +      if (err_mask & AC_ERR_INVALID)
 +              return "invalid argument";
 +      if (err_mask & AC_ERR_DEV)
 +              return "device error";
 +      return "unknown error";
 +}
 +
 +/**
 + *    atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
 + *    @dev: device to perform REQUEST_SENSE to
 + *    @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
 + *
 + *    Perform ATAPI REQUEST_SENSE after the device reported CHECK
 + *    SENSE.  This function is EH helper.
 + *
 + *    LOCKING:
 + *    Kernel thread context (may sleep).
 + *
 + *    RETURNS:
 + *    0 on success, AC_ERR_* mask on failure
 + */
 +static unsigned int atapi_eh_request_sense(struct ata_device *dev,
 +                                         unsigned char *sense_buf)
 +{
 +      struct ata_port *ap = dev->ap;
 +      struct ata_taskfile tf;
 +      u8 cdb[ATAPI_CDB_LEN];
 +
 +      DPRINTK("ATAPI request sense\n");
 +
 +      ata_tf_init(dev, &tf);
 +
 +      /* FIXME: is this needed? */
 +      memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
 +
 +      /* XXX: why tf_read here? */
 +      ap->ops->tf_read(ap, &tf);
 +
 +      /* fill these in, for the case where they are -not- overwritten */
 +      sense_buf[0] = 0x70;
 +      sense_buf[2] = tf.feature >> 4;
 +
 +      memset(cdb, 0, ATAPI_CDB_LEN);
 +      cdb[0] = REQUEST_SENSE;
 +      cdb[4] = SCSI_SENSE_BUFFERSIZE;
 +
 +      tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 +      tf.command = ATA_CMD_PACKET;
 +
 +      /* is it pointless to prefer PIO for "safety reasons"? */
 +      if (ap->flags & ATA_FLAG_PIO_DMA) {
 +              tf.protocol = ATA_PROT_ATAPI_DMA;
 +              tf.feature |= ATAPI_PKT_DMA;
 +      } else {
 +              tf.protocol = ATA_PROT_ATAPI;
 +              tf.lbam = (8 * 1024) & 0xff;
 +              tf.lbah = (8 * 1024) >> 8;
 +      }
 +
 +      return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
 +                               sense_buf, SCSI_SENSE_BUFFERSIZE);
 +}
 +
 +/**
 + *    ata_eh_analyze_serror - analyze SError for a failed port
 + *    @ap: ATA port to analyze SError for
 + *
 + *    Analyze SError if available and further determine cause of
 + *    failure.
 + *
 + *    LOCKING:
 + *    None.
 + */
 +static void ata_eh_analyze_serror(struct ata_port *ap)
 +{
 +      struct ata_eh_context *ehc = &ap->eh_context;
 +      u32 serror = ehc->i.serror;
 +      unsigned int err_mask = 0, action = 0;
 +
 +      if (serror & SERR_PERSISTENT) {
 +              err_mask |= AC_ERR_ATA_BUS;
 +              action |= ATA_EH_HARDRESET;
 +      }
 +      if (serror &
 +          (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
 +              err_mask |= AC_ERR_ATA_BUS;
 +              action |= ATA_EH_SOFTRESET;
 +      }
 +      if (serror & SERR_PROTOCOL) {
 +              err_mask |= AC_ERR_HSM;
 +              action |= ATA_EH_SOFTRESET;
 +      }
 +      if (serror & SERR_INTERNAL) {
 +              err_mask |= AC_ERR_SYSTEM;
 +              action |= ATA_EH_SOFTRESET;
 +      }
 +      if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) {
 +              err_mask |= AC_ERR_ATA_BUS;
 +              action |= ATA_EH_HARDRESET;
 +      }
 +
 +      ehc->i.err_mask |= err_mask;
 +      ehc->i.action |= action;
 +}
 +
 +/**
 + *    ata_eh_analyze_tf - analyze taskfile of a failed qc
 + *    @qc: qc to analyze
 + *    @tf: Taskfile registers to analyze
 + *
 + *    Analyze taskfile of @qc and further determine cause of
 + *    failure.  This function also requests ATAPI sense data if
 + *    avaliable.
 + *
 + *    LOCKING:
 + *    Kernel thread context (may sleep).
 + *
 + *    RETURNS:
 + *    Determined recovery action
 + */
 +static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
 +                                    const struct ata_taskfile *tf)
 +{
 +      unsigned int tmp, action = 0;
 +      u8 stat = tf->command, err = tf->feature;
 +
 +      if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
 +              qc->err_mask |= AC_ERR_HSM;
 +              return ATA_EH_SOFTRESET;
 +      }
 +
 +      if (!(qc->err_mask & AC_ERR_DEV))
 +              return 0;
 +
 +      switch (qc->dev->class) {
 +      case ATA_DEV_ATA:
 +              if (err & ATA_ICRC)
 +                      qc->err_mask |= AC_ERR_ATA_BUS;
 +              if (err & ATA_UNC)
 +                      qc->err_mask |= AC_ERR_MEDIA;
 +              if (err & ATA_IDNF)
 +                      qc->err_mask |= AC_ERR_INVALID;
 +              break;
 +
 +      case ATA_DEV_ATAPI:
 +              tmp = atapi_eh_request_sense(qc->dev,
 +                                           qc->scsicmd->sense_buffer);
 +              if (!tmp) {
 +                      /* ATA_QCFLAG_SENSE_VALID is used to tell
 +                       * atapi_qc_complete() that sense data is
 +                       * already valid.
 +                       *
 +                       * TODO: interpret sense data and set
 +                       * appropriate err_mask.
 +                       */
 +                      qc->flags |= ATA_QCFLAG_SENSE_VALID;
 +              } else
 +                      qc->err_mask |= tmp;
 +      }
 +
 +      if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
 +              action |= ATA_EH_SOFTRESET;
 +
 +      return action;
 +}
 +
 +static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent)
 +{
 +      if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT))
 +              return 1;
 +
 +      if (ent->is_io) {
 +              if (ent->err_mask & AC_ERR_HSM)
 +                      return 1;
 +              if ((ent->err_mask &
 +                   (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
 +                      return 2;
 +      }
 +
 +      return 0;
 +}
 +
 +struct speed_down_needed_arg {
 +      u64 since;
 +      int nr_errors[3];
 +};
 +
 +static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg)
 +{
 +      struct speed_down_needed_arg *arg = void_arg;
 +
 +      if (ent->timestamp < arg->since)
 +              return -1;
 +
 +      arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++;
 +      return 0;
 +}
 +
 +/**
 + *    ata_eh_speed_down_needed - Determine wheter speed down is necessary
 + *    @dev: Device of interest
 + *
 + *    This function examines error ring of @dev and determines
 + *    whether speed down is necessary.  Speed down is necessary if
 + *    there have been more than 3 of Cat-1 errors or 10 of Cat-2
 + *    errors during last 15 minutes.
 + *
 + *    Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM
 + *    violation for known supported commands.
 + *
 + *    Cat-2 errors are unclassified DEV error for known supported
 + *    command.
 + *
 + *    LOCKING:
 + *    Inherited from caller.
 + *
 + *    RETURNS:
 + *    1 if speed down is necessary, 0 otherwise
 + */
 +static int ata_eh_speed_down_needed(struct ata_device *dev)
 +{
 +      const u64 interval = 15LLU * 60 * HZ;
 +      static const int err_limits[3] = { -1, 3, 10 };
 +      struct speed_down_needed_arg arg;
 +      struct ata_ering_entry *ent;
 +      int err_cat;
 +      u64 j64;
 +
 +      ent = ata_ering_top(&dev->ering);
 +      if (!ent)
 +              return 0;
 +
 +      err_cat = ata_eh_categorize_ering_entry(ent);
 +      if (err_cat == 0)
 +              return 0;
 +
 +      memset(&arg, 0, sizeof(arg));
 +
 +      j64 = get_jiffies_64();
 +      if (j64 >= interval)
 +              arg.since = j64 - interval;
 +      else
 +              arg.since = 0;
 +
 +      ata_ering_map(&dev->ering, speed_down_needed_cb, &arg);
 +
 +      return arg.nr_errors[err_cat] > err_limits[err_cat];
 +}
 +
 +/**
 + *    ata_eh_speed_down - record error and speed down if necessary
 + *    @dev: Failed device
 + *    @is_io: Did the device fail during normal IO?
 + *    @err_mask: err_mask of the error
 + *
 + *    Record error and examine error history to determine whether
 + *    adjusting transmission speed is necessary.  It also sets
 + *    transmission limits appropriately if such adjustment is
 + *    necessary.
 + *
 + *    LOCKING:
 + *    Kernel thread context (may sleep).
 + *
 + *    RETURNS:
 + *    0 on success, -errno otherwise
 + */
 +static int ata_eh_speed_down(struct ata_device *dev, int is_io,
 +                           unsigned int err_mask)
 +{
 +      if (!err_mask)
 +              return 0;
 +
 +      /* record error and determine whether speed down is necessary */
 +      ata_ering_record(&dev->ering, is_io, err_mask);
 +
 +      if (!ata_eh_speed_down_needed(dev))
 +              return 0;
 +
 +      /* speed down SATA link speed if possible */
 +      if (sata_down_spd_limit(dev->ap) == 0)
 +              return ATA_EH_HARDRESET;
 +
 +      /* lower transfer mode */
 +      if (ata_down_xfermask_limit(dev, 0) == 0)
 +              return ATA_EH_SOFTRESET;
 +
 +      ata_dev_printk(dev, KERN_ERR,
 +                     "speed down requested but no transfer mode left\n");
 +      return 0;
 +}
 +
 +/**
 + *    ata_eh_autopsy - analyze error and determine recovery action
 + *    @ap: ATA port to perform autopsy on
 + *
 + *    Analyze why @ap failed and determine which recovery action is
 + *    needed.  This function also sets more detailed AC_ERR_* values
 + *    and fills sense data for ATAPI CHECK SENSE.
 + *
 + *    LOCKING:
 + *    Kernel thread context (may sleep).
 + */
 +static void ata_eh_autopsy(struct ata_port *ap)
 +{
 +      struct ata_eh_context *ehc = &ap->eh_context;
 +      unsigned int action = ehc->i.action;
 +      struct ata_device *failed_dev = NULL;
 +      unsigned int all_err_mask = 0;
 +      int tag, is_io = 0;
 +      u32 serror;
 +      int rc;
 +
 +      DPRINTK("ENTER\n");
 +
 +      /* obtain and analyze SError */
 +      rc = sata_scr_read(ap, SCR_ERROR, &serror);
 +      if (rc == 0) {
 +              ehc->i.serror |= serror;
 +              ata_eh_analyze_serror(ap);
 +      } else if (rc != -EOPNOTSUPP)
 +              action |= ATA_EH_HARDRESET;
 +
 +      /* any real error trumps AC_ERR_OTHER */
 +      if (ehc->i.err_mask & ~AC_ERR_OTHER)
 +              ehc->i.err_mask &= ~AC_ERR_OTHER;
 +
 +      all_err_mask |= ehc->i.err_mask;
 +
 +      for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
 +              struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
 +
 +              if (!(qc->flags & ATA_QCFLAG_FAILED))
 +                      continue;
 +
 +              /* inherit upper level err_mask */
 +              qc->err_mask |= ehc->i.err_mask;
 +
 +              if (qc->err_mask & AC_ERR_TIMEOUT)
 +                      action |= ATA_EH_SOFTRESET;
 +
 +              /* analyze TF */
 +              action |= ata_eh_analyze_tf(qc, &qc->result_tf);
 +
 +              /* DEV errors are probably spurious in case of ATA_BUS error */
 +              if (qc->err_mask & AC_ERR_ATA_BUS)
 +                      qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA |
 +                                        AC_ERR_INVALID);
 +
 +              /* any real error trumps unknown error */
 +              if (qc->err_mask & ~AC_ERR_OTHER)
 +                      qc->err_mask &= ~AC_ERR_OTHER;
 +
 +              /* SENSE_VALID trumps dev/unknown error and revalidation */
 +              if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
 +                      qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
 +                      action &= ~ATA_EH_REVALIDATE;
 +              }
 +
 +              /* accumulate error info */
 +              failed_dev = qc->dev;
 +              all_err_mask |= qc->err_mask;
 +              if (qc->flags & ATA_QCFLAG_IO)
 +                      is_io = 1;
 +      }
 +
 +      /* speed down iff command was in progress */
 +      if (failed_dev)
 +              action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask);
 +
 +      if (all_err_mask)
 +              action |= ATA_EH_REVALIDATE;
 +
 +      ehc->i.dev = failed_dev;
 +      ehc->i.action = action;
 +
 +      DPRINTK("EXIT\n");
 +}
 +
 +/**
 + *    ata_eh_report - report error handling to user
 + *    @ap: ATA port EH is going on
 + *
 + *    Report EH to user.
 + *
 + *    LOCKING:
 + *    None.
 + */
 +static void ata_eh_report(struct ata_port *ap)
 +{
 +      struct ata_eh_context *ehc = &ap->eh_context;
 +      const char *frozen, *desc;
 +      int tag, nr_failed = 0;
 +
 +      desc = NULL;
 +      if (ehc->i.desc[0] != '\0')
 +              desc = ehc->i.desc;
 +
 +      for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
 +              struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
 +
 +              if (!(qc->flags & ATA_QCFLAG_FAILED))
 +                      continue;
 +              if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
 +                      continue;
 +
 +              nr_failed++;
 +      }
 +
 +      if (!nr_failed && !ehc->i.err_mask)
 +              return;
 +
 +      frozen = "";
 +      if (ap->flags & ATA_FLAG_FROZEN)
 +              frozen = " frozen";
 +
 +      if (ehc->i.dev) {
 +              ata_dev_printk(ehc->i.dev, KERN_ERR,
 +                             "exception Emask 0x%x SErr 0x%x action 0x%x%s\n",
 +                             ehc->i.err_mask, ehc->i.serror, ehc->i.action,
 +                             frozen);
 +              if (desc)
 +                      ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
 +      } else {
 +              ata_port_printk(ap, KERN_ERR,
 +                              "exception Emask 0x%x SErr 0x%x action 0x%x%s\n",
 +                              ehc->i.err_mask, ehc->i.serror, ehc->i.action,
 +                              frozen);
 +              if (desc)
 +                      ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
 +      }
 +
 +      for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
 +              struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
 +
 +              if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
 +                      continue;
 +
 +              ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
 +                             "Emask 0x%x stat 0x%x err 0x%x (%s)\n",
 +                             qc->tag, qc->tf.command, qc->err_mask,
 +                             qc->result_tf.command, qc->result_tf.feature,
 +                             ata_err_string(qc->err_mask));
 +      }
 +}
 +
 +static int ata_eh_reset(struct ata_port *ap, ata_reset_fn_t softreset,
 +                      ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
 +{
 +      struct ata_eh_context *ehc = &ap->eh_context;
 +      unsigned int classes[ATA_MAX_DEVICES];
 +      int tries = ATA_EH_RESET_TRIES;
 +      ata_reset_fn_t reset;
 +      int rc;
 +
 +      if (softreset && (!hardreset || (!sata_set_spd_needed(ap) &&
 +                                       !(ehc->i.action & ATA_EH_HARDRESET))))
 +              reset = softreset;
 +      else
 +              reset = hardreset;
 +
 + retry:
 +      ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
 +                      reset == softreset ? "soft" : "hard");
 +
 +      /* reset */
 +      ata_eh_about_to_do(ap, ATA_EH_RESET_MASK);
 +      ehc->i.flags |= ATA_EHI_DID_RESET;
 +
 +      rc = ata_do_reset(ap, reset, classes);
 +
 +      if (rc && --tries) {
 +              ata_port_printk(ap, KERN_WARNING,
 +                              "%sreset failed, retrying in 5 secs\n",
 +                              reset == softreset ? "soft" : "hard");
 +              ssleep(5);
 +
 +              if (reset == hardreset)
 +                      sata_down_spd_limit(ap);
 +              if (hardreset)
 +                      reset = hardreset;
 +              goto retry;
 +      }
 +
 +      if (rc == 0) {
 +              if (postreset)
 +                      postreset(ap, classes);
 +
 +              /* reset successful, schedule revalidation */
 +              ehc->i.dev = NULL;
 +              ehc->i.action &= ~ATA_EH_RESET_MASK;
 +              ehc->i.action |= ATA_EH_REVALIDATE;
 +      }
 +
 +      return rc;
 +}
 +
 +static int ata_eh_revalidate(struct ata_port *ap,
 +                           struct ata_device **r_failed_dev)
 +{
 +      struct ata_eh_context *ehc = &ap->eh_context;
 +      struct ata_device *dev;
 +      int i, rc = 0;
 +
 +      DPRINTK("ENTER\n");
 +
 +      for (i = 0; i < ATA_MAX_DEVICES; i++) {
 +              dev = &ap->device[i];
 +
 +              if (ehc->i.action & ATA_EH_REVALIDATE && ata_dev_enabled(dev) &&
 +                  (!ehc->i.dev || ehc->i.dev == dev)) {
 +                      if (ata_port_offline(ap)) {
 +                              rc = -EIO;
 +                              break;
 +                      }
 +
 +                      ata_eh_about_to_do(ap, ATA_EH_REVALIDATE);
 +                      rc = ata_dev_revalidate(dev,
 +                                      ehc->i.flags & ATA_EHI_DID_RESET);
 +                      if (rc)
 +                              break;
 +
 +                      ehc->i.action &= ~ATA_EH_REVALIDATE;
 +              }
 +      }
 +
 +      if (rc)
 +              *r_failed_dev = dev;
 +
 +      DPRINTK("EXIT\n");
 +      return rc;
 +}
 +
 +static int ata_port_nr_enabled(struct ata_port *ap)
 +{
 +      int i, cnt = 0;
 +
 +      for (i = 0; i < ATA_MAX_DEVICES; i++)
 +              if (ata_dev_enabled(&ap->device[i]))
 +                      cnt++;
 +      return cnt;
 +}
 +
 +/**
 + *    ata_eh_recover - recover host port after error
 + *    @ap: host port to recover
 + *    @softreset: softreset method (can be NULL)
 + *    @hardreset: hardreset method (can be NULL)
 + *    @postreset: postreset method (can be NULL)
 + *
 + *    This is the alpha and omega, eum and yang, heart and soul of
 + *    libata exception handling.  On entry, actions required to
 + *    recover each devices are recorded in eh_context.  This
 + *    function executes all the operations with appropriate retrials
 + *    and fallbacks to resurrect failed devices.
 + *
 + *    LOCKING:
 + *    Kernel thread context (may sleep).
 + *
 + *    RETURNS:
 + *    0 on success, -errno on failure.
 + */
 +static int ata_eh_recover(struct ata_port *ap, ata_reset_fn_t softreset,
 +                        ata_reset_fn_t hardreset,
 +                        ata_postreset_fn_t postreset)
 +{
 +      struct ata_eh_context *ehc = &ap->eh_context;
 +      struct ata_device *dev;
 +      int down_xfermask, i, rc;
 +
 +      DPRINTK("ENTER\n");
 +
 +      /* prep for recovery */
 +      for (i = 0; i < ATA_MAX_DEVICES; i++) {
 +              dev = &ap->device[i];
 +
 +              ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
 +      }
 +
 + retry:
 +      down_xfermask = 0;
 +      rc = 0;
 +
 +      /* skip EH if possible. */
 +      if (!ata_port_nr_enabled(ap) && !(ap->flags & ATA_FLAG_FROZEN))
 +              ehc->i.action = 0;
 +
 +      /* reset */
 +      if (ehc->i.action & ATA_EH_RESET_MASK) {
 +              ata_eh_freeze_port(ap);
 +
 +              rc = ata_eh_reset(ap, softreset, hardreset, postreset);
 +              if (rc) {
 +                      ata_port_printk(ap, KERN_ERR,
 +                                      "reset failed, giving up\n");
 +                      goto out;
 +              }
 +
 +              ata_eh_thaw_port(ap);
 +      }
 +
 +      /* revalidate existing devices */
 +      rc = ata_eh_revalidate(ap, &dev);
 +      if (rc)
 +              goto dev_fail;
 +
 +      /* configure transfer mode if the port has been reset */
 +      if (ehc->i.flags & ATA_EHI_DID_RESET) {
 +              rc = ata_set_mode(ap, &dev);
 +              if (rc) {
 +                      down_xfermask = 1;
 +                      goto dev_fail;
 +              }
 +      }
 +
 +      goto out;
 +
 + dev_fail:
 +      switch (rc) {
 +      case -ENODEV:
 +      case -EINVAL:
 +              ehc->tries[dev->devno] = 0;
 +              break;
 +      case -EIO:
 +              sata_down_spd_limit(ap);
 +      default:
 +              ehc->tries[dev->devno]--;
 +              if (down_xfermask &&
 +                  ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1))
 +                      ehc->tries[dev->devno] = 0;
 +      }
 +
 +      /* disable device if it has used up all its chances */
 +      if (ata_dev_enabled(dev) && !ehc->tries[dev->devno])
 +              ata_dev_disable(dev);
 +
 +      /* soft didn't work?  be haaaaard */
 +      if (ehc->i.flags & ATA_EHI_DID_RESET)
 +              ehc->i.action |= ATA_EH_HARDRESET;
 +      else
 +              ehc->i.action |= ATA_EH_SOFTRESET;
 +
 +      if (ata_port_nr_enabled(ap)) {
 +              ata_port_printk(ap, KERN_WARNING, "failed to recover some "
 +                              "devices, retrying in 5 secs\n");
 +              ssleep(5);
 +      } else {
 +              /* no device left, repeat fast */
 +              msleep(500);
 +      }
 +
 +      goto retry;
 +
 + out:
 +      if (rc) {
 +              for (i = 0; i < ATA_MAX_DEVICES; i++)
 +                      ata_dev_disable(&ap->device[i]);
 +      }
 +
 +      DPRINTK("EXIT, rc=%d\n", rc);
 +      return rc;
 +}
 +
 +/**
 + *    ata_eh_finish - finish up EH
 + *    @ap: host port to finish EH for
 + *
 + *    Recovery is complete.  Clean up EH states and retry or finish
 + *    failed qcs.
 + *
 + *    LOCKING:
 + *    None.
 + */
 +static void ata_eh_finish(struct ata_port *ap)
 +{
 +      int tag;
 +
 +      /* retry or finish qcs */
 +      for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
 +              struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
 +
 +              if (!(qc->flags & ATA_QCFLAG_FAILED))
 +                      continue;
 +
 +              if (qc->err_mask) {
 +                      /* FIXME: Once EH migration is complete,
 +                       * generate sense data in this function,
 +                       * considering both err_mask and tf.
 +                       */
 +                      if (qc->err_mask & AC_ERR_INVALID)
 +                              ata_eh_qc_complete(qc);
 +                      else
 +                              ata_eh_qc_retry(qc);
 +              } else {
 +                      if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
 +                              ata_eh_qc_complete(qc);
 +                      } else {
 +                              /* feed zero TF to sense generation */
 +                              memset(&qc->result_tf, 0, sizeof(qc->result_tf));
 +                              ata_eh_qc_retry(qc);
 +                      }
 +              }
 +      }
 +}
 +
 +/**
 + *    ata_do_eh - do standard error handling
 + *    @ap: host port to handle error for
 + *    @softreset: softreset method (can be NULL)
 + *    @hardreset: hardreset method (can be NULL)
 + *    @postreset: postreset method (can be NULL)
 + *
 + *    Perform standard error handling sequence.
 + *
 + *    LOCKING:
 + *    Kernel thread context (may sleep).
 + */
 +void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset,
 +             ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
 +{
 +      ata_eh_autopsy(ap);
 +      ata_eh_report(ap);
 +      ata_eh_recover(ap, softreset, hardreset, postreset);
 +      ata_eh_finish(ap);
 +}
diff --combined drivers/scsi/sata_mv.c
index e8d00f0efdf2051bde4b005df2cf6b9f03feb92f,670ef16a843783039d516ce66e44480f2c633da9..e6d141dd0385b20d3f3fb54913d98e37e0987790
@@@ -87,7 -87,7 +87,7 @@@ enum 
        MV_FLAG_IRQ_COALESCE    = (1 << 29),  /* IRQ coalescing capability */
        MV_COMMON_FLAGS         = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-                                  ATA_FLAG_NO_ATAPI),
+                                  ATA_FLAG_PIO_POLLING),
        MV_6XXX_FLAGS           = MV_FLAG_IRQ_COALESCE,
  
        CRQB_FLAG_READ          = (1 << 0),
@@@ -680,7 -680,7 +680,7 @@@ static void mv_stop_dma(struct ata_por
        }
  
        if (EDMA_EN & reg) {
 -              printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
 +              ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
                /* FIXME: Consider doing a reset here to recover */
        }
  }
@@@ -1309,8 -1309,8 +1309,8 @@@ static void mv_err_intr(struct ata_por
        edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
  
        if (EDMA_ERR_SERR & edma_err_cause) {
 -              serr = scr_read(ap, SCR_ERROR);
 -              scr_write_flush(ap, SCR_ERROR, serr);
 +              sata_scr_read(ap, SCR_ERROR, &serr);
 +              sata_scr_write_flush(ap, SCR_ERROR, serr);
        }
        if (EDMA_ERR_SELF_DIS & edma_err_cause) {
                struct mv_port_priv *pp = ap->private_data;
@@@ -1396,7 -1396,7 +1396,7 @@@ static void mv_host_intr(struct ata_hos
                        }
                }
  
-               if (ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))
+               if (ap && (ap->flags & ATA_FLAG_DISABLED))
                        continue;
  
                err_mask = ac_err_mask(ata_status);
                                VPRINTK("port %u IRQ found for qc, "
                                        "ata_status 0x%x\n", port,ata_status);
                                /* mark qc status appropriately */
-                               if (!(qc->tf.ctl & ATA_NIEN)) {
+                               if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
                                        qc->err_mask |= err_mask;
                                        ata_qc_complete(qc);
                                }
@@@ -1934,16 -1934,15 +1934,16 @@@ static void __mv_phy_reset(struct ata_p
  
        /* Issue COMRESET via SControl */
  comreset_retry:
 -      scr_write_flush(ap, SCR_CONTROL, 0x301);
 +      sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
        __msleep(1, can_sleep);
  
 -      scr_write_flush(ap, SCR_CONTROL, 0x300);
 +      sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
        __msleep(20, can_sleep);
  
        timeout = jiffies + msecs_to_jiffies(200);
        do {
 -              sstatus = scr_read(ap, SCR_STATUS) & 0x3;
 +              sata_scr_read(ap, SCR_STATUS, &sstatus);
 +              sstatus &= 0x3;
                if ((sstatus == 3) || (sstatus == 0))
                        break;
  
                "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
                mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
  
 -      if (sata_dev_present(ap)) {
 +      if (ata_port_online(ap)) {
                ata_port_probe(ap);
        } else {
 -              printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
 -                     ap->id, scr_read(ap, SCR_STATUS));
 +              sata_scr_read(ap, SCR_STATUS, &sstatus);
 +              ata_port_printk(ap, KERN_INFO,
 +                              "no device found (phy stat %08x)\n", sstatus);
                ata_port_disable(ap);
                return;
        }
@@@ -2023,7 -2021,7 +2023,7 @@@ static void mv_eng_timeout(struct ata_p
  {
        struct ata_queued_cmd *qc;
  
 -      printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
 +      ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
        DPRINTK("All regs @ start of eng_timeout\n");
        mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
                         to_pci_dev(ap->host_set->dev));
index e9d61bc2b24730bd9595406f00c6a0d6aeae130f,aaf896a0c63ad38513210ac2ea2372adb0820e43..bb000438cb6c0a578aed45cd1a85ab6b415a838e
@@@ -76,7 -76,8 +76,8 @@@ enum 
        PDC_RESET               = (1 << 11), /* HDMA reset */
  
        PDC_COMMON_FLAGS        = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
-                                 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI,
+                                 ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+                                 ATA_FLAG_PIO_POLLING,
  };
  
  
@@@ -435,7 -436,7 +436,7 @@@ static void pdc_eng_timeout(struct ata_
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
        case ATA_PROT_NODATA:
 -              printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 +              ata_port_printk(ap, KERN_ERR, "command timeout\n");
                drv_stat = ata_wait_idle(ap);
                qc->err_mask |= __ac_err_mask(drv_stat);
                break;
        default:
                drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
  
 -              printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 -                     ap->id, qc->tf.command, drv_stat);
 +              ata_port_printk(ap, KERN_ERR,
 +                              "unknown timeout, cmd 0x%x stat 0x%x\n",
 +                              qc->tf.command, drv_stat);
  
                qc->err_mask |= ac_err_mask(drv_stat);
                break;
@@@ -534,11 -534,11 +535,11 @@@ static irqreturn_t pdc_interrupt (int i
                ap = host_set->ports[i];
                tmp = mask & (1 << (i + 1));
                if (tmp && ap &&
-                   !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) {
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
                        struct ata_queued_cmd *qc;
  
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
                                handled += pdc_host_intr(ap, qc);
                }
        }
diff --combined drivers/scsi/sata_sx4.c
index 96d7b73f5fdc985b9f1320522dfe63489e982467,4c07ba1f6e62c7cd443af43aa97dfb7c9287a1eb..70a695488291b33d179ec900448225dc8ec95e2a
@@@ -218,7 -218,7 +218,7 @@@ static const struct ata_port_info pdc_p
                .sht            = &pdc_sata_sht,
                .host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_SRST | ATA_FLAG_MMIO |
-                                 ATA_FLAG_NO_ATAPI,
+                                 ATA_FLAG_PIO_POLLING,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0x07, /* mwdma0-2 */
                .udma_mask      = 0x7f, /* udma0-6 ; FIXME */
@@@ -833,11 -833,11 +833,11 @@@ static irqreturn_t pdc20621_interrupt (
                tmp = mask & (1 << i);
                VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
                if (tmp && ap &&
-                   !(ap->flags & (ATA_FLAG_DISABLED | ATA_FLAG_NOINTR))) {
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
                        struct ata_queued_cmd *qc;
  
                        qc = ata_qc_from_tag(ap, ap->active_tag);
-                       if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
                                handled += pdc20621_host_intr(ap, qc, (i > 4),
                                                              mmio_base);
                }
@@@ -868,16 -868,15 +868,16 @@@ static void pdc_eng_timeout(struct ata_
        switch (qc->tf.protocol) {
        case ATA_PROT_DMA:
        case ATA_PROT_NODATA:
 -              printk(KERN_ERR "ata%u: command timeout\n", ap->id);
 +              ata_port_printk(ap, KERN_ERR, "command timeout\n");
                qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
                break;
  
        default:
                drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
  
 -              printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
 -                     ap->id, qc->tf.command, drv_stat);
 +              ata_port_printk(ap, KERN_ERR,
 +                              "unknown timeout, cmd 0x%x stat 0x%x\n",
 +                              qc->tf.command, drv_stat);
  
                qc->err_mask |= ac_err_mask(drv_stat);
                break;
diff --combined include/linux/ata.h
index a7c41f3df8f4282bb0329eb6992d20547c96b745,206d859083ea3cab0bc509cd100eb35f73e7d54b..1cbeb434af9a7e486474fc66114ae6c11564870d
@@@ -97,9 -97,6 +97,9 @@@ enum 
        ATA_DRQ                 = (1 << 3),     /* data request i/o */
        ATA_ERR                 = (1 << 0),     /* have an error */
        ATA_SRST                = (1 << 2),     /* software reset */
 +      ATA_ICRC                = (1 << 7),     /* interface CRC error */
 +      ATA_UNC                 = (1 << 6),     /* uncorrectable media error */
 +      ATA_IDNF                = (1 << 4),     /* ID not found */
        ATA_ABORTED             = (1 << 2),     /* command aborted */
  
        /* ATA command block registers */
        SCR_ACTIVE              = 3,
        SCR_NOTIFICATION        = 4,
  
 +      /* SError bits */
 +      SERR_DATA_RECOVERED     = (1 << 0), /* recovered data error */
 +      SERR_COMM_RECOVERED     = (1 << 1), /* recovered comm failure */
 +      SERR_DATA               = (1 << 8), /* unrecovered data error */
 +      SERR_PERSISTENT         = (1 << 9), /* persistent data/comm error */
 +      SERR_PROTOCOL           = (1 << 10), /* protocol violation */
 +      SERR_INTERNAL           = (1 << 11), /* host internal error */
 +      SERR_PHYRDY_CHG         = (1 << 16), /* PHY RDY changed */
 +      SERR_DEV_XCHG           = (1 << 26), /* device exchanged */
 +
        /* struct ata_taskfile flags */
        ATA_TFLAG_LBA48         = (1 << 0), /* enable 48-bit LBA and "HOB" */
        ATA_TFLAG_ISADDR        = (1 << 1), /* enable r/w to nsect/lba regs */
        ATA_TFLAG_WRITE         = (1 << 3), /* data dir: host->dev==1 (write) */
        ATA_TFLAG_LBA           = (1 << 4), /* enable LBA */
        ATA_TFLAG_FUA           = (1 << 5), /* enable FUA */
+       ATA_TFLAG_POLLING       = (1 << 6), /* set nIEN to 1 and use polling */
  };
  
  enum ata_tf_protocols {
@@@ -285,6 -273,8 +286,8 @@@ struct ata_taskfile 
          ((u64) (id)[(n) + 1] << 16) | \
          ((u64) (id)[(n) + 0]) )
  
+ #define ata_id_cdb_intr(id)   (((id)[0] & 0x60) == 0x20)
  static inline unsigned int ata_id_major_version(const u16 *id)
  {
        unsigned int mver;
@@@ -324,6 -314,15 +327,15 @@@ static inline int is_atapi_taskfile(con
               (tf->protocol == ATA_PROT_ATAPI_DMA);
  }
  
+ static inline int is_multi_taskfile(struct ata_taskfile *tf)
+ {
+       return (tf->command == ATA_CMD_READ_MULTI) ||
+              (tf->command == ATA_CMD_WRITE_MULTI) ||
+              (tf->command == ATA_CMD_READ_MULTI_EXT) ||
+              (tf->command == ATA_CMD_WRITE_MULTI_EXT) ||
+              (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT);
+ }
  static inline int ata_ok(u8 status)
  {
        return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
diff --combined include/linux/libata.h
index 6ccacbf889e3b6a79b2376529f953e7f34293cca,bf86ee474533663d0acbb891d0bd4850bc391d1c..db17723e23fb2664649be535850c78195121c637
@@@ -108,9 -108,7 +108,9 @@@ enum 
        LIBATA_MAX_PRD          = ATA_MAX_PRD / 2,
        ATA_MAX_PORTS           = 8,
        ATA_DEF_QUEUE           = 1,
 -      ATA_MAX_QUEUE           = 1,
 +      /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
 +      ATA_MAX_QUEUE           = 2,
 +      ATA_TAG_INTERNAL        = ATA_MAX_QUEUE - 1,
        ATA_MAX_SECTORS         = 200,  /* FIXME */
        ATA_MAX_BUS             = 2,
        ATA_DEF_BUSY_WAIT       = 10000,
        /* struct ata_device stuff */
        ATA_DFLAG_LBA           = (1 << 0), /* device supports LBA */
        ATA_DFLAG_LBA48         = (1 << 1), /* device supports LBA48 */
+       ATA_DFLAG_CDB_INTR      = (1 << 2), /* device asserts INTRQ when ready for CDB */
        ATA_DFLAG_CFG_MASK      = (1 << 8) - 1,
  
        ATA_DFLAG_PIO           = (1 << 8), /* device currently in PIO mode */
        ATA_FLAG_PIO_DMA        = (1 << 7), /* PIO cmds via DMA */
        ATA_FLAG_PIO_LBA48      = (1 << 8), /* Host DMA engine is LBA28 only */
        ATA_FLAG_IRQ_MASK       = (1 << 9), /* Mask IRQ in PIO xfers */
+       ATA_FLAG_PIO_POLLING    = (1 << 10), /* use polling PIO if LLD
+                                             * doesn't handle PIO interrupts */
  
-       ATA_FLAG_NOINTR         = (1 << 13), /* FIXME: Remove this once
-                                             * proper HSM is in place. */
 -      ATA_FLAG_DEBUGMSG       = (1 << 17),
 -      ATA_FLAG_FLUSH_PORT_TASK = (1 << 18), /* flush port task */
 +      ATA_FLAG_DEBUGMSG       = (1 << 14),
 +      ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* flush port task */
  
 -      ATA_FLAG_DISABLED       = (1 << 19), /* port is disabled, ignore it */
 -      ATA_FLAG_SUSPENDED      = (1 << 20), /* port is suspended */
 +      ATA_FLAG_EH_PENDING     = (1 << 16), /* EH pending */
 +      ATA_FLAG_FROZEN         = (1 << 17), /* port is frozen */
 +      ATA_FLAG_RECOVERED      = (1 << 18), /* recovery action performed */
 +
 +      ATA_FLAG_DISABLED       = (1 << 22), /* port is disabled, ignore it */
 +      ATA_FLAG_SUSPENDED      = (1 << 23), /* port is suspended (power) */
  
        /* bits 24:31 of ap->flags are reserved for LLDD specific flags */
  
        ATA_QCFLAG_SINGLE       = (1 << 2), /* no s/g, just a single buffer */
        ATA_QCFLAG_DMAMAP       = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
        ATA_QCFLAG_IO           = (1 << 3), /* standard IO command */
 -      ATA_QCFLAG_EH_SCHEDULED = (1 << 4), /* EH scheduled */
 +      ATA_QCFLAG_RESULT_TF    = (1 << 4), /* result TF requested */
 +
 +      ATA_QCFLAG_FAILED       = (1 << 16), /* cmd failed and is owned by EH */
 +      ATA_QCFLAG_SENSE_VALID  = (1 << 17), /* sense data valid */
 +      ATA_QCFLAG_EH_SCHEDULED = (1 << 18), /* EH scheduled (obsolete) */
  
        /* host set flags */
        ATA_HOST_SIMPLEX        = (1 << 0),     /* Host is simplex, one DMA channel per host_set only */
        
        /* various lengths of time */
-       ATA_TMOUT_PIO           = 30 * HZ,
        ATA_TMOUT_BOOT          = 30 * HZ,      /* heuristic */
        ATA_TMOUT_BOOT_QUICK    = 7 * HZ,       /* heuristic */
-       ATA_TMOUT_CDB           = 30 * HZ,
-       ATA_TMOUT_CDB_QUICK     = 5 * HZ,
        ATA_TMOUT_INTERNAL      = 30 * HZ,
        ATA_TMOUT_INTERNAL_QUICK = 5 * HZ,
  
        ATA_PORT_PRIMARY        = (1 << 0),
        ATA_PORT_SECONDARY      = (1 << 1),
  
 +      /* ering size */
 +      ATA_ERING_SIZE          = 32,
 +
 +      /* desc_len for ata_eh_info and context */
 +      ATA_EH_DESC_LEN         = 80,
 +
 +      /* reset / recovery action types */
 +      ATA_EH_REVALIDATE       = (1 << 0),
 +      ATA_EH_SOFTRESET        = (1 << 1),
 +      ATA_EH_HARDRESET        = (1 << 2),
 +
 +      ATA_EH_RESET_MASK       = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
 +
 +      /* ata_eh_info->flags */
 +      ATA_EHI_DID_RESET       = (1 << 0), /* already reset this port */
 +
 +      /* max repeat if error condition is still set after ->error_handler */
 +      ATA_EH_MAX_REPEAT       = 5,
 +
        /* how hard are we gonna try to probe/recover devices */
        ATA_PROBE_MAX_TRIES     = 3,
 +      ATA_EH_RESET_TRIES      = 3,
 +      ATA_EH_DEV_TRIES        = 3,
  };
  
  enum hsm_task_states {
-       HSM_ST_UNKNOWN,
-       HSM_ST_IDLE,
-       HSM_ST_POLL,
-       HSM_ST_TMOUT,
-       HSM_ST,
-       HSM_ST_LAST,
-       HSM_ST_LAST_POLL,
-       HSM_ST_ERR,
+       HSM_ST_UNKNOWN,         /* state unknown */
+       HSM_ST_IDLE,            /* no command on going */
+       HSM_ST,                 /* (waiting the device to) transfer data */
+       HSM_ST_LAST,            /* (waiting the device to) complete command */
+       HSM_ST_ERR,             /* error */
+       HSM_ST_FIRST,           /* (waiting the device to)
+                                  write CDB or first data block */
  };
  
  enum ata_completion_errors {
@@@ -374,7 -340,7 +371,7 @@@ struct ata_queued_cmd 
        struct scatterlist      *__sg;
  
        unsigned int            err_mask;
 -
 +      struct ata_taskfile     result_tf;
        ata_qc_cb_t             complete_fn;
  
        void                    *private_data;
@@@ -386,24 -352,12 +383,24 @@@ struct ata_host_stats 
        unsigned long           rw_reqbuf;
  };
  
 +struct ata_ering_entry {
 +      int                     is_io;
 +      unsigned int            err_mask;
 +      u64                     timestamp;
 +};
 +
 +struct ata_ering {
 +      int                     cursor;
 +      struct ata_ering_entry  ring[ATA_ERING_SIZE];
 +};
 +
  struct ata_device {
 +      struct ata_port         *ap;
        u64                     n_sectors;      /* size of device, if ATA */
        unsigned long           flags;          /* ATA_DFLAG_xxx */
        unsigned int            class;          /* ATA_DEV_xxx */
        unsigned int            devno;          /* 0 or 1 */
 -      u16                     *id;            /* IDENTIFY xxx DEVICE data */
 +      u16                     id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
        u8                      pio_mode;
        u8                      dma_mode;
        u8                      xfer_mode;
        u16                     cylinders;      /* Number of cylinders */
        u16                     heads;          /* Number of heads */
        u16                     sectors;        /* Number of sectors per track */
 +
 +      /* error history */
 +      struct ata_ering        ering;
 +};
 +
 +struct ata_eh_info {
 +      struct ata_device       *dev;           /* offending device */
 +      u32                     serror;         /* SError from LLDD */
 +      unsigned int            err_mask;       /* port-wide err_mask */
 +      unsigned int            action;         /* ATA_EH_* action mask */
 +      unsigned int            flags;          /* ATA_EHI_* flags */
 +      char                    desc[ATA_EH_DESC_LEN];
 +      int                     desc_len;
 +};
 +
 +struct ata_eh_context {
 +      struct ata_eh_info      i;
 +      int                     tries[ATA_MAX_DEVICES];
  };
  
  struct ata_port {
        unsigned int            cbl;    /* cable type; ATA_CBL_xxx */
        unsigned int            sata_spd_limit; /* SATA PHY speed limit */
  
 +      /* record runtime error info, protected by host_set lock */
 +      struct ata_eh_info      eh_info;
 +      /* EH context owned by EH */
 +      struct ata_eh_context   eh_context;
 +
        struct ata_device       device[ATA_MAX_DEVICES];
  
        struct ata_queued_cmd   qcmd[ATA_MAX_QUEUE];
        struct work_struct      port_task;
  
        unsigned int            hsm_task_state;
-       unsigned long           pio_task_timeout;
  
        u32                     msg_enable;
        struct list_head        eh_done_q;
  
        void                    *private_data;
 +
 +      u8                      sector_buf[ATA_SECT_SIZE]; /* owned by EH */
  };
  
  struct ata_port_operations {
        void (*qc_prep) (struct ata_queued_cmd *qc);
        unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
  
 -      void (*eng_timeout) (struct ata_port *ap);
 +      /* Error handlers.  ->error_handler overrides ->eng_timeout and
 +       * indicates that new-style EH is in place.
 +       */
 +      void (*eng_timeout) (struct ata_port *ap); /* obsolete */
 +
 +      void (*freeze) (struct ata_port *ap);
 +      void (*thaw) (struct ata_port *ap);
 +      void (*error_handler) (struct ata_port *ap);
 +      void (*post_internal_cmd) (struct ata_queued_cmd *qc);
  
        irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
        void (*irq_clear) (struct ata_port *);
@@@ -580,7 -500,7 +576,7 @@@ extern void ata_port_probe(struct ata_p
  extern void __sata_phy_reset(struct ata_port *ap);
  extern void sata_phy_reset(struct ata_port *ap);
  extern void ata_bus_reset(struct ata_port *ap);
 -extern int ata_set_sata_spd(struct ata_port *ap);
 +extern int sata_set_spd(struct ata_port *ap);
  extern int ata_drive_probe_reset(struct ata_port *ap,
                        ata_probeinit_fn_t probeinit,
                        ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
@@@ -589,7 -509,8 +585,7 @@@ extern void ata_std_probeinit(struct at
  extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
  extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
  extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
 -extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
 -                            int post_reset);
 +extern int ata_dev_revalidate(struct ata_device *dev, int post_reset);
  extern void ata_port_disable(struct ata_port *);
  extern void ata_std_ports(struct ata_ioports *ioaddr);
  #ifdef CONFIG_PCI
@@@ -605,18 -526,14 +601,18 @@@ extern void ata_host_set_remove(struct 
  extern int ata_scsi_detect(struct scsi_host_template *sht);
  extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
  extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
 -extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
 -extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
  extern int ata_scsi_release(struct Scsi_Host *host);
  extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
 +extern int sata_scr_valid(struct ata_port *ap);
 +extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val);
 +extern int sata_scr_write(struct ata_port *ap, int reg, u32 val);
 +extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val);
 +extern int ata_port_online(struct ata_port *ap);
 +extern int ata_port_offline(struct ata_port *ap);
  extern int ata_scsi_device_resume(struct scsi_device *);
  extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
 -extern int ata_device_resume(struct ata_port *, struct ata_device *);
 -extern int ata_device_suspend(struct ata_port *, struct ata_device *, pm_message_t state);
 +extern int ata_device_resume(struct ata_device *);
 +extern int ata_device_suspend(struct ata_device *, pm_message_t state);
  extern int ata_ratelimit(void);
  extern unsigned int ata_busy_sleep(struct ata_port *ap,
                                   unsigned long timeout_pat,
@@@ -661,22 -578,16 +657,22 @@@ extern void ata_bmdma_start (struct ata
  extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
  extern u8   ata_bmdma_status(struct ata_port *ap);
  extern void ata_bmdma_irq_clear(struct ata_port *ap);
 -extern void __ata_qc_complete(struct ata_queued_cmd *qc);
 -extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
 -                            struct scsi_cmnd *cmd,
 +extern void ata_bmdma_freeze(struct ata_port *ap);
 +extern void ata_bmdma_thaw(struct ata_port *ap);
 +extern void ata_bmdma_drive_eh(struct ata_port *ap,
 +                             ata_reset_fn_t softreset,
 +                             ata_reset_fn_t hardreset,
 +                             ata_postreset_fn_t postreset);
 +extern void ata_bmdma_error_handler(struct ata_port *ap);
 +extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
 +extern void ata_qc_complete(struct ata_queued_cmd *qc);
 +extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
                              void (*done)(struct scsi_cmnd *));
  extern int ata_std_bios_param(struct scsi_device *sdev,
                              struct block_device *bdev,
                              sector_t capacity, int geom[]);
  extern int ata_scsi_slave_config(struct scsi_device *sdev);
 -extern struct ata_device *ata_dev_pair(struct ata_port *ap, 
 -                                     struct ata_device *adev);
 +extern struct ata_device *ata_dev_pair(struct ata_device *adev);
  
  /*
   * Timing helpers
@@@ -726,46 -637,10 +722,46 @@@ extern unsigned long ata_pci_default_fi
   * EH
   */
  extern void ata_eng_timeout(struct ata_port *ap);
 +
 +extern void ata_port_schedule_eh(struct ata_port *ap);
 +extern int ata_port_abort(struct ata_port *ap);
 +extern int ata_port_freeze(struct ata_port *ap);
 +
 +extern void ata_eh_freeze_port(struct ata_port *ap);
 +extern void ata_eh_thaw_port(struct ata_port *ap);
 +
  extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
  extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
  
 +extern void ata_do_eh(struct ata_port *ap, ata_reset_fn_t softreset,
 +                    ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
 +
 +/*
 + * printk helpers
 + */
 +#define ata_port_printk(ap, lv, fmt, args...) \
 +      printk(lv"ata%u: "fmt, (ap)->id , ##args)
 +
 +#define ata_dev_printk(dev, lv, fmt, args...) \
 +      printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args)
  
 +/*
 + * ata_eh_info helpers
 + */
 +#define ata_ehi_push_desc(ehi, fmt, args...) do { \
 +      (ehi)->desc_len += scnprintf((ehi)->desc + (ehi)->desc_len, \
 +                                   ATA_EH_DESC_LEN - (ehi)->desc_len, \
 +                                   fmt , ##args); \
 +} while (0)
 +
 +#define ata_ehi_clear_desc(ehi) do { \
 +      (ehi)->desc[0] = '\0'; \
 +      (ehi)->desc_len = 0; \
 +} while (0)
 +
 +/*
 + * qc helpers
 + */
  static inline int
  ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc)
  {
@@@ -808,11 -683,6 +804,11 @@@ static inline unsigned int ata_tag_vali
        return (tag < ATA_MAX_QUEUE) ? 1 : 0;
  }
  
 +static inline unsigned int ata_tag_internal(unsigned int tag)
 +{
 +      return tag == ATA_MAX_QUEUE - 1;
 +}
 +
  static inline unsigned int ata_class_enabled(unsigned int class)
  {
        return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
@@@ -921,35 -791,20 +917,35 @@@ static inline void ata_qc_set_polling(s
        qc->tf.ctl |= ATA_NIEN;
  }
  
 -static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap,
 -                                                    unsigned int tag)
 +static inline struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
 +                                                     unsigned int tag)
  {
        if (likely(ata_tag_valid(tag)))
                return &ap->qcmd[tag];
        return NULL;
  }
  
 -static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, unsigned int device)
 +static inline struct ata_queued_cmd *ata_qc_from_tag(struct ata_port *ap,
 +                                                   unsigned int tag)
 +{
 +      struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
 +
 +      if (unlikely(!qc) || !ap->ops->error_handler)
 +              return qc;
 +
 +      if ((qc->flags & (ATA_QCFLAG_ACTIVE |
 +                        ATA_QCFLAG_FAILED)) == ATA_QCFLAG_ACTIVE)
 +              return qc;
 +
 +      return NULL;
 +}
 +
 +static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf)
  {
        memset(tf, 0, sizeof(*tf));
  
 -      tf->ctl = ap->ctl;
 -      if (device == 0)
 +      tf->ctl = dev->ap->ctl;
 +      if (dev->devno == 0)
                tf->device = ATA_DEVICE_OBS;
        else
                tf->device = ATA_DEVICE_OBS | ATA_DEV1;
@@@ -964,11 -819,26 +960,11 @@@ static inline void ata_qc_reinit(struc
        qc->nbytes = qc->curbytes = 0;
        qc->err_mask = 0;
  
 -      ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
 -}
 -
 -/**
 - *    ata_qc_complete - Complete an active ATA command
 - *    @qc: Command to complete
 - *    @err_mask: ATA Status register contents
 - *
 - *    Indicate to the mid and upper layers that an ATA
 - *    command has completed, with either an ok or not-ok status.
 - *
 - *    LOCKING:
 - *    spin_lock_irqsave(host_set lock)
 - */
 -static inline void ata_qc_complete(struct ata_queued_cmd *qc)
 -{
 -      if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
 -              return;
 +      ata_tf_init(qc->dev, &qc->tf);
  
 -      __ata_qc_complete(qc);
 +      /* init result_tf such that it indicates normal completion */
 +      qc->result_tf.command = ATA_DRDY;
 +      qc->result_tf.feature = 0;
  }
  
  /**
@@@ -1047,6 -917,28 +1043,6 @@@ static inline u8 ata_irq_ack(struct ata
        return status;
  }
  
 -static inline u32 scr_read(struct ata_port *ap, unsigned int reg)
 -{
 -      return ap->ops->scr_read(ap, reg);
 -}
 -
 -static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val)
 -{
 -      ap->ops->scr_write(ap, reg, val);
 -}
 -
 -static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
 -                                 u32 val)
 -{
 -      ap->ops->scr_write(ap, reg, val);
 -      (void) ap->ops->scr_read(ap, reg);
 -}
 -
 -static inline unsigned int sata_dev_present(struct ata_port *ap)
 -{
 -      return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
 -}
 -
  static inline int ata_try_flush_cache(const struct ata_device *dev)
  {
        return ata_id_wcache_enabled(dev->id) ||